Skip to content

Commit 32eb76b

Browse files
committed
Merge remote-tracking branch 'origin/next' into feature-zmskvr-319-optimization-of-location-settings
2 parents c5528c6 + b8aa67b commit 32eb76b

File tree

20 files changed

+303
-221
lines changed

20 files changed

+303
-221
lines changed

zmsadmin/js/page/useraccount/index.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,27 @@ class View extends BaseView {
3636
}
3737

3838
adjustCredentialsToOidc() {
39-
this.$main.find('input[type="password"]').each((index, item) => {
40-
if ($('#useOidcProvider').val() != "") {
41-
$(item).prop('readonly', true);
42-
$(item).val(this.randomPassword)
39+
const $oidcSelect = this.$main.find('#useOidcProvider');
40+
const $passwordInputs = this.$main.find('input[type="password"]');
41+
42+
// If OIDC select does not exist, we're on the edit page
43+
if (!$oidcSelect.length) {
44+
// On edit page: disable password fields (won't submit), show masked placeholder for visual indication
45+
// Keep value empty so nothing gets submitted, but placeholder shows there's a password set
46+
$passwordInputs.prop('disabled', true).attr('placeholder', '••••••••').val('');
47+
return;
48+
}
49+
50+
// On add page: fill with random password if OIDC is selected
51+
const oidcSelected = $oidcSelect.val() !== '';
52+
$passwordInputs.each((index, item) => {
53+
const $item = $(item);
54+
if (oidcSelected) {
55+
$item.prop('readonly', true).val(this.randomPassword);
4356
} else {
44-
$('#useOidcProvider').prop('checked', false)
45-
$(item).prop('readonly', false);
46-
$(item).val('')
57+
$item.prop('readonly', false).val('');
4758
}
48-
})
59+
});
4960
}
5061

5162
createRandomPassword() {

zmsadmin/src/Zmsadmin/BaseController.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace BO\Zmsadmin;
99

10+
use BO\Zmsadmin\Helper\TwigExceptionHandler;
1011
use Psr\Http\Message\RequestInterface;
1112
use Psr\Http\Message\ResponseInterface;
1213

@@ -46,4 +47,76 @@ public function getSchemaConstraintList($schema)
4647
}
4748
return $list;
4849
}
50+
51+
/**
52+
* Transform validation error data from JSON pointer format to field names
53+
* Maps pointers like "/id" to "id", "/changePassword" to "changePassword", etc.
54+
* Handles nested paths like "/contact/email" by flattening them.
55+
* Also handles data that's already in field name format (for test compatibility).
56+
*
57+
* @param array|null $errorData The exception data with JSON pointers as keys, or field names
58+
* @return array Transformed data with field names as keys
59+
*/
60+
protected function transformValidationErrors($errorData)
61+
{
62+
if (!is_array($errorData) && !($errorData instanceof \Traversable)) {
63+
return [];
64+
}
65+
$transformed = [];
66+
foreach ($errorData as $pointer => $item) {
67+
// Extract field name from JSON pointer (e.g., "/id" -> "id", "/contact/email" -> "contact/email")
68+
// If the key doesn't start with "/", it's already a field name, so use it as-is
69+
$fieldName = (strpos($pointer, '/') === 0) ? ltrim($pointer, '/') : $pointer;
70+
// Handle root level errors
71+
if ($fieldName === '' || $fieldName === null) {
72+
$fieldName = '_root';
73+
}
74+
// Ensure the item structure is correct (has 'messages' array)
75+
if (is_array($item) && isset($item['messages'])) {
76+
$transformed[$fieldName] = $item;
77+
} elseif (is_array($item)) {
78+
// If item is an array but doesn't have 'messages', wrap it
79+
$transformed[$fieldName] = $item;
80+
} else {
81+
$transformed[$fieldName] = $item;
82+
}
83+
}
84+
return $transformed;
85+
}
86+
87+
/**
88+
* Wraps an HTTP write operation with standardized exception handling.
89+
*
90+
* @param callable $httpCall
91+
* @return mixed
92+
* @throws \BO\Zmsclient\Exception
93+
*/
94+
protected function handleEntityWrite(callable $httpCall)
95+
{
96+
try {
97+
return $httpCall();
98+
} catch (\BO\Zmsclient\Exception $exception) {
99+
if ('BO\Zmsentities\Exception\SchemaValidation' == $exception->template) {
100+
return [
101+
'template' => 'exception/bo/zmsentities/exception/schemavalidation.twig',
102+
'include' => true,
103+
'data' => $this->transformValidationErrors($exception->data)
104+
];
105+
}
106+
107+
$template = TwigExceptionHandler::getExceptionTemplate($exception);
108+
if (
109+
'' != $exception->template
110+
&& \App::$slim->getContainer()->get('view')->getLoader()->exists($template)
111+
) {
112+
return [
113+
'template' => $template,
114+
'include' => true,
115+
'data' => $this->transformValidationErrors($exception->data)
116+
];
117+
}
118+
119+
throw $exception;
120+
}
121+
}
49122
}

