Skip to content

Commit 1102822

Browse files
committed
feat(collage): Adapt layout selection and limit calculation for new designer
Key changes include: - **Adapted Layout Selection:** The collage layout selection mechanism has been updated to align with the new designer's data structure. This means `config['collage']['layout']` now stores the relative path to the layout's JSON configuration file instead of an enum value. - **Persistent Collage Configuration:** The calculation of the collage limit and other related settings (e.g., placeholder properties) are now always saved to the main configuration, regardless of whether the collage feature is currently enabled. This ensures that the configuration is consistently up-to-date and prevents issues where stale limit values were used, leading to "Undefined array key" errors. - **Removed `CollageLayoutEnum`:** The `CollageLayoutEnum` and all its references have been deprecated and removed, simplifying the code and eliminating unnecessary abstraction now that layout paths are directly used. - **Enhanced `AdminInput::renderSelect`:** The `renderSelect` method in `AdminInput` now supports providing an HTML string as an option list, allowing for more flexible and dynamic dropdown constructions (e.g., with `optgroup` elements). - **Extended `CollageLayoutScanner`:** The `CollageLayoutScanner` class has been extended with new utility methods: - `getLayoutData()`: To retrieve detailed data for a specific layout. - `getLayoutSelectOptionsHtml()`: To generate the formatted HTML options for the select dropdown, including `optgroup` for better organization. - `getCollageConfigPath()`: To correctly determine the full file path for a given collage layout.
1 parent 37d9b8d commit 1102822

File tree

10 files changed

+209
-198
lines changed

10 files changed

+209
-198
lines changed

admin/collage-designer/components/design-selector.php

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,47 +6,14 @@
66

77
$languageService = LanguageService::getInstance();
88

9-
$currentDesign = '';
10-
11-
$designes = CollageLayoutScanner::scanLayouts();
9+
$currentDesign = $config['collage']['layout'];
1210

1311
$optionsHtml = '
1412
<option value="">
1513
' . $languageService->translate('collage_choose_new_design') . '
1614
</option>';
1715

18-
foreach ($designes as $mainGroupTitle => $subGroups) { // Iterate over main groups (e.g., "Standard Layouts", "Custom Layouts")
19-
$optionsHtml .= '<optgroup label="' . htmlspecialchars($mainGroupTitle, ENT_QUOTES) . '">';
20-
21-
// Sort subgroups by their translated titles to ensure consistent order
22-
// This is a simple key sort (by the translated name)
23-
ksort($subGroups);
24-
25-
foreach ($subGroups as $subGroupTitle => $layouts) { // Iterate over subgroups (e.g., "Portrait Layouts", "Community Layouts")
26-
// Add a disabled option as a heading for the subgroup
27-
if (!empty($subGroupTitle)) {
28-
$optionsHtml .= '<option disabled>' . str_repeat('&nbsp;', 4) . '--- ' . htmlspecialchars($subGroupTitle, ENT_QUOTES) . ' ---</option>';
29-
}
30-
31-
// Sort the layouts within the subgroup by their name
32-
uasort($layouts, function($a, $b) {
33-
return strcmp($a['name'] ?? $a['id'], $b['name'] ?? $b['id']);
34-
});
35-
36-
foreach ($layouts as $layoutId => $layoutData) { // Now these are the actual layout data
37-
$selected = ($layoutId === $currentDesign) ? ' selected="selected"' : '';
38-
39-
// Use the null coalescing operator for "name" to avoid Deprecated warnings
40-
// and use "id" as a fallback if "name" should be missing (which the scanner should already handle)
41-
$displayName = htmlspecialchars($layoutData['name'] ?? $layoutData['id'] ?? '', ENT_QUOTES);
42-
43-
$optionsHtml .= '<option value="' . htmlspecialchars($layoutId, ENT_QUOTES) . '"' . $selected . '>';
44-
$optionsHtml .= str_repeat('&nbsp;', 8); // Additional indentation for layout elements
45-
$optionsHtml .= $displayName . '</option>';
46-
}
47-
}
48-
$optionsHtml .= '</optgroup>';
49-
}
16+
$optionsHtml .= CollageLayoutScanner::getLayoutSelectOptionsHtml($currentDesign);
5017

5118
// --- Preparing the $configManagerSetting array (structure only, with real values later) ---
5219
$configManagerSetting = [

api/admin.php

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Photobooth\Utility\PathUtility;
2020
use Symfony\Component\Filesystem\Filesystem;
2121
use Symfony\Component\Finder\Finder;
22+
use Photobooth\Utility\CollageLayoutScanner;
2223

2324
header('Content-Type: application/json');
2425

@@ -255,61 +256,61 @@
255256
}
256257

