19 declare(strict_types=1);
    40         bool $config_error = 
false,
    41         string ...$already_existing_values
    42     ): ControlledVocabsRepository {
    43         return new class ($config_error, $already_existing_values) extends 
NullRepository {
    44             public array $created_vocabs = [];
    45             public array $created_values = [];
    48                 protected bool $config_error,
    49                 protected array $already_existing_values
    53             public function create(
    57                 if ($this->config_error) {
    58                     throw new \ilMDVocabulariesException(
'config error');
    60                 $new_id = 
'new id ' . count($this->created_vocabs);
    61                 $this->created_vocabs[] = [
    69             public function findAlreadyExistingValues(
    73                 yield 
from array_intersect($this->already_existing_values, $values);
    76             public function addValueToVocabulary(
    81                 $this->created_values[] = [
    82                     'vocab id' => $vocab_id,
    96                     protected $path_string = 
'';
    98                     public function withNextStep(
string $name, 
bool $add_as_first = 
false): 
BuilderInterface   100                         $clone = clone $this;
   101                         $clone->path_string .= $name . 
';';
   105                     public function withNextStepToSuperElement(
bool $add_as_first = 
false): 
BuilderInterface   107                         $clone = clone $this;
   108                         $clone->path_string .= 
'SUPER;';
   114                         $clone = clone $this;
   116                             $clone->path_string = 
'RELATIVE!' . $this->path_string;
   123                         if (str_contains($this->path_string, 
'INVALID')) {
   124                             throw new \ilMDPathException(
'path invalid');
   126                         return new class ($this->path_string) extends 
NullPath {
   127                             public function __construct(
protected string $path_string)
   133                                 return $this->path_string;
   144         return new class ($invalid_slot) extends NullSlotHandler {
   145             public function __construct(
protected bool $invalid_slot)
   149             public array $exposed_paths_and_conditions = [];
   151             public function identiferFromPathAndCondition(
   154                 ?
string $condition_value
   156                 if ($this->invalid_slot) {
   157                     return SlotIdentifier::NULL;
   159                 $this->exposed_paths_and_conditions[] = [
   160                     'path' => $path_to_element->
toString(),
   161                     'condition path' => $path_to_condition?->
toString(),
   162                     'condition value' => $condition_value
   164                 return SlotIdentifier::EDUCATIONAL_CONTEXT;
   177         $xml_string = 
'asbduafduhsbdjfbsjfbjdbgfd532t7hubfjxd';
   179         $result = $importer->import($xml_string);
   181         $this->assertFalse($result->wasSuccessful());
   182         $this->assertNotEmpty($result->getErrors());
   183         $this->assertEmpty($repo->created_vocabs);
   184         $this->assertEmpty($repo->created_values);
   196 <?xml version=
"1.0"?>
   202         $result = $importer->import($xml_string);
   204         $this->assertFalse($result->wasSuccessful());
   205         $this->assertNotEmpty($result->getErrors());
   206         $this->assertEmpty($repo->created_vocabs);
   207         $this->assertEmpty($repo->created_values);
   219 <?xml version=
"1.0"?>
   228     <source>some source</source>
   231         <value>different value</value>
   232         <value>third value</value>
   237         $result = $importer->import($xml_string);
   239         $this->assertFalse($result->wasSuccessful());
   240         $this->assertNotEmpty($result->getErrors());
   241         $this->assertEmpty($repo->created_vocabs);
   242         $this->assertEmpty($repo->created_values);
   254 <?xml version=
"1.0"?>
   261         <condition value=
"condition value">
   269     <source>some source</source>
   272         <value>different value</value>
   273         <value>third value</value>
   278         $result = $importer->import($xml_string);
   280         $this->assertFalse($result->wasSuccessful());
   281         $this->assertNotEmpty($result->getErrors());
   282         $this->assertEmpty($repo->created_vocabs);
   283         $this->assertEmpty($repo->created_values);
   295 <?xml version=
"1.0"?>
   302         <condition value=
"condition value">
   310     <source>some source</source>
   313         <value>different value</value>
   314         <value>third value</value>
   319         $result = $importer->import($xml_string);
   321         $this->assertFalse($result->wasSuccessful());
   322         $this->assertNotEmpty($result->getErrors());
   323         $this->assertEmpty($repo->created_vocabs);
   324         $this->assertEmpty($repo->created_values);
   336 <?xml version=
"1.0"?>
   344     <source>some source</source>
   347         <value>duplicate value</value>
   348         <value>duplicate value</value>
   353         $result = $importer->import($xml_string);
   355         $this->assertFalse($result->wasSuccessful());
   356         $this->assertNotEmpty($result->getErrors());
   357         $this->assertEmpty($repo->created_vocabs);
   358         $this->assertEmpty($repo->created_values);
   365             $repo = $this->
getRepo(
false, 
'already exists', 
'also already exists'),
   370 <?xml version=
"1.0"?>
   378     <source>some source</source>
   380         <value>already exists</value>
   382         <value>also already exists</value>
   387         $result = $importer->import($xml_string);
   389         $this->assertFalse($result->wasSuccessful());
   390         $this->assertNotEmpty($result->getErrors());
   391         $this->assertEmpty($repo->created_vocabs);
   392         $this->assertEmpty($repo->created_values);
   404 <?xml version=
"1.0"?>
   413     <source>some source</source>
   416         <value>different value</value>
   417         <value>third value</value>
   422         $result = $importer->import($xml_string);
   424         $this->assertFalse($result->wasSuccessful());
   425         $this->assertNotEmpty($result->getErrors());
   426         $this->assertEmpty($repo->created_vocabs);
   427         $this->assertEmpty($repo->created_values);
   439 <?xml version=
"1.0"?>
   448     <source>some source</source>
   451         <value>different value</value>
   452         <value>third value</value>
   457         $result = $importer->import($xml_string);
   459         $this->assertTrue($result->wasSuccessful());
   460         $this->assertEmpty($result->getErrors());
   464                 'slot' => SlotIdentifier::EDUCATIONAL_CONTEXT,
   465                 'source' => 
'some source',
   467             $repo->created_vocabs
   471                 'path' => 
'step1;step2;step3;',
   472                 'condition path' => null,
   473                 'condition value' => null
   475             $slots->exposed_paths_and_conditions
   479                 [
'vocab id' => 
'new id 0', 
'value' => 
'value', 
'label' => 
''],
   480                 [
'vocab id' => 
'new id 0', 
'value' => 
'different value', 
'label' => 
''],
   481                 [
'vocab id' => 
'new id 0', 
'value' => 
'third value', 
'label' => 
'']
   483             $repo->created_values
   496 <?xml version=
"1.0"?>
   505     <source>some source</source>
   507         <value label=
"label">value</value>
   508         <value label=
"different label">different value</value>
   509         <value label=
"third label">third value</value>
   514         $result = $importer->import($xml_string);
   516         $this->assertTrue($result->wasSuccessful());
   517         $this->assertEmpty($result->getErrors());
   521                  'slot' => SlotIdentifier::EDUCATIONAL_CONTEXT,
   522                  'source' => 
'some source',
   524             $repo->created_vocabs
   528                  'path' => 
'step1;step2;step3;',
   529                  'condition path' => null,
   530                  'condition value' => null
   532             $slots->exposed_paths_and_conditions
   536                 [
'vocab id' => 
'new id 0', 
'value' => 
'value', 
'label' => 
'label'],
   537                 [
'vocab id' => 
'new id 0', 
'value' => 
'different value', 
'label' => 
'different label'],
   538                 [
'vocab id' => 
'new id 0', 
'value' => 
'third value', 
'label' => 
'third label']
   540             $repo->created_values
   553 <?xml version=
"1.0"?>
   561          <condition value=
"condition value">
   564                 <step>condstep1</step>
   565                 <step>condstep2</step>
   569     <source>some source</source>
   572         <value>different value</value>
   573         <value>third value</value>
   578         $result = $importer->import($xml_string);
   580         $this->assertTrue($result->wasSuccessful());
   581         $this->assertEmpty($result->getErrors());
   585                  'slot' => SlotIdentifier::EDUCATIONAL_CONTEXT,
   586                  'source' => 
'some source',
   588             $repo->created_vocabs
   592                  'path' => 
'step1;step2;step3;',
   593                  'condition path' => 
'RELATIVE!SUPER;condstep1;condstep2;',
   594                  'condition value' => 
'condition value'   596             $slots->exposed_paths_and_conditions
   600                 [
'vocab id' => 
'new id 0', 
'value' => 
'value', 
'label' => 
''],
   601                 [
'vocab id' => 
'new id 0', 
'value' => 
'different value', 
'label' => 
''],
   602                 [
'vocab id' => 
'new id 0', 
'value' => 
'third value', 
'label' => 
'']
   604             $repo->created_values
 
__construct()
Constructor setup ILIAS global object  public. 
 
custom()
 expected output: > ILIAS shows a base horizontal bar chart but customized with e.g.