[2.0] Work on CLI: Added SchemaToolTask with preliminary support for dropping/creating the database schema. Prepared the sandbox. Adjusted build to include the sandbox.
This commit is contained in:
parent
733c3c24f7
commit
94c187685b
14
build.xml
14
build.xml
@ -37,6 +37,19 @@
|
||||
<fileset id="orm-sources" dir=".">
|
||||
<include name="lib/Doctrine/ORM/**"/>
|
||||
</fileset>
|
||||
|
||||
<!--
|
||||
Fileset for the Doctrine ORM tools + sandbox.
|
||||
-->
|
||||
<fileset id="orm-tools" dir=".">
|
||||
<include name="tools/sandbox/Entities"/>
|
||||
<include name="tools/sandbox/xml"/>
|
||||
<include name="tools/sandbox/yaml"/>
|
||||
<include name="tools/sandbox/cli-config.php"/>
|
||||
<include name="tools/sandbox/config.php"/>
|
||||
<include name="tools/sandbox/doctrine"/>
|
||||
<include name="tools/sandbox/index.php"/>
|
||||
</fileset>
|
||||
|
||||
<target name="clean">
|
||||
<delete dir="${build.dir}" includeemptydirs="true" />
|
||||
@ -77,6 +90,7 @@
|
||||
<fileset refid="common-sources"/>
|
||||
<fileset refid="dbal-sources"/>
|
||||
<fileset refid="orm-sources"/>
|
||||
<fileset refid="orm-tools"/>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
|
@ -302,11 +302,11 @@ class EntityManager
|
||||
|
||||
/**
|
||||
* Gets a reference to the entity identified by the given type and identifier
|
||||
* without actually loading it. Only the identifier of the returned entity
|
||||
* will be populated.
|
||||
*
|
||||
* NOTE: There is currently no magic proxying in place, that means the full state
|
||||
* of the entity will not be loaded upon accessing it.
|
||||
* without actually loading it.
|
||||
*
|
||||
* If partial objects are allowed, this method will return a partial object that only
|
||||
* has its identifier populated. Otherwise a proxy is returned that automatically
|
||||
* loads itself on first access.
|
||||
*
|
||||
* @return object The entity reference.
|
||||
*/
|
||||
|
@ -56,7 +56,7 @@ class CommitOrderCalculator
|
||||
* Uses a depth-first search (DFS) to traverse the graph.
|
||||
* The desired topological sorting is the reverse postorder of these searches.
|
||||
*
|
||||
* @return array The list of ordered items. These are the items wrapped in the nodes.
|
||||
* @return array The list of ordered classes.
|
||||
*/
|
||||
public function getCommitOrder()
|
||||
{
|
||||
@ -65,7 +65,7 @@ class CommitOrderCalculator
|
||||
if ($nodeCount == 0) {
|
||||
return array();
|
||||
} else if ($nodeCount == 1) {
|
||||
return $this->_classes;
|
||||
return array(0 => array_pop($this->_classes));
|
||||
}
|
||||
|
||||
// Init
|
||||
@ -102,7 +102,6 @@ class CommitOrderCalculator
|
||||
}
|
||||
|
||||
$this->_nodeStates[$node->name] = self::VISITED;
|
||||
|
||||
$this->_sorted[] = $node;
|
||||
}
|
||||
|
||||
|
@ -363,9 +363,8 @@ class ObjectHydrator extends AbstractHydrator
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array($key => $element);
|
||||
$result[] = $element;
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
end($result);
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = key($result);
|
||||
} else {
|
||||
$result[$key] = $element;
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $key;
|
||||
@ -373,11 +372,10 @@ class ObjectHydrator extends AbstractHydrator
|
||||
} else {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array(0 => $element);
|
||||
++$this->_resultCounter;
|
||||
}
|
||||
$result[] = $element;
|
||||
end($result);
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = key($result);
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
}
|
||||
|
||||
// Update result pointer
|
||||
|
@ -86,6 +86,11 @@ class ClassMetadataFactory
|
||||
{
|
||||
return $this->_cacheDriver;
|
||||
}
|
||||
|
||||
public function getLoadedMetadata()
|
||||
{
|
||||
return $this->_loadedMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the class metadata descriptor for a class.
|
||||
|
@ -91,9 +91,9 @@ abstract class AbstractFileDriver implements Driver
|
||||
* documents and operates in the specified operating mode.
|
||||
*
|
||||
* @param string|array $paths One or multiple paths where mapping documents can be found.
|
||||
* @param integer $mode The operating mode. Either PRELOAD (default) or FILE_PER_CLASS.
|
||||
* @param integer $mode The operating mode. Either PRELOAD or FILE_PER_CLASS (default).
|
||||
*/
|
||||
public function __construct($paths, $mode = self::PRELOAD)
|
||||
public function __construct($paths, $mode = self::FILE_PER_CLASS)
|
||||
{
|
||||
$this->_paths = $paths;
|
||||
$this->_mode = $mode;
|
||||
|
@ -120,6 +120,10 @@ class OneToOneMapping extends AssociationMapping
|
||||
$this->orphanRemoval = isset($mapping['orphanRemoval']) ?
|
||||
(bool) $mapping['orphanRemoval'] : false;
|
||||
|
||||
/*if ($this->isOptional) {
|
||||
$this->fetchMode = self::FETCH_EAGER;
|
||||
}*/
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect
|
||||
private $_backRefFieldName;
|
||||
|
||||
/**
|
||||
* The class descriptor of the owning entity.
|
||||
* The class descriptor of the collection's entity type.
|
||||
*/
|
||||
private $_typeClass;
|
||||
|
||||
@ -124,7 +124,8 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Sets the collection owner. Used (only?) during hydration.
|
||||
* Sets the collection's owning entity together with the AssociationMapping that
|
||||
* describes the association between the owner and the elements of the collection.
|
||||
*
|
||||
* @param object $entity
|
||||
* @param AssociationMapping $assoc
|
||||
@ -168,7 +169,8 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Adds an element to a collection during hydration.
|
||||
* Adds an element to a collection during hydration. This will automatically
|
||||
* complete bidirectional associations.
|
||||
*
|
||||
* @param mixed $element The element to add.
|
||||
*/
|
||||
@ -198,9 +200,23 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect
|
||||
* @param mixed $key The key to set.
|
||||
* $param mixed $value The element to set.
|
||||
*/
|
||||
public function hydrateSet($key, $value)
|
||||
public function hydrateSet($key, $element)
|
||||
{
|
||||
$this->_coll->set($key, $value);
|
||||
$this->_coll->set($key, $element);
|
||||
// If _backRefFieldName is set, then the association is bidirectional
|
||||
// and we need to set the back reference.
|
||||
if ($this->_backRefFieldName) {
|
||||
// Set back reference to owner
|
||||
if ($this->_association->isOneToMany()) {
|
||||
// OneToMany
|
||||
$this->_typeClass->reflFields[$this->_backRefFieldName]
|
||||
->setValue($element, $this->_owner);
|
||||
} else {
|
||||
// ManyToMany
|
||||
$this->_typeClass->reflFields[$this->_backRefFieldName]
|
||||
->getValue($element)->set($key, $this->_owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -307,9 +323,9 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the initialized flag of the collection, forcing it into that state.
|
||||
*
|
||||
* @param $bool
|
||||
* @return unknown_type
|
||||
* @param boolean $bool
|
||||
*/
|
||||
public function setInitialized($bool)
|
||||
{
|
||||
|
@ -172,6 +172,7 @@ final class Query extends AbstractQuery
|
||||
// Calculate hash for dql query.
|
||||
// TODO: Probably need to include query hints in hash calculation, because query hints
|
||||
// can have influence on the SQL.
|
||||
// TODO: Include _maxResults and _firstResult in hash calculation
|
||||
$hash = md5($this->getDql() . 'DOCTRINE_QUERY_CACHE_SALT');
|
||||
$cached = ($this->_expireQueryCache) ? false : $queryCache->fetch($hash);
|
||||
|
||||
|
@ -22,9 +22,9 @@
|
||||
namespace Doctrine\ORM\Tools;
|
||||
|
||||
use Doctrine\Common\Util\Inflector,
|
||||
Doctrine\ORM\Tools\Cli\AbstractPrinter,
|
||||
Doctrine\ORM\Tools\Cli\AbstractTask,
|
||||
Doctrine\ORM\Tools\Cli\Printer;
|
||||
Doctrine\ORM\Tools\Cli\Printers\AbstractPrinter,
|
||||
Doctrine\ORM\Tools\Cli\Tasks\AbstractTask,
|
||||
Doctrine\ORM\Tools\Cli\Printers\AnsiColorPrinter;
|
||||
|
||||
/**
|
||||
* Generic CLI Runner of Tasks
|
||||
@ -83,14 +83,16 @@ class Cli
|
||||
public function __construct(AbstractPrinter $printer = null)
|
||||
{
|
||||
//$this->_printer = new Printer\Normal();
|
||||
$this->_printer = $printer ?: new Printer\AnsiColor();
|
||||
$this->_printer = $printer ?: new AnsiColorPrinter;
|
||||
|
||||
// Include core tasks
|
||||
$ns = 'Doctrine\ORM\Tools\Cli\Task';
|
||||
$ns = 'Doctrine\ORM\Tools\Cli\Tasks';
|
||||
|
||||
$this->addTasks(array(
|
||||
'help' => $ns . '\Help',
|
||||
'version' => $ns . '\Version',
|
||||
'help' => $ns . '\HelpTask',
|
||||
'version' => $ns . '\VersionTask',
|
||||
'schema-tool' => $ns . '\SchemaToolTask',
|
||||
'run-sql' => $ns . '\RunSqlTask'
|
||||
));
|
||||
}
|
||||
|
||||
@ -146,12 +148,12 @@ class Cli
|
||||
// Automatically prepend 'help' task if:
|
||||
// 1- No arguments were passed
|
||||
// 2- First item is not a valid task name
|
||||
if (empty($args) || (isset($args[0]) && strpos($args[0], '-') !== false)) {
|
||||
if (empty($args) || ! isset($this->_tasks[$this->_processTaskName($args[0])])) {
|
||||
array_unshift($args, 'help');
|
||||
}
|
||||
|
||||
// Process all sent arguments
|
||||
$processedArgs = $this->_processArguments($args);
|
||||
$processedArgs = $this->_processArguments($args);
|
||||
|
||||
try {
|
||||
// Handle possible multiple tasks on a single command
|
||||
|
@ -19,7 +19,9 @@
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Tools\Cli;
|
||||
namespace Doctrine\ORM\Tools\Cli\Printers;
|
||||
|
||||
use Doctrine\ORM\Tools\Cli\Style;
|
||||
|
||||
/**
|
||||
* CLI Output Printer.
|
||||
@ -137,7 +139,7 @@ abstract class AbstractPrinter
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes to output stream the message, formatting it by applying the defined style.
|
||||
* Writes to the output stream, formatting it by applying the defined style.
|
||||
*
|
||||
* @param string $message Message to be outputted
|
||||
* @param mixed $style Optional style to be applied in message
|
||||
@ -149,6 +151,17 @@ abstract class AbstractPrinter
|
||||
fwrite($this->_stream, $this->format($message, $style));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a line to the output stream, formatting it by applying the defined style.
|
||||
*
|
||||
* @param string $message Message to be outputted
|
||||
* @param mixed $style Optional style to be applied in message
|
||||
*/
|
||||
public function writeln($message, $style = 'ERROR')
|
||||
{
|
||||
$this->write($message . PHP_EOL, $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the given message with the defined style.
|
||||
*
|
@ -19,10 +19,9 @@
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Tools\Cli\Printer;
|
||||
namespace Doctrine\ORM\Tools\Cli\Printers;
|
||||
|
||||
use Doctrine\ORM\Tools\Cli\AbstractPrinter,
|
||||
Doctrine\ORM\Tools\Cli\Style;
|
||||
use Doctrine\ORM\Tools\Cli\Style;
|
||||
|
||||
/**
|
||||
* CLI Output Printer for ANSI Color terminal
|
||||
@ -35,7 +34,7 @@ use Doctrine\ORM\Tools\Cli\AbstractPrinter,
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class AnsiColor extends AbstractPrinter
|
||||
class AnsiColorPrinter extends AbstractPrinter
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
@ -19,10 +19,9 @@
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Tools\Cli\Printer;
|
||||
namespace Doctrine\ORM\Tools\Cli\Printers;
|
||||
|
||||
use Doctrine\ORM\Tools\Cli\AbstractPrinter,
|
||||
Doctrine\ORM\Tools\Cli\Style;
|
||||
use Doctrine\ORM\Tools\Cli\Style;
|
||||
|
||||
/**
|
||||
* CLI Output Printer for Normal terminal
|
||||
@ -35,7 +34,7 @@ use Doctrine\ORM\Tools\Cli\AbstractPrinter,
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class Normal extends AbstractPrinter
|
||||
class NormalPrinter extends AbstractPrinter
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
@ -19,12 +19,21 @@
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Tools\Cli;
|
||||
namespace Doctrine\ORM\Tools\Cli\Tasks;
|
||||
|
||||
use Doctrine\ORM\Tools\Cli\Printers\AbstractPrinter;
|
||||
|
||||
/**
|
||||
* CLI Task.
|
||||
* Base class for CLI Tasks.
|
||||
* Provides basic methods and requires implementation of methods that
|
||||
* each task should implement in order to correctly work.
|
||||
*
|
||||
* The following arguments are common to all tasks:
|
||||
*
|
||||
* Argument: --config=<path>
|
||||
* Description: Specifies the path to the configuration file to use. The configuration file
|
||||
* can bootstrap an EntityManager as well as provide defaults for any cli
|
||||
* arguments.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
@ -51,6 +60,8 @@ abstract class AbstractTask
|
||||
*/
|
||||
protected $_availableTasks;
|
||||
|
||||
protected $_em;
|
||||
|
||||
/**
|
||||
* Defines a CLI Output Printer
|
||||
*
|
||||
@ -148,13 +159,44 @@ abstract class AbstractTask
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function validate();
|
||||
public function validate()
|
||||
{
|
||||
if ( ! isset($this->_arguments['config'])) {
|
||||
if (file_exists('./cli-config.php')) {
|
||||
require './cli-config.php';
|
||||
} else {
|
||||
$this->_printer->writeln('--config option or cli-config.php in the same directory required', 'ERROR');
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
require $this->_arguments['config'];
|
||||
}
|
||||
|
||||
// $em and $args come from the config
|
||||
if (isset($em)) {
|
||||
$this->_em = $em;
|
||||
}
|
||||
if (isset($args)) {
|
||||
// Merge arguments. Values specified via the CLI take preference.
|
||||
$this->_arguments = array_merge($args, $this->_arguments);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely execution of task.
|
||||
* Each CLI task should implement this as normal flow execution of
|
||||
* what is supposed to do.
|
||||
*
|
||||
*/
|
||||
abstract public function run();
|
||||
|
||||
protected function _requireEntityManager()
|
||||
{
|
||||
if ( ! isset($this->_em)) {
|
||||
$this->_printer->writeln('No EntityManager created in configuration but required by task ' . get_class($this), 'ERROR');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
14
lib/Doctrine/ORM/Tools/Cli/Tasks/CreateMappingTask.php
Normal file
14
lib/Doctrine/ORM/Tools/Cli/Tasks/CreateMappingTask.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\ORM\Tools\Cli\Tasks;
|
||||
|
||||
/**
|
||||
* Task for creating XML or YAML mappings based on an existing database schema.
|
||||
*
|
||||
* @author robo
|
||||
* @since 2.0
|
||||
*/
|
||||
class CreateMappingTask extends AbstractTask
|
||||
{
|
||||
|
||||
}
|
@ -19,9 +19,7 @@
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Tools\Cli\Task;
|
||||
|
||||
use Doctrine\ORM\Tools\Cli\AbstractTask;
|
||||
namespace Doctrine\ORM\Tools\Cli\Tasks;
|
||||
|
||||
/**
|
||||
* CLI Task to display available commands help
|
||||
@ -34,7 +32,7 @@ use Doctrine\ORM\Tools\Cli\AbstractTask;
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class Help extends AbstractTask
|
||||
class HelpTask extends AbstractTask
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
48
lib/Doctrine/ORM/Tools/Cli/Tasks/RunSqlTask.php
Normal file
48
lib/Doctrine/ORM/Tools/Cli/Tasks/RunSqlTask.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\ORM\Tools\Cli\Tasks;
|
||||
|
||||
/**
|
||||
* Task for executing arbitrary SQL that can come from a file or directly from
|
||||
* the command line.
|
||||
*
|
||||
* @author robo
|
||||
* @since 2.0
|
||||
*/
|
||||
class RunSqlTask extends AbstractTask
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function extendedHelp()
|
||||
{
|
||||
$this->getPrinter()->writeln('run-sql extended help.', 'INFO');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function basicHelp()
|
||||
{
|
||||
$this->getPrinter()->writeln('run-sql basic help.', 'INFO');
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the task.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$args = $this->getArguments();
|
||||
|
||||
if (isset($args['file'])) {
|
||||
//TODO
|
||||
} else if (isset($args['sql'])) {
|
||||
if (preg_match('/^select/i', $args['sql'])) {
|
||||
$stmt = $this->_em->getConnection()->execute($args['sql']);
|
||||
var_dump($stmt->fetchAll(\Doctrine\DBAL\Connection::FETCH_ASSOC));
|
||||
} else {
|
||||
var_dump($this->_em->getConnection()->executeUpdate($args['sql']));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
158
lib/Doctrine/ORM/Tools/Cli/Tasks/SchemaToolTask.php
Normal file
158
lib/Doctrine/ORM/Tools/Cli/Tasks/SchemaToolTask.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\ORM\Tools\Cli\Tasks;
|
||||
|
||||
use Doctrine\ORM\Tools\SchemaTool,
|
||||
Doctrine\Common\Annotations\AnnotationReader,
|
||||
Doctrine\ORM\Mapping\Driver\AnnotationDriver,
|
||||
Doctrine\ORM\Mapping\Driver\XmlDriver,
|
||||
Doctrine\ORM\Mapping\Driver\YamlDriver;
|
||||
|
||||
/**
|
||||
* Task to create the database schema for a set of classes based on their mappings.
|
||||
*
|
||||
* This task has the following arguments:
|
||||
*
|
||||
* <tt>--classdir=<path></tt>
|
||||
* Specifies the directory where to start looking for mapped classes.
|
||||
* This argument is required when the annotation metadata driver is used,
|
||||
* otherwise it has no effect.
|
||||
*
|
||||
* <tt>--dump-sql</tt>
|
||||
* Specifies that instead of directly executing the SQL statements for creating the
|
||||
* database schema, they should be printed to the standard output.
|
||||
*
|
||||
* <tt>--create</tt>
|
||||
* Specifies that the schema of the classes should be created.
|
||||
*
|
||||
* <tt>--drop</tt>
|
||||
* Specifies that the schema of the classes should be dropped.
|
||||
*
|
||||
* <tt>--update</tt>
|
||||
* Specifies that the schema of the classes should be updated.
|
||||
*
|
||||
*
|
||||
* @author robo
|
||||
* @since 2.0
|
||||
*/
|
||||
class SchemaToolTask extends AbstractTask
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function extendedHelp()
|
||||
{
|
||||
$this->getPrinter()->writeln('create-schema extended help.', 'INFO');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function basicHelp()
|
||||
{
|
||||
$this->getPrinter()->writeln('create-schema basic help.', 'INFO');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function validate()
|
||||
{
|
||||
if ( ! parent::validate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$args = $this->getArguments();
|
||||
$printer = $this->getPrinter();
|
||||
|
||||
if ( ! $this->_requireEntityManager()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$isCreate = isset($args['create']);
|
||||
$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');
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->_em->getConfiguration()->getMetadataDriverImpl() instanceof \Doctrine\ORM\Mapping\Driver\AnnotationDriver
|
||||
&& ! isset($args['classdir'])) {
|
||||
$printer->writeln("The supplied configuration uses the annotation metadata driver."
|
||||
. " The 'classdir' argument is required for this driver.", 'ERROR');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the task.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$args = $this->getArguments();
|
||||
|
||||
$isCreate = isset($args['create']);
|
||||
$isDrop = isset($args['drop']);
|
||||
$isUpdate = isset($args['update']);
|
||||
|
||||
$cmf = $this->_em->getMetadataFactory();
|
||||
$driver = $this->_em->getConfiguration()->getMetadataDriverImpl();
|
||||
|
||||
$classes = array();
|
||||
|
||||
if ($driver instanceof \Doctrine\ORM\Mapping\Driver\AnnotationDriver) {
|
||||
$iter = new \FilesystemIterator($args['classdir']);
|
||||
|
||||
$declared = get_declared_classes();
|
||||
foreach ($iter as $item) {
|
||||
$baseName = $item->getBaseName();
|
||||
if ($baseName[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
require_once $item->getPathName();
|
||||
}
|
||||
$declared = array_diff(get_declared_classes(), $declared);
|
||||
|
||||
foreach ($declared as $className) {
|
||||
if ( ! $driver->isTransient($className)) {
|
||||
$classes[] = $cmf->getMetadataFor($className);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$driver->preload();
|
||||
$classes = $cmf->getLoadedMetadata();
|
||||
}
|
||||
|
||||
$printer = $this->getPrinter();
|
||||
$tool = new SchemaTool($this->_em);
|
||||
|
||||
if ($isCreate) {
|
||||
if (isset($args['dump-sql'])) {
|
||||
foreach ($tool->getCreateSchemaSql($classes) as $sql) {
|
||||
$printer->writeln($sql, 'NONE');
|
||||
}
|
||||
} else {
|
||||
$printer->writeln('Creating database schema...', 'INFO');
|
||||
$tool->createSchema($classes);
|
||||
$printer->write('Database schema created successfully.' . PHP_EOL, 'INFO');
|
||||
}
|
||||
} else if ($isDrop) {
|
||||
if (isset($args['dump-sql'])) {
|
||||
foreach ($tool->getDropSchemaSql($classes) as $sql) {
|
||||
$printer->writeln($sql, 'NONE');
|
||||
}
|
||||
} else {
|
||||
$printer->writeln('Dropping database schema...', 'INFO');
|
||||
$tool->dropSchema($classes);
|
||||
$printer->writeln('Database schema dropped successfully.', 'INFO');
|
||||
}
|
||||
} else if ($isUpdate) {
|
||||
//TODO
|
||||
$printer->writeln('--update not yet implemented.', 'COMMENT');
|
||||
}
|
||||
}
|
||||
}
|
@ -19,9 +19,7 @@
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Tools\Cli\Task;
|
||||
|
||||
use Doctrine\ORM\Tools\Cli\AbstractTask;
|
||||
namespace Doctrine\ORM\Tools\Cli\Tasks;
|
||||
|
||||
/**
|
||||
* CLI Task to display the doctrine version
|
||||
@ -34,7 +32,7 @@ use Doctrine\ORM\Tools\Cli\AbstractTask;
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class Version extends AbstractTask
|
||||
class VersionTask extends AbstractTask
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
@ -22,17 +22,17 @@
|
||||
namespace Doctrine\ORM\Tools;
|
||||
|
||||
use Doctrine\DBAL\Types\Type,
|
||||
Doctrine\ORM\EntityManager;
|
||||
Doctrine\ORM\EntityManager,
|
||||
Doctrine\ORM\Internal\CommitOrderCalculator;
|
||||
|
||||
/**
|
||||
* The SchemaTool is a tool to create and/or drop database schemas based on
|
||||
* The SchemaTool is a tool to create/drop/update database schemas based on
|
||||
* <tt>ClassMetadata</tt> class descriptors.
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision: 4805 $
|
||||
*/
|
||||
class SchemaTool
|
||||
{
|
||||
@ -382,8 +382,9 @@ class SchemaTool
|
||||
public function getDropSchemaSql(array $classes)
|
||||
{
|
||||
$sql = array();
|
||||
$commitOrder = $classes; //FIXME: get real commit order!!
|
||||
|
||||
$commitOrder = $this->_getCommitOrder($classes);
|
||||
|
||||
// Drop tables in reverse commit order
|
||||
for ($i = count($commitOrder) - 1; $i >= 0; --$i) {
|
||||
$class = $commitOrder[$i];
|
||||
@ -393,6 +394,8 @@ class SchemaTool
|
||||
$sql[] = $this->_platform->getDropTableSql($class->getTableName());
|
||||
}
|
||||
|
||||
//TODO: Drop other schema elements, like sequences etc.
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
@ -529,4 +532,26 @@ class SchemaTool
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
private function _getCommitOrder(array $classes)
|
||||
{
|
||||
$calc = new CommitOrderCalculator;
|
||||
|
||||
// Calculate dependencies
|
||||
foreach ($classes as $class) {
|
||||
$calc->addClass($class);
|
||||
foreach ($class->associationMappings as $assoc) {
|
||||
if ($assoc->isOwningSide) {
|
||||
$targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
|
||||
if ( ! $calc->hasClass($targetClass->name)) {
|
||||
$calc->addClass($targetClass);
|
||||
}
|
||||
// add dependency ($targetClass before $class)
|
||||
$calc->addDependency($targetClass, $class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $calc->getCommitOrder();
|
||||
}
|
||||
}
|
||||
|
@ -1290,7 +1290,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$managedCopyVersion = $class->reflFields[$class->versionField]->getValue($managedCopy);
|
||||
$entityVersion = $class->reflFields[$class->versionField]->getValue($entity);
|
||||
// Throw exception if versions dont match.
|
||||
if ($managedCopyVersion != $entity) {
|
||||
if ($managedCopyVersion != $entityVersion) {
|
||||
throw OptimisticLockException::versionMismatch();
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ class MappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
||||
public function testXmlPreloadMode()
|
||||
{
|
||||
$className = 'Doctrine\Tests\ORM\Mapping\User';
|
||||
$xmlDriver = new XmlDriver(__DIR__ . DIRECTORY_SEPARATOR . 'xml');
|
||||
$xmlDriver = new XmlDriver(__DIR__ . DIRECTORY_SEPARATOR . 'xml', XmlDriver::PRELOAD);
|
||||
$class = new ClassMetadata($className);
|
||||
|
||||
$classNames = $xmlDriver->preload();
|
||||
@ -57,7 +57,7 @@ class MappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
||||
public function testYamlPreloadMode()
|
||||
{
|
||||
$className = 'Doctrine\Tests\ORM\Mapping\User';
|
||||
$yamlDriver = new YamlDriver(__DIR__ . DIRECTORY_SEPARATOR . 'yaml');
|
||||
$yamlDriver = new YamlDriver(__DIR__ . DIRECTORY_SEPARATOR . 'yaml', YamlDriver::PRELOAD);
|
||||
$class = new ClassMetadata($className);
|
||||
|
||||
$classNames = $yamlDriver->preload();
|
||||
|
14
tools/sandbox/cli-config.php
Normal file
14
tools/sandbox/cli-config.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
$config = new \Doctrine\ORM\Configuration();
|
||||
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache);
|
||||
$connectionOptions = array(
|
||||
'driver' => 'pdo_sqlite',
|
||||
'path' => 'database.sqlite'
|
||||
);
|
||||
|
||||
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);
|
||||
|
||||
$args = array(
|
||||
'classdir' => './Entities'
|
||||
);
|
@ -6,9 +6,17 @@ $classLoader = new \Doctrine\Common\ClassLoader();
|
||||
$classLoader->setBasePath('Doctrine', realpath(__DIR__ . '/../../lib'));
|
||||
$classLoader->setBasePath('Entities', __DIR__);
|
||||
|
||||
$config = new \Doctrine\ORM\Configuration();
|
||||
$config->setMetadataCacheImpl(new \Doctrine\ORM\Cache\ArrayCache);
|
||||
$config->setMetadataDriverImpl(new \Doctrine\ORM\Mapping\Driver\YamlDriver(__DIR__ . '/schema'));
|
||||
$config = new \Doctrine\ORM\Configuration;
|
||||
$cache = new \Doctrine\Common\Cache\ApcCache;
|
||||
$config->setMetadataCacheImpl($cache);
|
||||
$config->setQueryCacheImpl($cache);
|
||||
|
||||
# EXAMPLE FOR YAML DRIVER
|
||||
#$config->setMetadataDriverImpl(new \Doctrine\ORM\Mapping\Driver\YamlDriver(__DIR__ . '/yaml'));
|
||||
|
||||
# EXAMPLE FOR XML DRIVER
|
||||
#$config->setMetadataDriverImpl(new \Doctrine\ORM\Mapping\Driver\YamlDriver(__DIR__ . '/xml'));
|
||||
|
||||
$eventManager = new \Doctrine\Common\EventManager();
|
||||
$connectionOptions = array(
|
||||
'driver' => 'pdo_sqlite',
|
||||
|
10
tools/sandbox/doctrine
Executable file
10
tools/sandbox/doctrine
Executable file
@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../../lib/Doctrine/Common/ClassLoader.php';
|
||||
|
||||
$classLoader = new \Doctrine\Common\ClassLoader();
|
||||
$classLoader->setBasePath('Doctrine', __DIR__ . '/../../lib');
|
||||
|
||||
$cli = new \Doctrine\ORM\Tools\Cli();
|
||||
$cli->run($_SERVER['argv']);
|
Loading…
Reference in New Issue
Block a user