Skip to content

Commit 023d38d

Browse files
committed
Allow to configure seperators, category fallback and a global prefix for IPN generation
Translations still missing
1 parent 9a1961b commit 023d38d

File tree

4 files changed

+102
-26
lines changed

4 files changed

+102
-26
lines changed

config/reference.php

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,6 +1548,11 @@
15481548
* dump_destination?: scalar|null, // A stream URL where dumps should be written to. // Default: null
15491549
* theme?: "dark"|"light", // Changes the color of the dump() output when rendered directly on the templating. "dark" (default) or "light". // Default: "dark"
15501550
* }
1551+
* @psalm-type MakerConfig = array{
1552+
* root_namespace?: scalar|null, // Default: "App"
1553+
* generate_final_classes?: bool, // Default: true
1554+
* generate_final_entities?: bool, // Default: false
1555+
* }
15511556
* @psalm-type WebpackEncoreConfig = array{
15521557
* output_path: scalar|null, // The path where Encore is building the assets - i.e. Encore.setOutputPath()
15531558
* crossorigin?: false|"anonymous"|"use-credentials", // crossorigin value when Encore.enableIntegrityHashes() is used, can be false (default), anonymous or use-credentials // Default: false
@@ -1672,12 +1677,6 @@
16721677
* post_processors?: array<string, array<string, mixed>>,
16731678
* },
16741679
* }
1675-
* @psalm-type DamaDoctrineTestConfig = array{
1676-
* enable_static_connection?: mixed, // Default: true
1677-
* enable_static_meta_data_cache?: bool, // Default: true
1678-
* enable_static_query_cache?: bool, // Default: true
1679-
* connection_keys?: list<mixed>,
1680-
* }
16811680
* @psalm-type TwigExtraConfig = array{
16821681
* cache?: bool|array{
16831682
* enabled?: bool, // Default: false
@@ -2373,6 +2372,13 @@
23732372
* invalidate_on_env_change?: bool, // Default: true
23742373
* },
23752374
* }
2375+
* @psalm-type JbtronicsTranslationEditorConfig = array{
2376+
* translations_path?: scalar|null, // Default: "%translator.default_path%"
2377+
* format?: scalar|null, // Default: "xlf"
2378+
* xliff_version?: scalar|null, // Default: "2.0"
2379+
* use_intl_icu_format?: bool, // Default: false
2380+
* writer_options?: list<scalar|null>,
2381+
* }
23762382
* @psalm-type ApiPlatformConfig = array{
23772383
* title?: scalar|null, // The title of the API. // Default: ""
23782384
* description?: scalar|null, // The description of the API. // Default: ""
@@ -2628,17 +2634,11 @@
26282634
* ...<mixed>
26292635
* },
26302636
* }
2631-
* @psalm-type MakerConfig = array{
2632-
* root_namespace?: scalar|null, // Default: "App"
2633-
* generate_final_classes?: bool, // Default: true
2634-
* generate_final_entities?: bool, // Default: false
2635-
* }
2636-
* @psalm-type JbtronicsTranslationEditorConfig = array{
2637-
* translations_path?: scalar|null, // Default: "%translator.default_path%"
2638-
* format?: scalar|null, // Default: "xlf"
2639-
* xliff_version?: scalar|null, // Default: "2.0"
2640-
* use_intl_icu_format?: bool, // Default: false
2641-
* writer_options?: list<scalar|null>,
2637+
* @psalm-type DamaDoctrineTestConfig = array{
2638+
* enable_static_connection?: mixed, // Default: true
2639+
* enable_static_meta_data_cache?: bool, // Default: true
2640+
* enable_static_query_cache?: bool, // Default: true
2641+
* connection_keys?: list<mixed>,
26422642
* }
26432643
* @psalm-type ConfigType = array{
26442644
* imports?: ImportsConfig,

src/Repository/PartRepository.php

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,20 @@ public function autoCompleteIpn(Part $part, string $description, int $suggestPar
132132
$category = $part->getCategory();
133133
$ipnSuggestions = ['commonPrefixes' => [], 'prefixesPartIncrement' => []];
134134

135+
//Show global prefix first if configured
136+
if ($this->ipnSuggestSettings->globalPrefix !== null && $this->ipnSuggestSettings->globalPrefix !== '') {
137+
$ipnSuggestions['commonPrefixes'][] = [
138+
'title' => $this->ipnSuggestSettings->globalPrefix,
139+
'description' => $this->translator->trans('part.edit.tab.advanced.ipn.prefix.global_prefix')
140+
];
141+
142+
$increment = $this->generateNextPossibleGlobalIncrement();
143+
$ipnSuggestions['prefixesPartIncrement'][] = [
144+
'title' => $this->ipnSuggestSettings->globalPrefix . $increment,
145+
'description' => $this->translator->trans('part.edit.tab.advanced.ipn.prefix.global_prefix')
146+
];
147+
}
148+
135149
if (strlen($description) > 150) {
136150
$description = substr($description, 0, 150);
137151
}
@@ -160,17 +174,17 @@ public function autoCompleteIpn(Part $part, string $description, int $suggestPar
160174
if ($category instanceof Category) {
161175
$currentPath = $category->getPartIpnPrefix();
162176
$directIpnPrefixEmpty = $category->getPartIpnPrefix() === '';
163-
$currentPath = $currentPath === '' ? 'n.a.' : $currentPath;
177+
$currentPath = $currentPath === '' ? $this->ipnSuggestSettings->fallbackPrefix : $currentPath;
164178

165179
$increment = $this->generateNextPossiblePartIncrement($currentPath, $part, $suggestPartDigits);
166180

167181
$ipnSuggestions['commonPrefixes'][] = [
168-
'title' => $currentPath . '-',
182+
'title' => $currentPath . $this->ipnSuggestSettings->numberSeparator,
169183
'description' => $directIpnPrefixEmpty ? $this->translator->trans('part.edit.tab.advanced.ipn.prefix_empty.direct_category', ['%name%' => $category->getName()]) : $this->translator->trans('part.edit.tab.advanced.ipn.prefix.direct_category')
170184
];
171185

172186
$ipnSuggestions['prefixesPartIncrement'][] = [
173-
'title' => $currentPath . '-' . $increment,
187+
'title' => $currentPath . $this->ipnSuggestSettings->numberSeparator . $increment,
174188
'description' => $directIpnPrefixEmpty ? $this->translator->trans('part.edit.tab.advanced.ipn.prefix_empty.direct_category', ['%name%' => $category->getName()]) : $this->translator->trans('part.edit.tab.advanced.ipn.prefix.direct_category.increment')
175189
];
176190

@@ -179,18 +193,19 @@ public function autoCompleteIpn(Part $part, string $description, int $suggestPar
179193

180194
while ($parentCategory instanceof Category) {
181195
// Prepend the parent category's prefix to the current path
182-
$currentPath = $parentCategory->getPartIpnPrefix() . '-' . $currentPath;
183-
$currentPath = $parentCategory->getPartIpnPrefix() === '' ? 'n.a.-' . $currentPath : $currentPath;
196+
$effectiveIPNPrefix = $parentCategory->getPartIpnPrefix() === '' ? $this->ipnSuggestSettings->fallbackPrefix : $parentCategory->getPartIpnPrefix();
197+
198+
$currentPath = $effectiveIPNPrefix . $this->ipnSuggestSettings->categorySeparator . $currentPath;
184199

185200
$ipnSuggestions['commonPrefixes'][] = [
186-
'title' => $currentPath . '-',
201+
'title' => $currentPath . $this->ipnSuggestSettings->numberSeparator,
187202
'description' => $this->translator->trans('part.edit.tab.advanced.ipn.prefix.hierarchical.no_increment')
188203
];
189204

190205
$increment = $this->generateNextPossiblePartIncrement($currentPath, $part, $suggestPartDigits);
191206

192207
$ipnSuggestions['prefixesPartIncrement'][] = [
193-
'title' => $currentPath . '-' . $increment,
208+
'title' => $currentPath . $this->ipnSuggestSettings->numberSeparator . $increment,
194209
'description' => $this->translator->trans('part.edit.tab.advanced.ipn.prefix.hierarchical.increment')
195210
];
196211

@@ -199,7 +214,7 @@ public function autoCompleteIpn(Part $part, string $description, int $suggestPar
199214
}
200215
} elseif ($part->getID() === null) {
201216
$ipnSuggestions['commonPrefixes'][] = [
202-
'title' => 'n.a.',
217+
'title' => $this->ipnSuggestSettings->fallbackPrefix,
203218
'description' => $this->translator->trans('part.edit.tab.advanced.ipn.prefix.not_saved')
204219
];
205220
}
@@ -246,6 +261,33 @@ public function getIpnSuggestByDescription(string $description): ?string
246261
return $this->getNextIpnSuggestion($givenIpnsWithSameDescription);
247262
}
248263

264+
private function generateNextPossibleGlobalIncrement(): string
265+
{
266+
$qb = $this->createQueryBuilder('part');
267+
268+
269+
$qb->select('part.ipn')
270+
->where('REGEXP(part.ipn, :ipnPattern) = TRUE')
271+
->setParameter('ipnPattern', '^' . preg_quote($this->ipnSuggestSettings->globalPrefix, '/') . '\d+$')
272+
->orderBy('NATSORT(part.ipn)', 'DESC')
273+
->setMaxResults(1)
274+
;
275+
276+
$highestIPN = $qb->getQuery()->getOneOrNullResult();
277+
if ($highestIPN !== null) {
278+
//Remove the prefix and extract the increment part
279+
$incrementPart = substr($highestIPN['ipn'], strlen($this->ipnSuggestSettings->globalPrefix));
280+
//Extract a number using regex
281+
preg_match('/(\d+)$/', $incrementPart, $matches);
282+
$incrementInt = isset($matches[1]) ? (int) $matches[1] + 1 : 0;
283+
} else {
284+
$incrementInt = 1;
285+
}
286+
287+
288+
return str_pad((string) $incrementInt, $this->ipnSuggestSettings->suggestPartDigits, '0', STR_PAD_LEFT);
289+
}
290+
249291
/**
250292
* Generates the next possible increment for a part within a given category, while ensuring uniqueness.
251293
*
@@ -266,7 +308,7 @@ private function generateNextPossiblePartIncrement(string $currentPath, Part $cu
266308
{
267309
$qb = $this->createQueryBuilder('part');
268310

269-
$expectedLength = strlen($currentPath) + 1 + $suggestPartDigits; // Path + '-' + $suggestPartDigits digits
311+
$expectedLength = strlen($currentPath) + strlen($this->ipnSuggestSettings->categorySeparator) + $suggestPartDigits; // Path + '-' + $suggestPartDigits digits
270312

271313
// Fetch all parts in the given category, sorted by their ID in ascending order
272314
$qb->select('part')

src/Settings/MiscSettings/IpnSuggestSettings.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,32 @@ class IpnSuggestSettings
7878
envVar: "bool:IPN_USE_DUPLICATE_DESCRIPTION", envVarMode: EnvVarMode::OVERWRITE,
7979
)]
8080
public bool $useDuplicateDescription = false;
81+
82+
#[SettingsParameter(
83+
label: new TM("settings.misc.ipn_suggest.fallbackPrefix"),
84+
description: new TM("settings.misc.ipn_suggest.fallbackPrefix.help"),
85+
options: ['type' => StringType::class],
86+
)]
87+
public string $fallbackPrefix = 'N.A.';
88+
89+
#[SettingsParameter(
90+
label: new TM("settings.misc.ipn_suggest.numberSeparator"),
91+
description: new TM("settings.misc.ipn_suggest.numberSeparator.help"),
92+
options: ['type' => StringType::class],
93+
)]
94+
public ?string $numberSeparator = '-';
95+
96+
#[SettingsParameter(
97+
label: new TM("settings.misc.ipn_suggest.categorySeparator"),
98+
description: new TM("settings.misc.ipn_suggest.categorySeparator.help"),
99+
options: ['type' => StringType::class],
100+
)]
101+
public ?string $categorySeparator = '-';
102+
103+
#[SettingsParameter(
104+
label: new TM("settings.misc.ipn_suggest.globalPrefix"),
105+
description: new TM("settings.misc.ipn_suggest.globalPrefix.help"),
106+
options: ['type' => StringType::class],
107+
)]
108+
public ?string $globalPrefix = null;
81109
}

translations/messages.en.xlf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14478,5 +14478,11 @@ Please note that this system is currently experimental, and the synonyms defined
1447814478
<target>e.g. Format: 3–4 alphanumeric segments (any number) separated by "-", followed by "-" and 4 digits, e.g., PCOM-RES-0001</target>
1447914479
</segment>
1448014480
</unit>
14481+
<unit id="M5Q_eZW" name="part.edit.tab.advanced.ipn.prefix.global_prefix">
14482+
<segment>
14483+
<source>part.edit.tab.advanced.ipn.prefix.global_prefix</source>
14484+
<target>The global IPN prefix, common across all parts</target>
14485+
</segment>
14486+
</unit>
1448114487
</file>
1448214488
</xliff>

0 commit comments

Comments
 (0)