ILIAS  release_8 Revision v8.23
class.ilSamlIdpXmlMetadataParser.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
23 
25 {
28  private Result $result;
29  private bool $xmlErrorState = false;
31  private array $errorStack = [];
32 
33  public function __construct(DataTypeFactory $dataFactory, ilSamlIdpXmlMetadataErrorFormatter $errorFormatter)
34  {
35  $this->dataFactory = $dataFactory;
36  $this->errorFormatter = $errorFormatter;
37  $this->result = new Result\Error('No metadata parsed, yet');
38  }
39 
40  private function beginLogging(): void
41  {
42  if (0 === count($this->errorStack)) {
43  $this->xmlErrorState = libxml_use_internal_errors(true);
44  libxml_clear_errors();
45  } else {
46  $this->addErrors();
47  }
48 
49  $this->errorStack[] = [];
50  }
51 
52  private function addErrors(): void
53  {
54  $currentErrors = libxml_get_errors();
55  libxml_clear_errors();
56 
57  $level = count($this->errorStack) - 1;
58  $this->errorStack[$level] = array_merge($this->errorStack[$level], $currentErrors);
59  }
60 
64  private function endLogging(): array
65  {
66  $this->addErrors();
67 
68  $errors = array_pop($this->errorStack);
69 
70  if (0 === count($this->errorStack)) {
71  libxml_use_internal_errors($this->xmlErrorState);
72  }
73 
74  return $errors;
75  }
76 
77  public function parse(string $xmlString): void
78  {
79  try {
80  $this->beginLogging();
81 
82  $xml = new SimpleXMLElement($xmlString);
83 
84  $xml->registerXPathNamespace('md', 'urn:oasis:names:tc:SAML:2.0:metadata');
85  $xml->registerXPathNamespace('mdui', 'urn:oasis:names:tc:SAML:metadata:ui');
86 
87  $idps = $xml->xpath('//md:EntityDescriptor[//md:IDPSSODescriptor]');
88  $entityId = null;
89  if ($idps && is_array($idps) && isset($idps[0]) && $idps[0] instanceof SimpleXMLElement) {
90  $attributes = $idps[0]->attributes('', true);
91  if ($attributes && isset($attributes['entityID'])) {
92  $entityId = (string) ($attributes->entityID[0] ?? '');
93  }
94  }
95 
96  $errors = $this->endLogging();
97 
98  if ($entityId) {
99  $this->result = $this->dataFactory->ok($entityId);
100  return;
101  }
102 
103  $error = new LibXMLError();
104  $error->level = LIBXML_ERR_FATAL;
105  $error->code = 0;
106  $error->message = 'No entityID found';
107  $error->line = 1;
108  $error->column = 0;
109 
110  $errors[] = $error;
111 
112  $this->result = $this->dataFactory->error($this->errorFormatter->formatErrors(...$errors));
113  } catch (Exception $e) {
114  $this->result = $this->dataFactory->error($this->errorFormatter->formatErrors(...$this->endLogging()));
115  }
116  }
117 
118  public function result(): Result
119  {
120  return $this->result;
121  }
122 }
$attributes
Definition: metadata.php:248
ilSamlIdpXmlMetadataErrorFormatter $errorFormatter
$errors
Definition: imgupload.php:65
__construct(DataTypeFactory $dataFactory, ilSamlIdpXmlMetadataErrorFormatter $errorFormatter)
A result encapsulates a value or an error and simplifies the handling of those.
Definition: Result.php:14
$xml
Definition: metadata.php:351
if($source===null) if(!($source instanceof SP)) $entityId
Definition: metadata.php:105