Skip to content

Commit

Permalink
feat: automatic sorting services in seed file by dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
SergiiTao committed Aug 23, 2020
1 parent 3427275 commit 2109a11
Show file tree
Hide file tree
Showing 4 changed files with 327 additions and 62 deletions.
66 changes: 4 additions & 62 deletions install/class.Setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use oat\oatbox\log\LoggerService;
use oat\oatbox\service\ConfigurableService;
use oat\oatbox\service\ServiceManager;
use oat\tao\model\install\seed\SeedSorter;
use Zend\ServiceManager\ServiceLocatorAwareInterface;

class tao_install_Setup implements Action
Expand All @@ -52,6 +53,7 @@ class tao_install_Setup implements Action
* @throws common_ext_ExtensionException When a presented parameter is invalid or malformed.
* @throws InvalidArgumentException
* @throws tao_install_utils_Exception
* @throws ReflectionException
*/
public function __invoke($params)
{
Expand Down Expand Up @@ -223,12 +225,10 @@ public function __invoke($params)
} elseif (!isset($persistences['type'])) {
throw new InvalidArgumentException('Your config should have a \'default\' key under \'persistences\'');
}

$seedSorter = new SeedSorter();
foreach ($parameters['configuration'] as $extension => $configs) {

$sortedConfigs = $this->sortConfigs($serviceManager, $configs);

var_dump(array_keys($sortedConfigs));
$configs = $seedSorter->sort($configs);

foreach ($configs as $key => $config) {
if (isset($config['type']) && $config['type'] === 'configurableService') {
Expand Down Expand Up @@ -292,64 +292,6 @@ public function __invoke($params)
$this->logNotice('Installation completed!');
}

private function getDependencies(string $className): array
{
$reflection = new ReflectionClass($className);

$constructor = $reflection->getConstructor();

$result = [];

foreach ($constructor->getParameters() as $parameter) {
if ($class = $parameter->getClass()) {
$result[] = $class->name;
}
}

return $result;
}

private function sortDependencies(ServiceManager $serviceManager, array $graph, string $key, array &$result): void
{
echo "> $key\n";
echo ">> {$graph[$key]['class']}\n";

// if (!isset($graph[$key]) || !$serviceManager->get($graph[$key]['class'])) {
// throw new Exception("No '$key' in graph");
// }

if (isset($result[$key])) {
return;
}

if (!isset($graph[$key]['class'])) {
return;
}

$className = $graph[$key]['class'];

$deps = $this->getDependencies($className);

var_dump($deps);

foreach ($deps as $depKey) {
$this->sortDependencies($serviceManager, $graph, $depKey, $result);
}

$result[$key] = $graph[$key];
}

private function sortConfigs(ServiceManager $serviceManager, array $config): array
{
$result = [];

foreach ($config as $key => $value) {
$this->sortDependencies($serviceManager, $config, $key, $result);
}

return $result;
}

/**
* @param string $class
* @param array $parametersToSort
Expand Down
120 changes: 120 additions & 0 deletions models/classes/install/seed/SeedSorter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2020 (original work) Open Assessment Technologies SA;
*
*/

declare(strict_types=1);

namespace oat\tao\model\install\seed;

use ReflectionClass;
use ReflectionException;

class SeedSorter
{
/**
* @throws ReflectionException
*/
public function sort(array $config): array
{
$sortedConfig = [];

foreach ($config as $serviceKey => $serviceConfig) {
$this->sortDependencies($config, $serviceKey, $sortedConfig);
}

return $sortedConfig;
}

/**
* @throws ReflectionException
*/
private function getDependencies(string $className): array
{
$reflection = new ReflectionClass($className);

$constructor = $reflection->getConstructor();

if (null === $constructor) {
return [];
}

$dependencies = [];

foreach ($constructor->getParameters() as $parameter) {
if ($class = $parameter->getClass()) {
$dependencies[] = $class->name;
}
}

return $dependencies;
}

/**
* @throws ReflectionException
*/
private function sortDependencies(array $config, string $serviceKey, array &$result): void
{
if (isset($result[$serviceKey])) {
return;
}

if (!isset($config[$serviceKey]['class'])) {
$result[$serviceKey] = $config[$serviceKey];

return;
}

$serviceClassName = $config[$serviceKey]['class'];

$dependencies = $this->getDependencies($serviceClassName);

foreach ($dependencies as $dependencyClassName) {
try {
$dependencyKey = $this->findServiceKey($config, $dependencyClassName);
$this->sortDependencies($config, $dependencyKey, $result);
} catch (SeedSorterException $e) {
continue;
}
}

$result[$serviceKey] = $config[$serviceKey];
}

private function findServiceKey(array $config, string $className)
{
foreach ($config as $serviceKey => $serviceConfig) {
if (empty($serviceConfig['class'])) {
throw new SeedSorterException(
sprintf('%s not a class', $className)
);
}

if (
$serviceConfig['class'] === $className
|| is_subclass_of($serviceConfig['class'], $className)
) {
return $serviceKey;
}
}

throw new SeedSorterException(
sprintf('Service key for class %s not found', $className)
);
}
}
29 changes: 29 additions & 0 deletions models/classes/install/seed/SeedSorterException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2020 (original work) Open Assessment Technologies SA;
*
*/

declare(strict_types=1);

namespace oat\tao\model\install\seed;

use RuntimeException;

class SeedSorterException extends RuntimeException
{
}
Loading

0 comments on commit 2109a11

Please sign in to comment.