mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-12-06 02:59:29 +00:00
Compare commits
2 commits
f27f0ab12d
...
023d38d170
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
023d38d170 | ||
|
|
9a1961bcd7 |
5 changed files with 104 additions and 26 deletions
|
|
@ -1548,6 +1548,11 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
|||
* dump_destination?: scalar|null, // A stream URL where dumps should be written to. // Default: null
|
||||
* theme?: "dark"|"light", // Changes the color of the dump() output when rendered directly on the templating. "dark" (default) or "light". // Default: "dark"
|
||||
* }
|
||||
* @psalm-type MakerConfig = array{
|
||||
* root_namespace?: scalar|null, // Default: "App"
|
||||
* generate_final_classes?: bool, // Default: true
|
||||
* generate_final_entities?: bool, // Default: false
|
||||
* }
|
||||
* @psalm-type WebpackEncoreConfig = array{
|
||||
* output_path: scalar|null, // The path where Encore is building the assets - i.e. Encore.setOutputPath()
|
||||
* 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 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
|||
* post_processors?: array<string, array<string, mixed>>,
|
||||
* },
|
||||
* }
|
||||
* @psalm-type DamaDoctrineTestConfig = array{
|
||||
* enable_static_connection?: mixed, // Default: true
|
||||
* enable_static_meta_data_cache?: bool, // Default: true
|
||||
* enable_static_query_cache?: bool, // Default: true
|
||||
* connection_keys?: list<mixed>,
|
||||
* }
|
||||
* @psalm-type TwigExtraConfig = array{
|
||||
* cache?: bool|array{
|
||||
* enabled?: bool, // Default: false
|
||||
|
|
@ -2373,6 +2372,13 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
|||
* invalidate_on_env_change?: bool, // Default: true
|
||||
* },
|
||||
* }
|
||||
* @psalm-type JbtronicsTranslationEditorConfig = array{
|
||||
* translations_path?: scalar|null, // Default: "%translator.default_path%"
|
||||
* format?: scalar|null, // Default: "xlf"
|
||||
* xliff_version?: scalar|null, // Default: "2.0"
|
||||
* use_intl_icu_format?: bool, // Default: false
|
||||
* writer_options?: list<scalar|null>,
|
||||
* }
|
||||
* @psalm-type ApiPlatformConfig = array{
|
||||
* title?: scalar|null, // The title of the API. // Default: ""
|
||||
* description?: scalar|null, // The description of the API. // Default: ""
|
||||
|
|
@ -2628,17 +2634,11 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
|||
* ...<mixed>
|
||||
* },
|
||||
* }
|
||||
* @psalm-type MakerConfig = array{
|
||||
* root_namespace?: scalar|null, // Default: "App"
|
||||
* generate_final_classes?: bool, // Default: true
|
||||
* generate_final_entities?: bool, // Default: false
|
||||
* }
|
||||
* @psalm-type JbtronicsTranslationEditorConfig = array{
|
||||
* translations_path?: scalar|null, // Default: "%translator.default_path%"
|
||||
* format?: scalar|null, // Default: "xlf"
|
||||
* xliff_version?: scalar|null, // Default: "2.0"
|
||||
* use_intl_icu_format?: bool, // Default: false
|
||||
* writer_options?: list<scalar|null>,
|
||||
* @psalm-type DamaDoctrineTestConfig = array{
|
||||
* enable_static_connection?: mixed, // Default: true
|
||||
* enable_static_meta_data_cache?: bool, // Default: true
|
||||
* enable_static_query_cache?: bool, // Default: true
|
||||
* connection_keys?: list<mixed>,
|
||||
* }
|
||||
* @psalm-type ConfigType = array{
|
||||
* imports?: ImportsConfig,
|
||||
|
|
|
|||
|
|
@ -279,6 +279,8 @@ when@test: &test
|
|||
|
||||
App\DataFixtures\:
|
||||
resource: '../src/DataFixtures/'
|
||||
autoconfigure: true
|
||||
autowire: true
|
||||
|
||||
App\Doctrine\Purger\:
|
||||
resource: '../src/Doctrine/Purger/'
|
||||
|
|
|
|||
|
|
@ -132,6 +132,20 @@ class PartRepository extends NamedDBElementRepository
|
|||
$category = $part->getCategory();
|
||||
$ipnSuggestions = ['commonPrefixes' => [], 'prefixesPartIncrement' => []];
|
||||
|
||||
//Show global prefix first if configured
|
||||
if ($this->ipnSuggestSettings->globalPrefix !== null && $this->ipnSuggestSettings->globalPrefix !== '') {
|
||||
$ipnSuggestions['commonPrefixes'][] = [
|
||||
'title' => $this->ipnSuggestSettings->globalPrefix,
|
||||
'description' => $this->translator->trans('part.edit.tab.advanced.ipn.prefix.global_prefix')
|
||||
];
|
||||
|
||||
$increment = $this->generateNextPossibleGlobalIncrement();
|
||||
$ipnSuggestions['prefixesPartIncrement'][] = [
|
||||
'title' => $this->ipnSuggestSettings->globalPrefix . $increment,
|
||||
'description' => $this->translator->trans('part.edit.tab.advanced.ipn.prefix.global_prefix')
|
||||
];
|
||||
}
|
||||
|
||||
if (strlen($description) > 150) {
|
||||
$description = substr($description, 0, 150);
|
||||
}
|
||||
|
|
@ -160,17 +174,17 @@ class PartRepository extends NamedDBElementRepository
|
|||
if ($category instanceof Category) {
|
||||
$currentPath = $category->getPartIpnPrefix();
|
||||
$directIpnPrefixEmpty = $category->getPartIpnPrefix() === '';
|
||||
$currentPath = $currentPath === '' ? 'n.a.' : $currentPath;
|
||||
$currentPath = $currentPath === '' ? $this->ipnSuggestSettings->fallbackPrefix : $currentPath;
|
||||
|
||||
$increment = $this->generateNextPossiblePartIncrement($currentPath, $part, $suggestPartDigits);
|
||||
|
||||
$ipnSuggestions['commonPrefixes'][] = [
|
||||
'title' => $currentPath . '-',
|
||||
'title' => $currentPath . $this->ipnSuggestSettings->numberSeparator,
|
||||
'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')
|
||||
];
|
||||
|
||||
$ipnSuggestions['prefixesPartIncrement'][] = [
|
||||
'title' => $currentPath . '-' . $increment,
|
||||
'title' => $currentPath . $this->ipnSuggestSettings->numberSeparator . $increment,
|
||||
'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')
|
||||
];
|
||||
|
||||
|
|
@ -179,18 +193,19 @@ class PartRepository extends NamedDBElementRepository
|
|||
|
||||
while ($parentCategory instanceof Category) {
|
||||
// Prepend the parent category's prefix to the current path
|
||||
$currentPath = $parentCategory->getPartIpnPrefix() . '-' . $currentPath;
|
||||
$currentPath = $parentCategory->getPartIpnPrefix() === '' ? 'n.a.-' . $currentPath : $currentPath;
|
||||
$effectiveIPNPrefix = $parentCategory->getPartIpnPrefix() === '' ? $this->ipnSuggestSettings->fallbackPrefix : $parentCategory->getPartIpnPrefix();
|
||||
|
||||
$currentPath = $effectiveIPNPrefix . $this->ipnSuggestSettings->categorySeparator . $currentPath;
|
||||
|
||||
$ipnSuggestions['commonPrefixes'][] = [
|
||||
'title' => $currentPath . '-',
|
||||
'title' => $currentPath . $this->ipnSuggestSettings->numberSeparator,
|
||||
'description' => $this->translator->trans('part.edit.tab.advanced.ipn.prefix.hierarchical.no_increment')
|
||||
];
|
||||
|
||||
$increment = $this->generateNextPossiblePartIncrement($currentPath, $part, $suggestPartDigits);
|
||||
|
||||
$ipnSuggestions['prefixesPartIncrement'][] = [
|
||||
'title' => $currentPath . '-' . $increment,
|
||||
'title' => $currentPath . $this->ipnSuggestSettings->numberSeparator . $increment,
|
||||
'description' => $this->translator->trans('part.edit.tab.advanced.ipn.prefix.hierarchical.increment')
|
||||
];
|
||||
|
||||
|
|
@ -199,7 +214,7 @@ class PartRepository extends NamedDBElementRepository
|
|||
}
|
||||
} elseif ($part->getID() === null) {
|
||||
$ipnSuggestions['commonPrefixes'][] = [
|
||||
'title' => 'n.a.',
|
||||
'title' => $this->ipnSuggestSettings->fallbackPrefix,
|
||||
'description' => $this->translator->trans('part.edit.tab.advanced.ipn.prefix.not_saved')
|
||||
];
|
||||
}
|
||||
|
|
@ -246,6 +261,33 @@ class PartRepository extends NamedDBElementRepository
|
|||
return $this->getNextIpnSuggestion($givenIpnsWithSameDescription);
|
||||
}
|
||||
|
||||
private function generateNextPossibleGlobalIncrement(): string
|
||||
{
|
||||
$qb = $this->createQueryBuilder('part');
|
||||
|
||||
|
||||
$qb->select('part.ipn')
|
||||
->where('REGEXP(part.ipn, :ipnPattern) = TRUE')
|
||||
->setParameter('ipnPattern', '^' . preg_quote($this->ipnSuggestSettings->globalPrefix, '/') . '\d+$')
|
||||
->orderBy('NATSORT(part.ipn)', 'DESC')
|
||||
->setMaxResults(1)
|
||||
;
|
||||
|
||||
$highestIPN = $qb->getQuery()->getOneOrNullResult();
|
||||
if ($highestIPN !== null) {
|
||||
//Remove the prefix and extract the increment part
|
||||
$incrementPart = substr($highestIPN['ipn'], strlen($this->ipnSuggestSettings->globalPrefix));
|
||||
//Extract a number using regex
|
||||
preg_match('/(\d+)$/', $incrementPart, $matches);
|
||||
$incrementInt = isset($matches[1]) ? (int) $matches[1] + 1 : 0;
|
||||
} else {
|
||||
$incrementInt = 1;
|
||||
}
|
||||
|
||||
|
||||
return str_pad((string) $incrementInt, $this->ipnSuggestSettings->suggestPartDigits, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the next possible increment for a part within a given category, while ensuring uniqueness.
|
||||
*
|
||||
|
|
@ -266,7 +308,7 @@ class PartRepository extends NamedDBElementRepository
|
|||
{
|
||||
$qb = $this->createQueryBuilder('part');
|
||||
|
||||
$expectedLength = strlen($currentPath) + 1 + $suggestPartDigits; // Path + '-' + $suggestPartDigits digits
|
||||
$expectedLength = strlen($currentPath) + strlen($this->ipnSuggestSettings->categorySeparator) + $suggestPartDigits; // Path + '-' + $suggestPartDigits digits
|
||||
|
||||
// Fetch all parts in the given category, sorted by their ID in ascending order
|
||||
$qb->select('part')
|
||||
|
|
|
|||
|
|
@ -78,4 +78,32 @@ class IpnSuggestSettings
|
|||
envVar: "bool:IPN_USE_DUPLICATE_DESCRIPTION", envVarMode: EnvVarMode::OVERWRITE,
|
||||
)]
|
||||
public bool $useDuplicateDescription = false;
|
||||
|
||||
#[SettingsParameter(
|
||||
label: new TM("settings.misc.ipn_suggest.fallbackPrefix"),
|
||||
description: new TM("settings.misc.ipn_suggest.fallbackPrefix.help"),
|
||||
options: ['type' => StringType::class],
|
||||
)]
|
||||
public string $fallbackPrefix = 'N.A.';
|
||||
|
||||
#[SettingsParameter(
|
||||
label: new TM("settings.misc.ipn_suggest.numberSeparator"),
|
||||
description: new TM("settings.misc.ipn_suggest.numberSeparator.help"),
|
||||
options: ['type' => StringType::class],
|
||||
)]
|
||||
public ?string $numberSeparator = '-';
|
||||
|
||||
#[SettingsParameter(
|
||||
label: new TM("settings.misc.ipn_suggest.categorySeparator"),
|
||||
description: new TM("settings.misc.ipn_suggest.categorySeparator.help"),
|
||||
options: ['type' => StringType::class],
|
||||
)]
|
||||
public ?string $categorySeparator = '-';
|
||||
|
||||
#[SettingsParameter(
|
||||
label: new TM("settings.misc.ipn_suggest.globalPrefix"),
|
||||
description: new TM("settings.misc.ipn_suggest.globalPrefix.help"),
|
||||
options: ['type' => StringType::class],
|
||||
)]
|
||||
public ?string $globalPrefix = null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14478,5 +14478,11 @@ Please note that this system is currently experimental, and the synonyms defined
|
|||
<target>e.g. Format: 3–4 alphanumeric segments (any number) separated by "-", followed by "-" and 4 digits, e.g., PCOM-RES-0001</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="M5Q_eZW" name="part.edit.tab.advanced.ipn.prefix.global_prefix">
|
||||
<segment>
|
||||
<source>part.edit.tab.advanced.ipn.prefix.global_prefix</source>
|
||||
<target>The global IPN prefix, common across all parts</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue