Update
This commit is contained in:
parent
a37785b391
commit
33458b2ca3
9915 changed files with 1247019 additions and 0 deletions
3
trunk/_vendor/sensio/generator-bundle/.gitignore
vendored
Normal file
3
trunk/_vendor/sensio/generator-bundle/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
phpunit.xml
|
||||
vendor
|
||||
composer.lock
|
||||
28
trunk/_vendor/sensio/generator-bundle/.travis.yml
Normal file
28
trunk/_vendor/sensio/generator-bundle/.travis.yml
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
language: php
|
||||
|
||||
dist: trusty
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache/files
|
||||
- .phpunit
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- php: hhvm
|
||||
- php: 5.3
|
||||
dist: precise
|
||||
- php: 5.4
|
||||
- php: 5.5
|
||||
- php: 5.6
|
||||
- php: 7.0
|
||||
- php: 7.1
|
||||
env: composer_extra="--prefer-lowest --prefer-stable"
|
||||
fast_finish: true
|
||||
|
||||
install:
|
||||
- composer $composer_extra update
|
||||
|
||||
script:
|
||||
- ./vendor/bin/simple-phpunit
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<?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\Command\AutoComplete;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
* Provides auto-completion suggestions for entities.
|
||||
*
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
class EntitiesAutoCompleter
|
||||
{
|
||||
private $manager;
|
||||
|
||||
public function __construct(EntityManagerInterface $manager)
|
||||
{
|
||||
$this->manager = $manager;
|
||||
}
|
||||
|
||||
public function getSuggestions()
|
||||
{
|
||||
$configuration = $this->manager
|
||||
->getConfiguration()
|
||||
;
|
||||
|
||||
$namespaceReplacements = array();
|
||||
|
||||
foreach ($configuration->getEntityNamespaces() as $alias => $namespace) {
|
||||
$namespaceReplacements[$namespace.'\\'] = $alias.':';
|
||||
}
|
||||
|
||||
$entities = $configuration
|
||||
->getMetadataDriverImpl()
|
||||
->getAllClassNames()
|
||||
;
|
||||
|
||||
return array_map(function ($entity) use ($namespaceReplacements) {
|
||||
return strtr($entity, $namespaceReplacements);
|
||||
}, $entities);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,419 @@
|
|||
<?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\Command;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Manipulator\ConfigurationManipulator;
|
||||
use Sensio\Bundle\GeneratorBundle\Model\Bundle;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\BundleGenerator;
|
||||
use Sensio\Bundle\GeneratorBundle\Manipulator\KernelManipulator;
|
||||
use Sensio\Bundle\GeneratorBundle\Manipulator\RoutingManipulator;
|
||||
|
||||
/**
|
||||
* Generates bundles.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class GenerateBundleCommand extends GeneratorCommand
|
||||
{
|
||||
/**
|
||||
* @see Command
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('generate:bundle')
|
||||
->setDescription('Generates a bundle')
|
||||
->setDefinition(array(
|
||||
new InputOption('namespace', '', InputOption::VALUE_REQUIRED, 'The namespace of the bundle to create'),
|
||||
new InputOption('dir', '', InputOption::VALUE_REQUIRED, 'The directory where to create the bundle', 'src/'),
|
||||
new InputOption('bundle-name', '', InputOption::VALUE_REQUIRED, 'The optional bundle name'),
|
||||
new InputOption('format', '', InputOption::VALUE_REQUIRED, 'Use the format for configuration files (php, xml, yml, or annotation)'),
|
||||
new InputOption('shared', '', InputOption::VALUE_NONE, 'Are you planning on sharing this bundle across multiple applications?'),
|
||||
))
|
||||
->setHelp(<<<EOT
|
||||
The <info>%command.name%</info> command helps you generates new bundles.
|
||||
|
||||
By default, the command interacts with the developer to tweak the generation.
|
||||
Any passed option will be used as a default value for the interaction
|
||||
(<comment>--namespace</comment> is the only one needed if you follow the
|
||||
conventions):
|
||||
|
||||
<info>php %command.full_name% --namespace=Acme/BlogBundle</info>
|
||||
|
||||
Note that you can use <comment>/</comment> instead of <comment>\\ </comment>for the namespace delimiter to avoid any
|
||||
problems.
|
||||
|
||||
If you want to disable any user interaction, use <comment>--no-interaction</comment> but don't forget to pass all needed options:
|
||||
|
||||
<info>php %command.full_name% --namespace=Acme/BlogBundle --dir=src [--bundle-name=...] --no-interaction</info>
|
||||
|
||||
Note that the bundle namespace must end with "Bundle".
|
||||
EOT
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Command
|
||||
*
|
||||
* @throws \InvalidArgumentException When namespace doesn't end with Bundle
|
||||
* @throws \RuntimeException When bundle can't be executed
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$questionHelper = $this->getQuestionHelper();
|
||||
|
||||
$bundle = $this->createBundleObject($input);
|
||||
$questionHelper->writeSection($output, 'Bundle generation');
|
||||
|
||||
/** @var BundleGenerator $generator */
|
||||
$generator = $this->getGenerator();
|
||||
|
||||
$output->writeln(sprintf(
|
||||
'> Generating a sample bundle skeleton into <info>%s</info>',
|
||||
$this->makePathRelative($bundle->getTargetDirectory())
|
||||
));
|
||||
$generator->generateBundle($bundle);
|
||||
|
||||
$errors = array();
|
||||
$runner = $questionHelper->getRunner($output, $errors);
|
||||
|
||||
// check that the namespace is already autoloaded
|
||||
$runner($this->checkAutoloader($output, $bundle));
|
||||
|
||||
// register the bundle in the Kernel class
|
||||
$runner($this->updateKernel($output, $this->getContainer()->get('kernel'), $bundle));
|
||||
|
||||
// routing importing
|
||||
$runner($this->updateRouting($output, $bundle));
|
||||
|
||||
if (!$bundle->shouldGenerateDependencyInjectionDirectory()) {
|
||||
// we need to import their services.yml manually!
|
||||
$runner($this->updateConfiguration($output, $bundle));
|
||||
}
|
||||
|
||||
$questionHelper->writeGeneratorSummary($output, $errors);
|
||||
}
|
||||
|
||||
protected function interact(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$questionHelper = $this->getQuestionHelper();
|
||||
$questionHelper->writeSection($output, 'Welcome to the Symfony bundle generator!');
|
||||
|
||||
/*
|
||||
* shared option
|
||||
*/
|
||||
$shared = $input->getOption('shared');
|
||||
// ask, but use $shared as the default
|
||||
$question = new ConfirmationQuestion($questionHelper->getQuestion(
|
||||
'Are you planning on sharing this bundle across multiple applications?',
|
||||
$shared ? 'yes' : 'no'
|
||||
), $shared);
|
||||
$shared = $questionHelper->ask($input, $output, $question);
|
||||
$input->setOption('shared', $shared);
|
||||
|
||||
/*
|
||||
* namespace option
|
||||
*/
|
||||
$namespace = $input->getOption('namespace');
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'Your application code must be written in <comment>bundles</comment>. This command helps',
|
||||
'you generate them easily.',
|
||||
'',
|
||||
));
|
||||
|
||||
$askForBundleName = true;
|
||||
if ($shared) {
|
||||
// a shared bundle, so it should probably have a vendor namespace
|
||||
$output->writeln(array(
|
||||
'Each bundle is hosted under a namespace (like <comment>Acme/BlogBundle</comment>).',
|
||||
'The namespace should begin with a "vendor" name like your company name, your',
|
||||
'project name, or your client name, followed by one or more optional category',
|
||||
'sub-namespaces, and it should end with the bundle name itself',
|
||||
'(which must have <comment>Bundle</comment> as a suffix).',
|
||||
'',
|
||||
'See http://symfony.com/doc/current/cookbook/bundles/best_practices.html#bundle-name for more',
|
||||
'details on bundle naming conventions.',
|
||||
'',
|
||||
'Use <comment>/</comment> instead of <comment>\\ </comment>for the namespace delimiter to avoid any problems.',
|
||||
'',
|
||||
));
|
||||
|
||||
$question = new Question($questionHelper->getQuestion(
|
||||
'Bundle namespace',
|
||||
$namespace
|
||||
), $namespace);
|
||||
$question->setValidator(function ($answer) {
|
||||
return Validators::validateBundleNamespace($answer, true);
|
||||
});
|
||||
$namespace = $questionHelper->ask($input, $output, $question);
|
||||
} else {
|
||||
// a simple application bundle
|
||||
$output->writeln(array(
|
||||
'Give your bundle a descriptive name, like <comment>BlogBundle</comment>.',
|
||||
));
|
||||
|
||||
$question = new Question($questionHelper->getQuestion(
|
||||
'Bundle name',
|
||||
$namespace
|
||||
), $namespace);
|
||||
$question->setValidator(function ($inputNamespace) {
|
||||
return Validators::validateBundleNamespace($inputNamespace, false);
|
||||
});
|
||||
$namespace = $questionHelper->ask($input, $output, $question);
|
||||
|
||||
if (strpos($namespace, '\\') === false) {
|
||||
// this is a bundle name (FooBundle) not a namespace (Acme\FooBundle)
|
||||
// so this is the bundle name (and it is also the namespace)
|
||||
$input->setOption('bundle-name', $namespace);
|
||||
$askForBundleName = false;
|
||||
}
|
||||
}
|
||||
$input->setOption('namespace', $namespace);
|
||||
|
||||
/*
|
||||
* bundle-name option
|
||||
*/
|
||||
if ($askForBundleName) {
|
||||
$bundle = $input->getOption('bundle-name');
|
||||
// no bundle yet? Get a default from the namespace
|
||||
if (!$bundle) {
|
||||
$bundle = strtr($namespace, array('\\Bundle\\' => '', '\\' => ''));
|
||||
}
|
||||
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'In your code, a bundle is often referenced by its name. It can be the',
|
||||
'concatenation of all namespace parts but it\'s really up to you to come',
|
||||
'up with a unique name (a good practice is to start with the vendor name).',
|
||||
'Based on the namespace, we suggest <comment>'.$bundle.'</comment>.',
|
||||
'',
|
||||
));
|
||||
$question = new Question($questionHelper->getQuestion(
|
||||
'Bundle name',
|
||||
$bundle
|
||||
), $bundle);
|
||||
$question->setValidator(
|
||||
array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateBundleName')
|
||||
);
|
||||
$bundle = $questionHelper->ask($input, $output, $question);
|
||||
$input->setOption('bundle-name', $bundle);
|
||||
}
|
||||
|
||||
/*
|
||||
* dir option
|
||||
*/
|
||||
// defaults to src/ in the option
|
||||
$dir = $input->getOption('dir');
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'Bundles are usually generated into the <info>src/</info> directory. Unless you\'re',
|
||||
'doing something custom, hit enter to keep this default!',
|
||||
'',
|
||||
));
|
||||
|
||||
$question = new Question($questionHelper->getQuestion(
|
||||
'Target Directory',
|
||||
$dir
|
||||
), $dir);
|
||||
$dir = $questionHelper->ask($input, $output, $question);
|
||||
$input->setOption('dir', $dir);
|
||||
|
||||
/*
|
||||
* format option
|
||||
*/
|
||||
$format = $input->getOption('format');
|
||||
if (!$format) {
|
||||
$format = $shared ? 'xml' : 'annotation';
|
||||
}
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'What format do you want to use for your generated configuration?',
|
||||
'',
|
||||
));
|
||||
|
||||
$question = new Question($questionHelper->getQuestion(
|
||||
'Configuration format (annotation, yml, xml, php)',
|
||||
$format
|
||||
), $format);
|
||||
$question->setValidator(function ($format) {
|
||||
return Validators::validateFormat($format);
|
||||
});
|
||||
$question->setAutocompleterValues(array('annotation', 'yml', 'xml', 'php'));
|
||||
$format = $questionHelper->ask($input, $output, $question);
|
||||
$input->setOption('format', $format);
|
||||
}
|
||||
|
||||
protected function checkAutoloader(OutputInterface $output, Bundle $bundle)
|
||||
{
|
||||
$output->writeln('> Checking that the bundle is autoloaded');
|
||||
if (!class_exists($bundle->getBundleClassName())) {
|
||||
return array(
|
||||
'- Edit the <comment>composer.json</comment> file and register the bundle',
|
||||
' namespace in the "autoload" section:',
|
||||
'',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateKernel(OutputInterface $output, KernelInterface $kernel, Bundle $bundle)
|
||||
{
|
||||
$kernelManipulator = new KernelManipulator($kernel);
|
||||
|
||||
$output->writeln(sprintf(
|
||||
'> Enabling the bundle inside <info>%s</info>',
|
||||
$this->makePathRelative($kernelManipulator->getFilename())
|
||||
));
|
||||
|
||||
try {
|
||||
$ret = $kernelManipulator->addBundle($bundle->getBundleClassName());
|
||||
|
||||
if (!$ret) {
|
||||
$reflected = new \ReflectionObject($kernel);
|
||||
|
||||
return array(
|
||||
sprintf('- Edit <comment>%s</comment>', $reflected->getFilename()),
|
||||
' and add the following bundle in the <comment>AppKernel::registerBundles()</comment> method:',
|
||||
'',
|
||||
sprintf(' <comment>new %s(),</comment>', $bundle->getBundleClassName()),
|
||||
'',
|
||||
);
|
||||
}
|
||||
} catch (\RuntimeException $e) {
|
||||
return array(
|
||||
sprintf('Bundle <comment>%s</comment> is already defined in <comment>AppKernel::registerBundles()</comment>.', $bundle->getBundleClassName()),
|
||||
'',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateRouting(OutputInterface $output, Bundle $bundle)
|
||||
{
|
||||
$targetRoutingPath = $this->getContainer()->getParameter('kernel.root_dir').'/config/routing.yml';
|
||||
$output->writeln(sprintf(
|
||||
'> Importing the bundle\'s routes from the <info>%s</info> file',
|
||||
$this->makePathRelative($targetRoutingPath)
|
||||
));
|
||||
$routing = new RoutingManipulator($targetRoutingPath);
|
||||
try {
|
||||
$ret = $routing->addResource($bundle->getName(), $bundle->getConfigurationFormat());
|
||||
if (!$ret) {
|
||||
if ('annotation' === $bundle->getConfigurationFormat()) {
|
||||
$help = sprintf(" <comment>resource: \"@%s/Controller/\"</comment>\n <comment>type: annotation</comment>\n", $bundle->getName());
|
||||
} else {
|
||||
$help = sprintf(" <comment>resource: \"@%s/Resources/config/routing.%s\"</comment>\n", $bundle->getName(), $bundle->getConfigurationFormat());
|
||||
}
|
||||
$help .= " <comment>prefix: /</comment>\n";
|
||||
|
||||
return array(
|
||||
'- Import the bundle\'s routing resource in the app\'s main routing file:',
|
||||
'',
|
||||
sprintf(' <comment>%s:</comment>', $bundle->getName()),
|
||||
$help,
|
||||
'',
|
||||
);
|
||||
}
|
||||
} catch (\RuntimeException $e) {
|
||||
return array(
|
||||
sprintf('Bundle <comment>%s</comment> is already imported.', $bundle->getName()),
|
||||
'',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateConfiguration(OutputInterface $output, Bundle $bundle)
|
||||
{
|
||||
$targetConfigurationPath = $this->getContainer()->getParameter('kernel.root_dir').'/config/config.yml';
|
||||
$output->writeln(sprintf(
|
||||
'> Importing the bundle\'s %s from the <info>%s</info> file',
|
||||
$bundle->getServicesConfigurationFilename(),
|
||||
$this->makePathRelative($targetConfigurationPath)
|
||||
));
|
||||
$manipulator = new ConfigurationManipulator($targetConfigurationPath);
|
||||
try {
|
||||
$manipulator->addResource($bundle);
|
||||
} catch (\RuntimeException $e) {
|
||||
return array(
|
||||
sprintf('- Import the bundle\'s "%s" resource in the app\'s main configuration file:', $bundle->getServicesConfigurationFilename()),
|
||||
'',
|
||||
$manipulator->getImportCode($bundle),
|
||||
'',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Bundle object based on the user's (non-interactive) input.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
*
|
||||
* @return Bundle
|
||||
*/
|
||||
protected function createBundleObject(InputInterface $input)
|
||||
{
|
||||
foreach (array('namespace', 'dir') as $option) {
|
||||
if (null === $input->getOption($option)) {
|
||||
throw new \RuntimeException(sprintf('The "%s" option must be provided.', $option));
|
||||
}
|
||||
}
|
||||
|
||||
$shared = $input->getOption('shared');
|
||||
|
||||
$namespace = Validators::validateBundleNamespace($input->getOption('namespace'), $shared);
|
||||
if (!$bundleName = $input->getOption('bundle-name')) {
|
||||
$bundleName = strtr($namespace, array('\\' => ''));
|
||||
}
|
||||
$bundleName = Validators::validateBundleName($bundleName);
|
||||
$dir = $input->getOption('dir');
|
||||
if (null === $input->getOption('format')) {
|
||||
$input->setOption('format', 'annotation');
|
||||
}
|
||||
$format = Validators::validateFormat($input->getOption('format'));
|
||||
|
||||
// an assumption that the kernel root dir is in a directory (like app/)
|
||||
$projectRootDirectory = $this->getContainer()->getParameter('kernel.root_dir').'/..';
|
||||
|
||||
if (!$this->getContainer()->get('filesystem')->isAbsolutePath($dir)) {
|
||||
$dir = $projectRootDirectory.'/'.$dir;
|
||||
}
|
||||
// add trailing / if necessary
|
||||
$dir = '/' === substr($dir, -1, 1) ? $dir : $dir.'/';
|
||||
|
||||
$bundle = new Bundle(
|
||||
$namespace,
|
||||
$bundleName,
|
||||
$dir,
|
||||
$format,
|
||||
$shared
|
||||
);
|
||||
|
||||
// not shared - put the tests in the root
|
||||
if (!$shared) {
|
||||
$testsDir = $projectRootDirectory.'/tests/'.$bundleName;
|
||||
$bundle->setTestsDirectory($testsDir);
|
||||
}
|
||||
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
protected function createGenerator()
|
||||
{
|
||||
return new BundleGenerator($this->getContainer()->get('filesystem'));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
<?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\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\CommandGenerator;
|
||||
|
||||
/**
|
||||
* Generates commands.
|
||||
*
|
||||
* @author Javier Eguiluz <javier.eguiluz@gmail.com>
|
||||
*/
|
||||
class GenerateCommandCommand extends GeneratorCommand
|
||||
{
|
||||
const MAX_ATTEMPTS = 5;
|
||||
|
||||
/**
|
||||
* @see Command
|
||||
*/
|
||||
public function configure()
|
||||
{
|
||||
$this
|
||||
->setName('generate:command')
|
||||
->setDescription('Generates a console command')
|
||||
->setDefinition(array(
|
||||
new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle where the command is generated'),
|
||||
new InputArgument('name', InputArgument::OPTIONAL, 'The command\'s name (e.g. app:my-command)'),
|
||||
))
|
||||
->setHelp(<<<EOT
|
||||
The <info>%command.name%</info> command helps you generate new commands
|
||||
inside bundles. Provide the bundle name as the first argument and the command
|
||||
name as the second argument:
|
||||
|
||||
<info>php %command.full_name% AppBundle blog:publish-posts</info>
|
||||
|
||||
If any of the arguments is missing, the command will ask for their values
|
||||
interactively. If you want to disable any user interaction, use
|
||||
<comment>--no-interaction</comment>, but don't forget to pass all needed arguments.
|
||||
|
||||
Every generated file is based on a template. There are default templates but they can
|
||||
be overridden by placing custom templates in one of the following locations, by order of priority:
|
||||
|
||||
<info>BUNDLE_PATH/Resources/SensioGeneratorBundle/skeleton/command
|
||||
APP_PATH/Resources/SensioGeneratorBundle/skeleton/command</info>
|
||||
|
||||
You can check https://github.com/sensio/SensioGeneratorBundle/tree/master/Resources/skeleton
|
||||
in order to know the file structure of the skeleton.
|
||||
EOT
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
public function interact(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$bundle = $input->getArgument('bundle');
|
||||
$name = $input->getArgument('name');
|
||||
|
||||
if (null !== $bundle && null !== $name) {
|
||||
return;
|
||||
}
|
||||
|
||||
$questionHelper = $this->getQuestionHelper();
|
||||
$questionHelper->writeSection($output, 'Welcome to the Symfony command generator');
|
||||
|
||||
// bundle
|
||||
if (null !== $bundle) {
|
||||
$output->writeln(sprintf('Bundle name: %s', $bundle));
|
||||
} else {
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'First, you need to give the name of the bundle where the command will',
|
||||
'be generated (e.g. <comment>AppBundle</comment>)',
|
||||
'',
|
||||
));
|
||||
|
||||
$bundleNames = array_keys($this->getContainer()->get('kernel')->getBundles());
|
||||
|
||||
$question = new Question($questionHelper->getQuestion('Bundle name', $bundle), $bundle);
|
||||
$question->setAutocompleterValues($bundleNames);
|
||||
$question->setValidator(function ($answer) use ($bundleNames) {
|
||||
if (!in_array($answer, $bundleNames)) {
|
||||
throw new \RuntimeException(sprintf('Bundle "%s" does not exist.', $answer));
|
||||
}
|
||||
|
||||
return $answer;
|
||||
});
|
||||
$question->setMaxAttempts(self::MAX_ATTEMPTS);
|
||||
|
||||
$bundle = $questionHelper->ask($input, $output, $question);
|
||||
$input->setArgument('bundle', $bundle);
|
||||
}
|
||||
|
||||
// command name
|
||||
if (null !== $name) {
|
||||
$output->writeln(sprintf('Command name: %s', $name));
|
||||
} else {
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'Now, provide the name of the command as you type it in the console',
|
||||
'(e.g. <comment>app:my-command</comment>)',
|
||||
'',
|
||||
));
|
||||
|
||||
$question = new Question($questionHelper->getQuestion('Command name', $name), $name);
|
||||
$question->setValidator(function ($answer) {
|
||||
if (empty($answer)) {
|
||||
throw new \RuntimeException('The command name cannot be empty.');
|
||||
}
|
||||
|
||||
return $answer;
|
||||
});
|
||||
$question->setMaxAttempts(self::MAX_ATTEMPTS);
|
||||
|
||||
$name = $questionHelper->ask($input, $output, $question);
|
||||
$input->setArgument('name', $name);
|
||||
}
|
||||
|
||||
// summary and confirmation
|
||||
$questionHelper->writeSection($output, 'Summary before generation');
|
||||
$output->writeln(array(
|
||||
sprintf('You are going to generate a <info>%s</info> command inside <info>%s</info> bundle.', $name, $bundle),
|
||||
));
|
||||
|
||||
$question = new Question($questionHelper->getQuestion('Do you confirm generation', 'yes', '?'), true);
|
||||
if (!$questionHelper->ask($input, $output, $question)) {
|
||||
$output->writeln('<error>Command aborted</error>');
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$questionHelper = $this->getQuestionHelper();
|
||||
$bundle = $input->getArgument('bundle');
|
||||
$name = $input->getArgument('name');
|
||||
|
||||
try {
|
||||
$bundle = $this->getContainer()->get('kernel')->getBundle($bundle);
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln(sprintf('<bg=red>Bundle "%s" does not exist.</>', $bundle));
|
||||
}
|
||||
|
||||
$generator = $this->getGenerator($bundle);
|
||||
$generator->generate($bundle, $name);
|
||||
|
||||
$output->writeln(sprintf('Generated the <info>%s</info> command in <info>%s</info>', $name, $bundle->getName()));
|
||||
$questionHelper->writeGeneratorSummary($output, array());
|
||||
}
|
||||
|
||||
protected function createGenerator()
|
||||
{
|
||||
return new CommandGenerator($this->getContainer()->get('filesystem'));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,358 @@
|
|||
<?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\Command;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Manipulator\RoutingManipulator;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Sensio\Bundle\GeneratorBundle\Command\Helper\QuestionHelper;
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\ControllerGenerator;
|
||||
|
||||
/**
|
||||
* Generates controllers.
|
||||
*
|
||||
* @author Wouter J <wouter@wouterj.nl>
|
||||
*/
|
||||
class GenerateControllerCommand extends GeneratorCommand
|
||||
{
|
||||
/**
|
||||
* @see Command
|
||||
*/
|
||||
public function configure()
|
||||
{
|
||||
$this
|
||||
->setName('generate:controller')
|
||||
->setDescription('Generates a controller')
|
||||
->setDefinition(array(
|
||||
new InputOption('controller', '', InputOption::VALUE_REQUIRED, 'The name of the controller to create'),
|
||||
new InputOption('route-format', '', InputOption::VALUE_REQUIRED, 'The format that is used for the routing (yml, xml, php, annotation)', 'annotation'),
|
||||
new InputOption('template-format', '', InputOption::VALUE_REQUIRED, 'The format that is used for templating (twig, php)', 'twig'),
|
||||
new InputOption('actions', '', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'The actions in the controller'),
|
||||
))
|
||||
->setHelp(<<<EOT
|
||||
The <info>%command.name%</info> command helps you generates new controllers
|
||||
inside bundles.
|
||||
|
||||
By default, the command interacts with the developer to tweak the generation.
|
||||
Any passed option will be used as a default value for the interaction
|
||||
(<comment>--controller</comment> is the only one needed if you follow the conventions):
|
||||
|
||||
<info>php %command.full_name% --controller=AcmeBlogBundle:Post</info>
|
||||
|
||||
If you want to disable any user interaction, use <comment>--no-interaction</comment>
|
||||
but don't forget to pass all needed options:
|
||||
|
||||
<info>php %command.full_name% --controller=AcmeBlogBundle:Post --no-interaction</info>
|
||||
|
||||
Every generated file is based on a template. There are default templates but they can
|
||||
be overridden by placing custom templates in one of the following locations, by order of priority:
|
||||
|
||||
<info>BUNDLE_PATH/Resources/SensioGeneratorBundle/skeleton/controller
|
||||
APP_PATH/Resources/SensioGeneratorBundle/skeleton/controller</info>
|
||||
|
||||
You can check https://github.com/sensio/SensioGeneratorBundle/tree/master/Resources/skeleton
|
||||
in order to know the file structure of the skeleton
|
||||
EOT
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$questionHelper = $this->getQuestionHelper();
|
||||
|
||||
if ($input->isInteractive()) {
|
||||
$question = new ConfirmationQuestion($questionHelper->getQuestion('Do you confirm generation', 'yes', '?'), true);
|
||||
if (!$questionHelper->ask($input, $output, $question)) {
|
||||
$output->writeln('<error>Command aborted</error>');
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $input->getOption('controller')) {
|
||||
throw new \RuntimeException('The controller option must be provided.');
|
||||
}
|
||||
|
||||
list($bundle, $controller) = $this->parseShortcutNotation($input->getOption('controller'));
|
||||
if (is_string($bundle)) {
|
||||
$bundle = Validators::validateBundleName($bundle);
|
||||
|
||||
try {
|
||||
$bundle = $this->getContainer()->get('kernel')->getBundle($bundle);
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln(sprintf('<bg=red>Bundle "%s" does not exist.</>', $bundle));
|
||||
}
|
||||
}
|
||||
|
||||
$questionHelper->writeSection($output, 'Controller generation');
|
||||
|
||||
$routingFormat = $input->getOption('route-format');
|
||||
/** @var ControllerGenerator $generator */
|
||||
$generator = $this->getGenerator($bundle);
|
||||
$generator->generate(
|
||||
$bundle,
|
||||
$controller,
|
||||
$routingFormat,
|
||||
$input->getOption('template-format'),
|
||||
$this->parseActions($input->getOption('actions'))
|
||||
);
|
||||
|
||||
if ('annotations' === $routingFormat) {
|
||||
$this->tryUpdateAnnotationRouting($bundle, $controller);
|
||||
}
|
||||
|
||||
$output->writeln('Generating the bundle code: <info>OK</info>');
|
||||
|
||||
$questionHelper->writeGeneratorSummary($output, array());
|
||||
}
|
||||
|
||||
public function interact(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$questionHelper = $this->getQuestionHelper();
|
||||
$questionHelper->writeSection($output, 'Welcome to the Symfony controller generator');
|
||||
|
||||
// namespace
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'Every page, and even sections of a page, are rendered by a <comment>controller</comment>.',
|
||||
'This command helps you generate them easily.',
|
||||
'',
|
||||
'First, you need to give the controller name you want to generate.',
|
||||
'You must use the shortcut notation like <comment>AcmeBlogBundle:Post</comment>',
|
||||
'',
|
||||
));
|
||||
|
||||
$bundleNames = array_keys($this->getContainer()->get('kernel')->getBundles());
|
||||
|
||||
while (true) {
|
||||
$question = new Question($questionHelper->getQuestion('Controller name', $input->getOption('controller')), $input->getOption('controller'));
|
||||
$question->setAutocompleterValues($bundleNames);
|
||||
$question->setValidator(array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateControllerName'));
|
||||
$controller = $questionHelper->ask($input, $output, $question);
|
||||
list($bundle, $controller) = $this->parseShortcutNotation($controller);
|
||||
|
||||
try {
|
||||
$b = $this->getContainer()->get('kernel')->getBundle($bundle);
|
||||
|
||||
if (!file_exists($b->getPath().'/Controller/'.$controller.'Controller.php')) {
|
||||
break;
|
||||
}
|
||||
|
||||
$output->writeln(sprintf('<bg=red>Controller "%s:%s" already exists.</>', $bundle, $controller));
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln(sprintf('<bg=red>Bundle "%s" does not exist.</>', $bundle));
|
||||
}
|
||||
}
|
||||
$input->setOption('controller', $bundle.':'.$controller);
|
||||
|
||||
// routing format
|
||||
$defaultFormat = (null !== $input->getOption('route-format') ? $input->getOption('route-format') : 'annotation');
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'Determine the format to use for the routing.',
|
||||
'',
|
||||
));
|
||||
$question = new Question($questionHelper->getQuestion('Routing format (php, xml, yml, annotation)', $defaultFormat), $defaultFormat);
|
||||
$question->setValidator(array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateFormat'));
|
||||
$routeFormat = $questionHelper->ask($input, $output, $question);
|
||||
$input->setOption('route-format', $routeFormat);
|
||||
|
||||
// templating format
|
||||
$validateTemplateFormat = function ($format) {
|
||||
if (!in_array($format, array('twig', 'php'))) {
|
||||
throw new \InvalidArgumentException(sprintf('The template format must be twig or php, "%s" given', $format));
|
||||
}
|
||||
|
||||
return $format;
|
||||
};
|
||||
|
||||
$defaultFormat = (null !== $input->getOption('template-format') ? $input->getOption('template-format') : 'twig');
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'Determine the format to use for templating.',
|
||||
'',
|
||||
));
|
||||
$question = new Question($questionHelper->getQuestion('Template format (twig, php)', $defaultFormat), $defaultFormat);
|
||||
$question->setValidator($validateTemplateFormat);
|
||||
|
||||
$templateFormat = $questionHelper->ask($input, $output, $question);
|
||||
$input->setOption('template-format', $templateFormat);
|
||||
|
||||
// actions
|
||||
$input->setOption('actions', $this->addActions($input, $output, $questionHelper));
|
||||
|
||||
// summary
|
||||
$questionHelper->writeSection($output, 'Summary before generation');
|
||||
$output->writeln(array(
|
||||
sprintf('You are going to generate a "<info>%s:%s</info>" controller', $bundle, $controller),
|
||||
sprintf('using the "<info>%s</info>" format for the routing and the "<info>%s</info>" format', $routeFormat, $templateFormat),
|
||||
'for templating',
|
||||
));
|
||||
}
|
||||
|
||||
public function addActions(InputInterface $input, OutputInterface $output, QuestionHelper $questionHelper)
|
||||
{
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'Instead of starting with a blank controller, you can add some actions now. An action',
|
||||
'is a PHP function or method that executes, for example, when a given route is matched.',
|
||||
'Actions should be suffixed by <comment>Action</comment>.',
|
||||
'',
|
||||
));
|
||||
|
||||
$templateNameValidator = function ($name) {
|
||||
if ('default' == $name) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
if (2 != substr_count($name, ':')) {
|
||||
throw new \InvalidArgumentException(sprintf('Template name "%s" does not have 2 colons', $name));
|
||||
}
|
||||
|
||||
return $name;
|
||||
};
|
||||
|
||||
$actions = $this->parseActions($input->getOption('actions'));
|
||||
|
||||
while (true) {
|
||||
// name
|
||||
$output->writeln('');
|
||||
$question = new Question($questionHelper->getQuestion('New action name (press <return> to stop adding actions)', null), null);
|
||||
$question->setValidator(function ($name) use ($actions) {
|
||||
if (null == $name) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
if (isset($actions[$name])) {
|
||||
throw new \InvalidArgumentException(sprintf('Action "%s" is already defined', $name));
|
||||
}
|
||||
|
||||
if ('Action' != substr($name, -6)) {
|
||||
throw new \InvalidArgumentException(sprintf('Name "%s" is not suffixed by Action', $name));
|
||||
}
|
||||
|
||||
return $name;
|
||||
});
|
||||
|
||||
$actionName = $questionHelper->ask($input, $output, $question);
|
||||
if (!$actionName) {
|
||||
break;
|
||||
}
|
||||
|
||||
// route
|
||||
$question = new Question($questionHelper->getQuestion('Action route', '/'.substr($actionName, 0, -6)), '/'.substr($actionName, 0, -6));
|
||||
$route = $questionHelper->ask($input, $output, $question);
|
||||
$placeholders = $this->getPlaceholdersFromRoute($route);
|
||||
|
||||
// template
|
||||
$defaultTemplate = $input->getOption('controller').':'.
|
||||
strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr(substr($actionName, 0, -6), '_', '.')))
|
||||
.'.html.'.$input->getOption('template-format');
|
||||
$question = new Question($questionHelper->getQuestion('Template name (optional)', $defaultTemplate), $defaultTemplate);
|
||||
$template = $questionHelper->ask($input, $output, $question);
|
||||
|
||||
// adding action
|
||||
$actions[$actionName] = array(
|
||||
'name' => $actionName,
|
||||
'route' => $route,
|
||||
'placeholders' => $placeholders,
|
||||
'template' => $template,
|
||||
);
|
||||
}
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
public function parseActions($actions)
|
||||
{
|
||||
if (empty($actions) || $actions !== array_values($actions)) {
|
||||
return $actions;
|
||||
}
|
||||
|
||||
// '$actions' can be an array with just 1 element defining several actions
|
||||
// separated by white spaces: $actions = array('... ... ...');
|
||||
if (1 === count($actions)) {
|
||||
$actions = explode(' ', $actions[0]);
|
||||
}
|
||||
|
||||
$parsedActions = array();
|
||||
|
||||
foreach ($actions as $action) {
|
||||
$data = explode(':', $action);
|
||||
|
||||
// name
|
||||
if (!isset($data[0])) {
|
||||
throw new \InvalidArgumentException('An action must have a name');
|
||||
}
|
||||
$name = array_shift($data);
|
||||
|
||||
// route
|
||||
$route = (isset($data[0]) && '' != $data[0]) ? array_shift($data) : '/'.substr($name, 0, -6);
|
||||
if ($route) {
|
||||
$placeholders = $this->getPlaceholdersFromRoute($route);
|
||||
} else {
|
||||
$placeholders = array();
|
||||
}
|
||||
|
||||
// template
|
||||
$template = (0 < count($data) && '' != $data[0]) ? implode(':', $data) : 'default';
|
||||
|
||||
$parsedActions[$name] = array(
|
||||
'name' => $name,
|
||||
'route' => $route,
|
||||
'placeholders' => $placeholders,
|
||||
'template' => $template,
|
||||
);
|
||||
}
|
||||
|
||||
return $parsedActions;
|
||||
}
|
||||
|
||||
public function getPlaceholdersFromRoute($route)
|
||||
{
|
||||
preg_match_all('/{(.*?)}/', $route, $placeholders);
|
||||
$placeholders = $placeholders[1];
|
||||
|
||||
return $placeholders;
|
||||
}
|
||||
|
||||
public function parseShortcutNotation($shortcut)
|
||||
{
|
||||
$entity = str_replace('/', '\\', $shortcut);
|
||||
|
||||
if (false === $pos = strpos($entity, ':')) {
|
||||
throw new \InvalidArgumentException(sprintf('The controller name must contain a : ("%s" given, expecting something like AcmeBlogBundle:Post)', $entity));
|
||||
}
|
||||
|
||||
return array(substr($entity, 0, $pos), substr($entity, $pos + 1));
|
||||
}
|
||||
|
||||
protected function createGenerator()
|
||||
{
|
||||
return new ControllerGenerator($this->getContainer()->get('filesystem'));
|
||||
}
|
||||
|
||||
private function tryUpdateAnnotationRouting($bundleName, $controller)
|
||||
{
|
||||
$routing = new RoutingManipulator($this->getContainer()->getParameter('kernel.root_dir').'/config/routing.yml');
|
||||
|
||||
if ($routing->hasResourceInAnnotation($bundleName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$routing->addAnnotationController($bundleName, $controller);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?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\Command;
|
||||
|
||||
use Doctrine\Bundle\DoctrineBundle\Mapping\DisconnectedMetadataFactory;
|
||||
|
||||
abstract class GenerateDoctrineCommand extends GeneratorCommand
|
||||
{
|
||||
public function isEnabled()
|
||||
{
|
||||
return class_exists('Doctrine\\Bundle\\DoctrineBundle\\DoctrineBundle');
|
||||
}
|
||||
|
||||
protected function parseShortcutNotation($shortcut)
|
||||
{
|
||||
$entity = str_replace('/', '\\', $shortcut);
|
||||
|
||||
if (false === $pos = strpos($entity, ':')) {
|
||||
throw new \InvalidArgumentException(sprintf('The entity name must contain a : ("%s" given, expecting something like AcmeBlogBundle:Blog/Post)', $entity));
|
||||
}
|
||||
|
||||
return array(substr($entity, 0, $pos), substr($entity, $pos + 1));
|
||||
}
|
||||
|
||||
protected function getEntityMetadata($entity)
|
||||
{
|
||||
$factory = new DisconnectedMetadataFactory($this->getContainer()->get('doctrine'));
|
||||
|
||||
return $factory->getClassMetadata($entity)->getMetadata();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,351 @@
|
|||
<?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\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Sensio\Bundle\GeneratorBundle\Command\AutoComplete\EntitiesAutoCompleter;
|
||||
use Sensio\Bundle\GeneratorBundle\Command\Helper\QuestionHelper;
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGenerator;
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineFormGenerator;
|
||||
use Sensio\Bundle\GeneratorBundle\Manipulator\RoutingManipulator;
|
||||
|
||||
/**
|
||||
* Generates a CRUD for a Doctrine entity.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class GenerateDoctrineCrudCommand extends GenerateDoctrineCommand
|
||||
{
|
||||
private $formGenerator;
|
||||
|
||||
/**
|
||||
* @see Command
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('doctrine:generate:crud')
|
||||
->setAliases(array('generate:doctrine:crud'))
|
||||
->setDescription('Generates a CRUD based on a Doctrine entity')
|
||||
->addArgument('entity', InputArgument::OPTIONAL, 'The entity class name to initialize (shortcut notation)')
|
||||
->addOption('entity', null, InputOption::VALUE_OPTIONAL, 'The entity class name to initialize (shortcut notation)')
|
||||
->addOption('route-prefix', null, InputOption::VALUE_REQUIRED, 'The route prefix')
|
||||
->addOption('with-write', null, InputOption::VALUE_NONE, 'Whether or not to generate create, new and delete actions')
|
||||
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The format used for configuration files (php, xml, yml, or annotation)', 'annotation')
|
||||
->addOption('overwrite', null, InputOption::VALUE_NONE, 'Overwrite any existing controller or form class when generating the CRUD contents')
|
||||
->setHelp(<<<EOT
|
||||
The <info>%command.name%</info> command generates a CRUD based on a Doctrine entity.
|
||||
|
||||
The default command only generates the list and show actions.
|
||||
|
||||
<info>php %command.full_name% AcmeBlogBundle:Post --route-prefix=post_admin</info>
|
||||
|
||||
Using the --with-write option allows to generate the new, edit and delete actions.
|
||||
|
||||
<info>php %command.full_name% AcmeBlogBundle:Post --route-prefix=post_admin --with-write</info>
|
||||
|
||||
Every generated file is based on a template. There are default templates but they can be overridden by placing custom templates in one of the following locations, by order of priority:
|
||||
|
||||
<info>BUNDLE_PATH/Resources/SensioGeneratorBundle/skeleton/crud
|
||||
APP_PATH/Resources/SensioGeneratorBundle/skeleton/crud</info>
|
||||
|
||||
And
|
||||
|
||||
<info>__bundle_path__/Resources/SensioGeneratorBundle/skeleton/form
|
||||
__project_root__/app/Resources/SensioGeneratorBundle/skeleton/form</info>
|
||||
|
||||
You can check https://github.com/sensio/SensioGeneratorBundle/tree/master/Resources/skeleton
|
||||
in order to know the file structure of the skeleton
|
||||
EOT
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Command
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$questionHelper = $this->getQuestionHelper();
|
||||
|
||||
if ($input->isInteractive()) {
|
||||
$question = new ConfirmationQuestion($questionHelper->getQuestion('Do you confirm generation', 'yes', '?'), true);
|
||||
if (!$questionHelper->ask($input, $output, $question)) {
|
||||
$output->writeln('<error>Command aborted</error>');
|
||||
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
// BC to be removed in 4.0
|
||||
if ($input->hasOption('entity') && $entityOption = $input->getOption('entity')) {
|
||||
@trigger_error('Using the "--entity" option has been deprecated since version 3.0 and will be removed in 4.0. Pass it as argument instead.', E_USER_DEPRECATED);
|
||||
|
||||
$input->setArgument('entity', $entityOption);
|
||||
}
|
||||
}
|
||||
|
||||
$entity = Validators::validateEntityName($input->getArgument('entity'));
|
||||
list($bundle, $entity) = $this->parseShortcutNotation($entity);
|
||||
|
||||
$format = Validators::validateFormat($input->getOption('format'));
|
||||
$prefix = $this->getRoutePrefix($input, $entity);
|
||||
$withWrite = $input->getOption('with-write');
|
||||
$forceOverwrite = $input->getOption('overwrite');
|
||||
|
||||
$questionHelper->writeSection($output, 'CRUD generation');
|
||||
|
||||
try {
|
||||
$entityClass = $this->getContainer()->get('doctrine')->getAliasNamespace($bundle).'\\'.$entity;
|
||||
$metadata = $this->getEntityMetadata($entityClass);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException(sprintf('Entity "%s" does not exist in the "%s" bundle. Create it with the "doctrine:generate:entity" command and then execute this command again.', $entity, $bundle));
|
||||
}
|
||||
|
||||
$bundle = $this->getContainer()->get('kernel')->getBundle($bundle);
|
||||
|
||||
$generator = $this->getGenerator($bundle);
|
||||
$generator->generate($bundle, $entity, $metadata[0], $format, $prefix, $withWrite, $forceOverwrite);
|
||||
|
||||
$output->writeln('Generating the CRUD code: <info>OK</info>');
|
||||
|
||||
$errors = array();
|
||||
$runner = $questionHelper->getRunner($output, $errors);
|
||||
|
||||
// form
|
||||
if ($withWrite) {
|
||||
$this->generateForm($bundle, $entity, $metadata, $forceOverwrite);
|
||||
$output->writeln('Generating the Form code: <info>OK</info>');
|
||||
}
|
||||
|
||||
// routing
|
||||
$output->write('Updating the routing: ');
|
||||
if ('annotation' != $format) {
|
||||
$runner($this->updateRouting($questionHelper, $input, $output, $bundle, $format, $entity, $prefix));
|
||||
} else {
|
||||
$runner($this->updateAnnotationRouting($bundle, $entity, $prefix));
|
||||
}
|
||||
|
||||
$questionHelper->writeGeneratorSummary($output, $errors);
|
||||
}
|
||||
|
||||
protected function interact(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$questionHelper = $this->getQuestionHelper();
|
||||
$questionHelper->writeSection($output, 'Welcome to the Doctrine2 CRUD generator');
|
||||
|
||||
// namespace
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'This command helps you generate CRUD controllers and templates.',
|
||||
'',
|
||||
'First, give the name of the existing entity for which you want to generate a CRUD',
|
||||
'(use the shortcut notation like <comment>AcmeBlogBundle:Post</comment>)',
|
||||
'',
|
||||
));
|
||||
|
||||
if ($input->hasOption('entity') && $entityOption = $input->getOption('entity')) {
|
||||
@trigger_error('Using the "--entity" option has been deprecated since version 3.0 and will be removed in 4.0. Pass it as argument instead.', E_USER_DEPRECATED);
|
||||
|
||||
$input->setArgument('entity', $entityOption);
|
||||
}
|
||||
|
||||
$question = new Question($questionHelper->getQuestion('The Entity shortcut name', $input->getArgument('entity')), $input->getArgument('entity'));
|
||||
$question->setValidator(array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateEntityName'));
|
||||
|
||||
$autocompleter = new EntitiesAutoCompleter($this->getContainer()->get('doctrine')->getManager());
|
||||
$autocompleteEntities = $autocompleter->getSuggestions();
|
||||
$question->setAutocompleterValues($autocompleteEntities);
|
||||
$entity = $questionHelper->ask($input, $output, $question);
|
||||
|
||||
$input->setArgument('entity', $entity);
|
||||
list($bundle, $entity) = $this->parseShortcutNotation($entity);
|
||||
|
||||
try {
|
||||
$entityClass = $this->getContainer()->get('doctrine')->getAliasNamespace($bundle).'\\'.$entity;
|
||||
$metadata = $this->getEntityMetadata($entityClass);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException(sprintf('Entity "%s" does not exist in the "%s" bundle. You may have mistyped the bundle name or maybe the entity doesn\'t exist yet (create it first with the "doctrine:generate:entity" command).', $entity, $bundle));
|
||||
}
|
||||
|
||||
// write?
|
||||
$withWrite = $input->getOption('with-write') ?: false;
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'By default, the generator creates two actions: list and show.',
|
||||
'You can also ask it to generate "write" actions: new, update, and delete.',
|
||||
'',
|
||||
));
|
||||
$question = new ConfirmationQuestion($questionHelper->getQuestion('Do you want to generate the "write" actions', $withWrite ? 'yes' : 'no', '?', $withWrite), $withWrite);
|
||||
|
||||
$withWrite = $questionHelper->ask($input, $output, $question);
|
||||
$input->setOption('with-write', $withWrite);
|
||||
|
||||
// format
|
||||
$format = $input->getOption('format');
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'Determine the format to use for the generated CRUD.',
|
||||
'',
|
||||
));
|
||||
$question = new Question($questionHelper->getQuestion('Configuration format (yml, xml, php, or annotation)', $format), $format);
|
||||
$question->setValidator(array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateFormat'));
|
||||
$format = $questionHelper->ask($input, $output, $question);
|
||||
$input->setOption('format', $format);
|
||||
|
||||
// route prefix
|
||||
$prefix = $this->getRoutePrefix($input, $entity);
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'Determine the routes prefix (all the routes will be "mounted" under this',
|
||||
'prefix: /prefix/, /prefix/new, ...).',
|
||||
'',
|
||||
));
|
||||
$prefix = $questionHelper->ask($input, $output, new Question($questionHelper->getQuestion('Routes prefix', '/'.$prefix), '/'.$prefix));
|
||||
$input->setOption('route-prefix', $prefix);
|
||||
|
||||
// summary
|
||||
$questionHelper->writeSection($output, 'Summary before generation');
|
||||
$output->writeln(array(
|
||||
sprintf('You are going to generate a CRUD controller for "<info>%s:%s</info>"', $bundle, $entity),
|
||||
sprintf('using the "<info>%s</info>" format.', $format),
|
||||
'',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to generate forms if they don't exist yet and if we need write operations on entities.
|
||||
*/
|
||||
protected function generateForm($bundle, $entity, $metadata, $forceOverwrite = false)
|
||||
{
|
||||
$this->getFormGenerator($bundle)->generate($bundle, $entity, $metadata[0], $forceOverwrite);
|
||||
}
|
||||
|
||||
protected function updateRouting(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output, BundleInterface $bundle, $format, $entity, $prefix)
|
||||
{
|
||||
$auto = true;
|
||||
if ($input->isInteractive()) {
|
||||
$question = new ConfirmationQuestion($questionHelper->getQuestion('Confirm automatic update of the Routing', 'yes', '?'), true);
|
||||
$auto = $questionHelper->ask($input, $output, $question);
|
||||
}
|
||||
|
||||
$output->write('Importing the CRUD routes: ');
|
||||
$this->getContainer()->get('filesystem')->mkdir($bundle->getPath().'/Resources/config/');
|
||||
|
||||
// first, import the routing file from the bundle's main routing.yml file
|
||||
$routing = new RoutingManipulator($bundle->getPath().'/Resources/config/routing.yml');
|
||||
try {
|
||||
$ret = $auto ? $routing->addResource($bundle->getName(), $format, '/'.$prefix, 'routing/'.strtolower(str_replace('\\', '_', $entity))) : false;
|
||||
} catch (\RuntimeException $exc) {
|
||||
$ret = false;
|
||||
}
|
||||
|
||||
if (!$ret) {
|
||||
$help = sprintf(" <comment>resource: \"@%s/Resources/config/routing/%s.%s\"</comment>\n", $bundle->getName(), strtolower(str_replace('\\', '_', $entity)), $format);
|
||||
$help .= sprintf(" <comment>prefix: /%s</comment>\n", $prefix);
|
||||
|
||||
return array(
|
||||
'- Import the bundle\'s routing resource in the bundle routing file',
|
||||
sprintf(' (%s).', $bundle->getPath().'/Resources/config/routing.yml'),
|
||||
'',
|
||||
sprintf(' <comment>%s:</comment>', $routing->getImportedResourceYamlKey($bundle->getName(), $prefix)),
|
||||
$help,
|
||||
'',
|
||||
);
|
||||
}
|
||||
|
||||
// second, import the bundle's routing.yml file from the application's routing.yml file
|
||||
$routing = new RoutingManipulator($this->getContainer()->getParameter('kernel.root_dir').'/config/routing.yml');
|
||||
try {
|
||||
$ret = $auto ? $routing->addResource($bundle->getName(), 'yml') : false;
|
||||
} catch (\RuntimeException $e) {
|
||||
// the bundle is already imported form app's routing.yml file
|
||||
$errorMessage = sprintf(
|
||||
"\n\n[ERROR] The bundle's \"Resources/config/routing.yml\" file cannot be imported\n".
|
||||
"from \"app/config/routing.yml\" because the \"%s\" bundle is\n".
|
||||
"already imported. Make sure you are not using two different\n".
|
||||
"configuration/routing formats in the same bundle because it won't work.\n",
|
||||
$bundle->getName()
|
||||
);
|
||||
$output->write($errorMessage);
|
||||
$ret = true;
|
||||
} catch (\Exception $e) {
|
||||
$ret = false;
|
||||
}
|
||||
|
||||
if (!$ret) {
|
||||
return array(
|
||||
'- Import the bundle\'s routing.yml file in the application routing.yml file',
|
||||
sprintf('# app/config/routing.yml'),
|
||||
sprintf('%s:', $bundle->getName()),
|
||||
sprintf(' <comment>resource: "@%s/Resources/config/routing.yml"</comment>', $bundle->getName()),
|
||||
'',
|
||||
'# ...',
|
||||
'',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateAnnotationRouting(BundleInterface $bundle, $entity, $prefix)
|
||||
{
|
||||
$rootDir = $this->getContainer()->getParameter('kernel.root_dir');
|
||||
|
||||
$routing = new RoutingManipulator($rootDir.'/config/routing.yml');
|
||||
|
||||
if (!$routing->hasResourceInAnnotation($bundle->getName())) {
|
||||
$parts = explode('\\', $entity);
|
||||
$controller = array_pop($parts);
|
||||
|
||||
$ret = $routing->addAnnotationController($bundle->getName(), $controller);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getRoutePrefix(InputInterface $input, $entity)
|
||||
{
|
||||
$prefix = $input->getOption('route-prefix') ?: strtolower(str_replace(array('\\', '/'), '_', $entity));
|
||||
|
||||
if ($prefix && '/' === $prefix[0]) {
|
||||
$prefix = substr($prefix, 1);
|
||||
}
|
||||
|
||||
return $prefix;
|
||||
}
|
||||
|
||||
protected function createGenerator($bundle = null)
|
||||
{
|
||||
return new DoctrineCrudGenerator(
|
||||
$this->getContainer()->get('filesystem'),
|
||||
$this->getContainer()->getParameter('kernel.root_dir')
|
||||
);
|
||||
}
|
||||
|
||||
protected function getFormGenerator($bundle = null)
|
||||
{
|
||||
if (null === $this->formGenerator) {
|
||||
$this->formGenerator = new DoctrineFormGenerator($this->getContainer()->get('filesystem'));
|
||||
$this->formGenerator->setSkeletonDirs($this->getSkeletonDirs($bundle));
|
||||
}
|
||||
|
||||
return $this->formGenerator;
|
||||
}
|
||||
|
||||
public function setFormGenerator(DoctrineFormGenerator $formGenerator)
|
||||
{
|
||||
$this->formGenerator = $formGenerator;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,414 @@
|
|||
<?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\Command;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineEntityGenerator;
|
||||
use Sensio\Bundle\GeneratorBundle\Command\Helper\QuestionHelper;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
|
||||
/**
|
||||
* Initializes a Doctrine entity inside a bundle.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class GenerateDoctrineEntityCommand extends GenerateDoctrineCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('doctrine:generate:entity')
|
||||
->setAliases(array('generate:doctrine:entity'))
|
||||
->setDescription('Generates a new Doctrine entity inside a bundle')
|
||||
->addArgument('entity', InputArgument::OPTIONAL, 'The entity class name to initialize (shortcut notation)')
|
||||
->addOption('entity', null, InputOption::VALUE_OPTIONAL, 'The entity class name to initialize (shortcut notation)')
|
||||
->addOption('fields', null, InputOption::VALUE_REQUIRED, 'The fields to create with the new entity')
|
||||
->addOption('format', null, InputOption::VALUE_REQUIRED, 'Use the format for configuration files (php, xml, yml, or annotation)', 'annotation')
|
||||
->setHelp(<<<EOT
|
||||
The <info>%command.name%</info> task generates a new Doctrine
|
||||
entity inside a bundle:
|
||||
|
||||
<info>php %command.full_name% AcmeBlogBundle:Blog/Post</info>
|
||||
|
||||
The above command would initialize a new entity in the following entity
|
||||
namespace <info>Acme\BlogBundle\Entity\Blog\Post</info>.
|
||||
|
||||
You can also optionally specify the fields you want to generate in the new
|
||||
entity:
|
||||
|
||||
<info>php %command.full_name% AcmeBlogBundle:Blog/Post --fields="title:string(255) body:text"</info>
|
||||
|
||||
By default, the command uses annotations for the mapping information; change it
|
||||
with <comment>--format</comment>:
|
||||
|
||||
<info>php %command.full_name% AcmeBlogBundle:Blog/Post --format=yml</info>
|
||||
|
||||
To deactivate the interaction mode, simply use the <comment>--no-interaction</comment> option or its
|
||||
alias <comment>-n</comment>, without forgetting to pass all needed options:
|
||||
|
||||
<info>php %command.full_name% AcmeBlogBundle:Blog/Post -n --format=annotation --fields="title:string(255) body:text"</info>
|
||||
|
||||
This also has support for passing field specific attributes:
|
||||
|
||||
<info>php %command.full_name% AcmeBlogBundle:Blog/Post -n --format=annotation --fields="title:string(length=255 nullable=true unique=true) body:text ranking:decimal(precision=10 scale=0)"</info>
|
||||
EOT
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \InvalidArgumentException When the bundle doesn't end with Bundle (Example: "Bundle/MySampleBundle")
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$questionHelper = $this->getQuestionHelper();
|
||||
|
||||
// BC to be removed in 4.0
|
||||
if (!$input->isInteractive() && $input->hasOption('entity') && $entityOption = $input->getOption('entity')) {
|
||||
@trigger_error('Using the "--entity" option has been deprecated since version 3.0 and will be removed in 4.0. Pass it as argument instead.', E_USER_DEPRECATED);
|
||||
|
||||
$input->setArgument('entity', $entityOption);
|
||||
}
|
||||
|
||||
$entity = Validators::validateEntityName($input->getArgument('entity'));
|
||||
list($bundle, $entity) = $this->parseShortcutNotation($entity);
|
||||
$format = Validators::validateFormat($input->getOption('format'));
|
||||
$fields = $this->parseFields($input->getOption('fields'));
|
||||
|
||||
$questionHelper->writeSection($output, 'Entity generation');
|
||||
|
||||
$bundle = $this->getContainer()->get('kernel')->getBundle($bundle);
|
||||
|
||||
/** @var DoctrineEntityGenerator $generator */
|
||||
$generator = $this->getGenerator();
|
||||
$generatorResult = $generator->generate($bundle, $entity, $format, array_values($fields));
|
||||
|
||||
$output->writeln(sprintf(
|
||||
'> Generating entity class <info>%s</info>: <comment>OK!</comment>',
|
||||
$this->makePathRelative($generatorResult->getEntityPath())
|
||||
));
|
||||
$output->writeln(sprintf(
|
||||
'> Generating repository class <info>%s</info>: <comment>OK!</comment>',
|
||||
$this->makePathRelative($generatorResult->getRepositoryPath())
|
||||
));
|
||||
if ($generatorResult->getMappingPath()) {
|
||||
$output->writeln(sprintf(
|
||||
'> Generating mapping file <info>%s</info>: <comment>OK!</comment>',
|
||||
$this->makePathRelative($generatorResult->getMappingPath())
|
||||
));
|
||||
}
|
||||
|
||||
$questionHelper->writeGeneratorSummary($output, array());
|
||||
}
|
||||
|
||||
protected function interact(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$questionHelper = $this->getQuestionHelper();
|
||||
$questionHelper->writeSection($output, 'Welcome to the Doctrine2 entity generator');
|
||||
|
||||
// namespace
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'This command helps you generate Doctrine2 entities.',
|
||||
'',
|
||||
'First, you need to give the entity name you want to generate.',
|
||||
'You must use the shortcut notation like <comment>AcmeBlogBundle:Post</comment>.',
|
||||
'',
|
||||
));
|
||||
|
||||
if ($input->hasOption('entity') && $entityOption = $input->getOption('entity')) {
|
||||
@trigger_error('Using the "--entity" option has been deprecated since version 3.0 and will be removed in 4.0. Pass it as argument instead.', E_USER_DEPRECATED);
|
||||
|
||||
$input->setArgument('entity', $entityOption);
|
||||
}
|
||||
|
||||
$bundleNames = array_keys($this->getContainer()->get('kernel')->getBundles());
|
||||
|
||||
while (true) {
|
||||
$question = new Question($questionHelper->getQuestion('The Entity shortcut name', $input->getArgument('entity')), $input->getArgument('entity'));
|
||||
$question->setValidator(array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateEntityName'));
|
||||
$question->setAutocompleterValues($bundleNames);
|
||||
$entity = $questionHelper->ask($input, $output, $question);
|
||||
|
||||
list($bundle, $entity) = $this->parseShortcutNotation($entity);
|
||||
|
||||
// check reserved words
|
||||
if ($this->getGenerator()->isReservedKeyword($entity)) {
|
||||
$output->writeln(sprintf('<bg=red> "%s" is a reserved word</>.', $entity));
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$b = $this->getContainer()->get('kernel')->getBundle($bundle);
|
||||
|
||||
if (!file_exists($b->getPath().'/Entity/'.str_replace('\\', '/', $entity).'.php')) {
|
||||
break;
|
||||
}
|
||||
|
||||
$output->writeln(sprintf('<bg=red>Entity "%s:%s" already exists</>.', $bundle, $entity));
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln(sprintf('<bg=red>Bundle "%s" does not exist.</>', $bundle));
|
||||
}
|
||||
}
|
||||
$input->setArgument('entity', $bundle.':'.$entity);
|
||||
|
||||
// format
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'Determine the format to use for the mapping information.',
|
||||
'',
|
||||
));
|
||||
|
||||
$formats = array('yml', 'xml', 'php', 'annotation');
|
||||
|
||||
$question = new Question($questionHelper->getQuestion('Configuration format (yml, xml, php, or annotation)', $input->getOption('format')), $input->getOption('format'));
|
||||
$question->setValidator(array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateFormat'));
|
||||
$question->setAutocompleterValues($formats);
|
||||
$format = $questionHelper->ask($input, $output, $question);
|
||||
$input->setOption('format', $format);
|
||||
|
||||
// fields
|
||||
$input->setOption('fields', $this->addFields($input, $output, $questionHelper));
|
||||
}
|
||||
|
||||
private function parseFields($input)
|
||||
{
|
||||
if (is_array($input)) {
|
||||
return $input;
|
||||
}
|
||||
|
||||
$fields = array();
|
||||
foreach (preg_split('{(?:\([^\(]*\))(*SKIP)(*F)|\s+}', $input) as $value) {
|
||||
$elements = explode(':', $value);
|
||||
$name = $elements[0];
|
||||
$fieldAttributes = array();
|
||||
if (strlen($name)) {
|
||||
$fieldAttributes['fieldName'] = $name;
|
||||
$type = isset($elements[1]) ? $elements[1] : 'string';
|
||||
preg_match_all('{(.*)\((.*)\)}', $type, $matches);
|
||||
$fieldAttributes['type'] = isset($matches[1][0]) ? $matches[1][0] : $type;
|
||||
$length = null;
|
||||
if ('string' === $fieldAttributes['type']) {
|
||||
$fieldAttributes['length'] = $length;
|
||||
}
|
||||
if (isset($matches[2][0]) && $length = $matches[2][0]) {
|
||||
$attributesFound = array();
|
||||
if (false !== strpos($length, '=')) {
|
||||
preg_match_all('{([^,= ]+)=([^,= ]+)}', $length, $result);
|
||||
$attributesFound = array_combine($result[1], $result[2]);
|
||||
} else {
|
||||
$fieldAttributes['length'] = $length;
|
||||
}
|
||||
$fieldAttributes = array_merge($fieldAttributes, $attributesFound);
|
||||
foreach (array('length', 'precision', 'scale') as $intAttribute) {
|
||||
if (isset($fieldAttributes[$intAttribute])) {
|
||||
$fieldAttributes[$intAttribute] = (int) $fieldAttributes[$intAttribute];
|
||||
}
|
||||
}
|
||||
foreach (array('nullable', 'unique') as $boolAttribute) {
|
||||
if (isset($fieldAttributes[$boolAttribute])) {
|
||||
$fieldAttributes[$boolAttribute] = filter_var($fieldAttributes[$boolAttribute], FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$fields[$name] = $fieldAttributes;
|
||||
}
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
private function addFields(InputInterface $input, OutputInterface $output, QuestionHelper $questionHelper)
|
||||
{
|
||||
$fields = $this->parseFields($input->getOption('fields'));
|
||||
$output->writeln(array(
|
||||
'',
|
||||
'Instead of starting with a blank entity, you can add some fields now.',
|
||||
'Note that the primary key will be added automatically (named <comment>id</comment>).',
|
||||
'',
|
||||
));
|
||||
$output->write('<info>Available types:</info> ');
|
||||
|
||||
$types = array_keys(Type::getTypesMap());
|
||||
$count = 20;
|
||||
foreach ($types as $i => $type) {
|
||||
if ($count > 50) {
|
||||
$count = 0;
|
||||
$output->writeln('');
|
||||
}
|
||||
$count += strlen($type);
|
||||
$output->write(sprintf('<comment>%s</comment>', $type));
|
||||
if (count($types) != $i + 1) {
|
||||
$output->write(', ');
|
||||
} else {
|
||||
$output->write('.');
|
||||
}
|
||||
}
|
||||
$output->writeln('');
|
||||
|
||||
$fieldValidator = function ($type) use ($types) {
|
||||
if (!in_array($type, $types)) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid type "%s".', $type));
|
||||
}
|
||||
|
||||
return $type;
|
||||
};
|
||||
|
||||
$lengthValidator = function ($length) {
|
||||
if (!$length) {
|
||||
return $length;
|
||||
}
|
||||
|
||||
$result = filter_var($length, FILTER_VALIDATE_INT, array(
|
||||
'options' => array('min_range' => 1),
|
||||
));
|
||||
|
||||
if (false === $result) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid length "%s".', $length));
|
||||
}
|
||||
|
||||
return $length;
|
||||
};
|
||||
|
||||
$boolValidator = function ($value) {
|
||||
if (null === $valueAsBool = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid bool value "%s".', $value));
|
||||
}
|
||||
|
||||
return $valueAsBool;
|
||||
};
|
||||
|
||||
$precisionValidator = function ($precision) {
|
||||
if (!$precision) {
|
||||
return $precision;
|
||||
}
|
||||
|
||||
$result = filter_var($precision, FILTER_VALIDATE_INT, array(
|
||||
'options' => array('min_range' => 1, 'max_range' => 65),
|
||||
));
|
||||
|
||||
if (false === $result) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid precision "%s".', $precision));
|
||||
}
|
||||
|
||||
return $precision;
|
||||
};
|
||||
|
||||
$scaleValidator = function ($scale) {
|
||||
if (!$scale) {
|
||||
return $scale;
|
||||
}
|
||||
|
||||
$result = filter_var($scale, FILTER_VALIDATE_INT, array(
|
||||
'options' => array('min_range' => 0, 'max_range' => 30),
|
||||
));
|
||||
|
||||
if (false === $result) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid scale "%s".', $scale));
|
||||
}
|
||||
|
||||
return $scale;
|
||||
};
|
||||
|
||||
while (true) {
|
||||
$output->writeln('');
|
||||
$generator = $this->getGenerator();
|
||||
$question = new Question($questionHelper->getQuestion('New field name (press <return> to stop adding fields)', null), null);
|
||||
$question->setValidator(function ($name) use ($fields, $generator) {
|
||||
if (isset($fields[$name]) || 'id' == $name) {
|
||||
throw new \InvalidArgumentException(sprintf('Field "%s" is already defined.', $name));
|
||||
}
|
||||
|
||||
// check reserved words
|
||||
if ($generator->isReservedKeyword($name)) {
|
||||
throw new \InvalidArgumentException(sprintf('Name "%s" is a reserved word.', $name));
|
||||
}
|
||||
|
||||
// check for valid PHP variable name
|
||||
if (!is_null($name) && !$generator->isValidPhpVariableName($name)) {
|
||||
throw new \InvalidArgumentException(sprintf('"%s" is not a valid PHP variable name.', $name));
|
||||
}
|
||||
|
||||
return $name;
|
||||
});
|
||||
|
||||
$columnName = $questionHelper->ask($input, $output, $question);
|
||||
if (!$columnName) {
|
||||
break;
|
||||
}
|
||||
|
||||
$defaultType = 'string';
|
||||
|
||||
// try to guess the type by the column name prefix/suffix
|
||||
if (substr($columnName, -3) == '_at') {
|
||||
$defaultType = 'datetime';
|
||||
} elseif (substr($columnName, -3) == '_id') {
|
||||
$defaultType = 'integer';
|
||||
} elseif (substr($columnName, 0, 3) == 'is_') {
|
||||
$defaultType = 'boolean';
|
||||
} elseif (substr($columnName, 0, 4) == 'has_') {
|
||||
$defaultType = 'boolean';
|
||||
}
|
||||
|
||||
$question = new Question($questionHelper->getQuestion('Field type', $defaultType), $defaultType);
|
||||
$question->setValidator($fieldValidator);
|
||||
$question->setAutocompleterValues($types);
|
||||
$type = $questionHelper->ask($input, $output, $question);
|
||||
|
||||
$data = array('columnName' => $columnName, 'fieldName' => lcfirst(Container::camelize($columnName)), 'type' => $type);
|
||||
|
||||
if ($type == 'string') {
|
||||
$question = new Question($questionHelper->getQuestion('Field length', 255), 255);
|
||||
$question->setValidator($lengthValidator);
|
||||
$data['length'] = $questionHelper->ask($input, $output, $question);
|
||||
} elseif ('decimal' === $type) {
|
||||
// 10 is the default value given in \Doctrine\DBAL\Schema\Column::$_precision
|
||||
$question = new Question($questionHelper->getQuestion('Precision', 10), 10);
|
||||
$question->setValidator($precisionValidator);
|
||||
$data['precision'] = $questionHelper->ask($input, $output, $question);
|
||||
|
||||
// 0 is the default value given in \Doctrine\DBAL\Schema\Column::$_scale
|
||||
$question = new Question($questionHelper->getQuestion('Scale', 0), 0);
|
||||
$question->setValidator($scaleValidator);
|
||||
$data['scale'] = $questionHelper->ask($input, $output, $question);
|
||||
}
|
||||
|
||||
$question = new Question($questionHelper->getQuestion('Is nullable', 'false'), false);
|
||||
$question->setValidator($boolValidator);
|
||||
$question->setAutocompleterValues(array('true', 'false'));
|
||||
if ($nullable = $questionHelper->ask($input, $output, $question)) {
|
||||
$data['nullable'] = $nullable;
|
||||
}
|
||||
|
||||
$question = new Question($questionHelper->getQuestion('Unique', 'false'), false);
|
||||
$question->setValidator($boolValidator);
|
||||
$question->setAutocompleterValues(array('true', 'false'));
|
||||
if ($unique = $questionHelper->ask($input, $output, $question)) {
|
||||
$data['unique'] = $unique;
|
||||
}
|
||||
|
||||
$fields[$columnName] = $data;
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
protected function createGenerator()
|
||||
{
|
||||
return new DoctrineEntityGenerator($this->getContainer()->get('filesystem'), $this->getContainer()->get('doctrine'));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<?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\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineFormGenerator;
|
||||
|
||||
/**
|
||||
* Generates a form type class for a given Doctrine entity.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Hugo Hamon <hugo.hamon@sensio.com>
|
||||
*/
|
||||
class GenerateDoctrineFormCommand extends GenerateDoctrineCommand
|
||||
{
|
||||
/**
|
||||
* @see Command
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('doctrine:generate:form')
|
||||
->setAliases(array('generate:doctrine:form'))
|
||||
->setDescription('Generates a form type class based on a Doctrine entity')
|
||||
->setDefinition(array(
|
||||
new InputArgument('entity', InputArgument::REQUIRED, 'The entity class name to initialize (shortcut notation)'),
|
||||
))
|
||||
->setHelp(<<<EOT
|
||||
The <info>%command.name%</info> command generates a form class based on a Doctrine entity.
|
||||
|
||||
<info>php %command.full_name% AcmeBlogBundle:Post</info>
|
||||
|
||||
Every generated file is based on a template. There are default templates but they can be overridden by placing custom templates in one of the following locations, by order of priority:
|
||||
|
||||
<info>BUNDLE_PATH/Resources/SensioGeneratorBundle/skeleton/form
|
||||
APP_PATH/Resources/SensioGeneratorBundle/skeleton/form</info>
|
||||
|
||||
You can check https://github.com/sensio/SensioGeneratorBundle/tree/master/Resources/skeleton
|
||||
in order to know the file structure of the skeleton
|
||||
EOT
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Command
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$entity = Validators::validateEntityName($input->getArgument('entity'));
|
||||
list($bundle, $entity) = $this->parseShortcutNotation($entity);
|
||||
|
||||
$entityClass = $this->getContainer()->get('doctrine')->getAliasNamespace($bundle).'\\'.$entity;
|
||||
$metadata = $this->getEntityMetadata($entityClass);
|
||||
$bundle = $this->getApplication()->getKernel()->getBundle($bundle);
|
||||
$generator = $this->getGenerator($bundle);
|
||||
|
||||
$generator->generate($bundle, $entity, $metadata[0]);
|
||||
|
||||
$output->writeln(sprintf(
|
||||
'The new %s.php class file has been created under %s.',
|
||||
$generator->getClassName(),
|
||||
$generator->getClassPath()
|
||||
));
|
||||
}
|
||||
|
||||
protected function createGenerator()
|
||||
{
|
||||
return new DoctrineFormGenerator($this->getContainer()->get('filesystem'));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
<?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\Command;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\Generator;
|
||||
use Sensio\Bundle\GeneratorBundle\Command\Helper\QuestionHelper;
|
||||
|
||||
/**
|
||||
* Base class for generator commands.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
abstract class GeneratorCommand extends ContainerAwareCommand
|
||||
{
|
||||
/**
|
||||
* @var Generator
|
||||
*/
|
||||
private $generator;
|
||||
|
||||
// only useful for unit tests
|
||||
public function setGenerator(Generator $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
abstract protected function createGenerator();
|
||||
|
||||
protected function getGenerator(BundleInterface $bundle = null)
|
||||
{
|
||||
if (null === $this->generator) {
|
||||
$this->generator = $this->createGenerator();
|
||||
$this->generator->setSkeletonDirs($this->getSkeletonDirs($bundle));
|
||||
}
|
||||
|
||||
return $this->generator;
|
||||
}
|
||||
|
||||
protected function getSkeletonDirs(BundleInterface $bundle = null)
|
||||
{
|
||||
$skeletonDirs = array();
|
||||
|
||||
if (isset($bundle) && is_dir($dir = $bundle->getPath().'/Resources/SensioGeneratorBundle/skeleton')) {
|
||||
$skeletonDirs[] = $dir;
|
||||
}
|
||||
|
||||
if (is_dir($dir = $this->getContainer()->get('kernel')->getRootdir().'/Resources/SensioGeneratorBundle/skeleton')) {
|
||||
$skeletonDirs[] = $dir;
|
||||
}
|
||||
|
||||
$skeletonDirs[] = __DIR__.'/../Resources/skeleton';
|
||||
$skeletonDirs[] = __DIR__.'/../Resources';
|
||||
|
||||
return $skeletonDirs;
|
||||
}
|
||||
|
||||
protected function getQuestionHelper()
|
||||
{
|
||||
$question = $this->getHelperSet()->get('question');
|
||||
if (!$question || get_class($question) !== 'Sensio\Bundle\GeneratorBundle\Command\Helper\QuestionHelper') {
|
||||
$this->getHelperSet()->set($question = new QuestionHelper());
|
||||
}
|
||||
|
||||
return $question;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to make a path relative to the project, which prints nicer.
|
||||
*
|
||||
* @param string $absolutePath
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function makePathRelative($absolutePath)
|
||||
{
|
||||
$projectRootDir = dirname($this->getContainer()->getParameter('kernel.root_dir'));
|
||||
|
||||
return str_replace($projectRootDir.'/', '', realpath($absolutePath) ?: $absolutePath);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<?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\Command\Helper;
|
||||
|
||||
use Symfony\Component\Console\Helper\QuestionHelper as BaseQuestionHelper;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Generates bundles.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class QuestionHelper extends BaseQuestionHelper
|
||||
{
|
||||
public function writeGeneratorSummary(OutputInterface $output, $errors)
|
||||
{
|
||||
if (!$errors) {
|
||||
$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\'ll need to make the following changes manually.',
|
||||
), 'error');
|
||||
|
||||
$output->writeln($errors);
|
||||
}
|
||||
}
|
||||
|
||||
public function getRunner(OutputInterface $output, &$errors)
|
||||
{
|
||||
$runner = function ($err) use ($output, &$errors) {
|
||||
if ($err) {
|
||||
$output->writeln('<fg=red>FAILED</>');
|
||||
$errors = array_merge($errors, $err);
|
||||
} else {
|
||||
$output->writeln('<info>OK</info>');
|
||||
}
|
||||
};
|
||||
|
||||
return $runner;
|
||||
}
|
||||
|
||||
public function writeSection(OutputInterface $output, $text, $style = 'bg=blue;fg=white')
|
||||
{
|
||||
$output->writeln(array(
|
||||
'',
|
||||
$this->getHelperSet()->get('formatter')->formatBlock($text, $style, true),
|
||||
'',
|
||||
));
|
||||
}
|
||||
|
||||
public function getQuestion($question, $default, $sep = ':')
|
||||
{
|
||||
return $default ? sprintf('<info>%s</info> [<comment>%s</comment>]%s ', $question, $default, $sep) : sprintf('<info>%s</info>%s ', $question, $sep);
|
||||
}
|
||||
}
|
||||
210
trunk/_vendor/sensio/generator-bundle/Command/Validators.php
Normal file
210
trunk/_vendor/sensio/generator-bundle/Command/Validators.php
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
<?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\Command;
|
||||
|
||||
/**
|
||||
* Validator functions.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
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)) {
|
||||
throw new \InvalidArgumentException('The namespace must end with Bundle.');
|
||||
}
|
||||
|
||||
$namespace = strtr($namespace, '/', '\\');
|
||||
if (!preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\\\?)+$/', $namespace)) {
|
||||
throw new \InvalidArgumentException('The namespace contains invalid characters.');
|
||||
}
|
||||
|
||||
// validate reserved keywords
|
||||
$reserved = self::getReservedWords();
|
||||
foreach (explode('\\', $namespace) as $word) {
|
||||
if (in_array(strtolower($word), $reserved)) {
|
||||
throw new \InvalidArgumentException(sprintf('The namespace cannot contain PHP reserved words ("%s").', $word));
|
||||
}
|
||||
}
|
||||
|
||||
// validate that the namespace is at least one level deep
|
||||
if ($requireVendorNamespace && false === strpos($namespace, '\\')) {
|
||||
$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")?';
|
||||
|
||||
throw new \InvalidArgumentException(implode("\n\n", $msg));
|
||||
}
|
||||
|
||||
return $namespace;
|
||||
}
|
||||
|
||||
public static function validateBundleName($bundle)
|
||||
{
|
||||
if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $bundle)) {
|
||||
throw new \InvalidArgumentException(sprintf('The bundle name %s contains invalid characters.', $bundle));
|
||||
}
|
||||
|
||||
if (!preg_match('/Bundle$/', $bundle)) {
|
||||
throw new \InvalidArgumentException('The bundle name must end with Bundle.');
|
||||
}
|
||||
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
public static function validateControllerName($controller)
|
||||
{
|
||||
try {
|
||||
self::validateEntityName($controller);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf(
|
||||
'The controller name must contain a : ("%s" given, expecting something like AcmeBlogBundle:Post)',
|
||||
$controller
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
return $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs basic checks in entity name.
|
||||
*
|
||||
* @param string $entity
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function validateEntityName($entity)
|
||||
{
|
||||
if (!preg_match('{^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*:[a-zA-Z0-9_\x7f-\xff\\\/]+$}', $entity)) {
|
||||
throw new \InvalidArgumentException(sprintf('The entity name isn\'t valid ("%s" given, expecting something like AcmeBlogBundle:Blog/Post)', $entity));
|
||||
}
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
public static function getReservedWords()
|
||||
{
|
||||
return array(
|
||||
'abstract',
|
||||
'and',
|
||||
'array',
|
||||
'as',
|
||||
'break',
|
||||
'callable',
|
||||
'case',
|
||||
'catch',
|
||||
'class',
|
||||
'clone',
|
||||
'const',
|
||||
'continue',
|
||||
'declare',
|
||||
'default',
|
||||
'do',
|
||||
'else',
|
||||
'elseif',
|
||||
'enddeclare',
|
||||
'endfor',
|
||||
'endforeach',
|
||||
'endif',
|
||||
'endswitch',
|
||||
'endwhile',
|
||||
'extends',
|
||||
'final',
|
||||
'finally',
|
||||
'for',
|
||||
'foreach',
|
||||
'function',
|
||||
'global',
|
||||
'goto',
|
||||
'if',
|
||||
'implements',
|
||||
'interface',
|
||||
'instanceof',
|
||||
'insteadof',
|
||||
'namespace',
|
||||
'new',
|
||||
'or',
|
||||
'private',
|
||||
'protected',
|
||||
'public',
|
||||
'static',
|
||||
'switch',
|
||||
'throw',
|
||||
'trait',
|
||||
'try',
|
||||
'use',
|
||||
'var',
|
||||
'while',
|
||||
'xor',
|
||||
'yield',
|
||||
'__CLASS__',
|
||||
'__DIR__',
|
||||
'__FILE__',
|
||||
'__LINE__',
|
||||
'__FUNCTION__',
|
||||
'__METHOD__',
|
||||
'__NAMESPACE__',
|
||||
'__TRAIT__',
|
||||
'__halt_compiler',
|
||||
'die',
|
||||
'echo',
|
||||
'empty',
|
||||
'exit',
|
||||
'eval',
|
||||
'include',
|
||||
'include_once',
|
||||
'isset',
|
||||
'list',
|
||||
'require',
|
||||
'require_once',
|
||||
'return',
|
||||
'print',
|
||||
'unset',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<?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\Generator;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Model\Bundle;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
/**
|
||||
* Generates a bundle.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class BundleGenerator extends Generator
|
||||
{
|
||||
private $filesystem;
|
||||
|
||||
public function __construct(Filesystem $filesystem)
|
||||
{
|
||||
$this->filesystem = $filesystem;
|
||||
}
|
||||
|
||||
public function generateBundle(Bundle $bundle)
|
||||
{
|
||||
$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)));
|
||||
}
|
||||
$files = scandir($dir);
|
||||
if ($files != array('.', '..')) {
|
||||
throw new \RuntimeException(sprintf('Unable to generate the bundle as the target directory "%s" is not empty.', realpath($dir)));
|
||||
}
|
||||
if (!is_writable($dir)) {
|
||||
throw new \RuntimeException(sprintf('Unable to generate the bundle as the target directory "%s" is not writable.', realpath($dir)));
|
||||
}
|
||||
}
|
||||
|
||||
$parameters = array(
|
||||
'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->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', $bundle->getTestsDirectory().'/Controller/DefaultControllerTest.php', $parameters);
|
||||
$this->renderFile('bundle/index.html.twig.twig', $dir.'/Resources/views/Default/index.html.twig', $parameters);
|
||||
|
||||
// render the services.yml/xml file
|
||||
$servicesFilename = $bundle->getServicesConfigurationFilename();
|
||||
$this->renderFile(
|
||||
sprintf('bundle/%s.twig', $servicesFilename),
|
||||
$dir.'/Resources/config/'.$servicesFilename, $parameters
|
||||
);
|
||||
|
||||
if ($routingFilename = $bundle->getRoutingConfigurationFilename()) {
|
||||
$this->renderFile(
|
||||
sprintf('bundle/%s.twig', $routingFilename),
|
||||
$dir.'/Resources/config/'.$routingFilename, $parameters
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<?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\Generator;
|
||||
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
|
||||
|
||||
/**
|
||||
* Generates a Command inside a bundle.
|
||||
*
|
||||
* @author Javier Eguiluz <javier.eguiluz@gmail.com>
|
||||
*/
|
||||
class CommandGenerator extends Generator
|
||||
{
|
||||
private $filesystem;
|
||||
|
||||
public function __construct(Filesystem $filesystem)
|
||||
{
|
||||
$this->filesystem = $filesystem;
|
||||
}
|
||||
|
||||
public function generate(BundleInterface $bundle, $name)
|
||||
{
|
||||
$bundleDir = $bundle->getPath();
|
||||
$commandDir = $bundleDir.'/Command';
|
||||
self::mkdir($commandDir);
|
||||
|
||||
$commandClassName = $this->classify($name).'Command';
|
||||
$commandFile = $commandDir.'/'.$commandClassName.'.php';
|
||||
if ($this->filesystem->exists($commandFile)) {
|
||||
throw new \RuntimeException(sprintf('Command "%s" already exists', $name));
|
||||
}
|
||||
|
||||
$parameters = array(
|
||||
'namespace' => $bundle->getNamespace(),
|
||||
'class_name' => $commandClassName,
|
||||
'name' => $name,
|
||||
);
|
||||
|
||||
$this->renderFile('command/Command.php.twig', $commandFile, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the given string to a new string valid as a PHP class name
|
||||
* ('app:my-project' -> 'AppMyProject', 'app:namespace:name' -> 'AppNamespaceName').
|
||||
*
|
||||
* @param string $string
|
||||
*
|
||||
* @return string The string transformed to be a valid PHP class name
|
||||
*/
|
||||
public function classify($string)
|
||||
{
|
||||
return str_replace(' ', '', ucwords(strtr($string, '_-:', ' ')));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
<?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\Generator;
|
||||
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
|
||||
|
||||
/**
|
||||
* Generates a Controller inside a bundle.
|
||||
*
|
||||
* @author Wouter J <wouter@wouterj.nl>
|
||||
*/
|
||||
class ControllerGenerator extends Generator
|
||||
{
|
||||
private $filesystem;
|
||||
|
||||
public function __construct(Filesystem $filesystem)
|
||||
{
|
||||
$this->filesystem = $filesystem;
|
||||
}
|
||||
|
||||
public function generate(BundleInterface $bundle, $controller, $routeFormat, $templateFormat, array $actions = array())
|
||||
{
|
||||
$dir = $bundle->getPath();
|
||||
$controllerFile = $dir.'/Controller/'.$controller.'Controller.php';
|
||||
if (file_exists($controllerFile)) {
|
||||
throw new \RuntimeException(sprintf('Controller "%s" already exists', $controller));
|
||||
}
|
||||
|
||||
$parameters = array(
|
||||
'namespace' => $bundle->getNamespace(),
|
||||
'bundle' => $bundle->getName(),
|
||||
'format' => array(
|
||||
'routing' => $routeFormat,
|
||||
'templating' => $templateFormat,
|
||||
),
|
||||
'controller' => $controller,
|
||||
);
|
||||
|
||||
foreach ($actions as $i => $action) {
|
||||
// get the action name without the suffix Action (for the template logical name)
|
||||
$actions[$i]['basename'] = substr($action['name'], 0, -6);
|
||||
$params = $parameters;
|
||||
$params['action'] = $actions[$i];
|
||||
|
||||
// create a template
|
||||
$template = $actions[$i]['template'];
|
||||
if ('default' == $template) {
|
||||
@trigger_error('The use of the "default" keyword is deprecated. Use the real template name instead.', E_USER_DEPRECATED);
|
||||
$template = $bundle->getName().':'.$controller.':'.
|
||||
strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr(substr($action['name'], 0, -6), '_', '.')))
|
||||
.'.html.'.$templateFormat;
|
||||
}
|
||||
|
||||
if ('twig' == $templateFormat) {
|
||||
$this->renderFile('controller/Template.html.twig.twig', $dir.'/Resources/views/'.$this->parseTemplatePath($template), $params);
|
||||
} else {
|
||||
$this->renderFile('controller/Template.html.php.twig', $dir.'/Resources/views/'.$this->parseTemplatePath($template), $params);
|
||||
}
|
||||
|
||||
$this->generateRouting($bundle, $controller, $actions[$i], $routeFormat);
|
||||
}
|
||||
|
||||
$parameters['actions'] = $actions;
|
||||
|
||||
$this->renderFile('controller/Controller.php.twig', $controllerFile, $parameters);
|
||||
$this->renderFile('controller/ControllerTest.php.twig', $dir.'/Tests/Controller/'.$controller.'ControllerTest.php', $parameters);
|
||||
}
|
||||
|
||||
public function generateRouting(BundleInterface $bundle, $controller, array $action, $format)
|
||||
{
|
||||
// annotation is generated in the templates
|
||||
if ('annotation' == $format) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$file = $bundle->getPath().'/Resources/config/routing.'.$format;
|
||||
if (file_exists($file)) {
|
||||
$content = file_get_contents($file);
|
||||
} elseif (!is_dir($dir = $bundle->getPath().'/Resources/config')) {
|
||||
self::mkdir($dir);
|
||||
}
|
||||
|
||||
$controller = $bundle->getName().':'.$controller.':'.$action['basename'];
|
||||
$name = strtolower(preg_replace('/([A-Z])/', '_\\1', $action['basename']));
|
||||
|
||||
if ('yml' == $format) {
|
||||
// yaml
|
||||
if (!isset($content)) {
|
||||
$content = '';
|
||||
}
|
||||
|
||||
$content .= sprintf(
|
||||
"\n%s:\n path: %s\n defaults: { _controller: %s }\n",
|
||||
$name,
|
||||
$action['route'],
|
||||
$controller
|
||||
);
|
||||
} elseif ('xml' == $format) {
|
||||
// xml
|
||||
if (!isset($content)) {
|
||||
// new file
|
||||
$content = <<<EOT
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
</routes>
|
||||
EOT;
|
||||
}
|
||||
|
||||
$sxe = simplexml_load_string($content);
|
||||
|
||||
$route = $sxe->addChild('route');
|
||||
$route->addAttribute('id', $name);
|
||||
$route->addAttribute('path', $action['route']);
|
||||
|
||||
$default = $route->addChild('default', $controller);
|
||||
$default->addAttribute('key', '_controller');
|
||||
|
||||
$dom = new \DOMDocument('1.0');
|
||||
$dom->preserveWhiteSpace = false;
|
||||
$dom->formatOutput = true;
|
||||
$dom->loadXML($sxe->asXML());
|
||||
$content = $dom->saveXML();
|
||||
} elseif ('php' == $format) {
|
||||
// php
|
||||
if (isset($content)) {
|
||||
// edit current file
|
||||
$pointer = strpos($content, 'return');
|
||||
if (!preg_match('/(\$[^ ]*).*?new RouteCollection\(\)/', $content, $collection) || false === $pointer) {
|
||||
throw new \RuntimeException('Routing.php file is not correct, please initialize RouteCollection.');
|
||||
}
|
||||
|
||||
$content = substr($content, 0, $pointer);
|
||||
$content .= sprintf("%s->add('%s', new Route('%s', array(", $collection[1], $name, $action['route']);
|
||||
$content .= sprintf("\n '_controller' => '%s',", $controller);
|
||||
$content .= "\n)));\n\nreturn ".$collection[1].';';
|
||||
} else {
|
||||
// new file
|
||||
$content = <<<EOT
|
||||
<?php
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
\$collection = new RouteCollection();
|
||||
EOT;
|
||||
$content .= sprintf("\n\$collection->add('%s', new Route('%s', array(", $name, $action['route']);
|
||||
$content .= sprintf("\n '_controller' => '%s',", $controller);
|
||||
$content .= "\n)));\n\nreturn \$collection;";
|
||||
}
|
||||
}
|
||||
|
||||
$flink = fopen($file, 'w');
|
||||
if ($flink) {
|
||||
$write = fwrite($flink, $content);
|
||||
|
||||
if ($write) {
|
||||
fclose($flink);
|
||||
} else {
|
||||
throw new \RuntimeException(sprintf('We cannot write into file "%s", has that file the correct access level?', $file));
|
||||
}
|
||||
} else {
|
||||
throw new \RuntimeException(sprintf('Problems with generating file "%s", did you gave write access to that directory?', $file));
|
||||
}
|
||||
}
|
||||
|
||||
protected function parseTemplatePath($template)
|
||||
{
|
||||
$data = $this->parseLogicalTemplateName($template);
|
||||
|
||||
return $data['controller'].'/'.$data['template'];
|
||||
}
|
||||
|
||||
protected function parseLogicalTemplateName($logicalName, $part = '')
|
||||
{
|
||||
if (2 !== substr_count($logicalName, ':')) {
|
||||
throw new \RuntimeException(sprintf('The given template name ("%s") is not correct (it must contain two colons).', $logicalName));
|
||||
}
|
||||
|
||||
$data = array();
|
||||
|
||||
list($data['bundle'], $data['controller'], $data['template']) = explode(':', $logicalName);
|
||||
|
||||
return $part ? $data[$part] : $data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,316 @@
|
|||
<?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\Generator;
|
||||
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
use Doctrine\Common\Inflector\Inflector;
|
||||
|
||||
/**
|
||||
* Generates a CRUD controller.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class DoctrineCrudGenerator extends Generator
|
||||
{
|
||||
protected $filesystem;
|
||||
protected $rootDir;
|
||||
protected $routePrefix;
|
||||
protected $routeNamePrefix;
|
||||
protected $bundle;
|
||||
protected $entity;
|
||||
protected $entitySingularized;
|
||||
protected $entityPluralized;
|
||||
protected $metadata;
|
||||
protected $format;
|
||||
protected $actions;
|
||||
|
||||
/**
|
||||
* @param Filesystem $filesystem
|
||||
* @param string $rootDir
|
||||
*/
|
||||
public function __construct(Filesystem $filesystem, $rootDir)
|
||||
{
|
||||
$this->filesystem = $filesystem;
|
||||
$this->rootDir = $rootDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the CRUD controller.
|
||||
*
|
||||
* @param BundleInterface $bundle A bundle object
|
||||
* @param string $entity The entity relative class name
|
||||
* @param ClassMetadataInfo $metadata The entity class metadata
|
||||
* @param string $format The configuration format (xml, yaml, annotation)
|
||||
* @param string $routePrefix The route name prefix
|
||||
* @param bool $needWriteActions Whether or not to generate write actions
|
||||
* @param bool $forceOverwrite Whether or not to overwrite the controller
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function generate(BundleInterface $bundle, $entity, ClassMetadataInfo $metadata, $format, $routePrefix, $needWriteActions, $forceOverwrite)
|
||||
{
|
||||
$this->routePrefix = $routePrefix;
|
||||
$this->routeNamePrefix = self::getRouteNamePrefix($routePrefix);
|
||||
$this->actions = $needWriteActions ? array('index', 'show', 'new', 'edit', 'delete') : array('index', 'show');
|
||||
|
||||
if (count($metadata->identifier) != 1) {
|
||||
throw new \RuntimeException('The CRUD generator does not support entity classes with multiple or no primary keys.');
|
||||
}
|
||||
|
||||
$this->entity = $entity;
|
||||
$entity = str_replace('\\', '/', $entity);
|
||||
$entityParts = explode('/', $entity);
|
||||
$entityName = end($entityParts);
|
||||
$this->entitySingularized = lcfirst(Inflector::singularize($entityName));
|
||||
$this->entityPluralized = lcfirst(Inflector::pluralize($entityName));
|
||||
$this->bundle = $bundle;
|
||||
$this->metadata = $metadata;
|
||||
$this->setFormat($format);
|
||||
|
||||
$this->generateControllerClass($forceOverwrite);
|
||||
|
||||
$dir = sprintf('%s/Resources/views/%s', $this->rootDir, strtolower($entity));
|
||||
|
||||
if (!file_exists($dir)) {
|
||||
self::mkdir($dir);
|
||||
}
|
||||
|
||||
$this->generateIndexView($dir);
|
||||
|
||||
if (in_array('show', $this->actions)) {
|
||||
$this->generateShowView($dir);
|
||||
}
|
||||
|
||||
if (in_array('new', $this->actions)) {
|
||||
$this->generateNewView($dir);
|
||||
}
|
||||
|
||||
if (in_array('edit', $this->actions)) {
|
||||
$this->generateEditView($dir);
|
||||
}
|
||||
|
||||
$this->generateTestClass();
|
||||
$this->generateConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the configuration format.
|
||||
*
|
||||
* @param string $format The configuration format
|
||||
*/
|
||||
protected function setFormat($format)
|
||||
{
|
||||
switch ($format) {
|
||||
case 'yml':
|
||||
case 'xml':
|
||||
case 'php':
|
||||
case 'annotation':
|
||||
$this->format = $format;
|
||||
break;
|
||||
default:
|
||||
$this->format = 'yml';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the routing configuration.
|
||||
*/
|
||||
protected function generateConfiguration()
|
||||
{
|
||||
if (!in_array($this->format, array('yml', 'xml', 'php'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
$target = sprintf(
|
||||
'%s/Resources/config/routing/%s.%s',
|
||||
$this->bundle->getPath(),
|
||||
strtolower(str_replace('\\', '_', $this->entity)),
|
||||
$this->format
|
||||
);
|
||||
|
||||
$this->renderFile('crud/config/routing.'.$this->format.'.twig', $target, array(
|
||||
'actions' => $this->actions,
|
||||
'route_prefix' => $this->routePrefix,
|
||||
'route_name_prefix' => $this->routeNamePrefix,
|
||||
'bundle' => $this->bundle->getName(),
|
||||
'entity' => $this->entity,
|
||||
'identifier' => $this->metadata->identifier[0],
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the controller class only.
|
||||
*/
|
||||
protected function generateControllerClass($forceOverwrite)
|
||||
{
|
||||
$dir = $this->bundle->getPath();
|
||||
|
||||
$parts = explode('\\', $this->entity);
|
||||
$entityClass = array_pop($parts);
|
||||
$entityNamespace = implode('\\', $parts);
|
||||
|
||||
$target = sprintf(
|
||||
'%s/Controller/%s/%sController.php',
|
||||
$dir,
|
||||
str_replace('\\', '/', $entityNamespace),
|
||||
$entityClass
|
||||
);
|
||||
|
||||
if (!$forceOverwrite && file_exists($target)) {
|
||||
throw new \RuntimeException('Unable to generate the controller as it already exists.');
|
||||
}
|
||||
|
||||
$this->renderFile('crud/controller.php.twig', $target, array(
|
||||
'actions' => $this->actions,
|
||||
'route_prefix' => $this->routePrefix,
|
||||
'route_name_prefix' => $this->routeNamePrefix,
|
||||
'bundle' => $this->bundle->getName(),
|
||||
'entity' => $this->entity,
|
||||
'entity_singularized' => $this->entitySingularized,
|
||||
'entity_pluralized' => $this->entityPluralized,
|
||||
'identifier' => $this->metadata->identifier[0],
|
||||
'entity_class' => $entityClass,
|
||||
'namespace' => $this->bundle->getNamespace(),
|
||||
'entity_namespace' => $entityNamespace,
|
||||
'format' => $this->format,
|
||||
// BC with Symfony 2.7
|
||||
'use_form_type_instance' => !method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix'),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the functional test class only.
|
||||
*/
|
||||
protected function generateTestClass()
|
||||
{
|
||||
$parts = explode('\\', $this->entity);
|
||||
$entityClass = array_pop($parts);
|
||||
$entityNamespace = implode('\\', $parts);
|
||||
|
||||
$dir = $this->bundle->getPath().'/Tests/Controller';
|
||||
$target = $dir.'/'.str_replace('\\', '/', $entityNamespace).'/'.$entityClass.'ControllerTest.php';
|
||||
|
||||
$this->renderFile('crud/tests/test.php.twig', $target, array(
|
||||
'route_prefix' => $this->routePrefix,
|
||||
'route_name_prefix' => $this->routeNamePrefix,
|
||||
'entity' => $this->entity,
|
||||
'bundle' => $this->bundle->getName(),
|
||||
'entity_class' => $entityClass,
|
||||
'namespace' => $this->bundle->getNamespace(),
|
||||
'entity_namespace' => $entityNamespace,
|
||||
'actions' => $this->actions,
|
||||
'form_type_name' => strtolower(str_replace('\\', '_', $this->bundle->getNamespace()).($parts ? '_' : '').implode('_', $parts).'_'.$entityClass),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the index.html.twig template in the final bundle.
|
||||
*
|
||||
* @param string $dir The path to the folder that hosts templates in the bundle
|
||||
*/
|
||||
protected function generateIndexView($dir)
|
||||
{
|
||||
$this->renderFile('crud/views/index.html.twig.twig', $dir.'/index.html.twig', array(
|
||||
'bundle' => $this->bundle->getName(),
|
||||
'entity' => $this->entity,
|
||||
'entity_pluralized' => $this->entityPluralized,
|
||||
'entity_singularized' => $this->entitySingularized,
|
||||
'identifier' => $this->metadata->identifier[0],
|
||||
'fields' => $this->metadata->fieldMappings,
|
||||
'actions' => $this->actions,
|
||||
'record_actions' => $this->getRecordActions(),
|
||||
'route_prefix' => $this->routePrefix,
|
||||
'route_name_prefix' => $this->routeNamePrefix,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the show.html.twig template in the final bundle.
|
||||
*
|
||||
* @param string $dir The path to the folder that hosts templates in the bundle
|
||||
*/
|
||||
protected function generateShowView($dir)
|
||||
{
|
||||
$this->renderFile('crud/views/show.html.twig.twig', $dir.'/show.html.twig', array(
|
||||
'bundle' => $this->bundle->getName(),
|
||||
'entity' => $this->entity,
|
||||
'entity_singularized' => $this->entitySingularized,
|
||||
'identifier' => $this->metadata->identifier[0],
|
||||
'fields' => $this->metadata->fieldMappings,
|
||||
'actions' => $this->actions,
|
||||
'route_prefix' => $this->routePrefix,
|
||||
'route_name_prefix' => $this->routeNamePrefix,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the new.html.twig template in the final bundle.
|
||||
*
|
||||
* @param string $dir The path to the folder that hosts templates in the bundle
|
||||
*/
|
||||
protected function generateNewView($dir)
|
||||
{
|
||||
$this->renderFile('crud/views/new.html.twig.twig', $dir.'/new.html.twig', array(
|
||||
'bundle' => $this->bundle->getName(),
|
||||
'entity' => $this->entity,
|
||||
'entity_singularized' => $this->entitySingularized,
|
||||
'route_prefix' => $this->routePrefix,
|
||||
'route_name_prefix' => $this->routeNamePrefix,
|
||||
'actions' => $this->actions,
|
||||
'fields' => $this->metadata->fieldMappings,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the edit.html.twig template in the final bundle.
|
||||
*
|
||||
* @param string $dir The path to the folder that hosts templates in the bundle
|
||||
*/
|
||||
protected function generateEditView($dir)
|
||||
{
|
||||
$this->renderFile('crud/views/edit.html.twig.twig', $dir.'/edit.html.twig', array(
|
||||
'route_prefix' => $this->routePrefix,
|
||||
'route_name_prefix' => $this->routeNamePrefix,
|
||||
'identifier' => $this->metadata->identifier[0],
|
||||
'entity' => $this->entity,
|
||||
'entity_singularized' => $this->entitySingularized,
|
||||
'fields' => $this->metadata->fieldMappings,
|
||||
'bundle' => $this->bundle->getName(),
|
||||
'actions' => $this->actions,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of record actions to generate (edit, show).
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getRecordActions()
|
||||
{
|
||||
return array_filter($this->actions, function ($item) {
|
||||
return in_array($item, array('show', 'edit'));
|
||||
});
|
||||
}
|
||||
|
||||
public static function getRouteNamePrefix($prefix)
|
||||
{
|
||||
$prefix = preg_replace('/{(.*?)}/', '', $prefix); // {foo}_bar -> _bar
|
||||
$prefix = str_replace('/', '_', $prefix);
|
||||
$prefix = preg_replace('/_+/', '_', $prefix); // foo__bar -> foo_bar
|
||||
$prefix = trim($prefix, '_');
|
||||
|
||||
return $prefix;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
<?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\Generator;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Model\EntityGeneratorResult;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
|
||||
use Symfony\Bridge\Doctrine\RegistryInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
use Doctrine\ORM\Tools\EntityGenerator;
|
||||
use Doctrine\ORM\Tools\EntityRepositoryGenerator;
|
||||
use Doctrine\ORM\Tools\Export\ClassMetadataExporter;
|
||||
use Doctrine\Common\Util\Inflector;
|
||||
|
||||
/**
|
||||
* Generates a Doctrine entity class based on its name, fields and format.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
*/
|
||||
class DoctrineEntityGenerator extends Generator
|
||||
{
|
||||
private $filesystem;
|
||||
private $registry;
|
||||
|
||||
public function __construct(Filesystem $filesystem, RegistryInterface $registry)
|
||||
{
|
||||
$this->filesystem = $filesystem;
|
||||
$this->registry = $registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BundleInterface $bundle
|
||||
* @param string $entity
|
||||
* @param string $format
|
||||
* @param array $fields
|
||||
*
|
||||
* @return EntityGeneratorResult
|
||||
*
|
||||
* @throws \Doctrine\ORM\Tools\Export\ExportException
|
||||
*/
|
||||
public function generate(BundleInterface $bundle, $entity, $format, array $fields)
|
||||
{
|
||||
// configure the bundle (needed if the bundle does not contain any Entities yet)
|
||||
$config = $this->registry->getManager(null)->getConfiguration();
|
||||
$config->setEntityNamespaces(array_merge(
|
||||
array($bundle->getName() => $bundle->getNamespace().'\\Entity'),
|
||||
$config->getEntityNamespaces()
|
||||
));
|
||||
|
||||
$entityClass = $this->registry->getAliasNamespace($bundle->getName()).'\\'.$entity;
|
||||
$entityPath = $bundle->getPath().'/Entity/'.str_replace('\\', '/', $entity).'.php';
|
||||
if (file_exists($entityPath)) {
|
||||
throw new \RuntimeException(sprintf('Entity "%s" already exists.', $entityClass));
|
||||
}
|
||||
|
||||
$class = new ClassMetadataInfo($entityClass, $config->getNamingStrategy());
|
||||
$class->customRepositoryClassName = str_replace('\\Entity\\', '\\Repository\\', $entityClass).'Repository';
|
||||
$class->mapField(array('fieldName' => 'id', 'type' => 'integer', 'id' => true));
|
||||
$class->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
|
||||
foreach ($fields as $field) {
|
||||
$class->mapField($field);
|
||||
}
|
||||
|
||||
$entityGenerator = $this->getEntityGenerator();
|
||||
if ('annotation' === $format) {
|
||||
$entityGenerator->setGenerateAnnotations(true);
|
||||
$class->setPrimaryTable(array('name' => Inflector::tableize(str_replace('\\', '', $entity))));
|
||||
$entityCode = $entityGenerator->generateEntityClass($class);
|
||||
$mappingPath = $mappingCode = false;
|
||||
} else {
|
||||
$cme = new ClassMetadataExporter();
|
||||
$exporter = $cme->getExporter('yml' == $format ? 'yaml' : $format);
|
||||
$mappingPath = $bundle->getPath().'/Resources/config/doctrine/'.str_replace('\\', '.', $entity).'.orm.'.$format;
|
||||
|
||||
if (file_exists($mappingPath)) {
|
||||
throw new \RuntimeException(sprintf('Cannot generate entity when mapping "%s" already exists.', $mappingPath));
|
||||
}
|
||||
|
||||
$mappingCode = $exporter->exportClassMetadata($class);
|
||||
$entityGenerator->setGenerateAnnotations(false);
|
||||
$entityCode = $entityGenerator->generateEntityClass($class);
|
||||
}
|
||||
$entityCode = str_replace(
|
||||
array("@var integer\n", "@var boolean\n", "@param integer\n", "@param boolean\n", "@return integer\n", "@return boolean\n"),
|
||||
array("@var int\n", "@var bool\n", "@param int\n", "@param bool\n", "@return int\n", "@return bool\n"),
|
||||
$entityCode
|
||||
);
|
||||
|
||||
self::mkdir(dirname($entityPath));
|
||||
self::dump($entityPath, $entityCode);
|
||||
|
||||
if ($mappingPath) {
|
||||
self::mkdir(dirname($mappingPath));
|
||||
self::dump($mappingPath, $mappingCode);
|
||||
}
|
||||
|
||||
$path = $bundle->getPath().str_repeat('/..', substr_count(get_class($bundle), '\\'));
|
||||
$this->getRepositoryGenerator()->writeEntityRepositoryClass($class->customRepositoryClassName, $path);
|
||||
$repositoryPath = $path.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $class->customRepositoryClassName).'.php';
|
||||
|
||||
return new EntityGeneratorResult($entityPath, $repositoryPath, $mappingPath);
|
||||
}
|
||||
|
||||
public function isReservedKeyword($keyword)
|
||||
{
|
||||
return $this->registry->getConnection()->getDatabasePlatform()->getReservedKeywordsList()->isKeyword($keyword);
|
||||
}
|
||||
|
||||
protected function getEntityGenerator()
|
||||
{
|
||||
$entityGenerator = new EntityGenerator();
|
||||
$entityGenerator->setGenerateAnnotations(false);
|
||||
$entityGenerator->setGenerateStubMethods(true);
|
||||
$entityGenerator->setRegenerateEntityIfExists(false);
|
||||
$entityGenerator->setUpdateEntityIfExists(true);
|
||||
$entityGenerator->setNumSpaces(4);
|
||||
$entityGenerator->setAnnotationPrefix('ORM\\');
|
||||
|
||||
return $entityGenerator;
|
||||
}
|
||||
|
||||
protected function getRepositoryGenerator()
|
||||
{
|
||||
return new EntityRepositoryGenerator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given name is a valid PHP variable name.
|
||||
*
|
||||
* @see http://php.net/manual/en/language.variables.basics.php
|
||||
*
|
||||
* @param $name string
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isValidPhpVariableName($name)
|
||||
{
|
||||
return (bool) preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $name, $matches);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
<?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\Generator;
|
||||
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
|
||||
/**
|
||||
* Generates a form class based on a Doctrine entity.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Hugo Hamon <hugo.hamon@sensio.com>
|
||||
*/
|
||||
class DoctrineFormGenerator extends Generator
|
||||
{
|
||||
private $filesystem;
|
||||
private $className;
|
||||
private $classPath;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Filesystem $filesystem A Filesystem instance
|
||||
*/
|
||||
public function __construct(Filesystem $filesystem)
|
||||
{
|
||||
$this->filesystem = $filesystem;
|
||||
}
|
||||
|
||||
public function getClassName()
|
||||
{
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
public function getClassPath()
|
||||
{
|
||||
return $this->classPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the entity form class.
|
||||
*
|
||||
* @param BundleInterface $bundle The bundle in which to create the class
|
||||
* @param string $entity The entity relative class name
|
||||
* @param ClassMetadataInfo $metadata The entity metadata class
|
||||
* @param bool $forceOverwrite If true, remove any existing form class before generating it again
|
||||
*/
|
||||
public function generate(BundleInterface $bundle, $entity, ClassMetadataInfo $metadata, $forceOverwrite = false)
|
||||
{
|
||||
$parts = explode('\\', $entity);
|
||||
$entityClass = array_pop($parts);
|
||||
|
||||
$this->className = $entityClass.'Type';
|
||||
$dirPath = $bundle->getPath().'/Form';
|
||||
$this->classPath = $dirPath.'/'.str_replace('\\', '/', $entity).'Type.php';
|
||||
|
||||
if (!$forceOverwrite && file_exists($this->classPath)) {
|
||||
throw new \RuntimeException(sprintf('Unable to generate the %s form class as it already exists under the %s file', $this->className, $this->classPath));
|
||||
}
|
||||
|
||||
if (count($metadata->identifier) > 1) {
|
||||
throw new \RuntimeException('The form generator does not support entity classes with multiple primary keys.');
|
||||
}
|
||||
|
||||
$parts = explode('\\', $entity);
|
||||
array_pop($parts);
|
||||
|
||||
$this->renderFile('form/FormType.php.twig', $this->classPath, array(
|
||||
'fields' => $this->getFieldsFromMetadata($metadata),
|
||||
'namespace' => $bundle->getNamespace(),
|
||||
'entity_namespace' => implode('\\', $parts),
|
||||
'entity_class' => $entityClass,
|
||||
'bundle' => $bundle->getName(),
|
||||
'form_class' => $this->className,
|
||||
'form_type_name' => strtolower(str_replace('\\', '_', $bundle->getNamespace()).($parts ? '_' : '').implode('_', $parts).'_'.substr($this->className, 0, -4)),
|
||||
// BC with Symfony 2.7
|
||||
'get_name_required' => !method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix'),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of fields. Fields can be both column fields and
|
||||
* association fields.
|
||||
*
|
||||
* @param ClassMetadataInfo $metadata
|
||||
*
|
||||
* @return array $fields
|
||||
*/
|
||||
private function getFieldsFromMetadata(ClassMetadataInfo $metadata)
|
||||
{
|
||||
$fields = (array) $metadata->fieldNames;
|
||||
|
||||
// Remove the primary key field if it's not managed manually
|
||||
if (!$metadata->isIdentifierNatural()) {
|
||||
$fields = array_diff($fields, $metadata->identifier);
|
||||
}
|
||||
|
||||
foreach ($metadata->associationMappings as $fieldName => $relation) {
|
||||
if ($relation['type'] !== ClassMetadataInfo::ONE_TO_MANY) {
|
||||
$fields[] = $fieldName;
|
||||
}
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
}
|
||||
108
trunk/_vendor/sensio/generator-bundle/Generator/Generator.php
Normal file
108
trunk/_vendor/sensio/generator-bundle/Generator/Generator.php
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
<?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\Generator;
|
||||
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
|
||||
/**
|
||||
* Generator is the base class for all generators.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Generator
|
||||
{
|
||||
private $skeletonDirs;
|
||||
private static $output;
|
||||
|
||||
/**
|
||||
* Sets an array of directories to look for templates.
|
||||
*
|
||||
* The directories must be sorted from the most specific to the most
|
||||
* directory.
|
||||
*
|
||||
* @param array $skeletonDirs An array of skeleton dirs
|
||||
*/
|
||||
public function setSkeletonDirs($skeletonDirs)
|
||||
{
|
||||
$this->skeletonDirs = is_array($skeletonDirs) ? $skeletonDirs : array($skeletonDirs);
|
||||
}
|
||||
|
||||
protected function render($template, $parameters)
|
||||
{
|
||||
$twig = $this->getTwigEnvironment();
|
||||
|
||||
return $twig->render($template, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the twig environment that will render skeletons.
|
||||
*
|
||||
* @return \Twig_Environment
|
||||
*/
|
||||
protected function getTwigEnvironment()
|
||||
{
|
||||
return new \Twig_Environment(new \Twig_Loader_Filesystem($this->skeletonDirs), array(
|
||||
'debug' => true,
|
||||
'cache' => false,
|
||||
'strict_variables' => true,
|
||||
'autoescape' => false,
|
||||
));
|
||||
}
|
||||
|
||||
protected function renderFile($template, $target, $parameters)
|
||||
{
|
||||
self::mkdir(dirname($target));
|
||||
|
||||
return self::dump($target, $this->render($template, $parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function mkdir($dir, $mode = 0777, $recursive = true)
|
||||
{
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, $mode, $recursive);
|
||||
self::writeln(sprintf(' <fg=green>created</> %s', self::relativizePath($dir)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function dump($filename, $content)
|
||||
{
|
||||
if (file_exists($filename)) {
|
||||
self::writeln(sprintf(' <fg=yellow>updated</> %s', self::relativizePath($filename)));
|
||||
} else {
|
||||
self::writeln(sprintf(' <fg=green>created</> %s', self::relativizePath($filename)));
|
||||
}
|
||||
|
||||
return file_put_contents($filename, $content);
|
||||
}
|
||||
|
||||
private static function writeln($message)
|
||||
{
|
||||
if (null === self::$output) {
|
||||
self::$output = new ConsoleOutput();
|
||||
}
|
||||
|
||||
self::$output->writeln($message);
|
||||
}
|
||||
|
||||
private static function relativizePath($absolutePath)
|
||||
{
|
||||
$relativePath = str_replace(getcwd(), '.', $absolutePath);
|
||||
|
||||
return is_dir($absolutePath) ? rtrim($relativePath, '/').'/' : $relativePath;
|
||||
}
|
||||
}
|
||||
19
trunk/_vendor/sensio/generator-bundle/LICENSE
Normal file
19
trunk/_vendor/sensio/generator-bundle/LICENSE
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2011-2017 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
<?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\Generator\Generator;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @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 === Generator::dump($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'];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
<?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 Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\Generator;
|
||||
|
||||
/**
|
||||
* Changes the PHP code of a Kernel.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class KernelManipulator extends Manipulator
|
||||
{
|
||||
protected $kernel;
|
||||
protected $reflected;
|
||||
|
||||
public function __construct(KernelInterface $kernel)
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
$this->reflected = new \ReflectionObject($kernel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a bundle at the end of the existing ones.
|
||||
*
|
||||
* @param string $bundle The bundle class name
|
||||
*
|
||||
* @return bool Whether the operation succeeded
|
||||
*
|
||||
* @throws \RuntimeException If bundle is already defined
|
||||
*/
|
||||
public function addBundle($bundle)
|
||||
{
|
||||
if (!$this->getFilename()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$src = file($this->getFilename());
|
||||
$method = $this->reflected->getMethod('registerBundles');
|
||||
$lines = array_slice($src, $method->getStartLine() - 1, $method->getEndLine() - $method->getStartLine() + 1);
|
||||
|
||||
// Don't add same bundle twice
|
||||
if (false !== strpos(implode('', $lines), $bundle)) {
|
||||
throw new \RuntimeException(sprintf('Bundle "%s" is already defined in "AppKernel::registerBundles()".', $bundle));
|
||||
}
|
||||
|
||||
$this->setCode(token_get_all('<?php '.implode('', $lines)), $method->getStartLine());
|
||||
|
||||
while ($token = $this->next()) {
|
||||
// $bundles
|
||||
if (T_VARIABLE !== $token[0] || '$bundles' !== $token[1]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// =
|
||||
$this->next();
|
||||
|
||||
// array start with traditional or short syntax
|
||||
$token = $this->next();
|
||||
if (T_ARRAY !== $token[0] && '[' !== $this->value($token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// add the bundle at the end of the array
|
||||
while ($token = $this->next()) {
|
||||
// look for ); or ];
|
||||
if (')' !== $this->value($token) && ']' !== $this->value($token)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (';' !== $this->value($this->peek())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->next();
|
||||
|
||||
$leadingContent = implode('', array_slice($src, 0, $this->line));
|
||||
|
||||
// trim semicolon
|
||||
$leadingContent = rtrim(rtrim($leadingContent), ';');
|
||||
|
||||
// We want to match ) & ]
|
||||
$closingSymbolRegex = '#(\)|])$#';
|
||||
|
||||
// get closing symbol used
|
||||
preg_match($closingSymbolRegex, $leadingContent, $matches);
|
||||
$closingSymbol = $matches[0];
|
||||
|
||||
// remove last close parentheses
|
||||
$leadingContent = rtrim(preg_replace($closingSymbolRegex, '', rtrim($leadingContent)));
|
||||
|
||||
if ('(' !== substr($leadingContent, -1) && '[' !== substr($leadingContent, -1)) {
|
||||
// end of leading content is not open parentheses or bracket, then assume that array contains at least one element
|
||||
$leadingContent = rtrim($leadingContent, ',').',';
|
||||
}
|
||||
|
||||
$lines = array_merge(
|
||||
array($leadingContent, "\n"),
|
||||
array(str_repeat(' ', 12), sprintf('new %s(),', $bundle), "\n"),
|
||||
array(str_repeat(' ', 8), $closingSymbol.';', "\n"),
|
||||
array_slice($src, $this->line)
|
||||
);
|
||||
|
||||
Generator::dump($this->getFilename(), implode('', $lines));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getFilename()
|
||||
{
|
||||
return $this->reflected->getFileName();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* Changes the PHP code of a Kernel.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Manipulator
|
||||
{
|
||||
protected $tokens;
|
||||
protected $line;
|
||||
|
||||
/**
|
||||
* Sets the code to manipulate.
|
||||
*
|
||||
* @param array $tokens An array of PHP tokens
|
||||
* @param int $line The start line of the code
|
||||
*/
|
||||
protected function setCode(array $tokens, $line = 0)
|
||||
{
|
||||
$this->tokens = $tokens;
|
||||
$this->line = $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next token.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function next()
|
||||
{
|
||||
while ($token = array_shift($this->tokens)) {
|
||||
$this->line += substr_count($this->value($token), "\n");
|
||||
|
||||
if (is_array($token) && in_array($token[0], array(T_WHITESPACE, T_COMMENT, T_DOC_COMMENT))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Peeks the next token.
|
||||
*
|
||||
* @param int $nb
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function peek($nb = 1)
|
||||
{
|
||||
$i = 0;
|
||||
$tokens = $this->tokens;
|
||||
while ($token = array_shift($tokens)) {
|
||||
if (is_array($token) && in_array($token[0], array(T_WHITESPACE, T_COMMENT, T_DOC_COMMENT))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++$i;
|
||||
if ($i == $nb) {
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a token.
|
||||
*
|
||||
* @param string|string[] $token The token value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function value($token)
|
||||
{
|
||||
return is_array($token) ? $token[1] : $token;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
<?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 Symfony\Component\DependencyInjection\Container;
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGenerator;
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\Generator;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* Changes the PHP code of a YAML routing file.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class RoutingManipulator extends Manipulator
|
||||
{
|
||||
private $file;
|
||||
|
||||
/**
|
||||
* @param string $file The YAML routing file path
|
||||
*/
|
||||
public function __construct($file)
|
||||
{
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a routing resource at the top of the existing ones.
|
||||
*
|
||||
* @param string $bundle
|
||||
* @param string $format
|
||||
* @param string $prefix
|
||||
* @param string $path
|
||||
*
|
||||
* @return bool Whether the operation succeeded
|
||||
*
|
||||
* @throws \RuntimeException If bundle is already imported
|
||||
*/
|
||||
public function addResource($bundle, $format, $prefix = '/', $path = 'routing')
|
||||
{
|
||||
$current = '';
|
||||
$code = sprintf("%s:\n", $this->getImportedResourceYamlKey($bundle, $prefix));
|
||||
|
||||
if (file_exists($this->file)) {
|
||||
$current = file_get_contents($this->file);
|
||||
|
||||
// Don't add same bundle twice
|
||||
if (false !== strpos($current, '@'.$bundle)) {
|
||||
throw new \RuntimeException(sprintf('Bundle "%s" is already imported.', $bundle));
|
||||
}
|
||||
} elseif (!is_dir($dir = dirname($this->file))) {
|
||||
Generator::mkdir($dir);
|
||||
}
|
||||
|
||||
if ('annotation' == $format) {
|
||||
$code .= sprintf(" resource: \"@%s/Controller/\"\n type: annotation\n", $bundle);
|
||||
} else {
|
||||
$code .= sprintf(" resource: \"@%s/Resources/config/%s.%s\"\n", $bundle, $path, $format);
|
||||
}
|
||||
$code .= sprintf(" prefix: %s\n", $prefix);
|
||||
$code .= "\n";
|
||||
$code .= $current;
|
||||
|
||||
if (false === Generator::dump($this->file, $code)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the routing file contains a line for the bundle.
|
||||
*
|
||||
* @param string $bundle
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasResourceInAnnotation($bundle)
|
||||
{
|
||||
if (!file_exists($this->file)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$config = Yaml::parse(file_get_contents($this->file));
|
||||
|
||||
$search = sprintf('@%s/Controller/', $bundle);
|
||||
|
||||
foreach ($config as $resource) {
|
||||
if (array_key_exists('resource', $resource)) {
|
||||
return $resource['resource'] === $search;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an annotation controller resource.
|
||||
*
|
||||
* @param string $bundle
|
||||
* @param string $controller
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function addAnnotationController($bundle, $controller)
|
||||
{
|
||||
$current = '';
|
||||
|
||||
if (file_exists($this->file)) {
|
||||
$current = file_get_contents($this->file);
|
||||
} elseif (!is_dir($dir = dirname($this->file))) {
|
||||
mkdir($dir, 0777, true);
|
||||
}
|
||||
|
||||
$code = sprintf("%s:\n", Container::underscore(substr($bundle, 0, -6)).'_'.Container::underscore($controller));
|
||||
|
||||
$code .= sprintf(" resource: \"@%s/Controller/%sController.php\"\n type: annotation\n", $bundle, $controller);
|
||||
|
||||
$code .= "\n";
|
||||
$code .= $current;
|
||||
|
||||
return false !== file_put_contents($this->file, $code);
|
||||
}
|
||||
|
||||
public function getImportedResourceYamlKey($bundle, $prefix)
|
||||
{
|
||||
$snakeCasedBundleName = Container::underscore(substr($bundle, 0, -6));
|
||||
$routePrefix = DoctrineCrudGenerator::getRouteNamePrefix($prefix);
|
||||
|
||||
return sprintf('%s%s%s', $snakeCasedBundleName, '' !== $routePrefix ? '_' : '', $routePrefix);
|
||||
}
|
||||
}
|
||||
143
trunk/_vendor/sensio/generator-bundle/Model/Bundle.php
Normal file
143
trunk/_vendor/sensio/generator-bundle/Model/Bundle.php
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
|
||||
namespace Sensio\Bundle\GeneratorBundle\Model;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
|
||||
/**
|
||||
* Represents a bundle being built.
|
||||
*/
|
||||
class Bundle
|
||||
{
|
||||
private $namespace;
|
||||
|
||||
private $name;
|
||||
|
||||
private $targetDirectory;
|
||||
|
||||
private $configurationFormat;
|
||||
|
||||
private $isShared;
|
||||
|
||||
private $testsDirectory;
|
||||
|
||||
public function __construct($namespace, $name, $targetDirectory, $configurationFormat, $isShared)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
$this->name = $name;
|
||||
$this->targetDirectory = $targetDirectory;
|
||||
$this->configurationFormat = $configurationFormat;
|
||||
$this->isShared = $isShared;
|
||||
$this->testsDirectory = $this->getTargetDirectory().'/Tests';
|
||||
}
|
||||
|
||||
public function getNamespace()
|
||||
{
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getConfigurationFormat()
|
||||
{
|
||||
return $this->configurationFormat;
|
||||
}
|
||||
|
||||
public function isShared()
|
||||
{
|
||||
return $this->isShared;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the directory where the bundle will be generated.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTargetDirectory()
|
||||
{
|
||||
return rtrim($this->targetDirectory, '/').'/'.trim(strtr($this->namespace, '\\', '/'), '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the bundle without the Bundle suffix.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBasename()
|
||||
{
|
||||
return substr($this->name, 0, -6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dependency injection extension alias for this bundle.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getExtensionAlias()
|
||||
{
|
||||
return Container::underscore($this->getBasename());
|
||||
}
|
||||
|
||||
/**
|
||||
* Should a DependencyInjection directory be generated for this bundle?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function shouldGenerateDependencyInjectionDirectory()
|
||||
{
|
||||
return $this->isShared;
|
||||
}
|
||||
|
||||
/**
|
||||
* What is the filename for the services.yml/xml file?
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getServicesConfigurationFilename()
|
||||
{
|
||||
if ('yml' === $this->getConfigurationFormat() || 'annotation' === $this->configurationFormat) {
|
||||
return 'services.yml';
|
||||
} else {
|
||||
return 'services.'.$this->getConfigurationFormat();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* What is the filename for the routing.yml/xml file?
|
||||
*
|
||||
* If false, no routing file will be generated
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public function getRoutingConfigurationFilename()
|
||||
{
|
||||
if ($this->getConfigurationFormat() == 'annotation') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return 'routing.'.$this->getConfigurationFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class name of the Bundle class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBundleClassName()
|
||||
{
|
||||
return $this->namespace.'\\'.$this->name;
|
||||
}
|
||||
|
||||
public function setTestsDirectory($testsDirectory)
|
||||
{
|
||||
$this->testsDirectory = $testsDirectory;
|
||||
}
|
||||
|
||||
public function getTestsDirectory()
|
||||
{
|
||||
return $this->testsDirectory;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace Sensio\Bundle\GeneratorBundle\Model;
|
||||
|
||||
class EntityGeneratorResult
|
||||
{
|
||||
/** @var string */
|
||||
private $entityPath;
|
||||
|
||||
/** @var string */
|
||||
private $repositoryPath;
|
||||
|
||||
/** @var string */
|
||||
private $mappingPath;
|
||||
|
||||
/**
|
||||
* @param string $entityPath
|
||||
* @param string $repositoryPath
|
||||
* @param string $mappingPath
|
||||
*/
|
||||
public function __construct($entityPath, $repositoryPath, $mappingPath)
|
||||
{
|
||||
$this->entityPath = $entityPath;
|
||||
$this->repositoryPath = $repositoryPath;
|
||||
$this->mappingPath = $mappingPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getEntityPath()
|
||||
{
|
||||
return $this->entityPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRepositoryPath()
|
||||
{
|
||||
return $this->repositoryPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMappingPath()
|
||||
{
|
||||
return $this->mappingPath;
|
||||
}
|
||||
}
|
||||
12
trunk/_vendor/sensio/generator-bundle/README.md
Normal file
12
trunk/_vendor/sensio/generator-bundle/README.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
SensioGeneratorBundle
|
||||
=====================
|
||||
|
||||
**WARNING**: This bundle does not support Symfony 4. It also does not support the new bundle-less directory structure as created by Symfony Flex. Use the [Maker bundle](https://github.com/symfony/maker-bundle) instead.
|
||||
|
||||
The `SensioGeneratorBundle` extends the default Symfony command line
|
||||
interface by providing new interactive and intuitive commands for generating
|
||||
code skeletons like bundles, form classes, or CRUD controllers based on a
|
||||
Doctrine 2 schema.
|
||||
|
||||
More information in the official
|
||||
[documentation](http://symfony.com/doc/current/bundles/SensioGeneratorBundle/index.html).
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
Generating a New Bundle Skeleton
|
||||
================================
|
||||
|
||||
.. caution::
|
||||
|
||||
If your application is based on Symfony 2.x version, replace ``php bin/console``
|
||||
with ``php app/console`` before executing any of the console commands included
|
||||
in this article.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The ``generate:bundle`` generates a new bundle structure and automatically
|
||||
activates it in the application.
|
||||
|
||||
By default the command is run in the interactive mode and asks questions to
|
||||
determine the bundle name, location, configuration format and default
|
||||
structure:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:bundle
|
||||
|
||||
To deactivate the interactive mode, use the `--no-interaction` option but don't
|
||||
forget to pass all needed options:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:bundle --namespace=Acme/Bundle/BlogBundle --no-interaction
|
||||
|
||||
.. caution::
|
||||
|
||||
If the ``generate:bundle`` command returns an error about registering the
|
||||
bundle namespace in ``composer.json``, add the following line to your
|
||||
``composer.json`` file within the ``psr-4`` section:
|
||||
|
||||
``"Acme\\Bundle\\BlogBundle\\": "src/Acme/Bundle/BlogBundle"``
|
||||
|
||||
(for example:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Acme\\Bundle\\BlogBundle\\": "src/Acme/Bundle/BlogBundle"
|
||||
},
|
||||
"classmap": [ "app/AppKernel.php", "app/AppCache.php" ]
|
||||
},
|
||||
|
||||
), then execute the following command to regenerate the autoload files:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer dump-autoload
|
||||
|
||||
Available Options
|
||||
-----------------
|
||||
|
||||
``--shared``
|
||||
Provide this option if you are creating a bundle that will be shared across
|
||||
several of your applications or if you are developing a third-party bundle.
|
||||
Don't set this option if you are developing a bundle that will be used
|
||||
solely in your application (e.g. ``AppBundle``).
|
||||
|
||||
``--namespace``
|
||||
The namespace of the bundle to create. The namespace should begin with
|
||||
a "vendor" name like your company name, your project name, or your client
|
||||
name, followed by one or more optional category sub-namespaces, and it
|
||||
should end with the bundle name itself (which must have Bundle as a suffix):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:bundle --namespace=Acme/Bundle/BlogBundle
|
||||
|
||||
``--bundle-name``
|
||||
The optional bundle name. It must be a string ending with the ``Bundle``
|
||||
suffix:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:bundle --bundle-name=AcmeBlogBundle
|
||||
|
||||
``--dir``
|
||||
The directory in which to store the bundle. By convention, the command
|
||||
detects and uses the application's ``src/`` folder:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:bundle --dir=/var/www/myproject/src
|
||||
|
||||
``--format``
|
||||
**allowed values**: ``annotation|php|yml|xml`` **default**: ``annotation``
|
||||
|
||||
Determine the format to use for the generated configuration files (like
|
||||
routing). By default, the command uses the ``annotation`` format (choosing
|
||||
the ``annotation`` format expects the `SensioFrameworkExtraBundle`_ to
|
||||
be installed):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:bundle --format=annotation
|
||||
|
||||
.. _`SensioFrameworkExtraBundle`: http://symfony.com/doc/master/bundles/SensioFrameworkExtraBundle/index.html
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
Generating a New Command
|
||||
========================
|
||||
|
||||
.. caution::
|
||||
|
||||
If your application is based on Symfony 2.x version, replace ``php bin/console``
|
||||
with ``php app/console`` before executing any of the console commands included
|
||||
in this article.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The ``generate:command`` command generates a new Command class for the given
|
||||
console command.
|
||||
|
||||
By default the command is run in the interactive mode and asks questions to
|
||||
determine the bundle and the command name:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:command
|
||||
|
||||
The command can be run in a non interactive mode by using the
|
||||
``--no-interaction`` and providing the needed arguments:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:command --no-interaction AcmeBlogBundle blog:publish-posts
|
||||
|
||||
Available Arguments
|
||||
-------------------
|
||||
|
||||
* ``bundle``: The name of the bundle where the command class is generated.
|
||||
* ``name``: The name of the command as you type it in the console.
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
Generating a New Controller
|
||||
===========================
|
||||
|
||||
.. caution::
|
||||
|
||||
If your application is based on Symfony 2.x version, replace ``php bin/console``
|
||||
with ``php app/console`` before executing any of the console commands included
|
||||
in this article.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The ``generate:controller`` command generates a new controller including
|
||||
actions, tests, templates and routing.
|
||||
|
||||
By default, the command is run in the interactive mode and asks questions to
|
||||
determine the bundle name, location, configuration format and default
|
||||
structure:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:controller
|
||||
|
||||
The command can be run in a non-interactive mode by using the ``--no-interaction``
|
||||
option without forgetting all needed options:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:controller --no-interaction --controller=AcmeBlogBundle:Post
|
||||
|
||||
Available Options
|
||||
-----------------
|
||||
|
||||
``--controller``
|
||||
The controller name given as a shortcut notation containing the bundle
|
||||
name in which the controller is located and the name of the controller
|
||||
(for instance, ``AcmeBlogBundle:Post`` creates a ``PostController`` class
|
||||
inside the ``AcmeBlogBundle`` bundle):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:controller --controller=AcmeBlogBundle:Post
|
||||
|
||||
``--actions``
|
||||
The list of actions to generate in the controller class. This has a format
|
||||
like ``%actionname%:%route%:%template`` (where ``:%template%`` is optional):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:controller --actions="showPostAction:/article/{id} getListAction:/_list-posts/{max}:AcmeBlogBundle:Post:list_posts.html.twig"
|
||||
|
||||
# or
|
||||
$ php bin/console generate:controller --actions=showPostAction:/article/{id} --actions=getListAction:/_list-posts/{max}:AcmeBlogBundle:Post:list_posts.html.twig
|
||||
|
||||
``--route-format``
|
||||
**allowed values**: ``annotation|php|yml|xml`` **default**: ``annotation``
|
||||
|
||||
This option determines the format to use for the routing configuration.
|
||||
By default, the command uses the ``annotation`` format:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:controller --route-format=annotation
|
||||
|
||||
``--template-format``
|
||||
**allowed values**: ``php|twig`` **default**: ``twig``
|
||||
|
||||
This option determines the format to use for the templates. By default,
|
||||
the command uses the ``twig`` format:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:controller --template-format=twig
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
Generating a CRUD Controller Based on a Doctrine Entity
|
||||
=======================================================
|
||||
|
||||
.. caution::
|
||||
|
||||
If your application is based on Symfony 2.x version, replace ``php bin/console``
|
||||
with ``php app/console`` before executing any of the console commands included
|
||||
in this article.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The ``generate:doctrine:crud`` command generates a basic controller for a
|
||||
given entity located in a given bundle. This controller allows to perform
|
||||
the five basic operations on a model.
|
||||
|
||||
* Listing all records,
|
||||
* Showing one given record identified by its primary key,
|
||||
* Creating a new record,
|
||||
* Editing an existing record,
|
||||
* Deleting an existing record.
|
||||
|
||||
By default, the command is run in the interactive mode and asks questions to
|
||||
determine the entity name, the route prefix or whether or not to generate write
|
||||
actions:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:crud
|
||||
|
||||
To deactivate the interactive mode, use the ``--no-interaction`` option or its
|
||||
alias ``-n``, but don't forget to pass all needed options:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:crud AcmeBlogBundle:Post -n --format=annotation --with-write
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
``entity``
|
||||
The entity name given in shortcut notation containing the bundle name
|
||||
in which the entity is located and the name of the entity (for example,
|
||||
``AcmeBlogBundle:Post``):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:crud AcmeBlogBundle:Post
|
||||
|
||||
Available Options
|
||||
-----------------
|
||||
|
||||
``--entity``
|
||||
|
||||
.. caution::
|
||||
|
||||
This option has been deprecated in version 3.0, and will be removed in 4.0.
|
||||
Pass it as argument instead.
|
||||
|
||||
The entity name given in shortcut notation containing the bundle name
|
||||
in which the entity is located and the name of the entity (for example,
|
||||
``AcmeBlogBundle:Post``):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:crud --entity=AcmeBlogBundle:Post
|
||||
|
||||
``--route-prefix``
|
||||
The prefix to use for each route that identifies an action:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:crud --route-prefix=acme_post
|
||||
|
||||
``--with-write``
|
||||
**allowed values**: ``yes|no`` **default**: ``no``
|
||||
|
||||
Whether or not to generate the ``new``, ``create``, ``edit``, ``update``
|
||||
and ``delete`` actions:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:crud --with-write
|
||||
|
||||
``--format``
|
||||
**allowed values**: ``annotation|php|yml|xml`` **default**: ``annotation``
|
||||
|
||||
Determine the format to use for the generated configuration files (like,
|
||||
for example, routing). By default, the command uses the ``annotation``
|
||||
format. Choosing the ``annotation`` format expects the `SensioFrameworkExtraBundle`_
|
||||
to be installed:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:crud --format=annotation
|
||||
|
||||
``--overwrite``
|
||||
**allowed values**: ``yes|no`` **default**: ``no``
|
||||
|
||||
Whether or not to overwrite any existing files:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:crud --overwrite
|
||||
|
||||
.. _`SensioFrameworkExtraBundle`: http://symfony.com/doc/master/bundles/SensioFrameworkExtraBundle/index.html
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
Generating a New Doctrine Entity Stub
|
||||
=====================================
|
||||
|
||||
.. caution::
|
||||
|
||||
If your application is based on Symfony 2.x version, replace ``php bin/console``
|
||||
with ``php app/console`` before executing any of the console commands included
|
||||
in this article.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The ``generate:doctrine:entity`` command generates a new Doctrine entity stub
|
||||
including the mapping definition and the class properties, getters and setters.
|
||||
|
||||
By default, the command is run in the interactive mode and asks questions to
|
||||
determine the bundle name, location, configuration format and default structure:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:entity
|
||||
|
||||
To deactivate the interactive mode, use the ``--no-interaction`` option or its
|
||||
alias ``-n``, but don't forget to pass all needed options:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:entity AcmeBlogBundle:Post -n --fields="title:string(100) body:text" --format=xml
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
``entity``
|
||||
The entity name given as a shortcut notation containing the bundle name
|
||||
in which the entity is located and the name of the entity (for example,
|
||||
``AcmeBlogBundle:Post``):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:entity AcmeBlogBundle:Post
|
||||
|
||||
Available Options
|
||||
-----------------
|
||||
|
||||
``--entity``
|
||||
|
||||
.. caution::
|
||||
|
||||
This option has been deprecated in version 3.0, and will be removed in 4.0.
|
||||
Pass it as argument instead.
|
||||
|
||||
The entity name given as a shortcut notation containing the bundle name
|
||||
in which the entity is located and the name of the entity (for example,
|
||||
``AcmeBlogBundle:Post``):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:entity --entity=AcmeBlogBundle:Post
|
||||
|
||||
``--fields``
|
||||
The list of fields to generate in the entity class:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:entity --fields="title:string(length=100 nullable=true unique=false) body:text ranking:decimal(precision=10 scale=0)"
|
||||
|
||||
.. versionadded:: 3.0
|
||||
Ability to pass named options to fields was added in version 3.0.
|
||||
Previously, only the ``string`` type was allowed to receive the length
|
||||
value as argument. Available options are ``length``, ``nullable``,
|
||||
``unique``, ``precision`` and ``scale``.
|
||||
|
||||
``--format``
|
||||
**allowed values**: ``annotation|php|yml|xml`` **default**: ``annotation``
|
||||
|
||||
This option determines the format to use for the generated Doctrine entity
|
||||
mapping configuration files. By default, the command uses the ``annotation``
|
||||
format:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:entity --format=annotation
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
Generating a New Form Type Class Based on a Doctrine Entity
|
||||
===========================================================
|
||||
|
||||
.. caution::
|
||||
|
||||
If your application is based on Symfony 2.x version, replace ``php bin/console``
|
||||
with ``php app/console`` before executing any of the console commands included
|
||||
in this article.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The ``generate:doctrine:form`` command generates a basic form type class
|
||||
by using the metadata mapping of a given entity class:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:form AcmeBlogBundle:Post
|
||||
|
||||
Required Arguments
|
||||
------------------
|
||||
|
||||
``entity``
|
||||
|
||||
The entity name given in shortcut notation containing the bundle name
|
||||
in which the entity is located and the name of the entity (``AcmeBlogBundle:Post``,
|
||||
for example):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ php bin/console generate:doctrine:form AcmeBlogBundle:Post
|
||||
128
trunk/_vendor/sensio/generator-bundle/Resources/doc/index.rst
Normal file
128
trunk/_vendor/sensio/generator-bundle/Resources/doc/index.rst
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
SensioGeneratorBundle
|
||||
=====================
|
||||
|
||||
This bundle provides commands for scaffolding bundles, forms, controllers and
|
||||
even CRUD-based backends. The boilerplate code provided by these code generators
|
||||
will save you a large amount of time and work.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Step 1: Download the Bundle
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Open a command console, enter your project directory and execute the
|
||||
following command to download the latest stable version of this bundle:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer require sensio/generator-bundle
|
||||
|
||||
Step 2: Enable the Bundle
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Then, enable the bundle by adding it to the list of registered bundles for the
|
||||
``dev`` environment in the ``app/AppKernel.php`` file of your project::
|
||||
|
||||
// app/AppKernel.php
|
||||
|
||||
// ...
|
||||
class AppKernel extends Kernel
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
if (in_array($this->getEnvironment(), array('dev', 'test'))) {
|
||||
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
|
||||
// ...
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
List of Available Commands
|
||||
--------------------------
|
||||
|
||||
All the commands provided by this bundle can be run in interactive or
|
||||
non-interactive mode. The interactive mode asks you some questions to configure
|
||||
the command parameters that actually generate the code.
|
||||
|
||||
Read the following articles to learn how to use the new commands:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
commands/generate_bundle
|
||||
commands/generate_command
|
||||
commands/generate_controller
|
||||
commands/generate_doctrine_crud
|
||||
commands/generate_doctrine_entity
|
||||
commands/generate_doctrine_form
|
||||
|
||||
Overriding Skeleton Templates
|
||||
-----------------------------
|
||||
|
||||
.. versionadded:: 2.3
|
||||
The possibility to override the skeleton templates was added in 2.3.
|
||||
|
||||
All generators use a template skeleton to generate files. By default, the
|
||||
commands use templates provided by the bundle under its ``Resources/skeleton/``
|
||||
directory.
|
||||
|
||||
You can define custom skeleton templates by creating the same directory and
|
||||
file structure in the following locations (displayed from highest to lowest
|
||||
priority):
|
||||
|
||||
* ``<BUNDLE_PATH>/Resources/SensioGeneratorBundle/skeleton/``
|
||||
* ``app/Resources/SensioGeneratorBundle/skeleton/``
|
||||
|
||||
The ``<BUNDLE_PATH>`` value refers to the base path of the bundle where you are
|
||||
scaffolding a controller, a form or a CRUD backend.
|
||||
|
||||
For instance, if you want to override the ``edit`` template for the CRUD
|
||||
generator, create a ``crud/views/edit.html.twig.twig`` file under
|
||||
``app/Resources/SensioGeneratorBundle/skeleton/``.
|
||||
|
||||
When overriding a template, have a look at the default templates to learn more
|
||||
about the available templates, their paths and the variables they have access.
|
||||
|
||||
Instead of copy/pasting the original template to create your own, you can also
|
||||
extend it and only override the relevant parts:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{# app/Resources/SensioGeneratorBundle/skeleton/crud/actions/create.php.twig #}
|
||||
|
||||
{# notice the "skeleton" prefix here -- more about it below #}
|
||||
{% extends "skeleton/crud/actions/create.php.twig" %}
|
||||
|
||||
{% block phpdoc_header %}
|
||||
{{ parent() }}
|
||||
*
|
||||
* This is going to be inserted after the phpdoc title
|
||||
* but before the annotations.
|
||||
{% endblock phpdoc_header %}
|
||||
|
||||
Complex templates in the default skeleton are split into Twig blocks to allow
|
||||
easy inheritance and to avoid copy/pasting large chunks of code.
|
||||
|
||||
In some cases, templates in the skeleton include other ones, like
|
||||
in the ``crud/views/edit.html.twig.twig`` template for instance:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{{ include('crud/views/others/record_actions.html.twig.twig') }}
|
||||
|
||||
If you have defined a custom template for this template, it is going to be
|
||||
used instead of the default one. But you can explicitly include the original
|
||||
skeleton template by prefixing its path with ``skeleton/`` like we did above:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{{ include('skeleton/crud/views/others/record_actions.html.twig.twig') }}
|
||||
|
||||
You can learn more about this neat "trick" in the official `Twig documentation`_.
|
||||
|
||||
.. _`Twig documentation`: http://twig.sensiolabs.org/doc/recipes.html#overriding-a-template-that-also-extends-itself
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace {{ namespace }};
|
||||
|
||||
{% block use_statements %}
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
{% endblock use_statements %}
|
||||
|
||||
{% block class_definition %}
|
||||
class {{ bundle }} extends Bundle
|
||||
{% endblock class_definition %}
|
||||
{
|
||||
{% block class_body %}
|
||||
{% endblock class_body %}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace {{ namespace }}\DependencyInjection;
|
||||
|
||||
{% block use_statements %}
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
{% endblock use_statements %}
|
||||
|
||||
/**
|
||||
{% block phpdoc_class_header %}
|
||||
* This is the class that validates and merges configuration from your app/config files.
|
||||
{% endblock phpdoc_class_header %}
|
||||
*
|
||||
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/configuration.html}
|
||||
*/
|
||||
{% block class_definition %}
|
||||
class Configuration implements ConfigurationInterface
|
||||
{% endblock class_definition %}
|
||||
{
|
||||
{% block class_body %}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfigTreeBuilder()
|
||||
{
|
||||
$treeBuilder = new TreeBuilder();
|
||||
$rootNode = $treeBuilder->root('{{ extension_alias }}');
|
||||
|
||||
// Here you should define the parameters that are allowed to
|
||||
// configure your bundle. See the documentation linked above for
|
||||
// more information on that topic.
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
{% endblock class_body %}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace {{ namespace }}\Controller;
|
||||
|
||||
{% block use_statements %}
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
{% if 'annotation' == format -%}
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
{% endif %}
|
||||
{% endblock use_statements %}
|
||||
|
||||
{% block class_definition %}
|
||||
class DefaultController extends Controller
|
||||
{% endblock class_definition %}
|
||||
{
|
||||
{% block class_body %}
|
||||
{% if 'annotation' == format -%}
|
||||
/**
|
||||
* @Route("/")
|
||||
*/
|
||||
{% endif -%}
|
||||
public function indexAction()
|
||||
{
|
||||
return $this->render('{{ bundle }}:Default:index.html.twig');
|
||||
}
|
||||
{% endblock class_body %}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace {{ namespace }}\Tests\Controller;
|
||||
|
||||
{% block use_statements %}
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
{% endblock use_statements %}
|
||||
|
||||
{% block class_definition %}
|
||||
class DefaultControllerTest extends WebTestCase
|
||||
{% endblock class_definition %}
|
||||
{
|
||||
{% block class_body %}
|
||||
public function testIndex()
|
||||
{
|
||||
$client = static::createClient();
|
||||
|
||||
$crawler = $client->request('GET', '/');
|
||||
|
||||
$this->assertContains('Hello World', $client->getResponse()->getContent());
|
||||
}
|
||||
{% endblock class_body %}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace {{ namespace }}\DependencyInjection;
|
||||
|
||||
{% block use_statements %}
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
use Symfony\Component\DependencyInjection\Loader;
|
||||
{% endblock use_statements %}
|
||||
|
||||
/**
|
||||
{% block phpdoc_class_header %}
|
||||
* This is the class that loads and manages your bundle configuration.
|
||||
{% endblock phpdoc_class_header %}
|
||||
*
|
||||
* @link http://symfony.com/doc/current/cookbook/bundles/extension.html
|
||||
*/
|
||||
{% block class_definition %}
|
||||
class {{ bundle_basename }}Extension extends Extension
|
||||
{% endblock class_definition %}
|
||||
{
|
||||
{% block class_body %}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function load(array $configs, ContainerBuilder $container)
|
||||
{
|
||||
$configuration = new Configuration();
|
||||
$config = $this->processConfiguration($configuration, $configs);
|
||||
|
||||
{% if format == 'yml' or format == 'annotation' -%}
|
||||
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||
$loader->load('services.yml');
|
||||
{%- elseif format == 'xml' -%}
|
||||
$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||
$loader->load('services.xml');
|
||||
{%- elseif format == 'php' -%}
|
||||
$loader = new Loader\PhpFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||
$loader->load('services.php');
|
||||
{%- endif %}
|
||||
|
||||
}
|
||||
{% endblock class_body %}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
Hello World!
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
{% block use_statements %}
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
use Symfony\Component\Routing\Route;
|
||||
{% endblock use_statements %}
|
||||
|
||||
{% block definition %}
|
||||
$collection = new RouteCollection();
|
||||
{% endblock definition %}
|
||||
|
||||
{% block body %}
|
||||
$collection->add('{{ extension_alias }}_homepage', new Route('/', array(
|
||||
'_controller' => '{{ bundle }}:Default:index',
|
||||
)));
|
||||
{% endblock body %}
|
||||
|
||||
{% block return %}
|
||||
return $collection;
|
||||
{% endblock return %}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
|
||||
{% block body %}
|
||||
<route id="{{ extension_alias }}_homepage" path="/">
|
||||
<default key="_controller">{{ bundle }}:Default:index</default>
|
||||
</route>
|
||||
{% endblock body %}
|
||||
</routes>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{{ extension_alias }}_homepage:
|
||||
path: /
|
||||
defaults: { _controller: {{ bundle }}:Default:index }
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
{% block use_statements %}
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\Parameter;
|
||||
{% endblock use_statements %}
|
||||
|
||||
/*
|
||||
|
||||
{% block services %}
|
||||
$container->setDefinition(
|
||||
'{{ extension_alias }}.example',
|
||||
new Definition(
|
||||
'{{ namespace }}\Example',
|
||||
array(
|
||||
new Reference('service_id'),
|
||||
"plain_value",
|
||||
new Parameter('parameter_name'),
|
||||
)
|
||||
)
|
||||
);
|
||||
{% endblock services %}
|
||||
|
||||
*/
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" ?>
|
||||
|
||||
<container xmlns="http://symfony.com/schema/dic/services"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
|
||||
<!--
|
||||
<services>
|
||||
{% block services %}
|
||||
<service id="{{ extension_alias }}.example" class="{{ namespace }}\Example">
|
||||
<argument type="service" id="service_id" />
|
||||
<argument>plain_value</argument>
|
||||
<argument>%parameter_name%</argument>
|
||||
</service>
|
||||
{% endblock services %}
|
||||
</services>
|
||||
-->
|
||||
</container>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
services:
|
||||
{% block services %}
|
||||
# {{ extension_alias }}.example:
|
||||
# class: {{ namespace }}\Example
|
||||
# arguments: ["@service_id", "plain_value", "%parameter%"]
|
||||
{% endblock services %}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace {{ namespace }}\Command;
|
||||
|
||||
{% block use_statements %}
|
||||
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
{% endblock use_statements %}
|
||||
|
||||
{% block class_definition %}
|
||||
class {{ class_name }} extends ContainerAwareCommand
|
||||
{% endblock class_definition %}
|
||||
{
|
||||
{% block class_body %}
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('{{ name }}')
|
||||
->setDescription('...')
|
||||
->addArgument('argument', InputArgument::OPTIONAL, 'Argument description')
|
||||
->addOption('option', null, InputOption::VALUE_NONE, 'Option description')
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$argument = $input->getArgument('argument');
|
||||
|
||||
if ($input->getOption('option')) {
|
||||
// ...
|
||||
}
|
||||
|
||||
$output->writeln('Command result.');
|
||||
}
|
||||
|
||||
{% endblock class_body %}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace {{ namespace }}\Controller;
|
||||
|
||||
{% block use_statements %}
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
{% if 'annotation' == format.routing -%}
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
{% endif %}
|
||||
{% endblock use_statements %}
|
||||
|
||||
{% block class_definition %}
|
||||
class {{ controller }}Controller extends Controller
|
||||
{% endblock class_definition %}
|
||||
{
|
||||
{% block class_body %}
|
||||
{% for action in actions %}
|
||||
{% if 'annotation' == format.routing -%}
|
||||
/**
|
||||
* @Route("{{ action.route }}")
|
||||
*/
|
||||
{% endif -%}
|
||||
public function {{ action.name }}(
|
||||
{%- if action.placeholders|length > 0 -%}
|
||||
${{- action.placeholders|join(', $') -}}
|
||||
{%- endif -%})
|
||||
{
|
||||
{% if 'default' == action.template -%}
|
||||
return $this->render('{{ bundle }}:{{ controller }}:{{ action.name|slice(0, -6) }}.html.{{ format.templating }}', array(
|
||||
// ...
|
||||
));
|
||||
{%- else -%}
|
||||
return $this->render('{{ action.template }}', array(
|
||||
// ...
|
||||
));
|
||||
{%- endif %}
|
||||
|
||||
}
|
||||
|
||||
{% endfor -%}
|
||||
{% endblock class_body %}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace {{ namespace }}\Tests\Controller;
|
||||
|
||||
{% block use_statements %}
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
{% endblock use_statements %}
|
||||
|
||||
{% block class_definition %}
|
||||
class {{ controller }}ControllerTest extends WebTestCase
|
||||
{% endblock class_definition %}
|
||||
{
|
||||
{% block class_body %}
|
||||
{% for action in actions %}
|
||||
public function test{{ action.basename|capitalize }}()
|
||||
{
|
||||
$client = static::createClient();
|
||||
|
||||
$crawler = $client->request('GET', '{{ action.route }}');
|
||||
}
|
||||
|
||||
{% endfor -%}
|
||||
{% endblock class_body %}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php $view->extend('::base.html.twig') ?>
|
||||
|
||||
<?php $view['slots']->set('title', '{{ bundle }}:{{ controller }}:{{ action.basename }}') ?>
|
||||
|
||||
<?php $view['slots']->start('body') ?>
|
||||
<h1>Welcome to the {{ controller }}:{{ action.basename }} page</h1>
|
||||
<?php $view['slots']->stop() ?>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{{ '{% extends "::base.html.twig" %}' }}
|
||||
|
||||
{{ '{% block title %}' -}}
|
||||
{{ bundle }}:{{ controller }}:{{ action.basename }}
|
||||
{{- '{% endblock %}' }}
|
||||
|
||||
{{ '{% block body %}' }}
|
||||
<h1>Welcome to the {{ controller }}:{{ action.basename }} page</h1>
|
||||
{{ '{% endblock %}' }}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
/**
|
||||
{% block phpdoc_method_header %}
|
||||
* Deletes a {{ entity_singularized }} entity.
|
||||
{% endblock phpdoc_method_header %}
|
||||
*
|
||||
{% block phpdoc_method_annotations %}
|
||||
{% if 'annotation' == format %}
|
||||
* @Route("/{{ '{' ~ identifier ~ '}' }}", name="{{ route_name_prefix }}_delete")
|
||||
* @Method("DELETE")
|
||||
{% endif %}
|
||||
{% endblock phpdoc_method_annotations %}
|
||||
*/
|
||||
{% block method_definition %}
|
||||
public function deleteAction(Request $request, {{ entity_class }} ${{ entity_singularized }})
|
||||
{% endblock method_definition %}
|
||||
{
|
||||
{% block method_body %}
|
||||
$form = $this->createDeleteForm(${{ entity_singularized }});
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->remove(${{ entity_singularized }});
|
||||
$em->flush();
|
||||
}
|
||||
{% endblock method_body %}
|
||||
|
||||
{% block method_return %}
|
||||
return $this->redirectToRoute('{{ route_name_prefix }}_index');
|
||||
{% endblock method_return %}
|
||||
}
|
||||
|
||||
{% block form %}
|
||||
/**
|
||||
* Creates a form to delete a {{ entity_singularized }} entity.
|
||||
*
|
||||
* @param {{ entity_class }} ${{ entity_singularized }} The {{ entity_singularized }} entity
|
||||
*
|
||||
* @return \Symfony\Component\Form\Form The form
|
||||
*/
|
||||
private function createDeleteForm({{ entity_class }} ${{ entity_singularized }})
|
||||
{
|
||||
return $this->createFormBuilder()
|
||||
->setAction($this->generateUrl('{{ route_name_prefix }}_delete', array('{{ identifier }}' => ${{ entity_singularized }}->get{{ identifier|capitalize }}())))
|
||||
->setMethod('DELETE')
|
||||
->getForm()
|
||||
;
|
||||
}
|
||||
{% endblock form %}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
/**
|
||||
{% block phpdoc_method_header %}
|
||||
* Displays a form to edit an existing {{ entity_singularized }} entity.
|
||||
{% endblock phpdoc_method_header %}
|
||||
*
|
||||
{% block phpdoc_method_annotations %}
|
||||
{% if 'annotation' == format %}
|
||||
* @Route("/{{ '{' ~ identifier ~ '}' }}/edit", name="{{ route_name_prefix }}_edit")
|
||||
* @Method({"GET", "POST"})
|
||||
{% endif %}
|
||||
{% endblock phpdoc_method_annotations %}
|
||||
*/
|
||||
{% block method_definition %}
|
||||
public function editAction(Request $request, {{ entity_class }} ${{ entity_singularized }})
|
||||
{% endblock method_definition %}
|
||||
{
|
||||
{% block method_body %}
|
||||
$deleteForm = $this->createDeleteForm(${{ entity_singularized }});
|
||||
{% if use_form_type_instance -%}
|
||||
$editForm = $this->createForm(new {{ entity_singularized|capitalize }}Type(), ${{ entity_singularized }});
|
||||
{% else -%}
|
||||
$editForm = $this->createForm('{{ namespace }}\Form\{{ entity }}Type', ${{ entity_singularized }});
|
||||
{% endif -%}
|
||||
$editForm->handleRequest($request);
|
||||
|
||||
if ($editForm->isSubmitted() && $editForm->isValid()) {
|
||||
$this->getDoctrine()->getManager()->flush();
|
||||
|
||||
return $this->redirectToRoute('{{ route_name_prefix }}_edit', array('{{ identifier }}' => ${{ entity_singularized }}->get{{ identifier|capitalize }}()));
|
||||
}
|
||||
{% endblock method_body %}
|
||||
|
||||
{% block method_return %}
|
||||
return $this->render('{{ entity|lower|replace({'\\': '/'}) }}/edit.html.twig', array(
|
||||
'{{ entity_singularized }}' => ${{ entity_singularized }},
|
||||
'edit_form' => $editForm->createView(),
|
||||
'delete_form' => $deleteForm->createView(),
|
||||
));
|
||||
{% endblock method_return %}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
{% block phpdoc_method_header %}
|
||||
* Lists all {{ entity_singularized }} entities.
|
||||
{% endblock phpdoc_method_header %}
|
||||
*
|
||||
{% block phpdoc_method_annotations %}
|
||||
{% if 'annotation' == format %}
|
||||
* @Route("/", name="{{ route_name_prefix }}_index")
|
||||
* @Method("GET")
|
||||
{% endif %}
|
||||
{% endblock phpdoc_method_annotations %}
|
||||
*/
|
||||
{% block method_definition %}
|
||||
public function indexAction()
|
||||
{% endblock method_definition %}
|
||||
{
|
||||
{% block method_body %}
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
${{ entity_pluralized }} = $em->getRepository('{{ bundle }}:{{ entity }}')->findAll();
|
||||
{% endblock method_body %}
|
||||
|
||||
{% block method_return %}
|
||||
return $this->render('{{ entity|lower|replace({'\\': '/'}) }}/index.html.twig', array(
|
||||
'{{ entity_pluralized }}' => ${{ entity_pluralized }},
|
||||
));
|
||||
{% endblock method_return %}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
|
||||
/**
|
||||
{% block phpdoc_method_header %}
|
||||
* Creates a new {{ entity_singularized }} entity.
|
||||
{% endblock phpdoc_method_header %}
|
||||
*
|
||||
{% block phpdoc_method_annotations %}
|
||||
{% if 'annotation' == format %}
|
||||
* @Route("/new", name="{{ route_name_prefix }}_new")
|
||||
* @Method({"GET", "POST"})
|
||||
{% endif %}
|
||||
{% endblock phpdoc_method_annotations %}
|
||||
*/
|
||||
{% block method_definition %}
|
||||
public function newAction(Request $request)
|
||||
{% endblock method_definition %}
|
||||
{
|
||||
{% block method_body %}
|
||||
${{ entity_singularized }} = new {{ entity_singularized|capitalize }}();
|
||||
{% if use_form_type_instance -%}
|
||||
$form = $this->createForm(new {{ entity_singularized|capitalize }}Type(), ${{ entity_singularized }});
|
||||
{% else -%}
|
||||
$form = $this->createForm('{{ namespace }}\Form\{{ entity }}Type', ${{ entity_singularized }});
|
||||
{% endif -%}
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->persist(${{ entity_singularized }});
|
||||
$em->flush();
|
||||
|
||||
{% if 'show' in actions -%}
|
||||
return $this->redirectToRoute('{{ route_name_prefix }}_show', array('{{ identifier }}' => ${{ entity_singularized }}->get{{ identifier|capitalize }}()));
|
||||
{%- else -%}
|
||||
return $this->redirectToRoute('{{ route_name_prefix }}_index'));
|
||||
{%- endif %}
|
||||
|
||||
}
|
||||
{% endblock method_body %}
|
||||
|
||||
{% block method_return %}
|
||||
return $this->render('{{ entity|lower|replace({'\\': '/'}) }}/new.html.twig', array(
|
||||
'{{ entity_singularized }}' => ${{ entity_singularized }},
|
||||
'form' => $form->createView(),
|
||||
));
|
||||
{% endblock method_return %}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
/**
|
||||
{% block phpdoc_method_header %}
|
||||
* Finds and displays a {{ entity_singularized }} entity.
|
||||
{% endblock phpdoc_method_header %}
|
||||
*
|
||||
{% block phpdoc_method_annotations %}
|
||||
{% if 'annotation' == format %}
|
||||
* @Route("/{{ '{' ~ identifier ~ '}' }}", name="{{ route_name_prefix }}_show")
|
||||
* @Method("GET")
|
||||
{% endif %}
|
||||
{% endblock phpdoc_method_annotations %}
|
||||
*/
|
||||
{% block method_definition %}
|
||||
public function showAction({{ entity_class }} ${{ entity_singularized }})
|
||||
{% endblock method_definition %}
|
||||
{
|
||||
{% block method_body %}
|
||||
{% if 'delete' in actions %}
|
||||
$deleteForm = $this->createDeleteForm(${{ entity_singularized }});
|
||||
{% endif %}
|
||||
{% endblock method_body %}
|
||||
|
||||
{% block method_return %}
|
||||
return $this->render('{{ entity|lower|replace({'\\': '/'}) }}/show.html.twig', array(
|
||||
'{{ entity_singularized }}' => ${{ entity_singularized }},
|
||||
{% if 'delete' in actions %}
|
||||
'delete_form' => $deleteForm->createView(),
|
||||
{% endif %}
|
||||
));
|
||||
{% endblock method_return %}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
{% block use_statements %}
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
use Symfony\Component\Routing\Route;
|
||||
{% endblock use_statements %}
|
||||
|
||||
{% block definition %}
|
||||
$collection = new RouteCollection();
|
||||
{% endblock definition %}
|
||||
|
||||
{% block body %}
|
||||
{% if 'index' in actions %}
|
||||
$collection->add('{{ route_name_prefix }}_index', new Route(
|
||||
'/',
|
||||
array('_controller' => '{{ bundle }}:{{ entity }}:index'),
|
||||
array(),
|
||||
array(),
|
||||
'',
|
||||
array(),
|
||||
array('GET')
|
||||
));
|
||||
{% endif %}
|
||||
|
||||
{% if 'show' in actions %}
|
||||
$collection->add('{{ route_name_prefix }}_show', new Route(
|
||||
'/{{ '{' ~ identifier ~ '}' }}/show',
|
||||
array('_controller' => '{{ bundle }}:{{ entity }}:show'),
|
||||
array(),
|
||||
array(),
|
||||
'',
|
||||
array(),
|
||||
array('GET')
|
||||
));
|
||||
{% endif %}
|
||||
|
||||
{% if 'new' in actions %}
|
||||
$collection->add('{{ route_name_prefix }}_new', new Route(
|
||||
'/new',
|
||||
array('_controller' => '{{ bundle }}:{{ entity }}:new'),
|
||||
array(),
|
||||
array(),
|
||||
'',
|
||||
array(),
|
||||
array('GET', 'POST')
|
||||
));
|
||||
{% endif %}
|
||||
|
||||
{% if 'edit' in actions %}
|
||||
$collection->add('{{ route_name_prefix }}_edit', new Route(
|
||||
'/{{ '{' ~ identifier ~ '}' }}/edit',
|
||||
array('_controller' => '{{ bundle }}:{{ entity }}:edit'),
|
||||
array(),
|
||||
array(),
|
||||
'',
|
||||
array(),
|
||||
array('GET', 'POST')
|
||||
));
|
||||
{% endif %}
|
||||
|
||||
{% if 'delete' in actions %}
|
||||
$collection->add('{{ route_name_prefix }}_delete', new Route(
|
||||
'/{{ '{' ~ identifier ~ '}' }}/delete',
|
||||
array('_controller' => '{{ bundle }}:{{ entity }}:delete'),
|
||||
array(),
|
||||
array(),
|
||||
'',
|
||||
array(),
|
||||
array('DELETE')
|
||||
));
|
||||
{% endif %}
|
||||
{% endblock body %}
|
||||
|
||||
{% block return %}
|
||||
return $collection;
|
||||
{% endblock return %}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
|
||||
{% block body %}
|
||||
<route id="{{ route_name_prefix }}_index" path="/" methods="GET">
|
||||
<default key="_controller">{{ bundle }}:{{ entity }}:index</default>
|
||||
</route>
|
||||
|
||||
<route id="{{ route_name_prefix }}_show" path="/{{ '{' ~ identifier ~ '}' }}/show" methods="GET">
|
||||
<default key="_controller">{{ bundle }}:{{ entity }}:show</default>
|
||||
</route>
|
||||
|
||||
{% if 'new' in actions %}
|
||||
<route id="{{ route_name_prefix }}_new" path="/new" methods="GET|POST">
|
||||
<default key="_controller">{{ bundle }}:{{ entity }}:new</default>
|
||||
</route>
|
||||
{% endif %}
|
||||
|
||||
{% if 'edit' in actions %}
|
||||
<route id="{{ route_name_prefix }}_edit" path="/{{ '{' ~ identifier ~ '}' }}/edit" methods="GET|POST">
|
||||
<default key="_controller">{{ bundle }}:{{ entity }}:edit</default>
|
||||
</route>
|
||||
{% endif %}
|
||||
|
||||
{% if 'delete' in actions %}
|
||||
<route id="{{ route_name_prefix }}_delete" path="/{{ '{' ~ identifier ~ '}' }}/delete" methods="DELETE">
|
||||
<default key="_controller">{{ bundle }}:{{ entity }}:delete</default>
|
||||
</route>
|
||||
{% endif %}
|
||||
{% endblock body %}
|
||||
|
||||
</routes>
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
{% if 'index' in actions %}
|
||||
{{ route_name_prefix }}_index:
|
||||
path: /
|
||||
defaults: { _controller: "{{ bundle }}:{{ entity }}:index" }
|
||||
methods: GET
|
||||
{% endif %}
|
||||
|
||||
{% if 'show' in actions %}
|
||||
{{ route_name_prefix }}_show:
|
||||
path: /{{ '{' ~ identifier ~ '}' }}/show
|
||||
defaults: { _controller: "{{ bundle }}:{{ entity }}:show" }
|
||||
methods: GET
|
||||
{% endif %}
|
||||
|
||||
{% if 'new' in actions %}
|
||||
{{ route_name_prefix }}_new:
|
||||
path: /new
|
||||
defaults: { _controller: "{{ bundle }}:{{ entity }}:new" }
|
||||
methods: [GET, POST]
|
||||
{% endif %}
|
||||
|
||||
{% if 'edit' in actions %}
|
||||
{{ route_name_prefix }}_edit:
|
||||
path: /{{ '{' ~ identifier ~ '}' }}/edit
|
||||
defaults: { _controller: "{{ bundle }}:{{ entity }}:edit" }
|
||||
methods: [GET, POST]
|
||||
{% endif %}
|
||||
|
||||
{% if 'delete' in actions %}
|
||||
{{ route_name_prefix }}_delete:
|
||||
path: /{{ '{' ~ identifier ~ '}' }}/delete
|
||||
defaults: { _controller: "{{ bundle }}:{{ entity }}:delete" }
|
||||
methods: DELETE
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace {{ namespace }}\Controller{{ entity_namespace ? '\\' ~ entity_namespace : '' }};
|
||||
|
||||
{% block use_statements %}
|
||||
use {{ namespace }}\Entity\{{ entity }};
|
||||
{% if ('new' in actions or 'edit' in actions) and use_form_type_instance %}
|
||||
use {{ namespace }}\Form\{{ entity }}Type;
|
||||
{% endif %}
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
{% if 'annotation' == format -%}
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
{%- endif %}
|
||||
{% if 'new' in actions or 'edit' in actions or 'delete' in actions %}
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
{%- endif %}
|
||||
|
||||
{% endblock use_statements %}
|
||||
|
||||
/**
|
||||
{% block phpdoc_class_header %}
|
||||
* {{ entity_singularized|capitalize }} controller.
|
||||
{% endblock phpdoc_class_header %}
|
||||
*
|
||||
{% block phpdoc_class_annotations %}
|
||||
{% if 'annotation' == format %}
|
||||
* @Route("{{ route_prefix|default('/') }}")
|
||||
{% endif %}
|
||||
{% endblock phpdoc_class_annotations %}
|
||||
*/
|
||||
{% block class_definition %}
|
||||
class {{ entity_class }}Controller extends Controller
|
||||
{% endblock class_definition %}
|
||||
{
|
||||
{% block class_body %}
|
||||
{%- if 'index' in actions %}
|
||||
{%- include 'crud/actions/index.php.twig' %}
|
||||
{%- endif %}
|
||||
|
||||
{%- if 'new' in actions %}
|
||||
{%- include 'crud/actions/new.php.twig' %}
|
||||
{%- endif %}
|
||||
|
||||
{%- if 'show' in actions %}
|
||||
{%- include 'crud/actions/show.php.twig' %}
|
||||
{%- endif %}
|
||||
|
||||
{%- if 'edit' in actions %}
|
||||
{%- include 'crud/actions/edit.php.twig' %}
|
||||
{%- endif %}
|
||||
|
||||
{%- if 'delete' in actions %}
|
||||
{%- include 'crud/actions/delete.php.twig' %}
|
||||
{%- endif %}
|
||||
{% endblock class_body %}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
|
||||
public function testCompleteScenario()
|
||||
{
|
||||
// Create a new client to browse the application
|
||||
$client = static::createClient();
|
||||
|
||||
// Create a new entry in the database
|
||||
$crawler = $client->request('GET', '/{{ route_prefix }}/');
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode(), "Unexpected HTTP status code for GET /{{ route_prefix }}/");
|
||||
$crawler = $client->click($crawler->selectLink('Create a new entry')->link());
|
||||
|
||||
// Fill in the form and submit it
|
||||
$form = $crawler->selectButton('Create')->form(array(
|
||||
'{{ form_type_name|lower }}[field_name]' => 'Test',
|
||||
// ... other fields to fill
|
||||
));
|
||||
|
||||
$client->submit($form);
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
// Check data in the show view
|
||||
$this->assertGreaterThan(0, $crawler->filter('td:contains("Test")')->count(), 'Missing element td:contains("Test")');
|
||||
|
||||
// Edit the entity
|
||||
$crawler = $client->click($crawler->selectLink('Edit')->link());
|
||||
|
||||
$form = $crawler->selectButton('Update')->form(array(
|
||||
'{{ form_type_name|lower }}[field_name]' => 'Foo',
|
||||
// ... other fields to fill
|
||||
));
|
||||
|
||||
$client->submit($form);
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
// Check the element contains an attribute with value equals "Foo"
|
||||
$this->assertGreaterThan(0, $crawler->filter('[value="Foo"]')->count(), 'Missing element [value="Foo"]');
|
||||
|
||||
// Delete the entity
|
||||
$client->submit($crawler->selectButton('Delete')->form());
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
// Check the entity has been delete on the list
|
||||
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
public function testCompleteScenario()
|
||||
{
|
||||
// Create a new client to browse the application
|
||||
$client = static::createClient();
|
||||
|
||||
// Go to the list view
|
||||
$crawler = $client->request('GET', '/{{ route_prefix }}/');
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode(), "Unexpected HTTP status code for GET /{{ route_prefix }}/");
|
||||
|
||||
// Go to the show view
|
||||
$crawler = $client->click($crawler->selectLink('show')->link());
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode(), "Unexpected HTTP status code");
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace {{ namespace }}\Tests\Controller{{ entity_namespace ? '\\' ~ entity_namespace : '' }};
|
||||
|
||||
{% block use_statements %}
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
{% endblock use_statements %}
|
||||
|
||||
{% block class_definition %}
|
||||
class {{ entity_class }}ControllerTest extends WebTestCase
|
||||
{% endblock class_definition %}
|
||||
{
|
||||
{% block class_body %}
|
||||
/*
|
||||
|
||||
{%- if 'new' in actions %}
|
||||
{%- include 'crud/tests/others/full_scenario.php.twig' -%}
|
||||
{%- else %}
|
||||
{%- include 'crud/tests/others/short_scenario.php.twig' -%}
|
||||
{%- endif %}
|
||||
|
||||
*/
|
||||
{% endblock class_body %}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{% block extends %}
|
||||
{{ "{% extends 'base.html.twig' %}" }}
|
||||
{% endblock extends %}
|
||||
|
||||
{% block body %}
|
||||
{{ "{% block body %}" }}
|
||||
<h1>{{ entity_singularized|capitalize }} edit</h1>
|
||||
|
||||
{{ '{{ form_start(edit_form) }}' }}
|
||||
{{ '{{ form_widget(edit_form) }}' }}
|
||||
<input type="submit" value="Edit" />
|
||||
{{ '{{ form_end(edit_form) }}' }}
|
||||
|
||||
{% set hide_edit, hide_delete = true, false %}
|
||||
{{ include('crud/views/others/record_actions.html.twig.twig') -}}
|
||||
{{ "{% endblock %}" }}
|
||||
{% endblock body %}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
{% block extends %}
|
||||
{{ "{% extends 'base.html.twig' %}" }}
|
||||
{% endblock extends %}
|
||||
|
||||
{% block body %}
|
||||
{{ "{% block body %}" }}
|
||||
<h1>{{ entity_pluralized|capitalize }} list</h1>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{%- for field, metadata in fields %}
|
||||
|
||||
<th>{{ field|capitalize }}</th>
|
||||
|
||||
{%- endfor %}
|
||||
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ '{% for ' ~ entity_singularized ~ ' in ' ~ entity_pluralized ~ ' %}' }}
|
||||
<tr>
|
||||
|
||||
{%- for field, metadata in fields %}
|
||||
{%- if loop.first and ('show' in actions) %}
|
||||
|
||||
<td><a href="{{ "{{ path('" ~ route_name_prefix ~ "_show', { '"~ identifier ~"': " ~ entity_singularized ~ "."~ identifier ~" }) }}" }}">{{ '{{ ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ ' }}' }}</a></td>
|
||||
|
||||
{%- elseif metadata.type in ['datetime'] %}
|
||||
|
||||
<td>{{ '{% if ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ ' %}{{ ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ '|date(\'Y-m-d H:i:s\') }}{% endif %}' }}</td>
|
||||
|
||||
{%- elseif metadata.type in ['date'] %}
|
||||
|
||||
<td>{{ '{% if ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ ' %}{{ ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ '|date(\'Y-m-d\') }}{% endif %}' }}</td>
|
||||
|
||||
{%- elseif metadata.type in ['time'] %}
|
||||
|
||||
<td>{{ '{% if ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ ' %}{{ ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ '|date(\'H:i:s\') }}{% endif %}' }}</td>
|
||||
|
||||
{%- elseif metadata.type in ['array'] %}
|
||||
|
||||
<td>{{ '{% if ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ ' %}{{ ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ '|join(\', \') }}{% endif %}' }}</td>
|
||||
|
||||
{%- elseif metadata.type in ['boolean'] %}
|
||||
|
||||
<td>{{ '{% if ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ ' %}Yes{% else %}No{% endif %}' }}</td>
|
||||
|
||||
{%- else %}
|
||||
|
||||
<td>{{ '{{ ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ ' }}' }}</td>
|
||||
|
||||
{%- endif %}
|
||||
|
||||
{%- if loop.last %}
|
||||
|
||||
<td>
|
||||
<ul>
|
||||
|
||||
{%- for action in record_actions %}
|
||||
|
||||
<li>
|
||||
<a href="{{ "{{ path('" ~ route_name_prefix ~ "_" ~ action ~ "', { '"~ identifier ~"': " ~ entity_singularized ~ "."~ identifier ~" }) }}" }}">{{ action }}</a>
|
||||
</li>
|
||||
|
||||
{%- endfor %}
|
||||
|
||||
</ul>
|
||||
</td>
|
||||
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
|
||||
</tr>
|
||||
{{ '{% endfor %}' }}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% if 'new' in actions -%}
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ "{{ path('" ~ route_name_prefix ~ "_new') }}" }}">Create a new {{ entity_singularized }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
{%- endif %}
|
||||
|
||||
{{ "{% endblock %}" }}
|
||||
{% endblock body %}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{% block extends %}
|
||||
{{ "{% extends 'base.html.twig' %}" }}
|
||||
{% endblock extends %}
|
||||
|
||||
{% block body %}
|
||||
{{ "{% block body %}" }}
|
||||
<h1>{{ entity_singularized|capitalize }} creation</h1>
|
||||
|
||||
{{ '{{ form_start(form) }}' }}
|
||||
{{ '{{ form_widget(form) }}' }}
|
||||
<input type="submit" value="Create" />
|
||||
{{ '{{ form_end(form) }}' }}
|
||||
|
||||
{% set hide_edit, hide_delete = true, true %}
|
||||
{{ include('crud/views/others/record_actions.html.twig.twig') -}}
|
||||
{{ "{% endblock %}" }}
|
||||
{% endblock body %}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<ul>
|
||||
<li>
|
||||
<a href="{{ "{{ path('" ~ route_name_prefix ~ "_index') }}" }}">Back to the list</a>
|
||||
</li>
|
||||
|
||||
{%- if ('edit' in actions) and (not hide_edit) %}
|
||||
|
||||
<li>
|
||||
<a href="{{ "{{ path('" ~ route_name_prefix ~ "_edit', { '"~ identifier ~"': " ~ entity_singularized ~ "."~ identifier ~" }) }}" }}">Edit</a>
|
||||
</li>
|
||||
|
||||
{%- endif %}
|
||||
|
||||
{%- if ('delete' in actions) and (not hide_delete) %}
|
||||
|
||||
<li>
|
||||
{{ '{{ form_start(delete_form) }}' }}
|
||||
<input type="submit" value="Delete">
|
||||
{{ '{{ form_end(delete_form) }}' }}
|
||||
</li>
|
||||
|
||||
{%- endif %}
|
||||
|
||||
</ul>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
{% block extends %}
|
||||
{{ "{% extends 'base.html.twig' %}" }}
|
||||
{% endblock extends %}
|
||||
|
||||
{% block body %}
|
||||
{{ "{% block body %}" }}
|
||||
<h1>{{ entity_singularized|capitalize }}</h1>
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
{%- for field, metadata in fields %}
|
||||
|
||||
<tr>
|
||||
<th>{{ field|capitalize }}</th>
|
||||
|
||||
{%- if metadata.type in ['datetime'] %}
|
||||
|
||||
<td>{{ '{% if ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ ' %}{{ ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ '|date(\'Y-m-d H:i:s\') }}{% endif %}' }}</td>
|
||||
|
||||
{%- elseif metadata.type in ['date'] %}
|
||||
|
||||
<td>{{ '{% if ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ ' %}{{ ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ '|date(\'Y-m-d\') }}{% endif %}' }}</td>
|
||||
|
||||
{%- elseif metadata.type in ['time'] %}
|
||||
|
||||
<td>{{ '{% if ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ ' %}{{ ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ '|date(\'H:i:s\') }}{% endif %}' }}</td>
|
||||
|
||||
{%- elseif metadata.type in ['array'] %}
|
||||
|
||||
<td>{{ '{% if ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ ' %}{{ ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ '|join(\', \') }}{% endif %}' }}</td>
|
||||
|
||||
{%- elseif metadata.type in ['boolean'] %}
|
||||
|
||||
<td>{{ '{% if ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ ' %}Yes{% else %}No{% endif %}' }}</td>
|
||||
|
||||
{%- else %}
|
||||
|
||||
<td>{{ '{{ ' ~ entity_singularized ~ '.' ~ field|replace({'_': ''}) ~ ' }}' }}</td>
|
||||
|
||||
{%- endif %}
|
||||
|
||||
</tr>
|
||||
|
||||
{%- endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% set hide_edit, hide_delete = false, false %}
|
||||
{{ include('crud/views/others/record_actions.html.twig.twig') -}}
|
||||
{{ "{% endblock %}" }}
|
||||
{% endblock body %}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
namespace {{ namespace }}\Form{{ entity_namespace ? '\\' ~ entity_namespace : '' }};
|
||||
|
||||
{% block use_statements %}
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
{% endblock use_statements %}
|
||||
|
||||
{% block class_definition %}
|
||||
class {{ form_class }} extends AbstractType
|
||||
{% endblock class_definition %}
|
||||
{
|
||||
{% block class_body %}
|
||||
{%- if fields|length > 0 %}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
{%- for field in fields -%}
|
||||
|
||||
->add('{{ field }}')
|
||||
|
||||
{%- endfor %};
|
||||
}
|
||||
{%- endif -%}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => '{{ namespace }}\Entity{{ entity_namespace ? '\\' ~ entity_namespace : '' }}\{{ entity_class }}'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return '{{ form_type_name }}';
|
||||
}
|
||||
|
||||
{# BC with Symfony 2.7 #}
|
||||
{%- if get_name_required %}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->getBlockPrefix();
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
{% endblock class_body %}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Sensio\Bundle\GeneratorBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
/**
|
||||
* SensioGeneratorBundle.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class SensioGeneratorBundle extends Bundle
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
<?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\Tests\Command\AutoComplete;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Sensio\Bundle\GeneratorBundle\Command\AutoComplete\EntitiesAutoCompleter;
|
||||
|
||||
class EntitiesAutoCompleterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getNamespaces
|
||||
*/
|
||||
public function testSuggestions($expected, $alias, $classes)
|
||||
{
|
||||
$autoCompleter = new EntitiesAutoCompleter($this->getEntityManagerMock($alias, $classes));
|
||||
|
||||
$this->assertSame($expected, $autoCompleter->getSuggestions());
|
||||
}
|
||||
|
||||
public function getNamespaces()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array('AcmeBlogBundle:Post'),
|
||||
array('AcmeBlogBundle' => 'Acme\Bundle\BlogBundle\Entity'),
|
||||
array('Acme\Bundle\BlogBundle\Entity\Post'),
|
||||
),
|
||||
array(
|
||||
array('AcmeBlogBundle:Blog\Post'),
|
||||
array('AcmeBlogBundle' => 'Acme\Bundle\BlogBundle\Entity'),
|
||||
array('Acme\Bundle\BlogBundle\Entity\Blog\Post'),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'AcmeBlogBundle:Post',
|
||||
'AcmeCommentBundle:Comment',
|
||||
'AcmeBlogBundle:Blog\Post',
|
||||
),
|
||||
array(
|
||||
'AcmeBlogBundle' => 'Acme\Bundle\BlogBundle\Entity',
|
||||
'AcmeCommentBundle' => 'Acme\Bundle\CommentBundle\Entity',
|
||||
),
|
||||
array(
|
||||
'Acme\Bundle\BlogBundle\Entity\Post',
|
||||
'Acme\Bundle\CommentBundle\Entity\Comment',
|
||||
'Acme\Bundle\BlogBundle\Entity\Blog\Post',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $aliases
|
||||
* @param $classes
|
||||
*
|
||||
* @return EntityManagerInterface
|
||||
*/
|
||||
protected function getEntityManagerMock($aliases, $classes)
|
||||
{
|
||||
$cache = $this->getMockBuilder('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver')->getMock();
|
||||
$cache
|
||||
->expects($this->any())
|
||||
->method('getAllClassNames')
|
||||
->will($this->returnValue($classes))
|
||||
;
|
||||
|
||||
$configuration = $this->getMockBuilder('Doctrine\ORM\Configuration')->getMock();
|
||||
$configuration
|
||||
->expects($this->any())
|
||||
->method('getMetadataDriverImpl')
|
||||
->will($this->returnValue($cache))
|
||||
;
|
||||
|
||||
$configuration
|
||||
->expects($this->any())
|
||||
->method('getEntityNamespaces')
|
||||
->will($this->returnValue($aliases))
|
||||
;
|
||||
|
||||
$manager = $this->getMockBuilder('Doctrine\ORM\EntityManagerInterface')->getMock();
|
||||
$manager
|
||||
->expects($this->any())
|
||||
->method('getConfiguration')
|
||||
->will($this->returnValue($configuration))
|
||||
;
|
||||
|
||||
return $manager;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
<?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\Tests\Command;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Model\Bundle;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
class GenerateBundleCommandTest extends GenerateCommandTest
|
||||
{
|
||||
/**
|
||||
* @dataProvider getInteractiveCommandData
|
||||
*/
|
||||
public function testInteractiveCommand($options, $input, $expected)
|
||||
{
|
||||
list($namespace, $bundleName, $dir, $format, $shared) = $expected;
|
||||
$bundle = new Bundle($namespace, $bundleName, $dir, $format, $shared);
|
||||
|
||||
$container = $this->getContainer();
|
||||
|
||||
// not shared? the tests should be at the root of the project
|
||||
if (!$shared) {
|
||||
$bundle->setTestsDirectory($container->getParameter('kernel.root_dir').'/../tests/'.$bundleName);
|
||||
}
|
||||
|
||||
$generator = $this->getGenerator();
|
||||
$generator
|
||||
->expects($this->once())
|
||||
->method('generateBundle')
|
||||
->with($bundle)
|
||||
;
|
||||
|
||||
$tester = new CommandTester($command = $this->getCommand($generator, $container));
|
||||
$this->setInputs($tester, $command, $input);
|
||||
$tester->execute($options);
|
||||
}
|
||||
|
||||
public function getInteractiveCommandData()
|
||||
{
|
||||
$tmp = sys_get_temp_dir();
|
||||
|
||||
return array(
|
||||
array(
|
||||
array('--shared' => true, '--dir' => $tmp, '--format' => 'annotation'),
|
||||
// shared, namespace, bundle name, directory, format
|
||||
"\nFoo/BarBundle\n\n\n\n",
|
||||
array('Foo\BarBundle', 'FooBarBundle', $tmp.'/', 'annotation', true),
|
||||
),
|
||||
array(
|
||||
array(),
|
||||
// shared, namespace, bundle name, directory, format
|
||||
"y\nFoo/BarBundle\nBarBundle\nfoo\nyml",
|
||||
array('Foo\BarBundle', 'BarBundle', 'foo/', 'yml', true),
|
||||
),
|
||||
array(
|
||||
array('--shared' => true, '--dir' => $tmp, '--format' => 'yml', '--bundle-name' => 'BarBundle'),
|
||||
// shared, namespace, bundle name, directory, format
|
||||
"\nFoo/BarBundle\n\n\n\n",
|
||||
array('Foo\BarBundle', 'BarBundle', $tmp.'/', 'yml', true),
|
||||
),
|
||||
array(
|
||||
array(),
|
||||
// shared, namespace, bundle name, directory, format
|
||||
"n\nBazBundle\n\nsrc\nannotation",
|
||||
array('BazBundle', 'BazBundle', 'src/', 'annotation', false),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getNonInteractiveCommandData
|
||||
*/
|
||||
public function testNonInteractiveCommand($options, $expected)
|
||||
{
|
||||
list($namespace, $bundleName, $dir, $format, $shared) = $expected;
|
||||
$bundle = new Bundle($namespace, $bundleName, $dir, $format, $shared);
|
||||
|
||||
$container = $this->getContainer();
|
||||
|
||||
// not shared? the tests should be at the root of the project
|
||||
if (!$shared) {
|
||||
$bundle->setTestsDirectory($container->getParameter('kernel.root_dir').'/../tests/'.$bundleName);
|
||||
}
|
||||
|
||||
$generator = $this->getGenerator();
|
||||
$generator
|
||||
->expects($this->once())
|
||||
->method('generateBundle')
|
||||
->with($bundle)
|
||||
;
|
||||
|
||||
$tester = new CommandTester($this->getCommand($generator, $container));
|
||||
$tester->execute($options, array('interactive' => false));
|
||||
}
|
||||
|
||||
public function getNonInteractiveCommandData()
|
||||
{
|
||||
$tmp = sys_get_temp_dir();
|
||||
|
||||
return array(
|
||||
array(
|
||||
array('--shared' => true, '--dir' => $tmp, '--namespace' => 'Foo/BarBundle'),
|
||||
array('Foo\BarBundle', 'FooBarBundle', $tmp.'/', 'annotation', true),
|
||||
),
|
||||
array(
|
||||
array('--shared' => true, '--dir' => $tmp, '--namespace' => 'Foo/BarBundle', '--format' => 'yml', '--bundle-name' => 'BarBundle'),
|
||||
array('Foo\BarBundle', 'BarBundle', $tmp.'/', 'yml', true),
|
||||
),
|
||||
array(
|
||||
array('--dir' => $tmp, '--namespace' => 'BazBundle', '--format' => 'yml', '--bundle-name' => 'BazBundle'),
|
||||
array('BazBundle', 'BazBundle', $tmp.'/', 'yml', false),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getCommand($generator, $container)
|
||||
{
|
||||
$command = $this
|
||||
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Command\GenerateBundleCommand')
|
||||
->setMethods(array('checkAutoloader', 'updateKernel', 'updateRouting'))
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$command->setContainer($container);
|
||||
$command->setHelperSet($this->getHelperSet());
|
||||
$command->setGenerator($generator);
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
protected function getGenerator()
|
||||
{
|
||||
// get a noop generator
|
||||
return $this
|
||||
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Generator\BundleGenerator')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('generateBundle'))
|
||||
->getMock()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
<?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\Tests\Command;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
use Sensio\Bundle\GeneratorBundle\Command\GenerateCommandCommand;
|
||||
|
||||
class GenerateCommandCommandTest extends GenerateCommandTest
|
||||
{
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* @dataProvider getInteractiveCommandData
|
||||
*/
|
||||
public function testInteractiveCommand($options, $input, $expected)
|
||||
{
|
||||
list($bundle, $name) = $expected;
|
||||
|
||||
$generator = $this->getGenerator();
|
||||
$generator
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->getBundle(), $name)
|
||||
;
|
||||
|
||||
$tester = new CommandTester($command = $this->getCommand($generator));
|
||||
$this->setInputs($tester, $command, $input);
|
||||
$tester->execute($options);
|
||||
}
|
||||
|
||||
public function getInteractiveCommandData()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(),
|
||||
"FooBarBundle\napp:foo-bar\n",
|
||||
array('FooBarBundle', 'app:foo-bar'),
|
||||
),
|
||||
|
||||
array(
|
||||
array('bundle' => 'FooBarBundle'),
|
||||
"app:foo-bar\n",
|
||||
array('FooBarBundle', 'app:foo-bar'),
|
||||
),
|
||||
|
||||
array(
|
||||
array('name' => 'app:foo-bar'),
|
||||
"FooBarBundle\n",
|
||||
array('FooBarBundle', 'app:foo-bar'),
|
||||
),
|
||||
|
||||
array(
|
||||
array('bundle' => 'FooBarBundle', 'name' => 'app:foo-bar'),
|
||||
'',
|
||||
array('FooBarBundle', 'app:foo-bar'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getNonInteractiveCommandData
|
||||
*/
|
||||
public function testNonInteractiveCommand($options, $expected)
|
||||
{
|
||||
list($bundle, $name) = $expected;
|
||||
|
||||
$generator = $this->getGenerator();
|
||||
$generator
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->getBundle(), $name)
|
||||
;
|
||||
|
||||
$tester = new CommandTester($command = $this->getCommand($generator));
|
||||
$tester->execute($options, array('interactive' => false));
|
||||
}
|
||||
|
||||
public function getNonInteractiveCommandData()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array('bundle' => 'FooBarBundle', 'name' => 'app:my-command'),
|
||||
array('FooBarBundle', 'app:my-command'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getCommand($generator)
|
||||
{
|
||||
$command = new GenerateCommandCommand();
|
||||
|
||||
$command->setContainer($this->getContainer());
|
||||
$command->setHelperSet($this->getHelperSet());
|
||||
$command->setGenerator($generator);
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
protected function getApplication($input = '')
|
||||
{
|
||||
$application = new Application();
|
||||
|
||||
$command = new GenerateCommandCommand();
|
||||
$command->setContainer($this->getContainer());
|
||||
$command->setHelperSet($this->getHelperSet($input));
|
||||
$command->setGenerator($this->getGenerator());
|
||||
|
||||
$application->add($command);
|
||||
|
||||
return $application;
|
||||
}
|
||||
|
||||
protected function getGenerator()
|
||||
{
|
||||
if (null === $this->generator) {
|
||||
$this->setGenerator();
|
||||
}
|
||||
|
||||
return $this->generator;
|
||||
}
|
||||
|
||||
protected function setGenerator()
|
||||
{
|
||||
// get a noop generator
|
||||
$this->generator = $this
|
||||
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Generator\CommandGenerator')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('generate'))
|
||||
->getMock()
|
||||
;
|
||||
}
|
||||
|
||||
protected function getBundle()
|
||||
{
|
||||
if (null == $this->bundle) {
|
||||
$this->setBundle();
|
||||
}
|
||||
|
||||
return $this->bundle;
|
||||
}
|
||||
|
||||
protected function setBundle()
|
||||
{
|
||||
$bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock();
|
||||
$bundle->expects($this->any())->method('getPath')->will($this->returnValue(''));
|
||||
$bundle->expects($this->any())->method('getName')->will($this->returnValue('FooBarBundle'));
|
||||
$bundle->expects($this->any())->method('getNamespace')->will($this->returnValue('Foo\BarBundle'));
|
||||
|
||||
$this->bundle = $bundle;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<?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\Tests\Command;
|
||||
|
||||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
use Symfony\Component\Console\Helper\FormatterHelper;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Sensio\Bundle\GeneratorBundle\Command\Helper\QuestionHelper;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
|
||||
abstract class GenerateCommandTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $bundle;
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
if (null !== $this->bundle) {
|
||||
$fs = new Filesystem();
|
||||
$fs->remove($this->bundle->getPath());
|
||||
}
|
||||
}
|
||||
|
||||
protected function getHelperSet()
|
||||
{
|
||||
return new HelperSet(array(new FormatterHelper(), new QuestionHelper()));
|
||||
}
|
||||
|
||||
protected function setInputs($tester, $command, $input)
|
||||
{
|
||||
$input .= str_repeat("\n", 10);
|
||||
if (method_exists($tester, 'setInputs')) {
|
||||
$tester->setInputs(explode("\n", $input));
|
||||
} else {
|
||||
$stream = fopen('php://memory', 'r+', false);
|
||||
fwrite($stream, $input);
|
||||
rewind($stream);
|
||||
|
||||
$command->getHelperSet()->get('question')->setInputStream($stream);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getBundle()
|
||||
{
|
||||
if (null !== $this->bundle) {
|
||||
return $this->bundle;
|
||||
}
|
||||
|
||||
$tmpDir = sys_get_temp_dir().'/sf'.mt_rand(111111, 999999);
|
||||
@mkdir($tmpDir, 0777, true);
|
||||
|
||||
$this->bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock();
|
||||
$this->bundle
|
||||
->expects($this->any())
|
||||
->method('getPath')
|
||||
->will($this->returnValue($tmpDir))
|
||||
;
|
||||
|
||||
return $this->bundle;
|
||||
}
|
||||
|
||||
protected function getContainer()
|
||||
{
|
||||
$bundle = $this->getBundle();
|
||||
|
||||
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock();
|
||||
$kernel
|
||||
->expects($this->any())
|
||||
->method('getBundle')
|
||||
->will($this->returnValue($bundle))
|
||||
;
|
||||
$kernel
|
||||
->expects($this->any())
|
||||
->method('getBundles')
|
||||
->will($this->returnValue(array($bundle)))
|
||||
;
|
||||
|
||||
$filesystem = $this->getMockBuilder('Symfony\Component\Filesystem\Filesystem')->getMock();
|
||||
$filesystem
|
||||
->expects($this->any())
|
||||
->method('isAbsolutePath')
|
||||
->will($this->returnValue(true))
|
||||
;
|
||||
|
||||
$container = new Container();
|
||||
$container->set('kernel', $kernel);
|
||||
$container->set('filesystem', $filesystem);
|
||||
|
||||
$container->setParameter('kernel.root_dir', $bundle->getPath());
|
||||
|
||||
return $container;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
<?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\Tests\Command;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
use Sensio\Bundle\GeneratorBundle\Command\GenerateControllerCommand;
|
||||
|
||||
class GenerateControllerCommandTest extends GenerateCommandTest
|
||||
{
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* @dataProvider getInteractiveCommandData
|
||||
*/
|
||||
public function testInteractiveCommand($options, $input, $expected)
|
||||
{
|
||||
list($controller, $routeFormat, $templateFormat, $actions) = $expected;
|
||||
|
||||
$generator = $this->getGenerator();
|
||||
$generator
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->getBundle(), $controller, $routeFormat, $templateFormat, $actions)
|
||||
;
|
||||
|
||||
$tester = new CommandTester($command = $this->getCommand($generator));
|
||||
$this->setInputs($tester, $command, $input);
|
||||
$tester->execute($options);
|
||||
}
|
||||
|
||||
public function getInteractiveCommandData()
|
||||
{
|
||||
return array(
|
||||
array(array(), "AcmeBlogBundle:Post\n", array('Post', 'annotation', 'twig', array())),
|
||||
array(array('--controller' => 'AcmeBlogBundle:Post'), '', array('Post', 'annotation', 'twig', array())),
|
||||
|
||||
array(array(), "AcmeBlogBundle:Post\nyml\nphp\n", array('Post', 'yml', 'php', array())),
|
||||
|
||||
array(array(), "AcmeBlogBundle:Post\nyml\nphp\nshowAction\n\n\ngetListAction\n/_getlist/{max}\nAcmeBlogBundle:Lists:post.html.php\n", array('Post', 'yml', 'php', array(
|
||||
'showAction' => array(
|
||||
'name' => 'showAction',
|
||||
'route' => '/show',
|
||||
'placeholders' => array(),
|
||||
'template' => 'AcmeBlogBundle:Post:show.html.php',
|
||||
),
|
||||
'getListAction' => array(
|
||||
'name' => 'getListAction',
|
||||
'route' => '/_getlist/{max}',
|
||||
'placeholders' => array('max'),
|
||||
'template' => 'AcmeBlogBundle:Lists:post.html.php',
|
||||
),
|
||||
))),
|
||||
|
||||
array(array('--route-format' => 'xml', '--template-format' => 'php', '--actions' => array('showAction:/{slug}:AcmeBlogBundle:article.html.php')), 'AcmeBlogBundle:Post', array('Post', 'xml', 'php', array(
|
||||
'showAction' => array(
|
||||
'name' => 'showAction',
|
||||
'route' => '/{slug}',
|
||||
'placeholders' => array('slug'),
|
||||
'template' => 'AcmeBlogBundle:article.html.php',
|
||||
),
|
||||
))),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getNonInteractiveCommandData
|
||||
*/
|
||||
public function testNonInteractiveCommand($options, $expected)
|
||||
{
|
||||
list($controller, $routeFormat, $templateFormat, $actions) = $expected;
|
||||
|
||||
$generator = $this->getGenerator();
|
||||
$generator
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->getBundle(), $controller, $routeFormat, $templateFormat, $actions)
|
||||
;
|
||||
|
||||
$tester = new CommandTester($command = $this->getCommand($generator));
|
||||
$tester->execute($options, array('interactive' => false));
|
||||
}
|
||||
|
||||
public function getNonInteractiveCommandData()
|
||||
{
|
||||
return array(
|
||||
array(array('--controller' => 'AcmeBlogBundle:Post'), array('Post', 'annotation', 'twig', array())),
|
||||
array(array('--controller' => 'AcmeBlogBundle:Post', '--route-format' => 'yml', '--template-format' => 'php'), array('Post', 'yml', 'php', array())),
|
||||
array(array('--controller' => 'AcmeBlogBundle:Post', '--actions' => array('showAction getListAction:/_getlist/{max}:AcmeBlogBundle:List:post.html.twig createAction:/admin/create')), array('Post', 'annotation', 'twig', array(
|
||||
'showAction' => array(
|
||||
'name' => 'showAction',
|
||||
'route' => '/show',
|
||||
'placeholders' => array(),
|
||||
'template' => 'default',
|
||||
),
|
||||
'getListAction' => array(
|
||||
'name' => 'getListAction',
|
||||
'route' => '/_getlist/{max}',
|
||||
'placeholders' => array('max'),
|
||||
'template' => 'AcmeBlogBundle:List:post.html.twig',
|
||||
),
|
||||
'createAction' => array(
|
||||
'name' => 'createAction',
|
||||
'route' => '/admin/create',
|
||||
'placeholders' => array(),
|
||||
'template' => 'default',
|
||||
),
|
||||
))),
|
||||
array(array('--controller' => 'AcmeBlogBundle:Post', '--route-format' => 'xml', '--template-format' => 'php', '--actions' => array('showAction::')), array('Post', 'xml', 'php', array(
|
||||
'showAction' => array(
|
||||
'name' => 'showAction',
|
||||
'route' => '/show',
|
||||
'placeholders' => array(),
|
||||
'template' => 'default',
|
||||
),
|
||||
))),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getCommand($generator)
|
||||
{
|
||||
$command = $this
|
||||
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Command\GenerateControllerCommand')
|
||||
->setMethods(array('generateRouting'))
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$command->setContainer($this->getContainer());
|
||||
$command->setHelperSet($this->getHelperSet());
|
||||
$command->setGenerator($generator);
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
protected function getApplication($input = '')
|
||||
{
|
||||
$application = new Application();
|
||||
|
||||
$command = new GenerateControllerCommand();
|
||||
$command->setContainer($this->getContainer());
|
||||
$command->setHelperSet($this->getHelperSet($input));
|
||||
$command->setGenerator($this->getGenerator());
|
||||
|
||||
$application->add($command);
|
||||
|
||||
return $application;
|
||||
}
|
||||
|
||||
protected function getGenerator()
|
||||
{
|
||||
if (null == $this->generator) {
|
||||
$this->setGenerator();
|
||||
}
|
||||
|
||||
return $this->generator;
|
||||
}
|
||||
|
||||
protected function setGenerator()
|
||||
{
|
||||
// get a noop generator
|
||||
$this->generator = $this
|
||||
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Generator\ControllerGenerator')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('generate'))
|
||||
->getMock()
|
||||
;
|
||||
}
|
||||
|
||||
protected function getBundle()
|
||||
{
|
||||
if (null == $this->bundle) {
|
||||
$this->setBundle();
|
||||
}
|
||||
|
||||
return $this->bundle;
|
||||
}
|
||||
|
||||
protected function setBundle()
|
||||
{
|
||||
$bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock();
|
||||
$bundle->expects($this->any())->method('getPath')->will($this->returnValue(''));
|
||||
$bundle->expects($this->any())->method('getName')->will($this->returnValue('FooBarBundle'));
|
||||
$bundle->expects($this->any())->method('getNamespace')->will($this->returnValue('Foo\BarBundle'));
|
||||
|
||||
$this->bundle = $bundle;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,300 @@
|
|||
<?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\Tests\Command;
|
||||
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
class GenerateDoctrineCrudCommandTest extends GenerateCommandTest
|
||||
{
|
||||
/**
|
||||
* @dataProvider getInteractiveCommandData
|
||||
*/
|
||||
public function testInteractiveCommand($options, $input, $expected)
|
||||
{
|
||||
list($entity, $format, $prefix, $withWrite) = $expected;
|
||||
|
||||
$generator = $this->getGenerator();
|
||||
$generator
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->getBundle(), $entity, $this->getDoctrineMetadata(), $format, $prefix, $withWrite)
|
||||
;
|
||||
|
||||
$tester = new CommandTester($command = $this->getCommand($generator));
|
||||
$this->setInputs($tester, $command, $input);
|
||||
$tester->execute($options);
|
||||
}
|
||||
|
||||
public function getInteractiveCommandData()
|
||||
{
|
||||
return array(
|
||||
array(array(), "AcmeBlogBundle:Blog/Post\n", array('Blog\\Post', 'annotation', 'blog_post', false)),
|
||||
array(array(), "AcmeBlogBundle:Blog/Post\ny\nyml\nfoobar\n", array('Blog\\Post', 'yml', 'foobar', true)),
|
||||
array(array(), "AcmeBlogBundle:Blog/Post\ny\nyml\n/foobar\n", array('Blog\\Post', 'yml', 'foobar', true)),
|
||||
array(array('entity' => 'AcmeBlogBundle:Blog/Post'), "\ny\nyml\nfoobar\n", array('Blog\\Post', 'yml', 'foobar', true)),
|
||||
array(array('entity' => 'AcmeBlogBundle:Blog/Post'), '', array('Blog\\Post', 'annotation', 'blog_post', false)),
|
||||
array(array('entity' => 'AcmeBlogBundle:Blog/Post', '--format' => 'yml', '--route-prefix' => 'foo', '--with-write' => true), '', array('Blog\\Post', 'yml', 'foo', true)),
|
||||
// Deprecated, to be removed in 4.0
|
||||
array(array('--entity' => 'AcmeBlogBundle:Blog/Post'), '', array('Blog\\Post', 'annotation', 'blog_post', false)),
|
||||
array(array('--entity' => 'AcmeBlogBundle:Blog/Post', '--format' => 'yml', '--route-prefix' => 'foo', '--with-write' => true), '', array('Blog\\Post', 'yml', 'foo', true)),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getNonInteractiveCommandData
|
||||
*/
|
||||
public function testNonInteractiveCommand($options, $expected)
|
||||
{
|
||||
list($entity, $format, $prefix, $withWrite) = $expected;
|
||||
|
||||
$generator = $this->getGenerator();
|
||||
$generator
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->getBundle(), $entity, $this->getDoctrineMetadata(), $format, $prefix, $withWrite)
|
||||
;
|
||||
|
||||
$tester = new CommandTester($this->getCommand($generator));
|
||||
$tester->execute($options, array('interactive' => false));
|
||||
}
|
||||
|
||||
public function getNonInteractiveCommandData()
|
||||
{
|
||||
return array(
|
||||
array(array('entity' => 'AcmeBlogBundle:Blog/Post'), array('Blog\\Post', 'annotation', 'blog_post', false)),
|
||||
array(array('entity' => 'AcmeBlogBundle:Blog/Post', '--format' => 'yml', '--route-prefix' => 'foo', '--with-write' => true), array('Blog\\Post', 'yml', 'foo', true)),
|
||||
// Deprecated, to be removed in 4.0
|
||||
array(array('--entity' => 'AcmeBlogBundle:Blog/Post'), array('Blog\\Post', 'annotation', 'blog_post', false)),
|
||||
array(array('--entity' => 'AcmeBlogBundle:Blog/Post', '--format' => 'yml', '--route-prefix' => 'foo', '--with-write' => true), array('Blog\\Post', 'yml', 'foo', true)),
|
||||
);
|
||||
}
|
||||
|
||||
public function testCreateCrudWithAnnotationInNonAnnotationBundle()
|
||||
{
|
||||
$rootDir = $this->getContainer()->getParameter('kernel.root_dir');
|
||||
|
||||
$routing = <<<DATA
|
||||
acme_blog:
|
||||
resource: "@AcmeBlogBundle/Resources/config/routing.xml"
|
||||
prefix: /
|
||||
DATA;
|
||||
|
||||
@mkdir($rootDir.'/config', 0777, true);
|
||||
file_put_contents($rootDir.'/config/routing.yml', $routing);
|
||||
|
||||
$options = array();
|
||||
$input = "AcmeBlogBundle:Blog/Post\ny\nannotation\n/foobar\n";
|
||||
$expected = array('Blog\\Post', 'annotation', 'foobar', true);
|
||||
|
||||
list($entity, $format, $prefix, $withWrite) = $expected;
|
||||
|
||||
$generator = $this->getGenerator();
|
||||
$generator
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->getBundle(), $entity, $this->getDoctrineMetadata(), $format, $prefix, $withWrite)
|
||||
;
|
||||
|
||||
$tester = new CommandTester($command = $this->getCommand($generator));
|
||||
$this->setInputs($tester, $command, $input);
|
||||
$tester->execute($options);
|
||||
|
||||
$this->assertContains('acme_blog_post:', file_get_contents($rootDir.'/config/routing.yml'));
|
||||
}
|
||||
|
||||
public function testCreateCrudWithAnnotationInAnnotationBundle()
|
||||
{
|
||||
$rootDir = $this->getContainer()->getParameter('kernel.root_dir');
|
||||
|
||||
$routing = <<<DATA
|
||||
acme_blog:
|
||||
resource: "@AcmeBlogBundle/Controller/"
|
||||
type: annotation
|
||||
DATA;
|
||||
|
||||
@mkdir($rootDir.'/config', 0777, true);
|
||||
file_put_contents($rootDir.'/config/routing.yml', $routing);
|
||||
|
||||
$options = array();
|
||||
$input = "AcmeBlogBundle:Blog/Post\ny\nyml\n/foobar\n";
|
||||
$expected = array('Blog\\Post', 'yml', 'foobar', true);
|
||||
|
||||
list($entity, $format, $prefix, $withWrite) = $expected;
|
||||
|
||||
$generator = $this->getGenerator();
|
||||
$generator
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->getBundle(), $entity, $this->getDoctrineMetadata(), $format, $prefix, $withWrite)
|
||||
;
|
||||
|
||||
$tester = new CommandTester($command = $this->getCommand($generator));
|
||||
$this->setInputs($tester, $command, $input);
|
||||
$tester->execute($options);
|
||||
|
||||
$this->assertEquals($routing, file_get_contents($rootDir.'/config/routing.yml'));
|
||||
}
|
||||
|
||||
public function testAddACrudWithOneAlreadyDefined()
|
||||
{
|
||||
$rootDir = $this->getContainer()->getParameter('kernel.root_dir');
|
||||
|
||||
$routing = <<<DATA
|
||||
acme_blog:
|
||||
resource: "@AcmeBlogBundle/Controller/OtherController.php"
|
||||
type: annotation
|
||||
DATA;
|
||||
|
||||
@mkdir($rootDir.'/config', 0777, true);
|
||||
file_put_contents($rootDir.'/config/routing.yml', $routing);
|
||||
|
||||
$options = array();
|
||||
$input = "AcmeBlogBundle:Blog/Post\ny\nannotation\n/foobar\n";
|
||||
$expected = array('Blog\\Post', 'annotation', 'foobar', true);
|
||||
|
||||
list($entity, $format, $prefix, $withWrite) = $expected;
|
||||
|
||||
$generator = $this->getGenerator();
|
||||
$generator
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->getBundle(), $entity, $this->getDoctrineMetadata(), $format, $prefix, $withWrite)
|
||||
;
|
||||
|
||||
$tester = new CommandTester($command = $this->getCommand($generator));
|
||||
$this->setInputs($tester, $command, $input);
|
||||
$tester->execute($options);
|
||||
|
||||
$expected = '@AcmeBlogBundle/Controller/PostController.php';
|
||||
|
||||
$this->assertContains($expected, file_get_contents($rootDir.'/config/routing.yml'));
|
||||
}
|
||||
|
||||
protected function getCommand($generator)
|
||||
{
|
||||
$command = $this
|
||||
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineCrudCommand')
|
||||
->setMethods(array('getEntityMetadata'))
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$command
|
||||
->expects($this->any())
|
||||
->method('getEntityMetadata')
|
||||
->will($this->returnValue(array($this->getDoctrineMetadata())))
|
||||
;
|
||||
|
||||
$command->setContainer($this->getContainer());
|
||||
$command->setHelperSet($this->getHelperSet());
|
||||
$command->setGenerator($generator);
|
||||
$command->setFormGenerator($this->getFormGenerator());
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
protected function getDoctrineMetadata()
|
||||
{
|
||||
return $this
|
||||
->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadataInfo')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
}
|
||||
|
||||
protected function getGenerator()
|
||||
{
|
||||
// get a noop generator
|
||||
return $this
|
||||
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGenerator')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('generate'))
|
||||
->getMock()
|
||||
;
|
||||
}
|
||||
|
||||
protected function getFormGenerator()
|
||||
{
|
||||
return $this
|
||||
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Generator\DoctrineFormGenerator')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('generate'))
|
||||
->getMock()
|
||||
;
|
||||
}
|
||||
|
||||
protected function getBundle()
|
||||
{
|
||||
$bundle = parent::getBundle();
|
||||
$bundle
|
||||
->expects($this->any())
|
||||
->method('getName')
|
||||
->will($this->returnValue('AcmeBlogBundle'))
|
||||
;
|
||||
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
protected function getContainer()
|
||||
{
|
||||
$container = parent::getContainer();
|
||||
|
||||
$container->set('doctrine', $this->getDoctrine());
|
||||
|
||||
return $container;
|
||||
}
|
||||
|
||||
protected function getDoctrine()
|
||||
{
|
||||
$cache = $this->getMockBuilder('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver')->getMock();
|
||||
$cache
|
||||
->expects($this->any())
|
||||
->method('getAllClassNames')
|
||||
->will($this->returnValue(array('Acme\Bundle\BlogBundle\Entity\Post')))
|
||||
;
|
||||
|
||||
$configuration = $this->getMockBuilder('Doctrine\ORM\Configuration')->getMock();
|
||||
$configuration
|
||||
->expects($this->any())
|
||||
->method('getMetadataDriverImpl')
|
||||
->will($this->returnValue($cache))
|
||||
;
|
||||
|
||||
$configuration
|
||||
->expects($this->any())
|
||||
->method('getEntityNamespaces')
|
||||
->will($this->returnValue(array('AcmeBlogBundle' => 'Acme\Bundle\BlogBundle\Entity')))
|
||||
;
|
||||
|
||||
$manager = $this->getMockBuilder('Doctrine\ORM\EntityManagerInterface')->getMock();
|
||||
$manager
|
||||
->expects($this->any())
|
||||
->method('getConfiguration')
|
||||
->will($this->returnValue($configuration))
|
||||
;
|
||||
|
||||
$registry = $this->getMockBuilder('Symfony\Bridge\Doctrine\RegistryInterface')->getMock();
|
||||
$registry
|
||||
->expects($this->any())
|
||||
->method('getAliasNamespace')
|
||||
->will($this->returnValue('Acme\Bundle\BlogBundle\Entity\Blog\Post'))
|
||||
;
|
||||
|
||||
$registry
|
||||
->expects($this->any())
|
||||
->method('getManager')
|
||||
->will($this->returnValue($manager))
|
||||
;
|
||||
|
||||
return $registry;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
<?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\Tests\Command;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Model\EntityGeneratorResult;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineEntityCommand;
|
||||
|
||||
class GenerateDoctrineEntityCommandTest extends GenerateCommandTest
|
||||
{
|
||||
/**
|
||||
* @dataProvider getInteractiveCommandData
|
||||
*/
|
||||
public function testInteractiveCommand($options, $input, $expected)
|
||||
{
|
||||
list($entity, $format, $fields) = $expected;
|
||||
|
||||
$generator = $this->getGenerator();
|
||||
$generator
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->getBundle(), $entity, $format, $fields)
|
||||
->willReturn(new EntityGeneratorResult('', '', ''))
|
||||
;
|
||||
|
||||
$tester = new CommandTester($command = $this->getCommand($generator));
|
||||
$this->setInputs($tester, $command, $input);
|
||||
$tester->execute($options);
|
||||
}
|
||||
|
||||
public function getInteractiveCommandData()
|
||||
{
|
||||
return array(
|
||||
array(array(), "Acme2BlogBundle:Blog/Post\n", array('Blog\\Post', 'annotation', array())),
|
||||
array(array('entity' => 'Acme2BlogBundle:Blog/Post'), '', array('Blog\\Post', 'annotation', array())),
|
||||
array(array(), "Acme2BlogBundle:Blog/Post\nyml\n\n", array('Blog\\Post', 'yml', array())),
|
||||
array(array(), "Acme2BlogBundle:Blog/Post\nyml\ncreated_by\n\n255\nfalse\nfalse\ndescription\ntext\nfalse\ntrue\nupdated_at\ndatetime\ntrue\nfalse\nrating\ndecimal\n5\n3\nfalse\nfalse\n\n", array('Blog\\Post', 'yml', array(
|
||||
array('fieldName' => 'createdBy', 'type' => 'string', 'length' => 255, 'columnName' => 'created_by'),
|
||||
array('fieldName' => 'description', 'type' => 'text', 'unique' => true, 'columnName' => 'description'),
|
||||
array('fieldName' => 'updatedAt', 'type' => 'datetimetz', 'nullable' => true, 'columnName' => 'updated_at'),
|
||||
array('fieldName' => 'rating', 'type' => 'decimal', 'precision' => 5, 'scale' => 3, 'columnName' => 'rating'),
|
||||
))),
|
||||
// Deprecated, to be removed in 4.0
|
||||
array(array('--entity' => 'Acme2BlogBundle:Blog/Post'), '', array('Blog\\Post', 'annotation', array())),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getNonInteractiveCommandData
|
||||
*/
|
||||
public function testNonInteractiveCommand($options, $expected)
|
||||
{
|
||||
list($entity, $format, $fields) = $expected;
|
||||
|
||||
$generator = $this->getGenerator();
|
||||
$generator
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->getBundle(), $entity, $format, $fields)
|
||||
->willReturn(new EntityGeneratorResult('', '', ''))
|
||||
;
|
||||
$generator
|
||||
->expects($this->any())
|
||||
->method('isReservedKeyword')
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
|
||||
$tester = new CommandTester($this->getCommand($generator));
|
||||
$tester->execute($options, array('interactive' => false));
|
||||
}
|
||||
|
||||
public function getNonInteractiveCommandData()
|
||||
{
|
||||
return array(
|
||||
array(array('entity' => 'Acme2BlogBundle:Blog/Post'), array('Blog\\Post', 'annotation', array())),
|
||||
array(array('entity' => 'Acme2BlogBundle:Blog/Post', '--format' => 'yml', '--fields' => 'created_by:string(255) updated_by:string(length=128 nullable=true) description:text rating:decimal(precision=7 scale=2)'), array('Blog\\Post', 'yml', array(
|
||||
array('fieldName' => 'created_by', 'type' => 'string', 'length' => 255),
|
||||
array('fieldName' => 'updated_by', 'type' => 'string', 'length' => 128, 'nullable' => true),
|
||||
array('fieldName' => 'description', 'type' => 'text'),
|
||||
array('fieldName' => 'rating', 'type' => 'decimal', 'precision' => 7, 'scale' => 2),
|
||||
))),
|
||||
// Deprecated, to be removed in 4.0
|
||||
array(array('--entity' => 'Acme2BlogBundle:Blog/Post'), array('Blog\\Post', 'annotation', array())),
|
||||
array(array('--entity' => 'Acme2BlogBundle:Blog/Post', '--format' => 'yml', '--fields' => 'created_by:string(255) updated_by:string(length=128 nullable=true) description:text rating:decimal(precision=7 scale=2)'), array('Blog\\Post', 'yml', array(
|
||||
array('fieldName' => 'created_by', 'type' => 'string', 'length' => 255),
|
||||
array('fieldName' => 'updated_by', 'type' => 'string', 'length' => 128, 'nullable' => true),
|
||||
array('fieldName' => 'description', 'type' => 'text'),
|
||||
array('fieldName' => 'rating', 'type' => 'decimal', 'precision' => 7, 'scale' => 2),
|
||||
))),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getCommand($generator)
|
||||
{
|
||||
$command = new GenerateDoctrineEntityCommand();
|
||||
$command->setContainer($this->getContainer());
|
||||
$command->setHelperSet($this->getHelperSet());
|
||||
$command->setGenerator($generator);
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
protected function getGenerator()
|
||||
{
|
||||
// get a noop generator
|
||||
return $this
|
||||
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Generator\DoctrineEntityGenerator')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('generate', 'isReservedKeyword'))
|
||||
->getMock()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
<?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\Tests\Generator;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\BundleGenerator;
|
||||
use Sensio\Bundle\GeneratorBundle\Model\Bundle;
|
||||
|
||||
class BundleGeneratorTest extends GeneratorTest
|
||||
{
|
||||
public function testGenerateYaml()
|
||||
{
|
||||
$bundle = new Bundle('Foo\BarBundle', 'FooBarBundle', $this->tmpDir, 'yml', true);
|
||||
$this->getGenerator()->generateBundle($bundle);
|
||||
|
||||
$files = array(
|
||||
'FooBarBundle.php',
|
||||
'Controller/DefaultController.php',
|
||||
'Resources/views/Default/index.html.twig',
|
||||
'Resources/config/routing.yml',
|
||||
'Tests/Controller/DefaultControllerTest.php',
|
||||
'Resources/config/services.yml',
|
||||
'DependencyInjection/Configuration.php',
|
||||
'DependencyInjection/FooBarExtension.php',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/Foo/BarBundle/'.$file), sprintf('%s has been generated', $file));
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Foo/BarBundle/FooBarBundle.php');
|
||||
$this->assertContains('namespace Foo\\BarBundle', $content);
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Foo/BarBundle/Controller/DefaultController.php');
|
||||
$this->assertContains('public function indexAction', $content);
|
||||
$this->assertNotContains('@Route("/hello/{name}"', $content);
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Foo/BarBundle/Resources/views/Default/index.html.twig');
|
||||
$this->assertContains('Hello World!', $content);
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Foo/BarBundle/Resources/config/services.yml');
|
||||
$this->assertContains('class: Foo\BarBundle\Example', $content);
|
||||
}
|
||||
|
||||
public function testGenerateXml()
|
||||
{
|
||||
$bundle = new Bundle('Foo\BarBundle', 'FooBarBundle', $this->tmpDir, 'xml', true);
|
||||
$this->getGenerator()->generateBundle($bundle);
|
||||
|
||||
$files = array(
|
||||
'FooBarBundle.php',
|
||||
'Controller/DefaultController.php',
|
||||
'Resources/views/Default/index.html.twig',
|
||||
'Resources/config/routing.xml',
|
||||
'Tests/Controller/DefaultControllerTest.php',
|
||||
'Resources/config/services.xml',
|
||||
'DependencyInjection/Configuration.php',
|
||||
'DependencyInjection/FooBarExtension.php',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/Foo/BarBundle/'.$file), sprintf('%s has been generated', $file));
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Foo/BarBundle/Resources/config/services.xml');
|
||||
$this->assertContains('<service id="foo_bar.example" class="Foo\BarBundle\Example">', $content);
|
||||
}
|
||||
|
||||
public function testGenerateAnnotation()
|
||||
{
|
||||
$bundle = new Bundle('Foo\BarBundle', 'FooBarBundle', $this->tmpDir, 'annotation', false);
|
||||
$this->getGenerator()->generateBundle($bundle);
|
||||
|
||||
$this->assertFalse(file_exists($this->tmpDir.'/Foo/BarBundle/Resources/config/routing.yml'));
|
||||
$this->assertFalse(file_exists($this->tmpDir.'/Foo/BarBundle/Resources/config/routing.xml'));
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Foo/BarBundle/Controller/DefaultController.php');
|
||||
$this->assertContains('@Route("/")', $content);
|
||||
}
|
||||
|
||||
public function testDirIsFile()
|
||||
{
|
||||
$this->filesystem->mkdir($this->tmpDir.'/Foo');
|
||||
$this->filesystem->touch($this->tmpDir.'/Foo/BarBundle');
|
||||
|
||||
$bundle = new Bundle('Foo\BarBundle', 'FooBarBundle', $this->tmpDir, 'yml', false);
|
||||
try {
|
||||
$this->getGenerator()->generateBundle($bundle);
|
||||
$this->fail('An exception was expected!');
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->assertEquals(sprintf('Unable to generate the bundle as the target directory "%s" exists but is a file.', realpath($this->tmpDir.'/Foo/BarBundle')), $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function testIsNotWritableDir()
|
||||
{
|
||||
$this->filesystem->mkdir($this->tmpDir.'/Foo/BarBundle');
|
||||
$this->filesystem->chmod($this->tmpDir.'/Foo/BarBundle', 0444);
|
||||
|
||||
$bundle = new Bundle('Foo\BarBundle', 'FooBarBundle', $this->tmpDir, 'yml', false);
|
||||
try {
|
||||
$this->getGenerator()->generateBundle($bundle);
|
||||
$this->fail('An exception was expected!');
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->filesystem->chmod($this->tmpDir.'/Foo/BarBundle', 0777);
|
||||
$this->assertEquals(sprintf('Unable to generate the bundle as the target directory "%s" is not writable.', realpath($this->tmpDir.'/Foo/BarBundle')), $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function testIsNotEmptyDir()
|
||||
{
|
||||
$this->filesystem->mkdir($this->tmpDir.'/Foo/BarBundle');
|
||||
$this->filesystem->touch($this->tmpDir.'/Foo/BarBundle/somefile');
|
||||
|
||||
$bundle = new Bundle('Foo\BarBundle', 'FooBarBundle', $this->tmpDir, 'yml', false);
|
||||
try {
|
||||
$this->getGenerator()->generateBundle($bundle);
|
||||
$this->fail('An exception was expected!');
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->filesystem->chmod($this->tmpDir.'/Foo/BarBundle', 0777);
|
||||
$this->assertEquals(sprintf('Unable to generate the bundle as the target directory "%s" is not empty.', realpath($this->tmpDir.'/Foo/BarBundle')), $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function testExistingEmptyDirIsFine()
|
||||
{
|
||||
$this->filesystem->mkdir($this->tmpDir.'/Foo/BarBundle');
|
||||
|
||||
$bundle = new Bundle('Foo\BarBundle', 'FooBarBundle', $this->tmpDir, 'yml', true);
|
||||
$this->getGenerator()->generateBundle($bundle);
|
||||
}
|
||||
|
||||
public function testAlternateTestsDirectory()
|
||||
{
|
||||
$bundle = new Bundle('Foo\BarBundle', 'FooBarBundle', $this->tmpDir, 'xml', true);
|
||||
$bundle->setTestsDirectory($this->tmpDir.'/other/path/tests');
|
||||
$this->getGenerator()->generateBundle($bundle);
|
||||
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/other/path/tests/Controller/DefaultControllerTest.php'));
|
||||
}
|
||||
|
||||
protected function getGenerator()
|
||||
{
|
||||
$generator = new BundleGenerator($this->filesystem);
|
||||
$generator->setSkeletonDirs(__DIR__.'/../../Resources/skeleton');
|
||||
|
||||
return $generator;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<?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\Tests\Generator;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\CommandGenerator;
|
||||
|
||||
class CommandGeneratorTest extends GeneratorTest
|
||||
{
|
||||
public function testGenerateController()
|
||||
{
|
||||
$commandName = 'app:foo-bar';
|
||||
$commandFile = 'Command/AppFooBarCommand.php';
|
||||
$commandPath = $this->tmpDir.'/'.$commandFile;
|
||||
|
||||
$this->getGenerator()->generate($this->getBundle(), $commandName);
|
||||
|
||||
$this->assertTrue(file_exists($commandPath), sprintf('%s file has been generated.', $commandFile));
|
||||
|
||||
$commandContent = file_get_contents($commandPath);
|
||||
$strings = array(
|
||||
'namespace Foo\\BarBundle\\Command',
|
||||
'class AppFooBarCommand extends ContainerAwareCommand',
|
||||
sprintf("->setName('%s')", $commandName),
|
||||
);
|
||||
foreach ($strings as $string) {
|
||||
$this->assertContains($string, $commandContent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getNames
|
||||
*/
|
||||
public function testClassify($commandName, $className)
|
||||
{
|
||||
$generator = $this->getGenerator();
|
||||
$this->assertEquals($className, $generator->classify($commandName));
|
||||
}
|
||||
|
||||
public function getNames()
|
||||
{
|
||||
return array(
|
||||
array('app', 'App'),
|
||||
array('app-foo', 'AppFoo'),
|
||||
array('app_foo', 'AppFoo'),
|
||||
array('app:foo-bar', 'AppFooBar'),
|
||||
array('app:foo:bar', 'AppFooBar'),
|
||||
array('app:foo:bar-baz', 'AppFooBarBaz'),
|
||||
array('app:foo:bar_baz', 'AppFooBarBaz'),
|
||||
array('app-foo:bar-baz:foo-bar', 'AppFooBarBazFooBar'),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getGenerator()
|
||||
{
|
||||
$generator = new CommandGenerator($this->filesystem);
|
||||
$generator->setSkeletonDirs(__DIR__.'/../../Resources/skeleton');
|
||||
|
||||
return $generator;
|
||||
}
|
||||
|
||||
protected function getBundle()
|
||||
{
|
||||
$bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock();
|
||||
$bundle->expects($this->any())->method('getPath')->will($this->returnValue($this->tmpDir));
|
||||
$bundle->expects($this->any())->method('getName')->will($this->returnValue('FooBarBundle'));
|
||||
$bundle->expects($this->any())->method('getNamespace')->will($this->returnValue('Foo\BarBundle'));
|
||||
|
||||
return $bundle;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
<?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\Tests\Generator;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\ControllerGenerator;
|
||||
|
||||
class ControllerGeneratorTest extends GeneratorTest
|
||||
{
|
||||
public function testGenerateController()
|
||||
{
|
||||
$this->getGenerator()->generate($this->getBundle(), 'Welcome', 'annotation', 'twig');
|
||||
|
||||
$files = array(
|
||||
'Controller/WelcomeController.php',
|
||||
'Tests/Controller/WelcomeControllerTest.php',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/'.$file), sprintf('%s has been generated', $file));
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Controller/WelcomeController.php');
|
||||
$strings = array(
|
||||
'namespace Foo\\BarBundle\\Controller',
|
||||
'class WelcomeController',
|
||||
);
|
||||
foreach ($strings as $string) {
|
||||
$this->assertContains($string, $content);
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Tests/Controller/WelcomeControllerTest.php');
|
||||
$strings = array(
|
||||
'namespace Foo\\BarBundle\\Tests\\Controller',
|
||||
'class WelcomeControllerTest',
|
||||
);
|
||||
foreach ($strings as $string) {
|
||||
$this->assertContains($string, $content);
|
||||
}
|
||||
}
|
||||
|
||||
public function testGenerateActions()
|
||||
{
|
||||
$generator = $this->getGenerator();
|
||||
$actions = array(
|
||||
0 => array(
|
||||
'name' => 'showPageAction',
|
||||
'route' => '/{id}/{slug}',
|
||||
'placeholders' => array('id', 'slug'),
|
||||
'template' => 'FooBarBundle:Page:show_page.html.twig',
|
||||
),
|
||||
1 => array(
|
||||
'name' => 'getListOfPagesAction',
|
||||
'route' => '/_get-pages/{max_count}',
|
||||
'placeholders' => array('max_count'),
|
||||
'template' => 'FooBarBundle:Page:pages_list.html.twig',
|
||||
),
|
||||
);
|
||||
|
||||
$generator->generate($this->getBundle(), 'Page', 'annotation', 'twig', $actions);
|
||||
|
||||
$files = array(
|
||||
'Resources/views/Page/show_page.html.twig',
|
||||
'Resources/views/Page/pages_list.html.twig',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/'.$file), sprintf('%s has been generated', $file));
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Controller/PageController.php');
|
||||
$strings = array(
|
||||
'public function showPageAction($id, $slug)',
|
||||
'public function getListOfPagesAction($max_count)',
|
||||
'return $this->render(\'FooBarBundle:Page:show_page.html.twig\', array(',
|
||||
'return $this->render(\'FooBarBundle:Page:pages_list.html.twig\', array(',
|
||||
);
|
||||
foreach ($strings as $string) {
|
||||
$this->assertContains($string, $content);
|
||||
}
|
||||
}
|
||||
|
||||
public function testGenerateActionsWithNonDefaultFormats()
|
||||
{
|
||||
$generator = $this->getGenerator();
|
||||
|
||||
$generator->generate($this->getBundle(), 'Page', 'yml', 'php', array(
|
||||
1 => array(
|
||||
'name' => 'showPageAction',
|
||||
'route' => '/{slug}',
|
||||
'placeholders' => array('slug'),
|
||||
'template' => 'FooBarBundle:Page:showPage.html.php',
|
||||
),
|
||||
));
|
||||
|
||||
$files = array(
|
||||
'Resources/views/Page/showPage.html.php',
|
||||
'Resources/config/routing.yml',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/'.$file), $file.' has been generated');
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Controller/PageController.php');
|
||||
$this->assertNotContains('@Route()', $content, 'Routing is done via a yml file');
|
||||
|
||||
$this->assertContains("return \$this->render('FooBarBundle:Page:showPage.html.php', array(", $content, 'Controller renders template');
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Resources/views/Page/showPage.html.php');
|
||||
$this->assertContains($this->getBundle()->getName().':Page:showPage', $content);
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Resources/config/routing.yml');
|
||||
$this->assertContains("show_page:\n path: /{slug}\n defaults: { _controller: FooBarBundle:Page:showPage }", $content);
|
||||
}
|
||||
|
||||
protected function getGenerator()
|
||||
{
|
||||
$generator = new ControllerGenerator($this->filesystem);
|
||||
$generator->setSkeletonDirs(__DIR__.'/../../Resources/skeleton');
|
||||
|
||||
return $generator;
|
||||
}
|
||||
|
||||
protected function getBundle()
|
||||
{
|
||||
$bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock();
|
||||
$bundle->expects($this->any())->method('getPath')->will($this->returnValue($this->tmpDir));
|
||||
$bundle->expects($this->any())->method('getName')->will($this->returnValue('FooBarBundle'));
|
||||
$bundle->expects($this->any())->method('getNamespace')->will($this->returnValue('Foo\BarBundle'));
|
||||
|
||||
return $bundle;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,287 @@
|
|||
<?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\Tests\Generator;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGenerator;
|
||||
|
||||
class DoctrineCrudGeneratorTest extends GeneratorTest
|
||||
{
|
||||
public function testGenerateYamlFull()
|
||||
{
|
||||
$this->getGenerator()->generate($this->getBundle(), 'Post', $this->getMetadata(), 'yml', '/post', true, true);
|
||||
|
||||
$files = array(
|
||||
'Controller/PostController.php',
|
||||
'Tests/Controller/PostControllerTest.php',
|
||||
'Resources/config/routing/post.yml',
|
||||
'Resources/views/post/index.html.twig',
|
||||
'Resources/views/post/show.html.twig',
|
||||
'Resources/views/post/new.html.twig',
|
||||
'Resources/views/post/edit.html.twig',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/'.$file), sprintf('%s has been generated', $file));
|
||||
}
|
||||
|
||||
$files = array(
|
||||
'Resources/config/routing/post.xml',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertFalse(file_exists($this->tmpDir.'/'.$file), sprintf('%s has not been generated', $file));
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Controller/PostController.php');
|
||||
$strings = array(
|
||||
'namespace Foo\BarBundle\Controller;',
|
||||
'public function indexAction',
|
||||
'public function showAction',
|
||||
'public function newAction',
|
||||
'public function editAction',
|
||||
);
|
||||
foreach ($strings as $string) {
|
||||
$this->assertContains($string, $content);
|
||||
}
|
||||
}
|
||||
|
||||
public function testGenerateXml()
|
||||
{
|
||||
$this->getGenerator()->generate($this->getBundle(), 'Post', $this->getMetadata(), 'xml', '/post', false, true);
|
||||
|
||||
$files = array(
|
||||
'Controller/PostController.php',
|
||||
'Tests/Controller/PostControllerTest.php',
|
||||
'Resources/config/routing/post.xml',
|
||||
'Resources/views/post/index.html.twig',
|
||||
'Resources/views/post/show.html.twig',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/'.$file), sprintf('%s has been generated', $file));
|
||||
}
|
||||
|
||||
$files = array(
|
||||
'Resources/config/routing/post.yml',
|
||||
'Resources/views/post/new.html.twig',
|
||||
'Resources/views/post/edit.html.twig',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertFalse(file_exists($this->tmpDir.'/'.$file), sprintf('%s has not been generated', $file));
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Controller/PostController.php');
|
||||
$strings = array(
|
||||
'namespace Foo\BarBundle\Controller;',
|
||||
'public function indexAction',
|
||||
'public function showAction',
|
||||
);
|
||||
foreach ($strings as $string) {
|
||||
$this->assertContains($string, $content);
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Controller/PostController.php');
|
||||
$strings = array(
|
||||
'public function newAction',
|
||||
'public function editAction',
|
||||
'@Route',
|
||||
);
|
||||
foreach ($strings as $string) {
|
||||
$this->assertNotContains($string, $content);
|
||||
}
|
||||
}
|
||||
|
||||
public function testGenerateAnnotationWrite()
|
||||
{
|
||||
$this->getGenerator()->generate($this->getBundle(), 'Post', $this->getMetadata(), 'annotation', '/post', true, true);
|
||||
|
||||
$files = array(
|
||||
'Controller/PostController.php',
|
||||
'Tests/Controller/PostControllerTest.php',
|
||||
'Resources/views/post/index.html.twig',
|
||||
'Resources/views/post/show.html.twig',
|
||||
'Resources/views/post/new.html.twig',
|
||||
'Resources/views/post/edit.html.twig',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/'.$file), sprintf('%s has been generated', $file));
|
||||
}
|
||||
|
||||
$files = array(
|
||||
'Resources/config/routing/post.yml',
|
||||
'Resources/config/routing/post.xml',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertFalse(file_exists($this->tmpDir.'/'.$file), sprintf('%s has not been generated', $file));
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Controller/PostController.php');
|
||||
$strings = array(
|
||||
'namespace Foo\BarBundle\Controller;',
|
||||
'public function indexAction',
|
||||
'public function showAction',
|
||||
'public function newAction',
|
||||
'public function editAction',
|
||||
'@Route',
|
||||
);
|
||||
foreach ($strings as $string) {
|
||||
$this->assertContains($string, $content);
|
||||
}
|
||||
}
|
||||
|
||||
public function testGenerateAnnotation()
|
||||
{
|
||||
$this->getGenerator()->generate($this->getBundle(), 'Post', $this->getMetadata(), 'annotation', '/post', false, true);
|
||||
|
||||
$files = array(
|
||||
'Controller/PostController.php',
|
||||
'Tests/Controller/PostControllerTest.php',
|
||||
'Resources/views/post/index.html.twig',
|
||||
'Resources/views/post/show.html.twig',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/'.$file), sprintf('%s has been generated', $file));
|
||||
}
|
||||
|
||||
$files = array(
|
||||
'Resources/config/routing/post.yml',
|
||||
'Resources/config/routing/post.xml',
|
||||
'Resources/views/post/new.html.twig',
|
||||
'Resources/views/post/edit.html.twig',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertFalse(file_exists($this->tmpDir.'/'.$file), sprintf('%s has not been generated', $file));
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Controller/PostController.php');
|
||||
$strings = array(
|
||||
'namespace Foo\BarBundle\Controller;',
|
||||
'public function indexAction',
|
||||
'public function showAction',
|
||||
'@Route("/post")', // Controller level
|
||||
'@Route("/", name="post_index")',
|
||||
'@Route("/{id}", name="post_show")',
|
||||
);
|
||||
foreach ($strings as $string) {
|
||||
$this->assertContains($string, $content);
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Controller/PostController.php');
|
||||
$strings = array(
|
||||
'public function newAction',
|
||||
'public function editAction',
|
||||
);
|
||||
foreach ($strings as $string) {
|
||||
$this->assertNotContains($string, $content);
|
||||
}
|
||||
}
|
||||
|
||||
public function testGenerateNamespacedEntity()
|
||||
{
|
||||
$this->getGenerator()->generate($this->getBundle(), 'Blog\Post', $this->getMetadata(), 'annotation', '/blog_post', true, true);
|
||||
|
||||
$files = array(
|
||||
'Controller/Blog/PostController.php',
|
||||
'Tests/Controller/Blog/PostControllerTest.php',
|
||||
'Resources/views/blog/post/index.html.twig',
|
||||
'Resources/views/blog/post/show.html.twig',
|
||||
'Resources/views/blog/post/new.html.twig',
|
||||
'Resources/views/blog/post/edit.html.twig',
|
||||
);
|
||||
foreach ($files as $file) {
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/'.$file), sprintf('%s has been generated', $file));
|
||||
}
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Controller/Blog/PostController.php');
|
||||
$strings = array(
|
||||
'namespace Foo\BarBundle\Controller\Blog;',
|
||||
'@Route("/blog_post")', // Controller level
|
||||
'@Route("/", name="blog_post_index")',
|
||||
'@Route("/{id}", name="blog_post_show")',
|
||||
'@Route("/new", name="blog_post_new")',
|
||||
'@Route("/{id}/edit", name="blog_post_edit")',
|
||||
'@Route("/{id}", name="blog_post_delete")',
|
||||
'public function showAction(Post $post)',
|
||||
'\'post\' => $post,',
|
||||
'\'posts\' => $posts,',
|
||||
);
|
||||
if (method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')) {
|
||||
// Symfony >= 2.8
|
||||
$strings[] = '$form = $this->createForm(\'Foo\BarBundle\Form\Blog\PostType\', $post);';
|
||||
$strings[] = '$editForm = $this->createForm(\'Foo\BarBundle\Form\Blog\PostType\', $post);';
|
||||
} else {
|
||||
$strings[] = '$form = $this->createForm(new PostType(), $post);';
|
||||
$strings[] = '$editForm = $this->createForm(new PostType(), $post);';
|
||||
}
|
||||
foreach ($strings as $string) {
|
||||
$this->assertContains($string, $content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getRoutePrefixes
|
||||
*/
|
||||
public function testGetRouteNamePrefix($original, $expected)
|
||||
{
|
||||
$prefix = DoctrineCrudGenerator::getRouteNamePrefix($original);
|
||||
|
||||
$this->assertEquals($expected, $prefix);
|
||||
}
|
||||
|
||||
public function getRoutePrefixes()
|
||||
{
|
||||
return array(
|
||||
array('', ''),
|
||||
array('/', ''),
|
||||
array('//', ''),
|
||||
array('/{foo}', ''),
|
||||
array('/{_foo}', ''),
|
||||
array('/{/foo}', ''),
|
||||
array('/{/foo/}', ''),
|
||||
array('/{_locale}', ''),
|
||||
array('/{_locale}/foo', 'foo'),
|
||||
array('/{_locale}/foo/', 'foo'),
|
||||
array('/{_locale}/foo/{_format}', 'foo'),
|
||||
array('/{_locale}/foo/{_format}/', 'foo'),
|
||||
array('/{_locale}/foo/{_format}/bar', 'foo_bar'),
|
||||
array('/{_locale}/foo/{_format}/bar/', 'foo_bar'),
|
||||
array('/{_locale}/foo/{_format}/bar//', 'foo_bar'),
|
||||
array('/{foo}/foo/{bar}/bar', 'foo_bar'),
|
||||
array('/{foo}/foo/{bar}/bar/', 'foo_bar'),
|
||||
array('/{foo}/foo/{bar}/bar//', 'foo_bar'),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getGenerator()
|
||||
{
|
||||
$generator = new DoctrineCrudGenerator($this->filesystem, $this->tmpDir);
|
||||
$generator->setSkeletonDirs(__DIR__.'/../../Resources/skeleton');
|
||||
|
||||
return $generator;
|
||||
}
|
||||
|
||||
protected function getBundle()
|
||||
{
|
||||
$bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock();
|
||||
$bundle->expects($this->any())->method('getPath')->will($this->returnValue($this->tmpDir));
|
||||
$bundle->expects($this->any())->method('getName')->will($this->returnValue('FooBarBundle'));
|
||||
$bundle->expects($this->any())->method('getNamespace')->will($this->returnValue('Foo\BarBundle'));
|
||||
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
public function getMetadata()
|
||||
{
|
||||
$metadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadataInfo')->disableOriginalConstructor()->getMock();
|
||||
$metadata->identifier = array('id');
|
||||
$metadata->fieldMappings = array('title' => array('type' => 'string'));
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
<?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\Tests\Generator;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineEntityGenerator;
|
||||
|
||||
class DoctrineEntityGeneratorTest extends GeneratorTest
|
||||
{
|
||||
const FORMAT_XML = 'xml';
|
||||
const FORMAT_YAML = 'yml';
|
||||
const FORMAT_ANNOTATION = 'annotation';
|
||||
|
||||
const WITH_REPOSITORY = true;
|
||||
const WITHOUT_REPOSITORY = false;
|
||||
|
||||
public function testGenerateYaml()
|
||||
{
|
||||
$this->generate(self::FORMAT_YAML);
|
||||
|
||||
$files = array(
|
||||
'Entity/Foo.php',
|
||||
'Resources/config/doctrine/Foo.orm.yml',
|
||||
);
|
||||
|
||||
$this->assertFilesExists($files);
|
||||
$this->assertAttributesAndMethodsExists();
|
||||
}
|
||||
|
||||
public function testGenerateSubNamespacedYaml()
|
||||
{
|
||||
$this->generateSubNamespaced(self::FORMAT_YAML);
|
||||
|
||||
$files = array(
|
||||
'Entity/Sub/Foo.php',
|
||||
'Resources/config/doctrine/Sub.Foo.orm.yml',
|
||||
);
|
||||
|
||||
$this->assertFilesExists($files);
|
||||
$this->assertAttributesAndMethodsExists(array(), 'Sub/Foo');
|
||||
}
|
||||
|
||||
public function testGenerateXml()
|
||||
{
|
||||
$this->generate(self::FORMAT_XML);
|
||||
|
||||
$files = array(
|
||||
'Entity/Foo.php',
|
||||
'Resources/config/doctrine/Foo.orm.xml',
|
||||
);
|
||||
|
||||
$this->assertFilesExists($files);
|
||||
$this->assertAttributesAndMethodsExists();
|
||||
}
|
||||
|
||||
public function testGenerateSubNamespacedXml()
|
||||
{
|
||||
$this->generateSubNamespaced(self::FORMAT_XML);
|
||||
|
||||
$files = array(
|
||||
'Entity/Sub/Foo.php',
|
||||
'Resources/config/doctrine/Sub.Foo.orm.xml',
|
||||
);
|
||||
|
||||
$this->assertFilesExists($files);
|
||||
$this->assertAttributesAndMethodsExists(array(), 'Sub/Foo');
|
||||
}
|
||||
|
||||
public function testGenerateAnnotation()
|
||||
{
|
||||
$this->generate(self::FORMAT_ANNOTATION);
|
||||
|
||||
$files = array(
|
||||
'Entity/Foo.php',
|
||||
);
|
||||
|
||||
$annotations = array(
|
||||
'@ORM\Table(name="foo")',
|
||||
'@ORM\Column(name="bar"',
|
||||
'@ORM\Column(name="baz"',
|
||||
);
|
||||
|
||||
$this->assertFilesExists($files);
|
||||
$this->assertAttributesAndMethodsExists($annotations);
|
||||
}
|
||||
|
||||
public function testGenerateSubNamespacedAnnotation()
|
||||
{
|
||||
$this->generateSubNamespaced(self::FORMAT_ANNOTATION);
|
||||
|
||||
$files = array(
|
||||
'Entity/Sub/Foo.php',
|
||||
);
|
||||
|
||||
$annotations = array(
|
||||
'@ORM\Table(name="sub_foo")',
|
||||
'@ORM\Column(name="bar"',
|
||||
'@ORM\Column(name="baz"',
|
||||
);
|
||||
|
||||
$this->assertFilesExists($files);
|
||||
$this->assertAttributesAndMethodsExists($annotations, 'Sub/Foo');
|
||||
}
|
||||
|
||||
protected function assertFilesExists(array $files)
|
||||
{
|
||||
foreach ($files as $file) {
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/'.$file), sprintf('%s has been generated', $file));
|
||||
}
|
||||
}
|
||||
|
||||
protected function assertAttributesAndMethodsExists(array $otherStrings = array(), $entity = 'Foo')
|
||||
{
|
||||
$content = file_get_contents($this->tmpDir.'/Entity/'.$entity.'.php');
|
||||
|
||||
$strings = array(
|
||||
'namespace Foo\\BarBundle\\Entity',
|
||||
'class Foo',
|
||||
'private $id',
|
||||
'private $bar',
|
||||
'private $baz',
|
||||
'public function getId',
|
||||
'public function getBar',
|
||||
'public function getBaz',
|
||||
'public function setBar',
|
||||
'public function setBaz',
|
||||
);
|
||||
|
||||
$strings = array_merge($strings, $otherStrings);
|
||||
|
||||
foreach ($strings as $string) {
|
||||
$this->assertContains($string, $content);
|
||||
}
|
||||
}
|
||||
|
||||
protected function generate($format)
|
||||
{
|
||||
$this->getGenerator()->generate($this->getBundle(), 'Foo', $format, $this->getFields());
|
||||
}
|
||||
|
||||
protected function generateSubNamespaced($format)
|
||||
{
|
||||
$this->getGenerator()->generate($this->getBundle(), 'Sub\Foo', $format, $this->getFields());
|
||||
}
|
||||
|
||||
protected function getGenerator()
|
||||
{
|
||||
$generator = new DoctrineEntityGenerator($this->filesystem, $this->getRegistry());
|
||||
$generator->setSkeletonDirs(__DIR__.'/../../Resources/skeleton');
|
||||
|
||||
return $generator;
|
||||
}
|
||||
|
||||
protected function getBundle()
|
||||
{
|
||||
$bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock();
|
||||
$bundle->expects($this->any())->method('getPath')->will($this->returnValue($this->tmpDir));
|
||||
$bundle->expects($this->any())->method('getName')->will($this->returnValue('FooBarBundle'));
|
||||
$bundle->expects($this->any())->method('getNamespace')->will($this->returnValue('Foo\BarBundle'));
|
||||
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
protected function getFields()
|
||||
{
|
||||
return array(
|
||||
array('fieldName' => 'bar', 'type' => 'string', 'length' => 255),
|
||||
array('fieldName' => 'baz', 'type' => 'integer', 'length' => 11),
|
||||
);
|
||||
}
|
||||
|
||||
public function getRegistry()
|
||||
{
|
||||
$registry = $this->getMockBuilder('Symfony\Bridge\Doctrine\RegistryInterface')->getMock();
|
||||
$registry->expects($this->any())->method('getManager')->will($this->returnValue($this->getManager()));
|
||||
$registry->expects($this->any())->method('getAliasNamespace')->will($this->returnValue('Foo\\BarBundle\\Entity'));
|
||||
|
||||
return $registry;
|
||||
}
|
||||
|
||||
public function getManager()
|
||||
{
|
||||
$manager = $this->getMockBuilder('Doctrine\ORM\EntityManagerInterface')->getMock();
|
||||
$manager->expects($this->any())
|
||||
->method('getConfiguration')
|
||||
->will($this->returnValue($this->getConfiguration()));
|
||||
|
||||
return $manager;
|
||||
}
|
||||
|
||||
public function getConfiguration()
|
||||
{
|
||||
$config = $this->getMockBuilder('Doctrine\ORM\Configuration')->getMock();
|
||||
$config->expects($this->any())->method('getEntityNamespaces')->will($this->returnValue(array('Foo\\BarBundle')));
|
||||
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
<?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\Tests\Generator;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineFormGenerator;
|
||||
|
||||
class DoctrineFormGeneratorTest extends GeneratorTest
|
||||
{
|
||||
public function testGenerate()
|
||||
{
|
||||
$this->generateForm(false);
|
||||
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/Form/PostType.php'));
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Form/PostType.php');
|
||||
$this->assertContains('namespace Foo\BarBundle\Form', $content);
|
||||
$this->assertContains('class PostType extends AbstractType', $content);
|
||||
$this->assertContains('->add(\'title\')', $content);
|
||||
$this->assertContains('->add(\'createdAt\')', $content);
|
||||
$this->assertContains('->add(\'publishedAt\')', $content);
|
||||
$this->assertContains('->add(\'updatedAt\')', $content);
|
||||
$this->assertContains('public function configureOptions(OptionsResolver $resolver)', $content);
|
||||
$this->assertContains('\'data_class\' => \'Foo\BarBundle\Entity\Post\'', $content);
|
||||
}
|
||||
|
||||
public function testGenerateSubNamespacedEntity()
|
||||
{
|
||||
$this->generateSubNamespacedEntityForm(false);
|
||||
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/Form/Blog/PostType.php'));
|
||||
|
||||
$content = file_get_contents($this->tmpDir.'/Form/Blog/PostType.php');
|
||||
$this->assertContains('namespace Foo\BarBundle\Form\Blog', $content);
|
||||
$this->assertContains('class PostType extends AbstractType', $content);
|
||||
$this->assertContains('->add(\'title\')', $content);
|
||||
$this->assertContains('->add(\'createdAt\')', $content);
|
||||
$this->assertContains('->add(\'publishedAt\')', $content);
|
||||
$this->assertContains('->add(\'updatedAt\')', $content);
|
||||
$this->assertContains('public function configureOptions(OptionsResolver $resolver)', $content);
|
||||
$this->assertContains('\'data_class\' => \'Foo\BarBundle\Entity\Blog\Post\'', $content);
|
||||
$this->assertContains('public function getBlockPrefix()', $content);
|
||||
$this->assertContains('return \'foo_barbundle_blog_post\';', $content);
|
||||
if (method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')) {
|
||||
// Symfony >= 2.8
|
||||
$this->assertNotContains('public function getName()', $content);
|
||||
} else {
|
||||
// BC Symfony 2.7
|
||||
$this->assertContains('public function getName()', $content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessageRegExp: Unable to generate the PostType form class as it already exists under the .* file
|
||||
*/
|
||||
public function testNonOverwrittenForm()
|
||||
{
|
||||
$this->generateForm(false);
|
||||
$this->generateForm(false);
|
||||
}
|
||||
|
||||
public function testOverwrittenForm()
|
||||
{
|
||||
$this->generateForm(false);
|
||||
$this->generateForm(true);
|
||||
|
||||
$this->assertTrue(file_exists($this->tmpDir.'/Form/PostType.php'));
|
||||
}
|
||||
|
||||
private function generateForm($overwrite)
|
||||
{
|
||||
$generator = new DoctrineFormGenerator($this->filesystem);
|
||||
$generator->setSkeletonDirs(__DIR__.'/../../Resources/skeleton');
|
||||
|
||||
$bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock();
|
||||
$bundle->expects($this->any())->method('getPath')->will($this->returnValue($this->tmpDir));
|
||||
$bundle->expects($this->any())->method('getNamespace')->will($this->returnValue('Foo\BarBundle'));
|
||||
|
||||
$metadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadataInfo')->disableOriginalConstructor()->getMock();
|
||||
$metadata->identifier = array('id');
|
||||
$metadata->fieldMappings = array(
|
||||
'title' => array('type' => 'string'),
|
||||
'createdAt' => array('type' => 'date'),
|
||||
'publishedAt' => array('type' => 'time'),
|
||||
'updatedAt' => array('type' => 'datetime'),
|
||||
);
|
||||
$metadata->associationMappings = $metadata->fieldMappings;
|
||||
|
||||
$generator->generate($bundle, 'Post', $metadata, $overwrite);
|
||||
}
|
||||
|
||||
private function generateSubNamespacedEntityForm($overwrite)
|
||||
{
|
||||
$generator = new DoctrineFormGenerator($this->filesystem);
|
||||
$generator->setSkeletonDirs(__DIR__.'/../../Resources/skeleton');
|
||||
|
||||
$bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock();
|
||||
$bundle->expects($this->any())->method('getPath')->will($this->returnValue($this->tmpDir));
|
||||
$bundle->expects($this->any())->method('getNamespace')->will($this->returnValue('Foo\BarBundle'));
|
||||
|
||||
$metadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadataInfo')->disableOriginalConstructor()->getMock();
|
||||
$metadata->identifier = array('id');
|
||||
$metadata->fieldMappings = array(
|
||||
'title' => array('type' => 'string'),
|
||||
'createdAt' => array('type' => 'date'),
|
||||
'publishedAt' => array('type' => 'time'),
|
||||
'updatedAt' => array('type' => 'datetime'),
|
||||
);
|
||||
$metadata->associationMappings = $metadata->fieldMappings;
|
||||
|
||||
$generator->generate($bundle, 'Blog\Post', $metadata, $overwrite);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?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\Tests\Generator;
|
||||
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
abstract class GeneratorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $filesystem;
|
||||
protected $tmpDir;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->tmpDir = sys_get_temp_dir().'/sf';
|
||||
$this->filesystem = new Filesystem();
|
||||
$this->filesystem->remove($this->tmpDir);
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
$this->filesystem->remove($this->tmpDir);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
<?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\Tests\Generator;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Manipulator\ConfigurationManipulator;
|
||||
use Sensio\Bundle\GeneratorBundle\Model\Bundle;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
class ConfigurationManipulatorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $filesystem;
|
||||
protected $tmpDir;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->tmpDir = sys_get_temp_dir().'/sf';
|
||||
$this->filesystem = new Filesystem();
|
||||
$this->filesystem->remove($this->tmpDir);
|
||||
$this->filesystem->mkdir($this->tmpDir);
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
$this->filesystem->remove($this->tmpDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getAddResourcesTests
|
||||
*/
|
||||
public function testAddResource($bundleName, $format, $startingContents, $expectedContents)
|
||||
{
|
||||
$bundle = new Bundle('Acme', $bundleName, 'src', $format, true);
|
||||
|
||||
$configurationPath = $this->tmpDir.'/config.yml';
|
||||
file_put_contents($configurationPath, $startingContents);
|
||||
$manipulator = new ConfigurationManipulator($configurationPath);
|
||||
|
||||
$manipulator->addResource($bundle);
|
||||
$realContents = file_get_contents($configurationPath);
|
||||
$this->assertEquals($expectedContents, $realContents);
|
||||
}
|
||||
|
||||
public function getAddResourcesTests()
|
||||
{
|
||||
$tests = array();
|
||||
|
||||
// normal, .yml file
|
||||
$tests[] = array(
|
||||
'AppBundle',
|
||||
'yml',
|
||||
<<<EOF
|
||||
imports:
|
||||
- { resource: security.yml }
|
||||
- { resource: parameters.yml }
|
||||
- { resource: services.yml }
|
||||
framework:
|
||||
esi: { enabled: true }
|
||||
translator: { fallback: en }
|
||||
EOF
|
||||
, <<<EOF
|
||||
imports:
|
||||
- { resource: security.yml }
|
||||
- { resource: parameters.yml }
|
||||
- { resource: services.yml }
|
||||
- { resource: "@AppBundle/Resources/config/services.yml" }
|
||||
framework:
|
||||
esi: { enabled: true }
|
||||
translator: { fallback: en }
|
||||
EOF
|
||||
);
|
||||
|
||||
// normal, xml file
|
||||
$tests[] = array(
|
||||
'AppBundle',
|
||||
'xml',
|
||||
<<<EOF
|
||||
imports:
|
||||
- { resource: security.yml }
|
||||
- { resource: parameters.yml }
|
||||
- { resource: services.yml }
|
||||
framework:
|
||||
esi: { enabled: true }
|
||||
translator: { fallback: en }
|
||||
EOF
|
||||
, <<<EOF
|
||||
imports:
|
||||
- { resource: security.yml }
|
||||
- { resource: parameters.yml }
|
||||
- { resource: services.yml }
|
||||
- { resource: "@AppBundle/Resources/config/services.xml" }
|
||||
framework:
|
||||
esi: { enabled: true }
|
||||
translator: { fallback: en }
|
||||
EOF
|
||||
);
|
||||
|
||||
// imports further down
|
||||
$tests[] = array(
|
||||
'AppBundle',
|
||||
'yml',
|
||||
<<<EOF
|
||||
framework:
|
||||
esi: { enabled: true }
|
||||
translator: { fallback: en }
|
||||
|
||||
imports:
|
||||
- { resource: security.yml }
|
||||
- { resource: parameters.yml }
|
||||
- { resource: services.yml }
|
||||
|
||||
twig:
|
||||
debug: "%kernel.debug%"
|
||||
strict_variables: "%kernel.debug%"
|
||||
EOF
|
||||
, <<<EOF
|
||||
framework:
|
||||
esi: { enabled: true }
|
||||
translator: { fallback: en }
|
||||
|
||||
imports:
|
||||
- { resource: security.yml }
|
||||
- { resource: parameters.yml }
|
||||
- { resource: services.yml }
|
||||
- { resource: "@AppBundle/Resources/config/services.yml" }
|
||||
|
||||
twig:
|
||||
debug: "%kernel.debug%"
|
||||
strict_variables: "%kernel.debug%"
|
||||
EOF
|
||||
);
|
||||
|
||||
// extra line breaks in the imports list
|
||||
$tests[] = array(
|
||||
'AppBundle',
|
||||
'yml',
|
||||
<<<EOF
|
||||
imports:
|
||||
- { resource: security.yml }
|
||||
- { resource: parameters.yml }
|
||||
|
||||
- { resource: services.yml }
|
||||
|
||||
|
||||
framework:
|
||||
esi: { enabled: true }
|
||||
translator: { fallback: en }
|
||||
EOF
|
||||
, <<<EOF
|
||||
imports:
|
||||
- { resource: security.yml }
|
||||
- { resource: parameters.yml }
|
||||
|
||||
- { resource: services.yml }
|
||||
- { resource: "@AppBundle/Resources/config/services.yml" }
|
||||
|
||||
|
||||
framework:
|
||||
esi: { enabled: true }
|
||||
translator: { fallback: en }
|
||||
EOF
|
||||
);
|
||||
|
||||
return $tests;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
<?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\Tests\Manipulator;
|
||||
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\ProcessBuilder;
|
||||
use Symfony\Component\Process\PhpExecutableFinder;
|
||||
use Sensio\Bundle\GeneratorBundle\Tests\Generator\GeneratorTest;
|
||||
use Sensio\Bundle\GeneratorBundle\Manipulator\KernelManipulator;
|
||||
|
||||
class KernelManipulatorTest extends GeneratorTest
|
||||
{
|
||||
const STUB_BUNDLE_CLASS_NAME = 'Sensio\\Bundle\\GeneratorBundle\\Tests\\Manipulator\\Stubs\\StubBundle';
|
||||
const STUB_NAMESPACE = 'KernelManipulatorTest\\Stubs';
|
||||
|
||||
/**
|
||||
* @dataProvider kernelStubFilenamesProvider
|
||||
*
|
||||
* @param string $kernelOriginFilePath
|
||||
*/
|
||||
public function testAddToArray($kernelOriginFilePath)
|
||||
{
|
||||
if (defined('HHVM_VERSION')) {
|
||||
$this->markTestSkipped('Not supported in HHVM since it doesn\'t allow to lint PHP files.');
|
||||
}
|
||||
|
||||
$params = $this->prepareTestKernel($kernelOriginFilePath);
|
||||
|
||||
list($kernelClassName, $fullpath) = $params;
|
||||
$kernelClassName = self::STUB_NAMESPACE.'\\'.$kernelClassName;
|
||||
$this->registerClassLoader($kernelClassName, $fullpath);
|
||||
|
||||
$kernel = new $kernelClassName('test', true);
|
||||
$manipulator = new KernelManipulator($kernel);
|
||||
$manipulator->addBundle(self::STUB_BUNDLE_CLASS_NAME);
|
||||
|
||||
$phpFinder = new PhpExecutableFinder();
|
||||
$phpExecutable = $phpFinder->find();
|
||||
|
||||
$this->assertNotFalse($phpExecutable, 'Php executable binary found');
|
||||
|
||||
$arguments = array($phpExecutable, '-l', $fullpath);
|
||||
|
||||
// ProcessBuilder is deprecated in symfony/process version 3.4,
|
||||
// but Process doesn't accept an array of arguments in versions <3.3,
|
||||
// in which ProcessUtils::escapeArgument() is not marked as deprecated
|
||||
$useProcess = true;
|
||||
if (method_exists('Symfony\Component\Process\ProcessUtils', 'escapeArgument')) {
|
||||
$r = new \ReflectionMethod('Symfony\Component\Process\ProcessUtils', 'escapeArgument');
|
||||
if ($r->isPublic() && false === strpos($r->getDocComment(), '@deprecated')) {
|
||||
$useProcess = false;
|
||||
}
|
||||
}
|
||||
if ($useProcess) {
|
||||
$process = new Process($arguments);
|
||||
// preserve the BC with symfony <3.3
|
||||
$process->setCommandLine($process->getCommandLine());
|
||||
} else {
|
||||
$pb = new ProcessBuilder($arguments);
|
||||
$process = $pb->getProcess();
|
||||
}
|
||||
|
||||
$process->run();
|
||||
|
||||
$result = strpos($process->getOutput(), 'No syntax errors detected');
|
||||
$this->assertNotFalse($result, 'Manipulator should not provoke syntax errors');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function kernelStubFilenamesProvider()
|
||||
{
|
||||
$stubs = array(
|
||||
'With empty bundles array' => array(__DIR__.'/Stubs/EmptyBundlesKernelStub.php'),
|
||||
'With empty multiline bundles array' => array(__DIR__.'/Stubs/EmptyBundlesMultilineKernelStub.php'),
|
||||
'With bundles array contains comma' => array(__DIR__.'/Stubs/ContainsCommaKernelStub.php'),
|
||||
'With bundles added w/o trailing comma' => array(__DIR__.'/Stubs/ContainsBundlesKernelStub.php'),
|
||||
'With some extra code and bad formatted' => array(__DIR__.'/Stubs/ContainsExtraCodeKernelStub.php'),
|
||||
);
|
||||
|
||||
if (PHP_VERSION_ID >= 50400) {
|
||||
$stubs = array_merge($stubs, array(
|
||||
'With empty bundles array, short array syntax' => array(__DIR__.'/Stubs/EmptyBundlesShortArraySyntaxKernelStub.php'),
|
||||
'With empty multiline bundles array, short array syntax' => array(__DIR__.'/Stubs/EmptyBundlesMultilineShortArraySyntaxKernelStub.php'),
|
||||
'With bundles array contains comma, short array syntax' => array(__DIR__.'/Stubs/ContainsCommaShortArraySyntaxKernelStub.php'),
|
||||
'With bundles added w/o trailing comma, short array syntax' => array(__DIR__.'/Stubs/ContainsBundlesShortArraySyntaxKernelStub.php'),
|
||||
));
|
||||
}
|
||||
|
||||
return $stubs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies stub file to tmp.
|
||||
*
|
||||
* @param string $kernelOriginFilePath
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareTestKernel($kernelOriginFilePath)
|
||||
{
|
||||
$pathInfo = pathinfo($kernelOriginFilePath);
|
||||
$fileName = $pathInfo['basename'];
|
||||
$className = $pathInfo['filename'];
|
||||
|
||||
$targetDir = $this->tmpDir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, self::STUB_NAMESPACE);
|
||||
$this->filesystem->mkdir($targetDir);
|
||||
|
||||
$targetPath = $targetDir.DIRECTORY_SEPARATOR.$fileName;
|
||||
$this->filesystem->copy($kernelOriginFilePath, $targetPath, true);
|
||||
|
||||
return array($className, $targetPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the stubs namespace in the autoloader.
|
||||
*
|
||||
* @param string $kernelClassName
|
||||
* @param string $fullpath
|
||||
*/
|
||||
protected function registerClassLoader($kernelClassName, $fullpath)
|
||||
{
|
||||
spl_autoload_register(
|
||||
function ($class) use ($kernelClassName, $fullpath) {
|
||||
if ($class === $kernelClassName) {
|
||||
require $fullpath;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
<?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\Tests\Manipulator;
|
||||
|
||||
use Sensio\Bundle\GeneratorBundle\Manipulator\RoutingManipulator;
|
||||
|
||||
class RoutingManipulatorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getImportedResourceYamlKeys
|
||||
*/
|
||||
public function testGetImportedResourceYamlKey($bundleName, $prefix, $expectedKey)
|
||||
{
|
||||
$manipulator = new RoutingManipulator(__FILE__);
|
||||
$key = $manipulator->getImportedResourceYamlKey($bundleName, $prefix);
|
||||
|
||||
$this->assertEquals($expectedKey, $key);
|
||||
}
|
||||
|
||||
public function getImportedResourceYamlKeys()
|
||||
{
|
||||
return array(
|
||||
array('AppBundle', '', 'app'),
|
||||
array('AppBundle', '/', 'app'),
|
||||
array('AppBundle', '//', 'app'),
|
||||
array('AppBundle', '/{foo}', 'app'),
|
||||
array('AppBundle', '/{_foo}', 'app'),
|
||||
array('AppBundle', '/{/foo}', 'app'),
|
||||
array('AppBundle', '/{/foo/}', 'app'),
|
||||
array('AppBundle', '/{_locale}', 'app'),
|
||||
array('AppBundle', '/{_locale}/foo', 'app_foo'),
|
||||
array('AppBundle', '/{_locale}/foo/', 'app_foo'),
|
||||
array('AppBundle', '/{_locale}/foo/{_format}', 'app_foo'),
|
||||
array('AppBundle', '/{_locale}/foo/{_format}/', 'app_foo'),
|
||||
array('AppBundle', '/{_locale}/foo/{_format}/bar', 'app_foo_bar'),
|
||||
array('AppBundle', '/{_locale}/foo/{_format}/bar/', 'app_foo_bar'),
|
||||
array('AppBundle', '/{_locale}/foo/{_format}/bar//', 'app_foo_bar'),
|
||||
array('AcmeBlogBundle', '', 'acme_blog'),
|
||||
array('AcmeBlogBundle', '/', 'acme_blog'),
|
||||
array('AcmeBlogBundle', '//', 'acme_blog'),
|
||||
array('AcmeBlogBundle', '/{_locale}', 'acme_blog'),
|
||||
array('AcmeBlogBundle', '/{_locale}/foo', 'acme_blog_foo'),
|
||||
array('AcmeBlogBundle', '/{_locale}/foo/', 'acme_blog_foo'),
|
||||
array('AcmeBlogBundle', '/{_locale}/foo/{_format}', 'acme_blog_foo'),
|
||||
array('AcmeBlogBundle', '/{_locale}/foo/{_format}/', 'acme_blog_foo'),
|
||||
array('AcmeBlogBundle', '/{_locale}/foo/{_format}/bar', 'acme_blog_foo_bar'),
|
||||
array('AcmeBlogBundle', '/{_locale}/foo/{_format}/bar/', 'acme_blog_foo_bar'),
|
||||
array('AcmeBlogBundle', '/{_locale}/foo/{_format}/bar//', 'acme_blog_foo_bar'),
|
||||
);
|
||||
}
|
||||
|
||||
public function testHasResourceInAnnotation()
|
||||
{
|
||||
$tmpDir = sys_get_temp_dir().'/sf';
|
||||
@mkdir($tmpDir, 0777, true);
|
||||
$file = tempnam($tmpDir, 'routing');
|
||||
|
||||
$routing = <<<DATA
|
||||
acme_demo:
|
||||
resource: "@AcmeDemoBundle/Controller/"
|
||||
type: annotation
|
||||
DATA;
|
||||
|
||||
file_put_contents($file, $routing);
|
||||
|
||||
$manipulator = new RoutingManipulator($file);
|
||||
$this->assertTrue($manipulator->hasResourceInAnnotation('AcmeDemoBundle'));
|
||||
}
|
||||
|
||||
public function testHasResourceInAnnotationReturnFalseIfOnlyOneControllerDefined()
|
||||
{
|
||||
$tmpDir = sys_get_temp_dir().'/sf';
|
||||
@mkdir($tmpDir, 0777, true);
|
||||
$file = tempnam($tmpDir, 'routing');
|
||||
|
||||
$routing = <<<DATA
|
||||
acme_demo_post:
|
||||
resource: "@AcmeDemoBundle/Controller/PostController.php"
|
||||
type: annotation
|
||||
DATA;
|
||||
|
||||
file_put_contents($file, $routing);
|
||||
|
||||
$manipulator = new RoutingManipulator($file);
|
||||
$this->assertFalse($manipulator->hasResourceInAnnotation('AcmeDemoBundle'));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?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 KernelManipulatorTest\Stubs;
|
||||
|
||||
use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest;
|
||||
use Sensio\Bundle\GeneratorBundle\Tests\Manipulator\Stubs\StubBundle;
|
||||
|
||||
class ContainsBundlesKernelStub extends KernelForTest
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
$bundles = array(
|
||||
new StubBundle(),
|
||||
new StubBundle(),
|
||||
new StubBundle(),
|
||||
);
|
||||
|
||||
return $bundles;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?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 KernelManipulatorTest\Stubs;
|
||||
|
||||
use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest;
|
||||
use Sensio\Bundle\GeneratorBundle\Tests\Manipulator\Stubs\StubBundle;
|
||||
|
||||
class ContainsBundlesShortArraySyntaxKernelStub extends KernelForTest
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
$bundles = [
|
||||
new StubBundle(),
|
||||
new StubBundle(),
|
||||
new StubBundle(),
|
||||
];
|
||||
|
||||
return $bundles;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?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 KernelManipulatorTest\Stubs;
|
||||
|
||||
use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest;
|
||||
use Sensio\Bundle\GeneratorBundle\Tests\Manipulator\Stubs\StubBundle;
|
||||
|
||||
class ContainsCommaKernelStub extends KernelForTest
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
$bundles = array(
|
||||
new StubBundle(),
|
||||
);
|
||||
|
||||
return $bundles;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?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 KernelManipulatorTest\Stubs;
|
||||
|
||||
use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest;
|
||||
use Sensio\Bundle\GeneratorBundle\Tests\Manipulator\Stubs\StubBundle;
|
||||
|
||||
class ContainsCommaShortArraySyntaxKernelStub extends KernelForTest
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
$bundles = [
|
||||
new StubBundle(),
|
||||
];
|
||||
|
||||
return $bundles;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?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 KernelManipulatorTest\Stubs;
|
||||
|
||||
use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest;
|
||||
use Sensio\Bundle\GeneratorBundle\Tests\Manipulator\Stubs\StubBundle;
|
||||
|
||||
class ContainsExtraCodeKernelStub extends KernelForTest
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
$someVariable = false;
|
||||
|
||||
// some bad formatted definition
|
||||
$bundles = array(
|
||||
new StubBundle(),
|
||||
|
||||
new StubBundle(),
|
||||
|
||||
);
|
||||
|
||||
if (!$someVariable && in_array($this->getEnvironment(), array('dev', 'test'))) {
|
||||
$bundles[] = new StubBundle();
|
||||
}
|
||||
|
||||
return $bundles;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?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 KernelManipulatorTest\Stubs;
|
||||
|
||||
use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest;
|
||||
use Sensio\Bundle\GeneratorBundle\Tests\Manipulator\Stubs\StubBundle;
|
||||
|
||||
class ContainsExtraCodeShortArraySyntaxKernelStub extends KernelForTest
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
$someVariable = false;
|
||||
|
||||
// some bad formatted definition
|
||||
$bundles = [
|
||||
new StubBundle(),
|
||||
|
||||
new StubBundle(),
|
||||
|
||||
];
|
||||
|
||||
if (!$someVariable && in_array($this->getEnvironment(), array('dev', 'test'))) {
|
||||
$bundles[] = new StubBundle();
|
||||
}
|
||||
|
||||
return $bundles;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?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 KernelManipulatorTest\Stubs;
|
||||
|
||||
use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest;
|
||||
|
||||
class EmptyBundlesKernelStub extends KernelForTest
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
$bundles = array();
|
||||
|
||||
return $bundles;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?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 KernelManipulatorTest\Stubs;
|
||||
|
||||
use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest;
|
||||
|
||||
class EmptyBundlesMultilineKernelStub extends KernelForTest
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
$bundles = array(
|
||||
|
||||
);
|
||||
|
||||
return $bundles;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?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 KernelManipulatorTest\Stubs;
|
||||
|
||||
use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest;
|
||||
|
||||
class EmptyBundlesMultilineShortArraySyntaxKernelStub extends KernelForTest
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
$bundles = [
|
||||
|
||||
];
|
||||
|
||||
return $bundles;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?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 KernelManipulatorTest\Stubs;
|
||||
|
||||
use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest;
|
||||
|
||||
class EmptyBundlesShortArraySyntaxKernelStub extends KernelForTest
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
$bundles = [];
|
||||
|
||||
return $bundles;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?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\Tests\Manipulator\Stubs;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
class StubBundle extends Bundle
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?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 KernelManipulatorTest\Stubs;
|
||||
|
||||
use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest;
|
||||
use Sensio\Bundle\GeneratorBundle\Tests\Manipulator\Stubs\StubBundle;
|
||||
|
||||
class UsingShortArraySyntaxKernelStub extends KernelForTest
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
// short array syntax
|
||||
$bundles = [
|
||||
new StubBundle(),
|
||||
new StubBundle(),
|
||||
];
|
||||
|
||||
if (!$someVariable && in_array($this->getEnvironment(), array('dev', 'test'))) {
|
||||
$bundles[] = new StubBundle();
|
||||
}
|
||||
|
||||
return $bundles;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue