Skip to content

Commit

Permalink
Merge pull request #449 from acseo/master
Browse files Browse the repository at this point in the history
YAML file configuration and Command to generate YML from an entity
  • Loading branch information
Petit Yoann committed May 10, 2015
2 parents 7541ae2 + f3f2541 commit 08f109c
Show file tree
Hide file tree
Showing 12 changed files with 518 additions and 99 deletions.
60 changes: 60 additions & 0 deletions Command/GenerateGridCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
/*
* This file is part of the DataGridBundle.
*
* (c) Nicolas Potier <nicolas.potier@acseo-conseil.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace APY\DataGridBundle\Command;

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;

use Sensio\Bundle\GeneratorBundle\Command\Validators;
use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineCommand;

use APY\DataGridBundle\Generator\GridYamlGenerator;

class GenerateGridCommand extends GenerateDoctrineCommand
{
/**
* File extension
* @var string
*/
protected $_extension = '.grid.yml';

protected function configure()
{
$this
->setName('apydatagrid:generate:grid')
->setDescription('Generate the grid configuration for an entity')
->addArgument('entity', InputArgument::REQUIRED, 'The entity class name to initialize (shortcut notation)')
->addArgument('group', InputArgument::REQUIRED, 'The group name')
;
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$entity = Validators::validateEntityName($input->getArgument('entity'));
$group = $input->getArgument('group', "default");

list($bundle, $entity) = $this->parseShortcutNotation($entity);

$entityClass = $this->getContainer()->get('doctrine')->getEntityNamespace($bundle).'\\'.$entity;
$instance = new \ReflectionClass($entityClass);
$generator = $this->getGenerator(null);
$generator->generate($this->getContainer()->get('kernel')->getBundle($bundle), $entityClass, $entity, $group, $this->_extension);
}

protected function createGenerator($bundle = null)
{
$generator = new GridYamlGenerator($this->getContainer()->get('filesystem'));
return $generator;
}
}
1 change: 1 addition & 0 deletions DependencyInjection/APYDataGridExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public function load(array $configs, ContainerBuilder $container)
$loader->load('services.xml');
$loader->load('columns.xml');

$container->setParameter('apy_data_grid.drivers', $config['drivers']);
$container->setParameter('apy_data_grid.limits', $config['limits']);
$container->setParameter('apy_data_grid.theme', $config['theme']);
$container->setParameter('apy_data_grid.persistence', $config['persistence']);
Expand Down
11 changes: 11 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ public function getConfigTreeBuilder()
->defaultValue(array(20 => '20', 50 => '50', 100 => '100'))
->prototype('scalar')->end()
->end()
->arrayNode("drivers")
/*->validate()
->ifTrue(function($v) {
return !in_array($v, array("yml", "annotation"));
})
->thenInvalid("Some drivers are not known")
->end()
*/
->defaultValue(array('annotation', 'yml'))
->prototype('scalar')->end()
->end()
->booleanNode('persistence')->defaultFalse()->end()
->scalarNode('theme')->defaultValue('APYDataGridBundle::blocks.html.twig')->end()
->scalarNode('no_data_message')->defaultValue('No data')->end()
Expand Down
53 changes: 53 additions & 0 deletions Generator/GridYamlGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/*
* This file is part of the DataGridBundle.
*
* (c) Nicolas Potier <nicolas.potier@acseo-conseil.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace APY\DataGridBundle\Generator;

use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Sensio\Bundle\GeneratorBundle\Generator\Generator;


class GridYamlGenerator extends Generator
{
private $filesystem;

/**
* Constructor.
*
* @param Filesystem $filesystem A Filesystem instance
*/
public function __construct(Filesystem $filesystem)
{
$this->filesystem = $filesystem;
}

public function generate(BundleInterface $bundle, $entityClass, $entity, $group, $extension)
{
$this->setSkeletonDirs(__DIR__.'/../Resources/skeleton');
$dir = sprintf("%s/Resources/config/grid",$bundle->getPath());
if (!file_exists($dir)) {
$this->filesystem->mkdir($dir, 0777);
}

$gridFile = sprintf("%s/%s.%s%s", $dir, $entity, $group, $extension);

$instance = new \ReflectionClass($entityClass);

$parameters = array(
'columns' => $instance->getProperties(),
'entityClass' => $entityClass
);

$this->renderFile('grid/grid.yml.twig', $gridFile, $parameters);
}

}
1 change: 0 additions & 1 deletion Grid/Export/DSVExport.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ public function computeData($grid)
}

fclose($outstream);

$this->content = $content;
}

Expand Down
4 changes: 3 additions & 1 deletion Grid/Mapping/Driver/Annotation.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ protected function loadMetadataFromReader($className, $group = 'default')
}

