diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ba1f600f..fc54eef4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - BufferedAdd::setCommitWithin - BufferedAdd::setOverwrite - Set erroneous expression on StreamException +- Managed resources, stopwords and synonyms query types ### Deprecated - Endpoint::getBaseUri is deprecated. Please use getServerUri or getCoreBaseUri now. diff --git a/src/Core/Client/Adapter/Curl.php b/src/Core/Client/Adapter/Curl.php index 55fc88a14..f44b0fa76 100644 --- a/src/Core/Client/Adapter/Curl.php +++ b/src/Core/Client/Adapter/Curl.php @@ -136,6 +136,14 @@ public function createHandle($request, $endpoint) curl_setopt($handler, CURLOPT_CUSTOMREQUEST, 'DELETE'); } elseif (Request::METHOD_PUT == $method) { curl_setopt($handler, CURLOPT_CUSTOMREQUEST, 'PUT'); + + if ($request->getFileUpload()) { + $helper = new AdapterHelper(); + $data = $helper->buildUploadBodyFromRequest($request); + curl_setopt($handler, CURLOPT_POSTFIELDS, $data); + } else { + curl_setopt($handler, CURLOPT_POSTFIELDS, $request->getRawData()); + } } else { throw new InvalidArgumentException("unsupported method: $method"); } diff --git a/src/Core/Client/Adapter/Guzzle.php b/src/Core/Client/Adapter/Guzzle.php index ce316f0f3..1911f6764 100644 --- a/src/Core/Client/Adapter/Guzzle.php +++ b/src/Core/Client/Adapter/Guzzle.php @@ -103,6 +103,10 @@ public function getGuzzleClient() */ private function getRequestBody(Request $request) { + if (Request::METHOD_PUT == $request->getMethod()) { + return $request->getRawData(); + } + if (Request::METHOD_POST !== $request->getMethod()) { return null; } diff --git a/src/Core/Client/Adapter/Guzzle3.php b/src/Core/Client/Adapter/Guzzle3.php index 76e6f5340..69852baa6 100644 --- a/src/Core/Client/Adapter/Guzzle3.php +++ b/src/Core/Client/Adapter/Guzzle3.php @@ -98,6 +98,10 @@ public function getGuzzleClient() */ private function getRequestBody(Request $request) { + if (Request::METHOD_PUT == $request->getMethod()) { + return $request->getRawData(); + } + if (Request::METHOD_POST !== $request->getMethod()) { return null; } diff --git a/src/Core/Client/Adapter/Http.php b/src/Core/Client/Adapter/Http.php index 7715711c8..bbdcf9bd8 100644 --- a/src/Core/Client/Adapter/Http.php +++ b/src/Core/Client/Adapter/Http.php @@ -112,6 +112,17 @@ public function createContext($request, $endpoint) $request->addHeader('Content-Type: text/xml; charset=UTF-8'); } } + } elseif (Request::METHOD_PUT == $method) { + $data = $request->getRawData(); + if (null !== $data) { + stream_context_set_option( + $context, + 'http', + 'content', + $data + ); + $request->addHeader('Content-Type: application/json; charset=UTF-8'); + } } $headers = $request->getHeaders(); diff --git a/src/Core/Client/Adapter/PeclHttp.php b/src/Core/Client/Adapter/PeclHttp.php index 5fef12a8f..fb509a09c 100644 --- a/src/Core/Client/Adapter/PeclHttp.php +++ b/src/Core/Client/Adapter/PeclHttp.php @@ -112,6 +112,18 @@ public function toHttpRequest($request, $endpoint) break; case Request::METHOD_PUT: $method = HTTP_METH_PUT; + if ($request->getFileUpload()) { + $httpRequest->addPostFile( + 'content', + $request->getFileUpload(), + 'application/octet-stream; charset=binary' + ); + } else { + $httpRequest->setBody($request->getRawData()); + if (!isset($headers['Content-Type'])) { + $headers['Content-Type'] = 'application/json; charset=utf-8'; + } + } break; default: throw new InvalidArgumentException( diff --git a/src/Core/Client/Adapter/Zend2Http.php b/src/Core/Client/Adapter/Zend2Http.php index 396c37a93..86c06e94a 100644 --- a/src/Core/Client/Adapter/Zend2Http.php +++ b/src/Core/Client/Adapter/Zend2Http.php @@ -160,7 +160,13 @@ public function execute($request, $endpoint) break; case Request::METHOD_PUT: $client->setMethod('PUT'); - $client->setParameterGet($request->getParams()); + if ($request->getFileUpload()) { + $this->prepareFileUpload($client, $request); + } else { + $client->setParameterGet($request->getParams()); + $client->setRawBody($request->getRawData()); + $request->addHeader('Content-Type: application/json; charset=UTF-8'); + } break; default: throw new OutOfBoundsException('Unsupported method: '.$request->getMethod()); diff --git a/src/Core/Client/Adapter/ZendHttp.php b/src/Core/Client/Adapter/ZendHttp.php index 94d92738b..b8f46a6f0 100644 --- a/src/Core/Client/Adapter/ZendHttp.php +++ b/src/Core/Client/Adapter/ZendHttp.php @@ -162,6 +162,13 @@ public function execute($request, $endpoint) case Request::METHOD_PUT: $client->setMethod(\Zend_Http_Client::PUT); $client->setParameterGet($request->getParams()); + if ($request->getFileUpload()) { + $this->prepareFileUpload($client, $request); + } else { + $client->setParameterGet($request->getParams()); + $client->setRawData($request->getRawData()); + $request->addHeader('Content-Type: application/json; charset=UTF-8'); + } break; default: throw new OutOfBoundsException('Unsupported method: '.$request->getMethod()); diff --git a/src/Core/Client/Client.php b/src/Core/Client/Client.php index 70ba8dd0d..cd5608451 100644 --- a/src/Core/Client/Client.php +++ b/src/Core/Client/Client.php @@ -112,6 +112,21 @@ class Client extends Configurable implements ClientInterface */ const QUERY_CORE_ADMIN = 'cores'; + /** + * Querytype managed resource. + */ + const QUERY_MANAGED_RESOURCES = 'resources'; + + /** + * Querytype managed stopwords. + */ + const QUERY_MANAGED_STOPWORDS = 'stopwords'; + + /** + * Querytype managed synonyms. + */ + const QUERY_MANAGED_SYNONYMS = 'synonyms'; + /** * Default options. * @@ -144,6 +159,9 @@ class Client extends Configurable implements ClientInterface self::QUERY_EXTRACT => 'Solarium\QueryType\Extract\Query', self::QUERY_REALTIME_GET => 'Solarium\QueryType\RealtimeGet\Query', self::QUERY_CORE_ADMIN => 'Solarium\QueryType\Server\CoreAdmin\Query\Query', + self::QUERY_MANAGED_RESOURCES => 'Solarium\QueryType\ManagedResources\Query\Resources', + self::QUERY_MANAGED_STOPWORDS => 'Solarium\QueryType\ManagedResources\Query\Stopwords', + self::QUERY_MANAGED_SYNONYMS => 'Solarium\QueryType\ManagedResources\Query\Synonyms', ]; /** @@ -1224,6 +1242,42 @@ public function createCoreAdmin($options = null) return $this->createQuery(self::QUERY_CORE_ADMIN, $options); } + /** + * Create a managed resources query instance. + * + * @param mixed $options + * + * @return \Solarium\QueryType\ManagedResources\Query\Resources + */ + public function createManagedResources($options = null) + { + return $this->createQuery(self::QUERY_MANAGED_RESOURCES, $options); + } + + /** + * Create a managed resources query instance. + * + * @param mixed $options + * + * @return \Solarium\QueryType\ManagedResources\Query\Stopwords + */ + public function createManagedStopwords($options = null) + { + return $this->createQuery(self::QUERY_MANAGED_STOPWORDS, $options); + } + + /** + * Create a managed resources query instance. + * + * @param mixed $options + * + * @return \Solarium\QueryType\ManagedResources\Query\Synonyms + */ + public function createManagedSynonyms($options = null) + { + return $this->createQuery(self::QUERY_MANAGED_SYNONYMS, $options); + } + /** * Initialization hook. */ diff --git a/src/QueryType/ManagedResources/Query/Resources.php b/src/QueryType/ManagedResources/Query/Resources.php new file mode 100644 index 000000000..f75bf642e --- /dev/null +++ b/src/QueryType/ManagedResources/Query/Resources.php @@ -0,0 +1,69 @@ + 'schema/managed', + 'resultclass' => 'Solarium\QueryType\ManagedResources\Result\Resources\ResourceList', + 'omitheader' => true, + ]; + + /** + * Get the name of resources. + * + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * Get query type. + * + * @return string + */ + public function getType(): string + { + return Client::QUERY_MANAGED_RESOURCES; + } + + /** + * Get the request builder class for this query. + * + * @return RequestBuilder + */ + public function getRequestBuilder(): RequestBuilder + { + return new RequestBuilder(); + } + + /** + * Get the response parser class for this query. + * + * @return ResponseParser + */ + public function getResponseParser(): ResponseParser + { + return new ResponseParser(); + } +} diff --git a/src/QueryType/ManagedResources/Query/Stopwords.php b/src/QueryType/ManagedResources/Query/Stopwords.php new file mode 100644 index 000000000..807b974ca --- /dev/null +++ b/src/QueryType/ManagedResources/Query/Stopwords.php @@ -0,0 +1,173 @@ + 'Solarium\QueryType\ManagedResources\Query\Stopwords\Command\Add', + self::COMMAND_DELETE => 'Solarium\QueryType\ManagedResources\Query\Stopwords\Command\Delete', + self::COMMAND_EXISTS => 'Solarium\QueryType\ManagedResources\Query\Stopwords\Command\Exists', + ]; + + /** + * Default options. + * + * @var array + */ + protected $options = [ + 'handler' => 'schema/analysis/stopwords/', + 'resultclass' => 'Solarium\QueryType\ManagedResources\Result\Stopwords\WordSet', + 'omitheader' => true, + ]; + + /** + * Get query type. + * + * @return string + */ + public function getType(): string + { + return Client::QUERY_MANAGED_STOPWORDS; + } + + /** + * Get the request builder class for this query. + * + * @return RequestBuilder + */ + public function getRequestBuilder(): RequestBuilder + { + return new RequestBuilder(); + } + + /** + * Get the response parser class for this query. + * + * @return ResponseParser + */ + public function getResponseParser(): ResponseParser + { + return new ResponseParser(); + } + + /** + * Get the name of the stopwords resource. + * + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * Set the name of the stopwords resource. + * + * @param string $name + */ + public function setName(string $name) + { + $this->name = $name; + } + + /** + * Create a command instance. + * + * @param string $type + * @param mixed $options + * + * @throws InvalidArgumentException + * + * @return AbstractCommand + */ + public function createCommand($type, $options = null): AbstractCommand + { + $type = strtolower($type); + + if (!isset($this->commandTypes[$type])) { + throw new InvalidArgumentException('Stopwords commandtype unknown: '.$type); + } + + $class = $this->commandTypes[$type]; + + return new $class($options); + } + + /** + * Get command for this stopwords query. + * + * @return AbstractCommand|null + */ + public function getCommand() + { + return $this->command; + } + + /** + * Set a command to the stopwords query. + * + * @param AbstractCommand $command + * + * @return self Provides fluent interface + */ + public function setCommand(AbstractCommand $command): self + { + $this->command = $command; + + return $this; + } + + /** + * Remove command. + * + * @return self Provides fluent interface + */ + public function removeCommand(): self + { + $this->command = null; + + return $this; + } +} diff --git a/src/QueryType/ManagedResources/Query/Stopwords/Command/AbstractCommand.php b/src/QueryType/ManagedResources/Query/Stopwords/Command/AbstractCommand.php new file mode 100644 index 000000000..42a6ff25c --- /dev/null +++ b/src/QueryType/ManagedResources/Query/Stopwords/Command/AbstractCommand.php @@ -0,0 +1,39 @@ +stopwords; + } + + /** + * Set stopwords. + * + * @param array $synonyms + */ + public function setStopwords(array $stopwords) + { + $this->stopwords = $stopwords; + } + + /** + * Returns the data to be send to Solr. + * + * @return string + */ + public function getRawData(): string + { + return json_encode($this->stopwords); + } + + /** + * Returns the term to be send to Solr. + * + * @return string + */ + public function getTerm(): string + { + return ''; + } +} diff --git a/src/QueryType/ManagedResources/Query/Stopwords/Command/Delete.php b/src/QueryType/ManagedResources/Query/Stopwords/Command/Delete.php new file mode 100644 index 000000000..adbb8672a --- /dev/null +++ b/src/QueryType/ManagedResources/Query/Stopwords/Command/Delete.php @@ -0,0 +1,66 @@ +term; + } + + /** + * Set the term to be deleted. + * + * @param string $term + */ + public function setTerm(string $term) + { + $this->term = $term; + } +} diff --git a/src/QueryType/ManagedResources/Query/Stopwords/Command/Exists.php b/src/QueryType/ManagedResources/Query/Stopwords/Command/Exists.php new file mode 100644 index 000000000..ba3d3fab9 --- /dev/null +++ b/src/QueryType/ManagedResources/Query/Stopwords/Command/Exists.php @@ -0,0 +1,66 @@ +term; + } + + /** + * Set the term to be checked if exists. + * + * @param string $term + */ + public function setTerm(string $term) + { + $this->term = $term; + } +} diff --git a/src/QueryType/ManagedResources/Query/Stopwords/Stopword.php b/src/QueryType/ManagedResources/Query/Stopwords/Stopword.php new file mode 100644 index 000000000..d74d3edec --- /dev/null +++ b/src/QueryType/ManagedResources/Query/Stopwords/Stopword.php @@ -0,0 +1,27 @@ +term; + } + + /** + * @param string $term + */ + public function setTerm(string $term) + { + $this->term = $term; + } +} diff --git a/src/QueryType/ManagedResources/Query/Synonyms.php b/src/QueryType/ManagedResources/Query/Synonyms.php new file mode 100644 index 000000000..6c2f0d0e2 --- /dev/null +++ b/src/QueryType/ManagedResources/Query/Synonyms.php @@ -0,0 +1,197 @@ + 'Solarium\QueryType\ManagedResources\Query\Synonyms\Command\Add', + self::COMMAND_DELETE => 'Solarium\QueryType\ManagedResources\Query\Synonyms\Command\Delete', + self::COMMAND_EXISTS => 'Solarium\QueryType\ManagedResources\Query\Synonyms\Command\Exists', + ]; + + /** + * Default options. + * + * @var array + */ + protected $options = [ + 'handler' => 'schema/analysis/synonyms/', + 'resultclass' => 'Solarium\QueryType\ManagedResources\Result\Synonyms\SynonymMappings', + 'omitheader' => true, + ]; + + /** + * Get query type. + * + * @return string + */ + public function getType() + { + return Client::QUERY_MANAGED_SYNONYMS; + } + + /** + * Get the request builder class for this query. + * + * @return RequestBuilder + */ + public function getRequestBuilder(): RequestBuilder + { + return new RequestBuilder(); + } + + /** + * Get the response parser class for this query. + * + * @return ResponseParser + */ + public function getResponseParser(): ResponseParser + { + return new ResponseParser(); + } + + /** + * Get the name of the synonym resource. + * + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * Set the name of the synonym resource. + * + * @param string $name + */ + public function setName(string $name) + { + $this->name = $name; + } + + /** + * Create a command instance. + * + * @param string $type + * @param mixed $options + * + * @throws InvalidArgumentException + * + * @return AbstractCommand + */ + public function createCommand($type, $options = null): AbstractCommand + { + $type = strtolower($type); + + if (!isset($this->commandTypes[$type])) { + throw new InvalidArgumentException('Synonyms commandtype unknown: '.$type); + } + + $class = $this->commandTypes[$type]; + + return new $class($options); + } + + /** + * Get command for this synonyms query. + * + * @return AbstractCommand|null + */ + public function getCommand() + { + return $this->command; + } + + /** + * Set a command for the synonyms query. + * + * @param AbstractCommand $command + * + * @return self Provides fluent interface + */ + public function setCommand(AbstractCommand $command): self + { + $this->command = $command; + + return $this; + } + + /** + * Remove command. + * + * @return self Provides fluent interface + */ + public function removeCommand(): self + { + $this->command = null; + + return $this; + } +} diff --git a/src/QueryType/ManagedResources/Query/Synonyms/Command/AbstractCommand.php b/src/QueryType/ManagedResources/Query/Synonyms/Command/AbstractCommand.php new file mode 100644 index 000000000..54d7e229e --- /dev/null +++ b/src/QueryType/ManagedResources/Query/Synonyms/Command/AbstractCommand.php @@ -0,0 +1,39 @@ +synonyms; + } + + /** + * Set synonyms. + * + * @param SynonymsData $synonyms + */ + public function setSynonyms(SynonymsData $synonyms) + { + $this->synonyms = $synonyms; + } + + /** + * Returns the raw data to be sent to Solr. + */ + public function getRawData(): string + { + if (null !== $this->getSynonyms() && !empty($this->getSynonyms()->getSynonyms())) { + if (0 != strlen(trim($this->getSynonyms()->getTerm()))) { + return json_encode([$this->getSynonyms()->getTerm() => $this->getSynonyms()->getSynonyms()]); + } + + return json_encode($this->getSynonyms()->getSynonyms()); + } + + return ''; + } + + /** + * Empty. + * + * @return string + */ + public function getTerm(): string + { + return ''; + } +} diff --git a/src/QueryType/ManagedResources/Query/Synonyms/Command/Delete.php b/src/QueryType/ManagedResources/Query/Synonyms/Command/Delete.php new file mode 100644 index 000000000..2b3c2ab59 --- /dev/null +++ b/src/QueryType/ManagedResources/Query/Synonyms/Command/Delete.php @@ -0,0 +1,66 @@ +term; + } + + /** + * Set the term to be deleted. + * + * @param string $term + */ + public function setTerm(string $term) + { + $this->term = $term; + } +} diff --git a/src/QueryType/ManagedResources/Query/Synonyms/Command/Exists.php b/src/QueryType/ManagedResources/Query/Synonyms/Command/Exists.php new file mode 100644 index 000000000..c1cb91e54 --- /dev/null +++ b/src/QueryType/ManagedResources/Query/Synonyms/Command/Exists.php @@ -0,0 +1,66 @@ +term; + } + + /** + * Set the term to be checked if exists. + * + * @param string $term + */ + public function setTerm(string $term) + { + $this->term = $term; + } +} diff --git a/src/QueryType/ManagedResources/Query/Synonyms/Synonyms.php b/src/QueryType/ManagedResources/Query/Synonyms/Synonyms.php new file mode 100644 index 000000000..6fd421e85 --- /dev/null +++ b/src/QueryType/ManagedResources/Query/Synonyms/Synonyms.php @@ -0,0 +1,55 @@ +term; + } + + /** + * @param string $term + */ + public function setTerm(string $term) + { + $this->term = $term; + } + + /** + * @return array + */ + public function getSynonyms(): array + { + return $this->synonyms; + } + + /** + * Sets the synonyms. To set a list of symmetric synonyms leave the term empty. + * + * @param array $synonyms + */ + public function setSynonyms(array $synonyms) + { + $this->synonyms = $synonyms; + } +} diff --git a/src/QueryType/ManagedResources/RequestBuilder/Resources.php b/src/QueryType/ManagedResources/RequestBuilder/Resources.php new file mode 100644 index 000000000..634bd8db3 --- /dev/null +++ b/src/QueryType/ManagedResources/RequestBuilder/Resources.php @@ -0,0 +1,9 @@ +getName())) { + throw new \Solarium\Exception\RuntimeException('Name of the stopwords resource is not set in the query.'); + } + + $request = parent::build($query); + $request->setHandler($query->getHandler().$query->getName()); + if (null !== $query->getCommand()) { + $request->addHeader('Content-Type: application/json; charset=utf-8'); + $this->buildCommand($request, $query->getCommand()); + } else { + // Lists all stopwords. + $request->setMethod(Request::METHOD_GET); + } + + return $request; + } + + /** + * @param Request $request + * @param AbstractCommand $command + */ + protected function buildCommand(Request $request, AbstractCommand $command) + { + $request->setMethod($command->getRequestMethod()); + + switch ($command->getType()) { + case StopwordsQuery::COMMAND_ADD: + $request->setRawData($command->getRawData()); + break; + case StopwordsQuery::COMMAND_DELETE: + $request->setHandler($request->getHandler().'/'.$command->getTerm()); + break; + case StopwordsQuery::COMMAND_EXISTS: + $request->setHandler($request->getHandler().'/'.$command->getTerm()); + break; + default: + throw new RuntimeException('Unsupported command type'); + break; + } + + $request->setMethod($command->getRequestMethod()); + } +} diff --git a/src/QueryType/ManagedResources/RequestBuilder/Synonyms.php b/src/QueryType/ManagedResources/RequestBuilder/Synonyms.php new file mode 100644 index 000000000..4f28e26e0 --- /dev/null +++ b/src/QueryType/ManagedResources/RequestBuilder/Synonyms.php @@ -0,0 +1,65 @@ +getName())) { + throw new \Solarium\Exception\RuntimeException('Name of the synonym resource is not set in the query.'); + } + + $request = parent::build($query); + $request->setHandler($query->getHandler().$query->getName()); + if (null !== $query->getCommand()) { + $request->addHeader('Content-Type: application/json; charset=utf-8'); + $this->buildCommand($request, $query->getCommand()); + } else { + // Lists all synonyms. + $request->setMethod(Request::METHOD_GET); + } + + return $request; + } + + /** + * @param Request $request + * @param AbstractCommand $command + */ + protected function buildCommand(Request $request, AbstractCommand $command) + { + $request->setMethod($command->getRequestMethod()); + + switch ($command->getType()) { + case SynonymsQuery::COMMAND_ADD: + $request->setRawData($command->getRawData()); + break; + case SynonymsQuery::COMMAND_DELETE: + $request->setHandler($request->getHandler().'/'.$command->getTerm()); + break; + case SynonymsQuery::COMMAND_EXISTS: + $request->setHandler($request->getHandler().'/'.$command->getTerm()); + break; + default: + throw new RuntimeException('Unsupported command type'); + break; + } + + $request->setMethod($command->getRequestMethod()); + } +} diff --git a/src/QueryType/ManagedResources/ResponseParser/Resources.php b/src/QueryType/ManagedResources/ResponseParser/Resources.php new file mode 100644 index 000000000..b80e44051 --- /dev/null +++ b/src/QueryType/ManagedResources/ResponseParser/Resources.php @@ -0,0 +1,33 @@ +getData(); + + $items = []; + + if (isset($data['managedResources']) && !empty($data['managedResources'])) { + foreach ($data['managedResources'] as $resource) { + $items[] = new Resource($resource); + } + } + + return $this->addHeaderInfo($data, ['items' => $items]); + } +} diff --git a/src/QueryType/ManagedResources/ResponseParser/Stopwords.php b/src/QueryType/ManagedResources/ResponseParser/Stopwords.php new file mode 100644 index 000000000..4a46c1a02 --- /dev/null +++ b/src/QueryType/ManagedResources/ResponseParser/Stopwords.php @@ -0,0 +1,38 @@ +getData(); + $wordSet = null; + if (isset($data['wordSet'])) { + $wordSet = $data['wordSet']; + } + + $parsed = []; + + if (null !== $wordSet && !empty($wordSet)) { + $parsed['items'] = $wordSet['managedList']; + $parsed['ignoreCase'] = $wordSet['initArgs']['ignoreCase']; + $parsed['initializedOn'] = $wordSet['initializedOn']; + } + + $this->addHeaderInfo($data, $parsed); + + return $parsed; + } +} diff --git a/src/QueryType/ManagedResources/ResponseParser/Synonyms.php b/src/QueryType/ManagedResources/ResponseParser/Synonyms.php new file mode 100644 index 000000000..0be9b0a3f --- /dev/null +++ b/src/QueryType/ManagedResources/ResponseParser/Synonyms.php @@ -0,0 +1,47 @@ +getData(); + $synonymMappings = null; + if (isset($data['synonymMappings'])) { + $synonymMappings = $data['synonymMappings']; + } + + $parsed = []; + $items = []; + + if (null !== $synonymMappings && !empty($synonymMappings)) { + foreach ($synonymMappings['managedMap'] as $term => $synonyms) { + $items[] = new \Solarium\QueryType\ManagedResources\Result\Synonyms\Synonyms($term, $synonyms); + } + + $parsed['items'] = $items; + $parsed['ignoreCase'] = $synonymMappings['initArgs']['ignoreCase']; + $parsed['initializedOn'] = $synonymMappings['initializedOn']; + } + + $this->addHeaderInfo($data, $parsed); + + return $parsed; + } +} diff --git a/src/QueryType/ManagedResources/Result/Resources/Resource.php b/src/QueryType/ManagedResources/Result/Resources/Resource.php new file mode 100644 index 000000000..09ec8bdfa --- /dev/null +++ b/src/QueryType/ManagedResources/Result/Resources/Resource.php @@ -0,0 +1,107 @@ +resourceId = $resource['resourceId']; + $this->numObservers = $resource['numObservers']; + $this->class = $resource['class']; + } + + /** + * @return string + */ + public function getResourceId(): string + { + return $this->resourceId; + } + + /** + * @param string $resourceId + */ + public function setResourceId(string $resourceId) + { + $this->resourceId = $resourceId; + } + + /** + * @return int + */ + public function getNumObservers(): int + { + return $this->numObservers; + } + + /** + * @param int $numObservers + */ + public function setNumObservers(int $numObservers) + { + $this->numObservers = $numObservers; + } + + /** + * @return string + */ + public function getClass(): string + { + return $this->class; + } + + /** + * @param string $class + */ + public function setClass(string $class) + { + $this->class = $class; + } + + /* + * Returns the type: 'stopwords', 'synonyms' or '' if unknown. + * + * @return string + */ + public function getType(): string + { + if (0 === strncmp($this->resourceId, '/schema/analysis/stopwords', strlen('/schema/analysis/stopwords'))) { + return self::TYPE_STOPWORDS; + } elseif (0 === strncmp($this->resourceId, '/schema/analysis/synonyms', strlen('/schema/analysis/synonyms'))) { + return self::TYPE_SYNONYMS; + } + + return ''; + } +} diff --git a/src/QueryType/ManagedResources/Result/Resources/ResourceList.php b/src/QueryType/ManagedResources/Result/Resources/ResourceList.php new file mode 100644 index 000000000..5cb3657ea --- /dev/null +++ b/src/QueryType/ManagedResources/Result/Resources/ResourceList.php @@ -0,0 +1,79 @@ +name; + } + + /** + * Get all items. + * + * @return resource[] + */ + public function getItems(): array + { + $this->parseResponse(); + return $this->items; + } + + /** + * IteratorAggregate implementation. + * + * @return \ArrayIterator + */ + public function getIterator(): \ArrayIterator + { + $this->parseResponse(); + return new \ArrayIterator($this->items); + } + + /** + * Countable implementation. + * + * @return int + */ + public function count(): int + { + $this->parseResponse(); + return \count($this->items); + } +} diff --git a/src/QueryType/ManagedResources/Result/Stopwords/WordSet.php b/src/QueryType/ManagedResources/Result/Stopwords/WordSet.php new file mode 100644 index 000000000..f875d16dd --- /dev/null +++ b/src/QueryType/ManagedResources/Result/Stopwords/WordSet.php @@ -0,0 +1,117 @@ +parseResponse(); + } + + /** + * Get type value. + * + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * Get all items. + * + * @return array + */ + public function getItems(): array + { + $this->parseResponse(); + return $this->items; + } + + /** + * IteratorAggregate implementation. + * + * @return \ArrayIterator + */ + public function getIterator(): \ArrayIterator + { + $this->parseResponse(); + return new \ArrayIterator($this->items); + } + + /** + * Countable implementation. + * + * @return int + */ + public function count(): int + { + $this->parseResponse(); + return count($this->items); + } + + /** + * @return bool + */ + public function isIgnoreCase(): bool + { + $this->parseResponse(); + return $this->ignoreCase; + } + + /** + * @return string + */ + public function getInitializedOn(): string + { + $this->parseResponse(); + return $this->initializedOn; + } +} diff --git a/src/QueryType/ManagedResources/Result/Synonyms/SynonymMappings.php b/src/QueryType/ManagedResources/Result/Synonyms/SynonymMappings.php new file mode 100644 index 000000000..047b0dd78 --- /dev/null +++ b/src/QueryType/ManagedResources/Result/Synonyms/SynonymMappings.php @@ -0,0 +1,132 @@ +name; + } + + /** + * Get all items. + * + * @return Synonyms[] + */ + public function getItems(): array + { + $this->parseResponse(); + return $this->items; + } + + /** + * IteratorAggregate implementation. + * + * @return \ArrayIterator + */ + public function getIterator(): \ArrayIterator + { + $this->parseResponse(); + return new \ArrayIterator($this->items); + } + + /** + * Countable implementation. + * + * @return int + */ + public function count(): int + { + $this->parseResponse(); + return \count($this->items); + } + + /** + * @return string + */ + public function getResourceId(): string + { + $this->parseResponse(); + return $this->resourceId; + } + + /** + * @return bool + */ + public function isIgnoreCase(): bool + { + $this->parseResponse(); + return $this->ignoreCase; + } + + /** + * @return string + */ + public function getInitializedOn(): string + { + $this->parseResponse(); + return $this->initializedOn; + } +} diff --git a/src/QueryType/ManagedResources/Result/Synonyms/Synonyms.php b/src/QueryType/ManagedResources/Result/Synonyms/Synonyms.php new file mode 100644 index 000000000..2b98d4341 --- /dev/null +++ b/src/QueryType/ManagedResources/Result/Synonyms/Synonyms.php @@ -0,0 +1,67 @@ +term = $term; + $this->synonyms = $synonyms; + } + + /** + * Set the term. + * + * @return string + */ + public function getTerm(): string + { + return $this->term; + } + + /** + * @param string $term + */ + public function setTerm(string $term) + { + $this->term = $term; + } + + /** + * @return array + */ + public function getSynonyms(): array + { + return $this->synonyms; + } + + /** + * Sets the synonyms. To set a list of symmetric synonyms leave the term empty. + * + * @param array $synonyms + */ + public function setSynonyms(array $synonyms) + { + $this->synonyms = $synonyms; + } +} diff --git a/tests/Integration/AbstractTechproductsTest.php b/tests/Integration/AbstractTechproductsTest.php index 4206d76a6..dbc4eb149 100644 --- a/tests/Integration/AbstractTechproductsTest.php +++ b/tests/Integration/AbstractTechproductsTest.php @@ -8,6 +8,13 @@ use Solarium\Component\Result\Terms\Result; use Solarium\Core\Client\ClientInterface; use Solarium\Exception\HttpException; +use Solarium\QueryType\ManagedResources\Query\Stopwords\Command\Add as AddStopwords; +use Solarium\QueryType\ManagedResources\Query\Stopwords\Command\Delete as DeleteStopwords; +use Solarium\QueryType\ManagedResources\Query\Stopwords\Command\Exists as ExistsStopwords; +use Solarium\QueryType\ManagedResources\Query\Synonyms\Command\Add as AddSynonyms; +use Solarium\QueryType\ManagedResources\Query\Synonyms\Command\Delete as DeleteSynonyms; +use Solarium\QueryType\ManagedResources\Query\Synonyms\Command\Exists as ExistsSynonyms; +use Solarium\QueryType\ManagedResources\Query\Synonyms\Synonyms; use Solarium\QueryType\Select\Query\Query as SelectQuery; use Solarium\QueryType\Select\Result\Document; @@ -647,6 +654,114 @@ public function testGetStatusFromAllCoreWhenNoCoreNameWasSet() $response = $this->client->coreAdmin($coreAdminQuery); $this->assertTrue($response->getWasSuccessful()); } + + public function testManagedStopwords() + { + $query = $this->client->createManagedStopwords(); + $query->setName('english'); + $term = 'managed_stopword_test'; + + // Add stopwords + $add = new AddStopwords(); + $add->setStopwords([$term]); + $query->setCommand($add); + $result = $this->client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check if single stopword exist + $exists = new ExistsStopwords(); + $exists->setTerm($term); + $query->setCommand($exists); + $result = $this->client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // We need to remove the current command in order to have no command. Having no command lists the items. + $query->removeCommand(); + + // List stopwords + $result = $this->client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + $items = $result->getItems(); + $this->assertContains($term, $items); + + // Delete stopword + $delete = new DeleteStopwords(); + $delete->setTerm($term); + $query->setCommand($delete); + $result = $this->client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check if stopword is gone + $this->expectException(HttpException::class); + $exists = new ExistsStopwords(); + $exists->setTerm($term); + $query->setCommand($exists); + $this->client->execute($query); + } + + public function testManagedSynonyms() + { + $query = $this->client->createManagedSynonyms(); + $query->setName('english'); + $term = 'managed_synonyms_test'; + + // Add synonyms + $add = new AddSynonyms(); + $synonyms = new Synonyms(); + $synonyms->setTerm($term); + $synonyms->setSynonyms(['managed_synonym', 'synonym_test']); + $add->setSynonyms($synonyms); + $query->setCommand($add); + $result = $this->client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check if single synonym exist + $exists = new ExistsSynonyms(); + $exists->setTerm($term); + $query->setCommand($exists); + $result = $this->client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + $this->assertSame(['managed_synonyms_test' => ['managed_synonym', 'synonym_test']], $result->getData()); + + // We need to remove the current command in order to have no command. Having no command lists the items. + $query->removeCommand(); + + // List synonyms + $result = $this->client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + $items = $result->getItems(); + $success = false; + foreach ($items as $item) { + if ('managed_synonyms_test' === $item->getTerm()) { + $success = true; + } + } + if (!$success) { + $this->fail('Couldn\'t find synonym.'); + } + + // Delete synonyms + $delete = new DeleteSynonyms(); + $delete->setTerm($term); + $query->setCommand($delete); + $result = $this->client->execute($query); + $this->assertEquals(200, $result->getResponse()->getStatusCode()); + + // Check if synonyms are gone + $this->expectException(HttpException::class); + $exists = new ExistsSynonyms(); + $exists->setTerm($term); + $query->setCommand($exists); + $this->client->execute($query); + } + + public function testManagedResources() + { + $query = $this->client->createManagedResources(); + $result = $this->client->execute($query); + $items = $result->getItems(); + $this->assertCount(2, $items); + } } class TestQuery extends SelectQuery diff --git a/tests/QueryType/ManagedResources/Query/ResourcesTest.php b/tests/QueryType/ManagedResources/Query/ResourcesTest.php new file mode 100644 index 000000000..df259772c --- /dev/null +++ b/tests/QueryType/ManagedResources/Query/ResourcesTest.php @@ -0,0 +1,21 @@ +query = new Query(); + } + + public function testQuery() + { + $this->assertEquals('resources', $this->query->getType()); + } +} diff --git a/tests/QueryType/ManagedResources/Query/StopwordsTest.php b/tests/QueryType/ManagedResources/Query/StopwordsTest.php new file mode 100644 index 000000000..c83ae7bb4 --- /dev/null +++ b/tests/QueryType/ManagedResources/Query/StopwordsTest.php @@ -0,0 +1,43 @@ +query = new Stopwords(); + } + + public function testQuery() + { + $this->assertEquals('stopwords', $this->query->getType()); + } + + public function testAddCommand() + { + $command = $this->query->createCommand(Stopwords::COMMAND_ADD); + $this->assertInstanceOf(Add::class, $command); + } + + public function testDeleteCommand() + { + $command = $this->query->createCommand(Stopwords::COMMAND_DELETE); + $this->assertInstanceOf(Delete::class, $command); + } + + public function testExistsCommand() + { + $command = $this->query->createCommand(Stopwords::COMMAND_EXISTS); + + $this->assertInstanceOf(Exists::class, $command); + } +} diff --git a/tests/QueryType/ManagedResources/Query/SynonymsTest.php b/tests/QueryType/ManagedResources/Query/SynonymsTest.php new file mode 100644 index 000000000..cae9ef8a1 --- /dev/null +++ b/tests/QueryType/ManagedResources/Query/SynonymsTest.php @@ -0,0 +1,49 @@ +query = new Synonyms(); + } + + public function testQuery() + { + $this->assertEquals('synonyms', $this->query->getType()); + } + + public function testAddCommand() + { + $command = $this->query->createCommand(Synonyms::COMMAND_ADD); + $this->assertInstanceOf(Add::class, $command); + $synonyms = new Synonyms\Synonyms(); + $term = 'mad'; + $synonyms->setTerm($term); + $synonyms->setSynonyms(['angry', 'upset']); + $command->setSynonyms($synonyms); + $this->assertEquals('mad', $command->getSynonyms()->getTerm()); + $this->assertEquals(['angry', 'upset'], $command->getSynonyms()->getSynonyms()); + } + + public function testDeleteCommand() + { + $command = $this->query->createCommand(Synonyms::COMMAND_DELETE); + $this->assertInstanceOf(Delete::class, $command); + } + + public function testExistsCommand() + { + $command = $this->query->createCommand(Synonyms::COMMAND_EXISTS); + $this->assertInstanceOf(Exists::class, $command); + } +} diff --git a/tests/QueryType/ManagedResources/QueryTest.php b/tests/QueryType/ManagedResources/QueryTest.php new file mode 100644 index 000000000..db5bf8db0 --- /dev/null +++ b/tests/QueryType/ManagedResources/QueryTest.php @@ -0,0 +1,38 @@ +query = new ResourcesQuery(); + } + + public function testGetType() + { + $this->assertSame(Client::QUERY_MANAGED_RESOURCES, $this->query->getType()); + } + + public function testGetResponseParser() + { + $this->assertInstanceOf( + 'Solarium\QueryType\ManagedResources\ResponseParser\Resources', + $this->query->getResponseParser() + ); + } + + public function testGetRequestBuilder() + { + $this->assertInstanceOf( + 'Solarium\QueryType\ManagedResources\RequestBuilder\Resources', + $this->query->getRequestBuilder() + ); + } +} diff --git a/tests/QueryType/ManagedResources/RequestBuilder/ResourcesTest.php b/tests/QueryType/ManagedResources/RequestBuilder/ResourcesTest.php new file mode 100644 index 000000000..6c52c5131 --- /dev/null +++ b/tests/QueryType/ManagedResources/RequestBuilder/ResourcesTest.php @@ -0,0 +1,44 @@ +query = new ResourcesQuery(); + $this->builder = new ResourcesRequestBuilder(); + } + + public function testBuild() + { + $handler = 'schema/managed'; + + $request = $this->builder->build($this->query); + + $this->assertEquals( + [ + 'wt' => 'json', + 'json.nl' => 'flat', + 'omitHeader' => 'true', + ], + $request->getParams() + ); + + $this->assertSame($handler, $request->getHandler()); + } +} diff --git a/tests/QueryType/ManagedResources/RequestBuilder/StopwordsTest.php b/tests/QueryType/ManagedResources/RequestBuilder/StopwordsTest.php new file mode 100644 index 000000000..ef902aa22 --- /dev/null +++ b/tests/QueryType/ManagedResources/RequestBuilder/StopwordsTest.php @@ -0,0 +1,102 @@ +query = new StopwordsQuery(); + $this->builder = new StopwordsRequestBuilder(); + } + + public function testBuild() + { + $handler = 'schema/analysis/stopwords/dutch'; + + $this->query->setName('dutch'); + $request = $this->builder->build($this->query); + + $this->assertEquals( + [ + 'wt' => 'json', + 'json.nl' => 'flat', + 'omitHeader' => 'true', + ], + $request->getParams() + ); + + $this->assertSame($handler, $request->getHandler()); + } + + public function testNoName() + { + $this->expectException(\Solarium\Exception\RuntimeException::class); + $request = $this->builder->build($this->query); + } + + public function testQuery() + { + $this->query->setName('dutch'); + $request = $this->builder->build($this->query); + $this->assertSame(Request::METHOD_GET, $request->getMethod()); + } + + public function testAdd() + { + $stopwords = ['de']; + $command = new AddCommand(); + $command->setStopwords($stopwords); + $this->query->setName('dutch'); + $this->query->setCommand($command); + $request = $this->builder->build($this->query); + $this->assertSame(Request::METHOD_PUT, $request->getMethod()); + $this->assertEquals($stopwords, $command->getStopwords()); + $this->assertEquals('', $command->getTerm()); + $this->assertEquals('["de"]', $command->getRawData()); + } + + public function testDelete() + { + $term = 'de'; + $command = new DeleteCommand(); + $command->setTerm($term); + $this->query->setName('dutch'); + $this->query->setCommand($command); + $request = $this->builder->build($this->query); + $this->assertSame(Request::METHOD_DELETE, $request->getMethod()); + $this->assertEquals($term, $command->getTerm()); + $this->assertEquals('', $command->getRawData()); + } + + public function testExists() + { + $term = 'de'; + $command = new ExistsCommand(); + $command->setTerm('de'); + $this->query->setName('dutch'); + $this->query->setCommand($command); + $request = $this->builder->build($this->query); + $this->assertSame(Request::METHOD_GET, $request->getMethod()); + $this->assertEquals($term, $command->getTerm()); + $this->assertEquals('', $command->getRawData()); + } +} diff --git a/tests/QueryType/ManagedResources/RequestBuilder/SynonymsTest.php b/tests/QueryType/ManagedResources/RequestBuilder/SynonymsTest.php new file mode 100644 index 000000000..c90edb2fd --- /dev/null +++ b/tests/QueryType/ManagedResources/RequestBuilder/SynonymsTest.php @@ -0,0 +1,114 @@ +query = new SynonymsQuery(); + $this->builder = new SynonymsRequestBuilder(); + $this->client = new Client(); + } + + public function testBuild() + { + $handler = 'schema/analysis/synonyms/dutch'; + $this->query->setName('dutch'); + $request = $this->builder->build($this->query); + + $this->assertEquals( + [ + 'wt' => 'json', + 'json.nl' => 'flat', + 'omitHeader' => 'true', + ], + $request->getParams() + ); + + $this->assertSame($handler, $request->getHandler()); + } + + public function testNoName() + { + $this->expectException(\Solarium\Exception\RuntimeException::class); + $this->builder->build($this->query); + } + + public function testAdd() + { + $synonyms = new SynonymsQuery\Synonyms(); + $synonyms->setTerm('mad'); + $synonyms->setSynonyms(['angry', 'upset']); + $command = new AddCommand(); + $command->setSynonyms($synonyms); + $this->query->setName('dutch'); + $this->query->setCommand($command); + $request = $this->builder->build($this->query); + $this->assertSame(Request::METHOD_PUT, $request->getMethod()); + $this->assertEquals('{"mad":["angry","upset"]}', $request->getRawData()); + } + + public function testAddSymmytrical() + { + $synonyms = new SynonymsQuery\Synonyms(); + $synonyms->setSynonyms(['funny', 'entertaining', 'whimsical', 'jocular']); + $command = new AddCommand(); + $command->setSynonyms($synonyms); + $this->query->setName('dutch'); + $this->query->setCommand($command); + $request = $this->builder->build($this->query); + $this->assertSame(Request::METHOD_PUT, $request->getMethod()); + $this->assertEquals('["funny","entertaining","whimsical","jocular"]', $request->getRawData()); + } + + public function testDelete() + { + $term = 'mad'; + $command = new DeleteCommand(); + $command->setTerm($term); + $this->query->setName('dutch'); + $this->query->setCommand($command); + $request = $this->builder->build($this->query); + $this->assertSame(Request::METHOD_DELETE, $request->getMethod()); + $this->assertEquals($term, $command->getTerm()); + $this->assertEquals('', $command->getRawData()); + } + + public function testExists() + { + $term = 'mad'; + $command = new ExistsCommand(); + $command->setTerm($term); + $this->query->setName('dutch'); + $this->query->setCommand($command); + $request = $this->builder->build($this->query); + $this->assertSame(Request::METHOD_GET, $request->getMethod()); + $this->assertEquals($term, $command->getTerm()); + $this->assertEquals('', $command->getRawData()); + } +} diff --git a/tests/QueryType/ManagedResources/ResponseParser/ResourcesTest.php b/tests/QueryType/ManagedResources/ResponseParser/ResourcesTest.php new file mode 100644 index 000000000..b443b0031 --- /dev/null +++ b/tests/QueryType/ManagedResources/ResponseParser/ResourcesTest.php @@ -0,0 +1,51 @@ + [ + [ + 'resourceId' => '/schema/analysis/stopwords/dutch', + 'numObservers' => '1', + 'class' => 'org.apache.solr.rest.schema.analysis.ManagedWordSetResource', + ], + [ + 'resourceId' => '/schema/analysis/synonyms/dutch', + 'numObservers' => '1', + 'class' => 'org.apache.solr.rest.schema.analysis.ManagedSynonymFilterFactory$SynonymManager', + ], + ], + 'responseHeader' => [ + 'status' => 1, + 'QTime' => 5, + ], + ]; + + $query = new Resources(); + $resultStub = $this->createMock(ResourceList::class); + $resultStub->expects($this->once()) + ->method('getData') + ->will($this->returnValue($data)); + + $parser = new ResourcesResponseParser(); + + $result = $parser->parse($resultStub); + + $this->assertSame(count($data['managedResources']), count($result['items'])); + $this->assertSame('/schema/analysis/stopwords/dutch', $result['items'][0]->getResourceId()); + $this->assertSame(1, $result['items'][0]->getNumObservers()); + $this->assertSame('org.apache.solr.rest.schema.analysis.ManagedWordSetResource', $result['items'][0]->getClass()); + $this->assertSame('/schema/analysis/synonyms/dutch', $result['items'][1]->getResourceId()); + $this->assertSame(1, $result['items'][1]->getNumObservers()); + $this->assertSame('org.apache.solr.rest.schema.analysis.ManagedSynonymFilterFactory$SynonymManager', $result['items'][1]->getClass()); + } +} diff --git a/tests/QueryType/ManagedResources/ResponseParser/StopwordsTest.php b/tests/QueryType/ManagedResources/ResponseParser/StopwordsTest.php new file mode 100644 index 000000000..542c9e59e --- /dev/null +++ b/tests/QueryType/ManagedResources/ResponseParser/StopwordsTest.php @@ -0,0 +1,28 @@ +parse($result); + + $this->assertSame('2014-03-28T20:53:53.058Z', $parsed['initializedOn']); + $this->assertTrue($parsed['ignoreCase']); + $this->assertEquals([0 => 'a', 1 => 'an', 2 => 'and', 3 => 'are'], $parsed['items']); + } +} diff --git a/tests/QueryType/ManagedResources/ResponseParser/SynonymsTest.php b/tests/QueryType/ManagedResources/ResponseParser/SynonymsTest.php new file mode 100644 index 000000000..fc7bcfa78 --- /dev/null +++ b/tests/QueryType/ManagedResources/ResponseParser/SynonymsTest.php @@ -0,0 +1,50 @@ +parse($result); + + $this->assertSame('2014-12-16T22:44:05.33Z', $parsed['initializedOn']); + $this->assertTrue($parsed['ignoreCase']); + + $synonyms = + [ + 0 => new Synonyms('GB', + [ + 0 => 'GiB', + 1 => 'Gigabyte', + ] + ), + 1 => new Synonyms('TV', + [ + 0 => 'Television', + ] + ), + 2 => new Synonyms('happy', + [ + 0 => 'glad', + 1 => 'joyful', + ] + ), + ]; + + $this->assertEquals($synonyms, $parsed['items']); + } +}