diff --git a/Command/AbstractCommand.php b/Command/AbstractCommand.php index d9cda03..d151975 100644 --- a/Command/AbstractCommand.php +++ b/Command/AbstractCommand.php @@ -322,11 +322,11 @@ EOT; $fs = new Filesystem(); $buildProperties = $this->getContainer()->getParameter('propel.build_properties'); + $iniFile = $kernel->getRootDir().'/config/propel.ini'; - $inifile = $kernel->getRootDir().'/config/propel.ini'; - if (file_exists($inifile)) { + if ($fs->exists($iniFile)) { $buildProperties = array_merge( - parse_ini_file($inifile), + parse_ini_file($iniFile), $buildProperties ); } diff --git a/Command/FormGenerateCommand.php b/Command/FormGenerateCommand.php new file mode 100644 index 0000000..55b6d0a --- /dev/null +++ b/Command/FormGenerateCommand.php @@ -0,0 +1,236 @@ + + */ +class FormGenerateCommand extends AbstractCommand +{ + const DEFAULT_FORM_TYPE_DIRECTORY = '/Form/Type'; + + /** + * @see Command + */ + protected function configure() + { + parent::configure(); + + $this + ->setName('propel:form:generate') + ->setDescription('Generate Form types stubs based on the schema.xml') + + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Overwrite existing Form types') + ->addArgument('bundle', InputArgument::REQUIRED, 'The bundle to use to generate Form types') + ->addArgument('models', InputArgument::IS_ARRAY, 'Model classes to generate Form Types from') + + ->setHelp(<<%command.name% command allows you to quickly generate Form Type stubs for a given bundle. + +php app/console %command.full_name% + +The --force parameter allows you to overwrite existing files. +EOT + ); + } + + /** + * @see Command + * + * @throws \InvalidArgumentException When the target directory does not exist + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $kernel = $this->getApplication()->getKernel(); + $models = $input->getArgument('models'); + $force = $input->getOption('force'); + + $this->setupBuildTimeFiles(); + + if (!($schemas = $this->getFinalSchemas($kernel, $this->bundle))) { + $output->writeln(sprintf('No *schemas.xml files found in bundle %s.', $this->bundle->getName())); + return; + } + + $manager = $this->getModelManager($input, $schemas); + + foreach ($manager->getDataModels() as $dataModel) { + foreach ($dataModel->getDatabases() as $database) { + $this->createFormTypeFromDatabase($this->bundle, $database, $models, $output, $force); + } + } + } + + protected function createFormTypeFromDatabase(BundleInterface $bundle, Database $database, $models, OutputInterface $output, $force = false) + { + $dir = $this->createDirectory($bundle, $output); + + foreach ($database->getTables() as $table) { + if (0 < count($models) && !in_array($table->getPhpName(), $models)) { + continue; + } + + $file = new \SplFileInfo(sprintf('%s/%sType.php', $dir, $table->getPhpName())); + + if (!file_exists($file) || true === $force) { + $this->writeFormType($bundle, $table, $file, $force, $output); + } else { + $output->writeln(sprintf('File %-60s exists, skipped. Try the --force option.', $this->getRelativeFileName($file))); + } + } + } + + protected function createDirectory(BundleInterface $bundle, OutputInterface $output) + { + $fs = new Filesystem(); + + if (!$fs->exists($dir = $bundle->getPath() . self::DEFAULT_FORM_TYPE_DIRECTORY)) { + $fs->mkdir($dir); + $this->writeNewDirectory($output, $dir); + } + + return $dir; + } + + protected function writeFormType(BundleInterface $bundle, Table $table, \SplFileInfo $file, $force, OutputInterface $output) + { + $modelName = $table->getPhpName(); + $formTypeContent = file_get_contents(__DIR__ . '/../Resources/skeleton/FormType.php'); + + $formTypeContent = str_replace('##NAMESPACE##', $bundle->getNamespace() . str_replace('/', '\\', self::DEFAULT_FORM_TYPE_DIRECTORY), $formTypeContent); + $formTypeContent = str_replace('##CLASS##', $modelName . 'Type', $formTypeContent); + $formTypeContent = str_replace('##FQCN##', sprintf('%s\%s', $table->getNamespace(), $modelName), $formTypeContent); + $formTypeContent = str_replace('##TYPE_NAME##', strtolower($modelName), $formTypeContent); + $formTypeContent = $this->addFields($table, $formTypeContent); + + file_put_contents($file->getPathName(), $formTypeContent); + $this->writeNewFile($output, $this->getRelativeFileName($file) . ($force ? ' (forced)' : '')); + } + + protected function addFields(Table $table, $formTypeContent) + { + $buildCode = ''; + foreach ($table->getColumns() as $column) { + if (!$column->isPrimaryKey()) { + $buildCode .= sprintf("\n \$builder->add('%s');", lcfirst($column->getPhpName())); + } + } + + return str_replace('##BUILD_CODE##', $buildCode, $formTypeContent); + } + + /** + * {@inheritdoc} + */ + protected function createSubCommandInstance() + { + // useless here + } + + /** + * {@inheritdoc} + */ + protected function getSubCommandArguments(InputInterface $input) + { + // useless here + } + + protected function getDatabasesFromSchema(\SplFileInfo $file) + { + $databaseXml = simplexml_load_file($file); + $databaseName = (string) $databaseXml['name']; + + if (empty($databaseName)) { + throw new \RuntimeException(sprintf('Impossible to determine database name for schema "%s". Please define the "name" attribute', $file->getRealPath())); + } + + $serviceContainer = Propel::getServiceContainer(); + return $serviceContainer->getDatabaseMap($databaseName); + } + + /** + * @param \SplFileInfo $file + * @return string + */ + protected function getRelativeFileName(\SplFileInfo $file) + { + return substr(str_replace(realpath($this->getContainer()->getParameter('kernel.root_dir') . '/../'), '', $file), 1); + } + + protected function getGeneratorConfig(InputInterface $input) + { + $generatorConfig = array( + 'propel.platform.class' => $input->getOption('platform'), + 'propel.builder.object.class' => ModelBuildCommand::DEFAULT_OBJECT_BUILDER, + 'propel.builder.objectstub.class' => ModelBuildCommand::DEFAULT_OBJECT_STUB_BUILDER, + 'propel.builder.objectmultiextend.class' => ModelBuildCommand::DEFAULT_MULTIEXTEND_OBJECT_BUILDER, + 'propel.builder.query.class' => ModelBuildCommand::DEFAULT_QUERY_BUILDER, + 'propel.builder.querystub.class' => ModelBuildCommand::DEFAULT_QUERY_STUB_BUILDER, + 'propel.builder.queryinheritance.class' => ModelBuildCommand::DEFAULT_QUERY_INHERITANCE_BUILDER, + 'propel.builder.queryinheritancestub.class' => ModelBuildCommand::DEFAULT_QUERY_INHERITANCE_STUB_BUILDER, + 'propel.builder.tablemap.class' => ModelBuildCommand::DEFAULT_TABLEMAP_BUILDER, + 'propel.builder.pluralizer.class' => ModelBuildCommand::DEFAULT_PLURALIZER, + 'propel.disableIdentifierQuoting' => !false, + 'propel.packageObjectModel' => true, + 'propel.namespace.autoPackage' => !false, + 'propel.addGenericAccessors' => true, + 'propel.addGenericMutators' => true, + 'propel.addSaveMethod' => true, + 'propel.addTimeStamp' => false, + 'propel.addValidateMethod' => true, + 'propel.addHooks' => true, + 'propel.namespace.map' => 'Map', + 'propel.useLeftJoinsInDoJoinMethods' => true, + 'propel.emulateForeignKeyConstraints' => false, + 'propel.schema.autoPrefix' => false, + 'propel.dateTimeClass' => '\DateTime', + // MySQL specific + 'propel.mysql.tableType' => ModelBuildCommand::DEFAULT_MYSQL_ENGINE, + 'propel.mysql.tableEngineKeyword' => 'ENGINE', + ); + + // merge the custom build properties + $buildProperties = parse_ini_file($this->getCacheDir().'/build.properties'); + $generatorConfig = array_merge($generatorConfig, $buildProperties); + + return new GeneratorConfig($generatorConfig); + } + + protected function getModelManager(InputInterface $input, array $schemas) + { + $schemaFiles = array(); + foreach ($schemas as $data) { + $schemaFiles[] = $data[1]; + } + + $manager = new ModelManager(); + $manager->setFilesystem(new Filesystem()); + $manager->setGeneratorConfig($this->getGeneratorConfig($input)); + $manager->setSchemas($schemaFiles); + + return $manager; + } +} diff --git a/Form/BaseAbstractType.php b/Form/BaseAbstractType.php new file mode 100644 index 0000000..41d48f7 --- /dev/null +++ b/Form/BaseAbstractType.php @@ -0,0 +1,61 @@ + '', + ); + + public function __construct($mergeOptions = null) + { + if ($mergeOptions) { + $this->mergeOptions($mergeOptions); + } + } + + public function setOption($name, $value) + { + $this->options[$name] = $value; + } + + public function getOption($name) + { + return $this->options[$name]; + } + + public function setOptions($options) + { + $this->options = $options; + } + + public function getOptions() + { + return $this->options; + } + + public function mergeOptions($options) + { + $this->options = array_merge($this->options, $options); + } + + /** + * {@inheritdoc} + */ + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + $resolver->setDefaults($this->options); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->getOption('name'); + } +} diff --git a/Resources/skeleton/FormType.php b/Resources/skeleton/FormType.php new file mode 100644 index 0000000..a4cbbe3 --- /dev/null +++ b/Resources/skeleton/FormType.php @@ -0,0 +1,21 @@ + '##FQCN##', + 'name' => '##TYPE_NAME##', + ); + + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + {##BUILD_CODE## + } +}