Commit a9c1c5fb authored by Bas de Nooijer's avatar Bas de Nooijer

Merge pull request #339 from solariumphp/develop

Merging develop into master
parents 243ef1f6 597b6c12
......@@ -2,4 +2,4 @@ build
phpunit.xml
composer.phar
composer.lock
vendor
\ No newline at end of file
vendor
# CHANGELOG
## 3.4.0 - 2015-06-14
- bugfix: only check type for added documents to add query if provided as an array
- improvement: added support for calling empty() and isset() on result document properties
- improvement: added composer test script
- bugfix: curl file upload handling
- improvement: added 'contributing' file
- improvement: docblock fixes in grouping component facets
- added: facet interval support
- added: ZF2 http adapter
- added: stats for pivot facet
- bugfix: spellcheck 'collations' and 'correctlyspelled' updated to support Solr 5 format
- bugfix: curl adapter now uses Solr 5 compatible headers for a GET request
- improvement: lots of code style fixes, using the SF2 code style
## 3.3.0 - 2014-11-16
- improvement: fixes in build.xml (use phpunit in vendor directory)
......
# Contributing to Solarium
So you consider contributing to Solarium? That’s great!
Here are some pointers to hopefully get a good result.
If you are uncertain about any part or need help please feel free to ask for help.
## Bug reports
* Bugs are intended for problems in the code or missing / faulty documentation. Not for issues with your own environment, questions in how to use feature X etcetera.
* Include info about your environment: the version of Solarium you are using, PHP version, Solr version
* If you get a specific error, include as much info as possible. The PHP exception, a Solr error log line, etcetera.
* When something doesn't work as expected for you, also describe the behaviour you expect.
* Do a quick search to check if the issue has already been reported
* Describe your issue well, especially the title. Instead of ‘Select query exception’ use ‘Using a dash in a filterquery tag causes an exception’.
* Provide steps to reproduce the issue. A unittest is ideal, but a description of manual steps is also very helpful.
## Pull requests
* Your pull requests should target the develop branch, not master. Nothing will be directly merged into master!
* A pull request should be mergeable (fast-forward) if not, you will be asked to update it.
* Ideally any change should include updated or new unittests to cover the changes. You can submit a PR without tests, but it will take longer to merge as someone else will need to fix the test coverage.
* Solarium follows the Symfony2 code standards: http://symfony.com/doc/current/contributing/code/standards.html
* Each PR will be checked by the CI environment automatically. Ofcourse anything other than a 'green' status needs to be fixed before a PR can be merged.
......@@ -49,5 +49,3 @@ http://wiki.solarium-project.org/index.php/V3:Installation#Getting_Solarium
* Develop branch [![Coverage Status](https://coveralls.io/repos/solariumphp/solarium/badge.png?branch=develop)](https://coveralls.io/r/solariumphp/solarium?branch=develop)
* Master branch [![Develop build status](https://secure.travis-ci.org/solariumphp/solarium.png?branch=master)](http://travis-ci.org/solariumphp/solarium)
* Master branch [![Coverage Status](https://coveralls.io/repos/solariumphp/solarium/badge.png?branch=master)](https://coveralls.io/r/solariumphp/solarium?branch=master)
<?php
require(__DIR__.'/init.php');
htmlHeader();
// create a client instance
$client = new Solarium\Client($config);
// get a select query instance
$query = $client->createSelect();
// get the facetset component
$facetSet = $query->getFacetSet();
// create a facet field instance and set options
$facet = $facetSet->createFacetInterval('price');
$facet->setField('price');
$facet->setSet(array('1-9' => '[1,10)', '10-49' => '[10,50)', '49>' => '[50,*)'));
// this executes the query and returns the result
$resultset = $client->select($query);
// display the total number of documents found by solr
echo 'NumFound: '.$resultset->getNumFound();
// display facet counts
echo '<hr/>Facet intervals:<br/>';
$facet = $resultset->getFacetSet()->getFacet('price');
foreach ($facet as $range => $count) {
echo $range . ' to ' . ($range + 100) . ' [' . $count . ']<br/>';
}
// show documents using the resultset iterator
foreach ($resultset as $document) {
echo '<hr/><table>';
echo '<tr><th>id</th><td>' . $document->id . '</td></tr>';
echo '<tr><th>name</th><td>' . $document->name . '</td></tr>';
echo '<tr><th>price</th><td>' . $document->price . '</td></tr>';
echo '</table>';
}
htmlFooter();
......@@ -42,6 +42,7 @@
<li><a href="2.1.5.1.3-facet-multiquery.php">2.1.5.1.3 Facet multiquery</a></li>
<li><a href="2.1.5.1.4-facet-range.php">2.1.5.1.4 Facet range</a></li>
<li><a href="2.1.5.1.5-facet-pivot.php">2.1.5.1.5 Facet pivot</a></li>
<li><a href="2.1.5.1.6-facet-interval.php">2.1.5.1.6 Facet interval</a></li>
</ul>
<li><a href="2.1.5.2-morelikethis.php">2.1.5.2 MoreLikeThis</a></li>
<li><a href="2.1.5.3-highlighting.php">2.1.5.3 Highlighting</a></li>
......
......@@ -70,7 +70,7 @@ class Client extends CoreClient
*
* @var string
*/
const VERSION = '3.2.0';
const VERSION = '3.4.0';
/**
* Check for an exact version
......
......@@ -184,7 +184,7 @@ class Curl extends Configurable implements AdapterInterface
if ($request->getFileUpload()) {
if (version_compare(PHP_VERSION, '5.5.0') >= 0) {
$curlFile = curl_file_create($request->getFileUpload());
curl_setopt($handler, CURLOPT_POSTFIELDS, array('content', $curlFile));
curl_setopt($handler, CURLOPT_POSTFIELDS, array('content' => $curlFile));
} else {
curl_setopt($handler, CURLOPT_POSTFIELDS, array('content' => '@'.$request->getFileUpload()));
}
......
<?php
/**
* Copyright 2011 Bas de Nooijer. All rights reserved.
* Copyright 2012 Alexander Brausewetter. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this listof conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the copyright holder.
*
* @copyright Copyright 2011 Bas de Nooijer <solarium@raspberry.nl>
* @copyright Copyright 2012 Alexander Brausewetter <alex@helpdeskhq.com>
* @copyright Copyright 2014 Marin Purgar <marin.purgar@gmail.com.com>
* @license http://github.com/basdenooijer/solarium/raw/master/COPYING
* @link http://www.solarium-project.org/
*/
/**
* @namespace
*/
namespace Solarium\Core\Client\Adapter;
use Solarium\Core\Configurable;
use Solarium\Core\Client;
use Solarium\Core\Client\Request;
use Solarium\Core\Client\Response;
use Solarium\Core\Client\Endpoint;
use Solarium\Exception\HttpException;
use Solarium\Exception\OutOfBoundsException;
/**
* Adapter that uses a ZF2 Zend\Http\Client
*
* The Zend Framework HTTP client has many great features and has lots of
* configuration options. For more info see the manual at
* {@link http://framework.zend.com/manual/en/zend.http.html}
*
* To use this adapter you need to have the Zend Framework available (autoloading)
*/
class Zend2Http extends Configurable implements AdapterInterface
{
/**
* Zend Http instance for communication with Solr
*
* @var \Zend\Http\Client
*/
protected $zendHttp;
/**
* @var int
*/
protected $timeout;
/**
* Set options
*
* Overrides any existing values.
*
* If the options array has an 'options' entry it is forwarded to the
* Zend\Http\Client. See the Zend\Http\Client docs for the many config
* options available.
*
* The $options param should be an array or an object that has a toArray
* method, like Zend_Config
*
* @param array|object $options
* @param boolean $overwrite
* @return self Provides fluent interface
*/
public function setOptions($options, $overwrite = false)
{
parent::setOptions($options, $overwrite);
// forward options to zendHttp instance
if (null !== $this->zendHttp) {
// forward timeout setting
$adapterOptions = array();
// forward adapter options if available
if (isset($this->options['options'])) {
$adapterOptions = array_merge($adapterOptions, $this->options['options']);
}
$this->zendHttp->setOptions($adapterOptions);
}
return $this;
}
/**
* Set the Zend\Http\Client instance
*
* This method is optional, if you don't set a client it will be created
* upon first use, using default and/or custom options (the most common use
* case)
*
* @param \Zend\Http\Client $zendHttp
* @return self Provides fluent interface
*/
public function setZendHttp($zendHttp)
{
$this->zendHttp = $zendHttp;
return $this;
}
/**
* Get the Zend\Http\Client instance
*
* If no instance is available yet it will be created automatically based on
* options.
*
* You can use this method to get a reference to the client instance to set
* options, get the last response and use many other features offered by the
* Zend\Http\Client API.
*
* @return \Zend\Http\Client
*/
public function getZendHttp()
{
if (null == $this->zendHttp) {
$options = array();
// forward zendhttp options
if (isset($this->options['options'])) {
$options = array_merge(
$options,
$this->options['options']
);
}
$this->zendHttp = new \Zend\Http\Client(null, $options);
}
return $this->zendHttp;
}
/**
* Execute a Solr request using the Zend\Http\Client instance
*
* @throws HttpException
* @throws OutOfBoundsException
* @param Request $request
* @param Endpoint $endpoint
* @return Response
*/
public function execute($request, $endpoint)
{
$client = $this->getZendHttp();
$client->resetParameters();
switch ($request->getMethod()) {
case Request::METHOD_GET:
$client->setMethod('GET');
$client->setParameterGet($request->getParams());
break;
case Request::METHOD_POST:
$client->setMethod('POST');
if ($request->getFileUpload()) {
$this->prepareFileUpload($client, $request);
} else {
$client->setParameterGet($request->getParams());
$client->setRawBody($request->getRawData());
$request->addHeader('Content-Type: text/xml; charset=UTF-8');
}
break;
case Request::METHOD_HEAD:
$client->setMethod('HEAD');
$client->setParameterGet($request->getParams());
break;
default:
throw new OutOfBoundsException('Unsupported method: ' . $request->getMethod());
break;
}
$client->setUri($endpoint->getBaseUri() . $request->getHandler());
$client->setHeaders($request->getHeaders());
$this->timeout = $endpoint->getTimeout();
$response = $client->send();
return $this->prepareResponse(
$request,
$response
);
}
/**
* Prepare a solarium response from the given request and client
* response
*
* @throws HttpException
* @param Request $request
* @param \Zend\Http\Response $response
* @return Response
*/
protected function prepareResponse($request, $response)
{
if ($response->isClientError()) {
throw new HttpException(
$response->getReasonPhrase(),
$response->getStatusCode()
);
}
if ($request->getMethod() == Request::METHOD_HEAD) {
$data = '';
} else {
$data = $response->getBody();
}
// this is used because in ZF2 status line isn't in the headers anymore
$headers = array($response->renderStatusLine());
return new Response($data, $headers);
}
/**
* Prepare the client to send the file and params in request
*
* @param \Zend\Http\Client $client
* @param Request $request
* @return void
*/
protected function prepareFileUpload($client, $request)
{
$filename = $request->getFileUpload();
$client->setFileUpload(
'content',
'content',
file_get_contents($filename),
'application/octet-stream; charset=binary'
);
}
}
......@@ -104,6 +104,17 @@ class Document implements \IteratorAggregate, \Countable, \ArrayAccess
return $this->document->__get($name);
}
/**
* Forward isset call to the original document
*
* @param string $name
* @return boolean
*/
public function __isset($name)
{
return $this->document->__isset($name);
}
/**
* IteratorAggregate implementation
*
......
<?php
/**
* Copyright 2011 Bas de Nooijer. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this listof conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the copyright holder.
*
* @copyright Copyright 2011 Bas de Nooijer <solarium@raspberry.nl>
* @license http://github.com/basdenooijer/solarium/raw/master/COPYING
* @link http://www.solarium-project.org/
*/
/**
* @namespace
*/
namespace Solarium\QueryType\Select\Query\Component\Facet;
use Solarium\QueryType\Select\Query\Component\FacetSet;
/**
* Facet interval
*
* @link http://wiki.apache.org/solr/SimpleFacetParameters#Interval_Faceting
*/
class Interval extends Facet
{
/**
* Initialize options
*
* Several options need some extra checks or setup work, for these options
* the setters are called.
*
* @return void
*/
protected function init()
{
parent::init();
foreach ($this->options as $name => $value) {
switch ($name) {
case 'set':
$this->setSet($value);
break;
}
}
}
/**
* Get the facet type
*
* @return string
*/
public function getType()
{
return FacetSet::FACET_INTERVAL;
}
/**
* Set the field name
*
* @param string $field
* @return self Provides fluent interface
*/
public function setField($field)
{
return $this->setOption('field', $field);
}
/**
* Get the field name
*
* @return string
*/
public function getField()
{
return $this->getOption('field');
}
/**
* Set set counts
*
* Use one of the constants as value.
* If you want to use multiple values supply an array or comma separated string
*
* @param string|array $set
* @return self Provides fluent interface
*/
public function setSet($set)
{
if (is_string($set)) {
$set = explode(',', $set);
$set = array_map('trim', $set);
}
return $this->setOption('set', $set);
}
/**
* Get set counts
*
* @return array
*/
public function getSet()
{
$set = $this->getOption('set');
if ($set === null) {
$set = array();
}
return $set;
}
}
......@@ -54,6 +54,13 @@ class Pivot extends Facet
*/
protected $fields = array();
/**
* Optional stats
*
* @var array
*/
protected $stats = array();
/**
* Initialize options
*
......@@ -61,8 +68,15 @@ class Pivot extends Facet
*/
protected function init()
{
if (isset($this->options['fields'])) {
$this->addFields($this->options['fields']);
foreach ($this->options as $name => $value) {
switch ($name) {
case 'fields':
$this->addFields($value);
break;
case 'stats':
$this->setStats($value);
break;
}
}
}
......@@ -184,4 +198,92 @@ class Pivot extends Facet
return $this;
}
/**
* Add stat
*
* @param string $stat
* @return self Provides fluent interface
*/
public function addStat($stat)
{
$this->stats[$stat] = true;
return $this;
}
/**
* Specify multiple Stats
*
* @param string|array $stats can be an array or string with comma
* separated statnames
*
* @return self Provides fluent interface
*/
public function addStats($stats)
{
if (is_string($stats)) {
$stats = explode(',', $stats);
$stats = array_map('trim', $stats);
}
foreach ($stats as $stat) {
$this->addStat($stat);
}
return $this;
}
/**
* Remove a stat from the stats list
*
* @param string $stat
* @return self Provides fluent interface
*/
public function removeStat($stat)
{
if (isset($this->stats[$stat])) {
unset($this->stats[$stat]);
}
return $this;
}
/**
* Remove all stats from the stats list.
*
* @return self Provides fluent interface
*/
public function clearStats()
{
$this->stats = array();
return $this;
}
/**
* Get the list of stats
*
* @return array
*/
public function getStats()
{
return array_keys($this->stats);
}
/**
* Set multiple stats
*
* This overwrites any existing stats
*
* @param array $stats
* @return self Provides fluent interface
*/
public function setStats($stats)
{
$this->clearStats();
$this->addStats($stats);
return $this;
}
}
......@@ -77,6 +77,11 @@ class FacetSet extends Component
*/
const FACET_PIVOT = 'pivot';
/**
* Facet type interval
*/
const FACET_INTERVAL = 'interval';
/**
* Facet type mapping
*
......@@ -88,6 +93,7 @@ class FacetSet extends Component
self::FACET_MULTIQUERY => 'Solarium\QueryType\Select\Query\Component\Facet\MultiQuery',
self::FACET_RANGE => 'Solarium\QueryType\Select\Query\Component\Facet\Range',
self::FACET_PIVOT => 'Solarium\QueryType\Select\Query\Component\Facet\Pivot',
self::FACET_INTERVAL => 'Solarium\QueryType\Select\Query\Component\Facet\Interval',
);
/**
......@@ -526,4 +532,16 @@ class FacetSet extends Component
{
return $this->createFacet(self::FACET_PIVOT, $options, $add);
}
/**
* Get a facet interval instance
*
* @param mixed $options
* @param bool $add
* @return \Solarium\QueryType\Select\Query\Component\Facet\Interval
*/
public function createFacetInterval($options = null, $add = true)
{
return $this->createFacet(self::FACET_INTERVAL, $options, $add);
}
}
......@@ -477,11 +477,12 @@ class Grouping extends Component
/**
* Set facet option
*
* Group based on the unique values of a function query.
* Whether to compute grouped facets.
* Grouped facets are computed based on the first specified group.
* This parameter only is supported on Solr 4.0+
*
* @param string $value
* @return self Provides fluent interface
* @param boolean $value
* @return self Provides fluent interface
*/
public function setFacet($value)
{
......@@ -491,7 +492,7 @@ class Grouping extends Component
/**
* Get facet option
*
* @return string|null
* @return boolean|null
*/
public function getFacet()
{
......
......@@ -52,6 +52,13 @@ class Field extends Configurable
*/
protected $facets = array();
/**
* pivot facets for these stats
*
* @var array
*/
protected $pivots = array();
/**
* Initialize options
*
......@@ -67,6 +74,9 @@ class Field extends Configurable
case 'facet':
$this->setFacets($value);
break;
case 'pivot':
$this->setPivots($value);
break;
}
}
}
......@@ -179,4 +189,92 @@ class Field extends Configurable
return $this;
}
/**
* Add pivot
*
* @param string $pivot
* @return self Provides fluent interface
*/
public function addPivot($pivot)
{
$this->pivots[$pivot] = true;
return $this;
}
/**
* Specify multiple Pivots
*
* @param string|array $pivots can be an array or string with comma
* separated facetnames
*
* @return self Provides fluent interface
*/
public function addPivots($pivots)
{
if (is_string($pivots)) {
$pivots = explode(',', $pivots);
$pivots = array_map('trim', $pivots);
}
foreach ($pivots as $facet) {
$this->addPivot($facet);
}
return $this;
}
/**
* Remove a pivot facet from the pivot list
*
* @param string $pivot
* @return self Provides fluent interface
*/
public function removePivot($pivot)
{
if (isset($this->pivots[$pivot])) {
unset($this->pivots[$pivot]);
}
return $this;
}
/**
* Remove all pivot facets from the pivot list.
*
* @return self Provides fluent interface
*/
public function clearPivots()
{
$this->pivots = array();
return $this;
}
/**
* Get the list of pivot facets
*
* @return array
*/
public function getPivots()
{
return array_keys($this->pivots);
}
/**
* Set multiple pivot facets
*
* This overwrites any existing pivots
*
* @param array $pivots
* @return self Provides fluent interface
*/
public function setPivots($pivots)
{
$this->clearPivots();
$this->addPivots($pivots);
return $this;
}
}
......@@ -46,6 +46,7 @@ use Solarium\QueryType\Select\Query\Component\Facet\MultiQuery as FacetMultiQuer
use Solarium\QueryType\Select\Query\Component\Facet\Query as FacetQuery;
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;
use Solarium\Exception\UnexpectedValueException;
/**
......@@ -93,6 +94,9 @@ class FacetSet extends RequestBuilder implements ComponentRequestBuilderInterfac
case FacetsetComponent::FACET_PIVOT:
$this->addFacetPivot($request, $facet);
break;
case FacetsetComponent::FACET_INTERVAL:
$this->addFacetInterval($request, $facet);
break;
default:
throw new UnexpectedValueException('Unknown facet type');
}
......@@ -205,13 +209,52 @@ class FacetSet extends RequestBuilder implements ComponentRequestBuilderInterfac
*/
public function addFacetPivot($request, $facet)
{
$stats = $facet->getStats();
if (count($stats) > 0) {
$key = array('stats' => implode('', $stats));
// when specifying stats, solr sets the field as key
$facet->setKey(implode(',', $facet->getFields()));
} else {
$key = array('key' => $facet->getKey());
}
$request->addParam(
'facet.pivot',
$this->renderLocalParams(
implode(',', $facet->getFields()),
array('key' => $facet->getKey(), 'ex' => $facet->getExcludes())
array_merge($key, array('ex' => $facet->getExcludes()))
)
);
$request->addParam('facet.pivot.mincount', $facet->getMinCount(), true);
}
/**
* Add params for a interval facet to request
*
* @param Request $request
* @param FacetInterval $facet
* @return void
*/
public function addFacetInterval($request, $facet)
{
$field = $facet->getField();
$request->addParam(
'facet.interval',
$this->renderLocalParams(
$field
// key & ex not supported for interval
//,array('key' => $facet->getKey(), 'ex' => $facet->getExcludes())
)
);
foreach ($facet->getSet() as $key => $setValue) {
if(is_string($key)) {
$setValue = '{!key="'.$key.'"}'.$setValue;
}
$request->addParam("f.$field.facet.interval.set", $setValue);
}
}
}
......@@ -60,8 +60,10 @@ class Stats implements ComponentRequestBuilderInterface
// add fields
foreach ($component->getFields() as $field) {
$pivots = $field->getPivots();
$request->addParam('stats.field', $field->getKey());
$prefix = (count($pivots) > 0) ? '{!tag='.implode(',', $pivots).'}' : '';
$request->addParam('stats.field', $prefix . $field->getKey());
// add field specific facet stats
foreach ($field->getFacets() as $facet) {
......
......@@ -51,6 +51,7 @@ use Solarium\QueryType\Select\Result\Facet\Query as ResultFacetQuery;
use Solarium\QueryType\Select\Result\Facet\MultiQuery as ResultFacetMultiQuery;
use Solarium\QueryType\Select\Result\Facet\Range as ResultFacetRange;
use Solarium\QueryType\Select\Result\Facet\Pivot\Pivot as ResultFacetPivot;
use Solarium\QueryType\Select\Result\Facet\Interval as ResultFacetInterval;
use Solarium\Exception\RuntimeException;
use Solarium\Core\Query\ResponseParser as ResponseParserAbstract;
......@@ -86,6 +87,9 @@ class FacetSet extends ResponseParserAbstract implements ComponentParserInterfac
case 'facet_pivot':
$method = 'createFacetPivot';
break;
case 'facet_interval':
$method = 'createFacetInterval';
break;
default:
throw new RuntimeException('Unknown facet class identifier');
}
......@@ -118,6 +122,9 @@ class FacetSet extends ResponseParserAbstract implements ComponentParserInterfac
case QueryFacetSet::FACET_PIVOT:
$result = $this->facetPivot($query, $facet, $data);
break;
case QueryFacetSet::FACET_INTERVAL:
$result = $this->facetInterval($query, $facet, $data);
break;
default:
throw new RuntimeException('Unknown facet type');
}
......@@ -236,6 +243,24 @@ class FacetSet extends ResponseParserAbstract implements ComponentParserInterfac
return new ResultFacetRange($data['counts'], $before, $after, $between, $start, $end, $gap);
}
/**
* Add a facet result for a interval facet
*
* @param Query $query
* @param QueryFacetInterval $facet
* @param array $data
* @return ResultFacetInterval|null
*/
protected function facetInterval($query, $facet, $data)
{
$key = $facet->getKey();
if (!isset($data['facet_counts']['facet_intervals'][$key])) {
return null;
}
return new ResultFacetInterval($data['facet_counts']['facet_intervals'][$key]);
}
/**
* Add a facet result for a range facet
......
......@@ -96,6 +96,30 @@ class Spellcheck extends ResponseParserAbstract implements ComponentParserInterf
}
}
/*
* https://issues.apache.org/jira/browse/SOLR-3029
* Solr5 has moved collations and correctlySpelled
* directly under spellcheck.
*/
if (isset($data['spellcheck']['collations']) &&
is_array($data['spellcheck']['collations'])
) {
foreach ($data['spellcheck']['collations'] as $collationResult) {
if (is_array($collationResult)) {
$collation = array();
foreach ($collationResult as $key => $value) {
$collation = array_merge($collation, array($key, $value));
}
$collations = array_merge($collations, $this->parseCollation($query, $collation ));
}
}
}
if (isset($data['spellcheck']['correctlySpelled'])
) {
$correctlySpelled = $data['spellcheck']['correctlySpelled'];
}
return new SpellcheckResult\Result($suggestions, $collations, $correctlySpelled);
} else {
return null;
......
......@@ -78,6 +78,20 @@ abstract class AbstractDocument implements \IteratorAggregate, \Countable, \Arra
return $this->fields[$name];
}
/**
* Check if field is set by name
*
* Magic method for checking if fields are set as properties of this document
* object, by field name. Also used by empty().
*
* @param string $name
* @return boolean
*/
public function __isset($name)
{
return isset($this->fields[$name]);
}
/**
* IteratorAggregate implementation
*
......
<?php
/**
* Copyright 2011 Bas de Nooijer. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this listof conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the copyright holder.
*
* @copyright Copyright 2011 Bas de Nooijer <solarium@raspberry.nl>
* @license http://github.com/basdenooijer/solarium/raw/master/COPYING
* @link http://www.solarium-project.org/
*/
/**
* @namespace
*/
namespace Solarium\QueryType\Select\Result\Facet;
/**
* Select interval facet result
*
* A interval facet will usually return a dataset of multiple rows, in each row a
* value and its count. You can access the values as an array using
* {@link getValues()} or iterate this object.
*/
class Interval extends Field
{
}
......@@ -38,6 +38,8 @@
*/
namespace Solarium\QueryType\Select\Result\Facet\Pivot;
use Solarium\QueryType\Select\Result\Stats\Stats;
/**
* Select field pivot result
*
......@@ -65,6 +67,13 @@ class PivotItem extends Pivot
*/
protected $count;
/**
* Field stats
*
* @var mixed
*/
protected $stats;
/**
* Constructor
*
......@@ -81,6 +90,10 @@ class PivotItem extends Pivot
$this->pivot[] = new PivotItem($pivotData);
}
}
if (isset($data['stats'])) {
$this->stats = new Stats($data['stats']);
}
}
/**
......@@ -112,4 +125,14 @@ class PivotItem extends Pivot
{
return $this->count;
}
/**
* Get stats
*
* @return Stats
*/
public function getStats()
{
return $this->stats;
}
}
......@@ -89,9 +89,12 @@ class Add extends Command
*/
public function addDocuments($documents)
{
foreach ($documents as $document) {
if (!($document instanceof DocumentInterface)) {
throw new RuntimeException('Documents must implement DocumentInterface.');
//only check documents for type if in an array (iterating a Traversable may do unnecessary work)
if (is_array($documents)) {
foreach ($documents as $document) {
if (!($document instanceof DocumentInterface)) {
throw new RuntimeException('Documents must implement DocumentInterface.');
}
}
}
......
......@@ -33,9 +33,9 @@ namespace Solarium\Tests\Plugin\MinimumScoreFilter;
use Solarium\QueryType\Select\Result\Document;
use Solarium\Plugin\MinimumScoreFilter\Document as FilterDocument;
use Solarium\Tests\QueryType\Select\Result\DocumentTest as SelectDocumentTest;
use Solarium\Tests\QueryType\Select\Result\AbstractDocumentTest;
class DocumentTest extends SelectDocumentTest
class DocumentTest extends AbstractDocumentTest
{
protected function setUp()
{
......
......@@ -32,11 +32,10 @@
namespace Solarium\Tests\Plugin\MinimumScoreFilter;
use Solarium\Plugin\MinimumScoreFilter\Query;
use Solarium\Tests\QueryType\Select\Query\QueryTest as SelectQueryTest;
use Solarium\Tests\QueryType\Select\Query\AbstractQueryTest;
class QueryTest extends SelectQueryTest
class QueryTest extends AbstractQueryTest
{
public function setUp()
{
$this->query = new Query;
......
......@@ -34,9 +34,9 @@ namespace Solarium\Tests\Plugin\MinimumScoreFilter;
use Solarium\Plugin\MinimumScoreFilter\Query;
use Solarium\Plugin\MinimumScoreFilter\Result;
use Solarium\QueryType\Select\Result\Document;
use Solarium\Tests\QueryType\Select\Result\ResultTest as SelectResultTest;
use Solarium\Tests\QueryType\Select\Result\AbstractResultTest;
class ResultTest extends SelectResultTest
class ResultTest extends AbstractResultTest
{
public function setUp()
{
......
......@@ -131,4 +131,14 @@ class RequestBuilderTest extends \PHPUnit_Framework_TestCase
$this->setExpectedException('Solarium\Exception\RuntimeException');
$this->builder->build($this->query);
}
public function testContentTypeHeader()
{
$headers = array(
'Content-Type: multipart/form-data'
);
$request = $this->builder->build($this->query);
$this->assertEquals($headers,
$request->getHeaders());
}
}
......@@ -31,10 +31,10 @@
namespace Solarium\Tests\QueryType\Extract;
use Solarium\Tests\QueryType\Update\ResultTest as UpdateResultTest;
use Solarium\QueryType\Extract\Result as ExtractResult;
use Solarium\Tests\QueryType\Update\AbstractResultTest;
class ResultTest extends UpdateResultTest
class ResultTest extends AbstractResultTest
{
public function setUp()
{
......
......@@ -67,6 +67,13 @@ class PivotTest extends \PHPUnit_Framework_TestCase
);
}
public function testSetMinCount()
{
$this->facet->setMinCount(5);
$this->assertEquals(5, $this->facet->getMinCount());
}
public function testAddField()
{
$expectedFields = $this->facet->getFields();
......@@ -113,4 +120,51 @@ class PivotTest extends \PHPUnit_Framework_TestCase
$this->facet->setFields(array('field3', 'field4'));
$this->assertEquals(array('field3', 'field4'), $this->facet->getFields());
}
public function testAddStat()
{
$expectedStats = $this->facet->getStats();
$expectedStats[] = 'newstat';
$this->facet->addStat('newstat');
$this->assertEquals($expectedStats, $this->facet->getStats());
}
public function testClearStats()
{
$this->facet->addStat('newstat');
$this->facet->clearStats();
$this->assertEquals(array(), $this->facet->getStats());
}
public function testAddStats()
{
$stats = array('stat1', 'stat2');
$this->facet->clearStats();
$this->facet->addStats($stats);
$this->assertEquals($stats, $this->facet->getStats());
}
public function testAddStatsAsStringWithTrim()
{
$this->facet->clearStats();
$this->facet->addStats('stat1, stat2');
$this->assertEquals(array('stat1', 'stat2'), $this->facet->getStats());
}
public function testRemoveStat()
{
$this->facet->clearStats();
$this->facet->addStats(array('stat1', 'stat2'));
$this->facet->removeStat('stat1');
$this->assertEquals(array('stat2'), $this->facet->getstats());
}
public function testSetStats()
{
$this->facet->clearStats();
$this->facet->addStats(array('stat1', 'stat2'));
$this->facet->setStats(array('stat3', 'stat4'));
$this->assertEquals(array('stat3', 'stat4'), $this->facet->getStats());
}
}
......@@ -82,6 +82,13 @@ class RangeTest extends \PHPUnit_Framework_TestCase
);
}
public function testSetMinCount()
{
$this->facet->setMinCount(5);
$this->assertEquals(5, $this->facet->getMinCount());
}
public function testSetAndGetField()
{
$this->facet->setField('price');
......
......@@ -49,6 +49,7 @@ class FieldTest extends \PHPUnit_Framework_TestCase
{
$options = array(
'facet' => 'field1, field2',
'pivot' => 'piv1'
);
$this->field->setOptions($options);
......@@ -107,4 +108,51 @@ class FieldTest extends \PHPUnit_Framework_TestCase
$this->field->setFacets(array('facet3', 'facet4'));
$this->assertEquals(array('facet3', 'facet4'), $this->field->getFacets());
}
public function testAddPivot()
{
$expectedPivots = $this->field->getPivots();
$expectedPivots[] = 'newpivot';
$this->field->addPivot('newpivot');
$this->assertEquals($expectedPivots, $this->field->getPivots());
}
public function testClearPivots()
{
$this->field->addPivot('newpivot');
$this->field->clearPivots();
$this->assertEquals(array(), $this->field->getPivots());
}
public function testAddPivots()
{
$pivots = array('pivot1', 'pivot2');
$this->field->clearPivots();
$this->field->addPivots($pivots);
$this->assertEquals($pivots, $this->field->getPivots());
}
public function testAddPivotsAsStringWithTrim()
{
$this->field->clearPivots();
$this->field->addPivots('pivot1, pivot2');
$this->assertEquals(array('pivot1', 'pivot2'), $this->field->getPivots());
}
public function testRemovePivot()
{
$this->field->clearPivots();
$this->field->addPivots(array('pivot1', 'pivot2'));
$this->field->removePivot('pivot1');
$this->assertEquals(array('pivot2'), $this->field->getPivots());
}
public function testSetPivots()
{
$this->field->clearPivots();
$this->field->addPivots(array('pivot1', 'pivot2'));
$this->field->setPivots(array('pivot3', 'pivot4'));
$this->assertEquals(array('pivot3', 'pivot4'), $this->field->getPivots());
}
}
......@@ -208,6 +208,30 @@ class FacetSetTest extends \PHPUnit_Framework_TestCase
urldecode($request->getUri())
);
}
public function testBuildWithPivotStatFacet()
{
$facet = new FacetPivot(
array(
'key' => 'f1',
'fields' => 'cat,inStock',
'stats' => 'piv1'
)
);
$this->component->addFacet($facet);
$request = $this->builder->buildComponent($this->component, $this->request);
$this->assertEquals(
null,
$request->getRawData()
);
$this->assertEquals(
'?facet=true&facet.pivot={!stats=piv1}cat,inStock',
urldecode($request->getUri())
);
}
}
class UnknownFacet extends FacetField
......
......@@ -201,6 +201,10 @@ class FacetSetTest extends \PHPUnit_Framework_TestCase
'pivot' => array(
array('field' => 'price', 'value' => 1, 'count' => 12),
array('field' => 'price', 'value' => 2, 'count' => 8),
),
'stats' => array(
'min' => 4,
'max' => 6,
)
)
),
......@@ -262,6 +266,13 @@ class FacetSetTest extends \PHPUnit_Framework_TestCase
count($facets['cat,price'])
);
$pivots = $facets['cat,price']->getPivot();
$this->assertEquals(
2,
count($pivots[0]->getStats())
);
$this->query = new Query;
}
......
<?php
/**
* Copyright 2011 Bas de Nooijer. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this listof conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the copyright holder.
*/
namespace Solarium\Tests\QueryType\Select\Result;
abstract class AbstractDocumentTest extends \PHPUnit_Framework_TestCase
{
protected $doc;
protected $fields = array(
'id' => 123,
'name' => 'Test document',
'categories' => array(1, 2, 3),
'empty_field' => '',
);
public function testGetFields()
{
$this->assertEquals($this->fields, $this->doc->getFields());
}
public function testGetFieldAsProperty()
{
$this->assertEquals(
$this->fields['categories'],
$this->doc->categories
);
$this->assertEquals(
null,
$this->doc->invalidfieldname
);
}
public function testPropertyIsset()
{
$this->assertTrue(
isset($this->doc->categories)
);
$this->assertFalse(
isset($this->doc->invalidfieldname)
);
}
public function testPropertyEmpty()
{
$this->assertTrue(
empty($this->doc->empty_field)
);
$this->assertFalse(
empty($this->doc->categories)
);
}
public function testSetField()
{
$this->setExpectedException('Solarium\Exception\RuntimeException');
$this->doc->newField = 'new value';
}
public function testIterator()
{
$fields = array();
foreach ($this->doc as $key => $field) {
$fields[$key] = $field;
}
$this->assertEquals($this->fields, $fields);
}
public function testArrayGet()
{
$this->assertEquals(
$this->fields['categories'],
$this->doc['categories']
);
$this->assertEquals(
null,
$this->doc['invalidfieldname']
);
}
public function testArrayIsset()
{
$this->assertTrue(
isset($this->doc['categories'])
);
$this->assertFalse(
isset($this->doc['invalidfieldname'])
);
}
public function testArrayEmpty()
{
$this->assertTrue(
empty($this->doc['empty_field'])
);
$this->assertFalse(
empty($this->doc['categories'])
);
}
public function testArraySet()
{
$this->setExpectedException('Solarium\Exception\RuntimeException');
$this->doc['newField'] = 'new value';
}
public function testArrayUnset()
{
$this->setExpectedException('Solarium\Exception\RuntimeException');
unset($this->doc['newField']);
}
public function testCount()
{
$this->assertEquals(count($this->fields), count($this->doc));
}
}
<?php
/**
* Copyright 2011 Bas de Nooijer. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this listof conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the copyright holder.
*/
namespace Solarium\Tests\QueryType\Select\Result;
use Solarium\QueryType\Select\Result\Document;
use Solarium\QueryType\Select\Query\Query;
use Solarium\QueryType\Select\Result\Result;
abstract class AbstractResultTest extends \PHPUnit_Framework_TestCase
{
/**
* @var SelectDummy
*/
protected $result;
protected $numFound;
protected $maxScore;
protected $docs;
protected $components;
protected $facetSet;
protected $moreLikeThis;
protected $highlighting;
protected $grouping;
protected $stats;
protected $debug;
protected $spellcheck;
public function setUp()
{
$this->numFound = 11;
$this->maxScore = 0.91;
$this->docs = array(
new Document(array('id'=>1, 'title'=>'doc1')),
new Document(array('id'=>1, 'title'=>'doc1')),
);
$this->facetSet = 'dummy-facetset-value';
$this->moreLikeThis = 'dummy-facetset-value';
$this->highlighting = 'dummy-highlighting-value';
$this->grouping = 'dummy-grouping-value';
$this->spellcheck = 'dummy-grouping-value';
$this->stats = 'dummy-stats-value';
$this->debug = 'dummy-debug-value';
$this->components = array(
Query::COMPONENT_FACETSET => $this->facetSet,
Query::COMPONENT_MORELIKETHIS => $this->moreLikeThis,
Query::COMPONENT_HIGHLIGHTING => $this->highlighting,
Query::COMPONENT_GROUPING => $this->grouping,
Query::COMPONENT_SPELLCHECK => $this->spellcheck,
Query::COMPONENT_STATS => $this->stats,
Query::COMPONENT_DEBUG => $this->debug,
);
$this->result = new SelectDummy(1, 12, $this->numFound, $this->maxScore, $this->docs, $this->components);
}
public function testGetNumFound()
{
$this->assertEquals($this->numFound, $this->result->getNumFound());
}
public function testGetMaxScore()
{
$this->assertEquals($this->maxScore, $this->result->getMaxScore());
}
public function testGetDocuments()
{
$this->assertEquals($this->docs, $this->result->getDocuments());
}
public function testGetFacetSet()
{
$this->assertEquals($this->facetSet, $this->result->getFacetSet());
}
public function testCount()
{
$this->assertEquals(count($this->docs), count($this->result));
}
public function testGetComponents()
{
$this->assertEquals($this->components, $this->result->getComponents());
}
public function testGetComponent()
{
$this->assertEquals(
$this->components[Query::COMPONENT_MORELIKETHIS],
$this->result->getComponent(Query::COMPONENT_MORELIKETHIS)
);
}
public function testGetInvalidComponent()
{
$this->assertEquals(
null,
$this->result->getComponent('invalid')
);
}
public function testGetMoreLikeThis()
{
$this->assertEquals(
$this->components[Query::COMPONENT_MORELIKETHIS],
$this->result->getMoreLikeThis()
);
}
public function testGetHighlighting()
{
$this->assertEquals(
$this->components[Query::COMPONENT_HIGHLIGHTING],
$this->result->getHighlighting()
);
}
public function testGetGrouping()
{
$this->assertEquals(
$this->components[Query::COMPONENT_GROUPING],
$this->result->getGrouping()
);
}
public function testGetSpellcheck()
{
$this->assertEquals(
$this->components[Query::COMPONENT_SPELLCHECK],
$this->result->getSpellcheck()
);
}
public function testGetStats()
{
$this->assertEquals(
$this->components[Query::COMPONENT_STATS],
$this->result->getStats()
);
}
public function testGetDebug()
{
$this->assertEquals(
$this->components[Query::COMPONENT_DEBUG],
$this->result->getDebug()
);
}
public function testIterator()
{
$docs = array();
foreach ($this->result as $key => $doc) {
$docs[$key] = $doc;
}
$this->assertEquals($this->docs, $docs);
}
public function testGetStatus()
{
$this->assertEquals(
1,
$this->result->getStatus()
);
}
public function testGetQueryTime()
{
$this->assertEquals(
12,
$this->result->getQueryTime()
);
}
}
class SelectDummy extends Result
{
protected $parsed = true;
public function __construct($status, $queryTime, $numfound, $maxscore, $docs, $components)
{
$this->numfound = $numfound;
$this->maxscore = $maxscore;
$this->documents = $docs;
$this->components = $components;
$this->queryTime = $queryTime;
$this->status = $status;
}
}
......@@ -33,102 +33,10 @@ namespace Solarium\Tests\QueryType\Select\Result;
use Solarium\QueryType\Select\Result\Document;
class DocumentTest extends \PHPUnit_Framework_TestCase
class DocumentTest extends AbstractDocumentTest
{
protected $doc;
protected $fields = array(
'id' => 123,
'name' => 'Test document',
'categories' => array(1, 2, 3)
);
protected function setUp()
{
$this->doc = new Document($this->fields);
}
public function testGetFields()
{
$this->assertEquals($this->fields, $this->doc->getFields());
}
public function testGetFieldAsProperty()
{
$this->assertEquals(
$this->fields['categories'],
$this->doc->categories
);
}
public function testGetInvalidFieldAsProperty()
{
$this->assertEquals(
null,
$this->doc->invalidfieldname
);
}
public function testSetField()
{
$this->setExpectedException('Solarium\Exception\RuntimeException');
$this->doc->newField = 'new value';
}
public function testIterator()
{
$fields = array();
foreach ($this->doc as $key => $field) {
$fields[$key] = $field;
}
$this->assertEquals($this->fields, $fields);
}
public function testArrayGet()
{
$this->assertEquals(
$this->fields['categories'],
$this->doc['categories']
);
}
public function testArrayGetInvalidField()
{
$this->assertEquals(
null,
$this->doc['invalidfield']
);
}
public function testArrayIsset()
{
$this->assertTrue(
isset($this->doc['categories'])
);
}
public function testArrayIssetInvalidField()
{
$this->assertFalse(
isset($this->doc['invalidfield'])
);
}
public function testArraySet()
{
$this->setExpectedException('Solarium\Exception\RuntimeException');
$this->doc['newField'] = 'new value';
}
public function testArrayUnset()
{
$this->setExpectedException('Solarium\Exception\RuntimeException');
unset($this->doc['newField']);
}
public function testCount()
{
$this->assertEquals(count($this->fields), count($this->doc));
}
}
......@@ -31,192 +31,10 @@
namespace Solarium\Tests\QueryType\Select\Result;
use Solarium\QueryType\Select\Result\Document;
use Solarium\QueryType\Select\Query\Query;
use Solarium\QueryType\Select\Result\Result;
class ResultTest extends \PHPUnit_Framework_TestCase
class ResultTest extends AbstractResultTest
{
/**
* @var SelectDummy
*/
protected $result;
protected $numFound;
protected $maxScore;
protected $docs;
protected $components;
protected $facetSet;
protected $moreLikeThis;
protected $highlighting;
protected $grouping;
protected $stats;
protected $debug;
protected $spellcheck;
public function setUp()
{
$this->numFound = 11;
$this->maxScore = 0.91;
$this->docs = array(
new Document(array('id'=>1, 'title'=>'doc1')),
new Document(array('id'=>1, 'title'=>'doc1')),
);
$this->facetSet = 'dummy-facetset-value';
$this->moreLikeThis = 'dummy-facetset-value';
$this->highlighting = 'dummy-highlighting-value';
$this->grouping = 'dummy-grouping-value';
$this->spellcheck = 'dummy-grouping-value';
$this->stats = 'dummy-stats-value';
$this->debug = 'dummy-debug-value';
$this->components = array(
Query::COMPONENT_FACETSET => $this->facetSet,
Query::COMPONENT_MORELIKETHIS => $this->moreLikeThis,
Query::COMPONENT_HIGHLIGHTING => $this->highlighting,
Query::COMPONENT_GROUPING => $this->grouping,
Query::COMPONENT_SPELLCHECK => $this->spellcheck,
Query::COMPONENT_STATS => $this->stats,
Query::COMPONENT_DEBUG => $this->debug,
);
$this->result = new SelectDummy(1, 12, $this->numFound, $this->maxScore, $this->docs, $this->components);
}
public function testGetNumFound()
{
$this->assertEquals($this->numFound, $this->result->getNumFound());
}
public function testGetMaxScore()
{
$this->assertEquals($this->maxScore, $this->result->getMaxScore());
}
public function testGetDocuments()
{
$this->assertEquals($this->docs, $this->result->getDocuments());
}
public function testGetFacetSet()
{
$this->assertEquals($this->facetSet, $this->result->getFacetSet());
}
public function testCount()
{
$this->assertEquals(count($this->docs), count($this->result));
}
public function testGetComponents()
{
$this->assertEquals($this->components, $this->result->getComponents());
}
public function testGetComponent()
{
$this->assertEquals(
$this->components[Query::COMPONENT_MORELIKETHIS],
$this->result->getComponent(Query::COMPONENT_MORELIKETHIS)
);
}
public function testGetInvalidComponent()
{
$this->assertEquals(
null,
$this->result->getComponent('invalid')
);
}
public function testGetMoreLikeThis()
{
$this->assertEquals(
$this->components[Query::COMPONENT_MORELIKETHIS],
$this->result->getMoreLikeThis()
);
}
public function testGetHighlighting()
{
$this->assertEquals(
$this->components[Query::COMPONENT_HIGHLIGHTING],
$this->result->getHighlighting()
);
}
public function testGetGrouping()
{
$this->assertEquals(
$this->components[Query::COMPONENT_GROUPING],
$this->result->getGrouping()
);
}
public function testGetSpellcheck()
{
$this->assertEquals(
$this->components[Query::COMPONENT_SPELLCHECK],
$this->result->getSpellcheck()
);
}
public function testGetStats()
{
$this->assertEquals(
$this->components[Query::COMPONENT_STATS],
$this->result->getStats()
);
}
public function testGetDebug()
{
$this->assertEquals(
$this->components[Query::COMPONENT_DEBUG],
$this->result->getDebug()
);
}
public function testIterator()
{
$docs = array();
foreach ($this->result as $key => $doc) {
$docs[$key] = $doc;
}
$this->assertEquals($this->docs, $docs);
}
public function testGetStatus()
{
$this->assertEquals(
1,
$this->result->getStatus()
);
}
public function testGetQueryTime()
{
$this->assertEquals(
12,
$this->result->getQueryTime()
);
}
}
class SelectDummy extends Result
{
protected $parsed = true;
public function __construct($status, $queryTime, $numfound, $maxscore, $docs, $components)
{
$this->numfound = $numfound;
$this->maxscore = $maxscore;
$this->documents = $docs;
$this->components = $components;
$this->queryTime = $queryTime;
$this->status = $status;
parent::setUp();
}
}
<?php
/**
* Copyright 2011 Bas de Nooijer. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this listof conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the copyright holder.
*/
namespace Solarium\Tests\QueryType\Update;
abstract class AbstractResultTest extends \PHPUnit_Framework_TestCase
{
protected $result;
public function testGetStatus()
{
$this->assertEquals(
1,
$this->result->getStatus()
);
}
public function testGetQueryTime()
{
$this->assertEquals(
12,
$this->result->getQueryTime()
);
}
}
......@@ -33,33 +33,12 @@ namespace Solarium\Tests\QueryType\Update;
use Solarium\QueryType\Update\Result as UpdateResult;
class ResultTest extends \PHPUnit_Framework_TestCase
class ResultTest extends AbstractResultTest
{
/**
* @var UpdateDummy
*/
protected $result;
public function setUp()
{
$this->result = new UpdateDummy();
}
public function testGetStatus()
{
$this->assertEquals(
1,
$this->result->getStatus()
);
}
public function testGetQueryTime()
{
$this->assertEquals(
12,
$this->result->getQueryTime()
);
}
}
class UpdateDummy extends UpdateResult
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment