Created
April 16, 2019 14:54
-
-
Save nicolas-grekas/bfdd3c17b40d5be2eb9b36a181e66df4 to your computer and use it in GitHub Desktop.
From Yaml to PHP-DSL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
* This file is part of the Symfony package. | |
* | |
* (c) Fabien Potencier <[email protected]> | |
* | |
* For the full copyright and license information, please view the LICENSE | |
* file that was distributed with this source code. | |
*/ | |
namespace Symfony\Component\DependencyInjection\Dumper; | |
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; | |
use Symfony\Component\DependencyInjection\Argument\IteratorArgument; | |
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; | |
use Symfony\Component\DependencyInjection\Definition; | |
use Symfony\Component\DependencyInjection\ContainerInterface; | |
use Symfony\Component\DependencyInjection\Reference; | |
use Symfony\Component\DependencyInjection\Parameter; | |
use Symfony\Component\DependencyInjection\Exception\RuntimeException; | |
use Symfony\Component\ExpressionLanguage\Expression; | |
use Symfony\Component\Yaml\Tag\TaggedValue; | |
use Symfony\Component\Yaml\Yaml; | |
/** | |
* @author Guilhem Niot <[email protected]> | |
*/ | |
class YamlToDslConverter | |
{ | |
private $uses = array(); | |
/** | |
* Transforms a Yaml config file into a DSL file. | |
* | |
* @param string $yaml | |
* | |
* @return string | |
*/ | |
public function transform($yaml) | |
{ | |
$config = Yaml::parse(file_get_contents($file), Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS); | |
$header = <<<PHP | |
<?php | |
namespace Symfony\Component\DependencyInjection\Loader\Config; | |
PHP; | |
if (null === $config) { | |
return $header; | |
} | |
$code = ''; | |
$previous = null; | |
foreach ($config as $key => $value) { | |
switch ($key) { | |
case 'imports': | |
$code .= $this->dumpImports($value); | |
break; | |
case 'parameters': | |
$code .= $this->dumpParameters($value); | |
break; | |
case 'services': | |
$code .= $this->dumpServices($value); | |
break; | |
default: | |
if (in_array($previous, array('imports', 'parameters', 'services', null))) { | |
$code .= "\n"; | |
} | |
$code .= sprintf("config(%s, %s)\n", $this->dumpValue($key, false), $this->dumpValue($value, false)); | |
break; | |
} | |
$previous = $key; | |
} | |
} | |
private function dumpImports(array $imports) | |
{ | |
if (!$imports) { | |
return ''; | |
} | |
$code = ''; | |
foreach ($imports as $import) { | |
if (!is_array($import)) { | |
$import = array('resource' => $import); | |
} | |
$code .= sprintf("\nimport(%s", $this->dumpValue($import['resource'])); | |
if (isset($import['type']) || isset($import['ignore_errors'])) { | |
$code .= sprintf(', %s', $this->dumpValue(isset($import['type']) ? $import['type'] : null); | |
} | |
if (isset($import['ignore_errors'])) { | |
$code .= sprintf(', %s', $this->dumpValue((bool) $import['ignore_errors'])); | |
} | |
$code .= ');' | |
} | |
return $code."\n"; | |
} | |
private function dumpParameters(array $parameters) | |
{ | |
if (!$parameters) { | |
return ''; | |
} | |
$code = "\nparameters()"; | |
foreach ($parameters as $key => $value) { | |
$code .= sprintf("\n ->add(%s, %s)", $this->dumpValue($key), $this->dumpValue($value)); | |
} | |
return $code."\n;\n"; | |
} | |
private function dumpServices(array $services) | |
{ | |
if (!$services) { | |
return ''; | |
} | |
$code = "\nservices()"; | |
foreach ($services as $id => $definition) { | |
$code .= sprintf("\n ->add(%s, %s)", $this->dumpValue($key), $this->dumpValue($value)); | |
} | |
return $code."\n;\n"; | |
} | |
/** | |
* Dumps values. | |
* | |
* @param mixed $value | |
* @param bool $interpolate | |
* | |
* @return string | |
* | |
* @throws RuntimeException | |
*/ | |
private function dumpValue($value, $interpolate = true) | |
{ | |
if (is_array($value)) { | |
$code = array(); | |
if (array_keys($value) === range(0, count($value))) { | |
foreach ($value as $k => $v) { | |
$code[] = $this->dumpValue($v, $interpolate); | |
} | |
} else { | |
foreach ($value as $k => $v) { | |
$code[] = sprintf('%s => %s', $this->dumpValue($k, false), $this->dumpValue($v, $interpolate)); | |
} | |
} | |
return sprintf('array(%s)', implode(', ', $code)); | |
} elseif ($interpolate && $value instanceof TaggedValue) { | |
if ('iterator' === $value->getTag()) { | |
return sprintf('iter(%s)', $this->dumpValue($value->getValue())); | |
} | |
if ('service' === $value->getTag()) { | |
$definition = $value->getValue(); | |
$code = sprintf('service(%s)', isset($definition['class']) ? $this->dumpValue($definition['class']) : ''; | |
} | |
throw new RuntimeException(sprintf('Unsupported tag "%s".', $value->getTag())); | |
} elseif ($interpolate && $value instanceof Definition) { | |
$code = sprintf('service(%s)', null !== $value->getClass() ? $this->dumpValue($value->getClass()) : ''); | |
$arguments = array(); | |
foreach ($value->getArguments() as $argument) { | |
$arguments[] = $this->dumpValue($argument); | |
} | |
$code .= sprintf('->with(%s)', implode(', ', $arguments)); | |
if (null !== $value->getFactory()) { | |
$code .= sprintf('->factory(%s)', $this->dumpValue($value->getFactory())); | |
} | |
if ($value->isAutowired()) { | |
$code .= '->autowire()'; | |
} | |
if ($value->getTags()) { | |
foreach ($value->getTags() as $name => $tags) { | |
foreach ($tags as $attributes) { | |
$code .= sprintf('->tag(%s%s)', $this->dumpValue($name), ', '.$this->dumpValue($attributes)); | |
} | |
} | |
} | |
if ($value->getFile()) { | |
$code .= sprintf('->file(%s)', $this->dumpValue($value->getFile())); | |
} | |
if ($value->isLazy()) { | |
$code .= '->lazy()'; | |
} | |
return $code; | |
} elseif ($interpolate && is_string($value) && $value && '@' === $value[0]) { | |
if (isset($value[1])) { | |
if ('?' === $value[1]) { | |
return sprintf('ref(%s)->ignoreOnInvalid()', $this->dumpValue(substr($value, 2))); | |
} | |
if ('=' === $value[1]) { | |
return sprintf('expr(%s)', $this->dumpValue(substr($value, 2))); | |
} | |
if ('@' === $value[1]) { | |
return var_export(substr($value, 1), true); | |
} | |
} | |
return sprintf('ref(%s)', $this->dumpValue(substr($value, 1))); | |
} elseif (is_object($value) || is_resource($value)) { | |
throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); | |
} | |
$export = var_export($value, true); | |
if ('NULL' === $export) { | |
return 'null'; | |
} | |
return $export; | |
} | |
/** | |
* Escapes arguments. | |
* | |
* @param array $arguments | |
* | |
* @return array | |
*/ | |
private function escape(array $arguments) | |
{ | |
$args = array(); | |
foreach ($arguments as $k => $v) { | |
if (is_array($v)) { | |
$args[$k] = $this->escape($v); | |
} elseif (is_string($v)) { | |
$args[$k] = str_replace('%', '%%', $v); | |
} else { | |
$args[$k] = $v; | |
} | |
} | |
return $args; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment