Skip to content

Commit

Permalink
add support multiple choice select
Browse files Browse the repository at this point in the history
  • Loading branch information
Митрофанов Николай committed May 10, 2017
1 parent 99c9388 commit 7da425c
Show file tree
Hide file tree
Showing 10 changed files with 1,676 additions and 1,589 deletions.
2,292 changes: 1,149 additions & 1,143 deletions assets/fod.query-constructor.dev.js

Large diffs are not rendered by default.

44 changes: 22 additions & 22 deletions assets/fod.query-constructor.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"redux-devtools-dock-monitor": "^1.1.1",
"redux-devtools-log-monitor": "^1.0.11",
"redux-logger": "^2.7.2",
"reload-server-webpack-plugin": "^1.0.1",
"style-loader": "^0.16.1",
"webpack": "^1.13.3",
"webpack-dev-server": "^1.16.2"
Expand Down
16 changes: 16 additions & 0 deletions src/Mapping/Annotation/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ class Property
const TYPE_DATE = 'date';
const TYPE_SINGLE_CHOICE = 'single_choice';
const TYPE_MULTIPLE_CHOICE = 'multiple_choice';
const TYPE_AGGREGATE = 'aggregate';

/**
* @return array
*/
static public function getTypes()
{
return [
self::TYPE_STRING,
self::TYPE_INTEGER,
self::TYPE_DATE,
self::TYPE_SINGLE_CHOICE,
self::TYPE_MULTIPLE_CHOICE,
self::TYPE_AGGREGATE,
];
}

/**
* @var string
Expand Down
98 changes: 73 additions & 25 deletions src/Mapping/Reader.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadata as OrmClassMetadata;
use Doctrine\ORM\Mapping\MappingException;
use FOD\QueryConstructor\Mapping\Annotation\Entity;
use FOD\QueryConstructor\Mapping\Annotation\Property;

Expand All @@ -29,6 +30,9 @@ class Reader
*/
protected $associations;

/** @var array */
protected $invertAssociations = [];

