diff --git a/.coveralls.yml b/.coveralls.yml index 1c8760a59..91600595a 100644 --- a/.coveralls.yml +++ b/.coveralls.yml @@ -1,3 +1 @@ service_name: travis-ci - -src_dir: library diff --git a/.travis.yml b/.travis.yml index 39b13061b..07a1d3fec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ env: - SYMFONY_VERSION=2.3.* - SYMFONY_VERSION=2.7.* - SYMFONY_VERSION=2.8.* + - SYMFONY_VERSION=3.0.* # Does not work with php below 5.5 before_script: - bash -c "if [ $TRAVIS_PHP_VERSION != 'hhvm' ] && [ $TRAVIS_PHP_VERSION != '7.0' ] && [ $TRAVIS_PHP_VERSION != 'nightly' ]; then printf '\n\n\n\n' | pecl install pecl_http-1.7.6; fi" @@ -20,13 +21,17 @@ before_script: script: vendor/bin/phpunit -c phpunit.xml.travis -v -after_script: vendor/bin/coveralls -v +after_success: + - travis_retry php vendor/bin/coveralls -v matrix: + exclude: + - php: 5.3 + env: SYMFONY_VERSION=3.0.* + - php: 5.4 + env: SYMFONY_VERSION=3.0.* allow_failures: - php: 5.3 - - php: hhvm - php: nightly - sudo: false diff --git a/CHANGELOG.md b/CHANGELOG.md index f3c6b349d..124ff51df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # CHANGELOG + +## 3.6.0 + +- improvement: no longer allow failures for HHVM in continuous integration +- improvement: added Symfony 3.x components to CI tests for PHP 5.5+ +- added: support for replicas in distributed search +- added: support for multiple boost queries in dismax +- added: support for additional stats values like percentiles +- improvement: several typo / markup fixes in documentation +- improvement: several docblock fixes +- improvement: ClientInterface now also used for standard Client class + +## 3.5.1 + +- fix backwards incompatible change in classnames + ## 3.5.0 - 2015-12-09 - improvement: lots of code style fixes diff --git a/composer.json b/composer.json index 63536dd1d..538895cec 100644 --- a/composer.json +++ b/composer.json @@ -13,13 +13,13 @@ ], "require": { "php": ">=5.3.2", - "symfony/event-dispatcher": "~2.3" + "symfony/event-dispatcher": "~2.3|~3.0" }, "require-dev": { "phpunit/phpunit": "~3.7", "squizlabs/php_codesniffer": "~1.4", "zendframework/zendframework1": "~1.12", - "satooshi/php-coveralls": "~0.6" + "satooshi/php-coveralls": "~1.0" }, "extra": { "branch-alias": { diff --git a/docs/getting-started.md b/docs/getting-started.md index a6e5b0704..eba67e3df 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -25,11 +25,13 @@ See [](https://packagist.org) for other packages. - Add Solarium to your composer.json file. It should look something like this: -`  {` -`      "require": {` -`          "solarium/solarium": "2.4.0"` -`      }` -`  }` +```json +{ + "require": { + "solarium/solarium": "2.4.0" + } +} +``` - Run composer install @@ -37,13 +39,13 @@ See [](https://packagist.org) for other packages. **Only if you don't use composer:** you need to use a PSR-0 autoloader, or the supplied autoloader: ```php -``` - Also you need to make sure the the Symfony Event Dispatcher component is available. ### Checking the availability -To check your installation you can do a Solarium version check with the following code. If everything works you should see the version of Solarium you downloaded. To test Solr communication you can use a ping query (you might need some configuration to get the ping working, more on that later) ```php +To check your installation you can do a Solarium version check with the following code. If everything works you should see the version of Solarium you downloaded. To test Solr communication you can use a ping query (you might need some configuration to get the ping working, more on that later) + +```php ](http://github.com/basdenooijer/solarium/issues) \ No newline at end of file +If examples for some Solarium functionality are missing please request them by opening an issue in the issue tracker: [](http://github.com/solariumphp/solarium/issues) diff --git a/docs/index.md b/docs/index.md index c0957e36b..2b0fbadf6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,7 +4,7 @@ Solarium documentation Solarium is a Solr client library for PHP. It is developed with these goals in mind: -- Releave developers of the ‘raw communication’ with Solr, ie. setting params, building strings, hiding all this with an easy to use API, allowing you to focus on business logic. +- Relieve developers of the ‘raw communication’ with Solr, ie. setting params, building strings, hiding all this with an easy to use API, allowing you to focus on business logic. - Allow for reuse, for instance a query can be extended to modify it - Be flexible. For instance the query and result models are not tied to a specific Solr client implementation. There are multiple Solr Client adapters for Solr communication. All models can be extended by your own implementation if needed and a plugin system is available. - Be usable in any PHP application. No dependencies on other frameworks. Solarium tries to follow the Symfony 2 standard and integrates nicely with SF2, but doesn’t in rely on it. You can use Solarium just as easily in Zend Framework or any other PHP framework. @@ -37,4 +37,4 @@ foreach ($resultset as $document) { echo $document->id . PHP_EOL; echo $document->name . PHP_EOL; } -``` \ No newline at end of file +``` diff --git a/docs/queries/select-query/building-a-select-query/components/distributed-search-component.md b/docs/queries/select-query/building-a-select-query/components/distributed-search-component.md index 510f7551c..951e3aa87 100644 --- a/docs/queries/select-query/building-a-select-query/components/distributed-search-component.md +++ b/docs/queries/select-query/building-a-select-query/components/distributed-search-component.md @@ -8,6 +8,7 @@ Options | shards | string | null | Shards to use for request | | shardhandler | string | null | Request handler to use | | collections | string | null | A list of collections, for use with SolrCloud (available in Solarium 3.1+) | +| replicas | string | null | A list of replicas, for use with SolrCloud (available in Solarium 3.1+) | || Example diff --git a/docs/queries/select-query/result-of-a-select-query/result-of-a-select-query.md b/docs/queries/select-query/result-of-a-select-query/result-of-a-select-query.md index fd8c5baed..3bd2b6f5e 100644 --- a/docs/queries/select-query/result-of-a-select-query/result-of-a-select-query.md +++ b/docs/queries/select-query/result-of-a-select-query/result-of-a-select-query.md @@ -35,7 +35,8 @@ The countable interface returns the number of documents in this resultset. This Example ------- -A basic usage example: ```php +A basic usage example: +```php select($query); * */ -class Client extends Configurable +class Client extends Configurable implements ClientInterface { /** * Querytype select. diff --git a/library/Solarium/QueryType/Select/Query/Component/BoostQuery.php b/library/Solarium/QueryType/Select/Query/Component/BoostQuery.php new file mode 100644 index 000000000..d377cf313 --- /dev/null +++ b/library/Solarium/QueryType/Select/Query/Component/BoostQuery.php @@ -0,0 +1,130 @@ + + * @license http://github.com/basdenooijer/solarium/raw/master/COPYING + * + * @link http://www.solarium-project.org/ + */ + +/** + * @namespace + */ + +namespace Solarium\QueryType\Select\Query\Component; + +use Solarium\Core\Configurable; +use Solarium\Core\Query\Helper; + +/** + * Filterquery. + * + * @link http://wiki.apache.org/solr/CommonQueryParameters#fq + */ +class BoostQuery extends Configurable +{ + /** + * Query. + * + * @var string + */ + protected $query; + + /** + * Get key value. + * + * @return string + */ + public function getKey() + { + return $this->getOption('key'); + } + + /** + * Set key value. + * + * @param string $value + * + * @return self Provides fluent interface + */ + public function setKey($value) + { + return $this->setOption('key', $value); + } + + /** + * Set the query string. + * + * This overwrites the current value + * + * @param string $query + * @param array $bind Bind values for placeholders in the query string + * + * @return self Provides fluent interface + */ + public function setQuery($query, $bind = null) + { + if (!is_null($bind)) { + $helper = new Helper(); + $query = $helper->assemble($query, $bind); + } + + $this->query = trim($query); + + return $this; + } + + /** + * Get the query string. + * + * @return string + */ + public function getQuery() + { + return $this->query; + } + + /** + * Initialize options. + */ + protected function init() + { + foreach ($this->options as $name => $value) { + switch ($name) { + case 'key': + $this->setKey($value); + break; + case 'query': + $this->setQuery($value); + break; + } + } + } +} diff --git a/library/Solarium/QueryType/Select/Query/Component/DisMax.php b/library/Solarium/QueryType/Select/Query/Component/DisMax.php index 5c15f381e..db22b80e9 100644 --- a/library/Solarium/QueryType/Select/Query/Component/DisMax.php +++ b/library/Solarium/QueryType/Select/Query/Component/DisMax.php @@ -40,6 +40,7 @@ namespace Solarium\QueryType\Select\Query\Component; +use Solarium\Exception\InvalidArgumentException; use Solarium\QueryType\Select\Query\Query as SelectQuery; use Solarium\QueryType\Select\RequestBuilder\Component\DisMax as RequestBuilder; @@ -59,6 +60,13 @@ class DisMax extends AbstractComponent 'queryparser' => 'dismax', ); + /** + * Boostqueries. + * + * @var BoostQuery[] + */ + protected $boostQueries = array(); + /** * Get component type. * @@ -278,17 +286,147 @@ public function getTie() */ public function setBoostQuery($boostQuery) { - return $this->setOption('boostquery', $boostQuery); + $this->clearBoostQueries(); + $this->addBoostQuery(array('key' => 0, 'query' => $boostQuery)); + + return $this; } /** * Get BoostQuery option. * + * @param string $key + * * @return string|null */ - public function getBoostQuery() + public function getBoostQuery($key = null) + { + if ($key !== null) { + if (array_key_exists($key, $this->boostQueries)) { + return $this->boostQueries[$key]->getQuery(); + } + } else if (!empty($this->boostQueries)) { + /** @var BoostQuery[] $boostQueries */ + $boostQueries = array_values($this->boostQueries); + + return $boostQueries[0]->getQuery(); + } else if (array_key_exists('boostquery', $this->options)) { + return $this->options['boostquery']; + } + + return null; + } + + /** + * Add a boost query. + * + * Supports a boostquery instance or a config array, in that case a new + * boostquery instance wil be created based on the options. + * + * @throws InvalidArgumentException + * + * @param BoostQuery|array $boostQuery + * + * @return self Provides fluent interface + */ + public function addBoostQuery($boostQuery) + { + if (is_array($boostQuery)) { + $boostQuery = new BoostQuery($boostQuery); + } + + $key = $boostQuery->getKey(); + + if (0 === strlen($key)) { + throw new InvalidArgumentException('A boostquery must have a key value'); + } + + //double add calls for the same BQ are ignored, but non-unique keys cause an exception + if (array_key_exists($key, $this->boostQueries) && $this->boostQueries[$key] !== $boostQuery) { + throw new InvalidArgumentException('A boostquery must have a unique key value within a query'); + } else { + $this->boostQueries[$key] = $boostQuery; + } + + return $this; + } + + /** + * Add multiple boostqueries. + * + * @param array $boostQueries + * + * @return self Provides fluent interface + */ + public function addBoostQueries(array $boostQueries) + { + foreach ($boostQueries as $key => $boostQuery) { + // in case of a config array: add key to config + if (is_array($boostQuery) && !isset($boostQuery['key'])) { + $boostQuery['key'] = $key; + } + + $this->addBoostQuery($boostQuery); + } + + return $this; + } + + /** + * Get all boostqueries. + * + * @return BoostQuery[] + */ + public function getBoostQueries() + { + return $this->boostQueries; + } + + /** + * Remove a single boostquery. + * + * You can remove a boostquery by passing its key, or by passing the boostquery instance + * + * @param string|BoostQuery $boostQuery + * + * @return self Provides fluent interface + */ + public function removeBoostQuery($boostQuery) + { + if (is_object($boostQuery)) { + $boostQuery = $boostQuery->getKey(); + } + + if (isset($this->boostQueries[$boostQuery])) { + unset($this->boostQueries[$boostQuery]); + } + + return $this; + } + + /** + * Remove all boostqueries. + * + * @return self Provides fluent interface + */ + public function clearBoostQueries() + { + $this->boostQueries = array(); + + return $this; + } + + /** + * Set multiple boostqueries. + * + * This overwrites any existing boostqueries + * + * @param array $boostQueries + */ + public function setBoostQueries($boostQueries) { - return $this->getOption('boostquery'); + $this->clearBoostQueries(); + $this->addBoostQueries($boostQueries); } /** diff --git a/library/Solarium/QueryType/Select/Query/Component/DistributedSearch.php b/library/Solarium/QueryType/Select/Query/Component/DistributedSearch.php index 5e6c9f05a..b4341d102 100644 --- a/library/Solarium/QueryType/Select/Query/Component/DistributedSearch.php +++ b/library/Solarium/QueryType/Select/Query/Component/DistributedSearch.php @@ -65,6 +65,13 @@ class DistributedSearch extends AbstractComponent */ protected $collections = array(); + /** + * Requests will be load balanced across replicas in this list. + * + * @var array + */ + protected $replicas = array(); + /** * Get component type. * @@ -318,6 +325,94 @@ public function getCollections() return $this->collections; } + /** + * Add a replica. + * + * @param string $key unique string + * @param string $replica The syntax is host:port/base_url + * + * @return self Provides fluent interface + * + * @link https://cwiki.apache.org/confluence/display/solr/Distributed+Requests + */ + public function addReplica($key, $replica) + { + $this->replicas[$key] = $replica; + + return $this; + } + + /** + * Add multiple replicas. + * + * @param array $replicas + * + * @return self Provides fluent interface + */ + public function addReplicas(array $replicas) + { + foreach ($replicas as $key => $replica) { + $this->addReplica($key, $replica); + } + + return $this; + } + + /** + * Remove a replica. + * + * @param string $key + * + * @return self Provides fluent interface + */ + public function removeReplica($key) + { + if (isset($this->replicas[$key])) { + unset($this->replicas[$key]); + } + + return $this; + } + + /** + * Remove all replicas. + * + * @return self Provides fluent interface + */ + public function clearReplicas() + { + $this->replicas = array(); + + return $this; + } + + /** + * Set multiple replicas. + * + * This overwrites any existing replicas + * + * @param array $replicas Associative array of collections + * + * @return self Provides fluent interface + */ + public function setReplicas(array $replicas) + { + $this->clearReplicas(); + $this->addReplicas($replicas); + + return $this; + } + + /** + * Get a list of the replicas. + * + * @return array + */ + public function getReplicas() + { + return $this->replicas; + } + /** * Initialize options. * @@ -334,6 +429,9 @@ protected function init() case 'collections': $this->setCollections($value); break; + case 'replicas': + $this->setReplicas($value); + break; } } } diff --git a/library/Solarium/QueryType/Select/RequestBuilder/Component/DisMax.php b/library/Solarium/QueryType/Select/RequestBuilder/Component/DisMax.php index 3e44d4ad0..c607bef9c 100644 --- a/library/Solarium/QueryType/Select/RequestBuilder/Component/DisMax.php +++ b/library/Solarium/QueryType/Select/RequestBuilder/Component/DisMax.php @@ -68,7 +68,15 @@ public function buildComponent($component, $request) $request->addParam('ps', $component->getPhraseSlop()); $request->addParam('qs', $component->getQueryPhraseSlop()); $request->addParam('tie', $component->getTie()); - $request->addParam('bq', $component->getBoostQuery()); + + // add boostqueries to request + $boostQueries = $component->getBoostQueries(); + if (count($boostQueries) !== 0) { + foreach ($boostQueries as $boostQuery) { + $request->addParam('bq', $boostQuery->getQuery()); + } + } + $request->addParam('bf', $component->getBoostFunctions()); return $request; diff --git a/library/Solarium/QueryType/Select/RequestBuilder/Component/DistributedSearch.php b/library/Solarium/QueryType/Select/RequestBuilder/Component/DistributedSearch.php index aa5071ca8..80b9ee8f9 100644 --- a/library/Solarium/QueryType/Select/RequestBuilder/Component/DistributedSearch.php +++ b/library/Solarium/QueryType/Select/RequestBuilder/Component/DistributedSearch.php @@ -64,6 +64,14 @@ public function buildComponent($component, $request) $request->addParam('shards', implode(',', $shards)); } + $replicas = array_values($component->getReplicas()); + + if (count($replicas)) { + $value = ($request->getParam('shards')) ? $request->getParam('shards').','.implode('|', $replicas) : implode('|', $replicas); + + $request->addParam('shards', $value, true); + } + $request->addParam('shards.qt', $component->getShardRequestHandler()); // add collections to request diff --git a/library/Solarium/QueryType/Select/RequestBuilder/Component/EdisMax.php b/library/Solarium/QueryType/Select/RequestBuilder/Component/EdisMax.php index b25230fd2..64cbadcd9 100644 --- a/library/Solarium/QueryType/Select/RequestBuilder/Component/EdisMax.php +++ b/library/Solarium/QueryType/Select/RequestBuilder/Component/EdisMax.php @@ -72,7 +72,15 @@ public function buildComponent($component, $request) $request->addParam('ps3', $component->getPhraseTrigramSlop()); $request->addParam('qs', $component->getQueryPhraseSlop()); $request->addParam('tie', $component->getTie()); - $request->addParam('bq', $component->getBoostQuery()); + + // add boostqueries to request + $boostQueries = $component->getBoostQueries(); + if (count($boostQueries) !== 0) { + foreach ($boostQueries as $boostQuery) { + $request->addParam('bq', $boostQuery->getQuery()); + } + } + $request->addParam('bf', $component->getBoostFunctions()); $request->addParam('boost', $component->getBoostFunctionsMult()); $request->addParam('uf', $component->getUserFields()); diff --git a/library/Solarium/QueryType/Select/Result/Stats/Result.php b/library/Solarium/QueryType/Select/Result/Stats/Result.php index 935b0b332..279f3876a 100644 --- a/library/Solarium/QueryType/Select/Result/Stats/Result.php +++ b/library/Solarium/QueryType/Select/Result/Stats/Result.php @@ -88,7 +88,7 @@ public function getName() */ public function getMin() { - return $this->stats['min']; + return $this->getValue('min'); } /** @@ -98,7 +98,7 @@ public function getMin() */ public function getMax() { - return $this->stats['max']; + return $this->getValue('max'); } /** @@ -108,7 +108,7 @@ public function getMax() */ public function getSum() { - return $this->stats['sum']; + return $this->getValue('sum'); } /** @@ -118,7 +118,7 @@ public function getSum() */ public function getCount() { - return $this->stats['count']; + return $this->getValue('count'); } /** @@ -128,7 +128,7 @@ public function getCount() */ public function getMissing() { - return $this->stats['missing']; + return $this->getValue('missing'); } /** @@ -138,7 +138,7 @@ public function getMissing() */ public function getSumOfSquares() { - return $this->stats['sumOfSquares']; + return $this->getValue('sumOfSquares'); } /** @@ -148,7 +148,7 @@ public function getSumOfSquares() */ public function getMean() { - return $this->stats['mean']; + return $this->getValue('mean'); } /** @@ -158,7 +158,7 @@ public function getMean() */ public function getStddev() { - return $this->stats['stddev']; + return $this->getValue('stddev'); } /** @@ -168,6 +168,26 @@ public function getStddev() */ public function getFacets() { - return $this->stats['facets']; + return $this->getValue('facets'); } + + /** + * Get percentile stats. + * + * @return array + */ + public function getPercentiles() + { + return $this->getValue('percentiles'); + } + + /** + * Get value by name. + * + * @return string + */ + protected function getValue($name) + { + return isset($this->stats[$name]) ? $this->stats[$name] : null; + } } diff --git a/tests/Solarium/Tests/Core/Client/ClientTest.php b/tests/Solarium/Tests/Core/Client/ClientTest.php index 05070f0e4..51360190b 100644 --- a/tests/Solarium/Tests/Core/Client/ClientTest.php +++ b/tests/Solarium/Tests/Core/Client/ClientTest.php @@ -570,8 +570,10 @@ public function testCreateRequestPrePlugin() { $query = new SelectQuery(); $expectedEvent = new PreCreateRequestEvent($query); - $expectedEvent->setDispatcher($this->client->getEventDispatcher()); - $expectedEvent->setName(Events::PRE_CREATE_REQUEST); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setDispatcher($this->client->getEventDispatcher()); + $expectedEvent->setName(Events::PRE_CREATE_REQUEST); + } $observer = $this->getMock('Solarium\Core\Plugin\AbstractPlugin', array('preCreateRequest')); $observer->expects($this->once()) @@ -592,8 +594,10 @@ public function testCreateRequestPostPlugin() $query = new SelectQuery(); $request = $this->client->createRequest($query); $expectedEvent = new PostCreateRequestEvent($query, $request); - $expectedEvent->setDispatcher($this->client->getEventDispatcher()); - $expectedEvent->setName(Events::POST_CREATE_REQUEST); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setDispatcher($this->client->getEventDispatcher()); + $expectedEvent->setName(Events::POST_CREATE_REQUEST); + } $observer = $this->getMock('Solarium\Core\Plugin\AbstractPlugin', array('postCreateRequest')); $observer->expects($this->once()) @@ -616,8 +620,10 @@ public function testCreateRequestWithOverridingPlugin() $query = new SelectQuery(); $expectedEvent = new PreCreateRequestEvent($query); - $expectedEvent->setDispatcher($this->client->getEventDispatcher()); - $expectedEvent->setName(Events::PRE_CREATE_REQUEST); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setDispatcher($this->client->getEventDispatcher()); + $expectedEvent->setName(Events::PRE_CREATE_REQUEST); + } $test = $this; $this->client->getEventDispatcher()->addListener( @@ -653,8 +659,10 @@ public function testCreateResultPrePlugin() $query = new SelectQuery(); $response = new Response('', array('HTTP 1.0 200 OK')); $expectedEvent = new PreCreateResultEvent($query, $response); - $expectedEvent->setDispatcher($this->client->getEventDispatcher()); - $expectedEvent->setName(Events::PRE_CREATE_RESULT); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setDispatcher($this->client->getEventDispatcher()); + $expectedEvent->setName(Events::PRE_CREATE_RESULT); + } $observer = $this->getMock('Solarium\Core\Plugin\AbstractPlugin', array('preCreateResult')); $observer->expects($this->once()) @@ -676,8 +684,10 @@ public function testCreateResultPostPlugin() $response = new Response('', array('HTTP 1.0 200 OK')); $result = $this->client->createResult($query, $response); $expectedEvent = new PostCreateResultEvent($query, $response, $result); - $expectedEvent->setDispatcher($this->client->getEventDispatcher()); - $expectedEvent->setName(Events::POST_CREATE_RESULT); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setDispatcher($this->client->getEventDispatcher()); + $expectedEvent->setName(Events::POST_CREATE_RESULT); + } $observer = $this->getMock('Solarium\Core\Plugin\AbstractPlugin', array('postCreateResult')); $observer->expects($this->once()) @@ -698,8 +708,10 @@ public function testCreateResultWithOverridingPlugin() $query = new SelectQuery(); $response = new Response('test 1234', array('HTTP 1.0 200 OK')); $expectedEvent = new PreCreateResultEvent($query, $response); - $expectedEvent->setDispatcher($this->client->getEventDispatcher()); - $expectedEvent->setName(Events::PRE_CREATE_RESULT); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setDispatcher($this->client->getEventDispatcher()); + $expectedEvent->setName(Events::PRE_CREATE_RESULT); + } $expectedResult = new Result($this->client, $query, $response); $test = $this; @@ -768,7 +780,7 @@ public function testExecutePrePlugin() $response = new Response('', array('HTTP 1.0 200 OK')); $result = new Result($this->client, $query, $response); $expectedEvent = new PreExecuteEvent($query); - $expectedEvent->setName(Events::PRE_EXECUTE); + $mock = $this->getMock('Solarium\Core\Client\Client', array('createRequest', 'executeRequest', 'createResult')); @@ -791,7 +803,10 @@ public function testExecutePrePlugin() $mock->getEventDispatcher()->addListener(Events::PRE_EXECUTE, array($observer, 'preExecute')); - $expectedEvent->setDispatcher($mock->getEventDispatcher()); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setName(Events::PRE_EXECUTE); + $expectedEvent->setDispatcher($mock->getEventDispatcher()); + } $mock->execute($query); } @@ -802,7 +817,6 @@ public function testExecutePostPlugin() $response = new Response('', array('HTTP 1.0 200 OK')); $result = new Result($this->client, $query, $response); $expectedEvent = new PostExecuteEvent($query, $result); - $expectedEvent->setName(Events::POST_EXECUTE); $mock = $this->getMock('Solarium\Core\Client\Client', array('createRequest', 'executeRequest', 'createResult')); @@ -825,7 +839,10 @@ public function testExecutePostPlugin() $mock->getEventDispatcher()->addListener(Events::POST_EXECUTE, array($observer, 'postExecute')); - $expectedEvent->setDispatcher($mock->getEventDispatcher()); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setName(Events::POST_EXECUTE); + $expectedEvent->setDispatcher($mock->getEventDispatcher()); + } $mock->execute($query); } @@ -836,8 +853,10 @@ public function testExecuteWithOverridingPlugin() $response = new Response('', array('HTTP 1.0 200 OK')); $expectedResult = new Result($this->client, $query, $response); $expectedEvent = new PreExecuteEvent($query); - $expectedEvent->setDispatcher($this->client->getEventDispatcher()); - $expectedEvent->setName(Events::PRE_EXECUTE); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setDispatcher($this->client->getEventDispatcher()); + $expectedEvent->setName(Events::PRE_EXECUTE); + } $test = $this; $this->client->getEventDispatcher()->addListener( @@ -882,8 +901,10 @@ public function testExecuteRequestPrePlugin() $endpoint = $this->client->createEndpoint('s1'); $response = new Response('', array('HTTP 1.0 200 OK')); $expectedEvent = new PreExecuteRequestEvent($request, $endpoint); - $expectedEvent->setDispatcher($this->client->getEventDispatcher()); - $expectedEvent->setName(Events::PRE_EXECUTE_REQUEST); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setDispatcher($this->client->getEventDispatcher()); + $expectedEvent->setName(Events::PRE_EXECUTE_REQUEST); + } $mockAdapter = $this->getMock('Solarium\Core\Client\Adapter\Http', array('execute')); $mockAdapter->expects($this->once()) @@ -910,8 +931,10 @@ public function testExecuteRequestPostPlugin() $endpoint = $this->client->createEndpoint('s1'); $response = new Response('', array('HTTP 1.0 200 OK')); $expectedEvent = new PostExecuteRequestEvent($request, $endpoint, $response); - $expectedEvent->setDispatcher($this->client->getEventDispatcher()); - $expectedEvent->setName(Events::POST_EXECUTE_REQUEST); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setDispatcher($this->client->getEventDispatcher()); + $expectedEvent->setName(Events::POST_EXECUTE_REQUEST); + } $mockAdapter = $this->getMock('Solarium\Core\Client\Adapter\Http', array('execute')); $mockAdapter->expects($this->any()) @@ -938,8 +961,10 @@ public function testExecuteRequestWithOverridingPlugin() $response = new Response('', array('HTTP 1.0 200 OK')); $endpoint = $this->client->createEndpoint('s1'); $expectedEvent = new PreExecuteRequestEvent($request, $endpoint); - $expectedEvent->setDispatcher($this->client->getEventDispatcher()); - $expectedEvent->setName(Events::PRE_EXECUTE_REQUEST); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setDispatcher($this->client->getEventDispatcher()); + $expectedEvent->setName(Events::PRE_EXECUTE_REQUEST); + } $test = $this; $this->client->getEventDispatcher()->addListener( @@ -1088,8 +1113,10 @@ public function testCreateQueryPrePlugin() $type = Client::QUERY_SELECT; $options = array('optionA' => 1, 'optionB' => 2); $expectedEvent = new PreCreateQueryEvent($type, $options); - $expectedEvent->setDispatcher($this->client->getEventDispatcher()); - $expectedEvent->setName(Events::PRE_CREATE_QUERY); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setDispatcher($this->client->getEventDispatcher()); + $expectedEvent->setName(Events::PRE_CREATE_QUERY); + } $observer = $this->getMock('Solarium\Core\Plugin\AbstractPlugin', array('preCreateQuery')); $observer->expects($this->once()) @@ -1107,8 +1134,10 @@ public function testCreateQueryWithOverridingPlugin() $expectedQuery = new SelectQuery(); $expectedQuery->setQuery('test789'); $expectedEvent = new PreCreateQueryEvent($type, $options); - $expectedEvent->setDispatcher($this->client->getEventDispatcher()); - $expectedEvent->setName(Events::PRE_CREATE_QUERY); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setDispatcher($this->client->getEventDispatcher()); + $expectedEvent->setName(Events::PRE_CREATE_QUERY); + } $test = $this; $this->client->getEventDispatcher()->addListener( @@ -1133,8 +1162,10 @@ public function testCreateQueryPostPlugin() $options = array('optionA' => 1, 'optionB' => 2); $query = $this->client->createQuery($type, $options); $expectedEvent = new PostCreateQueryEvent($type, $options, $query); - $expectedEvent->setDispatcher($this->client->getEventDispatcher()); - $expectedEvent->setName(Events::POST_CREATE_QUERY); + if (method_exists($expectedEvent, 'setDispatcher')) { + $expectedEvent->setDispatcher($this->client->getEventDispatcher()); + $expectedEvent->setName(Events::POST_CREATE_QUERY); + } $observer = $this->getMock('Solarium\Core\Plugin\AbstractPlugin', array('postCreateQuery')); $observer->expects($this->once()) diff --git a/tests/Solarium/Tests/QueryType/Select/Query/Component/BoostQueryTest.php b/tests/Solarium/Tests/QueryType/Select/Query/Component/BoostQueryTest.php new file mode 100644 index 000000000..ed755b365 --- /dev/null +++ b/tests/Solarium/Tests/QueryType/Select/Query/Component/BoostQueryTest.php @@ -0,0 +1,70 @@ +boostQuery = new BoostQuery; + } + + public function testConfigMode() + { + $fq = new BoostQuery(array('key' => 'k1', 'query'=> 'id:[10 TO 20]')); + + $this->assertEquals('k1', $fq->getKey()); + $this->assertEquals('id:[10 TO 20]', $fq->getQuery()); + } + + public function testSetAndGetKey() + { + $this->boostQuery->setKey('testkey'); + $this->assertEquals('testkey', $this->boostQuery->getKey()); + } + + public function testSetAndGetQuery() + { + $this->boostQuery->setQuery('category:1'); + $this->assertEquals('category:1', $this->boostQuery->getQuery()); + } + + public function testSetAndGetQueryWithBind() + { + $this->boostQuery->setQuery('id:%1%', array(678)); + $this->assertEquals('id:678', $this->boostQuery->getQuery()); + } +} diff --git a/tests/Solarium/Tests/QueryType/Select/Query/Component/DisMaxTest.php b/tests/Solarium/Tests/QueryType/Select/Query/Component/DisMaxTest.php index 1c41d4b77..7e254e610 100644 --- a/tests/Solarium/Tests/QueryType/Select/Query/Component/DisMaxTest.php +++ b/tests/Solarium/Tests/QueryType/Select/Query/Component/DisMaxTest.php @@ -31,6 +31,7 @@ namespace Solarium\Tests\QueryType\Select\Query\Component; +use Solarium\QueryType\Select\Query\Component\BoostQuery; use Solarium\QueryType\Select\Query\Component\DisMax; use Solarium\QueryType\Select\Query\Query; @@ -195,6 +196,101 @@ public function testSetAndGetBoostQuery() ); } + public function testAddBoostQueryWithArray() + { + $query = 'cat:1^3'; + $key = 'cat'; + + $this->disMax->addBoostQuery(array('query' => $query, 'key' => $key)); + + $this->assertEquals( + $query, + $this->disMax->getBoostQuery($key) + ); + } + + public function testAddBoostQueryWithObject() + { + $query = 'cat:1^3'; + $key = 'cat'; + + $bq = new BoostQuery(); + $bq -> setKey($key); + $bq -> setQuery($query); + + $this->disMax->addBoostQuery($bq); + + $this->assertEquals( + $query, + $this->disMax->getBoostQuery($key) + ); + } + + public function testAddBoostQueryWithoutKey() + { + $bq = new BoostQuery; + $bq->setQuery('category:1'); + + $this->setExpectedException('Solarium\Exception\InvalidArgumentException'); + $this->disMax->addBoostQuery($bq); + } + + public function testAddBoostQueryWithUsedKey() + { + $bq1 = new BoostQuery; + $bq1->setKey('bq1')->setQuery('category:1'); + + $bq2 = new BoostQuery; + $bq2->setKey('bq1')->setQuery('category:2'); + + $this->disMax->addBoostQuery($bq1); + $this->setExpectedException('Solarium\Exception\InvalidArgumentException'); + $this->disMax->addBoostQuery($bq2); + } + + public function testAddBoostQueriesWithInnerKeys() + { + $bqs = array( + array('key' => 'key1', 'query' => 'cat:1'), + array('key' => 'key2', 'query' => 'cat:2') + ); + + $this->disMax->addBoostQueries($bqs); + + $bqs2 = array(); + + foreach ($bqs as $bq) { + $bqs2[$bq['key']] = new BoostQuery($bq); + } + + $this->assertEquals( + $bqs2, + $this->disMax->getBoostQueries() + ); + } + + public function testAddBoostQueriesWithOuterKeys() + { + $bqs = array( + 'key1' => array('query' => 'cat:1'), + 'key2' => array('query' => 'cat:2') + ); + + $this->disMax->addBoostQueries($bqs); + + $bqs2 = array(); + + foreach ($bqs as $key => $bq) { + $bq['key'] = $key; + $bqs2[$key] = new BoostQuery($bq); + } + + $this->assertEquals( + $bqs2, + $this->disMax->getBoostQueries() + ); + } + public function testSetAndGetBoostFunctions() { $value = 'funcA(arg1,arg2)^1.2 funcB(arg3,arg4)^2.2'; diff --git a/tests/Solarium/Tests/QueryType/Select/Query/Component/DistributedSearchTest.php b/tests/Solarium/Tests/QueryType/Select/Query/Component/DistributedSearchTest.php index 78a8a1ea4..bc450264a 100644 --- a/tests/Solarium/Tests/QueryType/Select/Query/Component/DistributedSearchTest.php +++ b/tests/Solarium/Tests/QueryType/Select/Query/Component/DistributedSearchTest.php @@ -75,6 +75,19 @@ public function testConfigModeForCollections() $this->assertEquals($options['collections'], $this->distributedSearch->getCollections()); } + public function testConfigModeForReplicas() + { + $options = array( + 'replicas' => array( + 'replica1' => 'localhost:8983/solr/collection1', + 'replica2' => 'localhost:8983/solr/collection2', + ), + ); + + $this->distributedSearch->setOptions($options); + $this->assertEquals($options['replicas'], $this->distributedSearch->getReplicas()); + } + public function testGetType() { $this->assertEquals( @@ -242,4 +255,73 @@ public function testSetCollections() $collections ); } + + public function testAddReplica() + { + $this->distributedSearch->addReplica('replica1', 'localhost:8983/solr/replica1'); + $replicas = $this->distributedSearch->getReplicas(); + $this->assertEquals( + 'localhost:8983/solr/replica1', + $replicas['replica1'] + ); + } + + public function testRemoveReplica() + { + $this->distributedSearch->addReplica('replica1', 'localhost:8983/solr/replica1'); + $this->distributedSearch->removeReplica('replica1'); + $replicas = $this->distributedSearch->getReplicas(); + $this->assertFalse(isset($replicas['replica1'])); + } + + public function testClearReplicas() + { + $this->distributedSearch->addReplicas( + array( + 'replica1' => 'localhost:8983/solr/replica1', + 'replica2' => 'localhost:8983/solr/replica2', + ) + ); + $this->distributedSearch->clearReplicas(); + $replicas = $this->distributedSearch->getReplicas(); + $this->assertTrue(is_array($replicas)); + $this->assertEquals(0, count($replicas)); + } + + public function testAddReplicas() + { + $replicas = array( + 'replica1' => 'localhost:8983/solr/replica1', + 'replica2' => 'localhost:8983/solr/replica2', + ); + $this->distributedSearch->addReplicas($replicas); + $this->assertEquals($replicas, $this->distributedSearch->getReplicas()); + } + + public function testSetReplicas() + { + $this->distributedSearch->addReplicas( + array( + 'replica1' => 'localhost:8983/solr/replica1', + 'replica2' => 'localhost:8983/solr/replica2', + ) + ); + $this->distributedSearch->setReplicas( + array( + 'replica3' => 'localhost:8983/solr/replica3', + 'replica4' => 'localhost:8983/solr/replica4', + 'replica5' => 'localhost:8983/solr/replica5', + ) + ); + $replicas = $this->distributedSearch->getReplicas(); + $this->assertEquals(3, count($replicas)); + $this->assertEquals( + array( + 'replica3' => 'localhost:8983/solr/replica3', + 'replica4' => 'localhost:8983/solr/replica4', + 'replica5' => 'localhost:8983/solr/replica5', + ), + $replicas + ); + } } diff --git a/tests/Solarium/Tests/QueryType/Select/Query/Component/Facet/IntervalTest.php b/tests/Solarium/Tests/QueryType/Select/Query/Component/Facet/IntervalTest.php new file mode 100644 index 000000000..369711dc5 --- /dev/null +++ b/tests/Solarium/Tests/QueryType/Select/Query/Component/Facet/IntervalTest.php @@ -0,0 +1,88 @@ +facet = new Interval(); + } + + public function testConfigMode() + { + $options = array( + 'key' => 'myKey', + 'exclude' => array('e1', 'e2'), + 'set' => array('i1', 'i2'), + ); + + $this->facet->setOptions($options); + + $this->assertEquals($options['key'], $this->facet->getKey()); + $this->assertEquals($options['exclude'], $this->facet->getExcludes()); + $this->assertEquals($options['set'], $this->facet->getSet()); + } + + public function testGetType() + { + $this->assertEquals( + FacetSet::FACET_INTERVAL, + $this->facet->getType() + ); + } + + public function testSetAndGetSet() + { + $this->facet->setSet('interval1,interval2'); + $this->assertEquals(array('interval1', 'interval2'), $this->facet->getSet()); + } + + public function testEmptySet() + { + $this->assertEquals(array(), $this->facet->getSet()); + } + + public function testSetAndGetField() + { + $this->facet->setField('field1'); + $this->assertEquals('field1', $this->facet->getField()); + } +} diff --git a/tests/Solarium/Tests/QueryType/Select/RequestBuilder/Component/DistributedSearchTest.php b/tests/Solarium/Tests/QueryType/Select/RequestBuilder/Component/DistributedSearchTest.php index 7d8894e79..226ed9ded 100644 --- a/tests/Solarium/Tests/QueryType/Select/RequestBuilder/Component/DistributedSearchTest.php +++ b/tests/Solarium/Tests/QueryType/Select/RequestBuilder/Component/DistributedSearchTest.php @@ -82,4 +82,47 @@ public function testBuildComponentWithCollections() $this->assertEquals(array('collection' => $url.'1,'.$url.'2,'.$url.'3'), $request->getParams()); } + + public function testBuildComponentWithReplicas() + { + $builder = new RequestBuilder(); + $request = new Request(); + + $url = 'localhost:8983/solr/replica'; + $component = new Component(); + $component->addReplica('replica1', $url.'1'); + $component->addReplicas( + array( + 'replica2' => $url.'2', + 'replica3' => $url.'3', + ) + ); + + $request = $builder->buildComponent($component, $request); + + $this->assertEquals(array('shards' => $url.'1|'.$url.'2|'.$url.'3'), $request->getParams()); + } + + + + public function testBuildComponentWithReplicasAndShard() + { + $builder = new RequestBuilder(); + $request = new Request(); + + $url = 'localhost:8983/solr/replica'; + $component = new Component(); + $component->addShard('shard1', 'localhost:8983/solr/shard1'); + + $component->addReplicas( + array( + 'replica2' => $url.'2', + 'replica3' => $url.'3', + ) + ); + + $request = $builder->buildComponent($component, $request); + + $this->assertEquals(array('shards' => 'localhost:8983/solr/shard1,'.$url.'2|'.$url.'3'), $request->getParams()); + } } diff --git a/tests/Solarium/Tests/QueryType/Select/RequestBuilder/Component/FacetSetTest.php b/tests/Solarium/Tests/QueryType/Select/RequestBuilder/Component/FacetSetTest.php index 2fd2c33e7..f1b99117b 100644 --- a/tests/Solarium/Tests/QueryType/Select/RequestBuilder/Component/FacetSetTest.php +++ b/tests/Solarium/Tests/QueryType/Select/RequestBuilder/Component/FacetSetTest.php @@ -39,6 +39,7 @@ use Solarium\QueryType\Select\Query\Component\Facet\MultiQuery as FacetMultiQuery; use Solarium\QueryType\Select\Query\Component\Facet\Range as FacetRange; use Solarium\QueryType\Select\Query\Component\Facet\Pivot as FacetPivot; +use Solarium\QueryType\Select\Query\Component\Facet\Interval as FacetInterval; class FacetSetTest extends \PHPUnit_Framework_TestCase { @@ -259,6 +260,31 @@ public function testBuildWithContainsSettings() urldecode($request->getUri()) ); } + + public function testBuildeWithIntervalFacet() + { + $facet = new FacetInterval( + array( + 'key' => 'f1', + 'fields' => 'cat,inStock', + 'set' => array(0 => 'int1', 'one' => 'int2'), + ) + ); + + $this->component->addFacet($facet); + + $request = $this->builder->buildComponent($this->component, $this->request); + + $this->assertEquals( + null, + $request->getRawData() + ); + + $this->assertEquals( + '?facet=true&f..facet.interval.set=int1&f..facet.interval.set={!key="one"}int2', + urldecode($request->getUri()) + ); + } } class UnknownFacet extends FacetField