2007-08-21 21:46:59 +00:00
< ? php
/* SVN FILE: $Id$ */
/**
* Command - line database management utility to automate programmer chores .
*
* Schema is CakePHP ' s database management utility . This helps you maintain versions of
* of your database .
*
* PHP versions 4 and 5
*
* CakePHP ( tm ) : Rapid Development Framework < http :// www . cakephp . org />
* Copyright 2005 - 2007 , Cake Software Foundation , Inc .
* 1785 E . Sahara Avenue , Suite 490 - 204
* Las Vegas , Nevada 89104
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice .
*
* @ filesource
* @ copyright Copyright 2005 - 2007 , Cake Software Foundation , Inc .
* @ link http :// www . cakefoundation . org / projects / info / cakephp CakePHP ( tm ) Project
* @ package cake
* @ subpackage cake . cake . console . libs
* @ since CakePHP ( tm ) v 1.2 . 0.5550
* @ version $Revision $
* @ modifiedby $LastChangedBy $
* @ lastmodified $Date $
* @ license http :// www . opensource . org / licenses / mit - license . php The MIT License
*/
uses ( 'file' , 'model' . DS . 'schema' );
/**
* Schema is a command - line database management utility for automating programmer chores .
*
* @ package cake
* @ subpackage cake . cake . console . libs
*/
class SchemaShell extends Shell {
2007-10-27 20:00:29 +00:00
/**
* is this a dry run ?
*
* @ var boolean
* @ access private
*/
var $__dry = null ;
2007-08-21 21:46:59 +00:00
/**
* Override initialize
*
* @ access public
*/
function initialize () {
$this -> out ( 'Cake Schema Shell' );
$this -> hr ();
}
/**
* Override startup
*
* @ access public
*/
function startup () {
2007-11-24 23:12:57 +00:00
$name = null ;
if ( ! empty ( $this -> params [ 'name' ])) {
$name = $this -> params [ 'name' ];
}
$path = null ;
if ( ! empty ( $this -> params [ 'path' ])) {
$path = $this -> params [ 'path' ];
}
$file = null ;
if ( ! empty ( $this -> params [ 'file' ])) {
$file = $this -> params [ 'file' ];
}
$this -> Schema =& new CakeSchema ( compact ( 'name' , 'path' , 'file' ));
2007-08-21 23:22:15 +00:00
}
/**
* Override main
*
* @ access public
*/
function main () {
$this -> help ();
2007-08-21 21:46:59 +00:00
}
/**
* Read and output contents od schema object
* path to read as second arg
*
* @ access public
*/
function view () {
2007-08-21 23:22:15 +00:00
$File = new File ( $this -> Schema -> path . DS . 'schema.php' );
2007-08-21 21:46:59 +00:00
if ( $File -> exists ()) {
$this -> out ( $File -> read ());
exit ();
} else {
$this -> err ( __ ( 'Schema could not be found' , true ));
exit ();
}
}
/**
* Read database and Write schema object
* accepts a connection as first arg or path to save as second arg
*
* @ access public
*/
function generate () {
$this -> out ( 'Generating Schema...' );
2007-10-27 20:00:29 +00:00
$options = array ();
if ( isset ( $this -> params [ 'f' ])) {
$options = array ( 'models' => false );
}
$snapshot = false ;
if ( isset ( $this -> args [ 0 ]) && $this -> args [ 0 ] === 'snapshot' ) {
$snapshot = true ;
}
2007-11-25 16:01:49 +00:00
if ( ! $snapshot && file_exists ( $this -> Schema -> path . DS . 'schema.php' )) {
2007-10-27 20:00:29 +00:00
$snapshot = true ;
$result = $this -> in ( " Schema file exists. \n [O]verwrite \n [S]napshot \n [Q]uit \n Would you like to do? " , array ( 'o' , 's' , 'q' ), 's' );
2007-11-25 16:01:49 +00:00
if ( $result === 'q' ) {
2007-10-27 20:00:29 +00:00
exit ();
}
2007-11-25 16:01:49 +00:00
if ( $result === 'o' ) {
2007-10-27 20:00:29 +00:00
$snapshot = false ;
}
}
2007-11-08 19:06:06 +00:00
$content = $this -> Schema -> read ( $options );
2007-10-27 20:00:29 +00:00
$content [ 'file' ] = 'schema.php' ;
2007-11-08 19:06:06 +00:00
2007-11-25 16:01:49 +00:00
if ( $snapshot === true ) {
2007-10-27 20:00:29 +00:00
$Folder =& new Folder ( $this -> Schema -> path );
$result = $Folder -> read ();
$count = 1 ;
2007-11-25 16:01:49 +00:00
if ( ! empty ( $result [ 1 ])) {
2007-10-27 20:00:29 +00:00
foreach ( $result [ 1 ] as $file ) {
if ( preg_match ( '/schema/' , $file )) {
$count ++ ;
}
}
}
$content [ 'file' ] = 'schema_' . $count . '.php' ;
}
2007-08-21 21:46:59 +00:00
if ( $this -> Schema -> write ( $content )) {
2007-10-27 20:00:29 +00:00
$this -> out ( sprintf ( __ ( 'Schema file: %s generated' , true ), $content [ 'file' ]));
2007-08-21 21:46:59 +00:00
exit ();
} else {
2007-10-27 20:00:29 +00:00
$this -> err ( __ ( 'Schema file: %s generated' , true ));
2007-08-21 21:46:59 +00:00
exit ();
}
}
/**
* Dump Schema object to sql file
* if first arg == write , file will be written to sql file
* or it will output sql
*
* @ access public
*/
function dump () {
$write = false ;
$Schema = $this -> Schema -> load ();
2007-11-25 16:01:49 +00:00
if ( ! $Schema ) {
2007-11-24 23:12:57 +00:00
$this -> err ( __ ( 'Schema could not be loaded' , true ));
exit ();
}
2007-08-23 00:57:00 +00:00
if ( ! empty ( $this -> args [ 0 ])) {
2007-11-25 16:01:49 +00:00
if ( $this -> args [ 0 ] == 'true' ) {
2007-08-23 00:57:00 +00:00
$write = Inflector :: underscore ( $this -> Schema -> name );
} else {
$write = $this -> args [ 0 ];
}
}
2007-08-21 21:46:59 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> Schema -> connection );
2007-08-23 00:57:00 +00:00
$contents = " # " . $Schema -> name . " sql generated on: " . date ( 'Y-m-d H:m:s' ) . " : " . time () . " \n \n " ;
$contents .= $db -> dropSchema ( $Schema ) . " \n \n " . $db -> createSchema ( $Schema );
2007-11-25 16:01:49 +00:00
if ( $write ) {
if ( strpos ( $write , '.sql' ) === false ) {
2007-08-23 00:57:00 +00:00
$write .= '.sql' ;
}
$File = new File ( $this -> Schema -> path . DS . $write , true );
2007-11-25 16:01:49 +00:00
if ( $File -> write ( $contents )) {
2007-09-18 04:16:04 +00:00
$this -> out ( sprintf ( __ ( 'SQL dump file created in %s' , true ), $File -> pwd ()));
2007-08-21 21:46:59 +00:00
exit ();
} else {
$this -> err ( __ ( 'SQL dump could not be created' , true ));
exit ();
}
}
$this -> out ( $contents );
return $contents ;
}
/**
2007-10-27 20:00:29 +00:00
* Run database commands : create , update
2007-08-21 21:46:59 +00:00
*
* @ access public
*/
2007-10-27 20:00:29 +00:00
function run () {
if ( ! isset ( $this -> args [ 0 ])) {
$this -> err ( 'command not found' );
exit ();
}
$command = $this -> args [ 0 ];
$this -> Dispatch -> shiftArgs ();
2007-11-25 16:01:49 +00:00
$name = null ;
if ( isset ( $this -> args [ 0 ])) {
$name = $this -> args [ 0 ];
}
if ( isset ( $this -> params [ 'dry' ])) {
2007-10-27 20:00:29 +00:00
$this -> __dry = true ;
$this -> out ( __ ( 'Performing a dry run.' , true ));
}
2007-11-25 16:01:49 +00:00
$options = array ( 'name' => $name , 'file' => $this -> Schema -> file );
if ( isset ( $this -> params [ 's' ])) {
2007-10-27 20:00:29 +00:00
$options = array ( 'file' => 'schema_' . $this -> params [ 's' ] . '.php' );
}
$Schema = $this -> Schema -> load ( $options );
2007-12-18 18:19:30 +00:00
2007-11-25 16:01:49 +00:00
if ( ! $Schema ) {
$this -> err ( sprintf ( __ ( '%s could not be loaded' , true ), $this -> Schema -> file ));
2007-10-27 20:00:29 +00:00
exit ();
}
$table = null ;
2007-11-25 16:01:49 +00:00
if ( isset ( $this -> args [ 1 ])) {
2007-10-27 20:00:29 +00:00
$table = $this -> args [ 1 ];
}
switch ( $command ) {
case 'create' :
$this -> __create ( $Schema , $table );
break ;
case 'update' :
$this -> __update ( $Schema , $table );
break ;
default :
2007-12-15 02:06:10 +00:00
$this -> err ( __ ( 'command not found' , true ));
2007-10-27 20:00:29 +00:00
exit ();
}
}
/**
* Create database from Schema object
* Should be called via the run method
*
* @ access private
*/
function __create ( $Schema , $table = null ) {
2007-08-21 21:46:59 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> Schema -> connection );
2007-12-15 02:06:10 +00:00
2007-12-18 18:19:30 +00:00
$drop = $create = array ();
2007-10-27 20:00:29 +00:00
2007-12-18 18:19:30 +00:00
if ( ! $table ) {
foreach ( $Schema -> tables as $table => $fields ) {
$drop [ $table ] = $db -> dropSchema ( $Schema , $table );
$create [ $table ] = $db -> createSchema ( $Schema , $table );
}
} elseif ( isset ( $Schema -> tables [ $table ])) {
$drop [ $table ] = $db -> dropSchema ( $Schema , $table );
$create [ $table ] = $db -> createSchema ( $Schema , $table );
}
if ( empty ( $drop ) || empty ( $create )) {
$this -> out ( __ ( 'Schema is up to date.' , true ));
exit ();
2007-08-21 21:46:59 +00:00
}
2007-12-18 18:19:30 +00:00
$this -> out ( " \n " . __ ( 'The following tables will drop.' , true ));
$this -> out ( array_keys ( $drop ));
if ( 'y' == $this -> in ( __ ( 'Are you sure you want to drop the tables?' , true ), array ( 'y' , 'n' ), 'n' )) {
$this -> out ( 'Dropping tables.' );
$this -> __run ( $drop , 'drop' );
}
$this -> out ( " \n " . __ ( 'The following tables will create.' , true ));
$this -> out ( array_keys ( $create ));
if ( 'y' == $this -> in ( __ ( 'Are you sure you want to create the tables?' , true ), array ( 'y' , 'n' ), 'y' )) {
$this -> out ( 'Creating tables.' );
$this -> __run ( $create , 'create' );
}
2007-12-15 02:06:10 +00:00
$this -> out ( __ ( 'End create.' , true ));
2007-08-21 21:46:59 +00:00
}
/**
* Update database with Schema object
2007-10-27 20:00:29 +00:00
* Should be called via the run method
2007-08-21 21:46:59 +00:00
*
2007-10-27 20:00:29 +00:00
* @ access private
2007-08-21 21:46:59 +00:00
*/
2007-10-27 20:00:29 +00:00
function __update ( $Schema , $table = null ) {
2007-12-15 02:06:10 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> Schema -> connection );
2007-08-21 21:46:59 +00:00
$this -> out ( 'Comparing Database to Schema...' );
$Old = $this -> Schema -> read ();
$compare = $this -> Schema -> compare ( $Old , $Schema );
2007-12-15 02:06:10 +00:00
$contents = array ();
2007-08-21 23:22:15 +00:00
2007-12-15 02:06:10 +00:00
if ( ! $table ) {
foreach ( $compare as $table => $changes ) {
$contents [ $table ] = $db -> alterSchema ( array ( $table => $changes ), $table );
}
} elseif ( isset ( $compare [ $table ])) {
$contents [ $table ] = $db -> alterSchema ( array ( $table => $compare [ $table ]), $table );
}
2007-08-21 22:46:05 +00:00
2007-11-25 16:01:49 +00:00
if ( empty ( $contents )) {
2007-10-27 20:00:29 +00:00
$this -> out ( __ ( 'Schema is up to date.' , true ));
2007-08-21 21:46:59 +00:00
exit ();
}
2007-12-15 02:06:10 +00:00
$this -> out ( " \n " . __ ( 'The following statements will run.' , true ));
$this -> out ( array_map ( 'trim' , $contents ));
if ( 'y' == $this -> in ( __ ( 'Are you sure you want to alter the tables?' , true ), array ( 'y' , 'n' ), 'n' )) {
$this -> out ( '' );
$this -> out ( __ ( 'Updating Database...' , true ));
$this -> __run ( $contents , 'update' );
}
$this -> out ( __ ( 'End update.' , true ));
}
/**
* runs sql from __create () or __update ()
*
* @ access private
*/
function __run ( $contents , $event ) {
2007-12-18 18:19:30 +00:00
if ( empty ( $contents )) {
$this -> err ( __ ( 'Sql could not be run' , true ));
return ;
}
2007-12-15 02:06:10 +00:00
Configure :: write ( 'debug' , 2 );
$db =& ConnectionManager :: getDataSource ( $this -> Schema -> connection );
$db -> fullDebug = true ;
$errors = array ();
foreach ( $contents as $table => $sql ) {
if ( empty ( $sql )) {
$this -> out ( sprintf ( __ ( '%s is up to date.' , true ), $table ));
} else {
if ( $this -> __dry === true ) {
$this -> out ( sprintf ( __ ( 'Dry run for %s :' , true ), $table ));
$this -> out ( $sql );
} else {
if ( ! $this -> Schema -> before ( array ( $event => $table ))) {
2007-10-27 20:00:29 +00:00
return false ;
}
2007-12-15 02:06:10 +00:00
if ( ! $db -> _execute ( $sql )) {
$error = $db -> lastError ();
2007-10-27 20:00:29 +00:00
}
2007-12-15 02:06:10 +00:00
$this -> Schema -> after ( array ( $event => $table , 'errors' => $errors ));
if ( isset ( $error )) {
$this -> out ( $errors );
} elseif ( $this -> __dry !== true ) {
$this -> out ( sprintf ( __ ( '%s updated.' , true ), $table ));
}
}
2007-08-21 21:46:59 +00:00
}
}
}
/**
* Displays help contents
*
2007-10-22 05:52:20 +00:00
* @ access public
2007-08-21 21:46:59 +00:00
*/
function help () {
2007-10-27 20:00:29 +00:00
$this -> out ( " The Schema Shell generates a schema object from \n \t \t the database and updates the database from the schema. " );
2007-08-21 21:46:59 +00:00
$this -> hr ();
$this -> out ( " Usage: cake schema <command> <arg1> <arg2>... " );
$this -> hr ();
2007-08-21 23:22:15 +00:00
$this -> out ( 'Params:' );
2007-10-27 20:00:29 +00:00
$this -> out ( " \n \t -connection <config> \n \t \t set db config <config>. uses 'default' if none is specified " );
$this -> out ( " \n \t -path <dir> \n \t \t path <dir> to read and write schema.php. \n \t \t default path: " . $this -> Schema -> path );
$this -> out ( " \n \t -file <name> \n \t \t file <name> to read and write. \n \t \t default file: " . $this -> Schema -> file );
$this -> out ( " \n \t -s <number> \n \t \t snapshot <number> to use for run. " );
$this -> out ( " \n \t -dry \n \t \t Perform a dry run on 'run' commands. \n \t \t Queries will be output to window instead of executed. " );
$this -> out ( " \n \t -f \n \t \t force 'generate' to create a new schema. " );
2007-08-21 21:46:59 +00:00
$this -> out ( 'Commands:' );
$this -> out ( " \n \t schema help \n \t \t shows this help message. " );
2007-08-21 23:22:15 +00:00
$this -> out ( " \n \t schema view \n \t \t read and output contents of schema file " );
2007-10-27 20:00:29 +00:00
$this -> out ( " \n \t schema generate \n \t \t reads from 'connection' writes to 'path' \n \t \t To force genaration of all tables into the schema, use the -f param. " );
$this -> out ( " \n \t schema dump <filename> \n \t \t dump database sql based on schema file to filename in schema path. \n \t \t if filename is true, default will use the app directory name. " );
$this -> out ( " \n \t schema run create <table> \n \t \t drop tables and create database based on schema file \n \t \t optional <table> arg for creating only one table \n \t \t pass the -s param with a number to use a snapshot \n \t \t To see the changes, perform a dry run with the -dry param " );
$this -> out ( " \n \t schema run update <table> \n \t \t alter tables based on schema file \n \t \t optional <table> arg for altering only one table. \n \t \t To use a snapshot, pass the -s param with the snapshot number \n \t \t To see the changes, perform a dry run with the -dry param " );
2007-08-21 21:46:59 +00:00
$this -> out ( " " );
exit ();
}
}
?>