welcome back to dyb-tech
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
|
||||
/**
|
||||
* @author Ryan Weaver <weaverryan@gmail.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class AutoloaderUtil
|
||||
{
|
||||
public function __construct(
|
||||
private ComposerAutoloaderFinder $autoloaderFinder,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the relative path to where a new class should live.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getPathForFutureClass(string $className): ?string
|
||||
{
|
||||
$classLoader = $this->getClassLoader();
|
||||
|
||||
// lookup is obviously modeled off of Composer's autoload logic
|
||||
foreach ($classLoader->getPrefixesPsr4() as $prefix => $paths) {
|
||||
if (str_starts_with($className, $prefix)) {
|
||||
return $paths[0].'/'.str_replace('\\', '/', substr($className, \strlen($prefix))).'.php';
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($classLoader->getPrefixes() as $prefix => $paths) {
|
||||
if (str_starts_with($className, $prefix)) {
|
||||
return $paths[0].'/'.str_replace('\\', '/', $className).'.php';
|
||||
}
|
||||
}
|
||||
|
||||
if ($classLoader->getFallbackDirsPsr4()) {
|
||||
return $classLoader->getFallbackDirsPsr4()[0].'/'.str_replace('\\', '/', $className).'.php';
|
||||
}
|
||||
|
||||
if ($classLoader->getFallbackDirs()) {
|
||||
return $classLoader->getFallbackDirs()[0].'/'.str_replace('\\', '/', $className).'.php';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getNamespacePrefixForClass(string $className): string
|
||||
{
|
||||
foreach ($this->getClassLoader()->getPrefixesPsr4() as $prefix => $paths) {
|
||||
if (str_starts_with($className, $prefix)) {
|
||||
return $prefix;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the namespace is configured by composer autoloader.
|
||||
*/
|
||||
public function isNamespaceConfiguredToAutoload(string $namespace): bool
|
||||
{
|
||||
$namespace = trim($namespace, '\\').'\\';
|
||||
$classLoader = $this->getClassLoader();
|
||||
|
||||
foreach ($classLoader->getPrefixesPsr4() as $prefix => $paths) {
|
||||
if (str_starts_with($namespace, $prefix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($classLoader->getPrefixes() as $prefix => $paths) {
|
||||
if (str_starts_with($namespace, $prefix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getClassLoader(): ClassLoader
|
||||
{
|
||||
return $this->autoloaderFinder->getClassLoader();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class ClassDetails
|
||||
{
|
||||
public function __construct(
|
||||
private string $fullClassName,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of property names except "id" for use in a make:form context.
|
||||
*/
|
||||
public function getFormFields(): array
|
||||
{
|
||||
$properties = $this->getProperties();
|
||||
|
||||
$fields = array_diff($properties, ['id']);
|
||||
|
||||
$fieldsWithTypes = [];
|
||||
foreach ($fields as $field) {
|
||||
$fieldsWithTypes[$field] = null;
|
||||
}
|
||||
|
||||
return $fieldsWithTypes;
|
||||
}
|
||||
|
||||
private function getProperties(): array
|
||||
{
|
||||
$reflect = new \ReflectionClass($this->fullClassName);
|
||||
$props = $reflect->getProperties();
|
||||
|
||||
$propertiesList = [];
|
||||
|
||||
foreach ($props as $prop) {
|
||||
$propertiesList[] = $prop->getName();
|
||||
}
|
||||
|
||||
return $propertiesList;
|
||||
}
|
||||
|
||||
public function getPath(): string
|
||||
{
|
||||
return (new \ReflectionClass($this->fullClassName))->getFileName();
|
||||
}
|
||||
|
||||
public function hasAttribute(string $attributeClassName): bool
|
||||
{
|
||||
$reflected = new \ReflectionClass($this->fullClassName);
|
||||
|
||||
foreach ($reflected->getAttributes($attributeClassName) as $reflectedAttribute) {
|
||||
if ($reflectedAttribute->getName() === $attributeClassName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
use Symfony\Bundle\MakerBundle\Str;
|
||||
|
||||
final class ClassNameDetails
|
||||
{
|
||||
public function __construct(
|
||||
private string $fullClassName,
|
||||
private string $namespacePrefix,
|
||||
private ?string $suffix = null,
|
||||
) {
|
||||
$this->namespacePrefix = trim($namespacePrefix, '\\');
|
||||
}
|
||||
|
||||
public function getFullName(): string
|
||||
{
|
||||
return $this->fullClassName;
|
||||
}
|
||||
|
||||
public function getShortName(): string
|
||||
{
|
||||
return Str::getShortClassName($this->fullClassName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the original class name the user entered (after
|
||||
* being cleaned up).
|
||||
*
|
||||
* For example, assuming the namespace is App\Entity:
|
||||
* App\Entity\Admin\User => Admin\User
|
||||
*/
|
||||
public function getRelativeName(): string
|
||||
{
|
||||
return str_replace($this->namespacePrefix.'\\', '', $this->fullClassName);
|
||||
}
|
||||
|
||||
public function getRelativeNameWithoutSuffix(): string
|
||||
{
|
||||
return Str::removeSuffix($this->getRelativeName(), $this->suffix);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
use Symfony\Bundle\MakerBundle\Str;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class ClassNameValue implements \Stringable
|
||||
{
|
||||
public function __construct(
|
||||
private string $typeHint,
|
||||
private string $fullClassName,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getShortName(): string
|
||||
{
|
||||
if ($this->isSelf()) {
|
||||
return Str::getShortClassName($this->fullClassName);
|
||||
}
|
||||
|
||||
return $this->typeHint;
|
||||
}
|
||||
|
||||
public function isSelf(): bool
|
||||
{
|
||||
return 'self' === $this->typeHint;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->getShortName();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
/**
|
||||
* Tools used to enhance maker command output.
|
||||
*
|
||||
* For additional context with Symfony CLI EnvVars, see
|
||||
* https://github.com/symfony-cli/symfony-cli/pull/231
|
||||
*
|
||||
* @author Jesse Rushlow <jr@rushlow.dev>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class CliOutputHelper
|
||||
{
|
||||
/**
|
||||
* EnvVars exposed by Symfony's CLI.
|
||||
*/
|
||||
public const ENV_VERSION = 'SYMFONY_CLI_VERSION'; // Current CLI Version
|
||||
public const ENV_BIN_NAME = 'SYMFONY_CLI_BINARY_NAME'; // Name of the binary e.g. "symfony"
|
||||
|
||||
/**
|
||||
* Get the correct command prefix based on Symfony CLI usage.
|
||||
*/
|
||||
public static function getCommandPrefix(): string
|
||||
{
|
||||
$prompt = 'php bin/console';
|
||||
|
||||
$binaryNameEnvVar = getenv(self::ENV_BIN_NAME);
|
||||
|
||||
if (false !== $binaryNameEnvVar && false !== getenv(self::ENV_VERSION)) {
|
||||
$prompt = sprintf('%s console', $binaryNameEnvVar);
|
||||
}
|
||||
|
||||
return $prompt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException;
|
||||
use Symfony\Component\Yaml\Dumper;
|
||||
|
||||
/**
|
||||
* Manipulate Docker Compose Files.
|
||||
*
|
||||
* @author Jesse Rushlow <jr@rushlow.dev>
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class ComposeFileManipulator
|
||||
{
|
||||
public const COMPOSE_FILE_VERSION = '3.7';
|
||||
|
||||
private YamlSourceManipulator $manipulator;
|
||||
|
||||
public function __construct(string $contents)
|
||||
{
|
||||
if ('' === $contents) {
|
||||
$this->manipulator = new YamlSourceManipulator(
|
||||
(new Dumper())->dump($this->getBasicStructure(), 2)
|
||||
);
|
||||
} else {
|
||||
$this->manipulator = new YamlSourceManipulator($contents);
|
||||
}
|
||||
|
||||
$this->checkComposeFileVersion();
|
||||
}
|
||||
|
||||
public function getComposeData(): array
|
||||
{
|
||||
return $this->manipulator->getData();
|
||||
}
|
||||
|
||||
public function getDataString(): string
|
||||
{
|
||||
return $this->manipulator->getContents();
|
||||
}
|
||||
|
||||
public function serviceExists(string $name): bool
|
||||
{
|
||||
$data = $this->manipulator->getData();
|
||||
|
||||
if (\array_key_exists('services', $data)) {
|
||||
return \array_key_exists($name, $data['services']);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function addDockerService(string $name, array $details): void
|
||||
{
|
||||
$data = $this->manipulator->getData();
|
||||
|
||||
$data['services'][$name] = $details;
|
||||
|
||||
$this->manipulator->setData($data);
|
||||
}
|
||||
|
||||
public function removeDockerService(string $name): void
|
||||
{
|
||||
$data = $this->manipulator->getData();
|
||||
|
||||
unset($data['services'][$name]);
|
||||
|
||||
$this->manipulator->setData($data);
|
||||
}
|
||||
|
||||
public function exposePorts(string $service, array $ports): void
|
||||
{
|
||||
$portData = [];
|
||||
$portData[] = sprintf('%s To allow the host machine to access the ports below, modify the lines below.', YamlSourceManipulator::COMMENT_PLACEHOLDER_VALUE);
|
||||
$portData[] = sprintf('%s For example, to allow the host to connect to port 3306 on the container, you would change', YamlSourceManipulator::COMMENT_PLACEHOLDER_VALUE);
|
||||
$portData[] = sprintf('%s "3306" to "3306:3306". Where the first port is exposed to the host and the second is the container port.', YamlSourceManipulator::COMMENT_PLACEHOLDER_VALUE);
|
||||
$portData[] = sprintf('%s See https://docs.docker.com/compose/compose-file/compose-file-v3/#ports for more information.', YamlSourceManipulator::COMMENT_PLACEHOLDER_VALUE);
|
||||
|
||||
foreach ($ports as $port) {
|
||||
$portData[] = $port;
|
||||
}
|
||||
|
||||
$data = $this->manipulator->getData();
|
||||
|
||||
$data['services'][$service]['ports'] = $portData;
|
||||
|
||||
$this->manipulator->setData($data);
|
||||
}
|
||||
|
||||
public function addVolume(string $service, string $hostPath, string $containerPath): void
|
||||
{
|
||||
$data = $this->manipulator->getData();
|
||||
|
||||
$data['services'][$service]['volumes'][] = sprintf('%s:%s', $hostPath, $containerPath);
|
||||
|
||||
$this->manipulator->setData($data);
|
||||
}
|
||||
|
||||
private function getBasicStructure(string $version = self::COMPOSE_FILE_VERSION): array
|
||||
{
|
||||
return [
|
||||
'version' => $version,
|
||||
'services' => [],
|
||||
];
|
||||
}
|
||||
|
||||
private function checkComposeFileVersion(): void
|
||||
{
|
||||
$data = $this->manipulator->getData();
|
||||
|
||||
if (empty($data['version'])) {
|
||||
throw new RuntimeCommandException('compose.yaml file version is not set.');
|
||||
}
|
||||
|
||||
if (2.0 > (float) $data['version']) {
|
||||
throw new RuntimeCommandException(sprintf('compose.yaml version %s is not supported. Please update your compose.yaml file to the latest version.', $data['version']));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Symfony\Component\Debug\DebugClassLoader;
|
||||
use Symfony\Component\ErrorHandler\DebugClassLoader as ErrorHandlerDebugClassLoader;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ComposerAutoloaderFinder
|
||||
{
|
||||
private array $rootNamespace;
|
||||
private ?ClassLoader $classLoader = null;
|
||||
|
||||
public function __construct(string $rootNamespace)
|
||||
{
|
||||
$this->rootNamespace = [
|
||||
'psr0' => rtrim($rootNamespace, '\\'),
|
||||
'psr4' => rtrim($rootNamespace, '\\').'\\',
|
||||
];
|
||||
}
|
||||
|
||||
public function getClassLoader(): ClassLoader
|
||||
{
|
||||
if (null === $this->classLoader) {
|
||||
$this->classLoader = $this->findComposerClassLoader();
|
||||
}
|
||||
|
||||
if (null === $this->classLoader) {
|
||||
throw new \Exception("Could not find a Composer autoloader that autoloads from '{$this->rootNamespace['psr4']}'");
|
||||
}
|
||||
|
||||
return $this->classLoader;
|
||||
}
|
||||
|
||||
private function findComposerClassLoader(): ?ClassLoader
|
||||
{
|
||||
$autoloadFunctions = spl_autoload_functions();
|
||||
|
||||
foreach ($autoloadFunctions as $autoloader) {
|
||||
if (!\is_array($autoloader)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classLoader = $this->extractComposerClassLoader($autoloader);
|
||||
if (null === $classLoader) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$finalClassLoader = $this->locateMatchingClassLoader($classLoader);
|
||||
if (null !== $finalClassLoader) {
|
||||
return $finalClassLoader;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function extractComposerClassLoader(array $autoloader): ?ClassLoader
|
||||
{
|
||||
if (isset($autoloader[0]) && \is_object($autoloader[0])) {
|
||||
if ($autoloader[0] instanceof ClassLoader) {
|
||||
return $autoloader[0];
|
||||
}
|
||||
if (
|
||||
($autoloader[0] instanceof DebugClassLoader
|
||||
|| $autoloader[0] instanceof ErrorHandlerDebugClassLoader)
|
||||
&& \is_array($autoloader[0]->getClassLoader())
|
||||
&& $autoloader[0]->getClassLoader()[0] instanceof ClassLoader) {
|
||||
return $autoloader[0]->getClassLoader()[0];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function locateMatchingClassLoader(ClassLoader $classLoader): ?ClassLoader
|
||||
{
|
||||
$makerClassLoader = null;
|
||||
foreach ($classLoader->getPrefixesPsr4() as $prefix => $paths) {
|
||||
if ('Symfony\\Bundle\\MakerBundle\\' === $prefix) {
|
||||
$makerClassLoader = $classLoader;
|
||||
}
|
||||
if (str_starts_with($this->rootNamespace['psr4'], $prefix)) {
|
||||
return $classLoader;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($classLoader->getPrefixes() as $prefix => $paths) {
|
||||
if (str_starts_with($this->rootNamespace['psr0'], $prefix)) {
|
||||
return $classLoader;
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing found? Try the class loader where we found MakerBundle
|
||||
return $makerClassLoader;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
||||
use Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter;
|
||||
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter as LegacyFileLinkFormatter;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class MakerFileLinkFormatter
|
||||
{
|
||||
public function __construct(
|
||||
private FileLinkFormatter|LegacyFileLinkFormatter|null $fileLinkFormatter = null,
|
||||
) {
|
||||
}
|
||||
|
||||
public function makeLinkedPath(string $absolutePath, string $relativePath): string
|
||||
{
|
||||
if (!$this->fileLinkFormatter) {
|
||||
return $relativePath;
|
||||
}
|
||||
|
||||
if (!$formatted = $this->fileLinkFormatter->format($absolutePath, 1)) {
|
||||
return $relativePath;
|
||||
}
|
||||
|
||||
// workaround for difficulties parsing linked file paths in appveyor
|
||||
if (getenv('MAKER_DISABLE_FILE_LINKS')) {
|
||||
return $relativePath;
|
||||
}
|
||||
|
||||
$outputFormatterStyle = new OutputFormatterStyle();
|
||||
|
||||
if (method_exists(OutputFormatterStyle::class, 'setHref')) {
|
||||
$outputFormatterStyle->setHref($formatted);
|
||||
}
|
||||
|
||||
return $outputFormatterStyle->apply($relativePath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
use Symfony\Bundle\MakerBundle\FileManager;
|
||||
|
||||
/**
|
||||
* @author Jesse Rushlow <jr@rushlow.dev>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class PhpCompatUtil
|
||||
{
|
||||
public function __construct(private FileManager $fileManager)
|
||||
{
|
||||
}
|
||||
|
||||
protected function getPhpVersion(): string
|
||||
{
|
||||
$rootDirectory = $this->fileManager->getRootDirectory();
|
||||
|
||||
$composerLockPath = sprintf('%s/composer.lock', $rootDirectory);
|
||||
|
||||
if (!$this->fileManager->fileExists($composerLockPath)) {
|
||||
return \PHP_VERSION;
|
||||
}
|
||||
|
||||
$lockFileContents = json_decode($this->fileManager->getFileContents($composerLockPath), true);
|
||||
|
||||
if (empty($lockFileContents['platform-overrides']) || empty($lockFileContents['platform-overrides']['php'])) {
|
||||
return \PHP_VERSION;
|
||||
}
|
||||
|
||||
return $lockFileContents['platform-overrides']['php'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\PrettyPrinter\Standard;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class PrettyPrinter extends Standard
|
||||
{
|
||||
/**
|
||||
* Overridden to fix indentation problem with tabs.
|
||||
*
|
||||
* If the original source code uses tabs, then the tokenizer
|
||||
* will see this as "1" indent level, and will indent new lines
|
||||
* with just 1 space. By changing 1 indent to 4, we effectively
|
||||
* "correct" this problem when printing.
|
||||
*
|
||||
* For code that is even further indented (e.g. 8 spaces),
|
||||
* the printer uses the first indentation (here corrected
|
||||
* from 1 space to 4) and already (without needing any other
|
||||
* changes) adds 4 spaces onto that. This is why we don't
|
||||
* also need to handle indent levels of 5, 9, etc: these
|
||||
* do not occur (at least in the code we generate);
|
||||
*/
|
||||
protected function setIndentLevel(int $level): void
|
||||
{
|
||||
if (1 === $level) {
|
||||
$level = 4;
|
||||
}
|
||||
|
||||
parent::setIndentLevel($level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden to change coding standards.
|
||||
*
|
||||
* Before:
|
||||
* public function getFoo() : string
|
||||
*
|
||||
* After
|
||||
* public function getFoo(): string
|
||||
*/
|
||||
protected function pStmt_ClassMethod(Stmt\ClassMethod $node): string
|
||||
{
|
||||
$classMethod = parent::pStmt_ClassMethod($node);
|
||||
|
||||
if ($node->returnType) {
|
||||
$classMethod = str_replace(') :', '):', $classMethod);
|
||||
}
|
||||
|
||||
return $classMethod;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
/**
|
||||
* @author Jesse Rushlow <jr@rushlow.dev>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class TemplateComponentGenerator
|
||||
{
|
||||
public function generateRouteForControllerMethod(string $routePath, string $routeName, array $methods = [], bool $indent = true, bool $trailingNewLine = true): string
|
||||
{
|
||||
$attribute = sprintf('%s#[Route(\'%s\', name: \'%s\'', $indent ? ' ' : null, $routePath, $routeName);
|
||||
|
||||
if (!empty($methods)) {
|
||||
$attribute .= ', methods: [';
|
||||
|
||||
foreach ($methods as $method) {
|
||||
$attribute .= sprintf('\'%s\', ', $method);
|
||||
}
|
||||
|
||||
$attribute = rtrim($attribute, ', ');
|
||||
|
||||
$attribute .= ']';
|
||||
}
|
||||
|
||||
$attribute .= sprintf(')]%s', $trailingNewLine ? "\n" : null);
|
||||
|
||||
return $attribute;
|
||||
}
|
||||
|
||||
public function getPropertyType(ClassNameDetails $classNameDetails): ?string
|
||||
{
|
||||
return sprintf('%s ', $classNameDetails->getShortName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Process\ExecutableFinder;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
/**
|
||||
* Linters used by make:* commands to cleanup the generated files.
|
||||
*
|
||||
* @author Jesse Rushlow <jr@rushlow.dev>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class TemplateLinter
|
||||
{
|
||||
private bool $usingBundledPhpCsFixer = true;
|
||||
private bool $usingBundledPhpCsFixerConfig = true;
|
||||
private bool $needsPhpCmdPrefix = true;
|
||||
|
||||
public function __construct(
|
||||
private ?string $phpCsFixerBinaryPath = null,
|
||||
private ?string $phpCsFixerConfigPath = null,
|
||||
) {
|
||||
$this->setBinary();
|
||||
$this->setConfig();
|
||||
}
|
||||
|
||||
public function lintFiles(array $templateFilePaths): void
|
||||
{
|
||||
$phpFiles = [];
|
||||
|
||||
foreach ($templateFilePaths as $filePath) {
|
||||
if (str_ends_with($filePath, '.php')) {
|
||||
$phpFiles[] = $filePath;
|
||||
}
|
||||
}
|
||||
|
||||
$this->lintPhpTemplate($phpFiles);
|
||||
}
|
||||
|
||||
public function lintPhpTemplate(string|array $templateFilePath): void
|
||||
{
|
||||
if (\is_string($templateFilePath)) {
|
||||
$templateFilePath = [$templateFilePath];
|
||||
}
|
||||
|
||||
foreach ($templateFilePath as $filePath) {
|
||||
$cmdPrefix = $this->needsPhpCmdPrefix ? 'php ' : '';
|
||||
|
||||
$process = Process::fromShellCommandline(sprintf('PHP_CS_FIXER_IGNORE_ENV=1 %s%s --config=%s --using-cache=no fix %s', $cmdPrefix, $this->phpCsFixerBinaryPath, $this->phpCsFixerConfigPath, $filePath));
|
||||
|
||||
$process->run();
|
||||
}
|
||||
}
|
||||
|
||||
public function writeLinterMessage(OutputInterface $output): void
|
||||
{
|
||||
$output->writeln('Linting Generated Files With:');
|
||||
|
||||
$fixerMessage = $this->usingBundledPhpCsFixer ?
|
||||
'Bundled PHP-CS-Fixer & ' :
|
||||
sprintf('System PHP-CS-Fixer (<info>%s</info>) & ', $this->phpCsFixerBinaryPath)
|
||||
|
||||
;
|
||||
|
||||
$fixerMessage .= $this->usingBundledPhpCsFixerConfig ?
|
||||
'Bundled PHP-CS-Fixer Configuration' :
|
||||
sprintf('System PHP-CS-Fixer Configuration (<info>%s</info>)', $this->phpCsFixerConfigPath)
|
||||
;
|
||||
|
||||
$output->writeln([$fixerMessage, '']); // Empty string so we have an empty line
|
||||
}
|
||||
|
||||
private function setBinary(): void
|
||||
{
|
||||
// Use Bundled PHP-CS-Fixer
|
||||
if (null === $this->phpCsFixerBinaryPath) {
|
||||
$this->phpCsFixerBinaryPath = \dirname(__DIR__).'/Resources/bin/php-cs-fixer-v3.13.0.phar';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Path to PHP-CS-Fixer provided
|
||||
if (is_file($this->phpCsFixerBinaryPath)) {
|
||||
$this->usingBundledPhpCsFixer = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// PHP-CS-Fixer in the system path?
|
||||
if (null !== $path = (new ExecutableFinder())->find($this->phpCsFixerBinaryPath)) {
|
||||
$this->phpCsFixerBinaryPath = $path;
|
||||
|
||||
$this->needsPhpCmdPrefix = false;
|
||||
$this->usingBundledPhpCsFixer = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// PHP-CS-Fixer provided is not a file and is not in the system path.
|
||||
throw new RuntimeCommandException(sprintf('The MAKER_PHP_CS_FIXER_BINARY_PATH provided: %s does not exist.', $this->phpCsFixerBinaryPath));
|
||||
}
|
||||
|
||||
private function setConfig(): void
|
||||
{
|
||||
// No config provided, but there is a dist config file in the project dir
|
||||
if (null === $this->phpCsFixerConfigPath && file_exists($defaultConfigPath = '.php-cs-fixer.dist.php')) {
|
||||
$this->phpCsFixerConfigPath = $defaultConfigPath;
|
||||
|
||||
$this->usingBundledPhpCsFixerConfig = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// No config provided and no project dist config - use our config
|
||||
if (null === $this->phpCsFixerConfigPath) {
|
||||
$this->phpCsFixerConfigPath = \dirname(__DIR__).'/Resources/config/php-cs-fixer.config.php';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// The config path provided doesn't exist...
|
||||
if (!file_exists($this->phpCsFixerConfigPath)) {
|
||||
throw new RuntimeCommandException(sprintf('The MAKER_PHP_CS_FIXER_CONFIG_PATH provided: %s does not exist.', $this->phpCsFixerConfigPath));
|
||||
}
|
||||
|
||||
$this->usingBundledPhpCsFixerConfig = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
/**
|
||||
* Converts fully qualified class names into sorted use statements for templates.
|
||||
*
|
||||
* @author Jesse Rushlow <jr@rushlow.dev>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class UseStatementGenerator implements \Stringable
|
||||
{
|
||||
/**
|
||||
* For use statements that contain aliases, the $classesToBeImported array
|
||||
* may contain an array(s) like [\Some\Class::class => 'ZYX']. The generated
|
||||
* use statement would appear as "use Some\Class::class as 'ZXY'". It is ok
|
||||
* to mix non-aliases classes with aliases.
|
||||
*
|
||||
* @param string[]|array<string, string> $classesToBeImported
|
||||
*/
|
||||
public function __construct(
|
||||
private array $classesToBeImported,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$transformed = [];
|
||||
$aliases = [];
|
||||
|
||||
foreach ($this->classesToBeImported as $key => $class) {
|
||||
if (\is_array($class)) {
|
||||
$aliasClass = key($class);
|
||||
$aliases[$aliasClass] = $class[$aliasClass];
|
||||
$class = $aliasClass;
|
||||
}
|
||||
|
||||
$transformedClass = str_replace('\\', ' ', $class);
|
||||
// Let's not add the class again if it already exists.
|
||||
if (!\in_array($transformedClass, $transformed, true)) {
|
||||
$transformed[$key] = $transformedClass;
|
||||
}
|
||||
}
|
||||
|
||||
asort($transformed);
|
||||
|
||||
$statements = '';
|
||||
|
||||
foreach ($transformed as $key => $class) {
|
||||
$importedClass = $this->classesToBeImported[$key];
|
||||
|
||||
if (!\is_array($importedClass)) {
|
||||
$statements .= sprintf("use %s;\n", $importedClass);
|
||||
continue;
|
||||
}
|
||||
|
||||
$aliasClass = key($importedClass);
|
||||
$statements .= sprintf("use %s as %s;\n", $aliasClass, $aliases[$aliasClass]);
|
||||
}
|
||||
|
||||
return $statements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|string[]|array<string, string> $className
|
||||
*/
|
||||
public function addUseStatement(array|string $className): void
|
||||
{
|
||||
if (\is_array($className)) {
|
||||
$this->classesToBeImported = array_merge($this->classesToBeImported, $className);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's not add the class again if it already exists.
|
||||
if (\in_array($className, $this->classesToBeImported, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->classesToBeImported[] = $className;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony MakerBundle package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\MakerBundle\Util;
|
||||
|
||||
/**
|
||||
* Thrown whenever YamlSourceManipulator cannot change contents successfully.
|
||||
*/
|
||||
class YamlManipulationFailedException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user