257258
// Collage json config
258-
if ($newConfig['collage']['enabled']) {
259-
$collageConfigFilePath = Collage::getCollageConfigPath($newConfig['collage']['layout'], $newConfig['collage']['orientation']);
259+
$collageConfigFilePath = CollageLayoutScanner::getCollageConfigPath($newConfig['collage']['layout']);;
260260

261-
if ($collageConfigFilePath !== null) {
262-
$collageJson = json_decode((string)file_get_contents($collageConfigFilePath), true);
261+
if ($collageConfigFilePath !== null) {
262+
$collageJson = json_decode((string)file_get_contents($collageConfigFilePath), true);
263263

264-
if (is_array($collageJson)) {
265-
if (isset($collageJson['layout']) && !empty($collageJson['layout'])) {
266-
$layoutConfigArray = $collageJson['layout'];
264+
if (is_array($collageJson)) {
265+
if (isset($collageJson['layout']) && !empty($collageJson['layout'])) {
266+
$layoutConfigArray = $collageJson['layout'];
267267

268-
if (array_key_exists('placeholder', $collageJson)) {
269-
$newConfig['collage']['placeholder'] = $collageJson['placeholder'];
270-
}
271-
if (array_key_exists('placeholderposition', $collageJson)) {
272-
$newConfig['collage']['placeholderposition'] = $collageJson['placeholderposition'];
273-
}
274-
if (array_key_exists('placeholderpath', $collageJson)) {
275-
$newConfig['collage']['placeholderpath'] = $collageJson['placeholderpath'];
276-
}
277-
} else {
278-
$layoutConfigArray = $collageJson;
268+
if (array_key_exists('placeholder', $collageJson)) {
269+
$newConfig['collage']['placeholder'] = $collageJson['placeholder'];
270+
}
271+
if (array_key_exists('placeholderposition', $collageJson)) {
272+
$newConfig['collage']['placeholderposition'] = $collageJson['placeholderposition'];
279273
}
274+
if (array_key_exists('placeholderpath', $collageJson)) {
275+
$newConfig['collage']['placeholderpath'] = $collageJson['placeholderpath'];
276+
}
277+
} else {
278+
$layoutConfigArray = $collageJson;
279+
}
280+
281+
// Calculate collage limit
282+
if (str_starts_with($collageJson['name'], '2x')) {
283+
$newConfig['collage']['limit'] = (int) ceil(count($layoutConfigArray) / 2);
284+
} else {
285+
$newConfig['collage']['limit'] = count($layoutConfigArray);
286+
}
287+
error_log('DEBUG: admin.php - limit: ' . $newConfig['collage']['limit']);
288+
280289

281-
// Calculate collage limit
282-
if (str_starts_with($newConfig['collage']['layout'], '2x')) {
283-
$newConfig['collage']['limit'] = (int) ceil(count($layoutConfigArray) / 2);
290+
// If there is a collage placeholder whithin the correct range (0 < placeholderposition <= collage limit), we need to decrease the collage limit by 1
291+
if ($newConfig['collage']['placeholder']) {
292+
$collagePlaceholderPosition = (int) $newConfig['collage']['placeholderposition'];
293+
if ($collagePlaceholderPosition > 0 && $collagePlaceholderPosition <= $newConfig['collage']['limit']) {
294+
$newConfig['collage']['limit'] = $newConfig['collage']['limit'] - 1;
284295
} else {
285-
$newConfig['collage']['limit'] = count($layoutConfigArray);
296+
$newConfig['collage']['placeholder'] = false;
297+
$logger->debug('Placeholder position not in range. Placeholder disabled.');
286298
}
287299

288-
// If there is a collage placeholder whithin the correct range (0 < placeholderposition <= collage limit), we need to decrease the collage limit by 1
289-
if ($newConfig['collage']['placeholder']) {
290-
$collagePlaceholderPosition = (int) $newConfig['collage']['placeholderposition'];
291-
if ($collagePlaceholderPosition > 0 && $collagePlaceholderPosition <= $newConfig['collage']['limit']) {
292-
$newConfig['collage']['limit'] = $newConfig['collage']['limit'] - 1;
293-
} else {
294-
$newConfig['collage']['placeholder'] = false;
295-
$logger->debug('Placeholder position not in range. Placeholder disabled.');
296-
}
297-
298-
if ($newConfig['collage']['placeholderpath'] === '') {
299-
$newConfig['collage']['placeholder'] = false;
300-
$logger->debug('Collage Placeholder is empty. Collage Placeholder disabled.');
301-
}
300+
if ($newConfig['collage']['placeholderpath'] === '') {
301+
$newConfig['collage']['placeholder'] = false;
302+
$logger->debug('Collage Placeholder is empty. Collage Placeholder disabled.');
302303
}
303-
} else {
304-
$newConfig['collage']['enabled'] = false;
305-
$logger->debug('No valid collage json found. Collage disabled.');
306304
}
307-
}
308-
if ($newConfig['collage']['limit'] < 1) {
305+
} else {
309306
$newConfig['collage']['enabled'] = false;
310-
$logger->debug('Invalid collage limit, must be 1 or greater. Collage disabled.');
307+
$logger->debug('No valid collage json found. Collage disabled.');
311308
}
312309
}
310+
if ($newConfig['collage']['limit'] < 1) {
311+
$newConfig['collage']['enabled'] = false;
312+
$logger->debug('Invalid collage limit, must be 1 or greater. Collage disabled.');
313+
}
313314

314315
if ($newConfig['picture']['take_frame'] && $newConfig['picture']['frame'] === '') {
315316
$newConfig['picture']['take_frame'] = false;

assets/js/admin/buttons.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/* eslint n/no-unsupported-features/node-builtins: "off" */
22
/* globals photoboothTools shellCommand */
33

4-
/* Saves the admin settings via the API.
4+
/**
5+
* Saves the admin settings via the API.
56
* Displays a loader during the saving process.
67
*
78
* @param {object} [options] - Configuration options for the save operation.
@@ -89,7 +90,8 @@ function saveAdminSettings(options = {}) {
8990
});
9091
}
9192

92-
/* Checks if the admin settings form has pending changes that need to be saved.
93+
/**
94+
* Checks if the admin settings form has pending changes that need to be saved.
9395
* Relies on the 'isDirty' class being added to the #save-admin-btn by the form change listener.
9496
*
9597
* @returns {boolean} True if there are unsaved changes (i.e., the save button has 'isDirty' class), false otherwise.

lib/configsetup.inc.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<?php
22

3-
use Photobooth\Enum\CollageLayoutEnum;
43
use Photobooth\Enum\ImageFilterEnum;
54
use Photobooth\Enum\MailSecurityTypeEnum;
65
use Photobooth\Enum\RemoteStorageTypeEnum;
@@ -10,6 +9,7 @@
109
use Photobooth\Service\LanguageService;
1110
use Photobooth\Service\PrintManagerService;
1211
use Photobooth\Utility\PathUtility;
12+
use Photobooth\Utility\CollageLayoutScanner;
1313

1414
/*
1515
** This file defines the admin panel of photobooth. The admin panel definition is done in a JSON variable and structured as follows
@@ -850,9 +850,7 @@
850850
'type' => 'select',
851851
'name' => 'collage[layout]',
852852
'data-theme-field' => 'true',
853-
'placeholder' => $defaultConfig['collage']['layout'],
854-
'options' => CollageLayoutEnum::cases(),
855-
'value' => $config['collage']['layout'],
853+
'options_html' => CollageLayoutScanner::getLayoutSelectOptionsHtml($config['collage']['layout'] ?? $defaultConfig['collage']['layout']),
856854
],
857855
'collage_orientation' => [
858856
'view' => 'basic',

src/Collage.php

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Photobooth\Factory\CollageConfigFactory;
88
use Photobooth\Utility\ImageUtility;
99
use Photobooth\Utility\PathUtility;
10+
use Photobooth\Utility\CollageLayoutScanner;
1011

1112
class Collage
1213
{
@@ -27,37 +28,6 @@ public static function reset(): void
2728
self::$layoutPath = '';
2829
}
2930

30-
public static function getCollageConfigPath(string $collageLayout, string $pictureOrientation): ?string
31-
{
32-
self::$drawDashedLine =
33-
$collageLayout === '2x4-2' ||
34-
$collageLayout === '2x4-3' ||
35-
$collageLayout === '2x3-1';
36-
37-
if (!str_ends_with($collageLayout, '.json')) {
38-
$collageLayout .= '.json';
39-
}
40-
41-
$relativePaths = [
42-
'private/collage/' . $pictureOrientation . '/' . $collageLayout,
43-
'private/collage/' . $collageLayout,
44-
'private/' . $collageLayout,
45-
'template/collage/' . $pictureOrientation . '/' . $collageLayout,
46-
'template/collage/' . $collageLayout,
47-
];
48-
49-
foreach ($relativePaths as $relativePath) {
50-
$absolutePath = PathUtility::getAbsolutePath($relativePath);
51-
52-
if (file_exists($absolutePath)) {
53-
self::$layoutPath = $absolutePath;
54-
return $absolutePath;
55-
}
56-
}
57-
58-
return null;
59-
}
60-
6131
public static function createCollage(array $config, array $srcImagePaths, string $destImagePath, ?ImageFilterEnum $filter = null, ?CollageConfig $c = null): bool
6232
{
6333
if ($c === null) {
@@ -71,15 +41,17 @@ public static function createCollage(array $config, array $srcImagePaths, string
7141

7242
self::$pictureOrientation = $c->collageOrientation;
7343

74-
$collageConfigFilePath = self::getCollageConfigPath($c->collageLayout, self::$pictureOrientation);
44+
$layoutPath = CollageLayoutScanner::getCollageConfigPath($c->collageLayout); //needed?
45+
$collageJson = CollageLayoutScanner::getLayoutData($c->collageLayout);
7546

76-
if ($collageConfigFilePath !== null) {
77-
$collageJson = json_decode((string)file_get_contents($collageConfigFilePath), true);
47+
if (!empty($collageJson)) {
7848

7949
if (is_array($collageJson)) {
8050
if (isset($collageJson['layout']) && !empty($collageJson['layout'])) {
8151
$layoutConfigArray = $collageJson['layout'];
8252

53+
self::$drawDashedLine = str_starts_with($collageJson['id'], '2x');
54+
8355
if (isset($collageJson['background_color']) && !empty($collageJson['background_color'])) {
8456
$c->collageBackgroundColor = $collageJson['background_color'];
8557
}
@@ -234,7 +206,7 @@ public static function createCollage(array $config, array $srcImagePaths, string
234206
unset($imageResource);
235207
}
236208

237-
if (strpos($c->collageLayout, '2x') === 0) {
209+
if (self::$drawDashedLine) {
238210
$editImages = array_merge($editImages, $editImages);
239211
}
240212

src/Configuration/Section/CollageConfiguration.php

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Photobooth\Configuration\Section;
44

5-
use Photobooth\Enum\CollageLayoutEnum;
5+
use Photobooth\Utility\CollageLayoutScanner;
66
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
77
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
88

@@ -37,16 +37,17 @@ public static function getNode(): NodeDefinition
3737
->values(['landscape', 'portrait'])
3838
->defaultValue('landscape')
3939
->end()
40-
->enumNode('layout')
41-
->values(CollageLayoutEnum::cases())
42-
->defaultValue(CollageLayoutEnum::TWO_PLUS_TWO_2)
43-
->beforeNormalization()
44-
->always(function ($value) {
45-
if (is_string($value)) {
46-
$value = CollageLayoutEnum::from($value);
40+
->scalarNode('layout')
41+
->defaultValue('template/collage/landscape/1+2-1')
42+
->validate()
43+
->ifTrue(function ($value) {
44+
if (!is_string($value) || empty($value)) {
45+
return true;
4746
}
48-
return $value;
47+
$absolutePath = CollageLayoutScanner::getCollageConfigPath($value);
48+
return $absolutePath === null;
4949
})
50+
->thenInvalid('The collage layout "%s" does not exist or is invalid.')
5051
->end()
5152
->end()
5253
->scalarNode('dashedline_color')->defaultValue('#000000')->end()

src/Enum/CollageLayoutEnum.php

Lines changed: 0 additions & 45 deletions
This file was deleted.

src/Factory/CollageConfigFactory.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,14 @@
33
namespace Photobooth\Factory;
44

55
use Photobooth\Dto\CollageConfig;
6-
use Photobooth\Enum\CollageLayoutEnum;
76
use Photobooth\Utility\PathUtility;
87

98
class CollageConfigFactory
109
{
1110
public static function fromConfig(array $config): CollageConfig
1211
{
1312
$collageConfig = new CollageConfig();
14-
$collageConfig->collageLayout = $config['collage']['layout'] instanceof CollageLayoutEnum
15-
? $config['collage']['layout']->value
16-
: (string) $config['collage']['layout'];
13+
$collageConfig->collageLayout = (string) $config['collage']['layout'];
1714
$collageConfig->collageOrientation = $config['collage']['orientation'];
1815
$collageConfig->collageBackgroundColor = $config['collage']['background_color'];
1916
$collageConfig->collageFrame = $config['collage']['frame'];

0 commit comments

Comments
 (0)