Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
/*
4
 * This file is part of the symfony package.
5
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
6
 * (c) Jonathan H. Wage <jonwage@gmail.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
 
12
/**
13
 * Base class for all symfony Doctrine tasks.
14
 *
15
 * @package    symfony
16
 * @subpackage doctrine
17
 * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
18
 * @author     Jonathan H. Wage <jonwage@gmail.com>
19
 * @version    SVN: $Id: sfDoctrineBaseTask.class.php 28976 2010-04-05 00:27:39Z Kris.Wallsmith $
20
 */
21
abstract class sfDoctrineBaseTask extends sfBaseTask
22
{
23
  /**
24
   * Returns an array of configuration variables for the Doctrine CLI.
25
   *
26
   * @return array $config
27
   *
28
   * @see sfDoctrinePluginConfiguration::getCliConfig()
29
   */
30
  public function getCliConfig()
31
  {
32
    return $this->configuration->getPluginConfiguration('sfDoctrinePlugin')->getCliConfig();
33
  }
34
 
35
  /**
36
   * Calls a Doctrine CLI command.
37
   *
38
   * @param string $task Name of the Doctrine task to call
39
   * @param array  $args Arguments for the task
40
   *
41
   * @see sfDoctrineCli
42
   */
43
  public function callDoctrineCli($task, $args = array())
44
  {
45
    $config = $this->getCliConfig();
46
 
47
    $arguments = array('./symfony', $task);
48
 
49
    foreach ($args as $key => $arg)
50
    {
51
      if (isset($config[$key]))
52
      {
53
        $config[$key] = $arg;
54
      }
55
      else
56
      {
57
        $arguments[] = $arg;
58
      }
59
    }
60
 
61
    $cli = new sfDoctrineCli($config);
62
    $cli->setSymfonyDispatcher($this->dispatcher);
63
    $cli->setSymfonyFormatter($this->formatter);
64
    $cli->run($arguments);
65
  }
66
 
67
  /**
68
   * Returns Doctrine databases from the supplied database manager.
69
   *
70
   * @param sfDatabaseManager $databaseManager
71
   * @param array|null        $names An array of names or NULL for all databases
72
   *
73
   * @return array An associative array of {@link sfDoctrineDatabase} objects and their names
74
   *
75
   * @throws InvalidArgumentException If a requested database is not a Doctrine database
76
   */
77
  protected function getDoctrineDatabases(sfDatabaseManager $databaseManager, array $names = null)
78
  {
79
    $databases = array();
80
 
81
    if (null === $names)
82
    {
83
      foreach ($databaseManager->getNames() as $name)
84
      {
85
        $database = $databaseManager->getDatabase($name);
86
 
87
        if ($database instanceof sfDoctrineDatabase)
88
        {
89
          $databases[$name] = $database;
90
        }
91
      }
92
    }
93
    else
94
    {
95
      foreach ($names as $name)
96
      {
97
        $database = $databaseManager->getDatabase($name);
98
 
99
        if (!$database instanceof sfDoctrineDatabase)
100
        {
101
          throw new InvalidArgumentException(sprintf('The database "%s" is not a Doctrine database.', $name));
102
        }
103
 
104
        $databases[$name] = $database;
105
      }
106
    }
107
 
108
    return $databases;
109
  }
110
 
111
  /**
112
   * Merges all project and plugin schema files into one.
113
   *
114
   * Schema files are merged similar to how other configuration files are in
115
   * symfony, utilizing a configuration cascade. Files later in the cascade
116
   * can change values from earlier in the cascade.
117
   *
118
   * The order in which schema files are processed is like so:
119
   *
120
   *  1. Plugin schema files
121
   *    * Plugins are processed in the order which they were enabled in ProjectConfiguration
122
   *    * Each plugin's schema files are processed in alphabetical order
123
   *  2. Project schema files
124
   *    * Project schema files are processed in alphabetical order
125
   *
126
   * A schema file is any file saved in a plugin or project's config/doctrine/
127
   * directory that matches the "*.yml" glob.
128
   *
129
   * @return string Absolute path to the consolidated schema file
130
   */
131
  protected function prepareSchemaFile($yamlSchemaPath)
132
  {
133
    $models = array();
134
    $finder = sfFinder::type('file')->name('*.yml')->sort_by_name()->follow_link();
135
 
136
    // plugin models
137
    foreach ($this->configuration->getPlugins() as $name)
138
    {
139
      $plugin = $this->configuration->getPluginConfiguration($name);
140
      foreach ($finder->in($plugin->getRootDir().'/config/doctrine') as $schema)
141
      {
142
        $pluginModels = (array) sfYaml::load($schema);
143
        $globals = $this->filterSchemaGlobals($pluginModels);
144
 
145
        foreach ($pluginModels as $model => $definition)
146
        {
147
          // canonicalize this definition
148
          $definition = $this->canonicalizeModelDefinition($model, $definition);
149
 
150
          // merge in the globals
151
          $definition = array_merge($globals, $definition);
152
 
153
          // merge this model into the schema
154
          $models[$model] = isset($models[$model]) ? sfToolkit::arrayDeepMerge($models[$model], $definition) : $definition;
155
 
156
          // the first plugin to define this model gets the package
157
          if (!isset($models[$model]['package']))
158
          {
159
            $models[$model]['package'] = $plugin->getName().'.lib.model.doctrine';
160
          }
161
 
162
          if (!isset($models[$model]['package_custom_path']) && 0 === strpos($models[$model]['package'], $plugin->getName()))
163
          {
164
            $models[$model]['package_custom_path'] = $plugin->getRootDir().'/lib/model/doctrine';
165
          }
166
        }
167
      }
168
    }
169
 
170
    // project models
171
    foreach ($finder->in($yamlSchemaPath) as $schema)
172
    {
173
      $projectModels = (array) sfYaml::load($schema);
174
      $globals = $this->filterSchemaGlobals($projectModels);
175
 
176
      foreach ($projectModels as $model => $definition)
177
      {
178
        // canonicalize this definition
179
        $definition = $this->canonicalizeModelDefinition($model, $definition);
180
 
181
        // merge in the globals
182
        $definition = array_merge($globals, $definition);
183
 
184
        // merge this model into the schema
185
        $models[$model] = isset($models[$model]) ? sfToolkit::arrayDeepMerge($models[$model], $definition) : $definition;
186
      }
187
    }
188
 
189
    // create one consolidated schema file
190
    $file = realpath(sys_get_temp_dir()).'/doctrine_schema_'.rand(11111, 99999).'.yml';
191
    $this->logSection('file+', $file);
192
    file_put_contents($file, sfYaml::dump($models, 4));
193
 
194
    return $file;
195
  }
196
 
197
  /**
198
   * Removes and returns globals from the supplied array of models.
199
   *
200
   * @param array $models An array of model definitions
201
   *
202
   * @return array An array of globals
203
   *
204
   * @see Doctrine_Import_Schema::getGlobalDefinitionKeys()
205
   */
206
  protected function filterSchemaGlobals(& $models)
207
  {
208
    $globals = array();
209
    $globalKeys = Doctrine_Import_Schema::getGlobalDefinitionKeys();
210
 
211
    foreach ($models as $key => $value)
212
    {
213
      if (in_array($key, $globalKeys))
214
      {
215
        $globals[$key] = $value;
216
        unset($models[$key]);
217
      }
218
    }
219
 
220
    return $globals;
221
  }
222
 
223
  /**
224
   * Canonicalizes a model definition in preparation for merging.
225
   *
226
   * @param string $model      The model name
227
   * @param array  $definition The model definition
228
   *
229
   * @return array The canonicalized model definition
230
   */
231
  protected function canonicalizeModelDefinition($model, $definition)
232
  {
233
    // expand short "type" syntax
234
    if (isset($definition['columns']))
235
    {
236
      foreach ($definition['columns'] as $key => $value)
237
      {
238
        if (!is_array($value))
239
        {
240
          $definition['columns'][$key] = array('type' => $value);
241
          $value = $definition['columns'][$key];
242
        }
243
 
244
        // expand short type(length, scale) syntax
245
        if (isset($value['type']) && preg_match('/ *(\w+) *\( *(\d+)(?: *, *(\d+))? *\)/', $value['type'], $match))
246
        {
247
          $definition['columns'][$key]['type'] = $match[1];
248
          $definition['columns'][$key]['length'] = $match[2];
249
 
250
          if (isset($match[3]))
251
          {
252
            $definition['columns'][$key]['scale'] = $match[3];
253
          }
254
        }
255
      }
256
    }
257
 
258
    // expand short "actAs" syntax
259
    if (isset($definition['actAs']))
260
    {
261
      foreach ($definition['actAs'] as $key => $value)
262
      {
263
        if (is_numeric($key))
264
        {
265
          $definition['actAs'][$value] = array();
266
          unset($definition['actAs'][$key]);
267
        }
268
      }
269
    }
270
 
271
    // expand short "listeners" syntax
272
    if (isset($definition['listeners']))
273
    {
274
      foreach ($definition['listeners'] as $key => $value)
275
      {
276
        if (is_numeric($key))
277
        {
278
          $definition['listeners'][$value] = array();
279
          unset($definition['listeners'][$key]);
280
        }
281
      }
282
    }
283
 
284
    return $definition;
285
  }
286
}