if (empty($this->columns[$className][$group])) {
$this->columns[$className][$group] = array_keys($this->fields[$className][$group]);
// Return empty array instead of array keys
$this->columns[$className][$group] = array();
//$this->columns[$className][$group] = array_keys($this->fields[$className][$group]);
} else {
foreach ($this->columns[$className][$group] as $columnId) {
// Ignore mapped fields
Expand Down
176 changes: 176 additions & 0 deletions Grid/Mapping/Driver/Yaml.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
<?php

/*
* This file is part of the DataGridBundle.
*
* (c) Abhoryo <abhoryo@free.fr>
* (c) Nicolas Potier <nicolas.potier@acseo-conseil.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace APY\DataGridBundle\Grid\Mapping\Driver;

use APY\DataGridBundle\Grid\Mapping\Column as Column;
use APY\DataGridBundle\Grid\Mapping\Source as Source;

use Symfony\Component\Yaml\Parser;
use Symfony\Component\Yaml\Exception\ParseException;

class Yaml implements DriverInterface
{

protected $columns;
protected $filterable;
protected $fields;
protected $loaded;
protected $groupBy;

protected $kernel;

/**
* File extension
* @var string
*/
protected $_extension = '.grid.yml';


public function __construct($kernel)
{
$this->kernel = $kernel;
}

public function getClassColumns($class, $group = 'default')
{
$this->loadMetadataFromReader($class, $group);

return isset($this->columns[$class][$group]) ? $this->columns[$class][$group] : array();
}

public function getFieldsMetadata($class, $group = 'default')
{
$this->loadMetadataFromReader($class, $group);

return isset($this->fields[$class][$group]) ? $this->fields[$class][$group] : array();
}

public function getGroupBy($class, $group = 'default')
{
return isset($this->groupBy[$class][$group]) ? $this->groupBy[$class][$group] : array();
}

protected function loadMetadataFromReader($className, $group = 'default')
{
if (isset($this->loaded[$className][$group])) return;

$instance = new \ReflectionClass($className);
$content = $this->getYamlContent($instance, $group);
if (!$content) {
return;
}
// TODO valider la présence de ces clés
// Peut être en passant par un TreeBuilder ?
$class = $instance->getName();
if (!isset($this->columns[$class])) {
$this->columns[$class] = array();
}

$columns = $content[$class]["Source"]["columns"];
foreach ($columns as $colName => $properties) {
if (!isset($this->columns[$class][$group])) {
$this->columns[$class][$group] = array();
}
$this->columns[$class][$group][] = $colName;
}

$fields = $content[$class]["Columns"];
foreach ($fields as $fieldName => $properties) {
if (!isset($this->fields[$class][$group])) {
$this->fields[$class][$group] = array();
}
$this->fields[$class][$group][$fieldName] = $properties;
}

$groupBys = isset($content[$class]["Source"]["groupBy"])? $content[$class]["Source"]["groupBy"] : array();
foreach($groupBys as $group => $groupBy) {
$this->groupBy[$class][$group] = $groupBy;
}

$filterables = isset($content[$class]["Source"]["filterable"]) ? $content[$class]["Source"]["filterable"] : array();
foreach($filterables as $group => $filterable) {
$this->filterable[$class][$group] = $filterable;
}

$this->loaded[$className][$group] = true;
}

/**
* Get The Yaml file associated to a class and a group
* @param \ReflectionClass $instance an instance of the class
* @param String $group the name of the group
* @return array the parsed YAML file
*/
private function getYamlContent($instance, $group)
{
$yamlFile = $this->locateYamlFile($instance, $group);
$content = false;

if ($yamlFile) {
$yamlParser = new Parser();
$content = $yamlParser->parse(file_get_contents($yamlFile));
}

return $content;
}

/**
* Locate a YAML File based on a directory convention
* @param \ReflectionClass $instance an instance of the class
* @param String $group the name of the group
* @return String the file name
*/
private function locateYamlFile($instance, $group) {
$bundleName = $this->getBundleNameForClass($instance->getName());

$fileToLocate = sprintf("@%s/Resources/config/grid/%s.%s%s",
$bundleName,
basename($instance->getFileName(), ".php"),
$group,
$this->_extension );

try {
return $this->kernel->locateResource($fileToLocate);
}
catch (\Exception $e) {
// The exception is silent
return false;
}
}

/**
* Get The Bundle Name of an entity class
* @param String an entity namespace
* @return the Bundle name of the entity
*/
private function getBundleNameForClass($rootEntityName) {
$bundles = $this->kernel->getBundles();
$bundleName = null;

foreach($bundles as $type => $bundle){
$className = get_class($bundle);

$entityClass = substr($rootEntityName,0,strpos($rootEntityName,'\\Entity\\'));

if(strpos($className,$entityClass) !== FALSE){
$bundleName = $type;
}
}

if (null === $bundleName) {
throw new \Exception(sprintf("Bundle was not found for entity %s, maybe you should declare it in AppKernel", $rootEntityName));
}

return $bundleName;
}
}
31 changes: 30 additions & 1 deletion Grid/Mapping/Metadata/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ class Manager
*/
protected $drivers;

public function __construct()
protected $container;

public function __construct($container)
{
$this->container = $container;
$this->drivers = new DriverHeap();
}

Expand All @@ -31,6 +34,28 @@ public function addDriver($driver, $priority)
$this->drivers->insert($driver, $priority);
}

/**
* Add drivers to the driver list
*/
public function setDrivers($driverList)
{
$priority = 1;
foreach ($driverList as $driverName) {
switch ($driverName) {
case "annotation" :
$driver = $this->container->get("grid.metadata.driver.annotation");
break;
case "yml" :
$driver = $this->container->get("grid.metadata.driver.yaml");
break;
default :
throw new \Exception("Driver $driverName not found");
}
$this->addDriver($driver, $priority);
$priority++;
}
}

/**
* @todo remove this hack
* @return \APY\DataGridBundle\Grid\Mapping\Metadata\DriverHeap
Expand Down Expand Up @@ -69,6 +94,10 @@ public function getMetadata($className, $group = 'default')
}
}

if (empty($cols)) {
throw new \Exception(sprintf("No metadata information has been found for %s (group : %s)", $className, $group));
}

$metadata->setFields($cols);
$metadata->setFieldsMappings($mappings);
$metadata->setGroupBy($groupBy);
Expand Down
Loading

0 comments on commit 08f109c

Please sign in to comment.