mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2025-01-18 10:36:16 +00:00
Adding Schema support, updated fixtures, deprecated loadInfo, changed Dbo::describe in all dbos, fixed tests,
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@5563 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
parent
2ff0e4f54f
commit
8bb67d9f6a
29 changed files with 1514 additions and 697 deletions
223
cake/console/libs/schema.php
Normal file
223
cake/console/libs/schema.php
Normal file
|
@ -0,0 +1,223 @@
|
|||
<?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 {
|
||||
/**
|
||||
* Override initialize
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function initialize() {
|
||||
$this->out('Cake Schema Shell');
|
||||
$this->hr();
|
||||
}
|
||||
/**
|
||||
* Override startup
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function startup() {
|
||||
$this->Schema =& new CakeSchema(array('path'=> CONFIGS .'sql'));
|
||||
}
|
||||
/**
|
||||
* Read and output contents od schema object
|
||||
* path to read as second arg
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function view() {
|
||||
$path = TMP;
|
||||
if (!empty($this->args[0])) {
|
||||
$path = $this->args[0];
|
||||
}
|
||||
$File = new File($path . DS .'schema.php');
|
||||
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
|
||||
* @return void
|
||||
*/
|
||||
function generate() {
|
||||
$this->out('Generating Schema...');
|
||||
if (!empty($this->args[0])) {
|
||||
$this->Schema->connection = $this->args[0];
|
||||
}
|
||||
if (!empty($this->args[1])) {
|
||||
$this->Schema->path = $this->args[1];
|
||||
}
|
||||
|
||||
$content = $this->Schema->read();
|
||||
if ($this->Schema->write($content)) {
|
||||
$this->out(__('Schema file created.', true));
|
||||
exit();
|
||||
} else {
|
||||
$this->err(__('Schema could not be created', true));
|
||||
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
|
||||
* @return void
|
||||
*/
|
||||
function dump() {
|
||||
$write = false;
|
||||
if (!empty($this->args[0])) {
|
||||
if($this->args[0] == 'write') {
|
||||
$write = true;
|
||||
}
|
||||
}
|
||||
if (!empty($this->args[1])) {
|
||||
$this->Schema->path = $this->args[1];
|
||||
}
|
||||
$Schema = $this->Schema->load();
|
||||
$db =& ConnectionManager::getDataSource($this->Schema->connection);
|
||||
$contents = $db->dropSchema($Schema) . $db->createSchema($Schema);
|
||||
if($write === true) {
|
||||
$File = new File($this->Schema->path . DS . Inflector::underscore($this->Schema->name) .'.sql', true);
|
||||
if($File->write($contents)) {
|
||||
$this->out(__('SQL dump file created in '. $File->pwd(), true));
|
||||
exit();
|
||||
} else {
|
||||
$this->err(__('SQL dump could not be created', true));
|
||||
exit();
|
||||
}
|
||||
}
|
||||
$this->out($contents);
|
||||
return $contents;
|
||||
}
|
||||
/**
|
||||
* Create database from Schema object
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function create() {
|
||||
$Schema = $this->Schema->load();
|
||||
$db =& ConnectionManager::getDataSource($this->Schema->connection);
|
||||
$drop = $db->dropSchema($Schema);
|
||||
$this->out($drop);
|
||||
if('y' == $this->in('Are you sure you want to drop tables and create your database?', array('y', 'n'), 'n')) {
|
||||
$contents = $db->createSchema($Schema);
|
||||
$this->out('Updating Database...');
|
||||
if ($db->_execute($contents)) {
|
||||
$this->out(__('Database created', true));
|
||||
exit();
|
||||
} else {
|
||||
$this->err(__('Database could not be created', true));
|
||||
$this->err($db->lastError());
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Update database with Schema object
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function update() {
|
||||
$this->out('Comparing Database to Schema...');
|
||||
if (!empty($this->args[0])) {
|
||||
$this->Schema->connection = $this->args[0];
|
||||
}
|
||||
if (!empty($this->args[1])) {
|
||||
$this->Schema->path = $this->args[1];
|
||||
}
|
||||
$Old = $this->Schema->read();
|
||||
$Schema = $this->Schema->load();
|
||||
$compare = $this->Schema->compare($Old, $Schema);
|
||||
|
||||
$db =& ConnectionManager::getDataSource($this->Schema->connection);
|
||||
$db->fullDebug = true;
|
||||
Configure::write('debug', 2);
|
||||
$contents = $db->alterSchema($compare);
|
||||
if(empty($contents)) {
|
||||
$this->out(__('Current database is up to date.', true));
|
||||
exit();
|
||||
} else {
|
||||
$this->out($contents);
|
||||
}
|
||||
if('y' == $this->in('Are you sure you want to update your database?', array('y', 'n'), 'n')) {
|
||||
$this->out('Updating Database...');
|
||||
if ($db->_execute($contents)) {
|
||||
$this->out(__('Database updated', true));
|
||||
exit();
|
||||
} else {
|
||||
$this->err(__('Database could not be updated', true));
|
||||
$this->err($db->lastError());
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Displays help contents
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function help() {
|
||||
$this->out('The Schema Shell generates a schema object from the database and updates the database from the schema.');
|
||||
$this->hr();
|
||||
$this->out("Usage: cake schema <command> <arg1> <arg2>...");
|
||||
$this->hr();
|
||||
$this->out('Commands:');
|
||||
$this->out("\n\tschema help\n\t\tshows this help message.");
|
||||
$this->out("\n\tschema view <path>\n\t\tread and output contents of schema file");
|
||||
$this->out("\n\tschema generate <connection> <path>\n\t\treads from 'connection' writes to 'path'");
|
||||
$this->out("\n\tschema dump 'write' <path>\n\t\tdump database sql based on schema file");
|
||||
$this->out("\n\tschema create <path>\n\t\tdrop tables and create database based on schema file");
|
||||
$this->out("\n\tschema update <path>\n\t\tmodify database based on schema file");
|
||||
$this->out("");
|
||||
exit();
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -112,9 +112,9 @@ class ModelTask extends Shell {
|
|||
$validate = array();
|
||||
|
||||
if (array_search($useTable, $this->__tables) !== false && (low($wannaDoValidation) == 'y' || low($wannaDoValidation) == 'yes')) {
|
||||
foreach ($modelFields as $field) {
|
||||
foreach ($modelFields as $fieldName => $field) {
|
||||
$this->out('');
|
||||
$prompt = 'Name: ' . $field['name'] . "\n";
|
||||
$prompt = 'Name: ' . $fieldName . "\n";
|
||||
$prompt .= 'Type: ' . $field['type'] . "\n";
|
||||
$prompt .= '---------------------------------------------------------------'."\n";
|
||||
$prompt .= 'Please select one of the following validation options:'."\n";
|
||||
|
@ -126,7 +126,7 @@ class ModelTask extends Shell {
|
|||
$prompt .= "5- Do not do any validation on this field.\n\n";
|
||||
$prompt .= "... or enter in a valid regex validation string.\n\n";
|
||||
|
||||
if ($field['null'] == 1 || $field['name'] == $primaryKey || $field['name'] == 'created' || $field['name'] == 'modified') {
|
||||
if ($field['null'] == 1 || $fieldName == $primaryKey || $fieldName == 'created' || $fieldName == 'modified') {
|
||||
$validation = $this->in($prompt, null, '5');
|
||||
} else {
|
||||
$validation = $this->in($prompt, null, '1');
|
||||
|
@ -134,21 +134,21 @@ class ModelTask extends Shell {
|
|||
|
||||
switch ($validation) {
|
||||
case '1':
|
||||
$validate[$field['name']] = 'VALID_NOT_EMPTY';
|
||||
$validate[$fieldName] = 'VALID_NOT_EMPTY';
|
||||
break;
|
||||
case '2':
|
||||
$validate[$field['name']] = 'VALID_EMAIL';
|
||||
$validate[$fieldName] = 'VALID_EMAIL';
|
||||
break;
|
||||
case '3':
|
||||
$validate[$field['name']] = 'VALID_NUMBER';
|
||||
$validate[$fieldName] = 'VALID_NUMBER';
|
||||
break;
|
||||
case '4':
|
||||
$validate[$field['name']] = 'VALID_YEAR';
|
||||
$validate[$fieldName] = 'VALID_YEAR';
|
||||
break;
|
||||
case '5':
|
||||
break;
|
||||
default:
|
||||
$validate[$field['name']] = $validation;
|
||||
$validate[$fieldName] = $validation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -161,13 +161,13 @@ class ModelTask extends Shell {
|
|||
$possibleKeys = array();
|
||||
//Look for belongsTo
|
||||
$i = 0;
|
||||
foreach ($modelFields as $field) {
|
||||
$offset = strpos($field['name'], '_id');
|
||||
if ($field['name'] != $primaryKey && $offset !== false) {
|
||||
$tmpModelName = $this->_modelNameFromKey($field['name']);
|
||||
foreach ($modelFields as $fieldName => $field) {
|
||||
$offset = strpos($fieldName, '_id');
|
||||
if ($fieldName != $primaryKey && $offset !== false) {
|
||||
$tmpModelName = $this->_modelNameFromKey($fieldName);
|
||||
$associations['belongsTo'][$i]['alias'] = $tmpModelName;
|
||||
$associations['belongsTo'][$i]['className'] = $tmpModelName;
|
||||
$associations['belongsTo'][$i]['foreignKey'] = $field['name'];
|
||||
$associations['belongsTo'][$i]['foreignKey'] = $fieldName;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
@ -179,17 +179,17 @@ class ModelTask extends Shell {
|
|||
$modelFieldsTemp = $db->describe($tempOtherModel);
|
||||
foreach ($modelFieldsTemp as $field) {
|
||||
if ($field['type'] == 'integer' || $field['type'] == 'string') {
|
||||
$possibleKeys[$otherTable][] = $field['name'];
|
||||
$possibleKeys[$otherTable][] = $fieldName;
|
||||
}
|
||||
if ($field['name'] != $primaryKey && $field['name'] == $this->_modelKey($currentModelName)) {
|
||||
if ($fieldName != $primaryKey && $fieldName == $this->_modelKey($currentModelName)) {
|
||||
$tmpModelName = $this->_modelName($otherTable);
|
||||
$associations['hasOne'][$j]['alias'] = $tmpModelName;
|
||||
$associations['hasOne'][$j]['className'] = $tmpModelName;
|
||||
$associations['hasOne'][$j]['foreignKey'] = $field['name'];
|
||||
$associations['hasOne'][$j]['foreignKey'] = $fieldName;
|
||||
|
||||
$associations['hasMany'][$j]['alias'] = $tmpModelName;
|
||||
$associations['hasMany'][$j]['className'] = $tmpModelName;
|
||||
$associations['hasMany'][$j]['foreignKey'] = $field['name'];
|
||||
$associations['hasMany'][$j]['foreignKey'] = $fieldName;
|
||||
$j++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,14 +64,12 @@ class ErrorHandler extends Object{
|
|||
require CAKE . 'dispatcher.php';
|
||||
}
|
||||
$this->__dispatch =& new Dispatcher();
|
||||
|
||||
if (!class_exists('appcontroller')) {
|
||||
loadController(null);
|
||||
}
|
||||
if ($__previousError != array($method, $messages)) {
|
||||
$__previousError = array($method, $messages);
|
||||
|
||||
if (!class_exists('AppController')) {
|
||||
loadController(null);
|
||||
}
|
||||
|
||||
$this->controller =& new AppController();
|
||||
if (!empty($this->controller->uses)) {
|
||||
$this->controller->constructClasses();
|
||||
|
@ -84,7 +82,7 @@ class ErrorHandler extends Object{
|
|||
return $this->controller->appError($method, $messages);
|
||||
}
|
||||
} else {
|
||||
$this->controller =& new Controller();
|
||||
$this->controller =& new AppController();
|
||||
$this->controller->cacheAction = false;
|
||||
}
|
||||
if (Configure::read() > 0 || $method == 'error') {
|
||||
|
|
|
@ -192,6 +192,270 @@ class DataSource extends Object {
|
|||
$this->setConfig(func_get_arg(0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Datsrouce Query abstraction
|
||||
*
|
||||
* @return resource Result resource identifier
|
||||
*/
|
||||
function query() {
|
||||
$args = func_get_args();
|
||||
$fields = null;
|
||||
$order = null;
|
||||
$limit = null;
|
||||
$page = null;
|
||||
$recursive = null;
|
||||
|
||||
if (count($args) == 1) {
|
||||
return $this->fetchAll($args[0]);
|
||||
|
||||
} elseif (count($args) > 1 && (strpos(low($args[0]), 'findby') === 0 || strpos(low($args[0]), 'findallby') === 0)) {
|
||||
$params = $args[1];
|
||||
|
||||
if (strpos(strtolower($args[0]), 'findby') === 0) {
|
||||
$all = false;
|
||||
$field = Inflector::underscore(preg_replace('/findBy/i', '', $args[0]));
|
||||
} else {
|
||||
$all = true;
|
||||
$field = Inflector::underscore(preg_replace('/findAllBy/i', '', $args[0]));
|
||||
}
|
||||
|
||||
$or = (strpos($field, '_or_') !== false);
|
||||
if ($or) {
|
||||
$field = explode('_or_', $field);
|
||||
} else {
|
||||
$field = explode('_and_', $field);
|
||||
}
|
||||
$off = count($field) - 1;
|
||||
|
||||
if (isset($params[1 + $off])) {
|
||||
$fields = $params[1 + $off];
|
||||
}
|
||||
|
||||
if (isset($params[2 + $off])) {
|
||||
$order = $params[2 + $off];
|
||||
}
|
||||
|
||||
if (!array_key_exists(0, $params)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$c = 0;
|
||||
$query = array();
|
||||
foreach ($field as $f) {
|
||||
if (!is_array($params[$c]) && !empty($params[$c]) && $params[$c] !== true && $params[$c] !== false) {
|
||||
$query[$args[2]->name . '.' . $f] = '= ' . $params[$c];
|
||||
} else {
|
||||
$query[$args[2]->name . '.' . $f] = $params[$c];
|
||||
}
|
||||
$c++;
|
||||
}
|
||||
|
||||
if ($or) {
|
||||
$query = array('OR' => $query);
|
||||
}
|
||||
|
||||
if ($all) {
|
||||
|
||||
if (isset($params[3 + $off])) {
|
||||
$limit = $params[3 + $off];
|
||||
}
|
||||
|
||||
if (isset($params[4 + $off])) {
|
||||
$page = $params[4 + $off];
|
||||
}
|
||||
|
||||
if (isset($params[5 + $off])) {
|
||||
$recursive = $params[5 + $off];
|
||||
}
|
||||
return $args[2]->findAll($query, $fields, $order, $limit, $page, $recursive);
|
||||
} else {
|
||||
if (isset($params[3 + $off])) {
|
||||
$recursive = $params[3 + $off];
|
||||
}
|
||||
return $args[2]->find($query, $fields, $order, $recursive);
|
||||
}
|
||||
} else {
|
||||
if (isset($args[1]) && $args[1] === true) {
|
||||
return $this->fetchAll($args[0], true);
|
||||
}
|
||||
return $this->fetchAll($args[0], false);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns an array of all result rows for a given SQL query.
|
||||
* Returns false if no rows matched.
|
||||
*
|
||||
* @param string $sql SQL statement
|
||||
* @param boolean $cache Enables returning/storing cached query results
|
||||
* @return array Array of resultset rows, or false if no rows matched
|
||||
*/
|
||||
function fetchAll($sql, $cache = true, $modelName = null) {
|
||||
if ($cache && isset($this->_queryCache[$sql])) {
|
||||
if (preg_match('/^\s*select/i', $sql)) {
|
||||
return $this->_queryCache[$sql];
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->execute($sql)) {
|
||||
$out = array();
|
||||
|
||||
while ($item = $this->fetchRow()) {
|
||||
$out[] = $item;
|
||||
}
|
||||
|
||||
if ($cache) {
|
||||
if (strpos(trim(strtolower($sql)), 'select') !== false) {
|
||||
$this->_queryCache[$sql] = $out;
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Caches/returns cached results for child instances
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function listSources($data = null) {
|
||||
if ($this->cacheSources === false) {
|
||||
return null;
|
||||
}
|
||||
if ($this->_sources != null) {
|
||||
return $this->_sources;
|
||||
}
|
||||
|
||||
if (Configure::read() > 0) {
|
||||
$expires = "+30 seconds";
|
||||
} else {
|
||||
$expires = "+999 days";
|
||||
}
|
||||
|
||||
if ($data != null) {
|
||||
$data = serialize($data);
|
||||
}
|
||||
$filename = ConnectionManager::getSourceName($this) . '_' . preg_replace("/[^A-Za-z0-9_-]/", "_", $this->config['database']) . '_list';
|
||||
$new = cache('models' . DS . $filename, $data, $expires);
|
||||
|
||||
if ($new != null) {
|
||||
$new = unserialize($new);
|
||||
$this->_sources = $new;
|
||||
}
|
||||
return $new;
|
||||
}
|
||||
/**
|
||||
* Convenience method for DboSource::listSources(). Returns source names in lowercase.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function sources() {
|
||||
$return = array_map('strtolower', $this->listSources());
|
||||
return $return;
|
||||
}
|
||||
/**
|
||||
* Returns a Model description (metadata) or null if none found.
|
||||
*
|
||||
* @param Model $model
|
||||
* @return mixed
|
||||
*/
|
||||
function describe($model) {
|
||||
if ($this->cacheSources === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isset($this->__descriptions[$model->tablePrefix.$model->table])) {
|
||||
return $this->__descriptions[$model->tablePrefix.$model->table];
|
||||
}
|
||||
$cache = $this->__cacheDescription($model->tablePrefix.$model->table);
|
||||
|
||||
if ($cache !== null) {
|
||||
$this->__descriptions[$model->tablePrefix.$model->table] =& $cache;
|
||||
return $cache;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Converts column types to basic types
|
||||
*
|
||||
* @param string $real Real column type (i.e. "varchar(255)")
|
||||
* @return string Abstract column type (i.e. "string")
|
||||
*/
|
||||
function column($real) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param unknown_type $model
|
||||
* @param unknown_type $fields
|
||||
* @param unknown_type $values
|
||||
* @return unknown
|
||||
*/
|
||||
function create(&$model, $fields = null, $values = null) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param unknown_type $model
|
||||
* @param unknown_type $queryData
|
||||
* @return unknown
|
||||
*/
|
||||
function read(&$model, $queryData = array()) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param unknown_type $model
|
||||
* @param unknown_type $fields
|
||||
* @param unknown_type $values
|
||||
* @return unknown
|
||||
*/
|
||||
function update(&$model, $fields = null, $values = null) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param unknown_type $model
|
||||
* @param unknown_type $id
|
||||
*/
|
||||
function delete(&$model, $id = null) {
|
||||
if ($id == null) {
|
||||
$id = $model->id;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the ID generated from the previous INSERT operation.
|
||||
*
|
||||
* @param unknown_type $source
|
||||
* @return in
|
||||
*/
|
||||
function lastInsertId($source = null) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns the ID generated from the previous INSERT operation.
|
||||
*
|
||||
* @param unknown_type $source
|
||||
* @return in
|
||||
*/
|
||||
function lastNumRows($source = null) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns the ID generated from the previous INSERT operation.
|
||||
*
|
||||
* @param unknown_type $source
|
||||
* @return in
|
||||
*/
|
||||
function lastAffected($source = null) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns true if the DataSource supports the given interface (method)
|
||||
*
|
||||
|
@ -249,116 +513,6 @@ class DataSource extends Object {
|
|||
}
|
||||
return $new;
|
||||
}
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function conditions($conditions) {
|
||||
return $conditions;
|
||||
}
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param unknown_type $name
|
||||
* @return unknown
|
||||
*/
|
||||
function name($name) {
|
||||
return $name;
|
||||
}
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param unknown_type $value
|
||||
* @return unknown
|
||||
*/
|
||||
function value($value) {
|
||||
return $value;
|
||||
}
|
||||
/**
|
||||
* Returns a Model description (metadata) or null if none found.
|
||||
*
|
||||
* @param Model $model
|
||||
* @return mixed
|
||||
*/
|
||||
function describe($model) {
|
||||
if ($this->cacheSources === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isset($this->__descriptions[$model->tablePrefix.$model->table])) {
|
||||
return $this->__descriptions[$model->tablePrefix.$model->table];
|
||||
}
|
||||
$cache = $this->__cacheDescription($model->tablePrefix.$model->table);
|
||||
|
||||
if ($cache !== null) {
|
||||
$this->__descriptions[$model->tablePrefix.$model->table] =& $cache;
|
||||
return $cache;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param unknown_type $model
|
||||
* @param unknown_type $fields
|
||||
* @param unknown_type $values
|
||||
* @return unknown
|
||||
*/
|
||||
function create(&$model, $fields = null, $values = null) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param unknown_type $model
|
||||
* @param unknown_type $queryData
|
||||
* @return unknown
|
||||
*/
|
||||
function read(&$model, $queryData = array()) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param unknown_type $model
|
||||
* @param unknown_type $fields
|
||||
* @param unknown_type $values
|
||||
* @return unknown
|
||||
*/
|
||||
function update(&$model, $fields = null, $values = null) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param unknown_type $model
|
||||
* @param unknown_type $id
|
||||
*/
|
||||
function delete(&$model, $id = null) {
|
||||
if ($id == null) {
|
||||
$id = $model->id;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param mixed $fields
|
||||
* @return mixed
|
||||
*/
|
||||
function fields($fields) {
|
||||
return $fields;
|
||||
}
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param Model $model
|
||||
* @param unknown_type $fields
|
||||
* @return unknown
|
||||
*/
|
||||
function getColumnType(&$model, $fields) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
|
|
|
@ -221,8 +221,9 @@ class DboAdodb extends DboSource {
|
|||
$cols = $this->_adodb->MetaColumns($this->fullTableName($model, false));
|
||||
|
||||
foreach ($cols as $column) {
|
||||
$fields[] = array('name' => $column->name,
|
||||
'type' => $this->column($column->type));
|
||||
$fields[$column->name] = array(
|
||||
'type' => $this->column($column->type)
|
||||
);
|
||||
}
|
||||
|
||||
$this->__cacheDescription($this->fullTableName($model, false), $fields);
|
||||
|
|
|
@ -216,8 +216,7 @@ class DboDb2 extends DboSource {
|
|||
$result = db2_columns($this->connection, '', '', strtoupper($this->fullTableName($model)));
|
||||
|
||||
while (db2_fetch_row($result)) {
|
||||
$fields[] = array(
|
||||
'name' => strtolower(db2_result($result, 'COLUMN_NAME')),
|
||||
$fields[strtolower(db2_result($result, 'COLUMN_NAME'))] = array(
|
||||
'type' => db2_result($result, 'TYPE_NAME'),
|
||||
'null' => db2_result($result, 'NULLABLE'),
|
||||
'default' => db2_result($result, 'COLUMN_DEF'));
|
||||
|
|
|
@ -205,11 +205,11 @@ class DboFirebird extends DboSource {
|
|||
$col_info = ibase_field_info($rs, $i);
|
||||
$col_info['type'] = $this->column($col_info['type']);
|
||||
|
||||
$fields[] = array(
|
||||
'name' => strtolower($col_info['name']),
|
||||
'type' => $col_info['type'],
|
||||
'null' => '',
|
||||
'length' => $col_info['length']);
|
||||
$fields[strtolower($col_info['name'])] = array(
|
||||
'type' => $col_info['type'],
|
||||
'null' => '',
|
||||
'length' => $col_info['length']
|
||||
);
|
||||
}
|
||||
$this->__cacheDescription($model->tablePrefix . $model->table, $fields);
|
||||
return $fields;
|
||||
|
|
|
@ -575,16 +575,6 @@ class DboMssql extends DboSource {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function buildSchemaQuery($schema) {
|
||||
$search = array('{AUTOINCREMENT}', '{PRIMARY}', '{UNSIGNED}', '{FULLTEXT}', '{BOOLEAN}', '{UTF_8}');
|
||||
|
||||
$replace = array('int(11) not null auto_increment', 'primary key', 'unsigned', 'FULLTEXT',
|
||||
'enum (\'true\', \'false\') NOT NULL default \'true\'', '/*!40100 CHARACTER SET utf8 COLLATE utf8_unicode_ci */');
|
||||
|
||||
$query = trim(r($search, $replace, $schema));
|
||||
return $query;
|
||||
}
|
||||
/**
|
||||
* Inserts multiple values into a join table
|
||||
*
|
||||
|
@ -598,5 +588,6 @@ class DboMssql extends DboSource {
|
|||
$this->query("INSERT INTO {$table} ({$fields}) VALUES {$values[$x]}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -163,12 +163,10 @@ class DboMysql extends DboSource {
|
|||
* @return array Fields in table. Keys are name and type
|
||||
*/
|
||||
function describe(&$model) {
|
||||
|
||||
$cache = parent::describe($model);
|
||||
if ($cache != null) {
|
||||
return $cache;
|
||||
}
|
||||
|
||||
$fields = false;
|
||||
$cols = $this->query('DESCRIBE ' . $this->fullTableName($model));
|
||||
|
||||
|
@ -178,16 +176,20 @@ class DboMysql extends DboSource {
|
|||
$column[0] = $column[$colKey[0]];
|
||||
}
|
||||
if (isset($column[0])) {
|
||||
$fields[] = array(
|
||||
'name' => $column[0]['Field'],
|
||||
$fields[$column[0]['Field']] = array(
|
||||
'type' => $this->column($column[0]['Type']),
|
||||
'null' => ($column[0]['Null'] == 'YES' ? true : false),
|
||||
'default' => $column[0]['Default'],
|
||||
'length' => $this->length($column[0]['Type'])
|
||||
'length' => $this->length($column[0]['Type']),
|
||||
);
|
||||
if(!empty($column[0]['Key']) && isset($this->index[$column[0]['Key']])) {
|
||||
$fields[$column[0]['Field']]['key'] = $this->index[$column[0]['Key']];
|
||||
}
|
||||
if(!empty($column[0]['Extra'])) {
|
||||
$fields[$column[0]['Field']]['extra'] = $column[0]['Extra'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->__cacheDescription($this->fullTableName($model, false), $fields);
|
||||
return $fields;
|
||||
}
|
||||
|
@ -451,6 +453,33 @@ class DboMysql extends DboSource {
|
|||
function getEncoding() {
|
||||
return mysql_client_encoding($this->connection);
|
||||
}
|
||||
/**
|
||||
* Returns an array of the indexes in given table name.
|
||||
*
|
||||
* @param string $model Name of model to inspect
|
||||
* @return array Fields in table. Keys are column and unique
|
||||
*/
|
||||
function index($model) {
|
||||
$index = array();
|
||||
$table = $this->fullTableName($model, false);
|
||||
if($table) {
|
||||
$indexes = $this->query('SHOW INDEX FROM ' . $table);
|
||||
$keys = Set::extract($indexes, '{n}.STATISTICS');
|
||||
foreach ($keys as $i => $key) {
|
||||
if(!isset($index[$key['Key_name']])) {
|
||||
$index[$key['Key_name']]['column'] = $key['Column_name'];
|
||||
$index[$key['Key_name']]['unique'] = ife($key['Non_unique'] == 0, 1, 0);
|
||||
} else {
|
||||
if(!is_array($index[$key['Key_name']]['column'])) {
|
||||
$col[] = $index[$key['Key_name']]['column'];
|
||||
}
|
||||
$col[] = $key['Column_name'];
|
||||
$index[$key['Key_name']]['column'] = $col;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $index;
|
||||
}
|
||||
/**
|
||||
* Generate a MySQL schema for the given Schema object
|
||||
*
|
||||
|
@ -459,31 +488,110 @@ class DboMysql extends DboSource {
|
|||
* Otherwise, all tables defined in the schema are generated.
|
||||
* @return string
|
||||
*/
|
||||
function generateSchema($schema, $table = null) {
|
||||
function createSchema($schema, $table = null) {
|
||||
if (!is_a($schema, 'CakeSchema')) {
|
||||
trigger_error(__('Invalid schema object', true), E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
$out = '';
|
||||
|
||||
foreach ($schema->tables as $curTable => $columns) {
|
||||
if (empty($table) || $table == $curTable) {
|
||||
if (!$table || $table == $curTable) {
|
||||
$out .= 'CREATE TABLE ' . $this->fullTableName($curTable) . " (\n";
|
||||
$colList = array();
|
||||
$cols = $colList = $index = array();
|
||||
$primary = null;
|
||||
|
||||
foreach ($columns as $col) {
|
||||
if (isset($col['key']) && $col['key'] == 'primary') {
|
||||
$primary = $col;
|
||||
foreach ($columns as $name => $col) {
|
||||
if (is_string($col)) {
|
||||
$col = array('type' => $col);
|
||||
}
|
||||
$colList[] = $this->generateColumnSchema($col);
|
||||
if (isset($col['key']) && $col['key'] == 'primary') {
|
||||
$primary = $name;
|
||||
}
|
||||
if($name !== 'indexes') {
|
||||
$col['name'] = $name;
|
||||
if(!isset($col['type'])) {
|
||||
$col['type'] = 'string';
|
||||
}
|
||||
$cols[] = $this->buildColumn($col);
|
||||
} else {
|
||||
$index[] = $this->buildIndex($col);
|
||||
}
|
||||
|
||||
}
|
||||
if (empty($primary)) {
|
||||
$primary = array('id', 'integer', 'key' => 'primary');
|
||||
array_unshift($colList, $this->generateColumnSchema($primary));
|
||||
if (empty($index) && empty($primary)) {
|
||||
$primary = 'id';
|
||||
$col = array('type'=>'integer', 'key' => 'primary');
|
||||
array_unshift($cols, $this->buildColumn($col));
|
||||
}
|
||||
$colList[] = 'PRIMARY KEY (' . $this->name($primary[0]) . ')';
|
||||
$out .= "\t" . join(",\n\t", $colList) . "\n);\n\n";
|
||||
if(empty($index) && !empty($primary)) {
|
||||
$col = array('PRIMARY'=> array('column'=> $primary, 'unique' => 1));
|
||||
$index[] = $this->buildIndex($col);
|
||||
}
|
||||
$out .= "\t" . join(",\n\t", $cols) . ",\n\t". join(",\n\t", $index) . "\n);\n\n";
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
/**
|
||||
* Generate a MySQL Alter Table syntax for the given Schema comparison
|
||||
*
|
||||
* @param unknown_type $schema
|
||||
* @return unknown
|
||||
*/
|
||||
function alterSchema($compare) {
|
||||
if(!is_array($compare)) {
|
||||
return false;
|
||||
}
|
||||
$out = '';
|
||||
$colList = array();
|
||||
foreach($compare as $table => $types) {
|
||||
$out .= 'ALTER TABLE ' . $this->fullTableName($table) . " \n";
|
||||
foreach($types as $type => $column) {
|
||||
switch($type) {
|
||||
case 'add':
|
||||
foreach($column as $field => $col) {
|
||||
$col['name'] = $field;
|
||||
$alter = 'ADD '.$this->buildColumn($col);
|
||||
if(isset($col['after'])) {
|
||||
$alter .= ' AFTER '. $this->name($col['after']);
|
||||
}
|
||||
$colList[] = $alter;
|
||||
}
|
||||
break;
|
||||
case 'drop':
|
||||
foreach($column as $field => $col) {
|
||||
$col['name'] = $field;
|
||||
$colList[] = 'DROP '.$this->name($field);
|
||||
}
|
||||
break;
|
||||
case 'change':
|
||||
foreach($column as $field => $col) {
|
||||
$col['name'] = $field;
|
||||
$colList[] = 'CHANGE '. $this->name($field).' '.$this->buildColumn($col);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
$out .= "\t" . join(",\n\t", $colList) . ";\n\n";
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
/**
|
||||
* Generate a MySQL Drop table for the given Schema object
|
||||
*
|
||||
* @param object $schema An instance of a subclass of CakeSchema
|
||||
* @param string $table Optional. If specified only the table name given will be generated.
|
||||
* Otherwise, all tables defined in the schema are generated.
|
||||
* @return string
|
||||
*/
|
||||
function dropSchema($schema, $table = null) {
|
||||
if (!is_a($schema, 'CakeSchema')) {
|
||||
trigger_error(__('Invalid schema object', true), E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
$out = '';
|
||||
foreach ($schema->tables as $curTable => $columns) {
|
||||
if (!$table || $table == $curTable) {
|
||||
$out .= 'DROP TABLE ' . $this->fullTableName($curTable) . ";\n";
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
|
@ -491,23 +599,25 @@ class DboMysql extends DboSource {
|
|||
/**
|
||||
* Generate a MySQL-native column schema string
|
||||
*
|
||||
* @param array $column An array structured like the following: array('name', 'type'[, options]),
|
||||
* @param array $column An array structured like the following: array('name'=>'value', 'type'=>'value'[, options]),
|
||||
* where options can be 'default', 'length', or 'key'.
|
||||
* @return string
|
||||
*/
|
||||
function generateColumnSchema($column) {
|
||||
function buildColumn($column) {
|
||||
$name = $type = null;
|
||||
$column = am(array('null' => true), $column);
|
||||
list($name, $type) = $column;
|
||||
extract($column);
|
||||
|
||||
if (empty($name) || empty($type)) {
|
||||
trigger_error('Column name or type not defined in schema', E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isset($this->columns[$type])) {
|
||||
trigger_error("Column type {$type} does not exist", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
|
||||
$real = $this->columns[$type];
|
||||
$out = $this->name($name) . ' ' . $real['name'];
|
||||
|
||||
|
@ -523,9 +633,10 @@ class DboMysql extends DboSource {
|
|||
}
|
||||
$out .= '(' . $length . ')';
|
||||
}
|
||||
|
||||
if (isset($column['key']) && $column['key'] == 'primary') {
|
||||
if (isset($column['key']) && $column['key'] == 'primary' && (!isset($column['extra']) || (isset($column['extra']) && $column['extra'] == 'auto_increment'))) {
|
||||
$out .= ' NOT NULL AUTO_INCREMENT';
|
||||
} elseif (isset($column['key']) && $column['key'] == 'primary') {
|
||||
$out .= ' NOT NULL';
|
||||
} elseif (isset($column['default'])) {
|
||||
$out .= ' DEFAULT ' . $this->value($column['default'], $type);
|
||||
} elseif (isset($column['null']) && $column['null'] == true) {
|
||||
|
@ -538,19 +649,30 @@ class DboMysql extends DboSource {
|
|||
return $out;
|
||||
}
|
||||
/**
|
||||
* Enter description here...
|
||||
* Format indexes for create table
|
||||
*
|
||||
* @param unknown_type $schema
|
||||
* @return unknown
|
||||
* @param array $indexes
|
||||
* @return string
|
||||
*/
|
||||
function buildSchemaQuery($schema) {
|
||||
$search = array('{AUTOINCREMENT}', '{PRIMARY}', '{UNSIGNED}', '{FULLTEXT}',
|
||||
'{FULLTEXT_MYSQL}', '{BOOLEAN}', '{UTF_8}');
|
||||
$replace = array('int(11) not null auto_increment', 'primary key', 'unsigned',
|
||||
'FULLTEXT', 'FULLTEXT', 'enum (\'true\', \'false\') NOT NULL default \'true\'',
|
||||
'/*!40100 CHARACTER SET utf8 COLLATE utf8_unicode_ci */');
|
||||
$query = trim(r($search, $replace, $schema));
|
||||
return $query;
|
||||
function buildIndex($indexes) {
|
||||
$join = array();
|
||||
foreach ($indexes as $name => $value) {
|
||||
$out = null;
|
||||
if ($name == 'PRIMARY') {
|
||||
$out .= 'PRIMARY KEY (' . $this->name($value['column']) . ')';
|
||||
} else {
|
||||
if (!empty($value['unique'])) {
|
||||
$out .= 'UNIQUE ';
|
||||
}
|
||||
if (is_array($value['column'])) {
|
||||
$out .= 'KEY '. $name .' (' . join(', ', array_map(array(&$this, 'name'), $value['column'])) . ')';
|
||||
} else {
|
||||
$out .= 'KEY '. $name .' (' . $this->name($value['column']) . ')';
|
||||
}
|
||||
}
|
||||
$join[] = $out;
|
||||
}
|
||||
return join(",\n\t", $join);
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -167,8 +167,7 @@ class DboMysqli extends DboSource {
|
|||
$column[0] = $column[$colKey[0]];
|
||||
}
|
||||
if (isset($column[0])) {
|
||||
$fields[] = array(
|
||||
'name' => $column[0]['Field'],
|
||||
$fields[$column[0]['Field']] = array(
|
||||
'type' => $this->column($column[0]['Type']),
|
||||
'null' => ($column[0]['Null'] == 'YES' ? true : false),
|
||||
'default' => $column[0]['Default'],
|
||||
|
@ -438,106 +437,5 @@ class DboMysqli extends DboSource {
|
|||
function getEncoding() {
|
||||
return mysqli_client_encoding($this->connection);
|
||||
}
|
||||
/**
|
||||
* Generate a MySQL schema for the given Schema object
|
||||
*
|
||||
* @param object $schema An instance of a subclass of CakeSchema
|
||||
* @param string $table Optional. If specified only the table name given will be generated.
|
||||
* Otherwise, all tables defined in the schema are generated.
|
||||
* @return string
|
||||
*/
|
||||
function generateSchema($schema, $table = null) {
|
||||
if (!is_a($schema, 'CakeSchema')) {
|
||||
trigger_error(__('Invalid schema object', true), E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
$out = '';
|
||||
|
||||
foreach ($schema->tables as $curTable => $columns) {
|
||||
if (empty($table) || $table == $curTable) {
|
||||
$out .= 'CREATE TABLE ' . $this->fullTableName($curTable) . " (\n";
|
||||
$colList = array();
|
||||
$primary = null;
|
||||
|
||||
foreach ($columns as $col) {
|
||||
if (isset($col['key']) && $col['key'] == 'primary') {
|
||||
$primary = $col;
|
||||
}
|
||||
$colList[] = $this->generateColumnSchema($col);
|
||||
}
|
||||
if (empty($primary)) {
|
||||
$primary = array('id', 'integer', 'key' => 'primary');
|
||||
array_unshift($colList, $this->generateColumnSchema($primary));
|
||||
}
|
||||
$colList[] = 'PRIMARY KEY (' . $this->name($primary[0]) . ')';
|
||||
$out .= "\t" . join(",\n\t", $colList) . "\n);\n\n";
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
/**
|
||||
* Generate a MySQL-native column schema string
|
||||
*
|
||||
* @param array $column An array structured like the following: array('name', 'type'[, options]),
|
||||
* where options can be 'default', 'length', or 'key'.
|
||||
* @return string
|
||||
*/
|
||||
function generateColumnSchema($column) {
|
||||
$name = $type = null;
|
||||
$column = am(array('null' => true), $column);
|
||||
list($name, $type) = $column;
|
||||
|
||||
if (empty($name) || empty($type)) {
|
||||
trigger_error('Column name or type not defined in schema', E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (!isset($this->columns[$type])) {
|
||||
trigger_error("Column type {$type} does not exist", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
$real = $this->columns[$type];
|
||||
$out = $this->name($name) . ' ' . $real['name'];
|
||||
|
||||
if (isset($real['limit']) || isset($real['length']) || isset($column['limit']) || isset($column['length'])) {
|
||||
if (isset($column['length'])) {
|
||||
$length = $column['length'];
|
||||
} elseif (isset($column['limit'])) {
|
||||
$length = $column['limit'];
|
||||
} elseif (isset($real['length'])) {
|
||||
$length = $real['length'];
|
||||
} else {
|
||||
$length = $real['limit'];
|
||||
}
|
||||
$out .= '(' . $length . ')';
|
||||
}
|
||||
|
||||
if (isset($column['key']) && $column['key'] == 'primary') {
|
||||
$out .= ' NOT NULL AUTO_INCREMENT';
|
||||
} elseif (isset($column['default'])) {
|
||||
$out .= ' DEFAULT ' . $this->value($column['default'], $type);
|
||||
} elseif (isset($column['null']) && $column['null'] == true) {
|
||||
$out .= ' DEFAULT NULL';
|
||||
} elseif (isset($column['default']) && isset($column['null']) && $column['null'] == false) {
|
||||
$out .= ' DEFAULT ' . $this->value($column['default'], $type) . ' NOT NULL';
|
||||
} elseif (isset($column['null']) && $column['null'] == false) {
|
||||
$out .= ' NOT NULL';
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @param unknown_type $schema
|
||||
* @return unknown
|
||||
*/
|
||||
function buildSchemaQuery($schema) {
|
||||
$search = array('{AUTOINCREMENT}', '{PRIMARY}', '{UNSIGNED}', '{FULLTEXT}',
|
||||
'{FULLTEXT_MYSQL}', '{BOOLEAN}', '{UTF_8}');
|
||||
$replace = array('int(11) not null auto_increment', 'primary key', 'unsigned',
|
||||
'FULLTEXT', 'FULLTEXT', 'enum (\'true\', \'false\') NOT NULL default \'true\'',
|
||||
'/*!40100 CHARACTER SET utf8 COLLATE utf8_unicode_ci */');
|
||||
$query = trim(r($search, $replace, $schema));
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -174,23 +174,19 @@ class DboOdbc extends DboSource{
|
|||
return $cache;
|
||||
}
|
||||
|
||||
$fields=array();
|
||||
$sql='SELECT * FROM ' . $this->fullTableName($model) . ' LIMIT 1';
|
||||
$result=odbc_exec($this->connection, $sql);
|
||||
$fields = array();
|
||||
$sql = 'SELECT * FROM ' . $this->fullTableName($model) . ' LIMIT 1';
|
||||
$result = odbc_exec($this->connection, $sql);
|
||||
|
||||
$count=odbc_num_fields($result);
|
||||
$count = odbc_num_fields($result);
|
||||
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
$cols[$i - 1] = odbc_field_name($result, $i);
|
||||
}
|
||||
|
||||
foreach ($cols as $column) {
|
||||
$type
|
||||
= odbc_field_type(
|
||||
odbc_exec($this->connection, "SELECT " . $column . " FROM " . $this->fullTableName($model)),
|
||||
1);
|
||||
array_push($fields, array('name' => $column,
|
||||
'type' => $type));
|
||||
$type = odbc_field_type(odbc_exec($this->connection, "SELECT " . $column . " FROM " . $this->fullTableName($model)), 1);
|
||||
$fields[$column] array('type' => $type));
|
||||
}
|
||||
|
||||
$this->__cacheDescription($model->tablePrefix . $model->table, $fields);
|
||||
|
@ -202,7 +198,7 @@ class DboOdbc extends DboSource{
|
|||
return '*';
|
||||
}
|
||||
|
||||
$pos=strpos($data, '`');
|
||||
$pos = strpos($data, '`');
|
||||
|
||||
if ($pos === false) {
|
||||
$data = '' . str_replace('.', '.', $data) . '';
|
||||
|
@ -441,26 +437,5 @@ class DboOdbc extends DboSource{
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function buildSchemaQuery($schema) {
|
||||
$search=array('{AUTOINCREMENT}',
|
||||
'{PRIMARY}',
|
||||
'{UNSIGNED}',
|
||||
'{FULLTEXT}',
|
||||
'{FULLTEXT_MYSQL}',
|
||||
'{BOOLEAN}',
|
||||
'{UTF_8}');
|
||||
|
||||
$replace=array('int(11) not null auto_increment',
|
||||
'primary key',
|
||||
'unsigned',
|
||||
'FULLTEXT',
|
||||
'FULLTEXT',
|
||||
'enum (\'true\', \'false\') NOT NULL default \'true\'',
|
||||
'/*!40100 CHARACTER SET utf8 COLLATE utf8_unicode_ci */');
|
||||
|
||||
$query=trim(str_replace($search, $replace, $schema));
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -424,9 +424,8 @@ class DboOracle extends DboSource {
|
|||
$fields = array();
|
||||
|
||||
for($i=0; $row = $this->fetchRow(); $i++) {
|
||||
$fields[$i]['name'] = strtolower($row[0]['COLUMN_NAME']);
|
||||
$fields[$i]['length'] = $row[0]['DATA_LENGTH'];
|
||||
$fields[$i]['type'] = $this->column($row[0]['DATA_TYPE']);
|
||||
$fields[strtolower($row[0]['COLUMN_NAME'])] = array('type'=> $this->column($row[0]['DATA_TYPE']),
|
||||
'length'=> $row[0]['DATA_LENGTH']);
|
||||
}
|
||||
$this->__cacheDescription($this->fullTableName($model, false), $fields);
|
||||
return $fields;
|
||||
|
@ -617,56 +616,6 @@ class DboOracle extends DboSource {
|
|||
function lastAffected() {
|
||||
return $this->_statementId ? ocirowcount($this->_statementId): false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a Oracle-native column schema string
|
||||
*
|
||||
* @param array $column An array structured like the following: array('name', 'type'[, options]),
|
||||
* where options can be 'default', 'length', or 'key'.
|
||||
* @return string
|
||||
*/
|
||||
function generateColumnSchema($column) {
|
||||
$name = $type = null;
|
||||
$column = am(array('null' => true), $column);
|
||||
list($name, $type) = $column;
|
||||
|
||||
if (empty($name) || empty($type)) {
|
||||
trigger_error('Column name or type not defined in schema', E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (!isset($this->columns[$type])) {
|
||||
trigger_error("Column type {$type} does not exist", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
$real = $this->columns[$type];
|
||||
$out = $this->name($name) . ' ' . $real['name'];
|
||||
|
||||
if (isset($real['limit']) || isset($real['length']) || isset($column['limit']) || isset($column['length'])) {
|
||||
if (isset($column['length'])) {
|
||||
$length = $column['length'];
|
||||
} elseif (isset($column['limit'])) {
|
||||
$length = $column['limit'];
|
||||
} elseif (isset($real['length'])) {
|
||||
$length = $real['length'];
|
||||
} else {
|
||||
$length = $real['limit'];
|
||||
}
|
||||
$out .= '(' . $length . ')';
|
||||
}
|
||||
|
||||
if (isset($column['key']) && $column['key'] == 'primary') {
|
||||
$out .= ' NOT NULL ';
|
||||
} elseif (isset($column['default'])) {
|
||||
$out .= ' DEFAULT ' . $this->value($column['default'], $type);
|
||||
} elseif (isset($column['null']) && $column['null'] == true) {
|
||||
$out .= ' DEFAULT NULL';
|
||||
} elseif (isset($column['default']) && isset($column['null']) && $column['null'] == false) {
|
||||
$out .= ' DEFAULT ' . $this->value($column['default'], $type) . ' NOT NULL';
|
||||
} elseif (isset($column['null']) && $column['null'] == false) {
|
||||
$out .= ' NOT NULL';
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
/**
|
||||
* Inserts multiple values into a join table
|
||||
*
|
||||
|
|
|
@ -190,8 +190,7 @@ class DboPostgres extends DboSource {
|
|||
} else {
|
||||
$length = $this->length($c['type']);
|
||||
}
|
||||
$fields[] = array(
|
||||
'name' => $c['name'],
|
||||
$fields[$c['name']] = array(
|
||||
'type' => $this->column($c['type']),
|
||||
'null' => ($c['null'] == 'NO' ? false : true),
|
||||
'default' => $c['default'],
|
||||
|
@ -579,59 +578,6 @@ class DboPostgres extends DboSource {
|
|||
function getEncoding() {
|
||||
return pg_client_encoding($this->connection);
|
||||
}
|
||||
/**
|
||||
* Generate a PostgreSQL-native column schema string
|
||||
*
|
||||
* @param array $column An array structured like the following: array('name', 'type'[, options]),
|
||||
* where options can be 'default', 'length', or 'key'.
|
||||
* @return string
|
||||
*/
|
||||
function generateColumnSchema($column) {
|
||||
$name = $type = $out = null;
|
||||
$column = am(array('null' => true), $column);
|
||||
list($name, $type) = $column;
|
||||
|
||||
if (empty($name) || empty($type)) {
|
||||
trigger_error('Column name or type not defined in schema', E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (!isset($this->columns[$type])) {
|
||||
trigger_error("Column type {$type} does not exist", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
$out = "\t" . $this->name($name) . ' ';
|
||||
|
||||
if (!isset($column['key']) || $column['key'] != 'primary') {
|
||||
$real = $this->columns[$type];
|
||||
$out .= $real['name'];
|
||||
|
||||
if (isset($real['limit']) || isset($real['length']) || isset($column['limit']) || isset($column['length'])) {
|
||||
if (isset($column['length'])) {
|
||||
$length = $column['length'];
|
||||
} elseif (isset($column['limit'])) {
|
||||
$length = $column['limit'];
|
||||
} elseif (isset($real['length'])) {
|
||||
$length = $real['length'];
|
||||
} else {
|
||||
$length = $real['limit'];
|
||||
}
|
||||
$out .= '(' . $length . ')';
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($column['key']) && $column['key'] == 'primary') {
|
||||
$out .= $this->columns['primary_key']['name'];
|
||||
} elseif (isset($column['default'])) {
|
||||
$out .= ' DEFAULT ' . $this->value($column['default'], $type);
|
||||
} elseif (isset($column['null']) && $column['null'] == true) {
|
||||
$out .= ' DEFAULT NULL';
|
||||
} elseif (isset($column['default']) && isset($column['null']) && $column['null'] == false) {
|
||||
$out .= ' DEFAULT ' . $this->value($column['default'], $type) . ' NOT NULL';
|
||||
} elseif (isset($column['null']) && $column['null'] == false) {
|
||||
$out .= ' NOT NULL';
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -160,8 +160,7 @@ class DboSqlite extends DboSource {
|
|||
$result = $this->fetchAll('PRAGMA table_info(' . $model->tablePrefix . $model->table . ')');
|
||||
|
||||
foreach ($result as $column) {
|
||||
$fields[] = array(
|
||||
'name' => $column[0]['name'],
|
||||
$fields[$column[0]['name']] = array(
|
||||
'type' => $this->column($column[0]['type']),
|
||||
'null' => ! $column[0]['notnull'],
|
||||
'default' => $column[0]['dflt_value']
|
||||
|
@ -405,6 +404,6 @@ class DboSqlite extends DboSource {
|
|||
for ($x = 0; $x < $count; $x++) {
|
||||
$this->query("INSERT INTO {$table} ({$fields}) VALUES {$values[$x]}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -170,7 +170,9 @@ class DboSybase extends DboSource {
|
|||
$column[0] = $column[$colKey[0]];
|
||||
}
|
||||
if (isset($column[0])) {
|
||||
$fields[] = array('name' => $column[0]['Field'], 'type' => $this->column($column[0]['Type']), 'null' => $column[0]['Null']);
|
||||
$fields[$column[0]['Field']] = array('type' => $this->column($column[0]['Type']),
|
||||
'null' => $column[0]['Null']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,21 +379,6 @@ class DboSybase extends DboSource {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @param unknown_type $schema
|
||||
* @return unknown
|
||||
*/
|
||||
function buildSchemaQuery($schema) {
|
||||
$search = array('{AUTOINCREMENT}', '{PRIMARY}', '{UNSIGNED}', '{FULLTEXT}',
|
||||
'{FULLTEXT_SYBASE}', '{BOOLEAN}', '{UTF_8}');
|
||||
$replace = array('int(11) not null auto_increment', 'primary key', 'unsigned',
|
||||
'FULLTEXT', 'FULLTEXT', 'enum (\'true\', \'false\') NOT NULL default \'true\'',
|
||||
'/*!40100 CHARACTER SET utf8 COLLATE utf8_unicode_ci */');
|
||||
$query = trim(r($search, $replace, $schema));
|
||||
return $query;
|
||||
}
|
||||
/**
|
||||
* Inserts multiple values into a join table
|
||||
*
|
||||
|
@ -404,6 +391,6 @@ class DboSybase extends DboSource {
|
|||
for ($x = 0; $x < $count; $x++) {
|
||||
$this->query("INSERT INTO {$table} ({$fields}) VALUES {$values[$x]}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -43,11 +43,11 @@ class DboSource extends DataSource {
|
|||
*/
|
||||
var $description = "Database Data Source";
|
||||
/**
|
||||
* Enter description here...
|
||||
* index definition, standard cake, primary, index, unique
|
||||
*
|
||||
* @var unknown_type
|
||||
* @var array
|
||||
*/
|
||||
var $__bypass = false;
|
||||
var $index = array('PRI'=> 'primary', 'MUL'=> 'index', 'UNI'=>'unique');
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
|
@ -66,18 +66,24 @@ class DboSource extends DataSource {
|
|||
* @var unknown_type
|
||||
*/
|
||||
var $alias = 'AS ';
|
||||
/**
|
||||
* The set of valid SQL operations usable in a WHERE statement
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $__sqlOps = array('like', 'ilike', 'or', 'not', 'in', 'between', 'regexp', 'similar to');
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @var unknown_type
|
||||
*/
|
||||
var $goofyLimit = false;
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @var unknown_type
|
||||
*/
|
||||
var $__bypass = false;
|
||||
/**
|
||||
* The set of valid SQL operations usable in a WHERE statement
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $__sqlOps = array('like', 'ilike', 'or', 'not', 'in', 'between', 'regexp', 'similar to');
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -126,135 +132,6 @@ class DboSource extends DataSource {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Caches/returns cached results for child instances
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function listSources($data = null) {
|
||||
if ($this->cacheSources === false) {
|
||||
return null;
|
||||
}
|
||||
if ($this->_sources != null) {
|
||||
return $this->_sources;
|
||||
}
|
||||
|
||||
if (Configure::read() > 0) {
|
||||
$expires = "+30 seconds";
|
||||
} else {
|
||||
$expires = "+999 days";
|
||||
}
|
||||
|
||||
if ($data != null) {
|
||||
$data = serialize($data);
|
||||
}
|
||||
$filename = ConnectionManager::getSourceName($this) . '_' . preg_replace("/[^A-Za-z0-9_-]/", "_", $this->config['database']) . '_list';
|
||||
$new = cache('models' . DS . $filename, $data, $expires);
|
||||
|
||||
if ($new != null) {
|
||||
$new = unserialize($new);
|
||||
$this->_sources = $new;
|
||||
}
|
||||
return $new;
|
||||
}
|
||||
/**
|
||||
* Convenience method for DboSource::listSources(). Returns source names in lowercase.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function sources() {
|
||||
$return = array_map('strtolower', $this->listSources());
|
||||
return $return;
|
||||
}
|
||||
/**
|
||||
* SQL Query abstraction
|
||||
*
|
||||
* @return resource Result resource identifier
|
||||
*/
|
||||
function query() {
|
||||
$args = func_get_args();
|
||||
$fields = null;
|
||||
$order = null;
|
||||
$limit = null;
|
||||
$page = null;
|
||||
$recursive = null;
|
||||
|
||||
if (count($args) == 1) {
|
||||
return $this->fetchAll($args[0]);
|
||||
|
||||
} elseif (count($args) > 1 && (strpos(low($args[0]), 'findby') === 0 || strpos(low($args[0]), 'findallby') === 0)) {
|
||||
$params = $args[1];
|
||||
|
||||
if (strpos(strtolower($args[0]), 'findby') === 0) {
|
||||
$all = false;
|
||||
$field = Inflector::underscore(preg_replace('/findBy/i', '', $args[0]));
|
||||
} else {
|
||||
$all = true;
|
||||
$field = Inflector::underscore(preg_replace('/findAllBy/i', '', $args[0]));
|
||||
}
|
||||
|
||||
$or = (strpos($field, '_or_') !== false);
|
||||
if ($or) {
|
||||
$field = explode('_or_', $field);
|
||||
} else {
|
||||
$field = explode('_and_', $field);
|
||||
}
|
||||
$off = count($field) - 1;
|
||||
|
||||
if (isset($params[1 + $off])) {
|
||||
$fields = $params[1 + $off];
|
||||
}
|
||||
|
||||
if (isset($params[2 + $off])) {
|
||||
$order = $params[2 + $off];
|
||||
}
|
||||
|
||||
if (!array_key_exists(0, $params)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$c = 0;
|
||||
$query = array();
|
||||
foreach ($field as $f) {
|
||||
if (!is_array($params[$c]) && !empty($params[$c]) && $params[$c] !== true && $params[$c] !== false) {
|
||||
$query[$args[2]->name . '.' . $f] = '= ' . $params[$c];
|
||||
} else {
|
||||
$query[$args[2]->name . '.' . $f] = $params[$c];
|
||||
}
|
||||
$c++;
|
||||
}
|
||||
|
||||
if ($or) {
|
||||
$query = array('OR' => $query);
|
||||
}
|
||||
|
||||
if ($all) {
|
||||
|
||||
if (isset($params[3 + $off])) {
|
||||
$limit = $params[3 + $off];
|
||||
}
|
||||
|
||||
if (isset($params[4 + $off])) {
|
||||
$page = $params[4 + $off];
|
||||
}
|
||||
|
||||
if (isset($params[5 + $off])) {
|
||||
$recursive = $params[5 + $off];
|
||||
}
|
||||
return $args[2]->findAll($query, $fields, $order, $limit, $page, $recursive);
|
||||
} else {
|
||||
if (isset($params[3 + $off])) {
|
||||
$recursive = $params[3 + $off];
|
||||
}
|
||||
return $args[2]->find($query, $fields, $order, $recursive);
|
||||
}
|
||||
} else {
|
||||
if (isset($args[1]) && $args[1] === true) {
|
||||
return $this->fetchAll($args[0], true);
|
||||
}
|
||||
return $this->fetchAll($args[0], false);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Executes given SQL statement.
|
||||
*
|
||||
|
@ -1829,5 +1706,64 @@ class DboSource extends DataSource {
|
|||
$values = implode(', ', $values);
|
||||
$this->query("INSERT INTO {$table} ({$fields}) VALUES {$values}");
|
||||
}
|
||||
/**
|
||||
* Returns an array of the indexes in given datasource name.
|
||||
*
|
||||
* @param string $model Name of model to inspect
|
||||
* @return array Fields in table. Keys are column and unique
|
||||
*/
|
||||
function index($model) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Generate a create syntax from CakeSchema
|
||||
*
|
||||
* @param object $schema An instance of a subclass of CakeSchema
|
||||
* @param string $table Optional. If specified only the table name given will be generated.
|
||||
* Otherwise, all tables defined in the schema are generated.
|
||||
* @return string
|
||||
*/
|
||||
function createSchema($schema, $table = null) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Generate a alter syntax from CakeSchema::compare()
|
||||
*
|
||||
* @param unknown_type $schema
|
||||
* @return unknown
|
||||
*/
|
||||
function alterSchema($compare) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Generate a drop syntax from CakeSchema
|
||||
*
|
||||
* @param object $schema An instance of a subclass of CakeSchema
|
||||
* @param string $table Optional. If specified only the table name given will be generated.
|
||||
* Otherwise, all tables defined in the schema are generated.
|
||||
* @return string
|
||||
*/
|
||||
function dropSchema($schema, $table = null) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Generate a column schema string
|
||||
*
|
||||
* @param array $column An array structured like the following: array('name'=>'value', 'type'=>'value'[, options]),
|
||||
* where options can be 'default', 'length', or 'key'.
|
||||
* @return string
|
||||
*/
|
||||
function buildColumn($column) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Format indexes for create table
|
||||
*
|
||||
* @param array $indexes
|
||||
* @return string
|
||||
*/
|
||||
function buildIndex($indexes) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -106,7 +106,12 @@ class Model extends Overloadable {
|
|||
* Table metadata
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
* @access protected
|
||||
*/
|
||||
var $_schema = null;
|
||||
/**
|
||||
*
|
||||
* @deprecated see $_schema
|
||||
*/
|
||||
var $_tableInfo = null;
|
||||
/**
|
||||
|
@ -706,12 +711,14 @@ class Model extends Overloadable {
|
|||
$this->{$type}[$assocKey]['joinTable'] = $this->{$with}->table;
|
||||
} elseif ($type == 'hasAndBelongsToMany') {
|
||||
$joinClass = Inflector::camelize($this->name . $assocKey);
|
||||
$this->{$type}[$assocKey]['_with'] = $joinClass;
|
||||
$this->{$joinClass} = new AppModel(array(
|
||||
'name' => $joinClass,
|
||||
'table' => $this->{$type}[$assocKey]['joinTable'],
|
||||
'ds' => $this->useDbConfig
|
||||
));
|
||||
if(!class_exists(low($joinClass))) {
|
||||
$this->{$type}[$assocKey]['_with'] = $joinClass;
|
||||
$this->{$joinClass} = new AppModel(array(
|
||||
'name' => $joinClass,
|
||||
'table' => $this->{$type}[$assocKey]['joinTable'],
|
||||
'ds' => $this->useDbConfig
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -724,7 +731,6 @@ class Model extends Overloadable {
|
|||
$this->setDataSource($this->useDbConfig);
|
||||
$db =& ConnectionManager::getDataSource($this->useDbConfig);
|
||||
$db->cacheSources = $this->cacheSources;
|
||||
|
||||
if ($db->isInterfaceSupported('listSources')) {
|
||||
$sources = $db->listSources();
|
||||
if (is_array($sources) && !in_array(low($this->tablePrefix . $tableName), array_map('low', $sources))) {
|
||||
|
@ -733,13 +739,13 @@ class Model extends Overloadable {
|
|||
'table' => $this->tablePrefix . $tableName
|
||||
)));
|
||||
} else {
|
||||
$this->table = $tableName;
|
||||
$this->table = $this->useTable = $tableName;
|
||||
$this->tableToModel[$this->table] = $this->name;
|
||||
$this->_tableInfo = null;
|
||||
$this->loadInfo();
|
||||
}
|
||||
} else {
|
||||
$this->table = $tableName;
|
||||
$this->table = $this->useTable = $tableName;
|
||||
$this->tableToModel[$this->table] = $this->name;
|
||||
$this->loadInfo();
|
||||
}
|
||||
|
@ -792,20 +798,34 @@ class Model extends Overloadable {
|
|||
}
|
||||
/**
|
||||
* Returns an array of table metadata (column names and types) from the database.
|
||||
* $field => keys(type, null, default, key, length, extra)
|
||||
*
|
||||
* @return array Array of table metadata
|
||||
*/
|
||||
function loadInfo($clear = false) {
|
||||
if (!is_object($this->_tableInfo) || $clear) {
|
||||
function schema($clear = false) {
|
||||
if (!is_object($this->_schema) || $clear) {
|
||||
$db =& ConnectionManager::getDataSource($this->useDbConfig);
|
||||
$db->cacheSources = $this->cacheSources;
|
||||
|
||||
if ($db->isInterfaceSupported('describe') && $this->useTable !== false) {
|
||||
$this->_tableInfo = new Set($db->describe($this, $clear));
|
||||
$this->_schema = new Set($db->describe($this, $clear));
|
||||
} elseif ($this->useTable === false) {
|
||||
$this->_tableInfo = new Set();
|
||||
$this->_schema = new Set();
|
||||
}
|
||||
}
|
||||
return $this->_schema;
|
||||
}
|
||||
/**
|
||||
* See Model::schema
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
function loadInfo($clear = false) {
|
||||
$info = $this->schema($clear);
|
||||
foreach($info->value as $field => $value) {
|
||||
$fields[] = am(array('name'=> $field), $value);
|
||||
}
|
||||
unset($info);
|
||||
$this->_tableInfo = new Set($fields);
|
||||
return $this->_tableInfo;
|
||||
}
|
||||
/**
|
||||
|
|
390
cake/libs/model/schema.php
Normal file
390
cake/libs/model/schema.php
Normal file
|
@ -0,0 +1,390 @@
|
|||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Schema database management for CakePHP.
|
||||
*
|
||||
* 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.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
|
||||
*/
|
||||
if (!class_exists('connectionmanager')) {
|
||||
uses('model' . DS . 'connection_manager');
|
||||
}
|
||||
/**
|
||||
* Base Class for Schema management
|
||||
*
|
||||
* @package cake.libs
|
||||
* @subpackage cake.libs
|
||||
*/
|
||||
class CakeSchema extends Object {
|
||||
/**
|
||||
* name of the App Schema
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $name = null;
|
||||
/**
|
||||
* path to write location
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $path = TMP;
|
||||
/**
|
||||
* connection used for read
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $connection = 'default';
|
||||
/**
|
||||
* array of tables
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $tables = array();
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $data optional load object properties
|
||||
* @access private
|
||||
*/
|
||||
function __construct($data = array()) {
|
||||
$this->path = CONFIGS . 'sql';
|
||||
$data = am(get_object_vars($this), $data);
|
||||
|
||||
$this->_build($data);
|
||||
|
||||
if (empty($this->name)) {
|
||||
$this->name = preg_replace('/schema$/i', '', get_class($this));
|
||||
}
|
||||
parent::__construct();
|
||||
}
|
||||
/**
|
||||
* Builds schema object properties
|
||||
*
|
||||
* @param array $data loaded object properties
|
||||
* @access protected
|
||||
*/
|
||||
function _build($data) {
|
||||
foreach ($data as $key => $val) {
|
||||
if (!in_array($key, array('name', 'path', 'connection', 'tables', '_log'))) {
|
||||
$this->tables[$key] = $val;
|
||||
unset($this->{$key});
|
||||
} elseif ($key != 'tables' && !empty($val)) {
|
||||
$this->{$key} = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Reads database and creates schema tables
|
||||
*
|
||||
* @param array $options schema object properties
|
||||
* @access public
|
||||
* @return array $name, $tables
|
||||
*/
|
||||
function load($options = array()) {
|
||||
if (is_string($options)) {
|
||||
$options = array('path'=> $options);
|
||||
}
|
||||
if (!isset($options['name'])) {
|
||||
$options['name'] = Inflector::camelize(Configure::read('App.dir'));
|
||||
}
|
||||
$options = am(
|
||||
get_object_vars($this), $options
|
||||
);
|
||||
extract($options);
|
||||
if (file_exists($path . DS . 'schema.php')) {
|
||||
require_once($path . DS . 'schema.php');
|
||||
$class = $name .'Schema';
|
||||
if(class_exists($class)) {
|
||||
$Schema =& new $class();
|
||||
$this->_build($options);
|
||||
return $Schema;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Reads database and creates schema tables
|
||||
*
|
||||
* @param array $options schema object properties
|
||||
* @access public
|
||||
* @return array $name, $tables
|
||||
*/
|
||||
function read($options = array()) {
|
||||
extract(am(
|
||||
array(
|
||||
'connection' => $this->connection,
|
||||
'name' => Inflector::camelize(Configure::read('App.dir')),
|
||||
),
|
||||
$options
|
||||
));
|
||||
$db =& ConnectionManager::getDataSource($connection);
|
||||
|
||||
if (empty($models)) {
|
||||
$models = Configure::listObjects('model');
|
||||
}
|
||||
$tables = array();
|
||||
foreach ($models as $model) {
|
||||
if (!class_exists($model)) {
|
||||
loadModel($model);
|
||||
}
|
||||
$Object =& new $model();
|
||||
$Object->setDataSource($connection);
|
||||
if (is_object($Object)) {
|
||||
if(empty($tables[$Object->table])) {
|
||||
$tables[$Object->table] = $this->__columns($Object);
|
||||
$tables[$Object->table]['indexes'] = $db->index($Object);
|
||||
if(!empty($Object->hasAndBelongsToMany)) {
|
||||
foreach($Object->hasAndBelongsToMany as $Assoc => $assocData) {
|
||||
$tables[$Object->$Assoc->table] = $this->__columns($Object->$Assoc);
|
||||
$tables[$Object->$Assoc->table]['indexes'] = $db->index($Object->$Assoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
trigger_error('Schema generation error: model class ' . $class . ' not found', E_USER_WARNING);
|
||||
}
|
||||
|
||||
}
|
||||
return compact('name', 'tables');
|
||||
}
|
||||
/**
|
||||
* Writes schema file from object or options
|
||||
*
|
||||
* @param mixed $object schema object or options array
|
||||
* @param array $options schema object properties to override object
|
||||
* @access public
|
||||
* @return mixed false or string written to file
|
||||
*/
|
||||
function write($object, $options = array()) {
|
||||
if (is_object($object)) {
|
||||
$object = get_object_vars($object);
|
||||
$this->_build($object);
|
||||
}
|
||||
|
||||
if (is_array($object)) {
|
||||
$options = $object;
|
||||
unset($object);
|
||||
}
|
||||
|
||||
extract(am(
|
||||
get_object_vars($this), $options
|
||||
));
|
||||
|
||||
$out = "\n\nclass {$name}Schema extends CakeSchema {\n\n";
|
||||
|
||||
$out .= "\tvar \$name = '{$name}';\n\n";
|
||||
|
||||
if ($path !== $this->path) {
|
||||
$out .= "\tvar \$path = '{$path}';\n\n";
|
||||
}
|
||||
|
||||
if ($connection !== 'default') {
|
||||
$out .= "\tvar \$connection = '{$connection}';\n\n";
|
||||
}
|
||||
|
||||
if(empty($tables)) {
|
||||
$this->read();
|
||||
}
|
||||
|
||||
foreach ($tables as $table => $fields) {
|
||||
if(!is_numeric($table)) {
|
||||
$out .= "\tvar \${$table} = array(\n";
|
||||
if (is_array($fields)) {
|
||||
$cols = array();
|
||||
foreach ($fields as $field => $value) {
|
||||
if($field != 'indexes') {
|
||||
if (is_string($value)) {
|
||||
$type = $value;
|
||||
$value = array('type'=> $type);
|
||||
}
|
||||
$col = "\t\t\t'{$field}' => array('type'=>'" . $value['type'] . "', ";
|
||||
unset($value['type']);
|
||||
$col .= join(', ', $this->__values($value));
|
||||
} else {
|
||||
$col = "\t\t\t'indexes' => array(";
|
||||
$props = array();
|
||||
foreach ($value as $key => $index) {
|
||||
$props[] = "'{$key}' => array(".join(', ', $this->__values($index)).")";
|
||||
}
|
||||
$col .= join(', ', $props);
|
||||
}
|
||||
$col .= ")";
|
||||
$cols[] = $col;
|
||||
}
|
||||
$out .= join(",\n", $cols);
|
||||
}
|
||||
$out .= "\n\t\t);\n";
|
||||
$out .="\n";
|
||||
}
|
||||
}
|
||||
$out .= "\n\tfunction setup(\$version) {\n\t}\n\n\tfunction teardown(\$version) {\n";
|
||||
$out .= "\t}\n}\n\n";
|
||||
|
||||
$File =& new File($path . DS . 'schema.php', true);
|
||||
$content = "<?php \n/*<!--". $name ." schema generated on: " . date('Y-m-d H:m:s') . " : ". time() . "-->*/\n{$out}?>";
|
||||
if ($File->write($content)) {
|
||||
return $content;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Writes schema file from object or options
|
||||
*
|
||||
* @param mixed $old schema object or array
|
||||
* @param mixed $new schema object or array
|
||||
* @access public
|
||||
* @return array $add, $drop, $change
|
||||
*/
|
||||
function compare($old, $new = null) {
|
||||
if (empty($new)) {
|
||||
$new = $this;
|
||||
}
|
||||
if (is_array($new)) {
|
||||
if (isset($new['tables'])) {
|
||||
$new = $new['tables'];
|
||||
}
|
||||
} else {
|
||||
$new = $new->tables;
|
||||
}
|
||||
|
||||
if (is_array($old)) {
|
||||
if (isset($old['tables'])) {
|
||||
$old = $old['tables'];
|
||||
}
|
||||
} else {
|
||||
$old = $old->tables;
|
||||
}
|
||||
$tables = array();
|
||||
foreach ($new as $table => $fields) {
|
||||
if (!array_key_exists($table, $old)) {
|
||||
$tables[$table]['add'] = $fields;
|
||||
} else {
|
||||
$diff = array_diff_assoc($fields, $old[$table]);
|
||||
if (!empty($diff)) {
|
||||
$tables[$table]['add'] = $diff;
|
||||
}
|
||||
$diff = array_diff_assoc($old[$table], $fields);
|
||||
if (!empty($diff)) {
|
||||
$tables[$table]['drop'] = $diff;
|
||||
}
|
||||
}
|
||||
foreach ($fields as $field => $value) {
|
||||
if (isset($old[$table][$field])) {
|
||||
$diff = array_diff($value, $old[$table][$field]);
|
||||
if (!empty($diff)) {
|
||||
$tables[$table]['change'][$field] = am($old[$table][$field], $diff);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($add[$table][$field])) {
|
||||
$wrapper = array_keys($fields);
|
||||
if ($column = array_search($field, $wrapper)) {
|
||||
if (isset($wrapper[$column - 1])) {
|
||||
$tables[$table]['add'][$field]['after'] = $wrapper[$column - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
/**
|
||||
* Formats Schema columns from Model Object
|
||||
*
|
||||
* @param array $value options keys(type, null, default, key, length, extra)
|
||||
* @access public
|
||||
* @return array $name, $tables
|
||||
*/
|
||||
function __values($values) {
|
||||
$vals = array();
|
||||
if(is_array($values)) {
|
||||
foreach ($values as $key => $val) {
|
||||
if(is_array($val)) {
|
||||
$vals[] = "'{$key}' => array('".join("', '", $val)."')";
|
||||
} else if (!is_numeric($key)) {
|
||||
$prop = "'{$key}' => ";
|
||||
if (is_bool($val)) {
|
||||
$prop .= $val ? 'true' : 'false';
|
||||
} elseif (is_numeric($val)) {
|
||||
$prop .= $val;
|
||||
} elseif ($val === null) {
|
||||
$prop .= 'null';
|
||||
} else {
|
||||
$prop .= "'{$val}'";
|
||||
}
|
||||
$vals[] = $prop;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $vals;
|
||||
}
|
||||
/**
|
||||
* Formats Schema columns from Model Object
|
||||
*
|
||||
* @param array $Obj model object
|
||||
* @access public
|
||||
* @return array $name, $tables
|
||||
*/
|
||||
function __columns(&$Obj) {
|
||||
$db =& ConnectionManager::getDataSource($Obj->useDbConfig);
|
||||
$fields = $Obj->schema(true);
|
||||
$columns = $props = array();
|
||||
foreach ($fields->value as $name => $value) {
|
||||
|
||||
if ($Obj->primaryKey == $name) {
|
||||
$value['key'] = 'primary';
|
||||
}
|
||||
if (!isset($db->columns[$value['type']])) {
|
||||
trigger_error('Schema generation error: invalid column type ' . $value['type'] . ' does not exist in DBO', E_USER_WARNING);
|
||||
continue;
|
||||
} else {
|
||||
$defaultCol = $db->columns[$value['type']];
|
||||
if (isset($defaultCol['limit']) && $defaultCol['limit'] == $value['length']) {
|
||||
unset($value['length']);
|
||||
} elseif (isset($defaultCol['length']) && $defaultCol['length'] == $value['length']) {
|
||||
unset($value['length']);
|
||||
}
|
||||
unset($value['limit']);
|
||||
}
|
||||
|
||||
if (empty($value['default']) && $value['null'] == true) {
|
||||
unset($value['default']);
|
||||
}
|
||||
if (empty($value['length'])) {
|
||||
unset($value['length']);
|
||||
}
|
||||
if (empty($value['key'])) {
|
||||
unset($value['key']);
|
||||
}
|
||||
if (empty($value['extra'])) {
|
||||
unset($value['extra']);
|
||||
}
|
||||
$columns[$name] = $value;
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -39,6 +39,7 @@ uses('controller'.DS.'components'.DS.'acl', 'model'.DS.'db_acl');
|
|||
if(!class_exists('aclnodetestbase')) {
|
||||
class AclNodeTestBase extends AclNode {
|
||||
var $useDbConfig = 'test_suite';
|
||||
var $cacheSources = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ uses('controller'.DS.'components'.DS.'acl', 'model'.DS.'db_acl');
|
|||
if(!class_exists('aclnodetestbase')) {
|
||||
class AclNodeTestBase extends AclNode {
|
||||
var $useDbConfig = 'test_suite';
|
||||
var $cacheSources = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,41 +330,49 @@ class AuthTest extends CakeTestCase {
|
|||
|
||||
|
||||
$this->Controller->Session->del('Auth');
|
||||
//$this->Controller->Acl->Aro->execute('truncate aros;');
|
||||
//$this->Controller->Acl->Aro->execute('truncate acos;');
|
||||
//$this->Controller->Acl->Aro->execute('truncate aros_acos;');
|
||||
}
|
||||
|
||||
function testLoginRedirect() {
|
||||
$backup = $_SERVER['HTTP_REFERER'];
|
||||
|
||||
$_SERVER['HTTP_REFERER'] = false;
|
||||
$this->Controller->data = array();
|
||||
$this->Controller->Auth->loginRedirect = array('controller' => 'pages', 'action' => 'display', 'welcome');
|
||||
|
||||
|
||||
$this->Controller->Session->write('Auth', array('AuthUser' => array('id'=>'1', 'username'=>'nate')));
|
||||
|
||||
$this->Controller->params['url']['url'] = 'users/login';
|
||||
$this->Controller->Auth->initialize($this->Controller);
|
||||
|
||||
$this->Controller->Auth->userModel = 'AuthUser';
|
||||
$this->Controller->Auth->loginRedirect = array('controller' => 'pages', 'action' => 'display', 'welcome');
|
||||
$this->Controller->Auth->startup($this->Controller);
|
||||
$expected = $this->Controller->Auth->_normalizeURL($this->Controller->Auth->loginRedirect);
|
||||
$this->assertEqual($expected, $this->Controller->Auth->redirect());
|
||||
$this->Controller->Session->del('Auth');
|
||||
|
||||
$this->Controller->Session->del('Auth');
|
||||
|
||||
$this->Controller->params['url']['url'] = 'admin/';
|
||||
$this->Controller->Auth->initialize($this->Controller);
|
||||
$this->Controller->Auth->userModel = 'AuthUser';
|
||||
$this->Controller->Auth->loginRedirect = null;
|
||||
$this->Controller->Auth->startup($this->Controller);
|
||||
$expected = $this->Controller->Auth->_normalizeURL('admin/');
|
||||
$this->assertEqual($expected, $this->Controller->Auth->redirect());
|
||||
$this->Controller->Session->del('Auth');
|
||||
|
||||
|
||||
$this->Controller->Session->del('Auth');
|
||||
|
||||
$_SERVER['HTTP_REFERER'] = '/admin/';
|
||||
$this->Controller->Session->write('Auth', array('AuthUser' => array('id'=>'1', 'username'=>'nate')));
|
||||
|
||||
$this->Controller->params['url']['url'] = 'users/login';
|
||||
$this->Controller->Auth->initialize($this->Controller);
|
||||
$this->Controller->Auth->userModel = 'AuthUser';
|
||||
$this->Controller->Auth->loginRedirect = null;
|
||||
$this->Controller->Auth->startup($this->Controller);
|
||||
$expected = '/admin/';
|
||||
$expected = $this->Controller->Auth->_normalizeURL('admin');
|
||||
$this->assertEqual($expected, $this->Controller->Auth->redirect());
|
||||
$this->Controller->Session->del('Auth');
|
||||
|
||||
$_SERVER['HTTP_REFERER'] = $backup;
|
||||
$this->Controller->Session->del('Auth');
|
||||
}
|
||||
|
||||
function testEmptyUsernameOrPassword() {
|
||||
|
|
|
@ -69,7 +69,7 @@ class NumberTree extends CakeTestModel {
|
|||
}
|
||||
|
||||
class NumberTreeCase extends CakeTestCase {
|
||||
var $fixtures = array('number_tree');
|
||||
var $fixtures = array('core.number_tree');
|
||||
|
||||
function testInitialize() {
|
||||
$this->NumberTree = & new NumberTree();
|
||||
|
@ -721,5 +721,9 @@ class NumberTreeCase extends CakeTestCase {
|
|||
array('NumberTree' => array('name' => '1.2.2')));
|
||||
$this->assertIdentical($result, $expects);
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
unset($this->NumberTree);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -41,6 +41,7 @@ uses('controller'.DS.'components'.DS.'acl', 'model'.DS.'db_acl');
|
|||
if(!class_exists('aclnodetestbase')) {
|
||||
class AclNodeTestBase extends AclNode {
|
||||
var $useDbConfig = 'test_suite';
|
||||
var $cacheSources = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,6 +132,45 @@ if(!class_exists('db_acl_test')) {
|
|||
function testNodeNesting() {
|
||||
}
|
||||
|
||||
function testNode(){
|
||||
$aco = new AcoTest();
|
||||
$result = Set::extract($aco->node('Controller1'), '{n}.AcoTest.id');
|
||||
$expected = array(2, 1);
|
||||
$this->assertEqual($result, $expected);
|
||||
|
||||
$result = Set::extract($aco->node('Controller1/action1'), '{n}.AcoTest.id');
|
||||
$expected = array(3, 2, 1);
|
||||
$this->assertEqual($result, $expected);
|
||||
|
||||
$result = Set::extract($aco->node('Controller2/action1'), '{n}.AcoTest.id');
|
||||
$expected = array(7, 6, 1);
|
||||
$this->assertEqual($result, $expected);
|
||||
|
||||
$result = Set::extract($aco->node('Controller1/action2'), '{n}.AcoTest.id');
|
||||
$expected = array(5, 2, 1);
|
||||
$this->assertEqual($result, $expected);
|
||||
|
||||
$result = Set::extract($aco->node('Controller1/action1/record1'), '{n}.AcoTest.id');
|
||||
$expected = array(4, 3, 2, 1);
|
||||
$this->assertEqual($result, $expected);
|
||||
|
||||
$result = Set::extract($aco->node('Controller2/action1/record1'), '{n}.AcoTest.id');
|
||||
$expected = array(8, 7, 6, 1);
|
||||
$this->assertEqual($result, $expected);
|
||||
|
||||
//action3 is an action with no ACO entry
|
||||
//the default returned ACOs should be its parents
|
||||
$result = Set::extract($aco->node('Controller2/action3'), '{n}.AcoTest.id');
|
||||
$expected = array(6, 1);
|
||||
$this->assertEqual($result, $expected);
|
||||
|
||||
//action3 and record5 have none ACO entry
|
||||
//the default returned ACOs should be their parents ACO
|
||||
$result = Set::extract($aco->node('Controller2/action3/record5'), '{n}.AcoTest.id');
|
||||
$expected = array(6, 1);
|
||||
$this->assertEqual($result, $expected);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -48,7 +48,7 @@ class Test extends Model {
|
|||
|
||||
function loadInfo() {
|
||||
return new Set(array(
|
||||
array('name' => 'id', 'type' => 'integer', 'null' => '', 'default' => '1', 'length' => '8'),
|
||||
array('name' => 'id', 'type' => 'integer', 'null' => '', 'default' => '1', 'length' => '8', 'key'=>'primary'),
|
||||
array('name' => 'name', 'type' => 'string', 'null' => '', 'default' => '', 'length' => '255'),
|
||||
array('name' => 'email', 'type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'),
|
||||
array('name' => 'notes', 'type' => 'text', 'null' => '1', 'default' => 'write some notes here', 'length' => ''),
|
||||
|
@ -56,6 +56,17 @@ class Test extends Model {
|
|||
array('name' => 'updated', 'type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null)
|
||||
));
|
||||
}
|
||||
|
||||
function schema() {
|
||||
return new Set(array(
|
||||
'id'=> array('type' => 'integer', 'null' => '', 'default' => '1', 'length' => '8', 'key'=>'primary'),
|
||||
'name'=> array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'),
|
||||
'email'=> array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'),
|
||||
'notes'=> array('type' => 'text', 'null' => '1', 'default' => 'write some notes here', 'length' => ''),
|
||||
'created'=> array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''),
|
||||
'updated'=> array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -174,6 +185,24 @@ class Featured extends CakeTestModel {
|
|||
class Tag extends CakeTestModel {
|
||||
var $name = 'Tag';
|
||||
}
|
||||
/**
|
||||
* Short description for class.
|
||||
*
|
||||
* @package cake.tests
|
||||
* @subpackage cake.tests.cases.libs.model
|
||||
*/
|
||||
class ArticleTag extends CakeTestModel {
|
||||
var $name = 'ArticleTag';
|
||||
}
|
||||
/**
|
||||
* Short description for class.
|
||||
*
|
||||
* @package cake.tests
|
||||
* @subpackage cake.tests.cases.libs.model
|
||||
*/
|
||||
class ArticleFeaturedTag extends CakeTestModel {
|
||||
var $name = 'ArticleFeaturedTag';
|
||||
}
|
||||
/**
|
||||
* Short description for class.
|
||||
*
|
||||
|
@ -354,7 +383,7 @@ class ModelTest extends CakeTestCase {
|
|||
|
||||
var $fixtures = array(
|
||||
'core.category', 'core.category_thread', 'core.user', 'core.article', 'core.featured', 'core.article_featureds_tags',
|
||||
'core.article_featured', 'core.tag', 'core.articles_tag', 'core.comment', 'core.attachment',
|
||||
'core.article_featured', 'core.articles', 'core.tag', 'core.articles_tag', 'core.comment', 'core.attachment',
|
||||
'core.apple', 'core.sample', 'core.another_article', 'core.advertisement', 'core.home', 'core.post', 'core.author',
|
||||
'core.project', 'core.thread', 'core.message', 'core.bid'
|
||||
);
|
||||
|
@ -430,9 +459,7 @@ class ModelTest extends CakeTestCase {
|
|||
'Thread' => array()
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEqual($result, $expected);
|
||||
|
||||
unset($this->Project);
|
||||
}
|
||||
|
||||
|
@ -521,7 +548,7 @@ class ModelTest extends CakeTestCase {
|
|||
}
|
||||
|
||||
$expected = array(
|
||||
array('name' => 'id', 'type' => 'integer', 'null' => false, 'default' => null, 'length' => $intLength),
|
||||
array('name' => 'id', 'type' => 'integer', 'null' => false, 'default' => null, 'length' => $intLength, 'key' => 'primary', 'extra' => 'auto_increment'),
|
||||
array('name' => 'user', 'type' => 'string', 'null' => false, 'default' => '', 'length' => 255),
|
||||
array('name' => 'password', 'type' => 'string', 'null' => false, 'default' => '', 'length' => 255),
|
||||
array('name' => 'created', 'type' => 'datetime', 'null' => true, 'default' => null, 'length' => null),
|
||||
|
|
185
cake/tests/cases/libs/model/schema.test.php
Normal file
185
cake/tests/cases/libs/model/schema.test.php
Normal file
|
@ -0,0 +1,185 @@
|
|||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Test for Schema database management
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
|
||||
* Copyright 2005-2007, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The Open Group Test Suite License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2005-2007, Cake Software Foundation, Inc.
|
||||
* @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests
|
||||
* @package cake.tests
|
||||
* @subpackage cake.tests.cases.libs
|
||||
* @since CakePHP(tm) v 1.2.0.5550
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
|
||||
*/
|
||||
uses('model' . DS .'schema');
|
||||
/**
|
||||
* Test for Schema database management
|
||||
*
|
||||
* @package cake.tests
|
||||
* @subpackage cake.tests.cases.libs
|
||||
*/
|
||||
class MyAppSchema extends CakeSchema {
|
||||
|
||||
var $name = 'MyApp';
|
||||
|
||||
var $connection = 'test_suite';
|
||||
|
||||
var $posts = array(
|
||||
'id' => array('type'=>'integer', 'null' => false, 'default' => null, 'key' => 'primary', 'extra'=> 'auto_increment'),
|
||||
'author_id' => array('type'=>'integer', 'null' => false, 'default' => ''),
|
||||
'title' => array('type'=>'string', 'null' => false, 'default' => 'Title'),
|
||||
'summary' => array('type'=>'text', 'null' => true),
|
||||
'body' => array('type'=>'text', 'null' => true),
|
||||
'published' => array('type'=>'string', 'null' => true, 'default' => 'Y', 'length' => 1),
|
||||
'created' => array('type'=>'datetime', 'null' => true),
|
||||
'updated' => array('type'=>'datetime', 'null' => true),
|
||||
'indexes' => array('PRIMARY'=>array('column'=>'id', 'unique' => true)),
|
||||
|
||||
);
|
||||
|
||||
var $comments = array(
|
||||
'id' => array('type'=>'integer', 'null' => false, 'default' => null, 'key' => 'primary', 'extra'=> 'auto_increment'),
|
||||
'post_id' => array('type'=>'integer', 'null' => false, 'default' => ''),
|
||||
'user_id' => array('type'=>'integer', 'null' => false, 'default' => ''),
|
||||
'title' => array('type'=>'string', 'null' => false, 'length' => 100),
|
||||
'comment' => array('type'=>'text', 'null' => false),
|
||||
'published' => array('type'=>'string', 'null' => true, 'default' => 'N', 'length' => 1),
|
||||
'created' => array('type'=>'datetime', 'null' => true),
|
||||
'updated' => array('type'=>'datetime', 'null' => true),
|
||||
'indexes' => array('PRIMARY'=>array('column'=>'id', 'unique' => true)),
|
||||
);
|
||||
|
||||
function setup($version) {
|
||||
}
|
||||
|
||||
function teardown($version) {
|
||||
}
|
||||
}
|
||||
class TestAppSchema extends CakeSchema {
|
||||
|
||||
var $name = 'MyApp';
|
||||
|
||||
var $posts = array(
|
||||
'id' => array('type'=>'integer', 'null' => false, 'default' => null, 'key' => 'primary', 'extra'=> 'auto_increment'),
|
||||
'author_id' => array('type'=>'integer', 'null' => false, 'default' => ''),
|
||||
'title' => array('type'=>'string', 'null' => false, 'default' => ''),
|
||||
'body' => array('type'=>'text', 'null' => true),
|
||||
'published' => array('type'=>'string', 'null' => true, 'default' => 'N', 'length' => 1),
|
||||
'created' => array('type'=>'datetime', 'null' => true),
|
||||
'updated' => array('type'=>'datetime', 'null' => true),
|
||||
'indexes' => array('PRIMARY'=>array('column'=>'id', 'unique' => true)),
|
||||
);
|
||||
var $comments = array(
|
||||
'id' => array('type'=>'integer', 'null' => false, 'default' => null, 'key' => 'primary', 'extra'=> 'auto_increment'),
|
||||
'article_id' => array('type'=>'integer', 'null' => false, 'default' => ''),
|
||||
'user_id' => array('type'=>'integer', 'null' => false, 'default' => ''),
|
||||
'comment' => array('type'=>'text', 'null' => true),
|
||||
'published' => array('type'=>'string', 'null' => true, 'default' => 'N', 'length' => 1),
|
||||
'created' => array('type'=>'datetime', 'null' => true),
|
||||
'updated' => array('type'=>'datetime', 'null' => true),
|
||||
'indexes' => array('PRIMARY'=>array('column'=>'id', 'unique' => true)),
|
||||
);
|
||||
|
||||
|
||||
function setup($version) {
|
||||
}
|
||||
|
||||
function teardown($version) {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Short description for class.
|
||||
*
|
||||
* @package cake.tests
|
||||
* @subpackage cake.tests.cases.libs.model
|
||||
*/
|
||||
class SchemaPost extends CakeTestModel {
|
||||
var $name = 'SchemaPost';
|
||||
//var $useTable = 'posts';
|
||||
var $hasMany = array('SchemaComment');
|
||||
}
|
||||
/**
|
||||
* Short description for class.
|
||||
*
|
||||
* @package cake.tests
|
||||
* @subpackage cake.tests.cases.libs.model
|
||||
*/
|
||||
class SchemaComment extends CakeTestModel {
|
||||
var $name = 'SchemaComment';
|
||||
//var $useTable = 'comments';
|
||||
var $belongsTo = array('SchemaPost');
|
||||
}
|
||||
/**
|
||||
* Short description for class.
|
||||
*
|
||||
* @package cake.tests
|
||||
* @subpackage cake.tests.cases.libs
|
||||
*/
|
||||
class CakeSchemaTest extends CakeTestCase {
|
||||
|
||||
var $fixtures = array('core.post', 'core.comment', 'core.author');
|
||||
|
||||
function setUp() {
|
||||
$this->Schema = new TestAppSchema();
|
||||
}
|
||||
|
||||
|
||||
function testSchemaGeneration() {
|
||||
|
||||
$read = $this->Schema->read(array('connection'=>'test_suite', 'name'=>'TestApp', 'models'=>array('post', 'comment')));
|
||||
$this->assertEqual($read['tables'], $this->Schema->tables);
|
||||
|
||||
$write = $this->Schema->write(array('name'=>'MyOtherApp', 'tables'=> $read['tables'], 'path'=> TMP . 'tests'));
|
||||
$file = file_get_contents(TMP . 'tests' . DS .'schema.php');
|
||||
$this->assertEqual($write, $file);
|
||||
|
||||
require_once( TMP . 'tests' . DS .'schema.php');
|
||||
$OtherSchema = new MyOtherAppSchema();
|
||||
$this->assertEqual($read['tables'], $OtherSchema->tables);
|
||||
}
|
||||
|
||||
function testSchemaComparison() {
|
||||
$New = new MyAppSchema();
|
||||
$compare = $New->compare($this->Schema);
|
||||
$expected = array(
|
||||
'posts'=> array(
|
||||
'add'=> array('summary'=>array('type'=> 'text', 'null'=> 1)),
|
||||
'change'=> array('title'=>array('type'=>'string', 'null'=> false, 'default'=> 'Title'), 'published'=>array('type'=>'string', 'null'=> true, 'default'=>'Y', 'length'=> '1')),
|
||||
),
|
||||
'comments'=> array(
|
||||
'add'=>array('post_id'=>array('type'=> 'integer', 'null'=> false, 'default'=>''), 'title'=>array('type'=> 'string', 'null'=> false, 'length'=> 100)),
|
||||
'drop'=>array('article_id'=>array('type'=> 'integer', 'null'=> false, 'default'=>'')),
|
||||
'change'=>array('comment'=>array('type'=>'text', 'null'=> false))
|
||||
|
||||
),
|
||||
);
|
||||
|
||||
$this->assertEqual($expected, $compare);
|
||||
}
|
||||
|
||||
function testSchemaLoading() {
|
||||
$Other = $this->Schema->load(array('name'=>'MyOtherApp', 'path'=> TMP . 'tests'));
|
||||
|
||||
$this->assertEqual($Other->name, 'MyOtherApp');
|
||||
$this->assertEqual($Other->tables, $this->Schema->tables);
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
unset($this->Schema);
|
||||
}
|
||||
}
|
||||
?>
|
9
cake/tests/fixtures/aco_fixture.php
vendored
9
cake/tests/fixtures/aco_fixture.php
vendored
|
@ -44,6 +44,15 @@ class AcoFixture extends CakeTestFixture {
|
|||
'rght' => array('type' => 'integer', 'length' => 10, 'null' => true)
|
||||
);
|
||||
var $records = array(
|
||||
array ('id' => 1, 'parent_id' => null, 'model' => '', 'foreign_key' => '', 'alias' => 'ROOT', 'lft' => 1, 'rght' => 18),
|
||||
array ('id' => 2, 'parent_id' => 1, 'model' => '', 'foreign_key' => '', 'alias' => 'Controller1', 'lft' => 2, 'rght' => 9),
|
||||
array ('id' => 3, 'parent_id' => 2, 'model' => '', 'foreign_key' => '', 'alias' => 'action1', 'lft' => 3, 'rght' => 6),
|
||||
array ('id' => 4, 'parent_id' => 3, 'model' => '', 'foreign_key' => '', 'alias' => 'record1', 'lft' => 4, 'rght' => 5),
|
||||
array ('id' => 5, 'parent_id' => 2, 'model' => '', 'foreign_key' => '', 'alias' => 'action2', 'lft' => 7, 'rght' => 8),
|
||||
array ('id' => 6, 'parent_id' => 1, 'model' => '', 'foreign_key' => '', 'alias' => 'Controller2', 'lft' => 10, 'rght' => 17),
|
||||
array ('id' => 7, 'parent_id' => 6, 'model' => '', 'foreign_key' => '', 'alias' => 'action1', 'lft' => 11, 'rght' => 14),
|
||||
array ('id' => 8, 'parent_id' => 7, 'model' => '', 'foreign_key' => '', 'alias' => 'record1', 'lft' => 12, 'rght' => 13),
|
||||
array ('id' => 9, 'parent_id' => 6, 'model' => '', 'foreign_key' => '', 'alias' => 'action2', 'lft' => 15, 'rght' => 16),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,11 +34,11 @@
|
|||
*/
|
||||
class ArticleFeaturedsTagsFixture extends CakeTestFixture {
|
||||
var $name = 'ArticleFeaturedsTags';
|
||||
var $primaryKey = array('article_featured_id', 'tag_id');
|
||||
|
||||
var $fields = array(
|
||||
'article_featured_id' => array('type' => 'integer', 'null' => false),
|
||||
'tag_id' => array('type' => 'integer', 'null' => false),
|
||||
'indexes' => array('UNIQUE_FEATURED' => array('column'=> array('article_featured_id', 'tag_id'), 'unique'=> 1))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
2
cake/tests/fixtures/articles_tag_fixture.php
vendored
2
cake/tests/fixtures/articles_tag_fixture.php
vendored
|
@ -37,8 +37,8 @@ class ArticlesTagFixture extends CakeTestFixture {
|
|||
var $fields = array(
|
||||
'article_id' => array('type' => 'integer', 'null' => false),
|
||||
'tag_id' => array('type' => 'integer', 'null' => false),
|
||||
'indexes' => array('UNIQUE_TAG' => array('column'=> array('article_id', 'tag_id'), 'unique'=>1))
|
||||
);
|
||||
var $primaryKey = array('article_id', 'tag_id');
|
||||
var $records = array(
|
||||
array('article_id' => 1, 'tag_id' => 1),
|
||||
array('article_id' => 1, 'tag_id' => 2),
|
||||
|
|
|
@ -181,10 +181,9 @@ class CakeTestCase extends UnitTestCase {
|
|||
|
||||
foreach ($models as $model) {
|
||||
$object =& $classRegistry->getObject($model['key']);
|
||||
|
||||
if ($object !== false) {
|
||||
$object->useDbConfig = 'test_suite';
|
||||
$object->setDataSource();
|
||||
$object->setDataSource('test_suite');
|
||||
$object->cacheSources = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -336,7 +335,6 @@ class CakeTestCase extends UnitTestCase {
|
|||
if (isset($this->_fixtures) && isset($this->db)) {
|
||||
foreach ($this->_fixtures as $fixture) {
|
||||
$query = $fixture->create();
|
||||
|
||||
if (isset($query) && $query !== false) {
|
||||
$this->db->_execute($query);
|
||||
}
|
||||
|
@ -352,7 +350,6 @@ class CakeTestCase extends UnitTestCase {
|
|||
if (isset($this->_fixtures) && isset($this->db)) {
|
||||
foreach (array_reverse($this->_fixtures) as $fixture) {
|
||||
$query = $fixture->drop();
|
||||
|
||||
if (isset($query) && $query !== false) {
|
||||
$this->db->_execute($query);
|
||||
}
|
||||
|
@ -370,7 +367,6 @@ class CakeTestCase extends UnitTestCase {
|
|||
if (isset($this->_fixtures) && isset($this->db) && !in_array(low($method), array('start', 'end'))) {
|
||||
foreach ($this->_fixtures as $fixture) {
|
||||
$query = $fixture->truncate();
|
||||
|
||||
if (isset($query) && $query !== false) {
|
||||
$this->db->_execute($query);
|
||||
}
|
||||
|
@ -393,9 +389,7 @@ class CakeTestCase extends UnitTestCase {
|
|||
*/
|
||||
function getTests() {
|
||||
$methods = array_diff(parent::getTests(), array('testAction', 'testaction'));
|
||||
|
||||
$methods = am(am(array('start', 'startCase'), $methods), array('endCase', 'end'));
|
||||
|
||||
return $methods;
|
||||
}
|
||||
/**
|
||||
|
@ -433,6 +427,7 @@ class CakeTestCase extends UnitTestCase {
|
|||
|
||||
// Get db connection
|
||||
$this->db =& ConnectionManager::getDataSource('test_suite');
|
||||
$this->db->cacheSources = false;
|
||||
$this->db->fullDebug = false;
|
||||
}
|
||||
/**
|
||||
|
|
|
@ -44,12 +44,17 @@ class CakeTestFixture extends Object {
|
|||
function __construct(&$db) {
|
||||
$this->db =& $db;
|
||||
$this->init();
|
||||
if(!class_exists('cakeschema')) {
|
||||
uses('model' . DS .'schema');
|
||||
}
|
||||
$this->Schema = new CakeSchema(array('name'=>'TestSuite', 'connection'=>'test_suite'));
|
||||
}
|
||||
/**
|
||||
* Initialize the fixture.
|
||||
*
|
||||
*/
|
||||
function init() {
|
||||
|
||||
if (isset($this->import) && (is_string($this->import) || is_array($this->import))) {
|
||||
$import = array();
|
||||
|
||||
|
@ -63,33 +68,29 @@ class CakeTestFixture extends Object {
|
|||
|
||||
if (isset($import['model']) && (class_exists($import['model']) || loadModel($import['model']))) {
|
||||
$model =& new $import['model'];
|
||||
$modelDb =& ConnectionManager::getDataSource($model->useDbConfig);
|
||||
|
||||
$info = $model->loadInfo();
|
||||
|
||||
$this->fields = array_combine(Set::extract($info->value, '{n}.name'), $info->value);
|
||||
$db =& ConnectionManager::getDataSource($model->useDbConfig);
|
||||
$db->cacheSources = false;
|
||||
$this->table = $this->useTable;
|
||||
$schema = $model->schema(true);
|
||||
$this->fields = $schema->value;
|
||||
$this->fields[$model->primaryKey]['key'] = 'primary';
|
||||
|
||||
$this->primaryKey = array( $model->primaryKey );
|
||||
} elseif (isset($import['table'])) {
|
||||
$model =& new stdClass();
|
||||
$modelDb =& ConnectionManager::getDataSource($import['connection']);
|
||||
|
||||
$model =& new Model(null, $import['table'], $import['connection']);
|
||||
$db =& ConnectionManager::getDataSource($import['connection']);
|
||||
$db->cacheSources = false;
|
||||
$model->name = Inflector::camelize(Inflector::singularize($import['table']));
|
||||
$model->table = $import['table'];
|
||||
$model->tablePrefix = $modelDb->config['prefix'];
|
||||
|
||||
$info = $modelDb->describe($model);
|
||||
|
||||
$this->fields = array_combine(Set::extract($info, '{n}.name'), $info);
|
||||
$model->tablePrefix = $db->config['prefix'];
|
||||
$schema = $model->schema(true);
|
||||
$this->fields = $schema->value;
|
||||
}
|
||||
|
||||
if ($import['records'] !== false && isset($model) && isset($modelDb)) {
|
||||
if ($import['records'] !== false && isset($model) && isset($db)) {
|
||||
$this->records = array();
|
||||
|
||||
$query = array(
|
||||
'fields' => Set::extract($this->fields, '{n}.name'),
|
||||
'table' => $modelDb->name($model->table),
|
||||
'fields' => array_keys($this->fields),
|
||||
'table' => $db->name($model->table),
|
||||
'alias' => $model->name,
|
||||
'conditions' => array(),
|
||||
'order' => null,
|
||||
|
@ -97,10 +98,10 @@ class CakeTestFixture extends Object {
|
|||
);
|
||||
|
||||
foreach ($query['fields'] as $index => $field) {
|
||||
$query['fields'][$index] = $modelDb->name($query['alias']) . '.' . $modelDb->name($field);
|
||||
$query['fields'][$index] = $db->name($query['alias']) . '.' . $db->name($field);
|
||||
}
|
||||
|
||||
$records = $modelDb->fetchAll($modelDb->buildStatement($query, $model), false, $model->name);
|
||||
$records = $db->fetchAll($db->buildStatement($query, $model), false, $model->name);
|
||||
|
||||
if ($records !== false && !empty($records)) {
|
||||
$this->records = Set::extract($records, '{n}.' . $model->name);
|
||||
|
@ -116,14 +117,6 @@ class CakeTestFixture extends Object {
|
|||
$this->primaryKey = 'id';
|
||||
}
|
||||
|
||||
if (isset($this->primaryKey) && !is_array($this->primaryKey)) {
|
||||
$this->primaryKey = array( $this->primaryKey );
|
||||
}
|
||||
|
||||
if (isset($this->primaryKey) && isset($this->fields[$this->primaryKey[0]])) {
|
||||
$this->fields[$this->primaryKey[0]]['key'] = 'primary';
|
||||
}
|
||||
|
||||
if (isset($this->fields)) {
|
||||
foreach ($this->fields as $index => $field) {
|
||||
if (empty($field['default'])) {
|
||||
|
@ -144,43 +137,9 @@ class CakeTestFixture extends Object {
|
|||
if (!isset($this->fields) || empty($this->fields)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$create = 'CREATE TABLE ' . $this->db->name($this->db->config['prefix'] . $this->table) . ' (' . "\n";
|
||||
|
||||
foreach ($this->fields as $field => $attributes) {
|
||||
if (!is_array($attributes)) {
|
||||
$attributes = array('type' => $attributes);
|
||||
} elseif (isset($attributes['key']) && low($attributes['key']) == 'primary' && !isset($this->primaryKey)) {
|
||||
$this->primaryKey = array ( $field );
|
||||
}
|
||||
|
||||
$column = array($field, $attributes['type']);
|
||||
unset($attributes['type']);
|
||||
|
||||
if (!empty($attributes)) {
|
||||
$column = array_merge($column, $attributes);
|
||||
}
|
||||
|
||||
$create .= $this->db->generateColumnSchema($column) . ',' . "\n";
|
||||
}
|
||||
|
||||
if (isset($this->primaryKey)) {
|
||||
foreach ($this->primaryKey as $index => $field) {
|
||||
$this->primaryKey[$index] = $this->db->name($field);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($this->primaryKey)) {
|
||||
$create = substr($create, 0, -1);
|
||||
} else {
|
||||
$create .= 'PRIMARY KEY(' . implode(', ', $this->primaryKey) . ')' . "\n";
|
||||
}
|
||||
|
||||
$create .= ')';
|
||||
|
||||
$this->_create = $create;
|
||||
$this->Schema->_build(array($this->table => $this->fields));
|
||||
$this->_create = $this->db->createSchema($this->Schema);
|
||||
}
|
||||
|
||||
return $this->_create;
|
||||
}
|
||||
/**
|
||||
|
@ -192,9 +151,9 @@ class CakeTestFixture extends Object {
|
|||
*/
|
||||
function drop() {
|
||||
if (!isset($this->_drop)) {
|
||||
$this->_drop = 'DROP TABLE ' . $this->db->name($this->db->config['prefix'] . $this->table);
|
||||
$this->Schema->_build(array($this->table => $this->fields));
|
||||
$this->_drop = $this->db->dropSchema($this->Schema);
|
||||
}
|
||||
|
||||
return $this->_drop;
|
||||
}
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue