Skip to content

Commit 28237c7

Browse files
authored
Merge pull request #107 from Flowpack/bugfix/cleanup-prefix-setting
BUGFIX: Setting injection doesn't cause errors
2 parents 02fc1ae + 1070e1b commit 28237c7

File tree

5 files changed

+198
-18
lines changed

5 files changed

+198
-18
lines changed

Classes/Domain/Model/Index.php

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ class Index
6464
'index.warmer.enabled',
6565
];
6666

67+
static protected $allowedIndexCreateKeys = [
68+
'settings',
69+
'aliases',
70+
'mappings'
71+
];
72+
6773
/**
6874
* @var DynamicIndexSettingService
6975
* @Flow\Inject
@@ -88,6 +94,7 @@ class Index
8894
protected $client;
8995

9096
/**
97+
* These are the Flow "Settings" aka Configuration, NOT the index settings
9198
* @var array
9299
*/
93100
protected $settings;
@@ -114,21 +121,14 @@ public function __construct(string $name, Client $client = null)
114121
}
115122

116123
/**
117-
* Inject the settings
124+
* Inject the framework settings
118125
*
119126
* @param array $settings
120127
* @return void
121128
*/
122129
public function injectSettings(array $settings): void
123130
{
124131
$this->settings = $settings;
125-
$indexSettings = $this->getSettings();
126-
if (!isset($indexSettings['prefix']) || empty($indexSettings['prefix'])) {
127-
return;
128-
}
129-
// This is obviously a side effect but can only be done after injecting settings
130-
// and it needs to be done as early as possible
131-
$this->name = $settings['prefix'] . '-' . $this->name;
132132
}
133133

134134
/**
@@ -141,7 +141,7 @@ public function findType(string $typeName): AbstractType
141141
}
142142

143143
/**
144-
* @param array <AbstractType> $types
144+
* @param array<AbstractType> $types
145145
* @return TypeGroup
146146
*/
147147
public function findTypeGroup(array $types): TypeGroup
@@ -173,11 +173,11 @@ public function exists(): bool
173173
public function request(string $method, string $path = null, array $arguments = [], $content = null, bool $prefixIndex = true): Response
174174
{
175175
if ($this->client === null) {
176-
throw new ElasticSearchException('The client of the index "' . $this->name . '" is not set, hence no requests can be done.', 1566313883);
176+
throw new ElasticSearchException('The client of the index "' . $this->prefixName() . '" is not set, hence no requests can be done.', 1566313883);
177177
}
178178
$path = ltrim($path ? trim($path) : '', '/');
179179
if ($prefixIndex === true) {
180-
$path = '/' . $this->name . '/' . $path;
180+
$path = '/' . $this->prefixName() . '/' . $path;
181181
} else {
182182
$path = '/' . ltrim($path, '/');
183183
}
@@ -191,22 +191,24 @@ public function request(string $method, string $path = null, array $arguments =
191191
*/
192192
public function create(): void
193193
{
194-
$this->request('PUT', null, [], json_encode($this->getSettings()));
194+
$indexConfiguration = $this->getConfiguration() ?? [];
195+
$indexCreateObject = array_filter($indexConfiguration, static fn($key) => in_array($key, self::$allowedIndexCreateKeys, true), ARRAY_FILTER_USE_KEY);
196+
$this->request('PUT', null, [], $this->encodeRequestBody($indexCreateObject));
195197
}
196198

197199
/**
198200
* @return array|null
199201
*/
200-
protected function getSettings(): ?array
202+
protected function getConfiguration(): ?array
201203
{
202204
if ($this->client instanceof Client) {
203205
$path = 'indexes.' . $this->client->getBundle() . '.' . $this->settingsKey;
204206
} else {
205207
$path = 'indexes.default' . '.' . $this->settingsKey;
206208
}
207209

208-
$settings = Arrays::getValueByPath($this->settings, $path);
209-
return $settings !== null ? $this->dynamicIndexSettingService->process($settings, $path, $this->getName()) : $settings;
210+
$cconfiguration = Arrays::getValueByPath($this->settings, $path);
211+
return $cconfiguration !== null ? $this->dynamicIndexSettingService->process($cconfiguration, $path, $this->name) : $cconfiguration;
210212
}
211213

212214
/**
@@ -215,15 +217,18 @@ protected function getSettings(): ?array
215217
*/
216218
public function updateSettings(): void
217219
{
218-
$settings = $this->getSettings();
220+
// we only ever need the settings path from all the settings.
221+
$settings = $this->getConfiguration()['settings'] ?? [];
219222
$updatableSettings = [];
220223
foreach (static::$updatableSettings as $settingPath) {
221224
$setting = Arrays::getValueByPath($settings, $settingPath);
222225
if ($setting !== null) {
223226
$updatableSettings = Arrays::setValueByPath($updatableSettings, $settingPath, $setting);
224227
}
225228
}
226-
$this->request('PUT', '/_settings', [], json_encode($updatableSettings));
229+
if ($updatableSettings !== []) {
230+
$this->request('PUT', '/_settings', [], $this->encodeRequestBody($updatableSettings));
231+
}
227232
}
228233

229234
/**
@@ -252,6 +257,11 @@ public function refresh(): Response
252257
* @return string
253258
*/
254259
public function getName(): string
260+
{
261+
return $this->prefixName();
262+
}
263+
264+
public function getOriginalName(): string
255265
{
256266
return $this->name;
257267
}
@@ -273,4 +283,28 @@ public function setSettingsKey(string $settingsKey): void
273283
{
274284
$this->settingsKey = $settingsKey;
275285
}
286+
287+
/**
288+
* Prepends configured preset to the base index name
289+
*
290+
* @return string
291+
*/
292+
private function prefixName(): string
293+
{
294+
$indexConfiguration = $this->getConfiguration();
295+
if (!isset($indexConfiguration['prefix']) || empty($indexConfiguration['prefix'])) {
296+
return $this->name;
297+
}
298+
299+
return $indexConfiguration['prefix'] . '-' . $this->name;
300+
}
301+
302+
private function encodeRequestBody(array $content): string
303+
{
304+
if ($content === []) {
305+
return '';
306+
}
307+
308+
return json_encode($content);
309+
}
276310
}

Classes/Service/DynamicIndexSettingService.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
/**
2222
* Transform indices settings dynamically
23+
* FIXME: This should be called DynamicIndexConfigurationService, the "settings" represent more than what elastic index "settings" are.
2324
*
2425
* @Flow\Scope("singleton")
2526
*/
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
Flowpack:
2+
ElasticSearch:
3+
clients:
4+
FunctionalTests:
5+
-
6+
host: localhost
7+
port: 9200
8+
scheme: 'http'
9+
username: ''
10+
password: ''
11+
realtimeIndexing:
12+
# we also use this setting for the object indexer client bundle
13+
client: FunctionalTests
14+
15+
indexes:
16+
FunctionalTests: # Configuration bundle name
17+
index_with_prefix: # The index prefix name, must be the same as in the Neos.ContentRepository.Search.elasticSearch.indexName setting
18+
prefix: 'prefix'
19+
settings:
20+
index:
21+
number_of_replicas: 1
22+
soft_deletes:
23+
enabled: true
24+
index_without_prefix:
25+
settings:
26+
index:
27+
number_of_replicas: 2
28+
soft_deletes:
29+
enabled: true

Tests/Functional/Domain/AbstractTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ final public function setUp(): void
4040
parent::setUp();
4141

4242
$this->clientFactory = $this->objectManager->get(ClientFactory::class);
43-
$client = $this->clientFactory->create();
43+
$client = $this->clientFactory->create("FunctionalTests");
4444
$this->testingIndex = $client->findIndex('flow_elasticsearch_functionaltests');
4545

4646
if ($this->testingIndex->exists()) {
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
namespace Flowpack\ElasticSearch\Tests\Functional\Domain;
3+
4+
/*
5+
* This file is part of the Flowpack.ElasticSearch package.
6+
*
7+
* (c) Contributors of the Flowpack Team - flowpack.org
8+
*
9+
* This package is Open Source Software. For the full copyright and license
10+
* information, please view the LICENSE file which was distributed with this
11+
* source code.
12+
*/
13+
14+
use Flowpack\ElasticSearch\Domain\Model\Client;
15+
use Flowpack\ElasticSearch\Transfer\Response;
16+
use Neos\Flow\Tests\FunctionalTestCase;
17+
use Flowpack\ElasticSearch\Domain\Model\Index;
18+
19+
class IndexTest extends FunctionalTestCase
20+
{
21+
/**
22+
* @test
23+
*/
24+
public function indexWithoutPrefix()
25+
{
26+
$clientMock = $this->createMock(Client::class);
27+
$clientMock->method('getBundle')
28+
->willReturn('FunctionalTests');
29+
30+
$clientMock->expects($this->exactly(2))->method('request')
31+
->withConsecutive(
32+
[
33+
'PUT',
34+
'/index_without_prefix/',
35+
[],
36+
json_encode([
37+
'settings' => [
38+
'index' => [
39+
'number_of_replicas' => 2,
40+
'soft_deletes' => [
41+
'enabled' => true
42+
]
43+
]
44+
]
45+
], JSON_THROW_ON_ERROR)
46+
],
47+
// updateSettings should correctly filter soft_deletes as it's not in the allow list
48+
[
49+
'PUT',
50+
'/index_without_prefix/_settings',
51+
[],
52+
json_encode([
53+
'index' => [
54+
'number_of_replicas' => 2
55+
]
56+
], JSON_THROW_ON_ERROR)
57+
]
58+
)
59+
->willReturn($this->createStub(Response::class));
60+
61+
$testObject = new Index('index_without_prefix', $clientMock);
62+
$testObject->create();
63+
$testObject->updateSettings();
64+
65+
static::assertSame('index_without_prefix', $testObject->getOriginalName());
66+
static::assertSame('index_without_prefix', $testObject->getName());
67+
}
68+
69+
/**
70+
* @test
71+
*/
72+
public function indexWithPrefix()
73+
{
74+
$clientMock = $this->createMock(Client::class);
75+
$clientMock->method('getBundle')
76+
->willReturn('FunctionalTests');
77+
78+
$clientMock->expects($this->exactly(2))->method('request')
79+
->withConsecutive(
80+
[
81+
'PUT',
82+
'/prefix-index_with_prefix/',
83+
[],
84+
json_encode([
85+
'settings' => [
86+
'index' => [
87+
'number_of_replicas' => 1,
88+
'soft_deletes' => [
89+
'enabled' => true
90+
]
91+
]
92+
]
93+
], JSON_THROW_ON_ERROR)
94+
],
95+
// updateSettings should correctly filter soft_deletes as it's not in the allow list
96+
[
97+
'PUT',
98+
'/prefix-index_with_prefix/_settings',
99+
[],
100+
json_encode([
101+
'index' => [
102+
'number_of_replicas' => 1
103+
]
104+
], JSON_THROW_ON_ERROR)
105+
]
106+
)
107+
->willReturn($this->createStub(Response::class));
108+
109+
$testObject = new Index('index_with_prefix', $clientMock);
110+
$testObject->create();
111+
$testObject->updateSettings();
112+
113+
static::assertSame('index_with_prefix', $testObject->getOriginalName());
114+
static::assertSame('prefix-index_with_prefix', $testObject->getName());
115+
}
116+
}

0 commit comments

Comments
 (0)