zmsadmin/src/Zmsadmin/Department.php

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,34 +27,37 @@ public function readResponse(
2727
$entity = \App::$http->readGetResult('/department/' . $entityId . '/', ['resolveReferences' => 1])->getEntity();
2828
$organisation = \App::$http->readGetResult('/department/' . $entityId . '/organisation/')->getEntity();
2929
$input = $request->getParsedBody();
30+
$result = null;
3031

3132
if ($request->getMethod() === 'POST') {
3233
$input = $this->withCleanupLinks($input);
3334
$input = $this->withCleanupDayoffs($input);
3435
$input = $this->withEmailReminderDefaultValues($input);
35-
$entity = (new Entity($input))->withCleanedUpFormData();
36-
$entity->id = $entityId;
37-
$entity->dayoff = $entity->getDayoffList()->withTimestampFromDateformat();
38-
$entity = \App::$http->readPostResult(
39-
'/department/' . $entity->id . '/',
40-
$entity
41-
)->getEntity();
42-
return \BO\Slim\Render::redirect('department', ['id' => $entityId], [
43-
'success' => 'department_saved'
44-
]);
36+
$result = $this->writeUpdatedEntity($input, $entityId);
37+
if ($result instanceof Entity) {
38+
return \BO\Slim\Render::redirect('department', ['id' => $entityId], [
39+
'success' => 'department_saved'
40+
]);
41+
}
4542
}
4643

44+
// If there was an error, use the submitted input data for form re-population
45+
$departmentData = (isset($result) && is_array($result) && isset($result['data']))
46+
? array_merge((new Schema($entity))->toSanitizedArray(), $input ?? [])
47+
: (new Schema($entity))->toSanitizedArray();
48+
4749
return \BO\Slim\Render::withHtml(
4850
$response,
4951
'page/department.twig',
5052
array(
5153
'title' => 'Standort',
5254
'workstation' => $workstation,
5355
'organisation' => $organisation,
54-
'department' => (new Schema($entity))->toSanitizedArray(),
56+
'department' => $departmentData,
5557
'hasAccess' => $entity->hasAccess($workstation->getUseraccount()),
5658
'menuActive' => 'owner',
5759
'success' => $success,
60+
'exception' => (isset($result) && !($result instanceof Entity)) ? $result : null,
5861
)
5962
);
6063
}
@@ -102,4 +105,17 @@ private function withEmailReminderDefaultValues(array $input)
102105

103106
return $input;
104107
}
108+
109+
protected function writeUpdatedEntity($input, $entityId)
110+
{
111+
$entity = (new Entity($input))->withCleanedUpFormData();
112+
$entity->id = $entityId;
113+
$entity->dayoff = $entity->getDayoffList()->withTimestampFromDateformat();
114+
return $this->handleEntityWrite(function () use ($entity) {
115+
return \App::$http->readPostResult(
116+
'/department/' . $entity->id . '/',
117+
$entity
118+
)->getEntity();
119+
});
120+
}
105121
}

