-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[WIP][FEATURE] Synchronization status
- Loading branch information
1 parent
c0c70f2
commit d5ce930
Showing
7 changed files
with
274 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace AawTeam\BackendRoles\Imaging; | ||
|
||
/* | ||
* Copyright by Agentur am Wasser | Maeder & Partner AG | ||
* | ||
* For the full copyright and license information, please read the | ||
* LICENSE file that was distributed with this source code. | ||
* | ||
* The TYPO3 project - inspiring people to share! | ||
*/ | ||
|
||
use AawTeam\BackendRoles\Role\SynchronizationStatusFactory; | ||
use TYPO3\CMS\Core\Utility\MathUtility; | ||
|
||
/** | ||
* IconHandler | ||
*/ | ||
class IconHandler | ||
{ | ||
public function __construct( | ||
protected SynchronizationStatusFactory $synchronizationStatusFactory | ||
) {} | ||
|
||
/** | ||
* @param mixed[] $parameters | ||
* @return string | ||
*/ | ||
public function typeIconUserFunction(array $parameters): string | ||
{ | ||
$row = $parameters['row'] ?? null; | ||
if (!is_array($row) || !array_key_exists('uid', $row) || !MathUtility::canBeInterpretedAsInteger($row['uid'])) { | ||
return ''; | ||
} | ||
|
||
$syncStatus = $this->synchronizationStatusFactory->createFromBackendGroupUid((int)$row['uid']); | ||
if ($syncStatus->isOutOfSync()) { | ||
return 'actions-synchronize'; | ||
} | ||
if ($syncStatus->isSyncOk()) { | ||
return 'status-user-admin'; | ||
} | ||
|
||
// Default return nothing | ||
return ''; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace AawTeam\BackendRoles\Role; | ||
|
||
/* | ||
* Copyright by Agentur am Wasser | Maeder & Partner AG | ||
* | ||
* For the full copyright and license information, please read the | ||
* LICENSE file that was distributed with this source code. | ||
* | ||
* The TYPO3 project - inspiring people to share! | ||
*/ | ||
|
||
/** | ||
* SynchronizationStatus | ||
*/ | ||
class SynchronizationStatus | ||
{ | ||
public const NOT_SYNCED = 0; | ||
public const OUT_OF_SYNC = 1; | ||
public const SYNC_OK = 2; | ||
|
||
public function __construct(public readonly int $status) | ||
{ | ||
if (!in_array($status, [self::NOT_SYNCED, self::OUT_OF_SYNC, self::SYNC_OK])) { | ||
throw new \InvalidArgumentException('Invalid status: ' . $status); | ||
} | ||
} | ||
|
||
public function isSynced(): bool | ||
{ | ||
return $this->status !== self::NOT_SYNCED; | ||
} | ||
|
||
public function isOutOfSync(): bool | ||
{ | ||
return $this->status === self::OUT_OF_SYNC; | ||
} | ||
|
||
public function isSyncOk(): bool | ||
{ | ||
return $this->status === self::SYNC_OK; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace AawTeam\BackendRoles\Role; | ||
|
||
/* | ||
* Copyright by Agentur am Wasser | Maeder & Partner AG | ||
* | ||
* For the full copyright and license information, please read the | ||
* LICENSE file that was distributed with this source code. | ||
* | ||
* The TYPO3 project - inspiring people to share! | ||
*/ | ||
|
||
use AawTeam\BackendRoles\Role\Definition\Formatter; | ||
use AawTeam\BackendRoles\Role\Definition\Loader; | ||
use TYPO3\CMS\Backend\Utility\BackendUtility; | ||
|
||
/** | ||
* SynchronizationStatusFactory | ||
*/ | ||
class SynchronizationStatusFactory | ||
{ | ||
public function __construct( | ||
protected Loader $loader, | ||
protected readonly Formatter $formatter, | ||
protected DefinitionFactory $definitionFactory | ||
) {} | ||
|
||
public function createFromBackendGroupUid(int $backendGroupuid): SynchronizationStatus | ||
{ | ||
$backendGroupRecord = BackendUtility::getRecord('be_groups', $backendGroupuid); | ||
if ($backendGroupRecord === null) { | ||
throw new \RuntimeException('Cannot load be_groups record with uid ' . $backendGroupuid, 1708168047); | ||
} | ||
return $this->createFromBackendGroupRecord($backendGroupRecord); | ||
} | ||
|
||
/** | ||
* @param mixed[] $backendGroupRecord | ||
* @return SynchronizationStatus | ||
*/ | ||
public function createFromBackendGroupRecord(array $backendGroupRecord): SynchronizationStatus | ||
{ | ||
$identifier = $this->getIdentifierFromBackendGroupRecord($backendGroupRecord); | ||
|
||
// Not synchronized | ||
if ($identifier === '') { | ||
return new SynchronizationStatus(SynchronizationStatus::NOT_SYNCED); | ||
} | ||
$definitions = $this->loader->getRoleDefinitions(); | ||
if (!$definitions->offsetExists($identifier)) { | ||
return new SynchronizationStatus(SynchronizationStatus::NOT_SYNCED); | ||
} | ||
|
||
// be_groups record is synchronized: load definitions | ||
/** @var Definition $definitionFromConfiguration */ | ||
$definitionFromConfiguration = $definitions->offsetGet($identifier); | ||
$definitionFromDatabase = $this->definitionFactory->create( | ||
array_merge( | ||
[ | ||
'identifier' => $definitionFromConfiguration->getIdentifier(), | ||
'title' => $definitionFromConfiguration->getTitle(), | ||
], | ||
$this->formatter->formatFromDbToArray($backendGroupRecord) | ||
) | ||
); | ||
|
||
// Compare the definitions | ||
$status = SynchronizationStatus::OUT_OF_SYNC; | ||
if ($this->areRoleDefinitionsEqual($definitionFromConfiguration, $definitionFromDatabase)) { | ||
$status = SynchronizationStatus::SYNC_OK; | ||
} | ||
|
||
return new SynchronizationStatus($status); | ||
} | ||
|
||
protected function areRoleDefinitionsEqual(Definition $definition1, Definition $definition2): bool | ||
{ | ||
$a = $this->formatter->formatForDatabase($definition1); | ||
$b = $this->formatter->formatForDatabase($definition2); | ||
return array_diff_assoc($a, $b) === []; | ||
} | ||
|
||
/** | ||
* @param mixed[] $backendGroupRecord | ||
* @return string | ||
*/ | ||
protected function getIdentifierFromBackendGroupRecord(array $backendGroupRecord): string | ||
{ | ||
// Input validation | ||
if (!array_key_exists('tx_backendroles_role_identifier', $backendGroupRecord)) { | ||
throw new \InvalidArgumentException('No field "tx_backendroles_role_identifier" found in $backendGroupRecord', 1708168285); | ||
} | ||
if (!is_string($backendGroupRecord['tx_backendroles_role_identifier'])) { | ||
throw new \InvalidArgumentException('Field "tx_backendroles_role_identifier" in $backendGroupRecord must be string', 1708168332); | ||
} | ||
|
||
return $backendGroupRecord['tx_backendroles_role_identifier']; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace AawTeam\BackendRoles\Tests\Unit\Role; | ||
|
||
/* | ||
* Copyright by Agentur am Wasser | Maeder & Partner AG | ||
* | ||
* For the full copyright and license information, please read the | ||
* LICENSE file that was distributed with this source code. | ||
* | ||
* The TYPO3 project - inspiring people to share! | ||
*/ | ||
|
||
use AawTeam\BackendRoles\Role\SynchronizationStatus; | ||
use PHPUnit\Framework\Attributes\DataProvider; | ||
use PHPUnit\Framework\Attributes\Test; | ||
use TYPO3\TestingFramework\Core\Unit\UnitTestCase; | ||
|
||
/** | ||
* SynchronizationStatusTest | ||
*/ | ||
class SynchronizationStatusTest extends UnitTestCase | ||
{ | ||
#[Test] | ||
public function constructorAcceptsKnownStatusValue(): void | ||
{ | ||
self::assertInstanceOf( | ||
SynchronizationStatus::class, | ||
new SynchronizationStatus(SynchronizationStatus::NOT_SYNCED) | ||
); | ||
self::assertInstanceOf( | ||
SynchronizationStatus::class, | ||
new SynchronizationStatus(SynchronizationStatus::OUT_OF_SYNC) | ||
); | ||
self::assertInstanceOf( | ||
SynchronizationStatus::class, | ||
new SynchronizationStatus(SynchronizationStatus::SYNC_OK) | ||
); | ||
} | ||
|
||
#[Test] | ||
#[DataProvider('unknownConstructorStatesDataProvider')] | ||
public function constructorFailsWithUnknownStatusValue(int $status): void | ||
{ | ||
self::expectException(\InvalidArgumentException::class); | ||
new SynchronizationStatus($status); | ||
} | ||
|
||
/** | ||
* @return mixed[] | ||
*/ | ||
public static function unknownConstructorStatesDataProvider(): array | ||
{ | ||
return [ | ||
'negative-status' => [-2], | ||
'one-below-known' => [-1], | ||
'one-above-known' => [3], | ||
'positive-status' => [4], | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
# cat=basic/enable/001; type=boolean; label=Hide managed columns of be_groups records in TCA | ||
hideManagedBackendUserGroupColumnns = 1 | ||
|
||
# cat=basic/enable/002; type=boolean; label=Show/visualize the synchronization status of be_groups records | ||
showSynchronizationStatus = 1 |