SchemaToolTask.php 7.76 KB
Newer Older
1 2 3 4
<?php

namespace Doctrine\ORM\Tools\Cli\Tasks;

5 6
use Doctrine\Common\DoctrineException,
    Doctrine\ORM\Tools\SchemaTool,
7 8 9 10 11 12 13 14 15 16
    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:
 * 
17
 * <tt>--class-dir=<path></tt>
18 19 20 21 22
 * 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>
23 24
 * Specifies that instead of directly executing the SQL statements,
 * they should be printed to the standard output.
25 26 27 28 29 30 31 32 33 34 35
 * 
 * <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.
 * 
 * 
36 37 38 39 40 41 42
 * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
 * @link    www.doctrine-project.org
 * @since   2.0
 * @version $Revision: 3938 $
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
43 44 45 46 47 48 49 50
 */
class SchemaToolTask extends AbstractTask
{
    /**
     * @inheritdoc
     */
    public function extendedHelp()
    {
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
        $printer = $this->getPrinter();
        
        $printer->write('Task: ')->writeln('schema-tool', 'KEYWORD')
                ->write('Synopsis: ');
        $this->_writeSynopsis($printer);
        
        $printer->writeln('Description: Processes the schema and either apply it directly on EntityManager or generate the SQL output.')
                ->writeln('Options:')
                ->write('--create', 'REQ_ARG')
                ->writeln("\t\tCreates the schema in EntityManager (create tables on Database)")
                ->writeln("\t\t\tIf defined, --drop and --update can not be requested on same task")
                ->write(PHP_EOL)
                ->write('--drop', 'REQ_ARG')
                ->writeln("\t\t\tDrops the schema of EntityManager (drop tables on Database)")
                ->writeln("\t\t\tIf defined, --create and --update can not be requested on same task")
                ->write(PHP_EOL)
                ->write('--update', 'REQ_ARG')
                ->writeln("\t\tUpdates the schema in EntityManager (update tables on Database)")
                ->writeln("\t\t\tIf defined, --create and --drop can not be requested on same task")
                ->write(PHP_EOL)
71 72 73
                ->write('--re-create', 'REQ_ARG')
                ->writeln("\t\tRuns --drop then --create to re-create the database.")
                ->write(PHP_EOL)
74 75 76
                ->write('--dump-sql', 'OPT_ARG')
                ->writeln("\t\tInstead of try to apply generated SQLs into EntityManager, output them.")
                ->write(PHP_EOL)
77
                ->write('--class-dir=<path>', 'OPT_ARG')
78 79
                ->writeln("\tOptional class directory to fetch for Entities.")
                ->write(PHP_EOL);
80 81 82 83 84 85 86
    }

    /**
     * @inheritdoc
     */
    public function basicHelp()
    {
87 88 89 90 91 92
        $this->_writeSynopsis($this->getPrinter());
    }
    
    private function _writeSynopsis($printer)
    {
        $printer->write('schema-tool', 'KEYWORD')
93 94
                ->write(' (--create | --drop | --update | --re-create)', 'REQ_ARG')
                ->writeln(' [--dump-sql] [--class-dir=<path>]', 'OPT_ARG');
95 96 97 98 99 100 101 102 103 104 105 106 107 108
    }
    
    /**
     * @inheritdoc
     */
    public function validate()
    {
        if ( ! parent::validate()) {
            return false;
        }
        
        $args = $this->getArguments();
        $printer = $this->getPrinter();
        
109 110 111 112 113
        if (array_key_exists('re-create', $args)) {
            $args['drop'] = true;
            $args['create'] = true;
            $this->setArguments($args);
        }
114 115 116 117 118
        
        $isCreate = isset($args['create']);
        $isDrop = isset($args['drop']);
        $isUpdate = isset($args['update']);
        
119 120
        if ($isUpdate && ($isCreate || $isDrop)) {
            $printer->writeln("You can't use --update with --create or --drop", 'ERROR');
121 122
            return false;
        }
123 124 125 126 127

        if ( ! ($isCreate || $isDrop || $isUpdate)) {
            $printer->writeln('You must specify at a minimum one of the options (--create, --drop, --update, --re-create).', 'ERROR');
            return false;
        }
128
        
129 130
        $metadataDriver = $this->getEntityManager()->getConfiguration()->getMetadataDriverImpl();
        
131 132 133 134 135 136 137 138
        if ($metadataDriver instanceof \Doctrine\ORM\Mapping\Driver\AnnotationDriver) {
            if ( ! isset($args['class-dir'])) {
                $printer->writeln("The supplied configuration uses the annotation metadata driver."
                        . " The 'class-dir' argument is required for this driver.", 'ERROR');
                return false;
            } else {
                $metadataDriver->setClassDirectory($args['class-dir']);
            }
139 140 141 142 143 144 145 146 147 148 149
        }
        
        return true;
    }

    /**
     * Executes the task.
     */
    public function run()
    {
        $args = $this->getArguments();
150

151 152 153 154
        $isCreate = isset($args['create']);
        $isDrop = isset($args['drop']);
        $isUpdate = isset($args['update']);

155 156 157
        $em = $this->getEntityManager();
        $cmf = $em->getMetadataFactory();
        $driver = $em->getConfiguration()->getMetadataDriverImpl();
158 159
        
        $classes = array();
160
        $preloadedClasses = $driver->preload(true);
161
        
162 163
        foreach ($preloadedClasses as $className) {
            $classes[] = $cmf->getMetadataFor($className);
164
        }
165

166 167
        $printer = $this->getPrinter();
        
168 169 170 171
        if (empty($classes)) {
            $printer->writeln('No classes to process.', 'INFO');
            return;
        }
172

173 174
        $tool = new SchemaTool($em);
        
175
        if ($isDrop) {
176
            if (isset($args['dump-sql'])) {
177
                foreach ($tool->getDropSchemaSql($classes) as $sql) {
178
                    $printer->writeln($sql);
179 180
                }
            } else {
181
                $printer->writeln('Dropping database schema...', 'INFO');
182 183
                
                try {
184 185
                    $tool->dropSchema($classes);
                    $printer->writeln('Database schema dropped successfully.', 'INFO');
186
                } catch (\Exception $ex) {
187
                    throw new DoctrineException($ex);
188
                }
189
            }
190 191 192
        }

        if ($isCreate) {
193
            if (isset($args['dump-sql'])) {
194
                foreach ($tool->getCreateSchemaSql($classes) as $sql) {
195
                    $printer->writeln($sql);
196 197
                }
            } else {
198
                $printer->writeln('Creating database schema...', 'INFO');
199 200
                
                try {
201 202
                    $tool->createSchema($classes);
                    $printer->writeln('Database schema created successfully.', 'INFO');
203
                } catch (\Exception $ex) {
204
                    throw new DoctrineException($ex);
205
                }
206
            }
207 208 209
        }

        if ($isUpdate) {            
210 211 212 213 214 215
            if (isset($args['dump-sql'])) {
                foreach ($tool->getUpdateSchemaSql($classes) as $sql) {
                    $printer->writeln($sql);
                }
            } else {
                $printer->writeln('Updating database schema...', 'INFO');
216 217 218 219 220
                
                try {
                    $tool->updateSchema($classes);
                    $printer->writeln('Database schema updated successfully.', 'INFO');
                } catch (\Exception $ex) {
221
                    throw new DoctrineException($ex);
222
                }
223
            }
224 225 226
        }
    }
}