2005-11-05 04:08:14 +00:00
< ? php
2005-12-22 01:07:28 +00:00
/* SVN FILE: $Id$ */
/**
* Short description for file .
2006-01-12 02:10:47 +00:00
*
2005-12-22 01:07:28 +00:00
* Long description for file
*
* PHP versions 4 and 5
*
* CakePHP : Rapid Development Framework < http :// www . cakephp . org />
2006-05-26 05:29:17 +00:00
* Copyright ( c ) 2006 , Cake Software Foundation , Inc .
* 1785 E . Sahara Avenue , Suite 490 - 204
* Las Vegas , Nevada 89104
2006-01-12 02:10:47 +00:00
*
2005-12-22 01:07:28 +00:00
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice .
*
2006-01-12 02:10:47 +00:00
* @ filesource
2006-05-26 05:29:17 +00:00
* @ copyright Copyright ( c ) 2006 , Cake Software Foundation , Inc .
* @ link http :// www . cakefoundation . org / projects / info / cakephp CakePHP Project
* @ package cake
* @ subpackage cake . cake . libs . controller . components . dbacl . models
* @ since CakePHP v 0.10 . 0.1232
* @ version $Revision $
* @ modifiedby $LastChangedBy $
* @ lastmodified $Date $
* @ license http :// www . opensource . org / licenses / mit - license . php The MIT License
2005-12-22 01:07:28 +00:00
*/
/**
* Short description for file .
2006-01-12 02:10:47 +00:00
*
2005-12-22 01:07:28 +00:00
* Long description for file
*
2006-05-26 05:29:17 +00:00
* @ package cake
* @ subpackage cake . cake . libs . controller . components . dbacl . models
2005-12-22 01:07:28 +00:00
*
*/
2006-11-24 17:27:11 +00:00
loadModel ();
2006-05-26 05:29:17 +00:00
class AclNode extends AppModel {
2006-10-09 15:47:50 +00:00
var $useDbConfig = ACL_DATABASE ;
2006-05-26 05:29:17 +00:00
var $cacheQueries = false ;
2005-12-22 01:07:28 +00:00
/**
2006-05-26 05:29:17 +00:00
* Creates a new ARO / ACO node
2005-12-22 01:07:28 +00:00
*
2006-05-26 05:29:17 +00:00
* @ param int $link_id
* @ param mixed $parent_id
* @ param string $alias
* @ return boolean True on success , false on fail
2005-12-22 01:07:28 +00:00
*/
2006-05-26 05:29:17 +00:00
function create ( $link_id = 0 , $parent_id = null , $alias = '' ) {
parent :: create ();
if ( strtolower ( get_class ( $this )) == " aclnode " ) {
trigger_error ( __ ( " [acl_base] The AclBase class constructor has been called, or the class was instantiated. This class must remain abstract. Please refer to the Cake docs for ACL configuration. " ), E_USER_ERROR );
return null ;
}
extract ( $this -> __dataVars ());
if ( $parent_id == null || $parent_id === 0 ) {
$parent = $this -> find ( null , 'MAX(rght) as rght' , null , - 1 );
$parent [ 'lft' ] = $parent [ 0 ][ 'rght' ];
if ( $parent [ 0 ][ 'rght' ] == null || ! $parent [ 0 ][ 'rght' ]) {
$parent [ 'lft' ] = 0 ;
}
} else {
$parent = $this -> find ( $this -> _resolveID ( $parent_id ), null , null , 0 );
if ( $parent == null || count ( $parent ) == 0 ) {
trigger_error ( " Null parent in { $class } ::create() " , E_USER_WARNING );
return null ;
}
$parent = $parent [ $class ];
$this -> _syncTable ( 1 , $parent [ 'lft' ], $parent [ 'lft' ]);
}
2006-06-14 18:02:37 +00:00
$return = $this -> save ( array ( $class => array (
$secondary_id => $link_id ,
'alias' => $alias ,
'lft' => $parent [ 'lft' ] + 1 ,
'rght' => $parent [ 'lft' ] + 2
)));
2006-05-26 05:29:17 +00:00
$this -> id = $this -> getLastInsertID ();
return $return ;
}
2006-09-21 00:12:40 +00:00
/**
* Deletes the ARO / ACO node with the given ID
*
* @ param mixed $id The id or alias of an ARO / ACO node
* @ return boolean True on success , false on fail
*/
function delete ( $id ) {
extract ( $this -> __dataVars ());
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
$result = $this -> find ( $this -> _resolveID ( $id ));
$object = $result [ $class ];
if ( $object == null || count ( $object ) == 0 ) {
return false ;
}
$children = $this -> findAll ( array ( " { $class } .rght " => " < { $result [ $class ][ 'rght' ] } " , " { $class } .lft " => " > { $result [ $class ][ 'lft' ] } " ), 'id' , null , null , null , - 1 );
2006-10-14 17:19:03 +00:00
$idList = Set :: extract ( $children , '{n}.' . $class . '.id' );
2006-09-21 00:12:40 +00:00
$idList [] = $result [ $class ][ 'id' ];
// Delete associated permissions.
$this -> ArosAco -> query ( 'DELETE FROM ' . $db -> fullTableName ( $this -> ArosAco ) . " WHERE { $class } _id in ( " . implode ( ', ' , $idList ) . ')' );
$table = $db -> fullTableName ( $this );
$this -> query ( " DELETE FROM { $table } WHERE { $table } .lft >= { $result [ $class ][ 'lft' ] } AND { $table } .rght <= { $result [ $class ][ 'rght' ] } " );
$shift = 1 + $result [ $class ][ 'rght' ] - $result [ $class ][ 'lft' ];
$this -> query ( 'UPDATE ' . $table . ' SET `rght` = `rght` - ' . $shift . ' WHERE `rght` > ' . $result [ $class ][ 'rght' ]);
$this -> query ( 'UPDATE ' . $table . ' SET `lft` = `lft` - ' . $shift . ' WHERE `lft` > ' . $result [ $class ][ 'lft' ]);
return true ;
}
2005-12-22 01:07:28 +00:00
/**
2006-05-26 05:29:17 +00:00
* Sets the parent of the given node
2005-12-22 01:07:28 +00:00
*
2006-05-26 05:29:17 +00:00
* @ param mixed $parent_id
* @ param mixed $id
* @ return boolean True on success , false on failure
2005-12-22 01:07:28 +00:00
*/
2006-05-26 05:29:17 +00:00
function setParent ( $parent_id = null , $id = null ) {
if ( strtolower ( get_class ( $this )) == " aclnode " ) {
trigger_error ( __ ( " [acl_base] The AclBase class constructor has been called, or the class was instantiated. This class must remain abstract. Please refer to the Cake docs for ACL configuration. " ), E_USER_ERROR );
return null ;
}
extract ( $this -> __dataVars ());
if ( $id == null && $this -> id == false ) {
return false ;
} else if ( $id == null ) {
$id = $this -> id ;
}
$object = $this -> find ( $this -> _resolveID ( $id ), null , null , 0 );
if ( $object == null || count ( $object ) == 0 ) {
return false ;
}
$object = $object [ $class ];
$parent = $this -> getParent ( $id );
2006-06-14 18:02:37 +00:00
if (( $parent == null && $parent_id == null ) || ( $parent_id == $parent [ $class ][ $secondary_id ] && $parent_id != null ) || ( $parent_id == $parent [ $class ][ 'alias' ] && $parent_id != null )) {
return false ;
2006-05-26 05:29:17 +00:00
}
if ( $parent_id == null ) {
$newParent = $this -> find ( null , 'MAX(rght) as lft' , null , - 1 );
$newParent = $newParent [ 0 ];
$newParent [ 'rght' ] = $newParent [ 'lft' ];
} else {
$newParent = $this -> find ( $this -> _resolveID ( $parent_id ), null , null , 0 );
$newParent = $newParent [ $class ];
}
if ( $parent_id != null && $newParent [ 'lft' ] <= $object [ 'lft' ] && $newParent [ 'rght' ] >= $object [ 'rght' ]) {
return false ;
}
$this -> _syncTable ( 0 , $object [ 'lft' ], $object [ 'lft' ]);
if ( $object [ 'lft' ] < $newParent [ 'lft' ]) {
$newParent [ 'lft' ] = $newParent [ 'lft' ] - 2 ;
$newParent [ 'rght' ] = $newParent [ 'rght' ] - 2 ;
}
if ( $parent_id != null ) {
$this -> _syncTable ( 1 , $newParent [ 'lft' ], $newParent [ 'lft' ]);
}
$object [ 'lft' ] = $newParent [ 'lft' ] + 1 ;
$object [ 'rght' ] = $newParent [ 'lft' ] + 2 ;
$this -> save ( array ( $class => $object ));
if ( $newParent [ 'lft' ] == 0 ) {
$this -> _syncTable ( 2 , $newParent [ 'lft' ], $newParent [ 'lft' ]);
}
return true ;
}
2005-12-22 01:07:28 +00:00
/**
2006-03-28 02:44:55 +00:00
* Get the parent node of the given Aro or Aco
2005-12-22 01:07:28 +00:00
*
2006-03-28 02:44:55 +00:00
* @ param moxed $id
* @ return array
2005-12-22 01:07:28 +00:00
*/
2006-05-26 05:29:17 +00:00
function getParent ( $id ) {
$path = $this -> getPath ( $id );
if ( $path == null || count ( $path ) < 2 ) {
return null ;
} else {
return $path [ count ( $path ) - 2 ];
}
}
2005-12-22 01:07:28 +00:00
/**
2006-03-28 02:44:55 +00:00
* Gets the path to the given Aro or Aco
2005-12-22 01:07:28 +00:00
*
2006-03-28 02:44:55 +00:00
* @ param mixed $id
* @ return array
2005-12-22 01:07:28 +00:00
*/
2006-05-26 05:29:17 +00:00
function getPath ( $id ) {
if ( strtolower ( get_class ( $this )) == " aclnode " ) {
trigger_error ( __ ( " [acl_base] The AclBase class constructor has been called, or the class was instantiated. This class must remain abstract. Please refer to the Cake docs for ACL configuration. " ), E_USER_ERROR );
return null ;
}
extract ( $this -> __dataVars ());
$item = $this -> find ( $this -> _resolveID ( $id ), null , null , 0 );
if ( $item == null || count ( $item ) == 0 ) {
return null ;
}
return $this -> findAll ( array ( $class . '.lft' => '<= ' . $item [ $class ][ 'lft' ], $class . '.rght' => '>= ' . $item [ $class ][ 'rght' ]), null , array ( $class . '.lft' => 'ASC' ), null , null , 0 );
}
2005-12-22 01:07:28 +00:00
/**
2006-03-28 02:44:55 +00:00
* Get the child nodes of the given Aro or Aco
2005-12-22 01:07:28 +00:00
*
2006-03-28 02:44:55 +00:00
* @ param mixed $id
* @ return array
2005-12-22 01:07:28 +00:00
*/
2006-05-26 05:29:17 +00:00
function getChildren ( $id ) {
if ( strtolower ( get_class ( $this )) == " aclnode " ) {
trigger_error ( __ ( " [acl_base] The AclBase class constructor has been called, or the class was instantiated. This class must remain abstract. Please refer to the Cake docs for ACL configuration. " ), E_USER_ERROR );
return null ;
}
extract ( $this -> __dataVars ());
$item = $this -> find ( $this -> _resolveID ( $id ), null , null , 0 );
return $this -> findAll ( array ( $class . '.lft' => '> ' . $item [ $class ][ 'lft' ], $class . '.rght' => '< ' . $item [ $class ][ 'rght' ]), null , null , null , null , null , 0 );
}
2005-12-22 01:07:28 +00:00
/**
2006-03-28 02:44:55 +00:00
* Gets a conditions array to find an Aro or Aco , based on the given id or alias
2005-12-22 01:07:28 +00:00
*
2006-03-28 02:44:55 +00:00
* @ param mixed $id
* @ return array Conditions array for a find / findAll call
2005-12-22 01:07:28 +00:00
*/
2006-05-26 05:29:17 +00:00
function _resolveID ( $id ) {
extract ( $this -> __dataVars ());
$key = ( is_numeric ( $id ) ? $secondary_id : 'alias' );
return array ( $this -> name . '.' . $key => $id );
}
2005-12-22 01:07:28 +00:00
/**
2006-03-28 02:44:55 +00:00
* Shifts the left and right values of the aro / aco tables
* when a node is added or removed
2005-12-22 01:07:28 +00:00
*
2006-01-12 02:10:47 +00:00
* @ param unknown_type $dir
* @ param unknown_type $lft
* @ param unknown_type $rght
2005-12-22 01:07:28 +00:00
*/
2006-05-26 05:29:17 +00:00
function _syncTable ( $dir , $lft , $rght ) {
$db =& ConnectionManager :: getDataSource ( $this -> useDbConfig );
if ( $dir == 2 ) {
$shift = 1 ;
$dir = '+' ;
} else {
$shift = 2 ;
if ( $dir > 0 ) {
$dir = '+' ;
} else {
$dir = '-' ;
}
}
2006-10-14 17:19:03 +00:00
$db -> query ( 'UPDATE ' . $db -> fullTableName ( $this ) . ' SET ' . $db -> name ( 'rght' ) . ' = ' . $db -> name ( 'rght' ) . ' ' . $dir . ' ' . $shift . ' WHERE ' . $db -> name ( 'rght' ) . ' > ' . $lft );
$db -> query ( 'UPDATE ' . $db -> fullTableName ( $this ) . ' SET ' . $db -> name ( 'lft' ) . ' = ' . $db -> name ( 'lft' ) . ' ' . $dir . ' ' . $shift . ' WHERE ' . $db -> name ( 'lft' ) . ' > ' . $lft );
2006-05-26 05:29:17 +00:00
}
2005-12-22 01:07:28 +00:00
/**
2006-05-26 05:29:17 +00:00
* Private method . Infers data based on the currently - intantiated subclass .
2005-12-22 01:07:28 +00:00
*
2006-05-26 05:29:17 +00:00
* @ return array
2005-12-22 01:07:28 +00:00
*/
2006-05-26 05:29:17 +00:00
function __dataVars () {
$vars = array ();
$class = strtolower ( get_class ( $this ));
if ( $class == 'aro' ) {
2006-10-28 04:40:30 +00:00
$vars [ 'secondary_id' ] = 'foreign_key' ;
2006-05-26 05:29:17 +00:00
} else {
$vars [ 'secondary_id' ] = 'object_id' ;
}
$vars [ 'class' ] = ucwords ( $class );
return $vars ;
}
2005-11-05 04:08:14 +00:00
}
2006-06-14 18:02:37 +00:00
2005-11-05 04:08:14 +00:00
?>