Skip to content

Commit

Permalink
Component/Dependencies: Render Resolved Tree in PHP
Browse files Browse the repository at this point in the history
  • Loading branch information
klees committed Nov 24, 2023
1 parent c00c986 commit 090ca0d
Show file tree
Hide file tree
Showing 21 changed files with 907 additions and 25 deletions.
5 changes: 5 additions & 0 deletions components/ILIAS/Component/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/Component/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/Component/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/Component/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/Component/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/Component/src/Dependencies/Out.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,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
58 changes: 58 additions & 0 deletions components/ILIAS/Component/src/Dependencies/RenamingDIC.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?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;

/**
* A wrapper around another DIC that superficially adds a _# and passes them to an
* underlying DIC. # is a counter over all objects that have been added, starting
* by 0.
*/
class RenamingDIC implements \ArrayAccess
{
protected int $counter = 0;

public function __construct(
protected \ArrayAccess $wrapped
) {
}

public function offsetSet($id, $value): void
{
$id = "{$id}_{$this->counter}";
$this->counter++;
$this->wrapped->offsetSet($id, $value);
}

public function offsetGet($id): mixed
{
return $this->wrapped->offsetGet($id);
}

public function offsetExists($id): bool
{
return $this->wrapped->offsetExists($id);
}

public function offsetUnset($id): void
{
$this->wrapped->offsetUnset($id);
}
}
148 changes: 148 additions & 0 deletions components/ILIAS/Component/src/Dependencies/Renderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<?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()];
$use = $this->renderUse($component_lookup, $component);
$seek = $this->renderSeek($component_lookup, $component);
$pull = $this->renderPull($component_lookup, $component);
return <<<PHP
\$component_$me = new {$component->getComponentName()}();
\$implement_$me = new ILIAS\Core\Dependencies\RenamingDIC(new Pimple\Container());
\$use = new Pimple\Container();{$use}
\$contribute_$me = new Pimple\Container();
\$seek = new Pimple\Container();{$seek}
\$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;
}

protected function renderUse(array $component_lookup, OfComponent $component): string
{
$use = "";
foreach ($component->getInDependenciesOf(InType::USE) as $in) {
$r = $in->getResolvedBy()[0];
$p = $r->aux["position"];
$o = $component_lookup[$r->getComponent()->getComponentName()];
$use .= "\n" . <<<PHP
\$use[{$in->getName()}::class] = fn() => \$implement_{$o}[{$r->getName()}::class . "_{$p}"];
PHP;
}
return $use;
}

protected function renderSeek(array $component_lookup, OfComponent $component): string
{
$seek = "";
foreach ($component->getInDependenciesOf(InType::SEEK) as $in) {
$rs = $in->getResolvedBy();
$u = [];
$a = "";
foreach ($rs as $r) {
$p = $r->aux["position"];
$o = $component_lookup[$r->getComponent()->getComponentName()];
$u[] = "\$contribute_{$o}";
$a .= "\n" . <<<PHP
\$contribute_{$o}[{$r->getName()}::class . "_{$p}"],
PHP;
}
$u = join(", ", array_unique($u));
$seek .= "\n" . <<<PHP
\$seek[{$in->getName()}::class] = function () use ({$u}) {
return [{$a}
];
};
PHP;
}
return $seek;
}

protected function renderPull(array $component_lookup, OfComponent $component): string
{
$pull = "";
foreach ($component->getInDependenciesOf(InType::PULL) as $in) {
$r = $in->getResolvedBy()[0];
$o = $component_lookup[$r->getComponent()->getComponentName()];
$pull .= "\n" . <<<PHP
\$pull[{$in->getName()}::class] = fn() => \$provide_{$o}[{$r->getName()}::class];
PHP;
}
return $pull;
}
}
2 changes: 1 addition & 1 deletion components/ILIAS/Component/src/Dependencies/Resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ protected function resolveUse(OfComponent $component, array &$disambiguation, In
);
}
foreach ($candidates as $candidate) {
if ($candidate->class === $preferred_class) {
if ($candidate->aux["class"] === $preferred_class) {
$in->addResolution($candidate);
return;
}
Expand Down
33 changes: 33 additions & 0 deletions components/ILIAS/Component/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);
}
}
Loading

0 comments on commit 090ca0d

Please sign in to comment.