ZendDbSchema
Schema management for Zend Framework
 All Classes Namespaces Functions Pages
Manager.php
1 <?php
29 class ZendDbSchema_Db_Migration_Manager implements IteratorAggregate
30 {
34  protected $_adapter;
35 
39  protected $_changes = array();
40 
41  protected $_currentVersion;
42 
49  public function __construct($version, array $files = array(), array $options = array())
50  {
51  $this->_currentVersion = (string) $version;
52 
53  foreach ($files as $file) {
54  $this->addChange($file);
55  }
56 
57  if (empty($options['directory'])) {
58  foreach (new DirectoryIterator($options['directory']) as $file) {
59  if ($file->isFile() && substr($file->getBasename(), -4) == '.php') {
60  $this->addChange($file);
61  }
62  }
63  }
64 
65  if ($this->_currentVersion && !array_key_exists($this->_currentVersion, $this->_changes)) {
67  "Current change '{$this->_currentVersion}' in not exists"
68  );
69  }
70 
71  $prev = null;
72  foreach ($this->_changes as $version => $instance) {
73  $this->_changes[$version]['previous'] = $prev;
74  if ($prev) {
75  $this->_changes[$prev]['next'] = $version;
76  }
77  $prev = $version;
78  }
79 
80  $this->init();
81  }
82 
89  public function addChange($change)
90  {
91  if (!$change instanceof ZendDbSchema_Db_Migration_Change) {
93  }
94  $this->_changes[$change->getVersion()] = array('instance' => $change);
95 
96  foreach ($this->_changes as $change) {
97  if ($change->compareVersion($change, '=')) {
98  break;
99  }
100  }
101  $next = next($this->_changes);
102  $this->_changes[$change->getVersion()]['next'] = key($next);
103 
104  $prev = prev(prev($this->_changes));
105 
106  $this->_changes[$prev]['next'] = $change->getVersion();
107 
108  return $this;
109  }
110 
114  public function init()
115  {
116  }
117 
123  public function getIterator()
124  {
125  ksort($this->_changes);
126 
127  return $this->_changes;
128  }
129 
135  public function getList()
136  {
137  return array_keys($this->getIterator());
138  }
139 
145  public function getVersion()
146  {
147  return $this->_currentVersion;
148  }
149 
156  public function getChange($version = null)
157  {
158  if (!$version) {
159  $version = $this->getVersion();
160  }
161 
162  if ($this->hasChange($version)) {
163  return $this->_changes[$version]['instance'];
164  }
165  return null;
166  }
167 
174  public function getNext($version = null)
175  {
176  if (!$version) {
177  $version = $this->getVersion();
178  }
179  if ($this->hasChange($version)) {
180  return $this->_changes[$version]['next'];
181  }
182  return key($this->getIterator());
183  }
184 
191  public function hasChange($change)
192  {
193  return array_key_exists((string) $change, $this->_changes);
194  }
195 
202  public function getPrevious($version = null)
203  {
204  if (!$version) {
205  $version = $this->getVersion();
206  }
207  if ($this->hasChange($version)) {
208  return $this->_changes[$version]['prev'];
209  }
210  return null;
211  }
212 
217  public function rollup()
218  {
219  $next = $this->getNext();
220  if (!$next) {
221  throw new ZendDbSchema_Db_Migration_Exception('No migration to rollup');
222  }
223 
224  $change = $this->getChange($next);
225  foreach ($change->getTablesConfig() as $name => $config) {
226  $schema = new ZendDbSchema_Db_Schema_Table($name);
227  $schema->setFromArray($config);
228  $schema->save();
229  }
230  $change->up();
231 
232  $this->_currentVersion = $next;
233  }
234 
239  public function rolldown()
240  {
241  if (!$this->getChange()) {
242  throw new ZendDbSchema_Db_Migration_Exception('No migration to rolldown');
243  }
244  $prev = $this->getPrevious();
245  if (!$prev) {
246  throw new ZendDbSchema_Db_Migration_Exception('Current migration is initial');
247  }
248 
249  if (!$this->getChange()->isDowngradable()) {
250  throw new ZendDbSchema_Db_Migration_Exception($this->getVersion() . ' migration is not downgradable');
251  }
252 
253  $change = $this->getChange($prev);
254  foreach ($change->getTablesConfig() as $name => $config) {
255  $schema = new ZendDbSchema_Db_Schema_Table($name);
256  $schema->setFromArray($config);
257  $schema->save();
258  }
259  $change->down();
260 
261  $this->_currentVersion = $prev;
262  }
263 
270  public function up($version = null)
271  {
272  if ($this->compareVersion($version, '=')) {
273  throw new ZendDbSchema_Db_Migration_Exception("Nothing to migrate");
274  }
275  if ($this->compareVersion($version, '<')) {
276  throw new ZendDbSchema_Db_Migration_Exception("'{$version}' is less then current");
277  }
278 
279  while ($this->compareVersion($version, '>')) {
280  $this->rollup();
281  }
282  }
283 
290  public function down($version)
291  {
292  if ($this->compareVersion($version, '=')) {
293  throw new ZendDbSchema_Db_Migration_Exception("Nothing to migrate");
294  }
295  if ($this->compareVersion($version, '>')) {
296  throw new ZendDbSchema_Db_Migration_Exception("'{$version}' is greater then current");
297  }
298 
299  while ($this->compareVersion($version, '<')) {
300  $this->rolldown();
301  }
302  }
303 
312  public function compareVersion($change, $operator = null)
313  {
314  if (!$this->hasChange($change)) {
315  throw new ZendDbSchema_Db_Migration_Exception("Change '{$change}' is not found");
316  }
317  if (!$change instanceof ZendDbSchema_Db_Migration_Change) {
318  $change = $this->getChange($change);
319  }
320 
321  $result = $change->compareVersion($this->getVersion(), $operator);
322 
323  return is_bool($result) ? !$result : -$result;
324  }
325 
331  public function isDirty()
332  {
333  $change = $this->getChange();
334 
335  foreach ($change->getTablesConfig() as $name => $config) {
336  $schema = new ZendDbSchema_Db_Schema_Table($name);
337  $schema->setFromArray($config);
338  if ($schema->isDirty()) {
339  return true;
340  }
341  }
342 
343  foreach ($change->getDatabasesConfig() as $name => $config) {
344  $schema = new ZendDbSchema_Db_Schema_Table($name);
345  $schema->setFromArray($config);
346  if ($schema->isDirty()) {
347  return true;
348  }
349  }
350  return false;
351  }
352 }