Merge pull request #272 from jsor/table_options
Implement custom options on table level and complete column options implementation
This commit is contained in:
commit
2ce705ceb3
@ -86,6 +86,7 @@
|
|||||||
|
|
||||||
<xs:complexType name="entity">
|
<xs:complexType name="entity">
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
|
<xs:element name="options" type="orm:options" minOccurs="0" />
|
||||||
<xs:element name="indexes" type="orm:indexes" minOccurs="0"/>
|
<xs:element name="indexes" type="orm:indexes" minOccurs="0"/>
|
||||||
<xs:element name="unique-constraints" type="orm:unique-constraints" minOccurs="0"/>
|
<xs:element name="unique-constraints" type="orm:unique-constraints" minOccurs="0"/>
|
||||||
<xs:element name="discriminator-column" type="orm:discriminator-column" minOccurs="0"/>
|
<xs:element name="discriminator-column" type="orm:discriminator-column" minOccurs="0"/>
|
||||||
@ -110,6 +111,23 @@
|
|||||||
<xs:anyAttribute namespace="##other"/>
|
<xs:anyAttribute namespace="##other"/>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="option" mixed="true">
|
||||||
|
<xs:sequence minOccurs="0" maxOccurs="unbounded">
|
||||||
|
<xs:element name="option" type="orm:option"/>
|
||||||
|
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="name" type="xs:NMTOKEN" use="required"/>
|
||||||
|
<xs:anyAttribute namespace="##other"/>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="options">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="option" type="orm:option" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:anyAttribute namespace="##other"/>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
<xs:complexType name="mapped-superclass" >
|
<xs:complexType name="mapped-superclass" >
|
||||||
<xs:complexContent>
|
<xs:complexContent>
|
||||||
<xs:extension base="orm:entity">
|
<xs:extension base="orm:entity">
|
||||||
@ -164,6 +182,7 @@
|
|||||||
|
|
||||||
<xs:complexType name="field">
|
<xs:complexType name="field">
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
|
<xs:element name="options" type="orm:options" minOccurs="0" />
|
||||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
||||||
|
@ -1705,6 +1705,10 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
if (isset($table['uniqueConstraints'])) {
|
if (isset($table['uniqueConstraints'])) {
|
||||||
$this->table['uniqueConstraints'] = $table['uniqueConstraints'];
|
$this->table['uniqueConstraints'] = $table['uniqueConstraints'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($table['options'])) {
|
||||||
|
$this->table['options'] = $table['options'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -190,6 +190,10 @@ class AnnotationDriver implements Driver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($tableAnnot->options !== null) {
|
||||||
|
$primaryTable['options'] = $tableAnnot->options;
|
||||||
|
}
|
||||||
|
|
||||||
$metadata->setPrimaryTable($primaryTable);
|
$metadata->setPrimaryTable($primaryTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +161,10 @@ class XmlDriver extends AbstractFileDriver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($xmlRoot->options)) {
|
||||||
|
$metadata->table['options'] = $this->_parseOptions($xmlRoot->options->children());
|
||||||
|
}
|
||||||
|
|
||||||
// Evaluate <field ...> mappings
|
// Evaluate <field ...> mappings
|
||||||
if (isset($xmlRoot->field)) {
|
if (isset($xmlRoot->field)) {
|
||||||
foreach ($xmlRoot->field as $fieldMapping) {
|
foreach ($xmlRoot->field as $fieldMapping) {
|
||||||
@ -192,10 +196,6 @@ class XmlDriver extends AbstractFileDriver
|
|||||||
$mapping['unique'] = ((string)$fieldMapping['unique'] == "false") ? false : true;
|
$mapping['unique'] = ((string)$fieldMapping['unique'] == "false") ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($fieldMapping['options'])) {
|
|
||||||
$mapping['options'] = (array)$fieldMapping['options'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($fieldMapping['nullable'])) {
|
if (isset($fieldMapping['nullable'])) {
|
||||||
$mapping['nullable'] = ((string)$fieldMapping['nullable'] == "false") ? false : true;
|
$mapping['nullable'] = ((string)$fieldMapping['nullable'] == "false") ? false : true;
|
||||||
}
|
}
|
||||||
@ -208,6 +208,10 @@ class XmlDriver extends AbstractFileDriver
|
|||||||
$mapping['columnDefinition'] = (string)$fieldMapping['column-definition'];
|
$mapping['columnDefinition'] = (string)$fieldMapping['column-definition'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($fieldMapping->options)) {
|
||||||
|
$mapping['options'] = $this->_parseOptions($fieldMapping->options->children());
|
||||||
|
}
|
||||||
|
|
||||||
$metadata->mapField($mapping);
|
$metadata->mapField($mapping);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -454,6 +458,35 @@ class XmlDriver extends AbstractFileDriver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses (nested) option elements.
|
||||||
|
*
|
||||||
|
* @param $options The XML element.
|
||||||
|
* @return array The options array.
|
||||||
|
*/
|
||||||
|
private function _parseOptions(SimpleXMLElement $options)
|
||||||
|
{
|
||||||
|
$array = array();
|
||||||
|
|
||||||
|
foreach ($options as $option) {
|
||||||
|
if ($option->count()) {
|
||||||
|
$value = $this->_parseOptions($option->children());
|
||||||
|
} else {
|
||||||
|
$value = (string) $option;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attr = $option->attributes();
|
||||||
|
|
||||||
|
if (isset($attr->name)) {
|
||||||
|
$array[(string) $attr->name] = $value;
|
||||||
|
} else {
|
||||||
|
$array[] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a joinColumn mapping array based on the information
|
* Constructs a joinColumn mapping array based on the information
|
||||||
* found in the given SimpleXMLElement.
|
* found in the given SimpleXMLElement.
|
||||||
|
@ -156,6 +156,10 @@ class YamlDriver extends AbstractFileDriver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($element['options'])) {
|
||||||
|
$metadata->table['options'] = $element['options'];
|
||||||
|
}
|
||||||
|
|
||||||
$associationIds = array();
|
$associationIds = array();
|
||||||
if (isset($element['id'])) {
|
if (isset($element['id'])) {
|
||||||
// Evaluate identifier settings
|
// Evaluate identifier settings
|
||||||
|
@ -33,4 +33,6 @@ final class Table implements Annotation
|
|||||||
public $indexes;
|
public $indexes;
|
||||||
/** @var array<\Doctrine\ORM\Mapping\UniqueConstraint> */
|
/** @var array<\Doctrine\ORM\Mapping\UniqueConstraint> */
|
||||||
public $uniqueConstraints;
|
public $uniqueConstraints;
|
||||||
|
/** @var array */
|
||||||
|
public $options = array();
|
||||||
}
|
}
|
||||||
|
@ -235,6 +235,12 @@ class SchemaTool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($class->table['options'])) {
|
||||||
|
foreach ($class->table['options'] AS $key => $val) {
|
||||||
|
$table->addOption($key, $val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$processedClasses[$class->name] = true;
|
$processedClasses[$class->name] = true;
|
||||||
|
|
||||||
if ($class->isIdGeneratorSequence() && $class->name == $class->rootEntityName) {
|
if ($class->isIdGeneratorSequence() && $class->name == $class->rootEntityName) {
|
||||||
|
@ -77,6 +77,21 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
* @depends testEntityTableNameAndInheritance
|
* @depends testEntityTableNameAndInheritance
|
||||||
* @param ClassMetadata $class
|
* @param ClassMetadata $class
|
||||||
*/
|
*/
|
||||||
|
public function testEntityOptions($class)
|
||||||
|
{
|
||||||
|
$this->assertArrayHasKey('options', $class->table, 'ClassMetadata should have options key in table property.');
|
||||||
|
|
||||||
|
$this->assertEquals(array(
|
||||||
|
'foo' => 'bar', 'baz' => array('key' => 'val')
|
||||||
|
), $class->table['options']);
|
||||||
|
|
||||||
|
return $class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testEntityOptions
|
||||||
|
* @param ClassMetadata $class
|
||||||
|
*/
|
||||||
public function testEntitySequence($class)
|
public function testEntitySequence($class)
|
||||||
{
|
{
|
||||||
$this->assertInternalType('array', $class->sequenceGeneratorDefinition, 'No Sequence Definition set on this driver.');
|
$this->assertInternalType('array', $class->sequenceGeneratorDefinition, 'No Sequence Definition set on this driver.');
|
||||||
@ -129,6 +144,9 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
$this->assertTrue($class->fieldMappings['name']['nullable']);
|
$this->assertTrue($class->fieldMappings['name']['nullable']);
|
||||||
$this->assertTrue($class->fieldMappings['name']['unique']);
|
$this->assertTrue($class->fieldMappings['name']['unique']);
|
||||||
|
|
||||||
|
$expected = array('foo' => 'bar', 'baz' => array('key' => 'val'));
|
||||||
|
$this->assertEquals($expected, $class->fieldMappings['name']['options']);
|
||||||
|
|
||||||
return $class;
|
return $class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,7 +442,8 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
* @Table(
|
* @Table(
|
||||||
* name="cms_users",
|
* name="cms_users",
|
||||||
* uniqueConstraints={@UniqueConstraint(name="search_idx", columns={"name", "user_email"})},
|
* uniqueConstraints={@UniqueConstraint(name="search_idx", columns={"name", "user_email"})},
|
||||||
* indexes={@Index(name="name_idx", columns={"name"}), @Index(name="0", columns={"user_email"})}
|
* indexes={@Index(name="name_idx", columns={"name"}), @Index(name="0", columns={"user_email"})},
|
||||||
|
* options={"foo": "bar", "baz": {"key": "val"}}
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
class User
|
class User
|
||||||
@ -438,7 +457,7 @@ class User
|
|||||||
public $id;
|
public $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Column(length=50, nullable=true, unique=true)
|
* @Column(length=50, nullable=true, unique=true, options={"foo": "bar", "baz": {"key": "val"}})
|
||||||
*/
|
*/
|
||||||
public $name;
|
public $name;
|
||||||
|
|
||||||
@ -495,6 +514,7 @@ class User
|
|||||||
$metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE);
|
$metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE);
|
||||||
$metadata->setPrimaryTable(array(
|
$metadata->setPrimaryTable(array(
|
||||||
'name' => 'cms_users',
|
'name' => 'cms_users',
|
||||||
|
'options' => array('foo' => 'bar', 'baz' => array('key' => 'val')),
|
||||||
));
|
));
|
||||||
$metadata->setChangeTrackingPolicy(ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT);
|
$metadata->setChangeTrackingPolicy(ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT);
|
||||||
$metadata->addLifecycleCallback('doStuffOnPrePersist', 'prePersist');
|
$metadata->addLifecycleCallback('doStuffOnPrePersist', 'prePersist');
|
||||||
@ -513,6 +533,7 @@ class User
|
|||||||
'unique' => true,
|
'unique' => true,
|
||||||
'nullable' => true,
|
'nullable' => true,
|
||||||
'columnName' => 'name',
|
'columnName' => 'name',
|
||||||
|
'options' => array('foo' => 'bar', 'baz' => array('key' => 'val')),
|
||||||
));
|
));
|
||||||
$metadata->mapField(array(
|
$metadata->mapField(array(
|
||||||
'fieldName' => 'email',
|
'fieldName' => 'email',
|
||||||
|
@ -27,6 +27,7 @@ $metadata->mapField(array(
|
|||||||
'unique' => true,
|
'unique' => true,
|
||||||
'nullable' => true,
|
'nullable' => true,
|
||||||
'columnName' => 'name',
|
'columnName' => 'name',
|
||||||
|
'options' => array('foo' => 'bar', 'baz' => array('key' => 'val')),
|
||||||
));
|
));
|
||||||
$metadata->mapField(array(
|
$metadata->mapField(array(
|
||||||
'fieldName' => 'email',
|
'fieldName' => 'email',
|
||||||
@ -106,6 +107,10 @@ $metadata->mapManyToMany(array(
|
|||||||
),
|
),
|
||||||
'orderBy' => NULL,
|
'orderBy' => NULL,
|
||||||
));
|
));
|
||||||
|
$metadata->table['options'] = array(
|
||||||
|
'foo' => 'bar',
|
||||||
|
'baz' => array('key' => 'val')
|
||||||
|
);
|
||||||
$metadata->table['uniqueConstraints'] = array(
|
$metadata->table['uniqueConstraints'] = array(
|
||||||
'search_idx' => array('columns' => array('name', 'user_email')),
|
'search_idx' => array('columns' => array('name', 'user_email')),
|
||||||
);
|
);
|
||||||
|
@ -6,6 +6,12 @@
|
|||||||
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
|
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
|
||||||
|
|
||||||
<entity name="Doctrine\Tests\ORM\Mapping\User" table="cms_users">
|
<entity name="Doctrine\Tests\ORM\Mapping\User" table="cms_users">
|
||||||
|
<options>
|
||||||
|
<option name="foo">bar</option>
|
||||||
|
<option name="baz">
|
||||||
|
<option name="key">val</option>
|
||||||
|
</option>
|
||||||
|
</options>
|
||||||
|
|
||||||
<indexes>
|
<indexes>
|
||||||
<index name="name_idx" columns="name"/>
|
<index name="name_idx" columns="name"/>
|
||||||
@ -15,7 +21,7 @@
|
|||||||
<unique-constraints>
|
<unique-constraints>
|
||||||
<unique-constraint columns="name,user_email" name="search_idx" />
|
<unique-constraint columns="name,user_email" name="search_idx" />
|
||||||
</unique-constraints>
|
</unique-constraints>
|
||||||
|
|
||||||
<lifecycle-callbacks>
|
<lifecycle-callbacks>
|
||||||
<lifecycle-callback type="prePersist" method="doStuffOnPrePersist"/>
|
<lifecycle-callback type="prePersist" method="doStuffOnPrePersist"/>
|
||||||
<lifecycle-callback type="prePersist" method="doOtherStuffOnPrePersistToo"/>
|
<lifecycle-callback type="prePersist" method="doOtherStuffOnPrePersistToo"/>
|
||||||
@ -31,7 +37,14 @@
|
|||||||
<sequence-generator sequence-name="tablename_seq" allocation-size="100" initial-value="1" />
|
<sequence-generator sequence-name="tablename_seq" allocation-size="100" initial-value="1" />
|
||||||
</id>
|
</id>
|
||||||
|
|
||||||
<field name="name" column="name" type="string" length="50" nullable="true" unique="true" />
|
<field name="name" column="name" type="string" length="50" nullable="true" unique="true">
|
||||||
|
<options>
|
||||||
|
<option name="foo">bar</option>
|
||||||
|
<option name="baz">
|
||||||
|
<option name="key">val</option>
|
||||||
|
</option>
|
||||||
|
</options>
|
||||||
|
</field>
|
||||||
<field name="email" column="user_email" type="string" column-definition="CHAR(32) NOT NULL" />
|
<field name="email" column="user_email" type="string" column-definition="CHAR(32) NOT NULL" />
|
||||||
|
|
||||||
<one-to-one field="address" target-entity="Address" inversed-by="user">
|
<one-to-one field="address" target-entity="Address" inversed-by="user">
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
Doctrine\Tests\ORM\Mapping\User:
|
Doctrine\Tests\ORM\Mapping\User:
|
||||||
type: entity
|
type: entity
|
||||||
table: cms_users
|
table: cms_users
|
||||||
|
options:
|
||||||
|
foo: bar
|
||||||
|
baz:
|
||||||
|
key: val
|
||||||
namedQueries:
|
namedQueries:
|
||||||
all: SELECT u FROM __CLASS__ u
|
all: SELECT u FROM __CLASS__ u
|
||||||
id:
|
id:
|
||||||
@ -18,6 +22,10 @@ Doctrine\Tests\ORM\Mapping\User:
|
|||||||
length: 50
|
length: 50
|
||||||
nullable: true
|
nullable: true
|
||||||
unique: true
|
unique: true
|
||||||
|
options:
|
||||||
|
foo: bar
|
||||||
|
baz:
|
||||||
|
key: val
|
||||||
email:
|
email:
|
||||||
type: string
|
type: string
|
||||||
column: user_email
|
column: user_email
|
||||||
|
@ -32,19 +32,21 @@ class SchemaToolTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
$this->assertTrue($schema->getTable('cms_users')->columnsAreIndexed(array('username')), "username column should be indexed.");
|
$this->assertTrue($schema->getTable('cms_users')->columnsAreIndexed(array('username')), "username column should be indexed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testColumnAnnotationOptionsAttribute()
|
public function testAnnotationOptionsAttribute()
|
||||||
{
|
{
|
||||||
$em = $this->_getTestEntityManager();
|
$em = $this->_getTestEntityManager();
|
||||||
$schemaTool = new SchemaTool($em);
|
$schemaTool = new SchemaTool($em);
|
||||||
|
|
||||||
$classes = array(
|
$classes = array(
|
||||||
$em->getClassMetadata(__NAMESPACE__ . '\\TestEntityWithColumnAnnotationOptionsAttribute'),
|
$em->getClassMetadata(__NAMESPACE__ . '\\TestEntityWithAnnotationOptionsAttribute'),
|
||||||
);
|
);
|
||||||
|
|
||||||
$schema = $schemaTool->getSchemaFromMetadata($classes);
|
$schema = $schemaTool->getSchemaFromMetadata($classes);
|
||||||
|
|
||||||
$expected = array('foo' => 'bar', 'baz' => array('key' => 'val'));
|
$expected = array('foo' => 'bar', 'baz' => array('key' => 'val'));
|
||||||
$this->assertEquals($expected, $schema->getTable('TestEntityWithColumnAnnotationOptionsAttribute')->getColumn('test')->getCustomSchemaOptions(), "options annotation are passed to the columns customSchemaOptions");
|
|
||||||
|
$this->assertEquals($expected, $schema->getTable('TestEntityWithAnnotationOptionsAttribute')->getOptions(), "options annotation are passed to the tables optionss");
|
||||||
|
$this->assertEquals($expected, $schema->getTable('TestEntityWithAnnotationOptionsAttribute')->getColumn('test')->getCustomSchemaOptions(), "options annotation are passed to the columns customSchemaOptions");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,8 +105,9 @@ class SchemaToolTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @Entity
|
* @Entity
|
||||||
|
* @Table(options={"foo": "bar", "baz": {"key": "val"}})
|
||||||
*/
|
*/
|
||||||
class TestEntityWithColumnAnnotationOptionsAttribute
|
class TestEntityWithAnnotationOptionsAttribute
|
||||||
{
|
{
|
||||||
/** @Id @Column */
|
/** @Id @Column */
|
||||||
private $id;
|
private $id;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user