diff --git a/Builder/Propel2/ActionsBuilderAction.php b/Builder/Propel2/ActionsBuilderAction.php new file mode 100644 index 00000000..acc74516 --- /dev/null +++ b/Builder/Propel2/ActionsBuilderAction.php @@ -0,0 +1,13 @@ + + */ +class ActionsBuilderAction extends AdminActionsBuilderAction +{ +} diff --git a/Builder/Propel2/ActionsBuilderTemplate.php b/Builder/Propel2/ActionsBuilderTemplate.php new file mode 100644 index 00000000..f42ca452 --- /dev/null +++ b/Builder/Propel2/ActionsBuilderTemplate.php @@ -0,0 +1,13 @@ + + */ +class ActionsBuilderTemplate extends AdminActionsBuilderTemplate +{ +} diff --git a/Builder/Propel2/EditBuilderAction.php b/Builder/Propel2/EditBuilderAction.php new file mode 100644 index 00000000..caf344de --- /dev/null +++ b/Builder/Propel2/EditBuilderAction.php @@ -0,0 +1,13 @@ +container->get('propel.configuration')); - \Propel::initialize(); + if (class_exists('Propel')) { // Propel 1 + if (!\Propel::isInit()) { + \Propel::setConfiguration($this->container->get('propel.configuration')); + \Propel::initialize(); + } + + return; } } } diff --git a/DependencyInjection/AdmingeneratorGeneratorExtension.php b/DependencyInjection/AdmingeneratorGeneratorExtension.php index 0c7a1194..eb0fa6e6 100644 --- a/DependencyInjection/AdmingeneratorGeneratorExtension.php +++ b/DependencyInjection/AdmingeneratorGeneratorExtension.php @@ -76,7 +76,7 @@ public function load(array $configs, ContainerBuilder $container) if ($config['use_jms_security']) { $container->getDefinition('twig.extension.admingenerator.security')->addArgument(true); $container->getDefinition('twig.extension.admingenerator.echo')->addArgument(true); - } + } $this->registerGeneratedFormsAsServices($container); $this->processModelManagerConfiguration($config, $container); @@ -91,7 +91,7 @@ public function load(array $configs, ContainerBuilder $container) */ private function processModelManagerConfiguration(array $config, ContainerBuilder $container) { - if (!($config['use_doctrine_orm'] || $config['use_doctrine_odm'] || $config['use_propel'])) { + if (!($config['use_doctrine_orm'] || $config['use_doctrine_odm'] || $config['use_propel'] || $config['use_propel2'])) { throw new ModelManagerNotSelectedException(); } @@ -105,6 +105,7 @@ private function processModelManagerConfiguration(array $config, ContainerBuilde $doctrineOrmTemplatesDirs[] = $dir . DIRECTORY_SEPARATOR . 'Doctrine'; $doctrineOdmTemplatesDirs[] = $dir . DIRECTORY_SEPARATOR . 'DoctrineODM'; $propelTemplatesDirs[] = $dir . DIRECTORY_SEPARATOR . 'Propel'; + $propel2TemplatesDirs[] = $dir . DIRECTORY_SEPARATOR . 'Propel2'; } if ($config['use_doctrine_orm']) { @@ -155,6 +156,23 @@ private function processModelManagerConfiguration(array $config, ContainerBuilde ->addArgument($config['guess_required']) ->addArgument($config['default_required']); } + + + if ($config['use_propel2']) { + $loader->load('propel2.xml'); + $this->addTemplatesInitialization($container->getDefinition('admingenerator.generator.propel2'), $propel2TemplatesDirs); + if ($config['overwrite_if_exists']) { + $container + ->getDefinition('admingenerator.generator.propel2') + ->addMethodCall('forceOverwriteIfExists'); + } + + $container->getDefinition('admingenerator.fieldguesser.propel2') + ->addArgument($config['form_types']['propel2']) + ->addArgument($config['filter_types']['propel2']) + ->addArgument($config['guess_required']) + ->addArgument($config['default_required']); + } } /** diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 701fbb3f..c7fd6717 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -123,6 +123,45 @@ public function __construct($rootName) // boolean types 'BOOLEAN' => 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', 'BOOLEAN_EMU' => 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', + ), + 'propel2' => array( + // datetime types + 'TIMESTAMP' => 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', + 'BU_TIMESTAMP' => 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', + // date types + 'DATE' => 'Symfony\Component\Form\Extension\Core\Type\DateType', + 'BU_DATE' => 'Symfony\Component\Form\Extension\Core\Type\DateType', + // time types + 'TIME' => 'Symfony\Component\Form\Extension\Core\Type\TimeType', + // number types + 'FLOAT' => 'Symfony\Component\Form\Extension\Core\Type\NumberType', + 'REAL' => 'Symfony\Component\Form\Extension\Core\Type\NumberType', + 'DOUBLE' => 'Symfony\Component\Form\Extension\Core\Type\NumberType', + 'DECIMAL' => 'Symfony\Component\Form\Extension\Core\Type\NumberType', + // integer types + 'TINYINT' => 'Symfony\Component\Form\Extension\Core\Type\IntegerType', + 'SMALLINT' => 'Symfony\Component\Form\Extension\Core\Type\IntegerType', + 'INTEGER' => 'Symfony\Component\Form\Extension\Core\Type\IntegerType', + 'BIGINT' => 'Symfony\Component\Form\Extension\Core\Type\IntegerType', + 'NUMERIC' => 'Symfony\Component\Form\Extension\Core\Type\IntegerType', + // text types + 'CHAR' => 'Symfony\Component\Form\Extension\Core\Type\TextType', + 'VARCHAR' => 'Symfony\Component\Form\Extension\Core\Type\TextType', + // textarea types + 'LONGVARCHAR' => 'Symfony\Component\Form\Extension\Core\Type\TextareaType', + 'BLOB' => 'Symfony\Component\Form\Extension\Core\Type\TextareaType', + 'CLOB' => 'Symfony\Component\Form\Extension\Core\Type\TextareaType', + 'CLOB_EMU' => 'Symfony\Component\Form\Extension\Core\Type\TextareaType', + // association types + 'model' => 'Propel\Bundle\PropelBundle\Form\Type\ModelType', + 'collection' => 'Symfony\Component\Form\Extension\Core\Type\CollectionType', + // array types + 'PHP_ARRAY' => 'Symfony\Component\Form\Extension\Core\Type\CollectionType', + // choice types + 'ENUM' => 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', + // boolean types + 'BOOLEAN' => 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', + 'BOOLEAN_EMU' => 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', )); private $defaultFilterTypes = array( @@ -223,6 +262,45 @@ public function __construct($rootName) // boolean types 'BOOLEAN' => 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', 'BOOLEAN_EMU' => 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', + ), + 'propel2' => array( + // datetime types + 'TIMESTAMP' => 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', + 'BU_TIMESTAMP' => 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', + // date types + 'DATE' => 'Symfony\Component\Form\Extension\Core\Type\DateType', + 'BU_DATE' => 'Symfony\Component\Form\Extension\Core\Type\DateType', + // time types + 'TIME' => 'Symfony\Component\Form\Extension\Core\Type\TimeType', + // number types + 'FLOAT' => 'Symfony\Component\Form\Extension\Core\Type\NumberType', + 'REAL' => 'Symfony\Component\Form\Extension\Core\Type\NumberType', + 'DOUBLE' => 'Symfony\Component\Form\Extension\Core\Type\NumberType', + 'DECIMAL' => 'Symfony\Component\Form\Extension\Core\Type\NumberType', + // integer types + 'TINYINT' => 'Symfony\Component\Form\Extension\Core\Type\IntegerType', + 'SMALLINT' => 'Symfony\Component\Form\Extension\Core\Type\IntegerType', + 'INTEGER' => 'Symfony\Component\Form\Extension\Core\Type\IntegerType', + 'BIGINT' => 'Symfony\Component\Form\Extension\Core\Type\IntegerType', + 'NUMERIC' => 'Symfony\Component\Form\Extension\Core\Type\NumberType', + // text types + 'CHAR' => 'Symfony\Component\Form\Extension\Core\Type\TextType', + 'VARCHAR' => 'Symfony\Component\Form\Extension\Core\Type\TextType', + // textarea types + 'LONGVARCHAR' => 'Symfony\Component\Form\Extension\Core\Type\TextType', + 'BLOB' => 'Symfony\Component\Form\Extension\Core\Type\TextType', + 'CLOB' => 'Symfony\Component\Form\Extension\Core\Type\TextType', + 'CLOB_EMU' => 'Symfony\Component\Form\Extension\Core\Type\TextType', + // association types + 'model' => 'Propel\Bundle\PropelBundle\Form\Type\ModelType', + 'collection' => 'Symfony\Component\Form\Extension\Core\Type\CollectionType', + // array types + 'PHP_ARRAY' => 'Symfony\Component\Form\Extension\Core\Type\TextType', + // choice types + 'ENUM' => 'Symfony\Component\Form\Extension\Core\Type\TextType', + // boolean types + 'BOOLEAN' => 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', + 'BOOLEAN_EMU' => 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', )); /** @@ -241,6 +319,7 @@ public function getConfigTreeBuilder() ->booleanNode('use_doctrine_orm')->defaultFalse()->end() ->booleanNode('use_doctrine_odm')->defaultFalse()->end() ->booleanNode('use_propel')->defaultFalse()->end() + ->booleanNode('use_propel2')->defaultFalse()->end() ->booleanNode('use_jms_security')->defaultFalse()->end() ->booleanNode('guess_required')->defaultTrue()->end() ->booleanNode('default_required')->defaultTrue()->end() @@ -317,6 +396,17 @@ public function getConfigTreeBuilder() }) ->end() ->end() + ->arrayNode('propel2') + ->useAttributeAsKey('name') + ->prototype('scalar')->end() + ->defaultValue($this->defaultFormTypes['propel2']) + ->validate() + ->ifNotInArray(array_values($this->defaultFormTypes['propel2'])) + ->then(function ($v){ + return array_merge($this->defaultFormTypes['propel2'], $v); + }) + ->end() + ->end() ->end() ->end() ->arrayNode('filter_types') @@ -355,6 +445,17 @@ public function getConfigTreeBuilder() }) ->end() ->end() + ->arrayNode('propel2') + ->useAttributeAsKey('name') + ->prototype('scalar')->end() + ->defaultValue($this->defaultFilterTypes['propel2']) + ->validate() + ->ifNotInArray(array_values($this->defaultFilterTypes['propel2'])) + ->then(function ($v){ + return array_merge($this->defaultFilterTypes['propel2'], $v); + }) + ->end() + ->end() ->end() ->end() ->append($this->getStylesheetNode()) @@ -402,4 +503,4 @@ private function getJavascriptsNode() return $node; } -} \ No newline at end of file +} diff --git a/Generator/Propel2Generator.php b/Generator/Propel2Generator.php new file mode 100644 index 00000000..910204e9 --- /dev/null +++ b/Generator/Propel2Generator.php @@ -0,0 +1,98 @@ +validateYaml(); + + $generator = new AdminGenerator($this->cache_dir, $this->getGeneratorYml()); + + $generator->setBundleConfig($this->bundleConfig); + $generator->setRouter($this->router); + $generator->setBaseAdminTemplate( + $generator->getFromYaml( + 'base_admin_template', + $generator->getFromBundleConfig('base_admin_template') + ) + ); + $generator->setFieldGuesser($this->getFieldGuesser()); + $generator->setMustOverwriteIfExists($this->needToOverwrite($generator)); + $generator->setTwigExtensions($this->twig->getExtensions()); + $generator->setTwigFilters($this->twig->getFilters()); + $generator->setTemplateDirs($this->templatesDirectories); + $generator->setBaseController('Admingenerator\GeneratorBundle\Controller\Propel\BaseController'); + $generator->setColumnClass('Admingenerator\GeneratorBundle\Generator\PropelColumn'); + $generator->setBaseGeneratorName($this->getBaseGeneratorName()); + + $builders = $generator->getFromYaml('builders', array()); + + if (array_key_exists('list', $builders)) { + $generator->addBuilder(new ListBuilderAction()); + $generator->addBuilder(new ListBuilderTemplate()); + $generator->addBuilder(new FiltersBuilderType()); + } + + if (array_key_exists('nested_list', $builders)) { + $generator->addBuilder(new NestedListBuilderAction()); + $generator->addBuilder(new NestedListBuilderTemplate()); + } + + if (array_key_exists('edit', $builders)) { + $generator->addBuilder(new EditBuilderAction()); + $generator->addBuilder(new EditBuilderTemplate()); + $generator->addBuilder(new EditBuilderType()); + } + + if (array_key_exists('new', $builders)) { + $generator->addBuilder(new NewBuilderAction()); + $generator->addBuilder(new NewBuilderTemplate()); + $generator->addBuilder(new NewBuilderType()); + } + + if (array_key_exists('show', $builders)) { + $generator->addBuilder(new ShowBuilderAction()); + $generator->addBuilder(new ShowBuilderTemplate()); + } + + if (array_key_exists('excel', $builders)) { + $generator->addBuilder(new ExcelBuilderAction()); + } + + if (array_key_exists('actions', $builders)) { + $generator->addBuilder(new ActionsBuilderAction()); + $generator->addBuilder(new ActionsBuilderTemplate()); + } + + $generator->writeOnDisk( + $this->getCachePath( + $generator->getFromYaml('params.namespace_prefix'), + $generator->getFromYaml('params.bundle_name') + ) + ); + } +} diff --git a/Guesser/Propel2ORMFieldGuesser.php b/Guesser/Propel2ORMFieldGuesser.php new file mode 100644 index 00000000..176689fb --- /dev/null +++ b/Guesser/Propel2ORMFieldGuesser.php @@ -0,0 +1,470 @@ +formTypes = $formTypes; + $this->filterTypes = $filterTypes; + $this->guessRequired = $guessRequired; + $this->defaultRequired = $defaultRequired; + } + + /** + * @param $class + * @return mixed + */ + protected function getMetadatas($class) + { + return $this->getTable($class); + } + + /** + * @param $class + * @return array + */ + public function getAllFields($class) + { + $return = array(); + + foreach ($this->getMetadatas($class)->getColumns() as $column) { + $return[] = Inflector::tableize($column->getPhpName()); + } + + return $return; + } + + public function getManyToMany($model, $fieldPath) + { + $resolved = $this->resolveRelatedField($model, $fieldPath); + $relation = $this->getRelation($resolved['field'], $resolved['class']); + + if ($relation) { + return RelationMap::MANY_TO_MANY === $relation->getType(); + } + + return false; + } + + /** + * Find out the database type for given model field path. + * + * @param string $model The starting model. + * @param string $fieldPath The field path. + * @return string The leaf field's primary key. + */ + public function getDbType($model, $fieldPath) + { + $resolved = $this->resolveRelatedField($model, $fieldPath); + $class = $resolved['class']; + $field = $resolved['field']; + + $relation = $this->getRelation($field, $class); + + if ($relation) { + return RelationMap::MANY_TO_ONE === $relation->getType() ? 'model' : 'collection'; + } + + $column = $this->getColumn($class, $field); + + return $column ? $column->getType() : 'virtual'; + } + + /** + * @param $fieldName + * @param $class + * @return object|false The relation object or false. + */ + protected function getRelation($fieldName, $class) + { + $table = $this->getMetadatas($class); + $relName = Inflector::classify($fieldName); + + foreach ($table->getRelations() as $relation) { + if ($relName === $relation->getName() || $relName === $relation->getPluralName()) { + return $relation; + } + } + + return false; + } + + /** + * @param $class + * @param $fieldName + * @return string|void + */ + public function getPhpName($class, $fieldName) + { + $column = $this->getColumn($class, $fieldName); + + if ($column) { + return $column->getPhpName(); + } + } + + /** + * @param $dbType + * @return string + */ + public function getSortType($dbType) + { + $alphabeticTypes = array( + PropelTypes::CHAR, + PropelTypes::VARCHAR, + PropelTypes::LONGVARCHAR, + PropelTypes::BLOB, + PropelTypes::CLOB, + PropelTypes::CLOB_EMU, + ); + + $numericTypes = array( + PropelTypes::FLOAT, + PropelTypes::REAL, + PropelTypes::DOUBLE, + PropelTypes::DECIMAL, + PropelTypes::TINYINT, + PropelTypes::SMALLINT, + PropelTypes::INTEGER, + PropelTypes::BIGINT, + PropelTypes::NUMERIC, + ); + + if (in_array($dbType, $alphabeticTypes)) { + return 'alphabetic'; + } + + if (in_array($dbType, $numericTypes)) { + return 'numeric'; + } + + return 'default'; + } + + /** + * @param $dbType + * @param $class: for debug only + * @param $columnName: for debug only + * @return string + */ + public function getFormType($dbType, $class, $columnName) + { + $formTypes = array(); + + foreach ($this->formTypes as $key => $value) { + // if config is all uppercase use it to retrieve PropelTypes + // constant, otherwise use it literally + if ($key === strtoupper($key)) { + $key = constant('\Propel\Generator\Model\PropelTypes::'.$key); + } + + $formTypes[$key] = $value; + } + + if (array_key_exists($dbType, $formTypes)) { + return $formTypes[$dbType]; + } + + if ('virtual' === $dbType) { + return 'virtual_form'; + } + + throw new NotImplementedException( + 'The dbType "'.$dbType.'" is not yet implemented ' + .'(column "'.$columnName.'" in "'.$class.'")' + ); + } + + /** + * @param $dbType + * @param $columnName + * @return string + */ + public function getFilterType($dbType, $class, $columnName) + { + $filterTypes = array(); + + foreach ($this->filterTypes as $key => $value) { + // if config is all uppercase use it to retrieve PropelTypes + // constant, otherwise use it literally + if ($key === strtoupper($key)) { + $key = constant('\Propel\Generator\Model\PropelTypes::'.$key); + } + + $filterTypes[$key] = $value; + } + + if (array_key_exists($dbType, $filterTypes)) { + return $filterTypes[$dbType]; + } + + if ('virtual' === $dbType) { + return 'virtual_filter'; + } + + throw new NotImplementedException( + 'The dbType "'.$dbType.'" is not yet implemented ' + .'(column "'.$columnName.'" in "'.$class.'")' + ); + } + + /** + * @param $formType + * @param $dbType + * @param $model + * @param $fieldPath + * @return array + */ + public function getFormOptions($formType, $dbType, $model, $fieldPath) + { + return $this->getOptions($formType, $dbType, $model, $fieldPath, false); + } + + /** + * @param $filterType + * @param $dbType + * @param $model + * @param $fieldPath + * @return array + */ + public function getFilterOptions($filterType, $dbType, $model, $fieldPath) + { + return $this->getOptions($filterType, $dbType, $model, $fieldPath, true); + } + + /** + * @param $type + * @param $dbType + * @param $model + * @param $fieldPath + * @param bool $filter + * @return array + */ + protected function getOptions($type, $dbType, $model, $fieldPath, $filter = false) + { + if ('virtual' === $dbType) { + return array(); + } + + $resolved = $this->resolveRelatedField($model, $fieldPath); + $class = $resolved['class']; + $columnName = $resolved['field']; + + if ((PropelTypes::BOOLEAN == $dbType || PropelTypes::BOOLEAN_EMU == $dbType) && + preg_match("#ChoiceType$#i", $type)) { + $options = array( + 'choices' => array( + 'boolean.no' => 0, + 'boolean.yes' => 1 + ), + 'placeholder' => 'boolean.yes_or_no', + 'translation_domain' => 'Admingenerator' + ); + + if (Kernel::MAJOR_VERSION < 3) { + $options['choices_as_values'] = true; + } + + return $options; + } + + if (!$filter && + (PropelTypes::BOOLEAN == $dbType || PropelTypes::BOOLEAN_EMU == $dbType) && + preg_match("#CheckboxType#i", $type)) { + return array( + 'required' => false + ); + } + + if (preg_match("#ModelType$#i", $type)) { + $relation = $this->getRelation($columnName, $class); + if ($relation) { + if (RelationMap::MANY_TO_ONE === $relation->getType()) { + return array( + 'class' => $relation->getForeignTable()->getClassname(), + 'multiple' => false, + ); + } + + return array( + 'class' => $relation->getLocalTable()->getClassname(), + 'multiple' => false, + ); + } + } + + if (preg_match("#CollectionType$#i", $type)) { + $relation = $this->getRelation($columnName, $class); + + if ($relation) { + return array( + 'allow_add' => true, + 'allow_delete' => true, + 'by_reference' => false, + 'entry_type' => 'entity', + 'entry_options' => array( + 'class' => RelationMap::MANY_TO_ONE === $relation->getType() ? $relation->getForeignTable()->getClassname() : $relation->getLocalTable()->getClassname() + ) + ); + } + + return array( + 'entry_type' => 'text', + ); + } + + if (PropelTypes::ENUM == $dbType) { + $valueSet = $this->getMetadatas($class)->getColumn($columnName)->getValueSet(); + + return array( + 'required' => $filter ? false : $this->isRequired($class, $columnName), + 'choices' => array_combine($valueSet, $valueSet), + ); + } + + return array('required' => $filter ? false : $this->isRequired($class, $columnName)); + } + + protected function isRequired($class, $fieldName) + { + if (!$this->guessRequired) { + return $this->defaultRequired; + } + + $column = $this->getColumn($class, $fieldName); + + return $column ? $column->isNotNull() : false; + } + + /** + * Find the pk name + */ + public function getModelPrimaryKeyName($class) + { + $pks = $this->getMetadatas($class)->getPrimaryKeys(); + + if (count($pks) == 1) { + return $pks[key($pks)]->getPhpName(); + } + + throw new \LogicException('No valid primary keys found'); + } + + protected function getTable($class) + { + if (isset($this->cache[$class])) { + return $this->cache[$class]; + } + + if (class_exists($queryClass = $class.'Query')) { + $query = new $queryClass(); + + return $this->cache[$class] = $query->getTableMap(); + } + + throw new \LogicException('Can\'t find query class '.$queryClass); + } + + protected function getColumn($class, $property) + { + if (isset($this->cache[$class.'::'.$property])) { + return $this->cache[$class.'::'.$property]; + } + + $table = $this->getTable($class); + + if ($table && $table->hasColumn($property)) { + return $this->cache[$class.'::'.$property] = $table->getColumn($property); + } else { + foreach ($table->getColumns() as $column) { + $tabelized = Inflector::tableize($column->getPhpName()); + if ($tabelized === $property || $column->getPhpName() === ucfirst($property)) { + return $this->cache[$class.'::'.$property] = $column; + } + } + } + } + + /** + * Find out the primary key for given model field path. + * + * @param string $model The starting model. + * @param string $fieldPath The field path. + * @return string The leaf field's primary key. + */ + public function getPrimaryKeyFor($model, $fieldPath) + { + $resolved = $this->resolveRelatedField($model, $fieldPath); + $class = $resolved['class']; + $field = $resolved['field']; + + if ($relation = $this->getRelation($field, $class)) { + $class = $relation->getLocalTable()->getClassname(); + + return $this->getModelPrimaryKeyName($class); + } else { + // if the leaf node is not an association + return null; + } + } + + /** + * Resolve field path for given model to class and field name. + * + * @param string $model The starting model. + * @param string $fieldPath The field path. + * @return array An array containing field and class information. + */ + private function resolveRelatedField($model, $fieldPath) + { + $path = explode('.', $fieldPath); + $field = array_pop($path); + $class = $model; + + foreach ($path as $part) { + if (!$relation = $this->getRelation($part, $class)) { + throw new \LogicException('Field "'.$part.'" for class "'.$class.'" is not an association.'); + } + + $class = $relation->getName(); + } + + return array( + 'field' => $field, + 'class' => $class + ); + } +} diff --git a/QueryFilter/Propel2QueryFilter.php b/QueryFilter/Propel2QueryFilter.php new file mode 100644 index 00000000..6a2dd8bc --- /dev/null +++ b/QueryFilter/Propel2QueryFilter.php @@ -0,0 +1,35 @@ +addTablePathToField($field); + + if (!is_array($value)) { + $method = 'filterBy'.Inflector::classify($filteredField); + $query->$method($value, $criteria); + } elseif (count($value) > 0) { + $query->filterBy($filteredField, $value, Criteria::IN); + } + } + + public function addBooleanFilter($field, $value) + { + if ("" !== $value) { + $this->addDefaultFilter($field, $value); + } + } + + public function addVarcharFilter($field, $value) + { + $this->addDefaultFilter($field, '%'.$value.'%', Criteria::LIKE); + } + +} diff --git a/Resources/config/propel2.xml b/Resources/config/propel2.xml new file mode 100644 index 00000000..a9820a90 --- /dev/null +++ b/Resources/config/propel2.xml @@ -0,0 +1,39 @@ + + + + + Admingenerator\GeneratorBundle\Generator\PropelGenerator + Admingenerator\GeneratorBundle\Guesser\Propel2ORMFieldGuesser + Admingenerator\GeneratorBundle\QueryFilter\Propel2QueryFilter + + + + + + + + + %kernel.root_dir% + %kernel.cache_dir% + + parameter('admingenerator') + + + + + + + + + + + + + + + + diff --git a/Resources/templates/Propel2/ActionsBuilderAction.php.twig b/Resources/templates/Propel2/ActionsBuilderAction.php.twig new file mode 100644 index 00000000..5905410a --- /dev/null +++ b/Resources/templates/Propel2/ActionsBuilderAction.php.twig @@ -0,0 +1,72 @@ +{% extends '../CommonAdmin/ActionsAction/ActionsBuilderAction.php.twig' %} + +{% block getObject %} + + protected function getObject($pk) + { + ${{ builder.ModelClass }} = $this->getObjectQuery($pk)->findPk($pk); + + if (!${{ builder.ModelClass }}) { + throw new NotFoundHttpException("No {{ model }} found on {{ builder.getFieldGuesser().getModelPrimaryKeyName(model) }} : $pk"); + } + + return ${{ builder.ModelClass }}; + } + +{% endblock %} + +{% block getQuery -%} + protected function getObjectQuery($pk) + { + return \{{ model }}Query::create(); + } +{% endblock %} + +{% block executeObjectDelete %} + + protected function executeObjectDelete(\{{ model }} ${{ builder.ModelClass }}) + { + ${{ builder.ModelClass }}->delete(); + } + +{% endblock %} + +{% block executeBatchDelete %} + + protected function executeBatchDelete(array $selected) + { + $oq = \{{ model }}Query::create(); +{% if admingenerator_config('use_propel_batch_remove') %} + $objects = $oq + ->filterByPrimaryKeys($selected) + ->find(); + + foreach ($objects as $object) { + $object->delete(); + } +{% else %} + $oq + ->filterByPrimaryKeys($selected) + ->delete(); +{% endif %} + } + +{% endblock %} + +{% block saveObject %} + + protected function saveObject(\{{ model }} ${{ builder.ModelClass }}, array $validationGroups = array(), $debug = true) + { + $validator = $this->get('validator'); + $errors = $validator->validate(${{ builder.ModelClass }}, $validationGroups, false, true); + + if (count($errors) > 0) { + if ($debug) { + $this->get('logger')->error((string) $errors); + } + throw new ValidationException($errors); + } else { + ${{ builder.ModelClass }}->save(); + } + } +{% endblock %} diff --git a/Resources/templates/Propel2/ActionsBuilderTemplate.php.twig b/Resources/templates/Propel2/ActionsBuilderTemplate.php.twig new file mode 100644 index 00000000..39bd358f --- /dev/null +++ b/Resources/templates/Propel2/ActionsBuilderTemplate.php.twig @@ -0,0 +1 @@ +{% extends '../CommonAdmin/ActionsTemplate/ActionsBuilderTemplate.php.twig' %} diff --git a/Resources/templates/Propel2/Edit/FormBuilderTemplate.php.twig b/Resources/templates/Propel2/Edit/FormBuilderTemplate.php.twig new file mode 100644 index 00000000..67cc304b --- /dev/null +++ b/Resources/templates/Propel2/Edit/FormBuilderTemplate.php.twig @@ -0,0 +1 @@ +{% extends '../CommonAdmin/EditTemplate/FormBuilderTemplate.php.twig' %} diff --git a/Resources/templates/Propel2/EditBuilderAction.php.twig b/Resources/templates/Propel2/EditBuilderAction.php.twig new file mode 100644 index 00000000..bb8af11c --- /dev/null +++ b/Resources/templates/Propel2/EditBuilderAction.php.twig @@ -0,0 +1,34 @@ +{% extends '../CommonAdmin/EditAction/EditBuilderAction.php.twig' %} + +{% block orm_use %} +use \PropelException; +{% endblock %} + +{% block getObject -%} + protected function getObject($pk) + { + return $this->getQuery($pk)->findPk($pk); + } +{% endblock %} + +{% block getQuery -%} + protected function getQuery($pk) + { + return \{{ model }}Query::create(); + } +{% endblock %} + +{% block saveObject -%} + protected function saveObject(\{{ model }} ${{ builder.ModelClass }}) + { + ${{ builder.ModelClass }}->save(); + } +{% endblock %} + +{% block checkVersion -%} + if (${{ builder.ModelClass }}->getVersion() !== $versions[$pk]) { + throw new PropelException("The lock failed, version ".$versions[$pk]." was expected, but is actually ".${{ builder.ModelClass }}->getVersion()); + } +{% endblock %} + +{% block lockException %}PropelException{% endblock %} \ No newline at end of file diff --git a/Resources/templates/Propel2/EditBuilderTemplate.php.twig b/Resources/templates/Propel2/EditBuilderTemplate.php.twig new file mode 100644 index 00000000..0b064e32 --- /dev/null +++ b/Resources/templates/Propel2/EditBuilderTemplate.php.twig @@ -0,0 +1 @@ +{% extends '../CommonAdmin/EditTemplate/EditBuilderTemplate.php.twig' %} diff --git a/Resources/templates/Propel2/EditBuilderType.php.twig b/Resources/templates/Propel2/EditBuilderType.php.twig new file mode 100644 index 00000000..558fcc70 --- /dev/null +++ b/Resources/templates/Propel2/EditBuilderType.php.twig @@ -0,0 +1 @@ +{% extends '../CommonAdmin/EditType/EditBuilderType.php.twig' %} diff --git a/Resources/templates/Propel2/ExcelBuilderAction.php.twig b/Resources/templates/Propel2/ExcelBuilderAction.php.twig new file mode 100644 index 00000000..52094ac3 --- /dev/null +++ b/Resources/templates/Propel2/ExcelBuilderAction.php.twig @@ -0,0 +1,8 @@ +{% extends '../CommonAdmin/ExcelAction/ExcelBuilderAction.php.twig' %} + +{% block getResults %} + protected function getResults() + { + return $this->getQuery()->find(); + } +{% endblock %} \ No newline at end of file diff --git a/Resources/templates/Propel2/FiltersBuilderType.php.twig b/Resources/templates/Propel2/FiltersBuilderType.php.twig new file mode 100644 index 00000000..0a1f7e95 --- /dev/null +++ b/Resources/templates/Propel2/FiltersBuilderType.php.twig @@ -0,0 +1 @@ +{% extends '../CommonAdmin/FiltersType/FiltersBuilderType.php.twig' %} diff --git a/Resources/templates/Propel2/List/FiltersBuilderTemplate.php.twig b/Resources/templates/Propel2/List/FiltersBuilderTemplate.php.twig new file mode 100644 index 00000000..8f0c3934 --- /dev/null +++ b/Resources/templates/Propel2/List/FiltersBuilderTemplate.php.twig @@ -0,0 +1 @@ +{% extends '../CommonAdmin/ListTemplate/FiltersBuilderTemplate.php.twig' %} diff --git a/Resources/templates/Propel2/List/ResultsBuilderTemplate.php.twig b/Resources/templates/Propel2/List/ResultsBuilderTemplate.php.twig new file mode 100644 index 00000000..7f7ea120 --- /dev/null +++ b/Resources/templates/Propel2/List/ResultsBuilderTemplate.php.twig @@ -0,0 +1 @@ +{% extends '../CommonAdmin/ListTemplate/ResultsBuilderTemplate.php.twig' %} diff --git a/Resources/templates/Propel2/List/RowBuilderTemplate.php.twig b/Resources/templates/Propel2/List/RowBuilderTemplate.php.twig new file mode 100644 index 00000000..5d8313d9 --- /dev/null +++ b/Resources/templates/Propel2/List/RowBuilderTemplate.php.twig @@ -0,0 +1 @@ +{% extends '../CommonAdmin/ListTemplate/RowBuilderTemplate.php.twig' %} diff --git a/Resources/templates/Propel2/ListBuilderAction.php.twig b/Resources/templates/Propel2/ListBuilderAction.php.twig new file mode 100644 index 00000000..c683333b --- /dev/null +++ b/Resources/templates/Propel2/ListBuilderAction.php.twig @@ -0,0 +1,72 @@ +{% extends '../CommonAdmin/ListAction/ListBuilderAction.php.twig' %} +{% block pager_adapter -%} +use Pagerfanta\Adapter\Propel2Adapter as PagerAdapter; +{% endblock %} +{% block getQuery -%} + protected function getQuery() + { + $query = $this->buildQuery(); + + $this->processQuery($query); + $this->processSort($query); + + $queryFilter = $this->getQueryFilter($query); + $this->processFilters($queryFilter); + $this->processScopes($queryFilter); + + return $query; + } + + protected function buildQuery() + { + return \{{ model }}Query::create(); + } +{% endblock %} + +{% block processSort -%} + protected function processSort($query) + { + if ($this->getSortColumn()) { + if (!strstr($this->getSortColumn(), '.')) { //direct column + $query->orderBy($this->getSortColumn(), $this->getSortOrder()); + } else { + list($table, $column) = explode('.', $this->getSortColumn(), 2); + $this->addJoinFor($table, $query); + $query->orderBy($this->getSortColumn(), $this->getSortOrder()); + } + } + } +{% endblock %} + +{% block getFilterForm -%} + protected function getFilterForm() + { + $filters = $this->getFilters(); + {# Don't we should handle "relations" for Propel too? #} + return $this->createForm( + $this->getFiltersType(), + $filters, + $this->getFiltersOptions() + ); + } +{% endblock %} + +{% block addJoinFor -%} + protected function addJoinFor($table, $query) + { + {# TODO: Not sure this is the good way to proceed. Shouldn't we use the useXXXXQuery method? #} + $query->leftJoin($table); + } +{% endblock %} + +{% block getQueryFilter %} + /** + * @return \Admingenerator\GeneratorBundle\QueryFilter\QueryFilterInterface + */ + protected function getQueryFilter($query) + { + $queryFilterClass = $this->container->getParameter('admingenerator.queryfilter.propel2.class'); + + return new $queryFilterClass($query); + } +{% endblock %} diff --git a/Resources/templates/Propel2/ListBuilderTemplate.php.twig b/Resources/templates/Propel2/ListBuilderTemplate.php.twig new file mode 100644 index 00000000..608e7663 --- /dev/null +++ b/Resources/templates/Propel2/ListBuilderTemplate.php.twig @@ -0,0 +1 @@ +{% extends '../CommonAdmin/ListTemplate/ListBuilderTemplate.php.twig' %} diff --git a/Resources/templates/Propel2/NestedList/ResultsBuilderTemplate.php.twig b/Resources/templates/Propel2/NestedList/ResultsBuilderTemplate.php.twig new file mode 100644 index 00000000..3d8f3969 --- /dev/null +++ b/Resources/templates/Propel2/NestedList/ResultsBuilderTemplate.php.twig @@ -0,0 +1 @@ +{% extends '../CommonAdmin/NestedListTemplate/ResultsBuilderTemplate.php.twig' %} diff --git a/Resources/templates/Propel2/NestedList/RowBuilderTemplate.php.twig b/Resources/templates/Propel2/NestedList/RowBuilderTemplate.php.twig new file mode 100644 index 00000000..9f051205 --- /dev/null +++ b/Resources/templates/Propel2/NestedList/RowBuilderTemplate.php.twig @@ -0,0 +1 @@ +{% extends '../CommonAdmin/NestedListTemplate/RowBuilderTemplate.php.twig' %} diff --git a/Resources/templates/Propel2/NestedListBuilderAction.php.twig b/Resources/templates/Propel2/NestedListBuilderAction.php.twig new file mode 100644 index 00000000..e38537c6 --- /dev/null +++ b/Resources/templates/Propel2/NestedListBuilderAction.php.twig @@ -0,0 +1,59 @@ +{% extends '../CommonAdmin/NestedListAction/NestedListBuilderAction.php.twig' %} + +{% block getQuery -%} + protected function getQuery() + { + $query = $this->buildQuery(); + + return $query; + } + + protected function buildQuery() + { + return \{{ model }}Query::create(); + } + + protected function getTree() + { + return $this->getQuery()->findTree(); + } +{% endblock %} + +{% block addJoinFor -%} + protected function addJoinFor($table, $query) + { + $query->leftJoin($table); + } +{% endblock %} + +{% block nested_moveAction -%} + public function nested_moveAction($dragged, $action, $dropped) + { + if(!in_array($action, array('before', 'in', 'after'))) { + throw new NotFoundHttpException("Unknown action"); + } + + $dragged = $this->buildQuery()->findPk($dragged); + $dropped = $this->buildQuery()->findPk($dropped); + + if (!$dragged || !$dropped) { + throw new NotFoundHttpException("Could not find the nodes"); + } + + switch($action) { + case 'before': + $dragged->moveToPrevSiblingOf($dropped); + break; + case 'in': + $dragged->moveToFirstChildOf($dropped); + break; + case 'after': + $dragged->moveToNextSiblingOf($dropped); + break; + } + + $dragged->save(); + + return new Response(); + } +{% endblock %} diff --git a/Resources/templates/Propel2/NestedListBuilderTemplate.php.twig b/Resources/templates/Propel2/NestedListBuilderTemplate.php.twig new file mode 100644 index 00000000..64330ecd --- /dev/null +++ b/Resources/templates/Propel2/NestedListBuilderTemplate.php.twig @@ -0,0 +1 @@ +{% extends '../CommonAdmin/NestedListTemplate/NestedListBuilderTemplate.php.twig' %} diff --git a/Resources/templates/Propel2/NewBuilderAction.php.twig b/Resources/templates/Propel2/NewBuilderAction.php.twig new file mode 100644 index 00000000..23e1be40 --- /dev/null +++ b/Resources/templates/Propel2/NewBuilderAction.php.twig @@ -0,0 +1,8 @@ +{% extends '../CommonAdmin/NewAction/NewBuilderAction.php.twig' %} + +{% block saveObject -%} + protected function saveObject(\{{ model }} ${{ builder.ModelClass }}) + { + ${{ builder.ModelClass }}->save(); + } +{% endblock %} diff --git a/Resources/templates/Propel2/ShowBuilderAction.php.twig b/Resources/templates/Propel2/ShowBuilderAction.php.twig new file mode 100644 index 00000000..fdbd8fd1 --- /dev/null +++ b/Resources/templates/Propel2/ShowBuilderAction.php.twig @@ -0,0 +1,15 @@ +{% extends '../CommonAdmin/ShowAction/ShowBuilderAction.php.twig' %} + +{% block getObject -%} + protected function getObject($pk) + { + return $this->getQuery($pk)->findPk($pk); + } +{% endblock %} + +{% block getQuery -%} + protected function getQuery($pk) + { + return \{{ model }}Query::create(); + } +{% endblock %} diff --git a/Resources/templates/Propel2/ShowBuilderTemplate.php.twig b/Resources/templates/Propel2/ShowBuilderTemplate.php.twig new file mode 100644 index 00000000..de9b9b11 --- /dev/null +++ b/Resources/templates/Propel2/ShowBuilderTemplate.php.twig @@ -0,0 +1 @@ +{% extends '../CommonAdmin/ShowTemplate/ShowBuilderTemplate.php.twig' %} diff --git a/composer.json b/composer.json index ff7e5c91..9af30087 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,8 @@ "doctrine/common": "~2.2", "sensio/generator-bundle": "~3.0", "symfony2admingenerator/twig-generator": "~1.2,>=1.2.2", - "white-october/pagerfanta-bundle": ">=1.0.6", + "pagerfanta/pagerfanta": ">=1.0.5", + "white-october/pagerfanta-bundle": ">=1.0.8", "twig/twig": "~1.12", "twig/extensions": "~1.0" },