Skip to content
This repository was archived by the owner on Jan 6, 2020. It is now read-only.

Update generate:bundle for non-shared bundles and more #312

Merged
merged 43 commits into from
Mar 23, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
778caf2
[DX] Re-work generate:bundle for simple app bundles #290
rafix Aug 23, 2014
ac39c7a
patch applied
rafix Aug 23, 2014
f541d16
fix test errors in Tests/Command/GenerateBundleCommandTest.php
rafix Aug 23, 2014
1d4600c
[WIP] more on test
rafix Aug 23, 2014
763e2f1
more on test
rafix Aug 23, 2014
5f4d06c
docs fixed
rafix Aug 23, 2014
5f3233b
droped shared element from parameters array in Generator/BundleGenera…
rafix Aug 23, 2014
8e4e023
shared option set to false by default
rafix Aug 23, 2014
1b5f7fb
[WIP] optional vendor's name
rafix Aug 23, 2014
bc058c7
= false in generate method :)
rafix Aug 23, 2014
3d65d3c
better explanation for --shared option
rafix Oct 7, 2014
4af1618
CS fix
rafix Oct 7, 2014
42c32d4
Very minor code tweaks (no functional stuff)
weaverryan Nov 19, 2014
ad28da8
Major overhaul of the interaction part of the generate:bundle command
weaverryan Nov 19, 2014
f0d0b95
Tweaks thanks to @javiereguiluz
weaverryan Nov 19, 2014
bfd1916
Fixing coding standards
weaverryan Nov 19, 2014
a55f65f
Adding line breaks, but no changes
weaverryan Nov 19, 2014
e388b40
Fixing bug that caused paths to be missing a slash
weaverryan Nov 19, 2014
e935050
fixing a bug where we'd ask shared even if it were passed as false
weaverryan Nov 19, 2014
5537e9c
Revert "fixing a bug where we'd ask shared even if it were passed as …
weaverryan Nov 19, 2014
e7645da
Improving error message on the validator - just a bit more helpful wh…
weaverryan Nov 19, 2014
5fa687a
Fixing a number of tests!
weaverryan Nov 19, 2014
955fae6
Fixing code standards
weaverryan Nov 19, 2014
48ced20
Removing an old, unused method
weaverryan Nov 25, 2014
7a6033b
Adding a Bundle model object to help centralize its metadata
weaverryan Nov 25, 2014
7a41f5c
Adding the ability to import a configuration file from app/config/con…
weaverryan Nov 25, 2014
cb4b1b9
Tweaking language based on comment from @samsonasik
weaverryan Nov 25, 2014
8a768ac
Fixing bad base class for test
weaverryan Nov 25, 2014
de0c682
Fixing test by using new Bundle object
weaverryan Nov 25, 2014
c66ed09
Fixing bad indentation (caught by tests!)
weaverryan Nov 25, 2014
5ae77db
Fixing another test now that the Bundle object is being passed
weaverryan Nov 25, 2014
89d3ee6
Fixing coding standards
weaverryan Nov 26, 2014
c5785e4
Trying to fix my rebase
weaverryan Mar 23, 2015
baab95e
Cleaning some things up and changing the behavior to ask questions ev…
weaverryan Mar 23, 2015
ae3db97
Fixing default value to be dependent on the "shared" value
weaverryan Mar 23, 2015
079250f
Not asking for the bundle if you're in non-shared mode - it was askin…
weaverryan Mar 23, 2015
2673bb4
Fixing wrong separator for namespace
weaverryan Mar 23, 2015
a802785
Displaying path to AppKernel in messaging
weaverryan Mar 23, 2015
8ee423b
Fixing a bug where we required the vendor namespace in the exact wron…
weaverryan Mar 23, 2015
1dd31e3
Removing an extra / in the target directory (was ok, but looked bad i…
weaverryan Mar 23, 2015
483ab4b
Coding standards
weaverryan Mar 23, 2015
712235e
updating the test because we now ALWAYS ask questions, unless you pas…
weaverryan Mar 23, 2015
e632cb8
Removing docs for now-gone option
weaverryan Mar 23, 2015
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
418 changes: 229 additions & 189 deletions Command/GenerateBundleCommand.php

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Command/Helper/QuestionHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ class QuestionHelper extends BaseQuestionHelper
public function writeGeneratorSummary(OutputInterface $output, $errors)
{
if (!$errors) {
$this->writeSection($output, 'You can now start using the generated code!');
$this->writeSection($output, 'Everything is OK! Now get to work :).');
} else {
$this->writeSection($output, array(
'The command was not able to configure everything automatically.',
'You must do the following changes manually.',
'You\'ll need to make the following changes manually.',
), 'error');

$output->writeln($errors);
Expand All @@ -43,7 +43,7 @@ public function getRunner(OutputInterface $output, &$errors)
$output->writeln('<fg=red>FAILED</>');
$errors = array_merge($errors, $err);
} else {
$output->writeln('<info>OK</info>');
$output->writeln('<comment>OK!</comment>');
}
};

Expand Down
28 changes: 20 additions & 8 deletions Command/Validators.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@
*/
class Validators
{
/**
* Validates that the given namespace (e.g. Acme\FooBundle) is a valid format
*
* If $requireVendorNamespace is true, then we require you to have a vendor
* namespace (e.g. Acme).
*
* @param $namespace
* @param bool $requireVendorNamespace
* @return string
*/
public static function validateBundleNamespace($namespace, $requireVendorNamespace = true)
{
if (!preg_match('/Bundle$/', $namespace)) {
Expand All @@ -39,7 +49,6 @@ public static function validateBundleNamespace($namespace, $requireVendorNamespa

// validate that the namespace is at least one level deep
if ($requireVendorNamespace && false === strpos($namespace, '\\')) {
// language is (almost) duplicated in GenerateBundleCommand
$msg = array();
$msg[] = sprintf('The namespace must contain a vendor namespace (e.g. "VendorName\%s" instead of simply "%s").', $namespace, $namespace);
$msg[] = 'If you\'ve specified a vendor namespace, did you forget to surround it with quotes (init:bundle "Acme\BlogBundle")?';
Expand All @@ -53,7 +62,7 @@ public static function validateBundleNamespace($namespace, $requireVendorNamespa
public static function validateBundleName($bundle)
{
if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $bundle)) {
throw new \InvalidArgumentException('The bundle name contains invalid characters.');
throw new \InvalidArgumentException(sprintf('The bundle name %s contains invalid characters.', $bundle));
}

if (!preg_match('/Bundle$/', $bundle)) {
Expand All @@ -79,16 +88,19 @@ public static function validateControllerName($controller)
return $controller;
}

public static function validateTargetDir($dir, $bundle, $namespace)
{
// add trailing / if necessary
return '/' === substr($dir, -1, 1) ? $dir : $dir.'/';
}

public static function validateFormat($format)
{
if (!$format) {
throw new \RuntimeException('Please enter a configuration format.');
}

$format = strtolower($format);

// in case they typed "yaml", but ok with that
if ($format == 'yaml') {
$format = 'yml';
}

if (!in_array($format, array('php', 'xml', 'yml', 'annotation'))) {
throw new \RuntimeException(sprintf('Format "%s" is not supported.', $format));
}
Expand Down
55 changes: 25 additions & 30 deletions Generator/BundleGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

namespace Sensio\Bundle\GeneratorBundle\Generator;

use Sensio\Bundle\GeneratorBundle\Model\Bundle;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\DependencyInjection\Container;

/**
* Generates a bundle.
Expand All @@ -28,9 +28,10 @@ public function __construct(Filesystem $filesystem)
$this->filesystem = $filesystem;
}

public function generate($namespace, $bundle, $dir, $format, $structure)
public function generateBundle(Bundle $bundle)
{
$dir .= '/'.strtr($namespace, '\\', '/');
$dir = $bundle->getTargetDirectory();

if (file_exists($dir)) {
if (!is_dir($dir)) {
throw new \RuntimeException(sprintf('Unable to generate the bundle as the target directory "%s" exists but is a file.', realpath($dir)));
Expand All @@ -44,41 +45,35 @@ public function generate($namespace, $bundle, $dir, $format, $structure)
}
}

$basename = substr($bundle, 0, -6);
$parameters = array(
'namespace' => $namespace,
'bundle' => $bundle,
'format' => $format,
'bundle_basename' => $basename,
'extension_alias' => Container::underscore($basename),
'namespace' => $bundle->getNamespace(),
'bundle' => $bundle->getName(),
'format' => $bundle->getConfigurationFormat(),
'bundle_basename' => $bundle->getBasename(),
'extension_alias' => $bundle->getExtensionAlias(),
);

$this->renderFile('bundle/Bundle.php.twig', $dir.'/'.$bundle.'.php', $parameters);
$this->renderFile('bundle/Extension.php.twig', $dir.'/DependencyInjection/'.$basename.'Extension.php', $parameters);
$this->renderFile('bundle/Configuration.php.twig', $dir.'/DependencyInjection/Configuration.php', $parameters);
$this->renderFile('bundle/Bundle.php.twig', $dir.'/'.$bundle->getName().'.php', $parameters);
if ($bundle->shouldGenerateDependencyInjectionDirectory()) {
$this->renderFile('bundle/Extension.php.twig', $dir.'/DependencyInjection/'.$bundle->getBasename().'Extension.php', $parameters);
$this->renderFile('bundle/Configuration.php.twig', $dir.'/DependencyInjection/Configuration.php', $parameters);
}
$this->renderFile('bundle/DefaultController.php.twig', $dir.'/Controller/DefaultController.php', $parameters);
$this->renderFile('bundle/DefaultControllerTest.php.twig', $dir.'/Tests/Controller/DefaultControllerTest.php', $parameters);
$this->renderFile('bundle/index.html.twig.twig', $dir.'/Resources/views/Default/index.html.twig', $parameters);

if ('xml' === $format || 'annotation' === $format) {
$this->renderFile('bundle/services.xml.twig', $dir.'/Resources/config/services.xml', $parameters);
} else {
$this->renderFile('bundle/services.'.$format.'.twig', $dir.'/Resources/config/services.'.$format, $parameters);
}

if ('annotation' != $format) {
$this->renderFile('bundle/routing.'.$format.'.twig', $dir.'/Resources/config/routing.'.$format, $parameters);
}

if ($structure) {
$this->renderFile('bundle/messages.fr.xlf', $dir.'/Resources/translations/messages.fr.xlf', $parameters);
// render the services.yml/xml file
$servicesFilename = $bundle->getServicesConfigurationFilename();
$this->renderFile(
sprintf('bundle/%s.twig', $servicesFilename),
$dir.'/Resources/config/'.$servicesFilename, $parameters
);

$this->filesystem->mkdir($dir.'/Resources/doc');
$this->filesystem->touch($dir.'/Resources/doc/index.rst');
$this->filesystem->mkdir($dir.'/Resources/translations');
$this->filesystem->mkdir($dir.'/Resources/public/css');
$this->filesystem->mkdir($dir.'/Resources/public/images');
$this->filesystem->mkdir($dir.'/Resources/public/js');
if ($routingFilename = $bundle->getRoutingConfigurationFilename()) {
$this->renderFile(
sprintf('bundle/%s.twig', $routingFilename),
$dir.'/Resources/config/'.$routingFilename, $parameters
);
}
}
}
115 changes: 115 additions & 0 deletions Manipulator/ConfigurationManipulator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php

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

use Sensio\Bundle\GeneratorBundle\Model\Bundle;
use Symfony\Component\Yaml\Yaml;

/**
* Changes the PHP code of a YAML services configuration file.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Ryan Weaver <weaverryan@gmail.com>
*/
class ConfigurationManipulator extends Manipulator
{
private $file;

/**
* Constructor.
*
* @param string $file The YAML configuration file path
*/
public function __construct($file)
{
$this->file = $file;
}

/**
* Adds a configuration resource at the top of the existing ones.
*
* @param Bundle $bundle
*
* @throws \RuntimeException If this process fails for any reason
*/
public function addResource(Bundle $bundle)
{
// if the config.yml file doesn't exist, don't even try.
if (!file_exists($this->file)) {
throw new \RuntimeException(sprintf('The target config file %s does not exist', $this->file));
}

$code = $this->getImportCode($bundle);

$currentContents = file_get_contents($this->file);
// Don't add same bundle twice
if (false !== strpos($currentContents, $code)) {
throw new \RuntimeException(sprintf(
'The %s configuration file from %s is already imported',
$bundle->getServicesConfigurationFilename(),
$bundle->getName()
));
}

// find the "imports" line and add this at the end of that list
$lastImportedPath = $this->findLastImportedPath($currentContents);
if (!$lastImportedPath) {
throw new \RuntimeException(sprintf('Could not find the imports key in %s', $this->file));
}

// find imports:
$importsPosition = strpos($currentContents, 'imports:');
// find the last import
$lastImportPosition = strpos($currentContents, $lastImportedPath, $importsPosition);
// find the line break after the last import
$targetLinebreakPosition = strpos($currentContents, "\n", $lastImportPosition);

$newContents = substr($currentContents, 0, $targetLinebreakPosition)."\n".$code.substr($currentContents, $targetLinebreakPosition);

if (false === file_put_contents($this->file, $newContents)) {
throw new \RuntimeException(sprintf('Could not write file %s ', $this->file));
}
}

public function getImportCode(Bundle $bundle)
{
return sprintf(<<<EOF
- { resource: "@%s/Resources/config/%s" }
EOF
,
$bundle->getName(),
$bundle->getServicesConfigurationFilename()
);
}

/**
* Finds the last imported resource path in the YAML file
*
* @param $yamlContents
* @return bool|string
*/
private function findLastImportedPath($yamlContents)
{
$data = Yaml::parse($yamlContents);
if (!isset($data['imports'])) {
return false;
}

// find the last imports entry
$lastImport = end($data['imports']);
if (!isset($lastImport['resource'])) {
return false;
}

return $lastImport['resource'];
}
}
11 changes: 8 additions & 3 deletions Manipulator/KernelManipulator.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ public function __construct(KernelInterface $kernel)
*/
public function addBundle($bundle)
{
if (!$this->reflected->getFilename()) {
if (!$this->getFilename()) {
return false;
}

$src = file($this->reflected->getFilename());
$src = file($this->getFilename());
$method = $this->reflected->getMethod('registerBundles');
$lines = array_slice($src, $method->getStartLine() - 1, $method->getEndLine() - $method->getStartLine() + 1);

Expand Down Expand Up @@ -96,10 +96,15 @@ public function addBundle($bundle)
array_slice($src, $this->line - 1)
);

file_put_contents($this->reflected->getFilename(), implode('', $lines));
file_put_contents($this->getFilename(), implode('', $lines));

return true;
}
}
}

public function getFilename()
{
return $this->reflected->getFileName();
}
}
Loading