Skip to content

Commit

Permalink
Core/Dependencies: Render Resolved Tree in PHP
Browse files Browse the repository at this point in the history
  • Loading branch information
klees committed Nov 22, 2023
1 parent 84cc604 commit fb2f584
Show file tree
Hide file tree
Showing 13 changed files with 459 additions and 4 deletions.
5 changes: 5 additions & 0 deletions components/ILIAS/Core/src/Dependencies/Define.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,9 @@ public function __toString(): string
{
return "DEFINE: " . $this->name;
}

public function getName(): string
{
return (string) $this->name;
}
}
1 change: 1 addition & 0 deletions components/ILIAS/Core/src/Dependencies/Dependency.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@
interface Dependency
{
public function __toString(): string;
public function getName(): string;
}
13 changes: 9 additions & 4 deletions components/ILIAS/Core/src/Dependencies/In.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ public function __construct(
$this->name = $name;
}

public function __toString(): string
public function getName(): string
{
return $this->type->value . ": " . $this->name;
return (string) $this->name;
}

public function getName(): Name
public function __toString(): string
{
return $this->name;
return $this->type->value . ": " . $this->name;
}

public function getType(): InType
Expand All @@ -70,4 +70,9 @@ public function addResolution(Out $other): void
$this->resolved_by[] = $other;
$other->addResolves($this);
}

public function getResolvedBy(): array
{
return $this->resolved_by;
}
}
46 changes: 46 additions & 0 deletions components/ILIAS/Core/src/Dependencies/NullDIC.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

/**
* This file is part of ILIAS, a powerful learning management system
* published by ILIAS open source e-Learning e.V.
*
* ILIAS is licensed with the GPL-3.0,
* see https://www.gnu.org/licenses/gpl-3.0.en.html
* You should have received a copy of said license along with the
* source code, too.
*
* If this is not the case or you just want to try ILIAS, you'll find
* us at:
* https://www.ilias.de
* https://github.com/ILIAS-eLearning
*
*********************************************************************/

declare(strict_types=1);

namespace ILIAS\Core\Dependencies;

/**
* An object that looks like a Dependency Injection Container but actually
* does nothing.
*/
class NullDIC implements \ArrayAccess
{
public function offsetSet($id, $value): void
{
}

public function offsetGet($id): null
{
return null;
}

public function offsetExists($id): false
{
return false;
}

public function offsetUnset($id): void
{
}
}
11 changes: 11 additions & 0 deletions components/ILIAS/Core/src/Dependencies/OfComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ public function getInDependencies(): \Iterator
}
}

public function getInDependenciesOf(InType $type): \Iterator
{
foreach ($this->dependencies as $d) {
foreach ($d as $i) {
if ($i instanceof In && $i->getType() === $type) {
yield $i;
}
}
}
}

// ArrayAccess

public function offsetExists($dependency_description): bool
Expand Down
5 changes: 5 additions & 0 deletions components/ILIAS/Core/src/Dependencies/Out.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ public function __toString(): string
return $this->type->value . ": " . $this->name;
}

public function getName(): string
{
return (string) $this->name;
}

