Skip to content

[RFC][WIP] add scaffolding system (make:scaffold) #1085

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

Open
wants to merge 21 commits into
base: 1.x
Choose a base branch
from
Open
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
11 changes: 11 additions & 0 deletions src/FileManager.php
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@

use Symfony\Bundle\MakerBundle\Util\AutoloaderUtil;
use Symfony\Bundle\MakerBundle\Util\MakerFileLinkFormatter;
use Symfony\Bundle\MakerBundle\Util\YamlSourceManipulator;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
@@ -86,6 +87,16 @@ public function dumpFile(string $filename, string $content): void
}
}

/**
* @param callable(array):array $manipulator
*/
public function manipulateYaml(string $filename, callable $manipulator): void
{
$yaml = new YamlSourceManipulator($this->getFileContents($filename));
$yaml->setData($manipulator($yaml->getData()));
$this->dumpFile($filename, $yaml->getContents());
}

public function fileExists($path): bool
{
return file_exists($this->absolutizePath($path));
103 changes: 103 additions & 0 deletions src/JsPackageManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php

/*
* This file is part of the Symfony MakerBundle 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\Bundle\MakerBundle;

use Symfony\Component\Process\ExecutableFinder;
use Symfony\Component\Process\Process;

/**
* @author Kevin Bond <[email protected]>
*/
final class JsPackageManager
{
private $executableFinder;
private $files;

public function __construct(FileManager $fileManager)
{
$this->executableFinder = new ExecutableFinder();
Copy link
Member

Choose a reason for hiding this comment

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

symfony/process is only a dev requirement of MakerBundle at the moment. After installing a fresh Symfony project with this PR's MakerBundle, I get this error when running make:scaffold:

Attempted to load class "ExecutableFinder" from namespace "Symfony\Component\Process".\n
Did you forget a "use" statement for another namespace?

$this->files = $fileManager;
}

public function isInstalled(string $package): bool
{
$packageJson = $this->packageJson();
$deps = array_merge($packageJson['dependencies'] ?? [], $packageJson['devDependencies'] ?? []);

return \array_key_exists($package, $deps);
}

public function add(string $package, string $version): void
{
$packageWithVersion = "{$package}@{$version}";

if ($yarn = $this->executableFinder->find('yarn')) {
$command = [$yarn, 'add', $packageWithVersion, '--dev'];
} elseif ($npm = $this->executableFinder->find('npm')) {
$command = [$npm, 'install', $packageWithVersion, '--save-dev'];
} else {
$this->addToPackageJson($package, $version);

return;
}

(new Process($command, $this->files->getRootDirectory()))->run();
}

public function install(): void
{
(new Process([$this->bin(), 'install'], $this->files->getRootDirectory()))->run();
}

public function run(string $script): void
{
(new Process([$this->bin(), 'run', $script], $this->files->getRootDirectory()))->run();
}

public function isAvailable(): bool
{
try {
$this->bin();

return true;
} catch (\RuntimeException $e) {
return false;
}
}

private function bin(): string
{
if (!$bin = $this->executableFinder->find('yarn') ?? $this->executableFinder->find('npm')) {
throw new \RuntimeException('Unable to find js package manager.');
}

return $bin;
}

private function addToPackageJson(string $package, string $version): void
{
$packageJson = $this->packageJson();
$devDeps = $packageJson['devDependencies'] ?? [];
$devDeps[$package] = $version;

ksort($devDeps);

$packageJson['devDependencies'] = $devDeps;

$this->files->dumpFile('package.json', json_encode($packageJson, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES));
}

private function packageJson(): array
{
return json_decode($this->files->getFileContents('package.json'), true);
}
}
5 changes: 5 additions & 0 deletions src/Maker/MakeRegistrationForm.php
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
@@ -112,6 +113,10 @@ public function configureCommand(Command $command, InputConfiguration $inputConf

public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void
{
if (Kernel::VERSION_ID >= 60000) {
$io->warning('make:registration-form is deprecated in favor of "make:scaffold register".');
}

$interactiveSecurityHelper = new InteractiveSecurityHelper();

if (!$this->fileManager->fileExists($path = 'config/packages/security.yaml')) {
5 changes: 5 additions & 0 deletions src/Maker/MakeResetPassword.php
Original file line number Diff line number Diff line change
@@ -39,6 +39,7 @@
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
@@ -127,6 +128,10 @@ public function configureDependencies(DependencyBuilder $dependencies): void

public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void
{
if (Kernel::VERSION_ID >= 60000) {
$io->warning('make:reset-password is deprecated in favor or "make:scaffold reset-password".');
}

$io->title('Let\'s make a password reset feature!');

$interactiveSecurityHelper = new InteractiveSecurityHelper();
Loading