This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php

216 lines
7.1 KiB
PHP
Raw Normal View History

2015-09-23 11:26:27 +01:00
<?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 Symfony\Bridge\Doctrine\PropertyInfo;
use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory;
use Doctrine\Common\Persistence\Mapping\MappingException;
use Doctrine\DBAL\Types\Type as DBALType;
2015-09-23 11:26:27 +01:00
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Mapping\MappingException as OrmMappingException;
2015-09-23 11:26:27 +01:00
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use Symfony\Component\PropertyInfo\Type;
/**
* Extracts data using Doctrine ORM and ODM metadata.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeExtractorInterface
{
/**
* @var ClassMetadataFactory
*/
private $classMetadataFactory;
public function __construct(ClassMetadataFactory $classMetadataFactory)
{
$this->classMetadataFactory = $classMetadataFactory;
}
/**
* {@inheritdoc}
*/
public function getProperties($class, array $context = array())
{
try {
$metadata = $this->classMetadataFactory->getMetadataFor($class);
} catch (MappingException $exception) {
return;
} catch (OrmMappingException $exception) {
return;
2015-09-23 11:26:27 +01:00
}
$properties = array_merge($metadata->getFieldNames(), $metadata->getAssociationNames());
if ($metadata instanceof ClassMetadataInfo && class_exists('Doctrine\ORM\Mapping\Embedded') && $metadata->embeddedClasses) {
$properties = array_filter($properties, function ($property) {
return false === strpos($property, '.');
});
$properties = array_merge($properties, array_keys($metadata->embeddedClasses));
}
return $properties;
2015-09-23 11:26:27 +01:00
}
/**
* {@inheritdoc}
*/
public function getTypes($class, $property, array $context = array())
{
try {
$metadata = $this->classMetadataFactory->getMetadataFor($class);
} catch (MappingException $exception) {
return;
} catch (OrmMappingException $exception) {
return;
2015-09-23 11:26:27 +01:00
}
if ($metadata->hasAssociation($property)) {
$class = $metadata->getAssociationTargetClass($property);
if ($metadata->isSingleValuedAssociation($property)) {
if ($metadata instanceof ClassMetadataInfo) {
$associationMapping = $metadata->getAssociationMapping($property);
$nullable = $this->isAssociationNullable($associationMapping);
2015-09-23 11:26:27 +01:00
} else {
$nullable = false;
}
return array(new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $class));
}
$collectionKeyType = Type::BUILTIN_TYPE_INT;
if ($metadata instanceof ClassMetadataInfo) {
$associationMapping = $metadata->getAssociationMapping($property);
if (isset($associationMapping['indexBy'])) {
$indexProperty = $associationMapping['indexBy'];
2016-09-24 22:32:50 +01:00
$subMetadata = $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']);
$typeOfField = $subMetadata->getTypeOfField($indexProperty);
$collectionKeyType = $this->getPhpType($typeOfField);
}
}
2015-09-23 11:26:27 +01:00
return array(new Type(
Type::BUILTIN_TYPE_OBJECT,
false,
'Doctrine\Common\Collections\Collection',
true,
new Type($collectionKeyType),
2015-09-23 11:26:27 +01:00
new Type(Type::BUILTIN_TYPE_OBJECT, false, $class)
));
}
if ($metadata instanceof ClassMetadataInfo && class_exists('Doctrine\ORM\Mapping\Embedded') && isset($metadata->embeddedClasses[$property])) {
return array(new Type(Type::BUILTIN_TYPE_OBJECT, false, $metadata->embeddedClasses[$property]['class']));
}
2015-09-23 11:26:27 +01:00
if ($metadata->hasField($property)) {
$typeOfField = $metadata->getTypeOfField($property);
$nullable = $metadata instanceof ClassMetadataInfo && $metadata->isNullable($property);
switch ($typeOfField) {
case DBALType::DATE:
case DBALType::DATETIME:
case DBALType::DATETIMETZ:
case 'vardatetime':
case DBALType::TIME:
2015-09-23 11:26:27 +01:00
return array(new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTime'));
case DBALType::TARRAY:
2015-09-23 11:26:27 +01:00
return array(new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true));
case DBALType::SIMPLE_ARRAY:
2015-09-23 11:26:27 +01:00
return array(new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)));
case DBALType::JSON_ARRAY:
2015-09-23 11:26:27 +01:00
return array(new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true));
default:
$builtinType = $this->getPhpType($typeOfField);
return $builtinType ? array(new Type($builtinType, $nullable)) : null;
2015-09-23 11:26:27 +01:00
}
}
}
/**
* Determines whether an association is nullable.
*
* @param array $associationMapping
*
* @return bool
*
* @see https://github.com/doctrine/doctrine2/blob/v2.5.4/lib/Doctrine/ORM/Tools/EntityGenerator.php#L1221-L1246
*/
private function isAssociationNullable(array $associationMapping)
{
if (isset($associationMapping['id']) && $associationMapping['id']) {
return false;
}
if (!isset($associationMapping['joinColumns'])) {
return true;
}
$joinColumns = $associationMapping['joinColumns'];
foreach ($joinColumns as $joinColumn) {
if (isset($joinColumn['nullable']) && !$joinColumn['nullable']) {
return false;
}
}
return true;
}
2015-09-23 11:26:27 +01:00
/**
* Gets the corresponding built-in PHP type.
*
* @param string $doctrineType
*
* @return string|null
2015-09-23 11:26:27 +01:00
*/
private function getPhpType($doctrineType)
{
switch ($doctrineType) {
case DBALType::SMALLINT:
case DBALType::INTEGER:
2015-09-23 11:26:27 +01:00
return Type::BUILTIN_TYPE_INT;
case DBALType::FLOAT:
2015-09-23 11:26:27 +01:00
return Type::BUILTIN_TYPE_FLOAT;
case DBALType::BIGINT:
case DBALType::STRING:
case DBALType::TEXT:
case DBALType::GUID:
case DBALType::DECIMAL:
2015-09-23 11:26:27 +01:00
return Type::BUILTIN_TYPE_STRING;
case DBALType::BOOLEAN:
2015-09-23 11:26:27 +01:00
return Type::BUILTIN_TYPE_BOOL;
case DBALType::BLOB:
2015-09-23 11:26:27 +01:00
case 'binary':
return Type::BUILTIN_TYPE_RESOURCE;
case DBALType::OBJECT:
return Type::BUILTIN_TYPE_OBJECT;
2015-09-23 11:26:27 +01:00
}
}
}