Skip to content

Commit b0f6a64

Browse files
Solr 10 support (#1176)
1 parent fbaa327 commit b0f6a64

File tree

17 files changed

+452
-143
lines changed

17 files changed

+452
-143
lines changed

.github/workflows/run-tests.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
strategy:
1616
matrix:
1717
php: [8.1, 8.2, 8.3, 8.4, 8.5]
18-
solr: [7, 8, 9]
18+
solr: [7, 8, 9, 10]
1919
mode: [cloud, server]
2020

2121
name: PHP ${{ matrix.php }}, Solr ${{ matrix.solr }} ${{ matrix.mode }}
@@ -59,6 +59,14 @@ jobs:
5959
ref: branch_9_10
6060
path: lucene-solr
6161

62+
- name: Checkout solr 10.0
63+
if: matrix.solr == 10
64+
uses: actions/checkout@v4
65+
with:
66+
repository: apache/solr
67+
ref: branch_10_0
68+
path: lucene-solr
69+
6270
- name: Start Solr ${{ matrix.solr }} in ${{ matrix.mode }} mode
6371
run: |
6472
chmod -R a+w lucene-solr

CHANGELOG.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [7.0.0]
88
### Added
9+
- Solr 10 support
910
- PHP 8.5 support
1011
- Solarium\QueryType\Extract\Query::setStreamType()
1112

@@ -15,13 +16,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1516
- Solarium\Plugin\MinimumScoreFilter\Document::__call() unpacks the $arguments array when forwarding a method call to the original document
1617

1718
### Changed
18-
- Added `void` return type to `Solarium\Core\Plugin\PluginInterface::initPlugin()` method signature
19-
- Added `void` return type to `Solarium\Core\Plugin\PluginInterface::deinitPlugin()` method signature
20-
- Added `void` return type to `Solarium\Core\Plugin\AbstractPlugin::initPluginType()` method signature
21-
- Changed return type of some Facets methods from `self`to `static`
22-
- Replaced class property type hints with type declarations
23-
- Added union type declarations to method signatures
24-
- Solarium\Core\Query\Helper::formatDate() throws a `TypeError` instead of returning `false` if called with an incompatibly typed parameter
19+
- Added `void` return type to `Solarium\Core\Plugin\PluginInterface::initPlugin()` method signature
20+
- Added `void` return type to `Solarium\Core\Plugin\PluginInterface::deinitPlugin()` method signature
21+
- Added `void` return type to `Solarium\Core\Plugin\AbstractPlugin::initPluginType()` method signature
22+
- Changed return type of some Facets methods from `self` to `static`
23+
- Replaced class property type hints with type declarations
24+
- Added union type declarations to method signatures
25+
- Solarium\Core\Query\Helper::formatDate() throws a `TypeError` instead of returning `false` if called with an incompatibly typed parameter
26+
- Managed resources queries no longer work around SOLR-6853 by default. Set the 'useDoubleEncoding' option to `true` if this bug affects you.
2527

2628
### Removed
2729
- Solarium\Component\Result\Stats\FacetValue::getFacets(), always returned `null`

docs/getting-started.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ do have one it must be contravariant.
112112
Code that calls a method with parameters of an incompatible type will result in a `TypeError` where
113113
they were previously coerced into a compatible type by PHP's type juggling.
114114

115+
Solarium 7 no longer works around [SOLR-6853](https://issues.apache.org/jira/browse/SOLR-6853) for
116+
managed resources queries by default. The workaround is no longer necessary for Solr 10, but also
117+
not forward compatible with this version. If this still affects you, set the 'useDoubleEncoding'
118+
option to `true` on `ManagedResources\Query\Stopwords` or `ManagedResources\Query\Synonyms`.
119+
115120
### Pitfall when upgrading to 6.3.6
116121

117122
Using a config object is no longer supported. You have to convert it to an array before passing

docs/queries/managedresources-query/managed-stopwords.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,24 @@ htmlFooter();
245245

246246
```
247247

248+
A note on percent-encoding reserved characters
249+
----------------------------------------------
250+
251+
If the name of a stopword list or a stopword itself contains characters that are not
252+
[unreserved characters as defined by RFC 3986](https://www.rfc-editor.org/rfc/rfc3986#section-2.3),
253+
they must be percent-encoded when appearing as part of a URL. Solarium handles this for you.
254+
255+
However, if you're using a Solr version prior to Solr 10 and list names or stopwords
256+
that contain [reserved characters](https://datatracker.ietf.org/doc/html/rfc3986#section-2.2),
257+
you will be affected by [SOLR-6853](https://issues.apache.org/jira/browse/SOLR-6853). You can
258+
instruct Solarium to double up on the percent-encoding as a workaround.
259+
260+
```php
261+
$query = $client->createManagedStopwords(['useDoubleEncoding' => true]);
262+
```
263+
264+
Keep in mind that Solr may not be able to handle some of these reserved characters regardless.
265+
248266
A note on `HEAD` requests
249267
-------------------------
250268

docs/queries/managedresources-query/managed-synonyms.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,24 @@ htmlFooter();
305305

306306
```
307307

308+
A note on percent-encoding reserved characters
309+
----------------------------------------------
310+
311+
If the name of a synonym map or a synonym itself contains characters that are not
312+
[unreserved characters as defined by RFC 3986](https://www.rfc-editor.org/rfc/rfc3986#section-2.3),
313+
they must be percent-encoded when appearing as part of a URL. Solarium handles this for you.
314+
315+
However, if you're using a Solr version prior to Solr 10 and map names or synonyms
316+
that contain [reserved characters](https://datatracker.ietf.org/doc/html/rfc3986#section-2.2),
317+
you will be affected by [SOLR-6853](https://issues.apache.org/jira/browse/SOLR-6853). You can
318+
instruct Solarium to double up on the percent-encoding as a workaround.
319+
320+
```php
321+
$query = $client->createManagedSynonyms(['useDoubleEncoding' => true]);
322+
```
323+
324+
Keep in mind that Solr may not be able to handle some of these reserved characters regardless.
325+
308326
A note on `HEAD` requests
309327
-------------------------
310328

examples/execute_all.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@
6262
$response = $client->coreAdmin($coreAdminQuery);
6363
}
6464

65-
// @todo Figure out why this fails on Solr 9.
66-
if (9 !== $solrVersion) {
65+
// @todo Figure out why this fails starting with Solr 9.
66+
if (9 > $solrVersion) {
6767
// check if /mlt handler exists (it will in the github worklow, but not when running this script on its own)
6868
$query = $client->createApi([
6969
'version' => Request::API_V1,
@@ -90,6 +90,23 @@
9090
}
9191
}
9292

93+
// Solr 10 no longer comes with LocalTikaExtractionBackend, the github workflow runs a remote Tika Server instead
94+
if (10 <= $solrVersion) {
95+
$query = $client->createApi([
96+
'version' => Request::API_V1,
97+
'handler' => $collection_or_core_name.'/config',
98+
'method' => Request::METHOD_POST,
99+
'rawdata' => json_encode([
100+
'update-requesthandler' => [
101+
'name' => '/update/extract',
102+
'class' => 'solr.extraction.ExtractingRequestHandler',
103+
'tikaserver.url' => 'http://tika:9998',
104+
],
105+
]),
106+
]);
107+
$client->execute($query);
108+
}
109+
93110
// check if attr_* dynamic field definition exists (it was removed from the techproducts configset in Solr 9.1)
94111
try {
95112
$query = $client->createApi([
@@ -172,7 +189,7 @@
172189
// examples that can't be run against this Solr version
173190
$skipForSolrVersion = [];
174191

175-
if (9 === $solrVersion) {
192+
if (9 <= $solrVersion) {
176193
$skipForSolrVersion[] = '2.3.1-mlt-query.php';
177194
$skipForSolrVersion[] = '2.3.2-mlt-stream.php';
178195
}

src/QueryType/ManagedResources/Query/AbstractQuery.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,4 +230,32 @@ public function removeCommand(): self
230230
* @return InitArgsInterface
231231
*/
232232
abstract public function createInitArgs(?array $initArgs = null): InitArgsInterface;
233+
234+
/**
235+
* Percent-encode names and terms twice as a workaround for SOLR-6853?
236+
*
237+
* @return bool
238+
*/
239+
public function getUseDoubleEncoding(): bool
240+
{
241+
return $this->getOption('useDoubleEncoding') ?? false;
242+
}
243+
244+
/**
245+
* Percent-encode names and terms twice as a workaround for SOLR-6853?
246+
*
247+
* Solr versions prior to 10 required reserved characters to be doubly
248+
* percent-encoded. Set this to true if your Solr version is affected by
249+
* {@link https://issues.apache.org/jira/browse/SOLR-6853 SOLR-6853}.
250+
*
251+
* @param bool $useDoubleEncoding
252+
*
253+
* @return self Provides fluent interface
254+
*/
255+
public function setUseDoubleEncoding(bool $useDoubleEncoding): self
256+
{
257+
$this->setOption('useDoubleEncoding', $useDoubleEncoding);
258+
259+
return $this;
260+
}
233261
}

src/QueryType/ManagedResources/RequestBuilder/Resource.php

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
use Solarium\Core\Query\AbstractRequestBuilder;
1414
use Solarium\Core\Query\QueryInterface;
1515
use Solarium\Exception\RuntimeException;
16-
use Solarium\QueryType\ManagedResources\Query\AbstractCommand;
1716
use Solarium\QueryType\ManagedResources\Query\AbstractQuery as BaseQuery;
1817

1918
/**
@@ -36,68 +35,92 @@ public function build(QueryInterface|BaseQuery $query): Request
3635
throw new RuntimeException('Name of the resource is not set in the query.');
3736
}
3837

38+
$name = rawurlencode($query->getName());
39+
if ($query->getUseDoubleEncoding()) {
40+
$name = rawurlencode($name);
41+
}
42+
3943
$request = parent::build($query);
40-
// reserved characters in a REST resource name need to be encoded twice to make it through the servlet (SOLR-6853)
41-
$request->setHandler($query->getHandler().rawurlencode(rawurlencode($query->getName())));
44+
$request->setHandler($query->getHandler().$name);
45+
4246
if (null !== $query->getCommand()) {
4347
$request->setContentType(Request::CONTENT_TYPE_APPLICATION_JSON);
44-
$this->buildCommand($request, $query->getCommand());
48+
$this->buildCommand($query, $request);
4549
} else {
4650
// Lists one or all items.
4751
$request->setMethod(Request::METHOD_GET);
4852

4953
if (null !== $term = $query->getTerm()) {
50-
// reserved characters in a REST resource name need to be encoded twice to make it through the servlet (SOLR-6853)
51-
$request->setHandler($request->getHandler().'/'.rawurlencode(rawurlencode($term)));
54+
$term = rawurlencode($term);
55+
if ($query->getUseDoubleEncoding()) {
56+
$term = rawurlencode($term);
57+
}
58+
59+
$request->setHandler($request->getHandler().'/'.$term);
5260
}
5361
}
5462

5563
return $request;
5664
}
5765

5866
/**
59-
* @param Request $request
60-
* @param AbstractCommand $command
67+
* @param QueryInterface|BaseQuery $query
68+
* @param Request $request
6169
*
6270
* @throws RuntimeException
6371
*
6472
* @return self Provides fluent interface
6573
*/
66-
protected function buildCommand(Request $request, AbstractCommand $command): self
74+
protected function buildCommand(QueryInterface|BaseQuery $query, Request $request): self
6775
{
76+
$command = $query->getCommand();
77+
6878
$request->setMethod($command->getRequestMethod());
6979

7080
switch ($command->getType()) {
7181
case BaseQuery::COMMAND_ADD:
7282
if (null === $rawData = $command->getRawData()) {
7383
throw new RuntimeException('Missing data for ADD command.');
7484
}
85+
7586
$request->setRawData($rawData);
7687
break;
7788
case BaseQuery::COMMAND_CONFIG:
7889
if (null === $rawData = $command->getRawData()) {
7990
throw new RuntimeException('Missing initArgs for CONFIG command.');
8091
}
92+
8193
$request->setRawData($rawData);
8294
break;
8395
case BaseQuery::COMMAND_CREATE:
8496
if (null === $rawData = $command->getRawData()) {
8597
throw new RuntimeException('Missing class for CREATE command.');
8698
}
99+
87100
$request->setRawData($rawData);
88101
break;
89102
case BaseQuery::COMMAND_DELETE:
90103
if (null === $term = $command->getTerm()) {
91104
throw new RuntimeException('Missing term for DELETE command.');
92105
}
93-
// reserved characters in a REST resource name need to be encoded twice to make it through the servlet (SOLR-6853)
94-
$request->setHandler($request->getHandler().'/'.rawurlencode(rawurlencode($command->getTerm())));
106+
107+
$term = rawurlencode($term);
108+
if ($query->getUseDoubleEncoding()) {
109+
$term = rawurlencode($term);
110+
}
111+
112+
$request->setHandler($request->getHandler().'/'.$term);
95113
break;
96114
case BaseQuery::COMMAND_EXISTS:
97115
if (null !== $term = $command->getTerm()) {
98-
// reserved characters in a REST resource name need to be encoded twice to make it through the servlet (SOLR-6853)
99-
$request->setHandler($request->getHandler().'/'.rawurlencode(rawurlencode($command->getTerm())));
116+
$term = rawurlencode($term);
117+
if ($query->getUseDoubleEncoding()) {
118+
$term = rawurlencode($term);
119+
}
120+
121+
$request->setHandler($request->getHandler().'/'.$term);
100122
}
123+
101124
break;
102125
case BaseQuery::COMMAND_REMOVE:
103126
break;

0 commit comments

Comments
 (0)