-
Côme Chilliet authored
issue #5948
Verified7590b8d0
<?php
/*
This code is part of FusionDirectory (http://www.fusiondirectory.org/)
Copyright (C) 2017-2019 FusionDirectory
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
class sinapsRequestException extends Exception
{
}
class sinapsRequest
{
protected $data;
public function __construct($xml)
{
$this->data = new SimpleXMLElement($xml);
if (!isset($this->data->domaine)) {
throw new sinapsRequestException('XML content is missing "domaine" tag');
}
if (!isset($this->data->domaine['code'])) {
throw new sinapsRequestException('"domaine" tag is missing "code" attribute');
}
if (!isset($this->data->domaine->donnees->operation)) {
throw new sinapsRequestException('XML content is missing "domaine>donnees>operation" tag');
}
if (!isset($this->data->domaine->donnees->operation['codeOperation'])) {
throw new sinapsRequestException('"operation" tag is missing "codeOperation" attribute');
}
if (!isset($this->data->domaine->identifiantTransaction)) {
throw new sinapsRequestException('"identifiantTransaction" tag is missing from "domaine" tag');
}
}
public function codeDomaine()
{
return $this->data->domaine['code'];
}
public function codeOperation()
{
return $this->data->domaine->donnees->operation['codeOperation'];
}
public function operationVersion()
{
return $this->data->domaine->donnees->operation['version'];
}
public function identifiantTransaction()
{
return $this->data->domaine->identifiantTransaction;
}
public function getOperationStructure()
{
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
return $this->data->domaine->donnees->operation->structure;
}
public function getOperationPersonne()
{
return $this->data->domaine->donnees->operation->personne;
}
public static function acquittementFonctionnel($responseCode = 200, $codeAcquittement = 0, $message = '', $identifiantObjApp = NULL, $synchrone = TRUE)
{
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?>
<Acquittement xmlns:acq="http://referentiels.SINAPS.amue.fr/acquittementFonctionnel">
</Acquittement>');
$xml->addChild('ResponseCode', $responseCode);
$xml->addChild('messageAcquittement', $message);
$xml->addChild('codeAcquittement', $codeAcquittement);
if ($identifiantObjApp) {
$xml->addChild('identifiantObjApp', $identifiantObjApp);
} else {
$xml->addChild('identifiantObjApp');
}
if ($synchrone) {
/* Hack because SINAPS API makes no sense and needs a prefix for Acquittement only for synchrone mode */
return preg_replace(
array('|<Acquittement |', '|</Acquittement>$|'),
array('<acq:Acquittement ', '</acq:Acquittement>'),
$xml->asXML(),
1
);
} else {
return $xml->asXML();
}
}
public function acquittementTechnique($responseCode = 200, $message = '')
{
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?>
<WebServiceHTTPResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="acquittementTechnique.xsd">
</WebServiceHTTPResponse>');
$xml->addChild('IdentifiantTransaction', $this->identifiantTransaction());
$xml->addChild('ResponseCode', $responseCode);
$xml->addChild('ResponseMessage', $message);
return $xml->asXML();
}
public function getSupannEntiteValues($identifiantApplication, $identifiantApplicationSync, $uuidPrefix, $ldapUuidToCodeEntiteCallback)
{
$structure = $this->getOperationStructure();
$now = new DateTime();
$mapping = array(
'libelle20' => array('entite','ou'),
'descriptifLong' => array('entite','description'),
'codeStructure' => array('entite','supannCodeEntite'),
'codeSousType' => array('entite','supannTypeEntite'),
'dateDebutValidite' => array('supannStructureExt','fdSupannStartDate'),
'dateFinValidite' => array('supannStructureExt','fdSupannEndDate'),
);
$values = array(
'entite' => array(
'supannRefId' => array(),
'postalAddress' => '',
'supannCodeEntiteParent' => array(),
),
);
$uuid = '';
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
if (isset($structure->referenceCroisee->identifiantsExternes)) {
foreach ($structure->referenceCroisee->identifiantsExternes as $ref) {
if ($ref->identifiantApplication == $identifiantApplication) {
$uuid = $ref->identifiantExterne;
} elseif (in_array($ref->identifiantApplication, $identifiantApplicationSync)) {
$values['entite']['supannRefId'][] = '{'.$ref->identifiantApplication.'}'.$ref->identifiantExterne;
}
}
}
if (empty($uuid)) {
$uuid = static::genUUID();
}
array_unshift($values['entite']['supannRefId'], '{'.$uuidPrefix.'}'.$uuid);
foreach ($mapping as $sinapsAttr => list($fdTab,$fdAttr)) {
if (isset($structure->$sinapsAttr)) {
$values[$fdTab][$fdAttr] = (string)$structure->$sinapsAttr;
} else {
$values[$fdTab][$fdAttr] = '';
}
}
if (isset($structure->methodesDeContact->methodeDeContact)) {
foreach ($structure->methodesDeContact->methodeDeContact as $method) {
if (!$this->checkValidite($method, $now)) {
continue;
}
switch ((string)$method->codeTypeMethodeContact) {
case 'ADR':
if ((string)$method->adresse->temoinAdressePrincipale != 'true') {
trigger_error('Ignore adresse non principale');
continue;
}
$adresse = $this->convertAddress($method->adresse);
if ($adresse === FALSE) {
trigger_error('Ignore adresse non FR non ETR');
continue;
}
$values['entite']['postalAddress'] = $adresse;
break;
default:
trigger_error('ignoring codeTypeMethodeContact '.$method->codeTypeMethodeContact);
}
}
}
if (isset($structure->liensStructure->lienStructure)) {
foreach ($structure->liensStructure->lienStructure as $lienStructure) {
if (((string)$lienStructure->codeTypeLien == 'HIE') && isset($lienStructure->codeStructureMere)) {
if (!$this->checkValidite($lienStructure, $now)) {
continue;
}
$mereUUID = $this->getUUIDFromReferenceCroisee($identifiantApplication, $lienStructure->referenceCroisee);
if (!empty($mereUUID)) {
$values['entite']['supannCodeEntiteParent'][] = $ldapUuidToCodeEntiteCallback($mereUUID)['supannCodeEntite'];
}
}
}
}
return $values;
}
public function getUserValues($identifiantApplication, array $identifiantApplicationSync, $uuidPrefix, $ldapUuidToCodeEntiteCallback, array $userRoles)
{
$personne = $this->getOperationPersonne();
$now = new DateTime();
$mapping = array(
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
'civilite' => array('supannAccount','supannCivilite'),
'nomUsage' => array('user','sn'),
'dateNaissance' => array('personalInfo','dateOfBirth'),
'sexe' => array('personalInfo','gender'),
);
$values = array(
'lock' => FALSE,
'user' => array(
'homePhone' => '',
'postalAddress' => '',
'homePostalAddress' => '',
'employeeNumber' => '',
),
'supannAccount' => array(
'supannRefId' => array(),
'supannEntiteAffectation' => array(),
'supannRoleGenerique' => array(),
'supannTypeEntiteAffectation' => array(),
'supannRoleEntite' => array(),
'supannActivite' => array(),
'supannEmpCorps' => '',
'supannEntiteAffectationPrincipale' => '',
),
'personalInfo' => array(
'fdPrivateMail' => array(),
),
);
$uuid = '';
if (isset($personne->referenceCroisee->identifiantsExternes)) {
foreach ($personne->referenceCroisee->identifiantsExternes as $ref) {
if ($ref->identifiantApplication == $identifiantApplication) {
$uuid = (string)$ref->identifiantExterne;
} elseif (in_array($ref->identifiantApplication, $identifiantApplicationSync)) {
$values['supannAccount']['supannRefId'][] = '{'.$ref->identifiantApplication.'}'.$ref->identifiantExterne;
}
if ($ref->identifiantApplication == 'SAP') {
$values['user']['employeeNumber'] = $ref->identifiantExterne;
}
}
}
if (empty($uuid)) {
$uuid = static::genUUID();
}
array_unshift($values['supannAccount']['supannRefId'], '{'.$uuidPrefix.'}'.$uuid);
/* Check if the user still has at least one role which means he exists, otherwise this is a deletion */
$userRoleExists = array();
foreach ($userRoles as $typeRole) {
if (preg_match('|^([^/]+)/(.+)$|', $typeRole, $m)) {
$userRoleExists[$m[1]][] = $m[2];
} else {
$userRoleExists[$typeRole] = TRUE;
}
}
$deletion = TRUE;
if (isset($personne->rattachements->rattachement)) {
foreach ($personne->rattachements->rattachement as $rattachement) {
if (isset($rattachement->roles->role)) {
foreach ($rattachement->roles->role as $role) {
if (isset($userRoleExists[(string)$role->typeRole])) {
if ($userRoleExists[(string)$role->typeRole] === TRUE) {
$deletion = FALSE;
break 2;
}
if (in_array_ics((string)$role->externe->typeExterne, $userRoleExists[(string)$role->typeRole])) {
if (!empty($role->externe->identifiantStructureInterne)) {
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
/* Store identifiantStructureInterne in supannEntiteAffectationPrincipale */
$UUID = (string)$role->externe->identifiantStructureInterne;
$entite = $ldapUuidToCodeEntiteCallback($UUID);
if (isset($entite['supannTypeEntite'])) {
$values['supannAccount']['supannTypeEntiteAffectation'][] = $entite['supannTypeEntite'];
}
$values['supannAccount']['supannEntiteAffectation'][] = $entite['supannCodeEntite'];
$values['supannAccount']['supannEntiteAffectationPrincipale'] = $entite['supannCodeEntite'];
}
$deletion = FALSE;
break 2;
}
}
}
}
}
}
if ($deletion) {
/* This is a deletion */
/* Store current date as end of contract */
$values['personalInfo']['fdContractEndDate'] = $now->format('d.m.Y');
/* Lock the account */
$values['lock'] = TRUE;
/* Remove all contact info */
$values['user']['telephoneNumber'] = '';
$values['user']['facsimileTelephoneNumber'] = '';
$values['user']['mobile'] = '';
$values['mailAccount'] = FALSE;
return $values;
}
foreach ($mapping as $sinapsAttr => list($fdTab,$fdAttr)) {
if (isset($personne->$sinapsAttr)) {
$values[$fdTab][$fdAttr] = (string)$personne->$sinapsAttr;
} else {
$values[$fdTab][$fdAttr] = '';
}
}
if (isset($personne->prenoms)) {
$values['user']['givenName'] = preg_replace('/;.*$/', '', $personne->prenoms);
}
if (isset($personne->methodesDeContact->methodeContact)) {
foreach ($personne->methodesDeContact->methodeContact as $method) {
if (!$this->checkValidite($method, $now)) {
continue;
}
switch ((string)$method->typeMethodeContact) {
case 'TELPERSO':
$values['user']['homePhone'] = (string)$method->valeur;
break;
case 'MAILPERSO':
$values['personalInfo']['fdPrivateMail'][] = (string)$method->valeur;
break;
case 'ADR':
if ((string)$method->adresse->temoinAdressePrincipale != 'true') {
trigger_error('Ignore adresse non principale');
continue;
}
$adresse = $this->convertAddress($method->adresse);
if ($adresse === FALSE) {
trigger_error('Ignore adresse non FR non ETR');
continue;
}
if ((string)$method->adresse->codeTypeAdresse == 'ADRPERSO') {
$values['user']['homePostalAddress'] = $adresse;
} else {
$values['user']['postalAddress'] = $adresse;
}
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
break;
default:
trigger_error('ignoring codeTypeMethodeContact '.$method->typeMethodeContact);
}
}
}
if (isset($personne->rattachements->rattachement)) {
foreach ($personne->rattachements->rattachement as $rattachement) {
if (!$this->checkValidite($rattachement, $now)) {
continue;
}
if (isset($rattachement->roles->role)) {
foreach ($rattachement->roles->role as $role) {
if (!$this->checkValidite($role, $now)) {
continue;
}
if ($role->typeRole != 'PR') {
continue;
}
if (isset($role->personneRessource->affectations->affectation)) {
$quotiteMax = NULL;
foreach ($role->personneRessource->affectations->affectation as $affectation) {
if (!$this->checkValidite($affectation, $now)) {
continue;
}
$UUID = (string)$affectation->identifiantStructureInterne;
$quotite = (isset($affectation->quotite) ? (int)$affectation->quotite : 0);
if (!empty($UUID)) {
$entite = $ldapUuidToCodeEntiteCallback($UUID);
if (isset($entite['supannTypeEntite'])) {
$values['supannAccount']['supannTypeEntiteAffectation'][] = $entite['supannTypeEntite'];
}
$values['supannAccount']['supannEntiteAffectation'][] = $entite['supannCodeEntite'];
if (($quotiteMax === NULL) || ($quotite > $quotiteMax)) {
$quotiteMax = $quotite;
$values['supannAccount']['supannEntiteAffectationPrincipale'] = $entite['supannCodeEntite'];
}
}
}
}
if (isset($role->personneRessource->elementsDeCarriere->elementCarriere)) {
foreach ($role->personneRessource->elementsDeCarriere->elementCarriere as $elementCarriere) {
if (!$this->checkValidite($elementCarriere, $now)) {
continue;
}
/* Warning: supannEmpCorps and employeeType are mono-value so we replace them */
if (isset($elementCarriere->corps)) {
$values['supannAccount']['supannEmpCorps'] = (string)$elementCarriere->corps;
}
if (isset($elementCarriere->bapReferens)) {
$values['supannAccount']['supannActivite'][] = (string)$elementCarriere->bapReferens;
}
}
}
}
}
if (isset($rattachement->fonctionsOccupees->fonctionOccupee)) {
foreach ($rattachement->fonctionsOccupees->fonctionOccupee as $fonctionOccupee) {
if (!$this->checkValidite($fonctionOccupee, $now)) {
continue;
}
$values['supannAccount']['supannRoleGenerique'][] = (string)$fonctionOccupee->fonctionRh;
$UUID = (string)$fonctionOccupee->identifiantStructureInterne;
if (!empty($UUID)) {
$entite = $ldapUuidToCodeEntiteCallback($UUID, TRUE);
$values['supannAccount']['supannTypeEntiteAffectation'][] = $entite['supannTypeEntite'];
$values['supannAccount']['supannEntiteAffectation'][] = $entite['supannCodeEntite'];
$values['supannAccount']['supannRoleEntite'][] =
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
'[role='.$fonctionOccupee->fonctionRh.']'.
'[type='.$entite['supannTypeEntite'].']'.
'[code='.$entite['supannCodeEntite'].']';
}
}
}
}
}
foreach (array('supannRefId','supannEntiteAffectation','supannRoleGenerique','supannTypeEntiteAffectation','supannRoleEntite','supannActivite') as $arrayattribute) {
$values['supannAccount'][$arrayattribute] = array_values(array_unique($values['supannAccount'][$arrayattribute]));
}
return $values;
}
protected function convertAddress(SimpleXMLElement $address)
{
$adresse = '';
if (!empty($address->adresseFR)) {
if (!empty($address->adresseFR->batiment)) {
$adresse .= $address->adresseFR->batiment;
if (!empty($address->adresseFR->etage)) {
$adresse .= ', '.$address->adresseFR->etage;
}
$adresse .= "\n";
}
$adresse .= $address->adresseFR->numeroVoie;
if (!empty($address->adresseFR->codeBTQC)) {
$adresse .= ' '.$address->adresseFR->codeBTQC;
}
$adresse .= ' '.$address->adresseFR->typeVoie;
$adresse .= ' '.$address->adresseFR->nomVoie;
$adresse .= "\n";
if (!empty($address->adresseFR->complement)) {
$adresse .= $address->adresseFR->complement."\n";
}
if (!empty($address->adresseFR->lieuDit)) {
$adresse .= $address->adresseFR->lieuDit."\n";
}
$adresse .= $address->adresseFR->codePostal;
$adresse .= ' '.$address->adresseFR->BD;
$adresse .= "\n";
$adresse .= "FRANCE\n";
} elseif (!empty($address->adresseEtr)) {
if (!empty($address->adresseEtr->batiment)) {
$adresse .= $address->adresseEtr->batiment;
if (!empty($address->adresseEtr->etage)) {
$adresse .= ', '.$address->adresseEtr->etage;
}
$adresse .= "\n";
}
$adresse .= $address->adresseEtr->numeroVoie;
$adresse .= ' '.$address->adresseEtr->nomVoie;
$adresse .= "\n";
if (!empty($address->adresseEtr->complement)) {
$adresse .= $address->adresseEtr->complement."\n";
}
$adresse .= $address->adresseEtr->codePostal;
$adresse .= ' '.$address->adresseEtr->ville;
$adresse .= "\n";
$adresse .= $address->adresseEtr->etat."\n";
$adresse .= $address->adresseEtr->pays."\n";
} else {
$adresse = FALSE;
}
return $adresse;
}
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
protected function checkValidite(SimpleXMLElement $object, DateTime $now)
{
if ($object->dateDebutValidite) {
$dateDebutValidite = new DateTime($object->dateDebutValidite);
if ($dateDebutValidite >= $now) {
// Object is not valid yet, skip it
return FALSE;
}
}
if ($object->dateFinValidite) {
$dateFinValidite = new DateTime($object->dateFinValidite);
if ($dateFinValidite < $now) {
// Object is not valid anymore, skip it
return FALSE;
}
}
return TRUE;
}
protected function getUUIDFromReferenceCroisee($identifiantApplication, $referenceCroisee)
{
foreach ($referenceCroisee->identifiantsExternes as $ref) {
if ($ref->identifiantApplication == $identifiantApplication) {
return $ref->identifiantExterne;
}
}
return '';
}
public static function genUUID()
{
//UUID v4
return sprintf(
'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
// 32 bits for "time_low"
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
// 16 bits for "time_mid"
mt_rand(0, 0xffff),
// 16 bits for "time_hi_and_version",
// four most significant bits holds version number 4
mt_rand(0, 0x0fff) | 0x4000,
// 16 bits, 8 bits for "clk_seq_hi_res",
// 8 bits for "clk_seq_low",
// two most significant bits holds zero and one for variant DCE1.1
mt_rand(0, 0x3fff) | 0x8000,
// 48 bits for "node"
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
);
}
}