Files
myep/src/BusProNet/XmlParser/CrmAttributesResponseParser.php
T

124 lines
4.8 KiB
PHP

<?php
namespace App\BusProNet\XmlParser;
use App\BusProNet\Model\CrmAction;
use App\BusProNet\Model\CrmAttributes;
use App\BusProNet\Model\CrmSelection;
use App\BusProNet\Model\CrmSelectionGroup;
use App\BusProNet\Traits\TypeConversionTrait;
use App\Security\Role;
use Symfony\Component\DomCrawler\Crawler;
/**
* Turns the SelektionCRM response into the roles and hotel codes the CRM claims for an account.
*
* This reports what BusPro says and nothing more: no fallback role, no default hotel code. What
* is made of the claims — which are granted outright and which only nominate — is Role::sync()'s
* business.
*
* The selection ids below are deployment-critical. BusPro always returns the full attribute tree
* and expresses membership through the `auswahl` flag, so a wrong or unset id yields a perfectly
* well-formed response in which nobody holds anything, and every user logging in is demoted one
* at a time. There is no signal inside the response that tells that apart from a real revocation.
*/
class CrmAttributesResponseParser
{
use TypeConversionTrait;
private const BPN_CRM_ID_ADMIN = 1292;
private const BPN_CRM_ID_MANAGER = 1293;
private const BPN_CRM_ID_TEAMER = 1070;
private const BPN_CRM_ID_GROUPS_MANAGER = 1477;
private const BPN_CRM_ID_GROUPS_ADMIN = 1478;
/**
* @param array<int|string, string> $houseManagerIds "Hausleitung" selection id => hotel code
*/
public function __construct(private readonly array $houseManagerIds = [])
{
}
public function parse(Crawler $result): CrmAttributes
{
$groups = [];
$actions = [];
$roles = [];
$hotelCodes = [];
$result
->filterXPath('//selektionsmerkmale/selektionsgruppe')
->each(function (Crawler $node) use (&$groups, &$roles, &$hotelCodes) {
$group = new CrmSelectionGroup();
$group->id = (int) $node->attr('id');
$group->label = $node->attr('bezeichnung');
$attributes = [];
$node
->filterXPath('//selektion')
->each(function (Crawler $node) use (&$attributes, &$roles, &$hotelCodes) {
$attribute = new CrmSelection();
$attribute->id = (int) $node->attr('id');
$attribute->label = $node->attr('bezeichnung');
$attribute->mutable = $this->stringToBool($node->attr('aenderbar'));
$attribute->selected = $this->stringToBool($node->attr('auswahl'));
if (true === $attribute->selected) {
$hotelCode = $this->houseManagerIds[$attribute->id] ?? null;
if (null !== $hotelCode) {
$roles[] = Role::HOUSE_MANAGER;
$hotelCodes[] = $hotelCode;
}
if (self::BPN_CRM_ID_ADMIN === $attribute->id) {
$roles[] = Role::ADMIN;
}
if (self::BPN_CRM_ID_MANAGER === $attribute->id) {
$roles[] = Role::MANAGER;
}
if (self::BPN_CRM_ID_TEAMER === $attribute->id) {
$roles[] = Role::TEAMER;
}
if (self::BPN_CRM_ID_GROUPS_MANAGER === $attribute->id) {
$roles[] = Role::GROUPS_MANAGER;
}
if (self::BPN_CRM_ID_GROUPS_ADMIN === $attribute->id) {
$roles[] = Role::GROUPS_ADMIN;
}
}
$attributes[] = $attribute;
})
;
$group->selections = $attributes;
$groups[] = $group;
})
;
$result
->filterXPath('//crmaktionen/crmaktion')
->each(function (Crawler $node) use (&$actions) {
$crmAction = new CrmAction();
$crmAction->id = (int) $node->attr('id');
$crmAction->code = $node->attr('code');
$crmAction->label = $node->attr('bezeichnung');
$crmAction->mutable = $this->stringToBool($node->attr('aenderbar'));
$crmAction->selected = $this->stringToBool($node->attr('auswahl'));
$actions[] = $crmAction;
})
;
$response = new CrmAttributes();
$response->selectionGroups = $groups;
$response->crmActions = $actions;
$response->roles = array_values(array_unique($roles));
$response->hotelCodes = array_values(array_unique($hotelCodes));
return $response;
}
}