1
0
mirror of synced 2025-03-05 04:13:20 +03:00

Merge pull request #272 from jsor/table_options

Implement custom options on table level and complete column options implementation
This commit is contained in:
Benjamin Eberlei 2012-01-28 12:56:19 -08:00
commit 2ce705ceb3
12 changed files with 134 additions and 12 deletions

View File

@ -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" />

View File

@ -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'];
}
} }
/** /**

View File

@ -190,6 +190,10 @@ class AnnotationDriver implements Driver
} }
} }
if ($tableAnnot->options !== null) {
$primaryTable['options'] = $tableAnnot->options;
}
$metadata->setPrimaryTable($primaryTable); $metadata->setPrimaryTable($primaryTable);
} }

View File

@ -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.

View File

@ -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

View File

@ -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();
} }

View File

@ -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) {

View File

@ -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',

View File

@ -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')),
); );

View File

@ -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"/>
@ -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">

View File

@ -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

View File

@ -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;