/**
* Constructor
*
Expand All @@ -52,11 +56,10 @@ public function getClassMetaData(OrmClassMetadata $metaData)
if ($entityMetadata = $this->reader->getClassAnnotation($metaData->getReflectionClass(), Entity::CLASSNAME)) {

$classMetadata = new ClassMetadata($metaData->getReflectionClass()->getName(), $entityMetadata);
$properties = $metaData->getReflectionProperties();

$classMetadata->setAggregatableProperties($this->fetchProperties($metaData,
$this->filterOnlyExcept(
$properties,
$metaData->getReflectionProperties(),
array_reduce($metaData->fieldMappings, function ($properties, $property) {
if (in_array($property['type'], [Type::INTEGER, Type::SMALLINT, Type::BIGINT, Type::FLOAT, Type::DECIMAL, Type::BINARY], true)) {
$properties[] = $property['fieldName'];
Expand All @@ -67,7 +70,7 @@ public function getClassMetaData(OrmClassMetadata $metaData)
)
));

$classMetadata->setProperties($this->fetchProperties($metaData, $properties));
$classMetadata->setProperties($this->fetchProperties($metaData));

$classMetadata->setJoins($this->makeJoins($metaData));

Expand Down Expand Up @@ -119,14 +122,25 @@ protected function filterExcept(array $properties, array $names = null)
* @param OrmClassMetadata $metadata
* @param array $properties
*
* @return array
* @return Property[]
*/
protected function fetchProperties(OrmClassMetadata $metadata, array $properties)
protected function fetchProperties(OrmClassMetadata $metadata, array $properties = [])
{
$result = [];
$oneToMany = [];
if (!$properties) {
$properties = $metadata->getReflectionProperties();
}

/** @var \ReflectionProperty $property */
foreach ($properties as $property) {
if (!isset($this->getAssociations($metadata)[$property->getName()])) {
$result[$property->getName()] = $this->makePropertyFromReflection($metadata, $property);
$propertyType = null;
if (isset($metadata->associationMappings[$property->getName()]) && !isset($metadata->associationMappings[$property->getName()]['joinColumns'])) {
$result['COUNT(' . $property->getName() . ')'] = $this->makePropertyFromReflection($metadata, $property, Property::TYPE_AGGREGATE, 'COUNT(' . $property->getName() . ')');
$propertyType = Property::TYPE_MULTIPLE_CHOICE;
}
$result[$property->getName()] = $this->makePropertyFromReflection($metadata, $property, $propertyType);
}
}

Expand All @@ -136,37 +150,46 @@ protected function fetchProperties(OrmClassMetadata $metadata, array $properties
/**
* @param OrmClassMetadata $metadata
* @param \ReflectionProperty $property
* @param string $propertyType
* @param string $propertyTitle
*
* @return Property
*/
protected function makePropertyFromReflection(OrmClassMetadata $metadata, \ReflectionProperty $property)
protected function makePropertyFromReflection(OrmClassMetadata $metadata, \ReflectionProperty $property, $propertyType = null, $propertyTitle = null)
{
$propertyMetadata = $this->reader->getPropertyAnnotation($property, Property::CLASSNAME);
if (!$propertyMetadata) {
$propertyMetadata = new Property();
}

if (!$propertyMetadata->title) {
$propertyMetadata->title = ucfirst($property->getName());
$propertyMetadata->title = $propertyTitle ?: ucfirst($property->getName());
}

if (!$propertyMetadata->choices && isset($this->getAssociations($metadata)[$property->getName()]['targetEntity'])) {
if (!$propertyMetadata->choices && isset($metadata->associationMappings[$property->getName()])) {
$titleField = isset($propertyMetadata->titleField) ? $propertyMetadata->titleField : null;
list($valueField, $titleField) = $this->detectListFields(
$metadata,
$property->getName(),
$this->getAssociations($metadata)[$property->getName()]['targetEntity'],
$metadata->associationMappings[$property->getName()]['targetEntity'],
$titleField
);

$propertyMetadata->choices = $this->loadChoices(
$this->getAssociations($metadata)[$property->getName()]['targetEntity'],
$metadata->associationMappings[$property->getName()]['targetEntity'],
$valueField,
$titleField
);
}

if (!$propertyMetadata->type) {
if (is_array($propertyMetadata->choices) && count($propertyMetadata->choices) > 0) {

if (null !== $propertyType) {
if (!in_array($propertyType, Property::getTypes(), true)) {
throw new \InvalidArgumentException('Property type \'' . $propertyType . '\' is not valid');
}
$propertyMetadata->type = $propertyType;
} elseif (is_array($propertyMetadata->choices) && count($propertyMetadata->choices) > 0) {
$propertyMetadata->type = Property::TYPE_MULTIPLE_CHOICE;
} else {
$propertyMetadata->type = $this->mapPropertyTypeFromDoctrine($metadata->getTypeOfField($property->getName()));
Expand All @@ -187,9 +210,14 @@ protected function makePropertyFromReflection(OrmClassMetadata $metadata, \Refle
*/
protected function detectListFields(OrmClassMetadata $metadata, $propertyName, $targetClassName, $titleField = null)
{
$valueColumn = $metadata->getSingleAssociationReferencedJoinColumnName($propertyName);
$referencedMetadata = $this->em->getMetadataFactory()->getMetadataFor($targetClassName);
$valueField = $referencedMetadata->getFieldName($valueColumn);

try {
$valueField = $referencedMetadata->getFieldName($metadata->getSingleAssociationReferencedJoinColumnName($propertyName));
} catch (MappingException $exception) {
$valueField = $referencedMetadata->getIdentifierFieldNames();
}

if (!$titleField) {
foreach ($referencedMetadata->getFieldNames() as $fieldName) {
if ($fieldName === $valueField) {
Expand All @@ -204,6 +232,7 @@ protected function detectListFields(OrmClassMetadata $metadata, $propertyName, $
throw new \LogicException(sprintf('String title field not found in class [%s]. Specify titleField option manually.', $targetClassName));
}
}

return [$valueField, $titleField];
}

Expand All @@ -217,14 +246,24 @@ protected function detectListFields(OrmClassMetadata $metadata, $propertyName, $
protected function loadChoices($className, $valueField, $titleField)
{
$resultSet = $this->em->createQueryBuilder()
->select("PARTIAL e.{{$valueField}, {$titleField}}")
->select("PARTIAL e.{" . implode(', ', array_merge([$titleField], (array)$valueField)) . "}")
->from($className, 'e')
->getQuery()
->getArrayResult();

// PHP5.4 support: instead of array_column($resultSet, $titleField, $valueField)
$resultMapped = array_reduce($resultSet, function (array $result, array $item) use ($valueField, $titleField) {
$result[$item[$valueField]] = $item[$titleField];
$valueField = (array)$valueField;
if (count($valueField) > 1) {
$key = [];
foreach ($valueField as $vField) {
$key[] = $vField . ':' . $item[$vField];
}
$result[implode(';', $key)] = $item[$titleField];
} else {
$result[$item[current($valueField)]] = $item[current($valueField)] . ': ' . $item[$titleField];
}

return $result;
}, []);

Expand Down Expand Up @@ -271,17 +310,26 @@ protected function getAssociations(OrmClassMetadata $metadata)

foreach ($metadata->getAssociationMappings() as $field => $mapping) {
if (!$mapping['isOwningSide']) {
continue;
}
$targetClassName = $mapping['targetEntity'];
$ormClassMetadata = $this->em->getMetadataFactory()->getMetadataFor($targetClassName);
$targetClassName = $mapping['targetEntity'];
$ormClassMetadata = $this->em->getMetadataFactory()->getMetadataFor($targetClassName);

$entityMetadata = $this->reader->getClassAnnotation(
$ormClassMetadata->getReflectionClass(),
Entity::CLASSNAME
);
$entityMetadata = $this->reader->getClassAnnotation(
$ormClassMetadata->getReflectionClass(),
Entity::CLASSNAME
);

$this->invertAssociations[$metadata->name][$field] = new AssociationMetaData($targetClassName, $entityMetadata, $this->getAssociations($ormClassMetadata));
} else {
$targetClassName = $mapping['targetEntity'];
$ormClassMetadata = $this->em->getMetadataFactory()->getMetadataFor($targetClassName);

$this->associations[$metadata->name][$field] = new AssociationMetaData($targetClassName, $entityMetadata, $this->getAssociations($ormClassMetadata));
$entityMetadata = $this->reader->getClassAnnotation(
$ormClassMetadata->getReflectionClass(),
Entity::CLASSNAME
);

$this->associations[$metadata->name][$field] = new AssociationMetaData($targetClassName, $entityMetadata, $this->getAssociations($ormClassMetadata));
}
}

return $this->associations[$metadata->name];
Expand Down
2 changes: 1 addition & 1 deletion src/Metadata/Registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public function getMetadata($className)
*/
public function getMetadataRegistry()
{
if (is_null($this->metadataRegistry)) {
if (null === $this->metadataRegistry) {
$this->metadataRegistry = $this->discovery->discoverAll();
}
return $this->metadataRegistry;
Expand Down
Loading

0 comments on commit 7da425c

Please sign in to comment.