zmsadmin/src/Zmsadmin/DepartmentAddScope.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function readResponse(
3434
$input = $request->getParsedBody();
3535

3636
if (is_array($input) && array_key_exists('save', $input)) {
37-
$result = $this->testUpdateEntity($input, $department->id);
37+
$result = $this->writeUpdatedEntity($input, $department->id);
3838
if ($result instanceof Entity) {
3939
$this->writeUploadedImage($request, $result->id, $input);
4040
return \BO\Slim\Render::redirect('scope', ['id' => $result->id], [

zmsadmin/src/Zmsadmin/Organisation.php

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,31 +34,47 @@ public function readResponse(
3434
)->getEntity();
3535

3636
$input = $request->getParsedBody();
37+
$result = null;
3738
if (array_key_exists('save', (array) $input)) {
38-
$entity = (new Entity($input))->withCleanedUpFormData();
39-
$entity->id = $entityId;
40-
$entity = \App::$http->readPostResult('/organisation/' . $entity->id . '/', $entity)->getEntity();
41-
return \BO\Slim\Render::redirect(
42-
'organisation',
43-
[
44-
'id' => $entityId
45-
],
46-
[
47-
'success' => 'organisation_saved'
48-
]
49-
);
39+
$result = $this->writeUpdatedEntity($input, $entityId);
40+
if ($result instanceof Entity) {
41+
return \BO\Slim\Render::redirect(
42+
'organisation',
43+
[
44+
'id' => $entityId
45+
],
46+
[
47+
'success' => 'organisation_saved'
48+
]
49+
);
50+
}
5051
}
5152

53+
// If there was an error, use the submitted input data for form re-population
54+
$organisationData = (isset($result) && is_array($result) && isset($result['data']))
55+
? new Entity(array_merge($entity->getArrayCopy(), $input ?? []))
56+
: $entity;
57+
5258
return \BO\Slim\Render::withHtml(
5359
$response,
5460
'page/organisation.twig',
5561
array(
5662
'title' => 'Bezirk - Einrichtung und Administration',
5763
'workstation' => $workstation,
58-
'organisation' => $entity,
64+
'organisation' => $organisationData,
5965
'menuActive' => 'owner',
60-
'success' => $success
66+
'success' => $success,
67+
'exception' => (isset($result) && !($result instanceof Entity)) ? $result : null,
6168
)
6269
);
6370
}
71+
72+
protected function writeUpdatedEntity($input, $entityId)
73+
{
74+
$entity = (new Entity($input))->withCleanedUpFormData();
75+
$entity->id = $entityId;
76+
return $this->handleEntityWrite(function () use ($entity) {
77+
return \App::$http->readPostResult('/organisation/' . $entity->id . '/', $entity)->getEntity();
78+
});
79+
}
6480
}

zmsadmin/src/Zmsadmin/Profile.php

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,8 @@ protected function writeUpdatedEntity($input)
6464
{
6565
$entity = (new Entity($input))->withCleanedUpFormData();
6666
$entity->setPassword($input);
67-
try {
68-
$entity = \App::$http->readPostResult('/workstation/password/', $entity)->getEntity();
69-
} catch (\BO\Zmsclient\Exception $exception) {
70-
$template = Helper\TwigExceptionHandler::getExceptionTemplate($exception);
71-
if (
72-
'' != $exception->template
73-
&& \App::$slim->getContainer()->get('view')->getLoader()->exists($template)
74-
) {
75-
return [
76-
'template' => $template,
77-
'data' => $exception->data
78-
];
79-
}
80-
throw $exception;
81-
}
82-
return $entity;
67+
return $this->handleEntityWrite(function () use ($entity) {
68+
return \App::$http->readPostResult('/workstation/password/', $entity)->getEntity();
69+
});
8370
}
8471
}

zmsadmin/src/Zmsadmin/Scope.php

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public function readResponse(
4848
$callDisplayImage = \App::$http->readGetResult('/scope/' . $entityId . '/imagedata/calldisplay/')->getEntity();
4949
$input = $request->getParsedBody();
5050
if ($request->getMethod() === 'POST') {
51-
$result = $this->testUpdateEntity($input, $entityId);
51+
$result = $this->writeUpdatedEntity($input, $entityId);
5252
if ($result instanceof Entity) {
5353
$this->writeUploadedImage($request, $entityId, $input);
5454
return \BO\Slim\Render::redirect('scope', ['id' => $entityId], [
@@ -94,31 +94,18 @@ protected function readCurrentSource($source)
9494
* @param \BO\Zmsentities\Scope $input scope entity, if used without ID, a new scope is created
9595
* @param Number $entityId Might be the entity scope or department if called from DepartmentAddScope
9696
*/
97-
protected function testUpdateEntity($input, $entityId = null)
97+
protected function writeUpdatedEntity($input, $entityId = null)
9898
{
9999
$entity = (new Entity($input))->withCleanedUpFormData();
100-
try {
100+
return $this->handleEntityWrite(function () use ($entity, $entityId) {
101101
if ($entity->id) {
102102
$entity->id = $entityId;
103-
$entity = \App::$http->readPostResult('/scope/' . $entity->id . '/', $entity)->getEntity();
104-
} else {
105-
$entity = \App::$http->readPostResult('/department/' . $entityId . '/scope/', $entity)
106-
->getEntity();
103+
return \App::$http->readPostResult('/scope/' . $entity->id . '/', $entity)->getEntity();
107104
}
108-
} catch (\BO\Zmsclient\Exception $exception) {
109-
$template = Helper\TwigExceptionHandler::getExceptionTemplate($exception);
110-
if (
111-
'' != $exception->template
112-
&& \App::$slim->getContainer()->get('view')->getLoader()->exists($template)
113-
) {
114-
return [
115-
'template' => $template,
116-
'data' => $exception->data
117-
];
118-
}
119-
throw $exception;
120-
}
121-
return $entity;
105+
return \App::$http
106+
->readPostResult('/department/' . $entityId . '/scope/', $entity)
107+
->getEntity();
108+
});
122109
}
123110

124111
protected function writeUploadedImage(\Psr\Http\Message\RequestInterface $request, $entityId, $input)

zmsadmin/src/Zmsadmin/SourceEdit.php

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public function readResponse(
5151

5252
$input = $request->getParsedBody();
5353
if (is_array($input) && array_key_exists('save', $input)) {
54-
$result = $this->testUpdateEntity($input);
54+
$result = $this->writeUpdatedEntity($input);
5555
if ($result instanceof Entity) {
5656
return \BO\Slim\Render::redirect('sourceEdit', ['name' => $result->getSource()], [
5757
'success' => 'source_saved'
@@ -76,22 +76,11 @@ public function readResponse(
7676
);
7777
}
7878

79-
protected function testUpdateEntity($input)
79+
protected function writeUpdatedEntity($input)
8080
{
8181
$entity = (new Entity($input))->withCleanedUpFormData();
82-
try {
83-
$entity = \App::$http->readPostResult('/source/', $entity)->getEntity();
84-
} catch (\BO\Zmsclient\Exception $exception) {
85-
if ('BO\Zmsentities\Exception\SchemaValidation' == $exception->template) {
86-
$exceptionData = [
87-
'template' => 'exception/bo/zmsentities/exception/schemavalidation.twig'
88-
];
89-
$exceptionData['data'] = $exception->data;
90-
return $exceptionData;
91-
} else {
92-
throw $exception;
93-
}
94-
}
95-
return $entity;
82+
return $this->handleEntityWrite(function () use ($entity) {
83+
return \App::$http->readPostResult('/source/', $entity)->getEntity();
84+
});
9685
}
9786
}

0 commit comments

Comments
 (0)