public function setComponent(OfComponent $component): void
{
if (!is_null($this->component)) {
Expand Down
98 changes: 98 additions & 0 deletions components/ILIAS/Core/src/Dependencies/Renderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

/**
* This file is part of ILIAS, a powerful learning management system
* published by ILIAS open source e-Learning e.V.
*
* ILIAS is licensed with the GPL-3.0,
* see https://www.gnu.org/licenses/gpl-3.0.en.html
* You should have received a copy of said license along with the
* source code, too.
*
* If this is not the case or you just want to try ILIAS, you'll find
* us at:
* https://www.ilias.de
* https://github.com/ILIAS-eLearning
*
*********************************************************************/

declare(strict_types=1);

namespace ILIAS\Core\Dependencies;

/**
* This takes a (hopefully resolved...) dependency tree and renders it in PHP to
* be used for initialisation.
*/
class Renderer
{
public function render(OfComponent ...$components): string
{
$component_lookup = array_flip(
array_map(
fn($c) => $c->getComponentName(),
$components
)
);

return
$this->renderHeader() .
join("\n", array_map(
fn($c) => $this->renderComponent($component_lookup, $c),
$components
));
}

protected function renderHeader(): string
{
return <<<PHP
<?php
/**
* This file is part of ILIAS, a powerful learning management system
* published by ILIAS open source e-Learning e.V.
*
* ILIAS is licensed with the GPL-3.0,
* see https://www.gnu.org/licenses/gpl-3.0.en.html
* You should have received a copy of said license along with the
* source code, too.
*
* If this is not the case or you just want to try ILIAS, you'll find
* us at:
* https://www.ilias.de
* https://github.com/ILIAS-eLearning
*
*********************************************************************/
\$null_dic = new ILIAS\Core\Dependencies\NullDIC();
PHP;
}

protected function renderComponent(array $component_lookup, OfComponent $component): string
{
$me = $component_lookup[$component->getComponentName()];
$pull = "";
foreach ($component->getInDependenciesOf(InType::PULL) as $in) {
$r = $in->getResolvedBy()[0];
$o = $component_lookup[$r->getComponent()->getComponentName()];
$pull .= "\n\$pull[{$in->getName()}::class] = fn() => \$provide_{$o}[{$r->getName()}::class];";
}
return <<<PHP
\$component_$me = new {$component->getComponentName()}();
\$implement_$me = new Pimple\Container();
\$use = new Pimple\Container();
\$contribute_$me = new Pimple\Container();
\$seek = new Pimple\Container();
\$provide_$me = new Pimple\Container();
\$pull = new Pimple\Container();{$pull}
\$internal = new Pimple\Container();
\$component_{$me}->init(\$null_dic, \$implement_$me, \$use, \$contribute_$me, \$seek, \$provide_$me, \$pull, \$internal);
PHP;
}
}
33 changes: 33 additions & 0 deletions components/ILIAS/Core/tests/Dependencies/NullDICTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

/**
* This file is part of ILIAS, a powerful learning management system
* published by ILIAS open source e-Learning e.V.
*
* ILIAS is licensed with the GPL-3.0,
* see https://www.gnu.org/licenses/gpl-3.0.en.html
* You should have received a copy of said license along with the
* source code, too.
*
* If this is not the case or you just want to try ILIAS, you'll find
* us at:
* https://www.ilias.de
* https://github.com/ILIAS-eLearning
*
*********************************************************************/

declare(strict_types=1);

namespace ILIAS\Core\Tests\Dependencies;

use PHPUnit\Framework\TestCase;
use ILIAS\Core\Dependencies\Name;

class NullDICTest extends TestCase
{
public function testExistence()
{
$dic = new \ILIAS\Core\Dependencies\NullDIC();
$this->assertInstanceOf(\ArrayAccess::class, $dic);
}
}
76 changes: 76 additions & 0 deletions components/ILIAS/Core/tests/Dependencies/RendererTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

/**
* This file is part of ILIAS, a powerful learning management system
* published by ILIAS open source e-Learning e.V.
*
* ILIAS is licensed with the GPL-3.0,
* see https://www.gnu.org/licenses/gpl-3.0.en.html
* You should have received a copy of said license along with the
* source code, too.
*
* If this is not the case or you just want to try ILIAS, you'll find
* us at:
* https://www.ilias.de
* https://github.com/ILIAS-eLearning
*
*********************************************************************/

declare(strict_types=1);

namespace ILIAS\Core\Tests\Dependencies;

use PHPUnit\Framework\TestCase;
use ILIAS\Core\Dependencies\Reader;
use ILIAS\Core\Dependencies\Resolver;
use ILIAS\Core\Dependencies\Renderer;
use ILIAS\Core\Component;

class RendererTest extends TestCase
{
protected Reader $reader;
protected Resolver $resolver;
protected Renderer $renderer;

public function setUp(): void
{
$this->reader = new Reader();
$this->resolver = new Resolver();
$this->renderer = new Renderer();
}

/**
* @dataProvider scenarios
*/
public function testScenario($scenario_file, $result_file, $components, $disambiguation)
{
require_once(__DIR__ . "/scenarios/$scenario_file");

$components = array_map(fn($c) => $this->reader->read(new $c()), $components);
$resolved = $this->resolver->resolveDependencies($disambiguation, ...$components);

$result = $this->renderer->render(...$resolved);

$expected = file_get_contents(__DIR__ . "/scenarios/$result_file");
$this->assertEquals($expected, $result);
}

public function scenarios()
{
return [
"no dependencies" => ["scenario1.php", "result1.php",
[
\ILIAS\Core\Tests\Dependencies\Scenario1\ComponentA::class
],
[]
],
"pull dependency" => ["scenario2.php", "result2.php",
[
\ILIAS\Core\Tests\Dependencies\Scenario2\ComponentA::class,
\ILIAS\Core\Tests\Dependencies\Scenario2\ComponentB::class
],
[]
]
];
}
}
32 changes: 32 additions & 0 deletions components/ILIAS/Core/tests/Dependencies/scenarios/result1.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/**
* This file is part of ILIAS, a powerful learning management system
* published by ILIAS open source e-Learning e.V.
*
* ILIAS is licensed with the GPL-3.0,
* see https://www.gnu.org/licenses/gpl-3.0.en.html
* You should have received a copy of said license along with the
* source code, too.
*
* If this is not the case or you just want to try ILIAS, you'll find
* us at:
* https://www.ilias.de
* https://github.com/ILIAS-eLearning
*
*********************************************************************/

$null_dic = new ILIAS\Core\Dependencies\NullDIC();


$component_0 = new ILIAS\Core\Tests\Dependencies\Scenario1\ComponentA();

$implement_0 = new Pimple\Container();
$use = new Pimple\Container();
$contribute_0 = new Pimple\Container();
$seek = new Pimple\Container();
$provide_0 = new Pimple\Container();
$pull = new Pimple\Container();
$internal = new Pimple\Container();

$component_0->init($null_dic, $implement_0, $use, $contribute_0, $seek, $provide_0, $pull, $internal);
Loading

0 comments on commit fb2f584

Please sign in to comment.