2005-08-21 06:49:02 +00:00
< ? php
/* SVN FILE: $Id$ */
2005-06-23 13:59:02 +00:00
/**
2005-09-07 01:52:45 +00:00
* Object - relational mapper .
2005-12-22 01:07:28 +00:00
*
2005-09-07 01:52:45 +00:00
* DBO - backed object data model , for mapping database tables to Cake objects .
2005-06-23 13:59:02 +00:00
*
2006-07-30 12:24:03 +00:00
* PHP versions 5
2005-08-21 06:49:02 +00:00
*
2007-02-02 10:39:45 +00:00
* CakePHP ( tm ) : Rapid Development Framework < http :// www . cakephp . org />
* Copyright 2005 - 2007 , Cake Software Foundation , Inc .
2006-05-26 05:29:17 +00:00
* 1785 E . Sahara Avenue , Suite 490 - 204
* Las Vegas , Nevada 89104
2005-12-27 03:33:44 +00:00
*
2005-12-23 21:57:26 +00:00
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice .
2005-06-23 13:59:02 +00:00
*
2005-12-22 01:07:28 +00:00
* @ filesource
2007-02-02 10:39:45 +00:00
* @ copyright Copyright 2005 - 2007 , Cake Software Foundation , Inc .
* @ link http :// www . cakefoundation . org / projects / info / cakephp CakePHP ( tm ) Project
2006-05-26 05:29:17 +00:00
* @ package cake
* @ subpackage cake . cake . libs . model
2007-02-02 10:39:45 +00:00
* @ since CakePHP ( tm ) v 0.10 . 0.0
2006-05-26 05:29:17 +00:00
* @ version $Revision $
* @ modifiedby $LastChangedBy $
* @ lastmodified $Date $
* @ license http :// www . opensource . org / licenses / mit - license . php The MIT License
2005-06-23 13:59:02 +00:00
*/
2006-07-22 14:13:07 +00:00
/**
2006-07-30 12:24:03 +00:00
* Included libs
2006-07-22 14:13:07 +00:00
*/
2007-11-18 07:18:25 +00:00
App :: import ( 'Core' , array ( 'ClassRegistry' , 'Overloadable' , 'Validation' , 'Behavior' , 'ConnectionManager' , 'Set' ));
2006-01-17 17:52:23 +00:00
/**
2006-07-30 12:24:03 +00:00
* Object - relational mapper .
*
* DBO - backed object data model .
* Automatically selects a database table name based on a pluralized lowercase object class name
* ( i . e . class ' User ' => table ' users '; class ' Man ' => table ' men ' )
* The table is required to have at least 'id auto_increment' , 'created datetime' ,
* and 'modified datetime' fields .
*
* @ package cake
* @ subpackage cake . cake . libs . model
*/
class Model extends Overloadable {
/**
* The name of the DataSource connection that this Model uses
*
* @ var string
* @ access public
*/
var $useDbConfig = 'default' ;
/**
* Custom database table name .
*
* @ var string
* @ access public
*/
var $useTable = null ;
/**
* Custom display field name . Display fields are used by Scaffold , in SELECT boxes ' OPTION elements .
*
* @ var string
* @ access public
*/
var $displayField = null ;
/**
* Value of the primary key ID of the record that this model is currently pointing to
*
2007-11-05 03:36:12 +00:00
* @ var mixed
2006-07-30 12:24:03 +00:00
* @ access public
*/
var $id = false ;
/**
* Container for the data that this model gets from persistent storage ( the database ) .
*
* @ var array
* @ access public
*/
var $data = array ();
/**
* Table name for this Model .
*
* @ var string
* @ access public
*/
var $table = false ;
/**
* The name of the ID field for this Model .
*
* @ var string
* @ access public
*/
var $primaryKey = null ;
/**
* Table metadata
*
* @ var array
2007-08-21 21:46:59 +00:00
* @ access protected
*/
var $_schema = null ;
2006-07-30 12:24:03 +00:00
/**
* List of validation rules . Append entries for validation as ( 'field_name' => '/^perl_compat_regexp$/' )
* that have to match with preg_match () . Use these rules with Model :: validate ()
*
* @ var array
* @ access public
*/
var $validate = array ();
/**
* Errors in validation
2007-11-05 03:36:12 +00:00
*
2006-07-30 12:24:03 +00:00
* @ var array
* @ access public
*/
var $validationErrors = array ();
/**
* Database table prefix for tables in model .
*
* @ var string
* @ access public
*/
var $tablePrefix = null ;
/**
* Name of the model .
*
* @ var string
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
var $name = null ;
/**
2007-10-27 01:32:17 +00:00
* Alias name for model .
2006-07-30 12:24:03 +00:00
*
2007-11-05 03:36:12 +00:00
* @ var string
2007-10-27 01:32:17 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
2007-10-27 01:32:17 +00:00
var $alias = null ;
2006-07-30 12:24:03 +00:00
/**
* List of table names included in the Model description . Used for associations .
*
* @ var array
* @ access public
*/
var $tableToModel = array ();
/**
* Whether or not transactions for this model should be logged
*
* @ var boolean
* @ access public
*/
var $logTransactions = false ;
/**
* Whether or not to enable transactions for this model ( i . e . BEGIN / COMMIT / ROLLBACK )
*
* @ var boolean
* @ access public
*/
var $transactional = false ;
/**
* Whether or not to cache queries for this model . This enables in - memory
* caching only , the results are not stored beyond this execution .
*
* @ var boolean
* @ access public
*/
2006-11-21 22:40:30 +00:00
var $cacheQueries = false ;
2006-07-30 12:24:03 +00:00
/**
* belongsTo association
*
* @ var array
* @ access public
*/
var $belongsTo = array ();
/**
* hasOne association
*
* @ var array
* @ access public
*/
var $hasOne = array ();
/**
* hasMany association
*
* @ var array
* @ access public
*/
var $hasMany = array ();
/**
* hasAndBelongsToMany association
*
* @ var array
* @ access public
*/
var $hasAndBelongsToMany = array ();
/**
2007-11-05 03:36:12 +00:00
* List of behaviors to use . Settings can be passed to behaviors
* by using the behavior name as index . Eg :
*
* array ( 'Translate' , 'MyBehavior' => array ( 'setting1' => 'value1' ))
2006-07-30 12:24:03 +00:00
*
* @ var array
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
var $actsAs = null ;
/**
* Behavior objects
*
* @ var array
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
var $behaviors = array ();
2007-10-17 21:19:30 +00:00
/**
* Whitelist of fields allowed to be saved
*
* @ var array
2007-11-05 03:36:12 +00:00
* @ access public
2007-10-17 21:19:30 +00:00
*/
var $whitelist = array ();
2007-04-08 23:30:31 +00:00
/**
2007-11-05 03:36:12 +00:00
* Should sources for this model be cached .
2007-04-08 23:30:31 +00:00
*
* @ var boolean
2007-11-05 03:36:12 +00:00
* @ access public
2007-04-08 23:30:31 +00:00
*/
var $cacheSources = true ;
2006-07-30 12:24:03 +00:00
/**
* Mapped behavior methods
*
* @ var array
* @ access private
*/
var $__behaviorMethods = array ();
/**
* Depth of recursive association
*
* @ var integer
* @ access public
*/
var $recursive = 1 ;
/**
* Default ordering of model records
*
2007-11-05 03:36:12 +00:00
* @ var string
* @ access public
2006-07-30 12:24:03 +00:00
*/
var $order = null ;
2007-10-01 16:49:37 +00:00
/**
2007-11-05 03:36:12 +00:00
* Whether or not the model record exists , set by Model :: exists ()
2007-10-01 16:49:37 +00:00
*
* @ var bool
2007-11-05 03:36:12 +00:00
* @ access private
2007-10-01 16:49:37 +00:00
*/
var $__exists = null ;
2006-07-30 12:24:03 +00:00
/**
* Default association keys
*
* @ var array
2007-11-05 03:36:12 +00:00
* @ access private
2006-07-30 12:24:03 +00:00
*/
var $__associationKeys = array (
2007-10-27 05:29:11 +00:00
'belongsTo' => array ( 'className' , 'foreignKey' , 'conditions' , 'fields' , 'order' , 'counterCache' ),
'hasOne' => array ( 'className' , 'foreignKey' , 'conditions' , 'fields' , 'order' , 'dependent' ),
'hasMany' => array ( 'className' , 'foreignKey' , 'conditions' , 'fields' , 'order' , 'limit' , 'offset' , 'dependent' , 'exclusive' , 'finderQuery' , 'counterQuery' ),
'hasAndBelongsToMany' => array ( 'className' , 'joinTable' , 'with' , 'foreignKey' , 'associationForeignKey' , 'conditions' , 'fields' , 'order' , 'limit' , 'offset' , 'unique' , 'finderQuery' , 'deleteQuery' , 'insertQuery' ));
2006-07-30 12:24:03 +00:00
/**
* Holds provided / generated association key names and other data for all associations
*
* @ var array
2007-11-05 03:36:12 +00:00
* @ access private
2006-07-30 12:24:03 +00:00
*/
var $__associations = array ( 'belongsTo' , 'hasOne' , 'hasMany' , 'hasAndBelongsToMany' );
2007-03-26 17:16:43 +00:00
/**
2007-05-20 05:05:18 +00:00
* Holds model associations temporarily to allow for dynamic ( un ) binding
2007-03-26 17:16:43 +00:00
*
* @ var array
2007-05-20 05:05:18 +00:00
* @ access private
2007-03-26 17:16:43 +00:00
*/
var $__backAssociation = array ();
2006-07-30 12:24:03 +00:00
/**
* The last inserted ID of the data that this model created
*
* @ var integer
2007-11-05 03:36:12 +00:00
* @ access private
2006-07-30 12:24:03 +00:00
*/
var $__insertID = null ;
/**
* The number of records returned by the last query
*
* @ var integer
2007-11-05 03:36:12 +00:00
* @ access private
2006-07-30 12:24:03 +00:00
*/
var $__numRows = null ;
/**
* The number of records affected by the last query
*
* @ var integer
2007-11-05 03:36:12 +00:00
* @ access private
2006-07-30 12:24:03 +00:00
*/
var $__affectedRows = null ;
2007-10-21 18:34:23 +00:00
/**
* List of valid finder method options
*
* @ var array
2007-11-05 03:36:12 +00:00
* @ access private
2007-10-21 18:34:23 +00:00
*/
var $__findMethods = array ( 'all' => true , 'first' => true , 'count' => true , 'neighbors' => true );
2006-07-30 12:24:03 +00:00
/**
* Constructor . Binds the Model ' s database table to the object .
*
2007-11-05 03:36:12 +00:00
* @ param integer $id Set this ID for this model on startup
2006-07-30 12:24:03 +00:00
* @ param string $table Name of database table to use .
2007-11-05 03:36:12 +00:00
* @ param object $ds DataSource connection object .
2006-07-30 12:24:03 +00:00
*/
function __construct ( $id = false , $table = null , $ds = null ) {
parent :: __construct ();
2007-08-04 17:20:50 +00:00
if ( is_array ( $id ) && isset ( $id [ 'name' ])) {
2007-10-22 02:11:58 +00:00
$options = am ( array ( 'id' => false , 'table' => null , 'ds' => null , 'alias' => null ), $id );
2007-08-04 17:20:50 +00:00
list ( $id , $table , $ds ) = array ( $options [ 'id' ], $options [ 'table' ], $options [ 'ds' ]);
$this -> name = $options [ 'name' ];
}
2006-07-30 12:24:03 +00:00
if ( $this -> name === null ) {
$this -> name = get_class ( $this );
}
if ( $this -> primaryKey === null ) {
$this -> primaryKey = 'id' ;
}
2007-10-22 02:11:58 +00:00
if ( isset ( $options [ 'alias' ]) || ! empty ( $options [ 'alias' ])) {
2007-10-27 01:32:17 +00:00
$this -> alias = $options [ 'alias' ];
2007-10-22 02:11:58 +00:00
unset ( $options );
} else {
2007-10-27 01:32:17 +00:00
$this -> alias = $this -> name ;
2007-10-22 02:11:58 +00:00
}
2007-10-27 01:32:17 +00:00
ClassRegistry :: addObject ( $this -> alias , $this );
2007-05-20 05:05:18 +00:00
2006-07-30 12:24:03 +00:00
$this -> id = $id ;
2007-10-22 02:11:58 +00:00
unset ( $id );
2007-05-20 05:05:18 +00:00
2007-06-20 06:15:35 +00:00
if ( $table === false ) {
2007-05-13 01:09:40 +00:00
$this -> useTable = false ;
2007-06-20 06:15:35 +00:00
} elseif ( $table ) {
2007-05-13 01:09:40 +00:00
$this -> useTable = $table ;
}
2007-05-20 05:05:18 +00:00
2006-07-30 12:24:03 +00:00
if ( $this -> useTable !== false ) {
$this -> setDataSource ( $ds );
2007-05-20 05:05:18 +00:00
2007-05-13 01:09:40 +00:00
if ( $this -> useTable === null ) {
$this -> useTable = Inflector :: tableize ( $this -> name );
2006-07-30 12:24:03 +00:00
}
if ( in_array ( 'settableprefix' , get_class_methods ( $this ))) {
$this -> setTablePrefix ();
}
2007-05-13 01:09:40 +00:00
$this -> setSource ( $this -> useTable );
2006-07-30 12:24:03 +00:00
$this -> __createLinks ();
if ( $this -> displayField == null ) {
if ( $this -> hasField ( 'title' )) {
$this -> displayField = 'title' ;
}
if ( $this -> hasField ( 'name' )) {
$this -> displayField = 'name' ;
}
if ( $this -> displayField == null ) {
$this -> displayField = $this -> primaryKey ;
}
}
}
2007-09-20 15:16:25 +00:00
if ( is_subclass_of ( $this , 'AppModel' )) {
$appVars = get_class_vars ( 'AppModel' );
$actsAs = $appVars [ 'actsAs' ];
$merge = array ( 'actsAs' );
if ( $this -> actsAs !== null || $this -> actsAs !== false ) {
$merge [] = 'actsAs' ;
}
foreach ( $merge as $var ) {
if ( isset ( $appVars [ $var ]) && ! empty ( $appVars [ $var ]) && is_array ( $this -> { $var })) {
$this -> { $var } = array_merge ( $this -> { $var }, array_diff ( $appVars [ $var ], $this -> { $var }));
}
}
}
2006-07-30 12:24:03 +00:00
if ( $this -> actsAs !== null && empty ( $this -> behaviors )) {
$callbacks = array ( 'setup' , 'beforeFind' , 'afterFind' , 'beforeSave' , 'afterSave' , 'beforeDelete' , 'afterDelete' , 'afterError' );
2007-01-20 20:50:57 +00:00
$this -> actsAs = Set :: normalize ( $this -> actsAs );
2006-07-30 12:24:03 +00:00
foreach ( $this -> actsAs as $behavior => $config ) {
2006-10-20 17:24:37 +00:00
$className = $behavior . 'Behavior' ;
Closes #2119 Only define clone() in PHP4 when it hasn't been already defined.
Closes #2213, Support multiple plugin paths.
Closes #2234, filepaths to behavior classes should be cached in class.paths.php also
Closes #2345, ability to group components into subfolders
Closes #2645, Improvement to basic.php for class loading.
Fixes #3526, Cache::write, when using just the config name, it fails.
Fixes #3559, loading plugin model as assoc don't work.
Closes #3567 Controller Folders (Note this does not need routing to work, but controller names can not conflict with others in the same application so naming must still be unique)
Fixes #3579, email.php component: Parse error with php 4.
Adding new class and file importer.
Updated most of the core to use the importer.
Added ClassRegsitry::init() that will create and instance of an object and store it in the registry.
Deprecated most of the load functions in basics.php
Plugin model loading now forces using the dot notation, to use models within a plugin, all the model associations must be in the PluginName.Model syntax, if this is not used, the plugin will look for the models in the main app/models directory first, if not found then it will search the plugin directories recursively until it finds a model.
var $belongsTo = array('SomeModel'); will look for some_model.php in the app/models
var $belongsTo = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $belongsTo = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
The controllers of the plugin will still look for the default models inside the plugin if var $uses is not set:
var $uses = array('SomeModel'); will look for some_model.php in the app/models
var $uses = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $uses = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
All of the above will work between plugins and main app
These changes also allow placing model and controllers is sub directories
Removed old class.paths.php file generation
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6001 3807eeeb-6ff5-0310-8944-8be069107fe0
2007-11-16 09:35:19 +00:00
if ( ! App :: import ( 'Behavior' , $behavior )) {
2006-07-30 12:24:03 +00:00
// Raise an error
} else {
2006-10-20 17:24:37 +00:00
if ( ClassRegistry :: isKeySet ( $className )) {
if ( PHP5 ) {
$this -> behaviors [ $behavior ] = ClassRegistry :: getObject ( $className );
} else {
$this -> behaviors [ $behavior ] =& ClassRegistry :: getObject ( $className );
}
} else {
if ( PHP5 ) {
$this -> behaviors [ $behavior ] = new $className ;
} else {
$this -> behaviors [ $behavior ] =& new $className ;
}
ClassRegistry :: addObject ( $className , $this -> behaviors [ $behavior ]);
}
2006-07-30 12:24:03 +00:00
$this -> behaviors [ $behavior ] -> setup ( $this , $config );
$methods = $this -> behaviors [ $behavior ] -> mapMethods ;
foreach ( $methods as $method => $alias ) {
if ( ! array_key_exists ( $method , $this -> __behaviorMethods )) {
$this -> __behaviorMethods [ $method ] = array ( $alias , $behavior );
}
}
$methods = get_class_methods ( $this -> behaviors [ $behavior ]);
$parentMethods = get_class_methods ( 'ModelBehavior' );
foreach ( $methods as $m ) {
if ( ! in_array ( $m , $parentMethods )) {
if ( strpos ( $m , '_' ) !== 0 && ! array_key_exists ( $m , $this -> __behaviorMethods ) && ! in_array ( $m , $callbacks )) {
$this -> __behaviorMethods [ $m ] = array ( $m , $behavior );
}
}
}
}
}
}
}
/**
* Handles custom method calls , like findBy < field > for DB models ,
* and custom RPC calls for remote data sources .
*
2007-11-05 03:36:12 +00:00
* @ param string $method Name of method to call .
* @ param array $params Parameters for the method .
* @ return mixed Whatever is returned by called method
2006-07-30 12:24:03 +00:00
* @ access protected
*/
2006-12-26 16:17:37 +00:00
function call__ ( $method , $params ) {
2006-08-25 00:43:48 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2006-07-30 16:49:40 +00:00
2006-10-20 17:24:37 +00:00
$methods = array_map ( 'strtolower' , array_keys ( $this -> __behaviorMethods ));
2006-07-30 12:24:03 +00:00
$call = array_values ( $this -> __behaviorMethods );
2006-10-20 17:24:37 +00:00
$map = array ();
2006-10-27 21:42:29 +00:00
2006-10-20 17:24:37 +00:00
if ( ! empty ( $methods ) && ! empty ( $call )) {
$map = array_combine ( $methods , $call );
}
2006-07-30 12:24:03 +00:00
$count = count ( $call );
2007-02-08 17:50:47 +00:00
$pass = array ( & $this );
if ( ! in_array ( low ( $method ), $methods )) {
$pass [] = $method ;
}
foreach ( $params as $param ) {
$pass [] = $param ;
}
2006-07-30 12:24:03 +00:00
2006-10-20 17:24:37 +00:00
if ( in_array ( low ( $method ), $methods )) {
2007-02-08 17:50:47 +00:00
$it = $map [ low ( $method )];
return call_user_func_array ( array ( & $this -> behaviors [ $it [ 1 ]], $it [ 0 ]), $pass );
2006-10-20 17:24:37 +00:00
}
2007-06-20 06:15:35 +00:00
for ( $i = 0 ; $i < $count ; $i ++ ) {
2006-10-20 17:24:37 +00:00
if ( strpos ( $methods [ $i ], '/' ) === 0 && preg_match ( $methods [ $i ] . 'i' , $method )) {
2007-02-08 17:50:47 +00:00
return call_user_func_array ( array ( $this -> behaviors [ $call [ $i ][ 1 ]], $call [ $i ][ 0 ]), $pass );
2006-07-30 12:24:03 +00:00
}
}
2006-11-27 05:57:53 +00:00
$return = $db -> query ( $method , $params , $this );
2006-12-19 19:26:02 +00:00
2006-11-27 05:57:53 +00:00
if ( ! PHP5 ) {
2007-10-22 02:11:58 +00:00
$this -> __resetAssociations ();
2006-11-27 05:57:53 +00:00
}
return $return ;
2006-07-30 12:24:03 +00:00
}
2007-01-06 04:58:24 +00:00
/**
* Bind model associations on the fly .
*
2007-01-06 08:41:48 +00:00
* If $permanent is true , association will not be reset
2007-11-05 03:36:12 +00:00
* to the originals defined in the model .
2007-01-06 04:58:24 +00:00
*
2007-11-05 03:36:12 +00:00
* @ param array $model Set of binding options ( indexed by model name type )
* @ param array $options Currently not used
* @ param boolean $permanent Set to true to make the binding permanent
* @ access public
* @ todo
2007-01-06 04:58:24 +00:00
*/
2007-01-31 23:25:05 +00:00
function bind ( $model , $options , $permanent = true ) {
if ( ! is_array ( $model )) {
$model = array ( $model => $options );
}
2007-06-20 06:15:35 +00:00
foreach ( $model as $name => $options ) {
2007-01-31 23:25:05 +00:00
if ( isset ( $options [ 'type' ])) {
$assoc = $options [ 'type' ];
} elseif ( isset ( $options [ 0 ])) {
$assoc = $options [ 0 ];
}
2007-06-20 06:15:35 +00:00
if ( ! $permanent ) {
2007-01-31 23:25:05 +00:00
$this -> __backAssociation [ $assoc ] = $this -> { $assoc };
}
2007-06-20 06:15:35 +00:00
foreach ( $model as $key => $value ) {
2007-01-31 23:25:05 +00:00
$assocName = $key ;
$modelName = $key ;
if ( isset ( $value [ 'className' ])) {
$modelName = $value [ 'className' ];
}
2007-01-24 10:47:12 +00:00
2007-01-31 23:25:05 +00:00
$this -> __constructLinkedModel ( $assocName , $modelName );
$this -> { $assoc }[ $assocName ] = $model [ $assocName ];
$this -> __generateAssociation ( $assoc );
}
}
2007-01-06 04:58:24 +00:00
}
2006-07-30 12:24:03 +00:00
/**
* Bind model associations on the fly .
2006-12-28 04:02:38 +00:00
*
* If $reset is false , association will not be reset
* to the originals defined in the model
2006-07-30 12:24:03 +00:00
*
2007-11-05 03:36:12 +00:00
* Example : Add a new hasOne binding to the Profile model not
* defined in the model source code :
* < code >
* $this -> User -> bindModel ( array ( 'hasOne' => array ( 'Profile' )) );
* </ code >
*
* @ param array $params Set of bindings ( indexed by binding type )
* @ param boolean $reset Set to false to make the binding permanent
* @ return boolean Success
* @ access public
2006-07-30 12:24:03 +00:00
*/
2007-02-01 18:45:38 +00:00
function bindModel ( $params , $reset = true ) {
2007-06-20 06:15:35 +00:00
foreach ( $params as $assoc => $model ) {
if ( $reset === true ) {
2007-02-01 18:45:38 +00:00
$this -> __backAssociation [ $assoc ] = $this -> { $assoc };
}
2006-07-30 12:24:03 +00:00
2007-06-20 06:15:35 +00:00
foreach ( $model as $key => $value ) {
2006-07-30 12:24:03 +00:00
$assocName = $key ;
2007-02-01 18:37:42 +00:00
if ( is_numeric ( $key )) {
$assocName = $value ;
$value = array ();
2006-07-30 12:24:03 +00:00
}
2007-02-01 18:37:42 +00:00
$modelName = $assocName ;
$this -> { $assoc }[ $assocName ] = $value ;
2006-07-30 12:24:03 +00:00
}
}
2007-02-01 18:37:42 +00:00
$this -> __createLinks ();
2006-07-30 12:24:03 +00:00
return true ;
}
/**
* Turn off associations on the fly .
*
2006-12-28 04:02:38 +00:00
* If $reset is false , association will not be reset
* to the originals defined in the model
*
* Example : Turn off the associated Model Support request ,
2006-08-03 06:49:51 +00:00
* to temporarily lighten the User model :
* < code >
* $this -> User -> unbindModel ( array ( 'hasMany' => array ( 'Supportrequest' )) );
* </ code >
*
2007-11-05 03:36:12 +00:00
* @ param array $params Set of bindings to unbind ( indexed by binding type )
* @ param boolean $reset Set to false to make the unbinding permanent
* @ return boolean Success
* @ access public
2006-07-30 12:24:03 +00:00
*/
2006-12-28 04:02:38 +00:00
function unbindModel ( $params , $reset = true ) {
2007-06-20 06:15:35 +00:00
foreach ( $params as $assoc => $models ) {
if ( $reset === true ) {
2006-12-28 04:02:38 +00:00
$this -> __backAssociation [ $assoc ] = $this -> { $assoc };
}
2006-07-30 12:24:03 +00:00
2007-06-20 06:15:35 +00:00
foreach ( $models as $model ) {
2006-07-30 12:24:03 +00:00
$this -> __backAssociation = array_merge ( $this -> __backAssociation , $this -> { $assoc });
2007-10-22 02:11:58 +00:00
unset ( $this -> __backAssociation [ $model ]);
2006-07-30 12:24:03 +00:00
unset ( $this -> { $assoc }[ $model ]);
}
}
return true ;
}
/**
2007-11-05 03:36:12 +00:00
* Create a set of associations
2006-07-30 12:24:03 +00:00
*
* @ access private
*/
function __createLinks () {
2007-06-20 06:15:35 +00:00
foreach ( $this -> __associations as $type ) {
2006-07-30 12:24:03 +00:00
if ( ! is_array ( $this -> { $type })) {
$this -> { $type } = explode ( ',' , $this -> { $type });
2007-06-20 06:15:35 +00:00
foreach ( $this -> { $type } as $i => $className ) {
2006-07-30 12:24:03 +00:00
$className = trim ( $className );
unset ( $this -> { $type }[ $i ]);
$this -> { $type }[ $className ] = array ();
}
}
2007-06-20 06:15:35 +00:00
foreach ( $this -> { $type } as $assoc => $value ) {
Closes #2119 Only define clone() in PHP4 when it hasn't been already defined.
Closes #2213, Support multiple plugin paths.
Closes #2234, filepaths to behavior classes should be cached in class.paths.php also
Closes #2345, ability to group components into subfolders
Closes #2645, Improvement to basic.php for class loading.
Fixes #3526, Cache::write, when using just the config name, it fails.
Fixes #3559, loading plugin model as assoc don't work.
Closes #3567 Controller Folders (Note this does not need routing to work, but controller names can not conflict with others in the same application so naming must still be unique)
Fixes #3579, email.php component: Parse error with php 4.
Adding new class and file importer.
Updated most of the core to use the importer.
Added ClassRegsitry::init() that will create and instance of an object and store it in the registry.
Deprecated most of the load functions in basics.php
Plugin model loading now forces using the dot notation, to use models within a plugin, all the model associations must be in the PluginName.Model syntax, if this is not used, the plugin will look for the models in the main app/models directory first, if not found then it will search the plugin directories recursively until it finds a model.
var $belongsTo = array('SomeModel'); will look for some_model.php in the app/models
var $belongsTo = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $belongsTo = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
The controllers of the plugin will still look for the default models inside the plugin if var $uses is not set:
var $uses = array('SomeModel'); will look for some_model.php in the app/models
var $uses = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $uses = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
All of the above will work between plugins and main app
These changes also allow placing model and controllers is sub directories
Removed old class.paths.php file generation
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6001 3807eeeb-6ff5-0310-8944-8be069107fe0
2007-11-16 09:35:19 +00:00
$plugin = null ;
2006-07-30 12:24:03 +00:00
if ( is_numeric ( $assoc )) {
unset ( $this -> { $type }[ $assoc ]);
$assoc = $value ;
$value = array ();
$this -> { $type }[ $assoc ] = $value ;
Closes #2119 Only define clone() in PHP4 when it hasn't been already defined.
Closes #2213, Support multiple plugin paths.
Closes #2234, filepaths to behavior classes should be cached in class.paths.php also
Closes #2345, ability to group components into subfolders
Closes #2645, Improvement to basic.php for class loading.
Fixes #3526, Cache::write, when using just the config name, it fails.
Fixes #3559, loading plugin model as assoc don't work.
Closes #3567 Controller Folders (Note this does not need routing to work, but controller names can not conflict with others in the same application so naming must still be unique)
Fixes #3579, email.php component: Parse error with php 4.
Adding new class and file importer.
Updated most of the core to use the importer.
Added ClassRegsitry::init() that will create and instance of an object and store it in the registry.
Deprecated most of the load functions in basics.php
Plugin model loading now forces using the dot notation, to use models within a plugin, all the model associations must be in the PluginName.Model syntax, if this is not used, the plugin will look for the models in the main app/models directory first, if not found then it will search the plugin directories recursively until it finds a model.
var $belongsTo = array('SomeModel'); will look for some_model.php in the app/models
var $belongsTo = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $belongsTo = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
The controllers of the plugin will still look for the default models inside the plugin if var $uses is not set:
var $uses = array('SomeModel'); will look for some_model.php in the app/models
var $uses = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $uses = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
All of the above will work between plugins and main app
These changes also allow placing model and controllers is sub directories
Removed old class.paths.php file generation
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6001 3807eeeb-6ff5-0310-8944-8be069107fe0
2007-11-16 09:35:19 +00:00
if ( strpos ( $assoc , '.' ) !== false ) {
$value = $this -> { $type }[ $assoc ];
unset ( $this -> { $type }[ $assoc ]);
list ( $plugin , $assoc ) = explode ( '.' , $assoc );
$this -> { $type }[ $assoc ] = $value ;
$plugin = $plugin . '.' ;
}
2006-07-30 12:24:03 +00:00
}
Closes #2119 Only define clone() in PHP4 when it hasn't been already defined.
Closes #2213, Support multiple plugin paths.
Closes #2234, filepaths to behavior classes should be cached in class.paths.php also
Closes #2345, ability to group components into subfolders
Closes #2645, Improvement to basic.php for class loading.
Fixes #3526, Cache::write, when using just the config name, it fails.
Fixes #3559, loading plugin model as assoc don't work.
Closes #3567 Controller Folders (Note this does not need routing to work, but controller names can not conflict with others in the same application so naming must still be unique)
Fixes #3579, email.php component: Parse error with php 4.
Adding new class and file importer.
Updated most of the core to use the importer.
Added ClassRegsitry::init() that will create and instance of an object and store it in the registry.
Deprecated most of the load functions in basics.php
Plugin model loading now forces using the dot notation, to use models within a plugin, all the model associations must be in the PluginName.Model syntax, if this is not used, the plugin will look for the models in the main app/models directory first, if not found then it will search the plugin directories recursively until it finds a model.
var $belongsTo = array('SomeModel'); will look for some_model.php in the app/models
var $belongsTo = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $belongsTo = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
The controllers of the plugin will still look for the default models inside the plugin if var $uses is not set:
var $uses = array('SomeModel'); will look for some_model.php in the app/models
var $uses = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $uses = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
All of the above will work between plugins and main app
These changes also allow placing model and controllers is sub directories
Removed old class.paths.php file generation
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6001 3807eeeb-6ff5-0310-8944-8be069107fe0
2007-11-16 09:35:19 +00:00
$className = $plugin . $assoc ;
2006-07-30 12:24:03 +00:00
if ( isset ( $value [ 'className' ]) && ! empty ( $value [ 'className' ])) {
$className = $value [ 'className' ];
Closes #2119 Only define clone() in PHP4 when it hasn't been already defined.
Closes #2213, Support multiple plugin paths.
Closes #2234, filepaths to behavior classes should be cached in class.paths.php also
Closes #2345, ability to group components into subfolders
Closes #2645, Improvement to basic.php for class loading.
Fixes #3526, Cache::write, when using just the config name, it fails.
Fixes #3559, loading plugin model as assoc don't work.
Closes #3567 Controller Folders (Note this does not need routing to work, but controller names can not conflict with others in the same application so naming must still be unique)
Fixes #3579, email.php component: Parse error with php 4.
Adding new class and file importer.
Updated most of the core to use the importer.
Added ClassRegsitry::init() that will create and instance of an object and store it in the registry.
Deprecated most of the load functions in basics.php
Plugin model loading now forces using the dot notation, to use models within a plugin, all the model associations must be in the PluginName.Model syntax, if this is not used, the plugin will look for the models in the main app/models directory first, if not found then it will search the plugin directories recursively until it finds a model.
var $belongsTo = array('SomeModel'); will look for some_model.php in the app/models
var $belongsTo = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $belongsTo = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
The controllers of the plugin will still look for the default models inside the plugin if var $uses is not set:
var $uses = array('SomeModel'); will look for some_model.php in the app/models
var $uses = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $uses = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
All of the above will work between plugins and main app
These changes also allow placing model and controllers is sub directories
Removed old class.paths.php file generation
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6001 3807eeeb-6ff5-0310-8944-8be069107fe0
2007-11-16 09:35:19 +00:00
if ( strpos ( $className , '.' ) !== false ) {
list ( $plugin , $className ) = explode ( '.' , $className );
$plugin = $plugin . '.' ;
$this -> { $type }[ $assoc ][ 'className' ] = $className ;
}
2006-07-30 12:24:03 +00:00
}
Closes #2119 Only define clone() in PHP4 when it hasn't been already defined.
Closes #2213, Support multiple plugin paths.
Closes #2234, filepaths to behavior classes should be cached in class.paths.php also
Closes #2345, ability to group components into subfolders
Closes #2645, Improvement to basic.php for class loading.
Fixes #3526, Cache::write, when using just the config name, it fails.
Fixes #3559, loading plugin model as assoc don't work.
Closes #3567 Controller Folders (Note this does not need routing to work, but controller names can not conflict with others in the same application so naming must still be unique)
Fixes #3579, email.php component: Parse error with php 4.
Adding new class and file importer.
Updated most of the core to use the importer.
Added ClassRegsitry::init() that will create and instance of an object and store it in the registry.
Deprecated most of the load functions in basics.php
Plugin model loading now forces using the dot notation, to use models within a plugin, all the model associations must be in the PluginName.Model syntax, if this is not used, the plugin will look for the models in the main app/models directory first, if not found then it will search the plugin directories recursively until it finds a model.
var $belongsTo = array('SomeModel'); will look for some_model.php in the app/models
var $belongsTo = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $belongsTo = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
The controllers of the plugin will still look for the default models inside the plugin if var $uses is not set:
var $uses = array('SomeModel'); will look for some_model.php in the app/models
var $uses = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $uses = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
All of the above will work between plugins and main app
These changes also allow placing model and controllers is sub directories
Removed old class.paths.php file generation
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6001 3807eeeb-6ff5-0310-8944-8be069107fe0
2007-11-16 09:35:19 +00:00
$this -> __constructLinkedModel ( $assoc , $plugin . $className );
2007-01-28 01:53:35 +00:00
}
2006-07-30 12:24:03 +00:00
$this -> __generateAssociation ( $type );
}
}
/**
* Private helper method to create associated models of given class .
2007-11-05 03:36:12 +00:00
*
* @ param string $assoc Association name
2006-07-30 12:24:03 +00:00
* @ param string $className Class name
2007-08-29 20:47:03 +00:00
* @ deprecated $this -> $className use $this -> $assoc instead . $assoc is the 'key' in the associations array ;
* examples : var $hasMany = array ( 'Assoc' => array ( 'className' => 'ModelName' ));
* usage : $this -> Assoc -> modelMethods ();
*
* var $hasMany = array ( 'ModelName' );
* usage : $this -> ModelName -> modelMethods ();
2006-07-30 12:24:03 +00:00
* @ access private
*/
2007-10-22 02:11:58 +00:00
function __constructLinkedModel ( $assoc , $className = null ) {
Closes #2119 Only define clone() in PHP4 when it hasn't been already defined.
Closes #2213, Support multiple plugin paths.
Closes #2234, filepaths to behavior classes should be cached in class.paths.php also
Closes #2345, ability to group components into subfolders
Closes #2645, Improvement to basic.php for class loading.
Fixes #3526, Cache::write, when using just the config name, it fails.
Fixes #3559, loading plugin model as assoc don't work.
Closes #3567 Controller Folders (Note this does not need routing to work, but controller names can not conflict with others in the same application so naming must still be unique)
Fixes #3579, email.php component: Parse error with php 4.
Adding new class and file importer.
Updated most of the core to use the importer.
Added ClassRegsitry::init() that will create and instance of an object and store it in the registry.
Deprecated most of the load functions in basics.php
Plugin model loading now forces using the dot notation, to use models within a plugin, all the model associations must be in the PluginName.Model syntax, if this is not used, the plugin will look for the models in the main app/models directory first, if not found then it will search the plugin directories recursively until it finds a model.
var $belongsTo = array('SomeModel'); will look for some_model.php in the app/models
var $belongsTo = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $belongsTo = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
The controllers of the plugin will still look for the default models inside the plugin if var $uses is not set:
var $uses = array('SomeModel'); will look for some_model.php in the app/models
var $uses = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $uses = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
All of the above will work between plugins and main app
These changes also allow placing model and controllers is sub directories
Removed old class.paths.php file generation
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6001 3807eeeb-6ff5-0310-8944-8be069107fe0
2007-11-16 09:35:19 +00:00
if ( empty ( $className )) {
2007-08-14 23:12:24 +00:00
$className = $assoc ;
}
Closes #2119 Only define clone() in PHP4 when it hasn't been already defined.
Closes #2213, Support multiple plugin paths.
Closes #2234, filepaths to behavior classes should be cached in class.paths.php also
Closes #2345, ability to group components into subfolders
Closes #2645, Improvement to basic.php for class loading.
Fixes #3526, Cache::write, when using just the config name, it fails.
Fixes #3559, loading plugin model as assoc don't work.
Closes #3567 Controller Folders (Note this does not need routing to work, but controller names can not conflict with others in the same application so naming must still be unique)
Fixes #3579, email.php component: Parse error with php 4.
Adding new class and file importer.
Updated most of the core to use the importer.
Added ClassRegsitry::init() that will create and instance of an object and store it in the registry.
Deprecated most of the load functions in basics.php
Plugin model loading now forces using the dot notation, to use models within a plugin, all the model associations must be in the PluginName.Model syntax, if this is not used, the plugin will look for the models in the main app/models directory first, if not found then it will search the plugin directories recursively until it finds a model.
var $belongsTo = array('SomeModel'); will look for some_model.php in the app/models
var $belongsTo = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $belongsTo = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
The controllers of the plugin will still look for the default models inside the plugin if var $uses is not set:
var $uses = array('SomeModel'); will look for some_model.php in the app/models
var $uses = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $uses = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
All of the above will work between plugins and main app
These changes also allow placing model and controllers is sub directories
Removed old class.paths.php file generation
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6001 3807eeeb-6ff5-0310-8944-8be069107fe0
2007-11-16 09:35:19 +00:00
$model = array ( 'class' => $className , 'alias' => $assoc );
2006-11-22 20:08:53 +00:00
Closes #2119 Only define clone() in PHP4 when it hasn't been already defined.
Closes #2213, Support multiple plugin paths.
Closes #2234, filepaths to behavior classes should be cached in class.paths.php also
Closes #2345, ability to group components into subfolders
Closes #2645, Improvement to basic.php for class loading.
Fixes #3526, Cache::write, when using just the config name, it fails.
Fixes #3559, loading plugin model as assoc don't work.
Closes #3567 Controller Folders (Note this does not need routing to work, but controller names can not conflict with others in the same application so naming must still be unique)
Fixes #3579, email.php component: Parse error with php 4.
Adding new class and file importer.
Updated most of the core to use the importer.
Added ClassRegsitry::init() that will create and instance of an object and store it in the registry.
Deprecated most of the load functions in basics.php
Plugin model loading now forces using the dot notation, to use models within a plugin, all the model associations must be in the PluginName.Model syntax, if this is not used, the plugin will look for the models in the main app/models directory first, if not found then it will search the plugin directories recursively until it finds a model.
var $belongsTo = array('SomeModel'); will look for some_model.php in the app/models
var $belongsTo = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $belongsTo = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
The controllers of the plugin will still look for the default models inside the plugin if var $uses is not set:
var $uses = array('SomeModel'); will look for some_model.php in the app/models
var $uses = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $uses = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
All of the above will work between plugins and main app
These changes also allow placing model and controllers is sub directories
Removed old class.paths.php file generation
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6001 3807eeeb-6ff5-0310-8944-8be069107fe0
2007-11-16 09:35:19 +00:00
if ( PHP5 ) {
$this -> { $assoc } = ClassRegistry :: init ( $model );
2006-07-30 12:24:03 +00:00
} else {
Closes #2119 Only define clone() in PHP4 when it hasn't been already defined.
Closes #2213, Support multiple plugin paths.
Closes #2234, filepaths to behavior classes should be cached in class.paths.php also
Closes #2345, ability to group components into subfolders
Closes #2645, Improvement to basic.php for class loading.
Fixes #3526, Cache::write, when using just the config name, it fails.
Fixes #3559, loading plugin model as assoc don't work.
Closes #3567 Controller Folders (Note this does not need routing to work, but controller names can not conflict with others in the same application so naming must still be unique)
Fixes #3579, email.php component: Parse error with php 4.
Adding new class and file importer.
Updated most of the core to use the importer.
Added ClassRegsitry::init() that will create and instance of an object and store it in the registry.
Deprecated most of the load functions in basics.php
Plugin model loading now forces using the dot notation, to use models within a plugin, all the model associations must be in the PluginName.Model syntax, if this is not used, the plugin will look for the models in the main app/models directory first, if not found then it will search the plugin directories recursively until it finds a model.
var $belongsTo = array('SomeModel'); will look for some_model.php in the app/models
var $belongsTo = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $belongsTo = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
The controllers of the plugin will still look for the default models inside the plugin if var $uses is not set:
var $uses = array('SomeModel'); will look for some_model.php in the app/models
var $uses = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $uses = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
All of the above will work between plugins and main app
These changes also allow placing model and controllers is sub directories
Removed old class.paths.php file generation
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6001 3807eeeb-6ff5-0310-8944-8be069107fe0
2007-11-16 09:35:19 +00:00
$this -> { $assoc } =& ClassRegistry :: init ( $model );
}
if ( $assoc ) {
$this -> tableToModel [ $this -> { $assoc } -> table ] = $assoc ;
2006-07-30 12:24:03 +00:00
}
}
/**
* Build array - based association from string .
*
2007-01-31 23:25:05 +00:00
* @ param string $type 'belongsTo' , 'hasOne' , 'hasMany' , 'hasAndBelongsToMany'
2006-07-30 12:24:03 +00:00
* @ access private
*/
function __generateAssociation ( $type ) {
2007-06-20 06:15:35 +00:00
foreach ( $this -> { $type } as $assocKey => $assocData ) {
2006-07-30 12:24:03 +00:00
$class = $assocKey ;
2007-06-20 06:15:35 +00:00
foreach ( $this -> __associationKeys [ $type ] as $key ) {
2006-07-30 12:24:03 +00:00
if ( ! isset ( $this -> { $type }[ $assocKey ][ $key ]) || $this -> { $type }[ $assocKey ][ $key ] == null ) {
$data = '' ;
switch ( $key ) {
case 'fields' :
$data = '' ;
break ;
case 'foreignKey' :
2007-01-31 23:25:05 +00:00
$data = ife ( $type == 'belongsTo' , Inflector :: underscore ( $assocKey ) . '_id' , Inflector :: singularize ( $this -> table ) . '_id' );
2006-07-30 12:24:03 +00:00
break ;
case 'associationForeignKey' :
$data = Inflector :: singularize ( $this -> { $class } -> table ) . '_id' ;
break ;
2007-08-29 10:14:14 +00:00
case 'with' :
$data = Inflector :: camelize ( Inflector :: singularize ( $this -> { $type }[ $assocKey ][ 'joinTable' ]));
break ;
2006-07-30 12:24:03 +00:00
case 'joinTable' :
$tables = array ( $this -> table , $this -> { $class } -> table );
sort ( $tables );
$data = $tables [ 0 ] . '_' . $tables [ 1 ];
break ;
case 'className' :
$data = $class ;
break ;
2007-08-29 10:14:14 +00:00
2006-07-30 12:24:03 +00:00
}
$this -> { $type }[ $assocKey ][ $key ] = $data ;
}
}
2007-08-14 23:12:24 +00:00
2007-08-29 10:14:14 +00:00
if ( isset ( $this -> { $type }[ $assocKey ][ 'with' ]) && ! empty ( $this -> { $type }[ $assocKey ][ 'with' ])) {
$joinClass = $this -> { $type }[ $assocKey ][ 'with' ];
Closes #2119 Only define clone() in PHP4 when it hasn't been already defined.
Closes #2213, Support multiple plugin paths.
Closes #2234, filepaths to behavior classes should be cached in class.paths.php also
Closes #2345, ability to group components into subfolders
Closes #2645, Improvement to basic.php for class loading.
Fixes #3526, Cache::write, when using just the config name, it fails.
Fixes #3559, loading plugin model as assoc don't work.
Closes #3567 Controller Folders (Note this does not need routing to work, but controller names can not conflict with others in the same application so naming must still be unique)
Fixes #3579, email.php component: Parse error with php 4.
Adding new class and file importer.
Updated most of the core to use the importer.
Added ClassRegsitry::init() that will create and instance of an object and store it in the registry.
Deprecated most of the load functions in basics.php
Plugin model loading now forces using the dot notation, to use models within a plugin, all the model associations must be in the PluginName.Model syntax, if this is not used, the plugin will look for the models in the main app/models directory first, if not found then it will search the plugin directories recursively until it finds a model.
var $belongsTo = array('SomeModel'); will look for some_model.php in the app/models
var $belongsTo = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $belongsTo = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
The controllers of the plugin will still look for the default models inside the plugin if var $uses is not set:
var $uses = array('SomeModel'); will look for some_model.php in the app/models
var $uses = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $uses = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
All of the above will work between plugins and main app
These changes also allow placing model and controllers is sub directories
Removed old class.paths.php file generation
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6001 3807eeeb-6ff5-0310-8944-8be069107fe0
2007-11-16 09:35:19 +00:00
$plugin = null ;
if ( strpos ( $joinClass , '.' ) !== false ) {
list ( $plugin , $joinClass ) = explode ( '.' , $joinClass );
$plugin = $plugin . '.' ;
$this -> { $type }[ $assocKey ][ 'with' ] = $joinClass ;
}
if ( ! App :: import ( 'Model' , $plugin . $joinClass )) {
2007-08-29 20:47:03 +00:00
$this -> { $joinClass } = new AppModel ( array (
'name' => $joinClass ,
'table' => $this -> { $type }[ $assocKey ][ 'joinTable' ],
'ds' => $this -> useDbConfig
));
2007-08-29 10:14:14 +00:00
$this -> { $joinClass } -> primaryKey = $this -> { $type }[ $assocKey ][ 'foreignKey' ];
} else {
Closes #2119 Only define clone() in PHP4 when it hasn't been already defined.
Closes #2213, Support multiple plugin paths.
Closes #2234, filepaths to behavior classes should be cached in class.paths.php also
Closes #2345, ability to group components into subfolders
Closes #2645, Improvement to basic.php for class loading.
Fixes #3526, Cache::write, when using just the config name, it fails.
Fixes #3559, loading plugin model as assoc don't work.
Closes #3567 Controller Folders (Note this does not need routing to work, but controller names can not conflict with others in the same application so naming must still be unique)
Fixes #3579, email.php component: Parse error with php 4.
Adding new class and file importer.
Updated most of the core to use the importer.
Added ClassRegsitry::init() that will create and instance of an object and store it in the registry.
Deprecated most of the load functions in basics.php
Plugin model loading now forces using the dot notation, to use models within a plugin, all the model associations must be in the PluginName.Model syntax, if this is not used, the plugin will look for the models in the main app/models directory first, if not found then it will search the plugin directories recursively until it finds a model.
var $belongsTo = array('SomeModel'); will look for some_model.php in the app/models
var $belongsTo = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $belongsTo = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
The controllers of the plugin will still look for the default models inside the plugin if var $uses is not set:
var $uses = array('SomeModel'); will look for some_model.php in the app/models
var $uses = array('MyPlugin.SomeModel'); will look for some_model.php in my_plugin/models
var $uses = array('MyPlugin.MyPlugin', 'SomeModel'); will used my_plugin/models/my_plugin.php and app/models/some_model.php
All of the above will work between plugins and main app
These changes also allow placing model and controllers is sub directories
Removed old class.paths.php file generation
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6001 3807eeeb-6ff5-0310-8944-8be069107fe0
2007-11-16 09:35:19 +00:00
$this -> __constructLinkedModel ( $plugin . $joinClass );
2007-09-03 04:48:58 +00:00
$this -> { $joinClass } -> primaryKey = $this -> { $type }[ $assocKey ][ 'foreignKey' ];
2007-08-29 10:14:14 +00:00
$this -> { $type }[ $assocKey ][ 'joinTable' ] = $this -> { $joinClass } -> table ;
2007-08-21 21:46:59 +00:00
}
2007-09-03 04:48:58 +00:00
2007-10-28 04:18:18 +00:00
if ( count ( $this -> { $joinClass } -> _schema ) > 2 ) {
if ( isset ( $this -> { $joinClass } -> _schema [ 'id' ])) {
2007-09-03 04:48:58 +00:00
$this -> { $joinClass } -> primaryKey = 'id' ;
}
}
2007-01-31 23:25:05 +00:00
}
2006-07-30 12:24:03 +00:00
}
}
/**
* Sets a custom table for your controller class . Used by your controller to select a database table .
*
* @ param string $tableName Name of the custom table
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function setSource ( $tableName ) {
2007-01-10 11:15:43 +00:00
$this -> setDataSource ( $this -> useDbConfig );
2006-08-25 00:43:48 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2007-04-08 23:30:31 +00:00
$db -> cacheSources = $this -> cacheSources ;
2007-08-29 00:16:13 +00:00
2006-07-30 12:24:03 +00:00
if ( $db -> isInterfaceSupported ( 'listSources' )) {
$sources = $db -> listSources ();
2007-01-10 11:15:43 +00:00
if ( is_array ( $sources ) && ! in_array ( low ( $this -> tablePrefix . $tableName ), array_map ( 'low' , $sources ))) {
2006-07-30 12:24:03 +00:00
return $this -> cakeError ( 'missingTable' , array ( array (
2007-10-29 00:17:37 +00:00
'className' => $this -> alias ,
'table' => $this -> tablePrefix . $tableName
)));
2007-08-29 00:16:13 +00:00
2006-07-30 12:24:03 +00:00
}
2007-10-06 05:31:46 +00:00
$this -> _schema = null ;
2006-07-30 12:24:03 +00:00
}
2007-08-29 00:16:13 +00:00
$this -> table = $this -> useTable = $tableName ;
2007-10-27 05:29:11 +00:00
$this -> tableToModel [ $this -> table ] = $this -> alias ;
2007-10-28 04:18:18 +00:00
$this -> schema ();
2006-07-30 12:24:03 +00:00
}
/**
* This function does two things : 1 ) it scans the array $one for the primary key ,
* and if that ' s found , it sets the current id to the value of $one [ id ] .
* For all other keys than 'id' the keys and values of $one are copied to the 'data' property of this object .
* 2 ) Returns an array with all of $one ' s keys and values .
* ( Alternative indata : two strings , which are mangled to
* a one - item , two - dimensional array using $one for a key and $two as its value . )
*
* @ param mixed $one Array or string of data
* @ param string $two Value string for the alternative indata method
2007-11-05 03:36:12 +00:00
* @ return array Data with all of $one ' s keys and values
* @ access public
2006-07-30 12:24:03 +00:00
*/
function set ( $one , $two = null ) {
2007-12-02 22:23:29 +00:00
if ( ! $one ) {
return ;
}
2006-10-09 22:00:22 +00:00
if ( is_object ( $one )) {
2007-06-30 06:52:39 +00:00
$one = Set :: reverse ( $one );
2006-10-09 22:00:22 +00:00
}
2006-07-30 12:24:03 +00:00
if ( is_array ( $one )) {
2006-11-08 03:28:24 +00:00
if ( Set :: countDim ( $one ) == 1 ) {
2007-10-27 01:32:17 +00:00
$data = array ( $this -> alias => $one );
2006-07-30 12:24:03 +00:00
} else {
$data = $one ;
}
} else {
2007-10-27 01:32:17 +00:00
$data = array ( $this -> alias => array ( $one => $two ));
2006-07-30 12:24:03 +00:00
}
2007-06-20 06:15:35 +00:00
foreach ( $data as $n => $v ) {
2006-07-30 12:24:03 +00:00
if ( is_array ( $v )) {
2007-10-17 21:19:30 +00:00
2007-06-20 06:15:35 +00:00
foreach ( $v as $x => $y ) {
2007-12-06 15:21:05 +00:00
if ( isset ( $this -> validationErrors [ $x ])) {
unset ( $this -> validationErrors [ $x ]);
}
2007-10-19 03:33:19 +00:00
2007-12-06 15:21:05 +00:00
if ( $n === $this -> alias ) {
if ( $x === $this -> primaryKey ) {
$this -> id = $y ;
2006-07-30 12:24:03 +00:00
}
}
2007-12-06 15:21:05 +00:00
if ( is_array ( $y ) || is_object ( $y )) {
$y = $this -> deconstruct ( $x , $y );
}
$this -> data [ $n ][ $x ] = $y ;
2006-07-30 12:24:03 +00:00
}
}
}
return $data ;
}
2007-11-08 00:05:12 +00:00
/**
* Deconstructs a complex data type ( array or object ) into a single field value
*
* @ param string $field The name of the field to be deconstructed
* @ param mixed $data An array or object to be deconstructed into a field
* @ return mixed The resulting data that should be assigned to a field
* @ access public
*/
function deconstruct ( $field , $data ) {
$copy = $data ;
$type = $this -> getColumnType ( $field );
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
if ( in_array ( $type , array ( 'datetime' , 'timestamp' , 'date' , 'time' ))) {
$useNewDate = ( isset ( $data [ 'year' ]) || isset ( $data [ 'month' ]) || isset ( $data [ 'day' ]) || isset ( $data [ 'hour' ]) || isset ( $data [ 'minute' ]));
$dateFields = array ( 'Y' => 'year' , 'm' => 'month' , 'd' => 'day' , 'H' => 'hour' , 'i' => 'min' , 's' => 'sec' );
$format = $db -> columns [ $type ][ 'format' ];
$date = array ();
2007-11-26 18:00:06 +00:00
if ( isset ( $data [ 'hour' ]) && isset ( $data [ 'meridian' ]) && $data [ 'hour' ] != 12 && 'pm' == $data [ 'meridian' ]) {
2007-11-08 00:05:12 +00:00
$data [ 'hour' ] = $data [ 'hour' ] + 12 ;
}
2007-11-26 18:00:06 +00:00
if ( isset ( $data [ 'hour' ]) && isset ( $data [ 'meridian' ]) && $data [ 'hour' ] == 12 && 'am' == $data [ 'meridian' ]) {
2007-11-08 00:05:12 +00:00
$data [ 'hour' ] = '00' ;
}
foreach ( $dateFields as $key => $val ) {
if ( in_array ( $val , array ( 'hour' , 'min' , 'sec' ))) {
if ( ! isset ( $data [ $val ]) || $data [ $val ] === '0' ) {
$data [ $val ] = '00' ;
}
}
$date [ $key ] = $data [ $val ];
}
$date = str_replace ( array_keys ( $date ), array_values ( $date ), $format );
if ( $useNewDate && ( ! empty ( $date ))) { // || isset($value['null'])
return $date ;
}
}
return $data ;
}
2006-07-30 12:24:03 +00:00
/**
* Returns an array of table metadata ( column names and types ) from the database .
2007-08-21 21:46:59 +00:00
* $field => keys ( type , null , default , key , length , extra )
2006-07-30 12:24:03 +00:00
*
2007-11-05 03:36:12 +00:00
* @ param boolean $clear Set to true to reload schema
2006-07-30 12:24:03 +00:00
* @ return array Array of table metadata
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
2007-08-21 21:46:59 +00:00
function schema ( $clear = false ) {
2007-10-28 04:18:18 +00:00
if ( ! is_array ( $this -> _schema ) || $clear ) {
2007-04-18 16:39:11 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
$db -> cacheSources = $this -> cacheSources ;
if ( $db -> isInterfaceSupported ( 'describe' ) && $this -> useTable !== false ) {
2007-10-28 04:18:18 +00:00
$this -> _schema = $db -> describe ( $this , $clear );
2007-04-18 16:39:11 +00:00
} elseif ( $this -> useTable === false ) {
2007-10-28 04:18:18 +00:00
$this -> _schema = array ();
2007-04-18 16:39:11 +00:00
}
2006-07-30 12:24:03 +00:00
}
2007-08-21 21:46:59 +00:00
return $this -> _schema ;
}
/**
* See Model :: schema
*
* @ deprecated
2007-11-05 03:36:12 +00:00
* @ see Model :: schema ()
2007-08-21 21:46:59 +00:00
*/
function loadInfo ( $clear = false ) {
2007-10-28 04:18:18 +00:00
$info = $this -> schema ( $clear );
if ( is_array ( $info )) {
2007-10-15 07:48:19 +00:00
$fields = array ();
2007-10-28 04:18:18 +00:00
foreach ( $info as $field => $value ) {
2007-10-15 07:48:19 +00:00
$fields [] = am ( array ( 'name' => $field ), $value );
}
unset ( $info );
2007-10-28 04:18:18 +00:00
return new Set ( $fields );
2007-08-21 21:46:59 +00:00
}
2006-07-30 12:24:03 +00:00
}
/**
* Returns an associative array of field names and column types .
*
2007-11-05 03:36:12 +00:00
* @ return array Field types indexed by field name
* @ access public
2006-07-30 12:24:03 +00:00
*/
function getColumnTypes () {
2007-10-28 04:18:18 +00:00
$columns = $this -> schema ();
if ( empty ( $columns )) {
trigger_error ( __ ( '(Model::getColumnTypes) Unable to build model field data. If you are using a model without a database table, try implementing schema()' , true ), E_USER_WARNING );
2007-05-05 17:36:30 +00:00
}
2007-10-28 04:18:18 +00:00
$cols = array ();
foreach ( $columns as $field => $values ) {
$cols [ $field ] = $values [ 'type' ];
}
return $cols ;
2006-07-30 12:24:03 +00:00
}
/**
* Returns the column type of a column in the model
*
* @ param string $column The name of the model column
* @ return string Column type
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function getColumnType ( $column ) {
2007-10-28 04:18:18 +00:00
$cols = $this -> schema ();
if ( empty ( $cols )) {
trigger_error ( __ ( '(Model::getColumnType) Unable to locate model field data. If you are using a model without a database table, try implementing schema()' , true ), E_USER_WARNING );
}
if ( isset ( $cols [ $column ][ 'type' ])) {
return $cols [ $column ][ 'type' ];
2006-07-30 12:24:03 +00:00
}
return null ;
}
/**
* Returns true if this Model has given field in its database table .
*
* @ param string $name Name of field to look for
2007-11-05 03:36:12 +00:00
* @ return bool Success
* @ access public
2006-07-30 12:24:03 +00:00
*/
function hasField ( $name ) {
2006-12-19 19:26:02 +00:00
if ( is_array ( $name )) {
foreach ( $name as $n ) {
if ( $this -> hasField ( $n )) {
return $n ;
}
}
return false ;
}
2007-10-28 04:18:18 +00:00
if ( empty ( $this -> _schema )) {
$this -> schema ();
2006-07-30 12:24:03 +00:00
}
2007-10-28 04:18:18 +00:00
if ( $this -> _schema != null ) {
return isset ( $this -> _schema [ $name ]);
2006-07-30 12:24:03 +00:00
}
2006-11-21 22:40:30 +00:00
return false ;
2006-07-30 12:24:03 +00:00
}
/**
2007-11-05 03:36:12 +00:00
* Initializes the model for writing a new record , loading the default values
* for those fields that are not defined in $data .
2006-07-30 12:24:03 +00:00
*
* @ param array $data Optional data to assign to the model after it is created
2006-10-27 22:35:40 +00:00
* @ return array The current data of the model
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
2007-01-16 12:53:39 +00:00
function create ( $data = array ()) {
2006-07-30 12:24:03 +00:00
$this -> id = false ;
$this -> data = array ();
2007-01-16 12:53:39 +00:00
$defaults = array ();
2007-10-28 04:18:18 +00:00
$fields = $this -> schema ();
foreach ( $fields as $field => $properties ) {
if ( $this -> primaryKey !== $field && isset ( $properties [ 'default' ])) {
$defaults [ $field ] = $properties [ 'default' ];
2006-07-30 12:24:03 +00:00
}
}
2007-01-22 08:22:10 +00:00
$this -> validationErrors = array ();
2007-06-10 17:41:35 +00:00
$this -> set ( Set :: filter ( $defaults ));
2007-02-15 18:45:47 +00:00
$this -> set ( $data );
2006-10-27 18:14:35 +00:00
return $this -> data ;
2006-07-30 12:24:03 +00:00
}
/**
2007-11-05 03:36:12 +00:00
* Returns a list of fields from the database , and sets the current model
* data ( Model :: $data ) with the record found .
2006-07-30 12:24:03 +00:00
*
* @ param mixed $fields String of single fieldname , or an array of fieldnames .
2007-11-05 03:36:12 +00:00
* @ param mixed $id The ID of the record to read
* @ return array Array of database fields , or false if not found
* @ access public
2006-07-30 12:24:03 +00:00
*/
function read ( $fields = null , $id = null ) {
$this -> validationErrors = array ();
if ( $id != null ) {
$this -> id = $id ;
}
$id = $this -> id ;
if ( is_array ( $this -> id )) {
$id = $this -> id [ 0 ];
}
if ( $this -> id !== null && $this -> id !== false ) {
2007-10-27 01:32:17 +00:00
$this -> data = $this -> find ( array ( $this -> alias . '.' . $this -> primaryKey => $id ), $fields );
2007-02-08 17:50:47 +00:00
return $this -> data ;
2006-07-30 12:24:03 +00:00
} else {
return false ;
}
}
/**
* Returns contents of a field in a query matching given conditions .
*
* @ param string $name Name of field to get
* @ param array $conditions SQL conditions ( defaults to NULL )
* @ param string $order SQL ORDER BY fragment
2007-11-05 03:36:12 +00:00
* @ return string field contents , or false if not found
* @ access public
2006-07-30 12:24:03 +00:00
*/
function field ( $name , $conditions = null , $order = null ) {
Fixes #2902, DB_ACL::allow allowing all when $actions is not an array.
Fixes #2988, AclComponent check() does not inherit permissions.
Fixes #3022, Inconsistent table alias quoting crashes Acl node lookup with PostgreSQL.
Fixes #3129, Console ACL Shell ACO View Broken
Fixes #3176, Problems with ACL support on Microsoft SQL Server.
Closes #3311 as invalid, DboSourceTest::testArrayConditionsParsing tests added
Fixes #3312, DB_ACL::check() fail returning right permission
Fixes #3344, Model->field adds incorrect condition under certain circumstances.
Fixes #3400, Cookie Component: When reading a non-existing key it throws a notice.
Fixes #3407, Since [5768] CookieComponent throws warning when used in beforeFilter().
Closes #3401, Added form test to ensure $Form->fields array is what the security component requires.
Updated AclComponentTest
Merged changes in app/ to cake/console/libs/templates/skel
Fixed generated link to Run More Test after running Group > All tests
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@5776 3807eeeb-6ff5-0310-8944-8be069107fe0
2007-10-17 12:51:17 +00:00
if ( $conditions === null && $this -> id !== false ) {
2007-10-27 01:32:17 +00:00
$conditions = array ( $this -> alias . '.' . $this -> primaryKey => $this -> id );
2006-07-30 12:24:03 +00:00
}
2007-06-20 06:15:35 +00:00
if ( $this -> recursive >= 1 ) {
2007-01-10 11:15:43 +00:00
$recursive = - 1 ;
} else {
$recursive = $this -> recursive ;
}
if ( $data = $this -> find ( $conditions , $name , $order , $recursive )) {
2006-07-30 12:24:03 +00:00
if ( strpos ( $name , '.' ) === false ) {
2007-10-27 01:32:17 +00:00
if ( isset ( $data [ $this -> alias ][ $name ])) {
return $data [ $this -> alias ][ $name ];
2006-07-30 12:24:03 +00:00
}
} else {
$name = explode ( '.' , $name );
if ( isset ( $data [ $name [ 0 ]][ $name [ 1 ]])) {
return $data [ $name [ 0 ]][ $name [ 1 ]];
}
}
2007-03-26 18:38:54 +00:00
if ( isset ( $data [ 0 ]) && count ( $data [ 0 ]) > 0 ) {
$name = key ( $data [ 0 ]);
return $data [ 0 ][ $name ];
}
2006-07-30 12:24:03 +00:00
} else {
return false ;
}
}
/**
* Saves a single field to the database .
*
* @ param string $name Name of the table field
* @ param mixed $value Value of the field
2007-10-22 16:54:36 +00:00
* @ param boolean $validate Whether or not this model should validate before saving ( defaults to false )
2007-10-22 16:09:35 +00:00
* @ return boolean True on success save
2007-11-05 03:36:12 +00:00
* @ access public
* @ see Model :: save ()
2006-07-30 12:24:03 +00:00
*/
function saveField ( $name , $value , $validate = false ) {
2007-10-27 01:32:17 +00:00
return $this -> save ( array ( $this -> alias => array ( $name => $value )), $validate , array ( $name ));
2006-07-30 12:24:03 +00:00
}
/**
2007-11-05 03:36:12 +00:00
* Saves model data to the database . By default , validation occurs before save .
2006-07-30 12:24:03 +00:00
*
* @ param array $data Data to save .
2007-10-22 16:54:36 +00:00
* @ param boolean $validate If set , validation will be done before the save
2006-07-30 12:24:03 +00:00
* @ param array $fieldList List of fields to allow to be written
2007-11-05 03:36:12 +00:00
* @ return mixed On success Model :: $data if its not empty or true , false on failure
* @ access public
2006-07-30 12:24:03 +00:00
*/
function save ( $data = null , $validate = true , $fieldList = array ()) {
2006-08-25 00:43:48 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2007-10-17 21:19:30 +00:00
$_whitelist = $this -> whitelist ;
2007-12-03 16:04:29 +00:00
$fields = array ();
2007-10-17 21:19:30 +00:00
if ( ! empty ( $fieldList )) {
$this -> whitelist = $fieldList ;
} elseif ( $fieldList === null ) {
$this -> whitelist = array ();
}
2006-10-09 22:00:22 +00:00
$this -> set ( $data );
2007-10-19 21:05:34 +00:00
if ( empty ( $this -> data )) {
return false ;
}
2007-10-17 21:19:30 +00:00
foreach ( array ( 'created' , 'updated' , 'modified' ) as $field ) {
2007-12-03 16:04:29 +00:00
if ( isset ( $this -> data [ $this -> alias ]) && array_key_exists ( $field , $this -> data [ $this -> alias ]) && $this -> data [ $this -> alias ][ $field ] === null ) {
2007-10-27 01:32:17 +00:00
unset ( $this -> data [ $this -> alias ][ $field ]);
2007-10-17 21:19:30 +00:00
}
}
$exists = $this -> exists ();
2007-12-06 15:21:05 +00:00
$dateFields = array ( 'modified' , 'updated' );
if ( ! $exists ) {
$dateFields [] = 'created' ;
2007-12-03 16:04:29 +00:00
}
2007-10-17 21:19:30 +00:00
2007-12-06 15:21:05 +00:00
if ( isset ( $this -> data [ $this -> alias ])) {
$fields = array_keys ( $this -> data [ $this -> alias ]);
2007-10-17 21:19:30 +00:00
}
2007-12-06 15:21:05 +00:00
foreach ( $dateFields as $updateCol ) {
2007-10-17 21:19:30 +00:00
if ( $this -> hasField ( $updateCol ) && ! in_array ( $updateCol , $fields )) {
$colType = am ( array ( 'formatter' => 'date' ), $db -> columns [ $this -> getColumnType ( $updateCol )]);
2007-12-06 15:21:05 +00:00
if ( ! array_key_exists ( 'formatter' , $colType ) || ! array_key_exists ( 'format' , $colType )) {
$time = strtotime ( 'now' );
} else {
$time = $colType [ 'formatter' ]( $colType [ 'format' ]);
}
$this -> set ( $updateCol , $time );
2007-10-17 21:19:30 +00:00
}
}
2006-07-30 12:24:03 +00:00
if ( $validate && ! $this -> validates ()) {
2007-10-17 21:19:30 +00:00
$this -> whitelist = $_whitelist ;
2006-07-30 12:24:03 +00:00
return false ;
}
2006-12-19 19:26:02 +00:00
if ( ! empty ( $this -> behaviors )) {
$behaviors = array_keys ( $this -> behaviors );
$ct = count ( $behaviors );
for ( $i = 0 ; $i < $ct ; $i ++ ) {
if ( $this -> behaviors [ $behaviors [ $i ]] -> beforeSave ( $this ) === false ) {
2007-10-17 21:19:30 +00:00
$this -> whitelist = $_whitelist ;
2006-12-19 19:26:02 +00:00
return false ;
}
}
}
2006-07-30 12:24:03 +00:00
if ( ! $this -> beforeSave ()) {
2007-10-17 21:19:30 +00:00
$this -> whitelist = $_whitelist ;
2006-07-30 12:24:03 +00:00
return false ;
}
$fields = $values = array ();
2007-12-03 16:04:29 +00:00
2007-06-20 06:15:35 +00:00
foreach ( $this -> data as $n => $v ) {
2007-11-30 23:31:41 +00:00
if ( isset ( $v [ $n ]) && in_array ( $n , array_keys ( $this -> hasAndBelongsToMany ))) {
2006-07-30 12:24:03 +00:00
$joined [] = $v ;
} else {
2007-10-27 01:32:17 +00:00
if ( $n === $this -> alias ) {
2006-09-11 00:35:06 +00:00
foreach ( array ( 'created' , 'updated' , 'modified' ) as $field ) {
2007-10-17 21:19:30 +00:00
if ( array_key_exists ( $field , $v ) && empty ( $v [ $field ])) {
2006-09-11 00:35:06 +00:00
unset ( $v [ $field ]);
}
}
2006-09-14 18:50:33 +00:00
2007-06-20 06:15:35 +00:00
foreach ( $v as $x => $y ) {
2007-12-06 15:21:05 +00:00
if ( $this -> hasField ( $x ) && ( empty ( $this -> whitelist ) || in_array ( $x , $this -> whitelist ))) {
2006-07-30 12:24:03 +00:00
$fields [] = $x ;
$values [] = $y ;
}
}
}
}
}
2007-06-28 02:47:16 +00:00
$count = count ( $fields );
2006-07-30 12:24:03 +00:00
2007-06-28 02:47:16 +00:00
if ( ! $exists && $count > 0 ) {
2006-07-30 12:24:03 +00:00
$this -> id = false ;
}
2007-06-28 02:47:16 +00:00
$success = true ;
2007-02-07 00:36:19 +00:00
$created = false ;
2006-07-30 12:24:03 +00:00
2007-06-28 02:47:16 +00:00
if ( $count > 0 ) {
2006-07-30 12:24:03 +00:00
if ( ! empty ( $this -> id )) {
2007-06-28 02:47:16 +00:00
if ( ! $db -> update ( $this , $fields , $values )) {
$success = false ;
2006-07-30 12:24:03 +00:00
}
} else {
2007-10-28 04:18:18 +00:00
foreach ( $this -> _schema as $field => $properties ) {
if ( $this -> primaryKey === $field ) {
if ( empty ( $this -> data [ $this -> alias ][ $this -> primaryKey ]) && $this -> _schema [ $field ][ 'type' ] === 'string' && $this -> _schema [ $field ][ 'length' ] === 36 ) {
2007-08-20 01:58:44 +00:00
$fields [] = $this -> primaryKey ;
$values [] = String :: uuid ();
}
break ;
}
}
2007-06-28 02:47:16 +00:00
if ( ! $db -> create ( $this , $fields , $values )) {
$success = $created = false ;
} else {
$created = true ;
2006-09-11 00:35:06 +00:00
if ( ! empty ( $this -> belongsTo )) {
foreach ( $this -> belongsTo as $parent => $assoc ) {
if ( isset ( $assoc [ 'counterCache' ]) && ! empty ( $assoc [ 'counterCache' ])) {
$parentObj =& $this -> { $assoc [ 'className' ]};
}
}
}
2007-02-07 00:36:19 +00:00
}
}
2007-06-28 02:47:16 +00:00
}
2006-07-30 12:24:03 +00:00
2007-06-28 02:47:16 +00:00
if ( ! empty ( $joined ) && $success === true ) {
$this -> __saveMulti ( $joined , $this -> id );
}
if ( $success && $count > 0 ) {
2007-11-28 16:44:59 +00:00
if ( ! empty ( $this -> data )) {
$success = $this -> data ;
}
2007-06-28 02:47:16 +00:00
if ( ! empty ( $this -> behaviors )) {
$behaviors = array_keys ( $this -> behaviors );
$ct = count ( $behaviors );
for ( $i = 0 ; $i < $ct ; $i ++ ) {
$this -> behaviors [ $behaviors [ $i ]] -> afterSave ( $this , $created );
2006-07-30 12:24:03 +00:00
}
}
2007-06-28 02:47:16 +00:00
$this -> afterSave ( $created );
2007-10-28 04:18:18 +00:00
if ( ! empty ( $this -> data )) {
2007-11-28 16:44:59 +00:00
$success = Set :: pushDiff ( $success , $this -> data );
2007-10-24 18:53:25 +00:00
}
2007-06-28 02:47:16 +00:00
$this -> data = false ;
2007-10-08 17:43:14 +00:00
$this -> __exists = null ;
2007-06-28 02:47:16 +00:00
$this -> _clearCache ();
$this -> validationErrors = array ();
2006-07-30 12:24:03 +00:00
}
2007-10-17 21:19:30 +00:00
$this -> whitelist = $_whitelist ;
2007-02-07 00:36:19 +00:00
return $success ;
2006-07-30 12:24:03 +00:00
}
/**
* Saves model hasAndBelongsToMany data to the database .
*
2007-11-05 03:36:12 +00:00
* @ param array $joined Data to save
* @ param mixed $id ID of record in this model
2006-07-30 12:24:03 +00:00
* @ access private
*/
function __saveMulti ( $joined , $id ) {
2006-08-25 00:43:48 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2007-06-20 06:15:35 +00:00
foreach ( $joined as $x => $y ) {
foreach ( $y as $assoc => $value ) {
2007-03-31 20:27:47 +00:00
if ( isset ( $this -> hasAndBelongsToMany [ $assoc ])) {
$joinTable [ $assoc ] = $this -> hasAndBelongsToMany [ $assoc ][ 'joinTable' ];
2007-06-28 17:31:26 +00:00
$mainKey [ $assoc ] = $db -> name ( $this -> hasAndBelongsToMany [ $assoc ][ 'foreignKey' ]);
$keys [] = $db -> name ( $this -> hasAndBelongsToMany [ $assoc ][ 'foreignKey' ]);
$keys [] = $db -> name ( $this -> hasAndBelongsToMany [ $assoc ][ 'associationForeignKey' ]);
2007-03-31 20:27:47 +00:00
$fields [ $assoc ] = join ( ',' , $keys );
unset ( $keys );
2007-04-08 23:30:31 +00:00
2007-06-20 06:15:35 +00:00
foreach ( $value as $update ) {
2007-03-31 20:27:47 +00:00
if ( ! empty ( $update )) {
$values [] = $db -> value ( $id , $this -> getColumnType ( $this -> primaryKey ));
$values [] = $db -> value ( $update );
$values = join ( ',' , $values );
$newValues [] = " ( { $values } ) " ;
unset ( $values );
}
}
2007-04-08 23:30:31 +00:00
2007-03-31 20:27:47 +00:00
if ( ! empty ( $newValues )) {
$newValue [ $assoc ] = $newValues ;
unset ( $newValues );
} else {
$newValue [ $assoc ] = array ();
2006-07-30 12:24:03 +00:00
}
}
}
}
2007-04-08 23:30:31 +00:00
2007-06-28 17:31:26 +00:00
if ( isset ( $joinTable ) && is_array ( $newValue )) {
foreach ( $newValue as $loopAssoc => $val ) {
$table = $db -> name ( $db -> fullTableName ( $joinTable [ $loopAssoc ]));
$db -> query ( " DELETE FROM { $table } WHERE { $mainKey [ $loopAssoc ] } = ' { $id } ' " );
2007-04-08 23:30:31 +00:00
2007-06-28 17:31:26 +00:00
if ( ! empty ( $newValue [ $loopAssoc ])) {
2007-07-25 04:38:28 +00:00
$db -> insertMulti ( $table , $fields [ $loopAssoc ], $newValue [ $loopAssoc ]);
2006-07-30 12:24:03 +00:00
}
}
}
}
2006-10-09 22:00:22 +00:00
/**
* Allows model records to be updated based on a set of conditions
*
2007-11-05 03:36:12 +00:00
* @ param array $fields Set of fields and values , indexed by fields
* @ param mixed $conditions Conditions to match , true for all records
2007-10-22 16:09:35 +00:00
* @ return boolean True on success , false on failure
2007-11-05 03:36:12 +00:00
* @ access public
2006-10-09 22:00:22 +00:00
*/
2007-02-08 18:36:26 +00:00
function updateAll ( $fields , $conditions = true ) {
2006-10-20 17:24:37 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
return $db -> update ( $this , $fields , null , $conditions );
2006-10-09 22:00:22 +00:00
}
2006-07-30 12:24:03 +00:00
/**
* Synonym for del () .
*
2007-11-05 03:36:12 +00:00
* @ param mixed $id ID of record to delete
* @ param boolean $cascade Set to true to delete records that depend on this record
2007-10-22 16:09:35 +00:00
* @ return boolean True on success
2007-11-05 03:36:12 +00:00
* @ access public
* @ see Model :: del ()
2006-07-30 12:24:03 +00:00
*/
function remove ( $id = null , $cascade = true ) {
return $this -> del ( $id , $cascade );
}
/**
* Removes record for given id . If no id is given , the current id is used . Returns true on success .
*
2007-11-05 03:36:12 +00:00
* @ param mixed $id ID of record to delete
* @ param boolean $cascade Set to true to delete records that depend on this record
2007-10-22 16:09:35 +00:00
* @ return boolean True on success
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function del ( $id = null , $cascade = true ) {
2006-12-13 04:04:15 +00:00
if ( ! empty ( $id )) {
2006-07-30 12:24:03 +00:00
$this -> id = $id ;
}
2007-04-30 02:46:51 +00:00
$id = $this -> id ;
2006-07-30 12:24:03 +00:00
2007-11-25 05:14:07 +00:00
if ( $this -> exists () && $this -> beforeDelete ( $cascade )) {
2006-08-25 00:43:48 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2006-07-30 12:24:03 +00:00
2006-12-19 19:26:02 +00:00
if ( ! empty ( $this -> behaviors )) {
$behaviors = array_keys ( $this -> behaviors );
$ct = count ( $behaviors );
for ( $i = 0 ; $i < $ct ; $i ++ ) {
2007-11-25 05:14:07 +00:00
if ( $this -> behaviors [ $behaviors [ $i ]] -> beforeDelete ( $this , $cascade ) === false ) {
2006-12-19 19:26:02 +00:00
return false ;
}
}
}
2007-04-30 02:46:51 +00:00
$this -> _deleteDependent ( $id , $cascade );
$this -> _deleteLinks ( $id );
2007-05-01 00:19:42 +00:00
$this -> id = $id ;
2006-12-19 19:26:02 +00:00
if ( $db -> delete ( $this )) {
if ( ! empty ( $this -> behaviors )) {
for ( $i = 0 ; $i < $ct ; $i ++ ) {
2007-02-10 20:28:22 +00:00
$this -> behaviors [ $behaviors [ $i ]] -> afterDelete ( $this );
2006-12-19 19:26:02 +00:00
}
}
2006-07-30 12:24:03 +00:00
$this -> afterDelete ();
$this -> _clearCache ();
$this -> id = false ;
2007-10-01 16:49:37 +00:00
$this -> __exists = null ;
2006-07-30 12:24:03 +00:00
return true ;
}
}
return false ;
}
/**
2007-11-05 03:36:12 +00:00
* Synonym for del () .
2006-07-30 12:24:03 +00:00
*
2007-11-05 03:36:12 +00:00
* @ param mixed $id ID of record to delete
* @ param boolean $cascade Set to true to delete records that depend on this record
2007-10-22 16:09:35 +00:00
* @ return boolean True on success
2007-11-05 03:36:12 +00:00
* @ access public
* @ see Model :: del ()
2006-07-30 12:24:03 +00:00
*/
function delete ( $id = null , $cascade = true ) {
return $this -> del ( $id , $cascade );
}
/**
2007-01-31 23:25:05 +00:00
* Cascades model deletes to hasMany and hasOne relationships .
2006-07-30 12:24:03 +00:00
*
2007-11-05 03:36:12 +00:00
* @ param string $id ID of record that was deleted
* @ param boolean $cascade Set to true to delete records that depend on this record
2006-07-30 12:24:03 +00:00
* @ access protected
*/
2007-01-31 23:25:05 +00:00
function _deleteDependent ( $id , $cascade ) {
2007-03-26 17:16:43 +00:00
if ( ! empty ( $this -> __backAssociation )) {
2006-11-23 11:31:59 +00:00
$savedAssociatons = $this -> __backAssociation ;
2007-03-26 17:16:43 +00:00
$this -> __backAssociation = array ();
2006-11-23 11:31:59 +00:00
}
2007-06-20 06:15:35 +00:00
foreach ( am ( $this -> hasMany , $this -> hasOne ) as $assoc => $data ) {
2006-07-30 12:24:03 +00:00
if ( $data [ 'dependent' ] === true && $cascade === true ) {
2007-01-31 23:25:05 +00:00
$model =& $this -> { $assoc };
2006-07-30 12:24:03 +00:00
$field = $model -> escapeField ( $data [ 'foreignKey' ]);
2007-01-31 23:25:05 +00:00
$model -> recursive = - 1 ;
$records = $model -> findAll ( array ( $field => $id ), $model -> primaryKey );
2006-07-30 12:24:03 +00:00
2007-06-20 06:15:35 +00:00
if ( ! empty ( $records )) {
foreach ( $records as $record ) {
2007-10-27 01:32:17 +00:00
$model -> delete ( $record [ $model -> alias ][ $model -> primaryKey ]);
2006-11-23 11:05:47 +00:00
}
2006-07-30 12:24:03 +00:00
}
}
}
2006-11-23 11:31:59 +00:00
if ( isset ( $savedAssociatons )) {
$this -> __backAssociation = $savedAssociatons ;
}
2006-07-30 12:24:03 +00:00
}
/**
2007-01-31 23:25:05 +00:00
* Cascades model deletes to HABTM join keys .
2006-07-30 12:24:03 +00:00
*
2007-11-05 03:36:12 +00:00
* @ param string $id ID of record that was deleted
2006-07-30 12:24:03 +00:00
* @ access protected
*/
2007-01-31 23:25:05 +00:00
function _deleteLinks ( $id ) {
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2007-06-20 06:15:35 +00:00
foreach ( $this -> hasAndBelongsToMany as $assoc => $data ) {
2007-01-31 23:25:05 +00:00
if ( isset ( $data [ 'with' ])) {
$model =& $this -> { $data [ 'with' ]};
$records = $model -> findAll ( array ( $data [ 'foreignKey' ] => $id ), $model -> primaryKey , null , null , null , - 1 );
2006-07-30 12:24:03 +00:00
2007-01-31 23:25:05 +00:00
if ( ! empty ( $records )) {
2007-06-20 06:15:35 +00:00
foreach ( $records as $record ) {
2007-10-27 01:32:17 +00:00
$model -> delete ( $record [ $model -> alias ][ $model -> primaryKey ]);
2006-11-23 11:05:47 +00:00
}
2006-07-30 12:24:03 +00:00
}
2007-01-31 23:25:05 +00:00
} else {
$table = $db -> name ( $db -> fullTableName ( $data [ 'joinTable' ]));
$conditions = $db -> name ( $data [ 'foreignKey' ]) . ' = ' . $db -> value ( $id );
$db -> query ( " DELETE FROM { $table } WHERE { $conditions } " );
2006-07-30 12:24:03 +00:00
}
}
}
2006-11-21 22:40:30 +00:00
/**
* Allows model records to be deleted based on a set of conditions
*
2007-11-05 03:36:12 +00:00
* @ param mixed $conditions Conditions to match
* @ param boolean $cascade Set to true to delete records that depend on this record
* @ param boolean $callbacks Run callbacks ( not being used )
2007-10-22 16:09:35 +00:00
* @ return boolean True on success , false on failure
2007-11-05 03:36:12 +00:00
* @ access public
2006-11-21 22:40:30 +00:00
*/
2007-10-23 13:41:25 +00:00
function deleteAll ( $conditions , $cascade = true , $callbacks = true ) {
2007-02-08 17:50:47 +00:00
if ( empty ( $conditions )) {
return false ;
}
$records = $this -> findAll ( $conditions , array ( $this -> escapeField ()), null , null , null , 0 );
if ( empty ( $records )) {
return false ;
}
2007-10-27 01:32:17 +00:00
$ids = Set :: extract ( $records , " { n}. { $this -> alias } . { $this -> primaryKey } " );
2007-02-08 17:50:47 +00:00
foreach ( $ids as $id ) {
$this -> _deleteLinks ( $id );
2007-12-03 00:43:11 +00:00
if ( $cascade ) {
$this -> _deleteDependent ( $id , $cascade );
}
2007-02-08 17:50:47 +00:00
}
2006-11-21 22:40:30 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2007-06-27 19:13:44 +00:00
return $db -> delete ( $this , array ( $this -> primaryKey => $ids ));
2006-11-21 22:40:30 +00:00
}
2006-07-30 12:24:03 +00:00
/**
* Returns true if a record with set id exists .
*
2007-10-22 16:54:36 +00:00
* @ param boolean $reset if true will force database query
2007-10-22 16:09:35 +00:00
* @ return boolean True if such a record exists
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
2007-10-01 16:49:37 +00:00
function exists ( $reset = false ) {
2006-10-27 18:14:35 +00:00
if ( $this -> getID () === false ) {
return false ;
2006-07-30 12:24:03 +00:00
}
2007-10-01 16:49:37 +00:00
if ( $this -> __exists !== null && $reset !== true ) {
return $this -> __exists ;
}
2007-10-27 01:32:17 +00:00
return $this -> __exists = ( $this -> findCount ( array ( $this -> alias . '.' . $this -> primaryKey => $this -> getID ()), - 1 ) > 0 );
2006-07-30 12:24:03 +00:00
}
/**
* Returns true if a record that meets given conditions exists
*
* @ param array $conditions SQL conditions array
2007-10-22 16:09:35 +00:00
* @ return boolean True if such a record exists
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function hasAny ( $conditions = null ) {
2007-10-21 18:34:23 +00:00
return ( $this -> find ( 'count' , array ( 'conditions' => $conditions , 'recursive' => - 1 )) != false );
2006-07-30 12:24:03 +00:00
}
/**
* Return a single row as a resultset array .
* By using the $recursive parameter , the call can access further " levels of association " than
* the ones this model is directly associated to .
*
2007-11-05 03:36:12 +00:00
* Eg : find ( array ( 'name' => 'mariano.iglesias' ), array ( 'name' , 'email' ), 'field3 DESC' , 2 );
*
* Also used to perform new - notation finds , where the first argument is type of find operation to perform
* ( all / first / count ), second parameter options for finding ( indexed array , including : 'conditions' , 'limit' ,
* 'recursive' , 'page' , 'fields' , 'offset' , 'order' )
*
* Eg : find ( 'all' , array (
* 'conditions' => array ( 'name' => 'mariano.iglesias' ),
* 'fields' => array ( 'name' , 'email' ),
* 'order' => 'field3 DESC' ,
* 'recursive' => 2 ));
*
* @ param array $conditions SQL conditions array , or type of find operation ( all / first / count )
* @ param mixed $fields Either a single string of a field name , or an array of field names , or options for matching
2006-07-30 12:24:03 +00:00
* @ param string $order SQL ORDER BY conditions ( e . g . " price DESC " or " name ASC " )
2007-10-22 16:11:12 +00:00
* @ param integer $recursive The number of levels deep to fetch associated records
2006-07-30 12:24:03 +00:00
* @ return array Array of records
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function find ( $conditions = null , $fields = null , $order = null , $recursive = null ) {
2007-10-21 18:34:23 +00:00
if ( ! is_string ( $conditions ) || ( is_string ( $conditions ) && ! array_key_exists ( $conditions , $this -> __findMethods ))) {
$type = 'first' ;
$query = am ( compact ( 'conditions' , 'fields' , 'order' , 'recursive' ), array ( 'limit' => 1 ));
} else {
$type = $conditions ;
$query = $fields ;
2006-07-30 12:24:03 +00:00
}
2006-08-25 00:43:48 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2006-07-30 12:24:03 +00:00
$this -> id = $this -> getID ();
2007-10-21 18:34:23 +00:00
$query = am (
array (
'conditions' => null , 'fields' => null , 'joins' => array (),
'limit' => null , 'offset' => null , 'order' => null , 'page' => null
),
$query
);
2007-12-02 21:39:43 +00:00
if ( $type == 'count' ) {
if ( empty ( $query [ 'fields' ])) {
$query [ 'fields' ] = 'COUNT(*) AS ' . $db -> name ( 'count' );
}
$query [ 'order' ] = false ;
2007-10-21 18:34:23 +00:00
}
if ( ! is_numeric ( $query [ 'page' ]) || intval ( $query [ 'page' ]) < 1 ) {
$query [ 'page' ] = 1 ;
2006-11-08 03:28:24 +00:00
}
2007-10-21 18:34:23 +00:00
if ( $query [ 'page' ] > 1 && $query [ 'limit' ] != null ) {
$query [ 'offset' ] = ( $query [ 'page' ] - 1 ) * $query [ 'limit' ];
2006-07-30 12:24:03 +00:00
}
2007-10-21 18:34:23 +00:00
if ( $query [ 'order' ] == null && $query [ 'order' ] !== false ) {
2006-07-30 12:24:03 +00:00
if ( $this -> order == null ) {
2007-10-21 18:34:23 +00:00
$query [ 'order' ] = array ();
2006-07-30 12:24:03 +00:00
} else {
2007-10-21 18:34:23 +00:00
$query [ 'order' ] = array ( $this -> order );
2006-07-30 12:24:03 +00:00
}
} else {
2007-10-21 18:34:23 +00:00
$query [ 'order' ] = array ( $query [ 'order' ]);
2006-07-30 12:24:03 +00:00
}
if ( ! empty ( $this -> behaviors )) {
2006-12-19 19:26:02 +00:00
$behaviors = array_keys ( $this -> behaviors );
$ct = count ( $behaviors );
2007-10-21 18:34:23 +00:00
2006-12-19 19:26:02 +00:00
for ( $i = 0 ; $i < $ct ; $i ++ ) {
2007-10-21 18:34:23 +00:00
$return = $this -> behaviors [ $behaviors [ $i ]] -> beforeFind ( $this , $query );
if ( is_array ( $return )) {
$query = $return ;
} elseif ( $return === false ) {
2006-12-19 19:26:02 +00:00
return null ;
}
2006-07-30 12:24:03 +00:00
}
}
2007-10-21 18:34:23 +00:00
$return = $this -> beforeFind ( $query );
if ( is_array ( $return )) {
$query = $return ;
} elseif ( $return === false ) {
2006-07-30 12:24:03 +00:00
return null ;
}
2007-10-21 18:34:23 +00:00
$results = $db -> read ( $this , $query );
2007-10-22 02:11:58 +00:00
$this -> __resetAssociations ();
2007-10-21 18:34:23 +00:00
switch ( $type ) {
case 'all' :
return $this -> __filterResults ( $results , true );
break ;
case 'first' :
$results = $this -> __filterResults ( $results , true );
if ( empty ( $results [ 0 ])) {
return false ;
}
return $results [ 0 ];
break ;
case 'count' :
if ( isset ( $results [ 0 ][ 0 ][ 'count' ])) {
return intval ( $results [ 0 ][ 0 ][ 'count' ]);
2007-10-27 01:32:17 +00:00
} elseif ( isset ( $results [ 0 ][ $this -> alias ][ 'count' ])) {
return intval ( $results [ 0 ][ $this -> alias ][ 'count' ]);
2007-10-21 18:34:23 +00:00
}
return false ;
break ;
}
}
/**
* Returns a resultset array with specified fields from database matching given conditions .
* By using the $recursive parameter , the call can access further " levels of association " than
* the ones this model is directly associated to .
*
* @ param mixed $conditions SQL conditions as a string or as an array ( 'field' => 'value' , ... )
* @ param mixed $fields Either a single string of a field name , or an array of field names
* @ param string $order SQL ORDER BY conditions ( e . g . " price DESC " or " name ASC " )
2007-10-22 16:11:12 +00:00
* @ param integer $limit SQL LIMIT clause , for calculating items per page .
* @ param integer $page Page number , for accessing paged data
* @ param integer $recursive The number of levels deep to fetch associated records
2007-10-21 18:34:23 +00:00
* @ return array Array of records
2007-11-05 03:36:12 +00:00
* @ access public
* @ see Model :: find ()
2007-10-21 18:34:23 +00:00
*/
function findAll ( $conditions = null , $fields = null , $order = null , $limit = null , $page = 1 , $recursive = null ) {
return $this -> find ( 'all' , compact ( 'conditions' , 'fields' , 'order' , 'limit' , 'page' , 'recursive' ));
}
/**
* Passes query results through model and behavior afterFilter () methods
*
2007-11-05 03:36:12 +00:00
* @ param array Results to filter
* @ param boolean $primary If this is the primary model results ( results from model where the find operation was performed )
* @ return array Set of filtered results
2007-10-21 18:34:23 +00:00
* @ access private
*/
function __filterResults ( $results , $primary = true ) {
2006-07-30 12:24:03 +00:00
if ( ! empty ( $this -> behaviors )) {
$b = array_keys ( $this -> behaviors );
$c = count ( $b );
2007-10-21 18:34:23 +00:00
2006-07-30 12:24:03 +00:00
for ( $i = 0 ; $i < $c ; $i ++ ) {
2007-10-21 18:34:23 +00:00
$return = $this -> behaviors [ $b [ $i ]] -> afterFind ( $this , $results , $primary );
if ( is_array ( $return )) {
$results = $return ;
2006-12-19 19:26:02 +00:00
}
2006-07-30 12:24:03 +00:00
}
}
2007-10-21 18:34:23 +00:00
return $this -> afterFind ( $results , $primary );
2006-07-30 12:24:03 +00:00
}
/**
* Method is called only when bindTo < ModelName > () is used .
* This resets the association arrays for the model back
* to the original as set in the model .
*
2007-11-05 03:36:12 +00:00
* @ return boolean Success
2006-07-30 12:24:03 +00:00
* @ access private
*/
function __resetAssociations () {
2007-10-22 02:11:58 +00:00
if ( ! empty ( $this -> __backAssociation )) {
foreach ( $this -> __associations as $type ) {
if ( isset ( $this -> __backAssociation [ $type ])) {
$this -> { $type } = $this -> __backAssociation [ $type ];
}
2006-07-30 12:24:03 +00:00
}
2007-10-22 02:11:58 +00:00
$this -> __backAssociation = array ();
2006-07-30 12:24:03 +00:00
}
2007-10-22 02:11:58 +00:00
foreach ( $this -> __associations as $type ) {
foreach ( $this -> { $type } as $key => $name ) {
if ( ! empty ( $this -> { $key } -> __backAssociation )) {
$this -> { $key } -> __resetAssociations ();
}
}
}
2007-03-26 17:16:43 +00:00
$this -> __backAssociation = array ();
2006-07-30 12:24:03 +00:00
return true ;
}
/**
* Runs a direct query against the bound DataSource , and returns the result .
*
* @ param string $data Query data
2007-11-05 03:36:12 +00:00
* @ return array Result of the query
* @ access public
2006-07-30 12:24:03 +00:00
*/
function execute ( $data ) {
2006-08-25 00:43:48 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2006-07-30 12:24:03 +00:00
$data = $db -> fetchAll ( $data , $this -> cacheQueries );
2007-06-20 06:15:35 +00:00
foreach ( $data as $key => $value ) {
foreach ( $this -> tableToModel as $key1 => $value1 ) {
2006-07-30 12:24:03 +00:00
if ( isset ( $data [ $key ][ $key1 ])) {
$newData [ $key ][ $value1 ] = $data [ $key ][ $key1 ];
}
}
}
if ( ! empty ( $newData )) {
return $newData ;
}
return $data ;
}
/**
* Returns number of rows matching given SQL condition .
*
* @ param array $conditions SQL conditions array for findAll
2007-11-05 03:36:12 +00:00
* @ param integer $recursive The number of levels deep to fetch associated records
2007-10-22 16:54:36 +00:00
* @ return integer Number of matching rows
2007-11-05 03:36:12 +00:00
* @ access public
* @ see Model :: find ()
2006-07-30 12:24:03 +00:00
*/
function findCount ( $conditions = null , $recursive = 0 ) {
2007-10-21 18:34:23 +00:00
return $this -> find ( 'count' , compact ( 'conditions' , 'recursive' ));
2006-07-30 12:24:03 +00:00
}
2007-01-22 08:09:17 +00:00
/**
* False if any fields passed match any ( by default , all if $or = false ) of their matching values .
*
* @ param array $fields Field / value pairs to search ( if no values specified , they are pulled from $this -> data )
2007-10-22 16:54:36 +00:00
* @ param boolean $or If false , all fields specified must match in order for a false return value
2007-10-22 16:09:35 +00:00
* @ return boolean False if any records matching any fields are found
2007-11-05 03:36:12 +00:00
* @ access public
2007-01-22 08:09:17 +00:00
*/
function isUnique ( $fields , $or = true ) {
if ( ! is_array ( $fields )) {
$fields = func_get_args ();
if ( is_bool ( $fields [ count ( $fields ) - 1 ])) {
$or = $fields [ count ( $fields ) - 1 ];
unset ( $fields [ count ( $fields ) - 1 ]);
}
}
foreach ( $fields as $field => $value ) {
if ( is_numeric ( $field )) {
unset ( $fields [ $field ]);
$field = $value ;
2007-10-27 01:32:17 +00:00
if ( isset ( $this -> data [ $this -> alias ][ $field ])) {
$value = $this -> data [ $this -> alias ][ $field ];
2007-01-22 08:09:17 +00:00
} else {
$value = null ;
}
}
2007-01-24 10:47:12 +00:00
2007-01-22 08:09:17 +00:00
if ( strpos ( $field , '.' ) === false ) {
unset ( $fields [ $field ]);
2007-10-27 01:32:17 +00:00
$fields [ $this -> alias . '.' . $field ] = $value ;
2007-01-22 08:09:17 +00:00
}
}
if ( $or ) {
$fields = array ( 'or' => $fields );
}
return ( $this -> findCount ( $fields ) == 0 );
}
2006-07-30 12:24:03 +00:00
/**
* Special findAll variation for tables joined to themselves .
* The table needs the fields id and parent_id to work .
*
* @ param array $conditions Conditions for the findAll () call
* @ param array $fields Fields for the findAll () call
* @ param string $sort SQL ORDER BY statement
2007-11-05 03:36:12 +00:00
* @ return array Threaded results
* @ access public
2006-07-30 12:24:03 +00:00
* @ todo Perhaps create a Component with this logic
*/
function findAllThreaded ( $conditions = null , $fields = null , $sort = null ) {
return $this -> __doThread ( Model :: findAll ( $conditions , $fields , $sort ), null );
}
/**
* Private , recursive helper method for findAllThreaded .
*
2007-11-05 03:36:12 +00:00
* @ param array $data Results of find operation
2006-07-30 12:24:03 +00:00
* @ param string $root NULL or id for root node of operation
2007-11-05 03:36:12 +00:00
* @ return array Threaded results
2006-07-30 12:24:03 +00:00
* @ access private
2007-11-05 03:36:12 +00:00
* @ see Model :: findAllThreaded ()
2006-07-30 12:24:03 +00:00
*/
function __doThread ( $data , $root ) {
$out = array ();
$sizeOf = sizeof ( $data );
2007-06-20 06:15:35 +00:00
for ( $ii = 0 ; $ii < $sizeOf ; $ii ++ ) {
2007-10-27 01:32:17 +00:00
if (( $data [ $ii ][ $this -> alias ][ 'parent_id' ] == $root ) || (( $root === null ) && ( $data [ $ii ][ $this -> alias ][ 'parent_id' ] == '0' ))) {
2006-07-30 12:24:03 +00:00
$tmp = $data [ $ii ];
2007-10-27 01:32:17 +00:00
if ( isset ( $data [ $ii ][ $this -> alias ][ $this -> primaryKey ])) {
$tmp [ 'children' ] = $this -> __doThread ( $data , $data [ $ii ][ $this -> alias ][ $this -> primaryKey ]);
2006-07-30 12:24:03 +00:00
} else {
$tmp [ 'children' ] = null ;
}
$out [] = $tmp ;
}
}
return $out ;
}
/**
* Returns an array with keys " prev " and " next " that holds the id ' s of neighbouring data ,
* which is useful when creating paged lists .
*
* @ param string $conditions SQL conditions for matching rows
* @ param string $field Field name ( parameter for findAll )
2007-11-05 03:36:12 +00:00
* @ param integer $value Value from where to find neighbours
2006-07-30 12:24:03 +00:00
* @ return array Array with keys " prev " and " next " that holds the id ' s
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function findNeighbours ( $conditions = null , $field , $value ) {
if ( ! is_null ( $conditions )) {
2007-10-23 13:41:25 +00:00
$conditions = array ( $conditions );
2006-07-30 12:24:03 +00:00
}
2007-10-23 13:41:25 +00:00
if ( is_array ( $field )) {
$fields = $field ;
$field = $fields [ 0 ];
} else {
$fields = $field ;
}
2007-10-21 18:34:23 +00:00
$prev = $next = null ;
2006-07-30 12:24:03 +00:00
2007-10-23 13:41:25 +00:00
@ list ( $prev ) = $this -> findAll ( array_filter ( am ( $conditions , array ( $field => '< ' . $value ))), $fields , $field . ' DESC' , 1 , null , 0 );
@ list ( $next ) = $this -> findAll ( array_filter ( am ( $conditions , array ( $field => '> ' . $value ))), $fields , $field . ' ASC' , 1 , null , 0 );
2006-07-30 12:24:03 +00:00
2007-10-21 18:34:23 +00:00
return compact ( 'prev' , 'next' );
2006-07-30 12:24:03 +00:00
}
/**
* Returns a resultset for given SQL statement . Generic SQL queries should be made with this method .
*
* @ param string $sql SQL statement
* @ return array Resultset
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function query () {
$params = func_get_args ();
2006-08-25 00:43:48 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2006-07-30 12:24:03 +00:00
return call_user_func_array ( array ( & $db , 'query' ), $params );
}
/**
* Returns true if all fields pass validation , otherwise false .
*
2007-11-05 03:36:12 +00:00
* @ param array $data Parameter usage is deprecated , set Model :: $data instead
2007-10-22 16:09:35 +00:00
* @ return boolean True if there are no errors
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function validates ( $data = array ()) {
2007-01-06 04:58:24 +00:00
if ( ! empty ( $data )) {
2007-11-26 19:48:46 +00:00
trigger_error ( __ ( '(Model::validates) Parameter usage is deprecated, use Model::set() to update your fields first' , true ), E_USER_WARNING );
2007-01-06 04:58:24 +00:00
}
2006-07-30 12:24:03 +00:00
$errors = $this -> invalidFields ( $data );
2006-10-10 22:29:13 +00:00
if ( is_array ( $errors )) {
return count ( $errors ) === 0 ;
}
return $errors ;
2006-07-30 12:24:03 +00:00
}
/**
2007-11-05 03:36:12 +00:00
* Returns an array of fields that do not meet validation .
2006-07-30 12:24:03 +00:00
*
2007-11-05 03:36:12 +00:00
* @ param array $data Parameter usage is deprecated , set Model :: $data instead
2007-09-20 15:16:25 +00:00
* @ return array Array of invalid fields
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function invalidFields ( $data = array ()) {
2007-09-20 15:16:25 +00:00
if ( ! empty ( $this -> behaviors )) {
$behaviors = array_keys ( $this -> behaviors );
$ct = count ( $behaviors );
for ( $i = 0 ; $i < $ct ; $i ++ ) {
if ( $this -> behaviors [ $behaviors [ $i ]] -> beforeValidate ( $this ) === false ) {
return $this -> validationErrors ;
}
}
}
2007-03-17 02:59:48 +00:00
if ( ! $this -> beforeValidate ()) {
return $this -> validationErrors ;
}
2006-07-30 12:24:03 +00:00
if ( empty ( $data )) {
$data = $this -> data ;
2007-01-06 04:58:24 +00:00
} else {
2007-04-18 16:39:11 +00:00
trigger_error ( __ ( '(Model::invalidFields) Parameter usage is deprecated, set the $data property instead' , true ), E_USER_WARNING );
2006-07-30 12:24:03 +00:00
}
2006-12-25 06:53:19 +00:00
if ( ! isset ( $this -> validate ) || empty ( $this -> validate )) {
2007-02-02 18:05:48 +00:00
return $this -> validationErrors ;
2006-07-30 12:24:03 +00:00
}
2007-10-27 01:32:17 +00:00
if ( isset ( $data [ $this -> alias ])) {
$data = $data [ $this -> alias ];
2006-07-30 12:24:03 +00:00
}
2006-12-25 06:53:19 +00:00
$Validation = new Validation ();
2007-10-01 16:49:37 +00:00
$exists = $this -> exists ();
2006-12-25 06:53:19 +00:00
2007-06-20 06:15:35 +00:00
foreach ( $this -> validate as $fieldName => $ruleSet ) {
2007-04-30 06:24:33 +00:00
if ( ! is_array ( $ruleSet ) || ( is_array ( $ruleSet ) && isset ( $ruleSet [ 'rule' ]))) {
$ruleSet = array ( $ruleSet );
2007-01-06 04:58:24 +00:00
}
2006-12-25 06:53:19 +00:00
2007-04-30 12:10:57 +00:00
foreach ( $ruleSet as $index => $validator ) {
2007-04-30 06:24:33 +00:00
if ( ! is_array ( $validator )) {
$validator = array ( 'rule' => $validator );
}
2006-12-25 06:53:19 +00:00
2007-05-02 07:48:22 +00:00
$default = array (
2007-05-01 03:52:28 +00:00
'allowEmpty' => null ,
'required' => null ,
2007-04-30 06:24:33 +00:00
'rule' => 'blank' ,
'last' => false ,
'on' => null
2007-05-02 07:48:22 +00:00
);
$validator = am ( $default , $validator );
2007-04-30 06:24:33 +00:00
2007-04-30 12:10:57 +00:00
if ( isset ( $validator [ 'message' ])) {
$message = $validator [ 'message' ];
} else {
2007-10-01 16:49:37 +00:00
$message = __ ( 'This field cannot be left blank' , true );
2007-04-30 12:10:57 +00:00
}
2007-08-29 20:47:03 +00:00
if ( empty ( $validator [ 'on' ]) || ( $validator [ 'on' ] == 'create' && ! $exists ) || ( $validator [ 'on' ] == 'update' && $exists )) {
2007-05-04 07:13:15 +00:00
if (( ! isset ( $data [ $fieldName ]) && $validator [ 'required' ] === true ) || ( isset ( $data [ $fieldName ]) && ( empty ( $data [ $fieldName ]) && ! is_numeric ( $data [ $fieldName ])) && $validator [ 'allowEmpty' ] === false )) {
2007-04-30 12:10:57 +00:00
$this -> invalidate ( $fieldName , $message );
2007-09-20 22:45:00 +00:00
} elseif ( array_key_exists ( $fieldName , $data )) {
2007-06-20 06:15:35 +00:00
if ( empty ( $data [ $fieldName ]) && $data [ $fieldName ] != '0' && $validator [ 'allowEmpty' ] === true ) {
2007-05-01 03:52:28 +00:00
break ;
}
2007-04-30 06:24:33 +00:00
if ( is_array ( $validator [ 'rule' ])) {
$rule = $validator [ 'rule' ][ 0 ];
unset ( $validator [ 'rule' ][ 0 ]);
$ruleParams = am ( array ( $data [ $fieldName ]), array_values ( $validator [ 'rule' ]));
} else {
$rule = $validator [ 'rule' ];
$ruleParams = array ( $data [ $fieldName ]);
}
$valid = true ;
2007-05-05 17:36:30 +00:00
$msg = null ;
2007-09-16 18:18:23 +00:00
if ( method_exists ( $this , $rule ) || isset ( $this -> __behaviorMethods [ $rule ]) || isset ( $this -> __behaviorMethods [ low ( $rule )])) {
2007-05-02 07:48:22 +00:00
$ruleParams [] = array_diff_key ( $validator , $default );
2007-04-30 06:24:33 +00:00
$valid = call_user_func_array ( array ( & $this , $rule ), $ruleParams );
} elseif ( method_exists ( $Validation , $rule )) {
$valid = call_user_func_array ( array ( & $Validation , $rule ), $ruleParams );
} elseif ( ! is_array ( $validator [ 'rule' ])) {
$valid = preg_match ( $rule , $data [ $fieldName ]);
}
if ( ! $valid ) {
2007-04-30 12:10:57 +00:00
if ( ! isset ( $validator [ 'message' ])) {
2007-05-14 10:37:23 +00:00
if ( is_string ( $index )) {
$validator [ 'message' ] = $index ;
} else {
$validator [ 'message' ] = ife ( is_numeric ( $index ) && count ( $ruleSet ) > 1 , ( $index + 1 ), $message );
}
2007-04-30 12:10:57 +00:00
}
2007-04-30 06:24:33 +00:00
$this -> invalidate ( $fieldName , $validator [ 'message' ]);
}
2006-12-25 06:53:19 +00:00
}
}
2006-07-30 12:24:03 +00:00
}
}
return $this -> validationErrors ;
}
/**
2007-11-05 03:36:12 +00:00
* Sets a field as invalid , optionally setting the name of validation
* rule ( in case of multiple validation for field ) that was broken
2006-07-30 12:24:03 +00:00
*
* @ param string $field The name of the field to invalidate
2007-11-05 03:36:12 +00:00
* @ param string $value Name of validation rule that was not met
* @ access public
2006-07-30 12:24:03 +00:00
*/
2007-04-30 06:24:33 +00:00
function invalidate ( $field , $value = null ) {
2006-07-30 12:24:03 +00:00
if ( ! is_array ( $this -> validationErrors )) {
$this -> validationErrors = array ();
}
2007-04-30 06:24:33 +00:00
if ( empty ( $value )) {
$value = true ;
}
2007-10-21 03:44:26 +00:00
$this -> validationErrors [ $field ] = $value ;
2006-07-30 12:24:03 +00:00
}
/**
* Returns true if given field name is a foreign key in this Model .
*
* @ param string $field Returns true if the input string ends in " _id "
2007-11-05 03:36:12 +00:00
* @ return boolean True if the field is a foreign key listed in the belongsTo array .
* @ access public
2006-07-30 12:24:03 +00:00
*/
function isForeignKey ( $field ) {
$foreignKeys = array ();
2007-11-05 03:36:12 +00:00
if ( ! empty ( $this -> belongsTo )) {
2007-06-20 06:15:35 +00:00
foreach ( $this -> belongsTo as $assoc => $data ) {
2006-07-30 12:24:03 +00:00
$foreignKeys [] = $data [ 'foreignKey' ];
}
}
2007-11-05 03:36:12 +00:00
return in_array ( $field , $foreignKeys );
2006-07-30 12:24:03 +00:00
}
/**
* Gets the display field for this model
*
* @ return string The name of the display field for this Model ( i . e . 'name' , 'title' ) .
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function getDisplayField () {
return $this -> displayField ;
}
/**
* Returns a resultset array with specified fields from database matching given conditions .
* Method can be used to generate option lists for SELECT elements .
*
* @ param mixed $conditions SQL conditions as a string or as an array ( 'field' => 'value' , ... )
* @ param string $order SQL ORDER BY conditions ( e . g . " price DESC " or " name ASC " )
2007-10-22 16:11:12 +00:00
* @ param integer $limit SQL LIMIT clause , for calculating items per page
2006-07-30 12:24:03 +00:00
* @ param string $keyPath A string path to the key , i . e . " { n}.Post.id "
* @ param string $valuePath A string path to the value , i . e . " { n}.Post.title "
2006-07-30 23:31:04 +00:00
* @ param string $groupPath A string path to a value to group the elements by , i . e . " { n}.Post.category_id "
2006-07-30 12:24:03 +00:00
* @ return array An associative array of records , where the id is the key , and the display field is the value
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
2006-07-30 23:31:04 +00:00
function generateList ( $conditions = null , $order = null , $limit = null , $keyPath = null , $valuePath = null , $groupPath = null ) {
if ( $keyPath == null && $valuePath == null && $groupPath == null && $this -> hasField ( $this -> displayField )) {
2006-07-30 12:24:03 +00:00
$fields = array ( $this -> primaryKey , $this -> displayField );
} else {
$fields = null ;
}
2006-11-22 19:36:59 +00:00
$recursive = $this -> recursive ;
2007-06-20 06:15:35 +00:00
if ( $groupPath == null && $recursive >= 1 ) {
2006-10-18 01:07:09 +00:00
$this -> recursive = - 1 ;
2007-06-20 07:51:52 +00:00
} elseif ( $groupPath && $recursive >= 1 ) {
2006-11-03 19:49:32 +00:00
$this -> recursive = 0 ;
2006-10-18 01:07:09 +00:00
}
$result = $this -> findAll ( $conditions , $fields , $order , $limit );
2006-11-22 19:36:59 +00:00
$this -> recursive = $recursive ;
2006-12-26 16:17:37 +00:00
2007-06-20 06:15:35 +00:00
if ( ! $result ) {
2006-12-04 06:59:56 +00:00
return false ;
}
2006-07-30 12:24:03 +00:00
if ( $keyPath == null ) {
2007-10-27 01:32:17 +00:00
$keyPath = '{n}.' . $this -> alias . '.' . $this -> primaryKey ;
2006-07-30 12:24:03 +00:00
}
if ( $valuePath == null ) {
2007-10-27 01:32:17 +00:00
$valuePath = '{n}.' . $this -> alias . '.' . $this -> displayField ;
2006-07-30 12:24:03 +00:00
}
2007-07-01 03:43:05 +00:00
return Set :: combine ( $result , $keyPath , $valuePath , $groupPath );
2006-07-30 12:24:03 +00:00
}
/**
* Escapes the field name and prepends the model name . Escaping will be done according to the current database driver ' s rules .
*
2007-11-05 03:36:12 +00:00
* @ param string $field Field to escape ( e . g : id )
* @ param string $alias Alias for the model ( e . g : Post )
2006-07-30 12:24:03 +00:00
* @ return string The name of the escaped field for this Model ( i . e . id becomes `Post` . `id` ) .
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
2007-02-08 17:50:47 +00:00
function escapeField ( $field = null , $alias = null ) {
if ( empty ( $alias )) {
2007-10-27 01:32:17 +00:00
$alias = $this -> alias ;
2006-07-30 12:24:03 +00:00
}
2007-02-08 17:50:47 +00:00
if ( empty ( $field )) {
$field = $this -> primaryKey ;
}
2006-08-25 00:43:48 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2006-07-30 12:24:03 +00:00
return $db -> name ( $alias ) . '.' . $db -> name ( $field );
}
/**
* Returns the current record ' s ID
*
2007-11-05 03:36:12 +00:00
* @ param integer $list Index on which the composed ID is located
* @ return mixed The ID of the current record , false if no ID
* @ access public
2006-07-30 12:24:03 +00:00
*/
function getID ( $list = 0 ) {
2006-12-12 22:06:22 +00:00
if ( empty ( $this -> id ) || ( is_array ( $this -> id ) && isset ( $this -> id [ 0 ]) && empty ( $this -> id [ 0 ]))) {
2006-10-27 18:14:35 +00:00
return false ;
}
2006-07-30 12:24:03 +00:00
if ( ! is_array ( $this -> id )) {
return $this -> id ;
}
2007-11-05 03:36:12 +00:00
if ( empty ( $this -> id )) {
2006-07-30 12:24:03 +00:00
return false ;
}
2006-12-12 22:06:22 +00:00
if ( isset ( $this -> id [ $list ]) && ! empty ( $this -> id [ $list ])) {
2006-07-30 12:24:03 +00:00
return $this -> id [ $list ];
2006-12-12 22:06:22 +00:00
} elseif ( isset ( $this -> id [ $list ])) {
return false ;
2006-07-30 12:24:03 +00:00
}
2007-06-20 06:15:35 +00:00
foreach ( $this -> id as $id ) {
2006-07-30 12:24:03 +00:00
return $id ;
}
return false ;
}
2007-11-17 22:46:55 +00:00
2007-11-18 06:14:27 +00:00
function normalizeFindParams ( $type , $data , $altType = null , $r = array (), $_this = null ) {
2007-11-17 22:46:55 +00:00
if ( $_this == null ) {
$_this = $this ;
$root = true ;
}
foreach (( array ) $data as $name => $children ) {
if ( is_numeric ( $name )) {
$name = $children ;
$children = array ();
}
if ( strpos ( $name , '.' ) !== false ) {
$chain = explode ( '.' , $name );
$name = array_shift ( $chain );
$children = array ( join ( '.' , $chain ) => $children );
}
if ( ! empty ( $children )) {
if ( $_this -> name == $name ) {
2007-11-18 06:14:27 +00:00
$r = am ( $r , $this -> normalizeFindParams ( $type , $children , $altType , $r , $_this ));
2007-11-17 22:46:55 +00:00
} else {
2007-11-18 06:14:27 +00:00
if ( ! $_this -> getAssociated ( $name )) {
$r [ $altType ][ $name ] = $children ;
} else {
$r [ $name ] = $this -> normalizeFindParams ( $type , $children , $altType , @ $r [ $name ], $_this -> { $name });;
}
2007-11-17 22:46:55 +00:00
}
} else {
if ( $_this -> getAssociated ( $name )) {
$r [ $name ] = array ( $type => null );
} else {
2007-11-18 06:14:27 +00:00
if ( $altType != null ) {
$r [ $type ][] = $name ;
} else {
$r [ $type ] = $name ;
}
2007-11-17 22:46:55 +00:00
}
}
}
if ( isset ( $root )) {
return array ( $this -> name => $r );
}
2007-11-18 07:18:25 +00:00
2007-11-17 22:46:55 +00:00
return $r ;
}
2006-07-30 12:24:03 +00:00
/**
* Returns the ID of the last record this Model inserted
*
2007-11-05 03:36:12 +00:00
* @ return mixed Last inserted ID
* @ access public
2006-07-30 12:24:03 +00:00
*/
function getLastInsertID () {
return $this -> getInsertID ();
}
/**
* Returns the ID of the last record this Model inserted
*
2007-11-05 03:36:12 +00:00
* @ return mixed Last inserted ID
* @ access public
2006-07-30 12:24:03 +00:00
*/
function getInsertID () {
return $this -> __insertID ;
}
2006-10-20 17:24:37 +00:00
/**
* Sets the ID of the last record this Model inserted
*
2007-11-05 03:36:12 +00:00
* @ param mixed Last inserted ID
* @ access public
2006-10-20 17:24:37 +00:00
*/
function setInsertID ( $id ) {
$this -> __insertID = $id ;
}
2006-07-30 12:24:03 +00:00
/**
* Returns the number of rows returned from the last query
*
2007-11-05 03:36:12 +00:00
* @ return int Number of rows
* @ access public
2006-07-30 12:24:03 +00:00
*/
function getNumRows () {
2006-08-25 00:43:48 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2006-07-30 12:24:03 +00:00
return $db -> lastNumRows ();
}
/**
* Returns the number of rows affected by the last query
*
2007-11-05 03:36:12 +00:00
* @ return int Number of rows
* @ access public
2006-07-30 12:24:03 +00:00
*/
function getAffectedRows () {
2006-08-25 00:43:48 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2006-07-30 12:24:03 +00:00
return $db -> lastAffected ();
}
/**
* Sets the DataSource to which this model is bound
*
* @ param string $dataSource The name of the DataSource , as defined in Connections . php
2007-10-22 16:09:35 +00:00
* @ return boolean True on success
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function setDataSource ( $dataSource = null ) {
2007-01-10 11:15:43 +00:00
if ( $dataSource != null ) {
$this -> useDbConfig = $dataSource ;
2006-07-30 12:24:03 +00:00
}
2007-01-10 11:15:43 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
2006-07-30 12:24:03 +00:00
2007-08-28 21:44:47 +00:00
if ( ! empty ( $db -> config [ 'prefix' ]) && $this -> tablePrefix === null ) {
2006-07-30 12:24:03 +00:00
$this -> tablePrefix = $db -> config [ 'prefix' ];
}
if ( empty ( $db ) || $db == null || ! is_object ( $db )) {
2007-10-27 01:32:17 +00:00
return $this -> cakeError ( 'missingConnection' , array ( array ( 'className' => $this -> alias )));
2006-07-30 12:24:03 +00:00
}
}
/**
2006-08-25 00:43:48 +00:00
* Gets the DataSource to which this model is bound .
* Not safe for use with some versions of PHP4 , because this class is overloaded .
2006-07-30 12:24:03 +00:00
*
2007-11-05 03:36:12 +00:00
* @ return object A DataSource object
* @ access public
2006-07-30 12:24:03 +00:00
*/
function & getDataSource () {
2006-08-25 00:43:48 +00:00
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
return $db ;
2006-07-30 12:24:03 +00:00
}
/**
* Gets all the models with which this model is associated
*
2007-11-05 03:36:12 +00:00
* @ param string $type Only result associations of this type
* @ return array Associations
* @ access public
2006-07-30 12:24:03 +00:00
*/
function getAssociated ( $type = null ) {
if ( $type == null ) {
$associated = array ();
foreach ( $this -> __associations as $assoc ) {
if ( ! empty ( $this -> { $assoc })) {
$models = array_keys ( $this -> { $assoc });
foreach ( $models as $m ) {
$associated [ $m ] = $assoc ;
}
}
}
return $associated ;
} elseif ( in_array ( $type , $this -> __associations )) {
if ( empty ( $this -> { $type })) {
return array ();
}
return array_keys ( $this -> { $type });
} else {
$assoc = am ( $this -> hasOne , $this -> hasMany , $this -> belongsTo , $this -> hasAndBelongsToMany );
if ( array_key_exists ( $type , $assoc )) {
2007-01-16 12:53:39 +00:00
foreach ( $this -> __associations as $a ) {
if ( isset ( $this -> { $a }[ $type ])) {
$assoc [ $type ][ 'association' ] = $a ;
break ;
}
}
2006-07-30 12:24:03 +00:00
return $assoc [ $type ];
}
return null ;
}
}
/**
* Before find callback
*
* @ param array $queryData Data used to execute this query , i . e . conditions , order , etc .
2007-10-22 16:09:35 +00:00
* @ return boolean True if the operation should continue , false if it should abort
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
2006-12-23 20:36:00 +00:00
function beforeFind ( $queryData ) {
2006-07-30 12:24:03 +00:00
return true ;
}
/**
* After find callback . Can be used to modify any results returned by find and findAll .
*
* @ param mixed $results The results of the find operation
2007-10-22 16:54:36 +00:00
* @ param boolean $primary Whether this model is being queried directly ( vs . being queried as an association )
2006-07-30 12:24:03 +00:00
* @ return mixed Result of the find operation
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
2006-08-18 08:00:54 +00:00
function afterFind ( $results , $primary = false ) {
2006-07-30 12:24:03 +00:00
return $results ;
}
/**
* Before save callback
*
2007-10-22 16:09:35 +00:00
* @ return boolean True if the operation should continue , false if it should abort
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function beforeSave () {
return true ;
}
/**
* After save callback
*
2007-10-22 16:54:36 +00:00
* @ param boolean $created True if this save created a new record
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
2007-02-07 00:36:19 +00:00
function afterSave ( $created ) {
2006-07-30 12:24:03 +00:00
}
/**
* Before delete callback
*
2007-11-25 05:14:07 +00:00
* @ param boolean $cascade If true records that depend on this record will also be deleted
2007-10-22 16:09:35 +00:00
* @ return boolean True if the operation should continue , false if it should abort
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
2007-11-25 05:14:07 +00:00
function beforeDelete ( $cascade = true ) {
2006-07-30 12:24:03 +00:00
return true ;
}
/**
* After delete callback
*
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function afterDelete () {
}
/**
* Before validate callback
*
2007-11-05 03:36:12 +00:00
* @ return boolean True if validate operation should continue , false to abort
* @ access public
2006-07-30 12:24:03 +00:00
*/
function beforeValidate () {
return true ;
}
/**
* DataSource error callback
*
2007-11-05 03:36:12 +00:00
* @ access public
2006-07-30 12:24:03 +00:00
*/
function onError () {
}
/**
2007-11-05 03:36:12 +00:00
* Private method . Clears cache for this model
2006-01-17 17:52:23 +00:00
*
2007-10-01 16:49:37 +00:00
* @ param string $type If null this deletes cached views if Cache . check is true
2006-07-30 12:24:03 +00:00
* Will be used to allow deleting query cache also
2007-10-22 16:09:35 +00:00
* @ return boolean true on delete
2007-11-05 03:36:12 +00:00
* @ access protected
* @ todo
2006-01-17 17:52:23 +00:00
*/
2006-07-30 12:24:03 +00:00
function _clearCache ( $type = null ) {
if ( $type === null ) {
2007-10-01 16:49:37 +00:00
if ( Configure :: read ( 'Cache.check' ) === true ) {
2007-10-27 01:32:17 +00:00
$assoc [] = strtolower ( Inflector :: pluralize ( $this -> alias ));
2007-06-20 06:15:35 +00:00
foreach ( $this -> __associations as $key => $association ) {
foreach ( $this -> $association as $key => $className ) {
2006-07-30 12:24:03 +00:00
$check = strtolower ( Inflector :: pluralize ( $className [ 'className' ]));
if ( ! in_array ( $check , $assoc )) {
$assoc [] = strtolower ( Inflector :: pluralize ( $className [ 'className' ]));
}
}
}
clearCache ( $assoc );
return true ;
}
} else {
//Will use for query cache deleting
}
}
/**
* Called when serializing a model
*
2007-11-05 03:36:12 +00:00
* @ return array Set of object variable names this model has
* @ access private
2006-07-30 12:24:03 +00:00
*/
function __sleep () {
$return = array_keys ( get_object_vars ( $this ));
return $return ;
2006-07-22 14:13:07 +00:00
}
2006-10-28 00:42:51 +00:00
/**
* Called when unserializing a model
*
2007-11-05 03:36:12 +00:00
* @ access private
2006-10-28 00:42:51 +00:00
*/
function __wakeup () {
}
2006-01-12 02:10:47 +00:00
}
2007-01-27 17:45:26 +00:00
if ( ! defined ( 'CAKEPHP_UNIT_TEST_EXECUTION' )) {
Overloadable :: overload ( 'Model' );
}
2007-10-21 18:34:23 +00:00
?>