[2.0] Work on mapping drivers, exporter drivers and reverse engineering of database schemas
This commit is contained in:
parent
c8362da494
commit
165abc3ca4
@ -72,198 +72,13 @@ class Inflector
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string has utf7 characters in it
|
||||
* Camelize a word. This uses the classify() method and turns the first character to lowercase
|
||||
*
|
||||
* By bmorel at ssi dot fr
|
||||
*
|
||||
* @param string $string
|
||||
* @return boolean $bool
|
||||
* @param string $word
|
||||
* @return string $word
|
||||
*/
|
||||
public static function seemsUtf8($string)
|
||||
public static function camelize($word)
|
||||
{
|
||||
for ($i = 0; $i < strlen($string); $i++) {
|
||||
if (ord($string[$i]) < 0x80) continue; # 0bbbbbbb
|
||||
elseif ((ord($string[$i]) & 0xE0) == 0xC0) $n=1; # 110bbbbb
|
||||
elseif ((ord($string[$i]) & 0xF0) == 0xE0) $n=2; # 1110bbbb
|
||||
elseif ((ord($string[$i]) & 0xF8) == 0xF0) $n=3; # 11110bbb
|
||||
elseif ((ord($string[$i]) & 0xFC) == 0xF8) $n=4; # 111110bb
|
||||
elseif ((ord($string[$i]) & 0xFE) == 0xFC) $n=5; # 1111110b
|
||||
else return false; # Does not match any model
|
||||
for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
|
||||
if ((++$i == strlen($string)) || ((ord($string[$i]) & 0xC0) != 0x80))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any illegal characters, accents, etc.
|
||||
*
|
||||
* @param string $string String to unaccent
|
||||
* @return string $string Unaccented string
|
||||
*/
|
||||
public static function unaccent($string)
|
||||
{
|
||||
if ( ! preg_match('/[\x80-\xff]/', $string) ) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
if (self::seemsUtf8($string)) {
|
||||
$chars = array(
|
||||
// Decompositions for Latin-1 Supplement
|
||||
chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
|
||||
chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
|
||||
chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
|
||||
chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
|
||||
chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
|
||||
chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
|
||||
chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
|
||||
chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
|
||||
chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
|
||||
chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
|
||||
chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
|
||||
chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
|
||||
chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
|
||||
chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
|
||||
chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
|
||||
chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
|
||||
chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
|
||||
chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
|
||||
chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
|
||||
chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
|
||||
chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
|
||||
chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
|
||||
chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
|
||||
chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
|
||||
chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
|
||||
chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
|
||||
chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
|
||||
chr(195).chr(191) => 'y',
|
||||
// Decompositions for Latin Extended-A
|
||||
chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
|
||||
chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
|
||||
chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
|
||||
chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
|
||||
chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
|
||||
chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
|
||||
chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
|
||||
chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
|
||||
chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
|
||||
chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
|
||||
chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
|
||||
chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
|
||||
chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
|
||||
chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
|
||||
chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
|
||||
chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
|
||||
chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
|
||||
chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
|
||||
chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
|
||||
chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
|
||||
chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
|
||||
chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
|
||||
chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
|
||||
chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
|
||||
chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
|
||||
chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
|
||||
chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
|
||||
chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
|
||||
chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
|
||||
chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
|
||||
chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
|
||||
chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
|
||||
chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
|
||||
chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
|
||||
chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
|
||||
chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
|
||||
chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
|
||||
chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
|
||||
chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
|
||||
chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
|
||||
chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
|
||||
chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
|
||||
chr(197).chr(148) => 'R', chr(197).chr(149) => 'r',
|
||||
chr(197).chr(150) => 'R', chr(197).chr(151) => 'r',
|
||||
chr(197).chr(152) => 'R', chr(197).chr(153) => 'r',
|
||||
chr(197).chr(154) => 'S', chr(197).chr(155) => 's',
|
||||
chr(197).chr(156) => 'S', chr(197).chr(157) => 's',
|
||||
chr(197).chr(158) => 'S', chr(197).chr(159) => 's',
|
||||
chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
|
||||
chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
|
||||
chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
|
||||
chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
|
||||
chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
|
||||
chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
|
||||
chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
|
||||
chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
|
||||
chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
|
||||
chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
|
||||
chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
|
||||
chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
|
||||
chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
|
||||
chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
|
||||
chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
|
||||
chr(197).chr(190) => 'z', chr(197).chr(191) => 's',
|
||||
// Euro Sign
|
||||
chr(226).chr(130).chr(172) => 'E',
|
||||
// GBP (Pound) Sign
|
||||
chr(194).chr(163) => '',
|
||||
'Ä' => 'Ae', 'ä' => 'ae', 'Ü' => 'Ue', 'ü' => 'ue',
|
||||
'Ö' => 'Oe', 'ö' => 'oe', 'ß' => 'ss');
|
||||
|
||||
$string = strtr($string, $chars);
|
||||
} else {
|
||||
// Assume ISO-8859-1 if not UTF-8
|
||||
$chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158)
|
||||
.chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194)
|
||||
.chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202)
|
||||
.chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210)
|
||||
.chr(211).chr(212).chr(213).chr(214).chr(216).chr(217).chr(218)
|
||||
.chr(219).chr(220).chr(221).chr(224).chr(225).chr(226).chr(227)
|
||||
.chr(228).chr(229).chr(231).chr(232).chr(233).chr(234).chr(235)
|
||||
.chr(236).chr(237).chr(238).chr(239).chr(241).chr(242).chr(243)
|
||||
.chr(244).chr(245).chr(246).chr(248).chr(249).chr(250).chr(251)
|
||||
.chr(252).chr(253).chr(255);
|
||||
|
||||
$chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy";
|
||||
|
||||
$string = strtr($string, $chars['in'], $chars['out']);
|
||||
$doubleChars['in'] = array(chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254));
|
||||
$doubleChars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th');
|
||||
$string = str_replace($doubleChars['in'], $doubleChars['out'], $string);
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert any passed string to a url friendly string. Converts 'My first blog post' to 'my-first-blog-post'
|
||||
*
|
||||
* @param string $text Text to urlize
|
||||
* @return string $text Urlized text
|
||||
*/
|
||||
public static function urlize($text)
|
||||
{
|
||||
// Remove all non url friendly characters with the unaccent function
|
||||
$text = self::unaccent($text);
|
||||
|
||||
if (function_exists('mb_strtolower'))
|
||||
{
|
||||
$text = mb_strtolower($text);
|
||||
} else {
|
||||
$text = strtolower($text);
|
||||
}
|
||||
|
||||
// Remove all none word characters
|
||||
$text = preg_replace('/\W/', ' ', $text);
|
||||
|
||||
// More stripping. Replace spaces with dashes
|
||||
$text = strtolower(preg_replace('/[^A-Z^a-z^0-9^\/]+/', '-',
|
||||
preg_replace('/([a-z\d])([A-Z])/', '\1_\2',
|
||||
preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1_\2',
|
||||
preg_replace('/::/', '/', $text)))));
|
||||
|
||||
return trim($text, '-');
|
||||
return lcfirst(self::classify($word));
|
||||
}
|
||||
}
|
@ -177,4 +177,10 @@ abstract class Type
|
||||
|
||||
self::$_typesMap[$name] = $className;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
$e = explode('\\', get_class($this));
|
||||
return str_replace('Type', '', end($e));
|
||||
}
|
||||
}
|
158
lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php
Normal file
158
lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\Common\DoctrineException,
|
||||
Doctrine\Common\Cache\ArrayCache,
|
||||
Doctrine\Common\Annotations\AnnotationReader,
|
||||
Doctrine\DBAL\Schema\AbstractSchemaManager,
|
||||
Doctrine\ORM\Mapping\ClassMetadataInfo,
|
||||
Doctrine\ORM\Mapping\MappingException,
|
||||
Doctrine\Common\Util\Inflector;
|
||||
|
||||
/**
|
||||
* The DatabaseDriver reverse engineers the mapping metadata from a database
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class DatabaseDriver implements Driver
|
||||
{
|
||||
/** The SchemaManager. */
|
||||
private $_sm;
|
||||
|
||||
/**
|
||||
* Initializes a new AnnotationDriver that uses the given AnnotationReader for reading
|
||||
* docblock annotations.
|
||||
*
|
||||
* @param AnnotationReader $reader The AnnotationReader to use.
|
||||
*/
|
||||
public function __construct(AbstractSchemaManager $schemaManager)
|
||||
{
|
||||
$this->_sm = $schemaManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadMetadataForClass($className, ClassMetadataInfo $metadata)
|
||||
{
|
||||
$tableName = $className;
|
||||
$className = Inflector::classify($tableName);
|
||||
|
||||
$metadata->name = $className;
|
||||
$metadata->primaryTable['name'] = $tableName;
|
||||
|
||||
$columns = $this->_sm->listTableColumns($tableName);
|
||||
$foreignKeys = $this->_sm->listTableForeignKeys($tableName);
|
||||
|
||||
$ids = array();
|
||||
$fieldMappings = array();
|
||||
foreach ($columns as $column) {
|
||||
// Skip columns that are foreign keys
|
||||
foreach ($foreignKeys as $foreignKey) {
|
||||
if ($column['name'] == $foreignKey['local']) {
|
||||
continue(2);
|
||||
}
|
||||
}
|
||||
|
||||
$fieldMapping = array();
|
||||
if ($column['primary']) {
|
||||
$fieldMapping['id'] = true;
|
||||
}
|
||||
|
||||
$fieldMapping['fieldName'] = Inflector::camelize($column['name']);
|
||||
$fieldMapping['columnName'] = $column['name'];
|
||||
$fieldMapping['type'] = strtolower((string) $column['type']);
|
||||
$fieldMapping['length'] = $column['length'];
|
||||
$fieldMapping['unsigned'] = $column['unsigned'];
|
||||
$fieldMapping['fixed'] = $column['fixed'];
|
||||
$fieldMapping['notnull'] = $column['notnull'];
|
||||
$fieldMapping['default'] = $column['default'];
|
||||
|
||||
if (isset($fieldMapping['id'])) {
|
||||
$ids[] = $fieldMapping;
|
||||
} else {
|
||||
$fieldMappings[] = $fieldMapping;
|
||||
}
|
||||
}
|
||||
|
||||
if ($ids) {
|
||||
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$metadata->mapField($id);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($fieldMappings as $fieldMapping) {
|
||||
$metadata->mapField($fieldMapping);
|
||||
}
|
||||
|
||||
foreach ($foreignKeys as $foreignKey) {
|
||||
$associationMapping = array();
|
||||
$associationMapping['fieldName'] = Inflector::camelize(str_replace('_id', '', $foreignKey['local']));
|
||||
$associationMapping['columnName'] = $foreignKey['local'];
|
||||
$associationMapping['targetEntity'] = Inflector::classify($foreignKey['table']);
|
||||
$associationMapping['joinColumns'][] = array(
|
||||
'name' => $foreignKey['local'],
|
||||
'referencedColumnName' => $foreignKey['foreign']
|
||||
);
|
||||
|
||||
$metadata->mapManyToOne($associationMapping);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the class with the specified name should have its metadata loaded.
|
||||
* This is only the case if it is either mapped as an Entity or a
|
||||
* MappedSuperclass.
|
||||
*
|
||||
* @param string $className
|
||||
* @return boolean
|
||||
*/
|
||||
public function isTransient($className)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preloads all mapping information found in any documents within the
|
||||
* configured paths and returns a list of class names that have been preloaded.
|
||||
*
|
||||
* @return array The list of class names that have been preloaded.
|
||||
*/
|
||||
public function preload()
|
||||
{
|
||||
$tables = array();
|
||||
foreach ($this->_sm->listTables() as $table) {
|
||||
$tables[] = $table;
|
||||
}
|
||||
|
||||
return $tables;
|
||||
}
|
||||
}
|
@ -149,39 +149,49 @@ class YamlDriver extends AbstractFileDriver
|
||||
// Evaluate fields
|
||||
if (isset($element['fields'])) {
|
||||
foreach ($element['fields'] as $name => $fieldMapping) {
|
||||
$e = explode('(', $fieldMapping['type']);
|
||||
$fieldMapping['type'] = $e[0];
|
||||
if (isset($e[1])) {
|
||||
$fieldMapping['length'] = substr($e[1], 0, strlen($e[1]) - 1);
|
||||
}
|
||||
$mapping = array(
|
||||
'fieldName' => $name,
|
||||
'type' => $fieldMapping['type']
|
||||
);
|
||||
|
||||
if (isset($fieldMapping['id'])) {
|
||||
$mapping['id'] = true;
|
||||
if (isset($fieldMapping['generator']['strategy'])) {
|
||||
$metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_'
|
||||
. strtoupper($fieldMapping['generator']['strategy'])));
|
||||
}
|
||||
}
|
||||
// Check for SequenceGenerator/TableGenerator definition
|
||||
if (isset($fieldMapping['sequenceGenerator'])) {
|
||||
$metadata->setSequenceGeneratorDefinition($fieldMapping['sequenceGenerator']);
|
||||
} else if (isset($fieldMapping['tableGenerator'])) {
|
||||
throw DoctrineException::tableIdGeneratorNotImplemented();
|
||||
}
|
||||
if (isset($fieldMapping['column'])) {
|
||||
$mapping['columnName'] = $fieldMapping['column'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['length'])) {
|
||||
$mapping['length'] = $fieldMapping['length'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['precision'])) {
|
||||
$mapping['precision'] = $fieldMapping['precision'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['scale'])) {
|
||||
$mapping['scale'] = $fieldMapping['scale'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['unique'])) {
|
||||
$mapping['unique'] = (bool)$fieldMapping['unique'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['options'])) {
|
||||
$mapping['options'] = $fieldMapping['options'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['notnull'])) {
|
||||
$mapping['notnull'] = $fieldMapping['notnull'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['version']) && $fieldMapping['version']) {
|
||||
$metadata->setVersionMapping($mapping);
|
||||
}
|
||||
|
@ -101,6 +101,10 @@ class ConvertMappingTask extends AbstractTask
|
||||
$printer->writeln('You can only use the --extend argument when converting to annoations.');
|
||||
return false;
|
||||
}
|
||||
if ($args['from'][0] == 'database') {
|
||||
$config = $this->_em->getConfiguration();
|
||||
$config->setMetadataDriverImpl(new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($this->_em->getConnection()->getSchemaManager()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -127,47 +131,83 @@ class ConvertMappingTask extends AbstractTask
|
||||
$printer->writeln('Converting Doctrine 1 schema to Doctrine 2 mapping files', 'INFO');
|
||||
|
||||
$converter = new \Doctrine\ORM\Tools\ConvertDoctrine1Schema($from);
|
||||
$exporter->setMetadatas($converter->getMetadatasFromSchema());
|
||||
$metadatas = $converter->getMetadatasFromSchema();
|
||||
} else {
|
||||
foreach ($from as $path) {
|
||||
$type = $this->_determinePathType($path);
|
||||
foreach ($from as $source) {
|
||||
$sourceArg = $source;
|
||||
|
||||
$printer->writeln(sprintf('Adding %s mapping directory: "%s"', $type, $path), 'INFO');
|
||||
$type = $this->_determineSourceType($sourceArg);
|
||||
$source = $this->_getSourceByType($type, $sourceArg);
|
||||
|
||||
$cme->addMappingDir($path, $type);
|
||||
$printer->writeln(sprintf('Adding "%s" mapping source', $sourceArg), 'INFO');
|
||||
|
||||
$cme->addMappingSource($source, $type);
|
||||
}
|
||||
$exporter->setMetadatas($cme->getMetadatasForMappingDirectories());
|
||||
$metadatas = $cme->getMetadatasForMappingSources();
|
||||
}
|
||||
|
||||
$printer->writeln(sprintf('Exporting %s mapping information to directory: "%s"', $args['to'], $args['dest']), 'INFO');
|
||||
foreach ($metadatas as $metadata) {
|
||||
$printer->write('Processing entity "')
|
||||
->write($metadata->name, 'KEYWORD')->writeln('"');
|
||||
}
|
||||
|
||||
$printer->writeln(sprintf('Exporting %s mapping information to directory "%s"', $args['to'], $args['dest']), 'INFO');
|
||||
|
||||
$exporter->setMetadatas($metadatas);
|
||||
$exporter->export();
|
||||
}
|
||||
|
||||
private function _isDoctrine1Schema(array $from)
|
||||
{
|
||||
$files = glob($from[0] . '/*.yml');
|
||||
$files = glob(current($from) . '/*.yml');
|
||||
if ($files) {
|
||||
$array = \sfYaml::load($files[0]);
|
||||
$first = current($array);
|
||||
// We're dealing with a Doctrine 1 schema if you have
|
||||
// a columns index in the first model array
|
||||
return isset($first['columns']);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function _determinePathType($path)
|
||||
private function _determineSourceType($source)
|
||||
{
|
||||
$files = glob($path . '/*.*');
|
||||
if (!$files)
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('No schema mapping files found in "%s"', $path));
|
||||
}
|
||||
$contents = file_get_contents($files[0]);
|
||||
if (preg_match("/class (.*)/", $contents)) {
|
||||
return 'annotation';
|
||||
} else {
|
||||
$info = pathinfo($files[0]);
|
||||
return $info['extension'];
|
||||
}
|
||||
// If the --from=<VALUE> is a directory lets determine if it is
|
||||
// annotations, yaml, xml, etc.
|
||||
if (is_dir($source)) {
|
||||
// Find the files in the directory
|
||||
$files = glob($source . '/*.*');
|
||||
if ( ! $files) {
|
||||
throw new \InvalidArgumentException(sprintf('No mapping files found in "%s"', $source));
|
||||
}
|
||||
|
||||
// Get the contents of the first file
|
||||
$contents = file_get_contents($files[0]);
|
||||
|
||||
// Check if it has a class definition in it for annotations
|
||||
if (preg_match("/class (.*)/", $contents)) {
|
||||
return 'annotation';
|
||||
// Otherwise lets determine the type based on the extension of the
|
||||
// first file in the directory (yml, xml, etc)
|
||||
} else {
|
||||
$info = pathinfo($files[0]);
|
||||
return $info['extension'];
|
||||
}
|
||||
// Nothing special for database
|
||||
} else if ($source == 'database') {
|
||||
return 'database';
|
||||
}
|
||||
}
|
||||
|
||||
private function _getSourceByType($type, $source)
|
||||
{
|
||||
// If --from==database then the source is an instance of SchemaManager
|
||||
// for the current EntityMAnager
|
||||
if ($type == 'database') {
|
||||
return $this->_em->getConnection()->getSchemaManager();
|
||||
} else {
|
||||
return $source;
|
||||
}
|
||||
}
|
||||
}
|
@ -110,8 +110,8 @@ class SchemaToolTask extends AbstractTask
|
||||
$isDrop = isset($args['drop']);
|
||||
$isUpdate = isset($args['update']);
|
||||
|
||||
if ( ! ($isCreate ^ $isDrop ^ $isUpdate)) {
|
||||
$printer->writeln("One of --create, --drop or --update required, and only one.", 'ERROR');
|
||||
if ($isUpdate && ($isCreate || $isDrop)) {
|
||||
$printer->writeln("You can't use --update with --create or --drop", 'ERROR');
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -174,7 +174,24 @@ class SchemaToolTask extends AbstractTask
|
||||
$printer->writeln('No classes to process.', 'INFO');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ($isDrop) {
|
||||
if (isset($args['dump-sql'])) {
|
||||
foreach ($tool->getDropSchemaSql($classes) as $sql) {
|
||||
$printer->writeln($sql);
|
||||
}
|
||||
} else {
|
||||
$printer->writeln('Dropping database schema...', 'INFO');
|
||||
|
||||
try {
|
||||
$tool->dropSchema($classes);
|
||||
$printer->writeln('Database schema dropped successfully.', 'INFO');
|
||||
} catch (\Exception $ex) {
|
||||
throw new DoctrineException($ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($isCreate) {
|
||||
if (isset($args['dump-sql'])) {
|
||||
foreach ($tool->getCreateSchemaSql($classes) as $sql) {
|
||||
@ -190,24 +207,9 @@ class SchemaToolTask extends AbstractTask
|
||||
throw new DoctrineException($ex);
|
||||
}
|
||||
}
|
||||
} else if ($isDrop) {
|
||||
if (isset($args['dump-sql'])) {
|
||||
foreach ($tool->getDropSchemaSql($classes) as $sql) {
|
||||
$printer->writeln($sql);
|
||||
}
|
||||
} else {
|
||||
$printer->writeln('Dropping database schema...', 'INFO');
|
||||
|
||||
try {
|
||||
$tool->dropSchema($classes);
|
||||
$printer->writeln('Database schema dropped successfully.', 'INFO');
|
||||
} catch (\Exception $ex) {
|
||||
throw new DoctrineException($ex);
|
||||
}
|
||||
}
|
||||
} else if ($isUpdate) {
|
||||
$printer->writeln("--update support is not yet fully implemented.", 'ERROR');
|
||||
|
||||
}
|
||||
|
||||
if ($isUpdate) {
|
||||
if (isset($args['dump-sql'])) {
|
||||
foreach ($tool->getUpdateSchemaSql($classes) as $sql) {
|
||||
$printer->writeln($sql);
|
||||
|
@ -35,14 +35,14 @@ use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
* // and convert it to a single set of yaml files.
|
||||
*
|
||||
* $cme = new Doctrine\ORM\Tools\Export\ClassMetadataExporter();
|
||||
* $cme->addMappingDirectory(__DIR__ . '/Entities', 'php');
|
||||
* $cme->addMappingDirectory(__DIR__ . '/xml', 'xml');
|
||||
* $cme->addMappingDirectory(__DIR__ . '/yaml', 'yaml');
|
||||
* $cme->addMappingSource(__DIR__ . '/Entities', 'php');
|
||||
* $cme->addMappingSource(__DIR__ . '/xml', 'xml');
|
||||
* $cme->addMappingSource(__DIR__ . '/yaml', 'yaml');
|
||||
*
|
||||
* $exporter = $cme->getExporter('yaml');
|
||||
* $exporter->setOutputDir(__DIR__ . '/new_yaml');
|
||||
*
|
||||
* $exporter->setMetadatas($cme->getMetadatasForMappingDirectories());
|
||||
* $exporter->setMetadatas($cme->getMetadatasForMappingSources());
|
||||
* $exporter->export();
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
@ -65,10 +65,11 @@ class ClassMetadataExporter
|
||||
'annotation' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
|
||||
'yaml' => 'Doctrine\ORM\Mapping\Driver\YamlDriver',
|
||||
'yml' => 'Doctrine\ORM\Mapping\Driver\YamlDriver',
|
||||
'xml' => 'Doctrine\ORM\Mapping\Driver\XmlDriver'
|
||||
'xml' => 'Doctrine\ORM\Mapping\Driver\XmlDriver',
|
||||
'database' => 'Doctrine\ORM\Mapping\Driver\DatabaseDriver'
|
||||
);
|
||||
|
||||
private $_mappingDirectories = array();
|
||||
private $_mappingSources = array();
|
||||
|
||||
/**
|
||||
* Add a new mapping directory to the array of directories to convert and export
|
||||
@ -76,23 +77,24 @@ class ClassMetadataExporter
|
||||
*
|
||||
* [php]
|
||||
* $cme = new Doctrine\ORM\Tools\Export\ClassMetadataExporter();
|
||||
* $cme->addMappingDirectory(__DIR__ . '/yaml', 'yaml');
|
||||
* $cme->addMappingSource(__DIR__ . '/yaml', 'yaml');
|
||||
* $cme->addMappingSource($schemaManager, 'database');
|
||||
*
|
||||
* @param string $dir The path to the mapping files
|
||||
* @param string $source The source for the mapping
|
||||
* @param string $type The type of mapping files (yml, xml, etc.)
|
||||
* @return void
|
||||
*/
|
||||
public function addMappingDirectory($dir, $type)
|
||||
public function addMappingSource($source, $type)
|
||||
{
|
||||
if ($type === 'php') {
|
||||
$this->_mappingDirectories[] = array($dir, $type);
|
||||
$this->_mappingSources[] = array($source, $type);
|
||||
} else {
|
||||
if ( ! isset($this->_mappingDrivers[$type])) {
|
||||
throw DoctrineException::invalidMappingDriverType($type);
|
||||
}
|
||||
|
||||
$driver = $this->getMappingDriver($type, $dir);
|
||||
$this->_mappingDirectories[] = array($dir, $driver);
|
||||
$driver = $this->getMappingDriver($type, $source);
|
||||
$this->_mappingSources[] = array($source, $driver);
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,24 +102,26 @@ class ClassMetadataExporter
|
||||
* Get an instance of a mapping driver
|
||||
*
|
||||
* @param string $type The type of mapping driver (yaml, xml, annotation, etc.)
|
||||
* @param string $dir The directory to configure the driver to look in. Only required for file drivers (yml, xml).
|
||||
* @param string $source The source for the driver
|
||||
* @return AbstractDriver $driver
|
||||
*/
|
||||
public function getMappingDriver($type, $dir = null)
|
||||
public function getMappingDriver($type, $source = null)
|
||||
{
|
||||
if ( ! isset($this->_mappingDrivers[$type])) {
|
||||
return false;
|
||||
}
|
||||
$class = $this->_mappingDrivers[$type];
|
||||
if (is_subclass_of($class, 'Doctrine\ORM\Mapping\Driver\AbstractFileDriver')) {
|
||||
if (is_null($dir)) {
|
||||
if (is_null($source)) {
|
||||
throw DoctrineException::fileMappingDriversRequireDirectoryPath();
|
||||
}
|
||||
$driver = new $class($dir, constant($class . '::PRELOAD'));
|
||||
} else {
|
||||
$driver = new $class($source, constant($class . '::PRELOAD'));
|
||||
} else if ($class == 'Doctrine\ORM\Mapping\Driver\AnnotationDriver') {
|
||||
$reader = new \Doctrine\Common\Annotations\AnnotationReader(new \Doctrine\Common\Cache\ArrayCache);
|
||||
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
|
||||
$driver = new $class($reader);
|
||||
$driver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader);
|
||||
} else if ($class == 'Doctrine\ORM\Mapping\Driver\DatabaseDriver') {
|
||||
$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($source);
|
||||
}
|
||||
return $driver;
|
||||
}
|
||||
@ -127,9 +131,9 @@ class ClassMetadataExporter
|
||||
*
|
||||
* @return array $mappingDirectories
|
||||
*/
|
||||
public function getMappingDirectories()
|
||||
public function getMappingSources()
|
||||
{
|
||||
return $this->_mappingDirectories;
|
||||
return $this->_mappingSources;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,14 +143,14 @@ class ClassMetadataExporter
|
||||
*
|
||||
* @return array $classes
|
||||
*/
|
||||
public function getMetadatasForMappingDirectories()
|
||||
public function getMetadatasForMappingSources()
|
||||
{
|
||||
$classes = array();
|
||||
|
||||
foreach ($this->_mappingDirectories as $d) {
|
||||
list($dir, $driver) = $d;
|
||||
foreach ($this->_mappingSources as $d) {
|
||||
list($source, $driver) = $d;
|
||||
if ($driver == 'php') {
|
||||
$iter = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir),
|
||||
$iter = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY);
|
||||
|
||||
foreach ($iter as $item) {
|
||||
@ -164,7 +168,7 @@ class ClassMetadataExporter
|
||||
}
|
||||
} else {
|
||||
if ($driver instanceof \Doctrine\ORM\Mapping\Driver\AnnotationDriver) {
|
||||
$iter = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir),
|
||||
$iter = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY);
|
||||
|
||||
$declared = get_declared_classes();
|
||||
@ -200,7 +204,6 @@ class ClassMetadataExporter
|
||||
unset($classes[$key]);
|
||||
}
|
||||
}
|
||||
$classes = array_values($classes);
|
||||
return $classes;
|
||||
}
|
||||
|
||||
@ -208,16 +211,16 @@ class ClassMetadataExporter
|
||||
* Get a exporter driver instance
|
||||
*
|
||||
* @param string $type The type to get (yml, xml, etc.)
|
||||
* @param string $dir The directory where the exporter will export to
|
||||
* @param string $source The directory where the exporter will export to
|
||||
* @return AbstractExporter $exporter
|
||||
*/
|
||||
public function getExporter($type, $dir = null)
|
||||
public function getExporter($type, $source = null)
|
||||
{
|
||||
if ( ! isset($this->_exporterDrivers[$type])) {
|
||||
throw DoctrineException::invalidExporterDriverType($type);
|
||||
}
|
||||
|
||||
$class = $this->_exporterDrivers[$type];
|
||||
return new $class($dir);
|
||||
return new $class($source);
|
||||
}
|
||||
}
|
@ -250,7 +250,10 @@ class AnnotationExporter extends AbstractExporter
|
||||
$methods = array();
|
||||
|
||||
foreach ($metadata->fieldMappings as $fieldMapping) {
|
||||
$this->_addMethod('set', $fieldMapping['fieldName'], $metadata, $methods);
|
||||
if ( ! isset($fieldMapping['id']) || ! $fieldMapping['id']) {
|
||||
$this->_addMethod('set', $fieldMapping['fieldName'], $metadata, $methods);
|
||||
}
|
||||
|
||||
$this->_addMethod('get', $fieldMapping['fieldName'], $metadata, $methods);
|
||||
}
|
||||
|
||||
@ -302,6 +305,9 @@ class AnnotationExporter extends AbstractExporter
|
||||
$lines[] = str_repeat(' ', $this->_numSpaces) . '/**';
|
||||
|
||||
$column = array();
|
||||
if (isset($fieldMapping['columnName'])) {
|
||||
$column[] = 'name="' . $fieldMapping['columnName'] . '"';
|
||||
}
|
||||
if (isset($fieldMapping['type'])) {
|
||||
$column[] = 'type="' . $fieldMapping['type'] . '"';
|
||||
}
|
||||
|
@ -145,11 +145,14 @@ class XmlExporter extends AbstractExporter
|
||||
if (isset($field['scale'])) {
|
||||
$fieldXml->addAttribute('scale', $field['scale']);
|
||||
}
|
||||
if (isset($field['unique'])) {
|
||||
if (isset($field['unique']) && $field['unique']) {
|
||||
$fieldXml->addAttribute('unique', $field['unique']);
|
||||
}
|
||||
if (isset($field['options'])) {
|
||||
$fieldXml->addAttribute('options', $field['options']);
|
||||
$optionsXml = $fieldXml->addChild('options');
|
||||
foreach ($field['options'] as $key => $value) {
|
||||
$optionsXml->addAttribute($key, $value);
|
||||
}
|
||||
}
|
||||
if (isset($field['version'])) {
|
||||
$fieldXml->addAttribute('version', $field['version']);
|
||||
@ -225,6 +228,51 @@ class XmlExporter extends AbstractExporter
|
||||
}
|
||||
}
|
||||
|
||||
return $xml->asXml();
|
||||
return $this->_asXml($xml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Code originally taken from
|
||||
* http://recurser.com/articles/2007/04/05/format-xml-with-php/
|
||||
*
|
||||
* @param string $simpleXml
|
||||
* @return string $xml
|
||||
*/
|
||||
private function _asXml($simpleXml)
|
||||
{
|
||||
$xml = $simpleXml->asXml();
|
||||
|
||||
// add marker linefeeds to aid the pretty-tokeniser (adds a linefeed between all tag-end boundaries)
|
||||
$xml = preg_replace('/(>)(<)(\/*)/', "$1\n$2$3", $xml);
|
||||
|
||||
// now indent the tags
|
||||
$token = strtok($xml, "\n");
|
||||
$result = ''; // holds formatted version as it is built
|
||||
$pad = 0; // initial indent
|
||||
$matches = array(); // returns from preg_matches()
|
||||
|
||||
// test for the various tag states
|
||||
while ($token !== false) {
|
||||
// 1. open and closing tags on same line - no change
|
||||
if (preg_match('/.+<\/\w[^>]*>$/', $token, $matches)) {
|
||||
$indent = 0;
|
||||
// 2. closing tag - outdent now
|
||||
} else if (preg_match('/^<\/\w/', $token, $matches)) {
|
||||
$pad = $pad - 4;
|
||||
// 3. opening tag - don't pad this one, only subsequent tags
|
||||
} elseif (preg_match('/^<\w[^>]*[^\/]>.*$/', $token, $matches)) {
|
||||
$indent = 4;
|
||||
// 4. no indentation needed
|
||||
} else {
|
||||
$indent = 0;
|
||||
}
|
||||
|
||||
// pad the line with the required number of leading spaces
|
||||
$line = str_pad($token, strlen($token)+$pad, ' ', STR_PAD_LEFT);
|
||||
$result .= $line . "\n"; // add to the cumulative result, with linefeed
|
||||
$token = strtok("\n"); // get the next token
|
||||
$pad += $indent; // update the pad size for subsequent lines
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -70,7 +70,10 @@ class YamlExporter extends AbstractExporter
|
||||
$array['schema'] = $metadata->primaryTable['schema'];
|
||||
}
|
||||
|
||||
$array['inheritanceType'] = $this->_getInheritanceTypeString($metadata->getInheritanceType());
|
||||
$inheritanceType = $metadata->getInheritanceType();
|
||||
if ($inheritanceType !== ClassMetadataInfo::INHERITANCE_TYPE_NONE) {
|
||||
$array['inheritanceType'] = $this->_getInheritanceTypeString($inheritanceType);
|
||||
}
|
||||
|
||||
if ($column = $metadata->getDiscriminatorColumn()) {
|
||||
$array['discriminatorColumn'] = $column;
|
||||
@ -80,7 +83,9 @@ class YamlExporter extends AbstractExporter
|
||||
$array['discriminatorMap'] = $map;
|
||||
}
|
||||
|
||||
$array['changeTrackingPolicy'] = $this->_getChangeTrackingPolicyString($metadata->changeTrackingPolicy);
|
||||
if ($metadata->changeTrackingPolicy !== ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT) {
|
||||
$array['changeTrackingPolicy'] = $this->_getChangeTrackingPolicyString($metadata->changeTrackingPolicy);
|
||||
}
|
||||
|
||||
if (isset($metadata->primaryTable['indexes'])) {
|
||||
$array['indexes'] = $metadata->primaryTable['indexes'];
|
||||
@ -92,27 +97,48 @@ class YamlExporter extends AbstractExporter
|
||||
}
|
||||
}
|
||||
|
||||
$fields = $metadata->fieldMappings;
|
||||
$fieldMappings = $metadata->fieldMappings;
|
||||
|
||||
$id = array();
|
||||
foreach ($fields as $name => $field) {
|
||||
if (isset($field['id']) && $field['id']) {
|
||||
$id[$name] = $field;
|
||||
unset($fields[$name]);
|
||||
$ids = array();
|
||||
foreach ($fieldMappings as $name => $fieldMapping) {
|
||||
if (isset($fieldMapping['length'])) {
|
||||
$fieldMapping['type'] = $fieldMapping['type'] . '(' . $fieldMapping['length'] . ')';
|
||||
unset($fieldMapping['length']);
|
||||
}
|
||||
|
||||
unset($fieldMapping['fieldName']);
|
||||
|
||||
if ($fieldMapping['columnName'] == $name) {
|
||||
unset($fieldMapping['columnName']);
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['id']) && $fieldMapping['id']) {
|
||||
$ids[$name] = $fieldMapping;
|
||||
unset($fieldMappings[$name]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$fieldMappings[$name] = $fieldMapping;
|
||||
}
|
||||
|
||||
if ($idGeneratorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) {
|
||||
$id[$metadata->getSingleIdentifierFieldName()]['generator']['strategy'] = $this->_getIdGeneratorTypeString($metadata->generatorType);
|
||||
$ids[$metadata->getSingleIdentifierFieldName()]['generator']['strategy'] = $this->_getIdGeneratorTypeString($metadata->generatorType);
|
||||
}
|
||||
|
||||
$array['id'] = $id;
|
||||
$array['fields'] = $fields;
|
||||
if ($ids) {
|
||||
$array['fields'] = $ids;
|
||||
}
|
||||
|
||||
if ($fieldMappings) {
|
||||
if ( ! isset($array['fields'])) {
|
||||
$array['fields'] = array();
|
||||
}
|
||||
$array['fields'] = array_merge($array['fields'], $fieldMappings);
|
||||
}
|
||||
|
||||
$associations = array();
|
||||
foreach ($metadata->associationMappings as $name => $associationMapping) {
|
||||
$associationMappingArray = array(
|
||||
'fieldName' => $associationMapping->sourceFieldName,
|
||||
'targetEntity' => $associationMapping->targetEntityName,
|
||||
'cascade' => array(
|
||||
'remove' => $associationMapping->isCascadeRemove,
|
||||
@ -124,9 +150,14 @@ class YamlExporter extends AbstractExporter
|
||||
);
|
||||
|
||||
if ($associationMapping instanceof OneToOneMapping) {
|
||||
$joinColumns = $associationMapping->joinColumns;
|
||||
$newJoinColumns = array();
|
||||
foreach ($joinColumns as $joinColumn) {
|
||||
$newJoinColumns[$joinColumn['name']]['referencedColumnName'] = $joinColumn['referencedColumnName'];
|
||||
}
|
||||
$oneToOneMappingArray = array(
|
||||
'mappedBy' => $associationMapping->mappedByFieldName,
|
||||
'joinColumns' => $associationMapping->joinColumns,
|
||||
'joinColumns' => $newJoinColumns,
|
||||
'orphanRemoval' => $associationMapping->orphanRemoval,
|
||||
);
|
||||
|
||||
@ -137,7 +168,7 @@ class YamlExporter extends AbstractExporter
|
||||
'mappedBy' => $associationMapping->mappedByFieldName,
|
||||
'orphanRemoval' => $associationMapping->orphanRemoval,
|
||||
);
|
||||
|
||||
|
||||
$associationMappingArray = array_merge($associationMappingArray, $oneToManyMappingArray);
|
||||
$array['oneToMany'][$name] = $associationMappingArray;
|
||||
} else if ($associationMapping instanceof ManyToManyMapping) {
|
||||
|
@ -50,19 +50,19 @@ class ConvertDoctrine1SchemaTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertTrue(file_exists(__DIR__ . '/convert/User.dcm.yml'));
|
||||
$this->assertTrue(file_exists(__DIR__ . '/convert/Profile.dcm.yml'));
|
||||
|
||||
$cme->addMappingDirectory(__DIR__ . '/convert', 'yml');
|
||||
$metadatas = $cme->getMetadatasForMappingDirectories();
|
||||
$cme->addMappingSource(__DIR__ . '/convert', 'yml');
|
||||
$metadatas = $cme->getMetadatasForMappingSources();
|
||||
|
||||
$this->assertEquals(2, count($metadatas));
|
||||
$this->assertEquals('Profile', $metadatas[0]->name);
|
||||
$this->assertEquals('User', $metadatas[1]->name);
|
||||
$this->assertEquals(4, count($metadatas[0]->fieldMappings));
|
||||
$this->assertEquals(3, count($metadatas[1]->fieldMappings));
|
||||
$this->assertEquals('Profile', $metadatas['Profile']->name);
|
||||
$this->assertEquals('User', $metadatas['User']->name);
|
||||
$this->assertEquals(4, count($metadatas['Profile']->fieldMappings));
|
||||
$this->assertEquals(3, count($metadatas['User']->fieldMappings));
|
||||
|
||||
$this->assertEquals('Profile', $metadatas[0]->associationMappings['User']->sourceEntityName);
|
||||
$this->assertEquals('\User', $metadatas[0]->associationMappings['User']->targetEntityName);
|
||||
$this->assertEquals('Profile', $metadatas['Profile']->associationMappings['User']->sourceEntityName);
|
||||
$this->assertEquals('\User', $metadatas['Profile']->associationMappings['User']->targetEntityName);
|
||||
|
||||
$this->assertEquals('username', $metadatas[1]->primaryTable['indexes']['username']['columns'][0]);
|
||||
$this->assertEquals('username', $metadatas['User']->primaryTable['indexes']['username']['columns'][0]);
|
||||
|
||||
unlink(__DIR__ . '/convert/User.dcm.yml');
|
||||
unlink(__DIR__ . '/convert/Profile.dcm.yml');
|
||||
|
@ -61,25 +61,25 @@ class ClassMetadataExporterTest extends \Doctrine\Tests\OrmTestCase
|
||||
public function testAddMappingDirectory()
|
||||
{
|
||||
$cme = new ClassMetadataExporter();
|
||||
$cme->addMappingDirectory(__DIR__ . '/annotation', 'annotation');
|
||||
$cme->addMappingDirectory(__DIR__ . '/php', 'php');
|
||||
$cme->addMappingDirectory(__DIR__ . '/xml', 'xml');
|
||||
$cme->addMappingDirectory(__DIR__ . '/yml', 'yml');
|
||||
$cme->addMappingSource(__DIR__ . '/annotation', 'annotation');
|
||||
$cme->addMappingSource(__DIR__ . '/php', 'php');
|
||||
$cme->addMappingSource(__DIR__ . '/xml', 'xml');
|
||||
$cme->addMappingSource(__DIR__ . '/yml', 'yml');
|
||||
|
||||
$mappingDirectories = $cme->getMappingDirectories();
|
||||
$this->assertEquals(4, count($mappingDirectories));
|
||||
$mappingSources = $cme->getMappingSources();
|
||||
$this->assertEquals(4, count($mappingSources));
|
||||
|
||||
$this->assertEquals($mappingDirectories[0][0], __DIR__.'/annotation');
|
||||
$this->assertTrue($mappingDirectories[0][1] instanceof \Doctrine\ORM\Mapping\Driver\AnnotationDriver);
|
||||
$this->assertEquals($mappingSources[0][0], __DIR__.'/annotation');
|
||||
$this->assertTrue($mappingSources[0][1] instanceof \Doctrine\ORM\Mapping\Driver\AnnotationDriver);
|
||||
|
||||
$this->assertEquals($mappingDirectories[1][0], __DIR__.'/php');
|
||||
$this->assertEquals('php', $mappingDirectories[1][1]);
|
||||
$this->assertEquals($mappingSources[1][0], __DIR__.'/php');
|
||||
$this->assertEquals('php', $mappingSources[1][1]);
|
||||
|
||||
$this->assertEquals($mappingDirectories[2][0], __DIR__.'/xml');
|
||||
$this->assertTrue($mappingDirectories[2][1] instanceof \Doctrine\ORM\Mapping\Driver\XmlDriver);
|
||||
$this->assertEquals($mappingSources[2][0], __DIR__.'/xml');
|
||||
$this->assertTrue($mappingSources[2][1] instanceof \Doctrine\ORM\Mapping\Driver\XmlDriver);
|
||||
|
||||
$this->assertEquals($mappingDirectories[3][0], __DIR__.'/yml');
|
||||
$this->assertTrue($mappingDirectories[3][1] instanceof \Doctrine\ORM\Mapping\Driver\YamlDriver);
|
||||
$this->assertEquals($mappingSources[3][0], __DIR__.'/yml');
|
||||
$this->assertTrue($mappingSources[3][1] instanceof \Doctrine\ORM\Mapping\Driver\YamlDriver);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,16 +89,16 @@ class ClassMetadataExporterTest extends \Doctrine\Tests\OrmTestCase
|
||||
public function testGetMetadataInstances()
|
||||
{
|
||||
$cme = new ClassMetadataExporter();
|
||||
$cme->addMappingDirectory(__DIR__ . '/php', 'php');
|
||||
$cme->addMappingDirectory(__DIR__ . '/xml', 'xml');
|
||||
$cme->addMappingDirectory(__DIR__ . '/yml', 'yml');
|
||||
$cme->addMappingSource(__DIR__ . '/php', 'php');
|
||||
$cme->addMappingSource(__DIR__ . '/xml', 'xml');
|
||||
$cme->addMappingSource(__DIR__ . '/yml', 'yml');
|
||||
|
||||
$metadataInstances = $cme->getMetadatasForMappingDirectories();
|
||||
$metadataInstances = $cme->getMetadatasForMappingSources();
|
||||
|
||||
$this->assertEquals(3, count($metadataInstances));
|
||||
$this->assertEquals('PhpTest', $metadataInstances[0]->name);
|
||||
$this->assertEquals('XmlTest', $metadataInstances[1]->name);
|
||||
$this->assertEquals('YmlTest', $metadataInstances[2]->name);
|
||||
$this->assertEquals('PhpTest', $metadataInstances['PhpTest']->name);
|
||||
$this->assertEquals('XmlTest', $metadataInstances['XmlTest']->name);
|
||||
$this->assertEquals('YmlTest', $metadataInstances['YmlTest']->name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,14 +116,14 @@ class ClassMetadataExporterTest extends \Doctrine\Tests\OrmTestCase
|
||||
$types = array('annotation', 'php', 'xml', 'yml');
|
||||
|
||||
$cme = new ClassMetadataExporter();
|
||||
$cme->addMappingDirectory(__DIR__ . '/php', 'php');
|
||||
$cme->addMappingDirectory(__DIR__ . '/xml', 'xml');
|
||||
$cme->addMappingDirectory(__DIR__ . '/yml', 'yml');
|
||||
$cme->addMappingSource(__DIR__ . '/php', 'php');
|
||||
$cme->addMappingSource(__DIR__ . '/xml', 'xml');
|
||||
$cme->addMappingSource(__DIR__ . '/yml', 'yml');
|
||||
|
||||
foreach ($types as $type) {
|
||||
// Export the above mapping directories to the type
|
||||
$exporter = $cme->getExporter($type, __DIR__ . '/export/' . $type);
|
||||
$exporter->setMetadatas($cme->getMetadatasForMappingDirectories());
|
||||
$exporter->setMetadatas($cme->getMetadatasForMappingSources());
|
||||
$exporter->export();
|
||||
|
||||
// Make sure the files were written
|
||||
@ -133,12 +133,12 @@ class ClassMetadataExporterTest extends \Doctrine\Tests\OrmTestCase
|
||||
|
||||
// Try and read back in the exported mapping files to make sure they are valid
|
||||
$cme2 = new ClassMetadataExporter();
|
||||
$cme2->addMappingDirectory(__DIR__ . '/export/' . $type, $type);
|
||||
$metadataInstances = $cme2->getMetadatasForMappingDirectories();
|
||||
$cme2->addMappingSource(__DIR__ . '/export/' . $type, $type);
|
||||
$metadataInstances = $cme2->getMetadatasForMappingSources();
|
||||
$this->assertEquals(3, count($metadataInstances));
|
||||
$this->assertEquals('PhpTest', $metadataInstances[0]->name);
|
||||
$this->assertEquals('XmlTest', $metadataInstances[1]->name);
|
||||
$this->assertEquals('YmlTest', $metadataInstances[2]->name);
|
||||
$this->assertEquals('PhpTest', $metadataInstances['PhpTest']->name);
|
||||
$this->assertEquals('XmlTest', $metadataInstances['XmlTest']->name);
|
||||
$this->assertEquals('YmlTest', $metadataInstances['YmlTest']->name);
|
||||
|
||||
// Cleanup
|
||||
unlink(__DIR__ . '/export/' . $type . '/PhpTest'.$exporter->getExtension());
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Entities;
|
||||
|
||||
/** @Entity @Table(name="users") */
|
||||
/** @Entity @Table(name="users", indexes={@Index(name="name_idx", columns={"name", "test"})}) */
|
||||
class User {
|
||||
/**
|
||||
* @Id @Column(type="integer")
|
||||
@ -11,6 +11,8 @@ class User {
|
||||
private $id;
|
||||
/** @Column(type="string", length=50) */
|
||||
private $name;
|
||||
/** @Column(type="string", length=50) */
|
||||
private $test;
|
||||
/**
|
||||
* @OneToOne(targetEntity="Address")
|
||||
* @JoinColumn(name="address_id", referencedColumnName="id")
|
||||
|
@ -23,8 +23,10 @@ $config = new \Doctrine\ORM\Configuration();
|
||||
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache);
|
||||
|
||||
$connectionOptions = array(
|
||||
'driver' => 'pdo_sqlite',
|
||||
'path' => 'database.sqlite'
|
||||
'driver' => 'pdo_mysql',
|
||||
'user' => 'root',
|
||||
'password' => '',
|
||||
'dbname' => 'doctrine2'
|
||||
);
|
||||
|
||||
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);
|
||||
|
Loading…
Reference in New Issue
Block a user