Skip to content

Allow generation into sub-namespaces #120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Feb 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
1.1
===

* [BC BREAK] The MakerInterface changed: `writeNextStepsMessage`
was renamed to `writeSuccessMessage`. You should now extend
`AbstractMaker` instead of implementing the interface directly,
and use `parent::writeSuccessMessage()` to get the normal success
message after the command.
* [BC BREAK] The MakerInterface changed: `getParameters()`, `getFiles()`
and `writeNextStepsMessage()` were removed and `generate()` was added
in their place. We recommend extending `AbstractMaker` instead of implementing
the interface directly, and use `$this->writeSuccessMessage()` to get
the normal "success" message after the command.
22 changes: 11 additions & 11 deletions src/Command/MakerCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use Symfony\Bundle\MakerBundle\ConsoleStyle;
use Symfony\Bundle\MakerBundle\DependencyBuilder;
use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException;
use Symfony\Bundle\MakerBundle\ExtraGenerationMakerInterface;
use Symfony\Bundle\MakerBundle\FileManager;
use Symfony\Bundle\MakerBundle\Generator;
use Symfony\Bundle\MakerBundle\InputConfiguration;
use Symfony\Bundle\MakerBundle\MakerInterface;
Expand All @@ -33,16 +33,16 @@
final class MakerCommand extends Command
{
private $maker;
private $generator;
private $fileManager;
private $inputConfig;
/** @var ConsoleStyle */
private $io;
private $checkDependencies = true;

public function __construct(MakerInterface $maker, Generator $generator)
public function __construct(MakerInterface $maker, FileManager $fileManager)
{
$this->maker = $maker;
$this->generator = $generator;
$this->fileManager = $fileManager;
$this->inputConfig = new InputConfiguration();

parent::__construct();
Expand All @@ -56,6 +56,7 @@ protected function configure()
protected function initialize(InputInterface $input, OutputInterface $output)
{
$this->io = new ConsoleStyle($input, $output);
$this->fileManager->setIo($this->io);

if ($this->checkDependencies) {
$dependencies = new DependencyBuilder();
Expand Down Expand Up @@ -86,15 +87,14 @@ protected function interact(InputInterface $input, OutputInterface $output)

protected function execute(InputInterface $input, OutputInterface $output)
{
$this->generator->setIO($this->io);
$params = $this->maker->getParameters($input);
$this->generator->generate($params, $this->maker->getFiles($params));
$generator = new Generator($this->fileManager, 'App\\');

if ($this->maker instanceof ExtraGenerationMakerInterface) {
$this->maker->afterGenerate($this->io, $params);
}
$this->maker->generate($input, $this->io, $generator);

$this->maker->writeSuccessMessage($params, $this->io);
// sanity check for custom makers
if ($generator->hasPendingOperations()) {
throw new \LogicException('Make sure to call the writeChanges() method on the generator.');
}
}

public function setApplication(Application $application = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function process(ContainerBuilder $container)
MakerCommand::class
)->setArguments([
new Reference($id),
new Reference('maker.generator'),
new Reference('maker.file_manager'),
])->addTag('console.command', ['command' => $class::getCommandName()]);
}
}
Expand Down
25 changes: 0 additions & 25 deletions src/ExtraGenerationMakerInterface.php

This file was deleted.

117 changes: 114 additions & 3 deletions src/FileManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Bundle\MakerBundle;

use Composer\Autoload\ClassLoader;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Filesystem\Filesystem;

Expand All @@ -20,17 +21,19 @@
*
* @internal
*/
final class FileManager
class FileManager
{
private $fs;
private $rootDirectory;
/** @var SymfonyStyle */
private $io;

private static $classLoader;

public function __construct(Filesystem $fs, string $rootDirectory)
{
$this->fs = $fs;
$this->rootDirectory = $rootDirectory;
$this->rootDirectory = rtrim($this->realpath($rootDirectory).'/');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there must be a comma, not dot ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, looks like you might be right. Could you open a PR?

}

public function setIO(SymfonyStyle $io)
Expand Down Expand Up @@ -60,11 +63,81 @@ public function fileExists($path): bool

public function relativizePath($absolutePath): string
{
$relativePath = str_replace($this->rootDirectory, '.', $absolutePath);
// see if the path is even in the root
if (false === strpos($absolutePath, $this->rootDirectory)) {
return $absolutePath;
}

$absolutePath = $this->realPath($absolutePath);

$relativePath = ltrim(str_replace($this->rootDirectory, '', $absolutePath), '/');
if (0 === strpos($relativePath, './')) {
$relativePath = substr($relativePath, 2);
}

return is_dir($absolutePath) ? rtrim($relativePath, '/').'/' : $relativePath;
}

public function getPathForFutureClass(string $className)
{
// lookup is obviously modeled off of Composer's autoload logic
foreach ($this->getClassLoader()->getPrefixesPsr4() as $prefix => $paths) {
if (0 === strpos($className, $prefix)) {
$path = $paths[0].'/'.str_replace('\\', '/', str_replace($prefix, '', $className)).'.php';

return $this->relativizePath($path);
}
}

foreach ($this->getClassLoader()->getPrefixes() as $prefix => $paths) {
if (0 === strpos($className, $prefix)) {
$path = $paths[0].'/'.str_replace('\\', '/', $className).'.php';

return $this->relativizePath($path);
}
}

if ($this->getClassLoader()->getFallbackDirsPsr4()) {
$path = $this->getClassLoader()->getFallbackDirsPsr4()[0].'/'.str_replace('\\', '/', $className).'.php';

return $this->relativizePath($path);
}

if ($this->getClassLoader()->getFallbackDirs()) {
$path = $this->getClassLoader()->getFallbackDirs()[0].'/'.str_replace('\\', '/', $className).'.php';

return $this->relativizePath($path);
}

return null;
}

public function getNamespacePrefixForClass(string $className): string
{
foreach ($this->getClassLoader()->getPrefixesPsr4() as $prefix => $paths) {
if (0 === strpos($className, $prefix)) {
return $prefix;
}
}

return '';
}

private function getClassLoader(): ClassLoader
{
if (null === self::$classLoader) {
$autoloadPath = $this->absolutizePath('vendor/autoload.php');

if (!file_exists($autoloadPath)) {
throw new \Exception(sprintf('Could not find the autoload file: "%s"', $autoloadPath));
}

self::$classLoader = require $autoloadPath;
}

return self::$classLoader;
}

private function absolutizePath($path): string
{
if (0 === strpos($path, '/')) {
Expand All @@ -73,4 +146,42 @@ private function absolutizePath($path): string

return sprintf('%s/%s', $this->rootDirectory, $path);
}

/**
* Resolve '../' in paths (like real_path), but for non-existent files.
*
* @param string $absolutePath
*
* @return string
*/
private function realPath($absolutePath): string
{
$finalParts = [];
$currentIndex = -1;

foreach (explode('/', $absolutePath) as $pathPart) {
if ('..' === $pathPart) {
// we need to remove the previous entry
if (-1 === $currentIndex) {
throw new \Exception(sprintf('Problem making path relative - is the path "%s" absolute?', $absolutePath));
}

unset($finalParts[$currentIndex]);
--$currentIndex;

continue;
}

$finalParts[] = $pathPart;
++$currentIndex;
}

$finalPath = implode('/', $finalParts);
// Normalize: // => /
// Normalize: /./ => /
$finalPath = str_replace('//', '/', $finalPath);
$finalPath = str_replace('/./', '/', $finalPath);

return $finalPath;
}
}
Loading