ILIAS  trunk Revision v11.0_alpha-1744-gb0451eebef4
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
ReaderTest.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
26 
27 interface TestInterface
28 {
29 }
30 
31 interface TestInterface2
32 {
33 }
34 
36 {
37 }
38 
40 {
41 }
42 
43 
44 class ReaderTest extends TestCase
45 {
46  protected D\Reader $reader;
47 
48  public function setUp(): void
49  {
50  $this->reader = new D\Reader();
51  }
52 
53  public function testNullComponent(): void
54  {
55  $component = new class () implements Component {
56  public function init(
57  array | \ArrayAccess &$define,
58  array | \ArrayAccess &$implement,
59  array | \ArrayAccess &$use,
60  array | \ArrayAccess &$contribute,
61  array | \ArrayAccess &$seek,
62  array | \ArrayAccess &$provide,
63  array | \ArrayAccess &$pull,
64  array | \ArrayAccess &$internal,
65  ): void {
66  }
67  };
68 
69  $result = $this->reader->read($component);
70 
71  $this->assertEquals(new D\OfComponent($component), $result);
72  }
73 
74  public function testSimpleDefine(): void
75  {
76  $component = new class () implements Component {
77  public function init(
78  array | \ArrayAccess &$define,
79  array | \ArrayAccess &$implement,
80  array | \ArrayAccess &$use,
81  array | \ArrayAccess &$contribute,
82  array | \ArrayAccess &$seek,
83  array | \ArrayAccess &$provide,
84  array | \ArrayAccess &$pull,
85  array | \ArrayAccess &$internal,
86  ): void {
87  $define[] = TestInterface::class;
88  }
89  };
90  $result = $this->reader->read($component);
91 
92  $name = new D\Name(TestInterface::class);
93  $define = new D\Define($name, false);
94 
95  $this->assertEquals(new D\OfComponent($component, $define), $result);
96  }
97 
99  {
100  $this->expectException(\LogicException::class);
101 
102  $result = $this->reader->read(new class () implements Component {
103  public function init(
104  array | \ArrayAccess &$define,
105  array | \ArrayAccess &$implement,
106  array | \ArrayAccess &$use,
107  array | \ArrayAccess &$contribute,
108  array | \ArrayAccess &$seek,
109  array | \ArrayAccess &$provide,
110  array | \ArrayAccess &$pull,
111  array | \ArrayAccess &$internal,
112  ): void {
113  $define[TestInterface::class] = fn() => new class ($use[ILIAS\Component\Service::class]) implements TestInterface {};
114  }
115  });
116  }
117 
118  public function testImplementWithoutImplementation(): void
119  {
120  $this->expectException(\LogicException::class);
121 
122  $result = $this->reader->read(new class () implements Component {
123  public function init(
124  array | \ArrayAccess &$define,
125  array | \ArrayAccess &$implement,
126  array | \ArrayAccess &$use,
127  array | \ArrayAccess &$contribute,
128  array | \ArrayAccess &$seek,
129  array | \ArrayAccess &$provide,
130  array | \ArrayAccess &$pull,
131  array | \ArrayAccess &$internal,
132  ): void {
133  $implement[TestInterface::class] = null;
134  }
135  });
136  }
137 
139  {
140  $component = new class () implements Component {
141  public function init(
142  array | \ArrayAccess &$define,
143  array | \ArrayAccess &$implement,
144  array | \ArrayAccess &$use,
145  array | \ArrayAccess &$contribute,
146  array | \ArrayAccess &$seek,
147  array | \ArrayAccess &$provide,
148  array | \ArrayAccess &$pull,
149  array | \ArrayAccess &$internal,
150  ): void {
151  $implement[TestInterface::class] = fn() => new ImplementsTestInterface();
152  }
153  };
154  $result = $this->reader->read($component);
155 
156  $name = TestInterface::class;
157  $implement = new D\Out(D\OutType::IMPLEMENT, $name, ["class" => ImplementsTestInterface::class, "position" => 0], []);
158 
159  $this->assertEquals(new D\OfComponent($component, $implement), $result);
160  }
161 
162  public function testImplementWithWrongImplementation(): void
163  {
164  $this->expectException(\LogicException::class);
165 
166  $result = $this->reader->read(new class () implements Component {
167  public function init(
168  array | \ArrayAccess &$define,
169  array | \ArrayAccess &$implement,
170  array | \ArrayAccess &$use,
171  array | \ArrayAccess &$contribute,
172  array | \ArrayAccess &$seek,
173  array | \ArrayAccess &$provide,
174  array | \ArrayAccess &$pull,
175  array | \ArrayAccess &$internal,
176  ): void {
177  $implement[TestInterface::class] = fn() => new class () {};
178  }
179  });
180  }
181 
183  {
184  $component = new class () implements Component {
185  public function init(
186  array | \ArrayAccess &$define,
187  array | \ArrayAccess &$implement,
188  array | \ArrayAccess &$use,
189  array | \ArrayAccess &$contribute,
190  array | \ArrayAccess &$seek,
191  array | \ArrayAccess &$provide,
192  array | \ArrayAccess &$pull,
193  array | \ArrayAccess &$internal,
194  ): void {
195  $implement[TestInterface::class] = fn() => new ImplementsTestInterface($use[TestInterface::class], $seek[TestInterface::class], $pull[TestInterface::class], $internal["something"]);
196 
197  $internal["something"] = fn() => new Implements2TestInterface();
198  }
199  };
200 
201  $result = $this->reader->read($component);
202 
203  $name = TestInterface::class;
204  $use = new D\In(D\InType::USE, $name);
205  $seek = new D\In(D\InType::SEEK, $name);
206  $pull = new D\In(D\InType::PULL, $name);
207  $internal_in = new D\In(D\InType::INTERNAL, "something");
208  $internal_out = new D\Out(D\OutType::INTERNAL, "something", null, []);
209  $implement = new D\Out(D\OutType::IMPLEMENT, $name, ["class" => ImplementsTestInterface::class, "position" => 0], [$use, $seek, $pull, $internal_in]);
210 
211  $expected = new D\OfComponent($component, $use, $seek, $pull, $internal_in, $internal_out, $implement);
212 
213  $this->assertEquals($expected, $result);
214 
215  $this->assertEquals([$implement], $result[(string) $implement]);
216  $this->assertEquals([$use], $result[(string) $use]);
217  $this->assertEquals([$seek], $result[(string) $seek]);
218  $this->assertEquals([$pull], $result[(string) $pull]);
219  $this->assertEquals([$internal_in], $result[(string) $internal_in]);
220  $this->assertEquals([$internal_out], $result[(string) $internal_out]);
221  }
222 
223  public function testImplementWithTwoImplementations(): void
224  {
225  $component = new class () implements Component {
226  public function init(
227  array | \ArrayAccess &$define,
228  array | \ArrayAccess &$implement,
229  array | \ArrayAccess &$use,
230  array | \ArrayAccess &$contribute,
231  array | \ArrayAccess &$seek,
232  array | \ArrayAccess &$provide,
233  array | \ArrayAccess &$pull,
234  array | \ArrayAccess &$internal,
235  ): void {
236  $implement[TestInterface::class] = fn() => new ImplementsTestInterface();
237  $implement[TestInterface::class] = fn() => new Implements2TestInterface();
238  }
239  };
240  $result = $this->reader->read($component);
241 
242  $name = TestInterface::class;
243  $implement = new D\Out(D\OutType::IMPLEMENT, $name, ["class" => ImplementsTestInterface::class, "position" => 0], []);
244  $implement2 = new D\Out(D\OutType::IMPLEMENT, $name, ["class" => Implements2TestInterface::class, "position" => 1], []);
245 
246  $this->assertEquals(new D\OfComponent($component, $implement, $implement2), $result);
247  $this->assertCount(2, $result[(string) $implement]);
248  }
249 
250  public function testUseWithoutContext(): void
251  {
252  $this->expectException(\LogicException::class);
253 
254  $result = $this->reader->read(new class () implements Component {
255  public function init(
256  array | \ArrayAccess &$define,
257  array | \ArrayAccess &$implement,
258  array | \ArrayAccess &$use,
259  array | \ArrayAccess &$contribute,
260  array | \ArrayAccess &$seek,
261  array | \ArrayAccess &$provide,
262  array | \ArrayAccess &$pull,
263  array | \ArrayAccess &$internal,
264  ): void {
265  $foo = $use[TestInterface::class];
266  }
267  });
268  }
269 
270  public function testContributeWithoutImplementation(): void
271  {
272  $this->expectException(\LogicException::class);
273 
274  $result = $this->reader->read(new class () implements Component {
275  public function init(
276  array | \ArrayAccess &$define,
277  array | \ArrayAccess &$implement,
278  array | \ArrayAccess &$use,
279  array | \ArrayAccess &$contribute,
280  array | \ArrayAccess &$seek,
281  array | \ArrayAccess &$provide,
282  array | \ArrayAccess &$pull,
283  array | \ArrayAccess &$internal,
284  ): void {
285  $contribute[TestInterface::class] = null;
286  }
287  });
288  }
289 
291  {
292  $component = new class () implements Component {
293  public function init(
294  array | \ArrayAccess &$define,
295  array | \ArrayAccess &$implement,
296  array | \ArrayAccess &$use,
297  array | \ArrayAccess &$contribute,
298  array | \ArrayAccess &$seek,
299  array | \ArrayAccess &$provide,
300  array | \ArrayAccess &$pull,
301  array | \ArrayAccess &$internal,
302  ): void {
303  $contribute[TestInterface::class] = fn() => new ImplementsTestInterface();
304  }
305  };
306  $result = $this->reader->read($component);
307 
308  $name = TestInterface::class;
309  $contribute = new D\Out(D\OutType::CONTRIBUTE, $name, ["position" => 0], []);
310 
311  $this->assertEquals(new D\OfComponent($component, $contribute), $result);
312  }
313 
315  {
316  $this->expectException(\LogicException::class);
317 
318  $result = $this->reader->read(new class () implements Component {
319  public function init(
320  array | \ArrayAccess &$define,
321  array | \ArrayAccess &$implement,
322  array | \ArrayAccess &$use,
323  array | \ArrayAccess &$contribute,
324  array | \ArrayAccess &$seek,
325  array | \ArrayAccess &$provide,
326  array | \ArrayAccess &$pull,
327  array | \ArrayAccess &$internal,
328  ): void {
329  $contribute[TestInterface::class] = fn() => new class () {};
330  }
331  });
332  }
333 
335  {
336  $component = new class () implements Component {
337  public function init(
338  array | \ArrayAccess &$define,
339  array | \ArrayAccess &$implement,
340  array | \ArrayAccess &$use,
341  array | \ArrayAccess &$contribute,
342  array | \ArrayAccess &$seek,
343  array | \ArrayAccess &$provide,
344  array | \ArrayAccess &$pull,
345  array | \ArrayAccess &$internal,
346  ): void {
347  $contribute[TestInterface::class] = fn() => new ImplementsTestInterface($use[TestInterface::class], $seek[TestInterface::class], $pull[TestInterface::class], $internal["something"]);
348  $internal["something"] = fn() => new Implements2TestInterface();
349  }
350  };
351  $result = $this->reader->read($component);
352 
353  $name = TestInterface::class;
354  $use = new D\In(D\InType::USE, $name);
355  $seek = new D\In(D\InType::SEEK, $name);
356  $pull = new D\In(D\InType::PULL, $name);
357  $internal_in = new D\In(D\InType::INTERNAL, "something");
358  $internal_out = new D\Out(D\OutType::INTERNAL, "something", null, []);
359  $contribute = new D\Out(D\OutType::CONTRIBUTE, $name, ["position" => 0], [$use, $seek, $pull, $internal_in]);
360 
361  $expected = new D\OfComponent($component, $use, $seek, $pull, $internal_in, $internal_out, $contribute);
362 
363  $this->assertEquals([$contribute], $result[(string) $contribute]);
364  $this->assertEquals([$use], $result[(string) $use]);
365  $this->assertEquals([$seek], $result[(string) $seek]);
366  $this->assertEquals([$pull], $result[(string) $pull]);
367  $this->assertEquals([$internal_in], $result[(string) $internal_in]);
368  $this->assertEquals([$internal_out], $result[(string) $internal_out]);
369  }
370 
371  public function testSeekWithoutContext(): void
372  {
373  $this->expectException(\LogicException::class);
374 
375  $result = $this->reader->read(new class () implements Component {
376  public function init(
377  array | \ArrayAccess &$define,
378  array | \ArrayAccess &$implement,
379  array | \ArrayAccess &$use,
380  array | \ArrayAccess &$contribute,
381  array | \ArrayAccess &$seek,
382  array | \ArrayAccess &$provide,
383  array | \ArrayAccess &$pull,
384  array | \ArrayAccess &$internal,
385  ): void {
386  $foo = $seek[TestInterface::class];
387  }
388  });
389  }
390 
391  public function testProvideWithoutImplementation(): void
392  {
393  $this->expectException(\LogicException::class);
394 
395  $result = $this->reader->read(new class () implements Component {
396  public function init(
397  array | \ArrayAccess &$define,
398  array | \ArrayAccess &$implement,
399  array | \ArrayAccess &$use,
400  array | \ArrayAccess &$contribute,
401  array | \ArrayAccess &$seek,
402  array | \ArrayAccess &$provide,
403  array | \ArrayAccess &$pull,
404  array | \ArrayAccess &$internal,
405  ): void {
406  $provide[TestInterface::class] = null;
407  }
408  });
409  }
410 
411  public function testProvideWithSimpleImplementation(): void
412  {
413  $component = new class () implements Component {
414  public function init(
415  array | \ArrayAccess &$define,
416  array | \ArrayAccess &$implement,
417  array | \ArrayAccess &$use,
418  array | \ArrayAccess &$contribute,
419  array | \ArrayAccess &$seek,
420  array | \ArrayAccess &$provide,
421  array | \ArrayAccess &$pull,
422  array | \ArrayAccess &$internal,
423  ): void {
424  $provide[TestInterface::class] = fn() => new ImplementsTestInterface();
425  }
426  };
427  $result = $this->reader->read($component);
428 
429  $name = TestInterface::class;
430  $provide = new D\Out(D\OutType::PROVIDE, $name, null, []);
431 
432  $this->assertEquals(new D\OfComponent($component, $provide), $result);
433  }
434 
435  public function testProvideWithWrongImplementation(): void
436  {
437  $this->expectException(\LogicException::class);
438 
439  $result = $this->reader->read(new class () implements Component {
440  public function init(
441  array | \ArrayAccess &$define,
442  array | \ArrayAccess &$implement,
443  array | \ArrayAccess &$use,
444  array | \ArrayAccess &$contribute,
445  array | \ArrayAccess &$seek,
446  array | \ArrayAccess &$provide,
447  array | \ArrayAccess &$pull,
448  array | \ArrayAccess &$internal,
449  ): void {
450  $provide[TestInterface::class] = fn() => new class () {};
451  }
452  });
453  }
454 
456  {
457  $component = new class () implements Component {
458  public function init(
459  array | \ArrayAccess &$define,
460  array | \ArrayAccess &$implement,
461  array | \ArrayAccess &$use,
462  array | \ArrayAccess &$contribute,
463  array | \ArrayAccess &$seek,
464  array | \ArrayAccess &$provide,
465  array | \ArrayAccess &$pull,
466  array | \ArrayAccess &$internal,
467  ): void {
468  $provide[TestInterface::class] = fn() => new ImplementsTestInterface($use[TestInterface::class], $seek[TestInterface::class], $pull[TestInterface::class], $internal["something"]);
469 
470  $internal["something"] = fn() => new Implements2TestInterface();
471  }
472  };
473  $result = $this->reader->read($component);
474 
475  $name = TestInterface::class;
476  $use = new D\In(D\InType::USE, $name);
477  $seek = new D\In(D\InType::SEEK, $name);
478  $pull = new D\In(D\InType::PULL, $name);
479  $internal_in = new D\In(D\InType::INTERNAL, "something");
480  $internal_out = new D\Out(D\OutType::INTERNAL, "something", null, []);
481  $provide = new D\Out(D\OutType::PROVIDE, $name, null, [$use, $seek, $pull, $internal_in]);
482 
483  $expected = new D\OfComponent($component, $use, $seek, $pull, $internal_in, $internal_out, $provide);
484 
485  $this->assertEquals($expected, $result);
486 
487  $this->assertEquals([$provide], $result[(string) $provide]);
488  $this->assertEquals([$use], $result[(string) $use]);
489  $this->assertEquals([$seek], $result[(string) $seek]);
490  $this->assertEquals([$pull], $result[(string) $pull]);
491  $this->assertEquals([$internal_in], $result[(string) $internal_in]);
492  $this->assertEquals([$internal_out], $result[(string) $internal_out]);
493  }
494 
495  public function testPullWithoutContext(): void
496  {
497  $this->expectException(\LogicException::class);
498 
499  $result = $this->reader->read(new class () implements Component {
500  public function init(
501  array | \ArrayAccess &$define,
502  array | \ArrayAccess &$implement,
503  array | \ArrayAccess &$use,
504  array | \ArrayAccess &$contribute,
505  array | \ArrayAccess &$seek,
506  array | \ArrayAccess &$provide,
507  array | \ArrayAccess &$pull,
508  array | \ArrayAccess &$internal,
509  ): void {
510  $foo = $pull[TestInterface::class];
511  }
512  });
513  }
514 
515  public function testSimpleInternal(): void
516  {
517  $this->expectException(\LogicException::class);
518 
519  $raw_name = "some_name";
520 
521  $result = $this->reader->read(new class ($raw_name) implements Component {
522  public function __construct(
523  protected string $raw_name
524  ) {
525  }
526 
527  public function init(
528  array | \ArrayAccess &$define,
529  array | \ArrayAccess &$implement,
530  array | \ArrayAccess &$use,
531  array | \ArrayAccess &$contribute,
532  array | \ArrayAccess &$seek,
533  array | \ArrayAccess &$provide,
534  array | \ArrayAccess &$pull,
535  array | \ArrayAccess &$internal,
536  ): void {
537  $internal[$this->raw_name] = fn() => $internal[$this->raw_name];
538  }
539  });
540  }
541 
542  public function testReaderProvidesMocks(): void
543  {
544  $raw_name = "some_name";
545  $results = [];
546 
547  $result = $this->reader->read(new class ($raw_name, $results) implements Component {
548  public function __construct(
549  protected string $raw_name,
550  protected array &$results
551  ) {
552  }
553 
554  public function init(
555  array | \ArrayAccess &$define,
556  array | \ArrayAccess &$implement,
557  array | \ArrayAccess &$use,
558  array | \ArrayAccess &$contribute,
559  array | \ArrayAccess &$seek,
560  array | \ArrayAccess &$provide,
561  array | \ArrayAccess &$pull,
562  array | \ArrayAccess &$internal,
563  ): void {
564  $provide[TestInterface::class] = fn() => new class (
566  $use[TestInterface::class],
567  $seek[TestInterface::class],
568  $pull[TestInterface::class]
569  ) implements TestInterface {
570  public function __construct(
571  array &$results,
572  $a,
573  $b,
574  $c
575  ) {
576  $results[] = $a;
577  $results[] = $b;
578  $results[] = $c;
579  }
580  };
581  }
582  });
583 
584  $this->assertInstanceOf(TestInterface::class, $results[0]);
585  $this->assertEquals([], $results[1]);
586  $this->assertInstanceOf(TestInterface::class, $results[2]);
587  }
588 
589  public function testReaderResolvesInternal(): void
590  {
591  $raw_name = "some_name";
592  $results = [];
593 
594  $result = $this->reader->read(new class ($raw_name, $results) implements Component {
595  public function __construct(
596  protected string $raw_name,
597  protected array &$results
598  ) {
599  }
600 
601  public function init(
602  array | \ArrayAccess &$define,
603  array | \ArrayAccess &$implement,
604  array | \ArrayAccess &$use,
605  array | \ArrayAccess &$contribute,
606  array | \ArrayAccess &$seek,
607  array | \ArrayAccess &$provide,
608  array | \ArrayAccess &$pull,
609  array | \ArrayAccess &$internal,
610  ): void {
611  $provide[TestInterface::class] = fn() => new class (
613  $internal["foo"],
614  $internal["bar"],
615  $internal["baz"]
616  ) implements TestInterface {
617  public function __construct(
618  array &$results,
619  $a,
620  $b,
621  $c
622  ) {
623  $results[] = $a;
624  $results[] = $b;
625  $results[] = $c;
626  }
627  };
628 
629  $internal["foo"] = fn() => $use[TestInterface::class];
630  $internal["bar"] = fn() => $seek[TestInterface::class];
631  $internal["baz"] = fn() => $pull[TestInterface2::class];
632  }
633  });
634 
635  $this->assertInstanceOf(TestInterface::class, $results[0]);
636  $this->assertEquals([], $results[1]);
637  $this->assertInstanceOf(TestInterface2::class, $results[2]);
638  }
639 }
init(array|\ArrayAccess &$define, array|\ArrayAccess &$implement, array|\ArrayAccess &$use, array|\ArrayAccess &$contribute, array|\ArrayAccess &$seek, array|\ArrayAccess &$provide, array|\ArrayAccess &$pull, array|\ArrayAccess &$internal,)
Definition: Component.php:25
$c
Definition: deliver.php:25
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
__construct()
Constructor setup ILIAS global object public.
Definition: class.ilias.php:76
$results
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples