| [ Index ] |
PHP Cross Reference of Akelos Framework |
[Summary view] [Print] [Text view]
1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 3 4 // +----------------------------------------------------------------------+ 5 // | Akelos Framework - http://www.akelos.org | 6 // +----------------------------------------------------------------------+ 7 // | Copyright (c) 2002-2006, Akelos Media, S.L. & Bermi Ferrer Martinez | 8 // | Released under the GNU Lesser General Public License, see LICENSE.txt| 9 // +----------------------------------------------------------------------+ 10 11 /** 12 * @package ActiveRecord 13 * @subpackage Behaviours 14 * @author Bermi Ferrer <bermi a.t akelos c.om> 15 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org 16 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html> 17 */ 18 19 require_once (AK_LIB_DIR.DS.'AkActiveRecord'.DS.'AkObserver.php'); 20 21 /** 22 * This act provides the capabilities for sorting and reordering a number of objects in list. 23 * The class that has this specified needs to have a "position" column defined as an integer on 24 * the mapped database table. 25 * 26 * Todo list example: 27 * <code> 28 * class TodoList extends ActiveRecord 29 * { 30 * var $has_many = array('todo_items', array('order' => "position")); 31 * } 32 * 33 * class TodoItem extends ActiveRecord 34 * { 35 * var $belongs_to = 'todo_list'; 36 * var $acts_as = array('list' => array('scope' => 'todo_list')); 37 * } 38 * 39 * $TodoList =& new TodoList(); 40 * 41 * $TodoList->list->moveToBottom(); 42 * </code> 43 */ 44 class AkActsAsList extends AkObserver 45 { 46 var $column = 'position'; 47 var $scope = ''; 48 var $scope_condition; 49 /** 50 * Configuration options are: 51 * 52 * * +column+ - specifies the column name to use for keeping the position integer (default: position) 53 * * +scope+ - restricts what is to be considered a list. 54 * Example: 55 * 56 * class TodoTask extends ActiveRecord 57 * { 58 * var $acts_as = array('list'=> array('scope'=> array('todo_list_id','completed = 0'))); 59 * var $belongs_to = 'todo_list'; 60 * } 61 */ 62 var $_ActiveRecordInstance; 63 function AkActsAsList(&$ActiveRecordInstance) 64 { 65 $this->_ActiveRecordInstance =& $ActiveRecordInstance; 66 } 67 68 function init($options = array()) 69 { 70 $this->column = !empty($options['column']) ? $options['column'] : $this->column; 71 $this->scope = !empty($options['scope']) ? $options['scope'] : $this->scope; 72 return $this->_ensureIsActiveRecordInstance($this->_ActiveRecordInstance); 73 } 74 75 function _ensureIsActiveRecordInstance(&$ActiveRecordInstance) 76 { 77 if(is_object($ActiveRecordInstance) && method_exists($ActiveRecordInstance,'actsLike')){ 78 $this->_ActiveRecordInstance =& $ActiveRecordInstance; 79 if(!$this->_ActiveRecordInstance->hasColumn($this->column)){ 80 trigger_error(Ak::t('Could not find the column "%column" into the table "%table". This column is needed in order to make "%model" act as a list.',array('%column'=>$this->column,'%table'=>$this->_ActiveRecordInstance->getTableName(),'%model'=>$this->_ActiveRecordInstance->getModelName())),E_USER_ERROR); 81 unset($this->_ActiveRecordInstance->list); 82 return false; 83 }else { 84 $this->observe(&$ActiveRecordInstance); 85 } 86 }else{ 87 trigger_error(Ak::t('You are trying to set an object that is not an active record.'), E_USER_ERROR); 88 return false; 89 } 90 return true; 91 } 92 93 function reloadActiveRecordInstance(&$listObject) 94 { 95 AK_PHP5 ? null : $listObject->list->setActiveRecordInstance(&$listObject); 96 } 97 98 function getType() 99 { 100 return 'list'; 101 } 102 103 function beforeDestroy(&$object) 104 { 105 $object->list->_ActiveRecordInstance->reload(); 106 return true; 107 } 108 109 function afterSave(&$object) 110 { 111 $object->list->_ActiveRecordInstance->reload(); 112 return true; 113 } 114 115 function afterDestroy(&$object) 116 { 117 return $object->list->removeFromList(); 118 } 119 120 function beforeCreate(&$object) 121 { 122 $object->list->_addToBottom(); 123 return true; 124 } 125 126 /** 127 * All the methods available to a record that has had <tt>acts_as list</tt> specified. Each method works 128 * by assuming the object to be the item in the list, so <tt>$Chapter->list->moveLower()</tt> would move that chapter 129 * lower in the list of all chapters. Likewise, <tt>$Chapter->list->isFirst()</tt> would return true if that chapter is 130 * the first in the list of all chapters. 131 */ 132 133 134 function insertAt($position = 1) 135 { 136 return $this->insertAtPosition($position); 137 } 138 139 /** 140 * This function saves the object using save() before inserting it into the list 141 */ 142 function insertAtPosition($position) 143 { 144 $this->_ActiveRecordInstance->transactionStart(); 145 if($this->_ActiveRecordInstance->isNewRecord()){ 146 $this->_ActiveRecordInstance->save(); 147 } 148 $this->removeFromList(); 149 $this->incrementPositionsOnLowerItems($position); 150 151 $this->_ActiveRecordInstance->updateAttribute($this->column, $position); 152 if($this->_ActiveRecordInstance->transactionHasFailed()){ 153 $this->_ActiveRecordInstance->transactionComplete(); 154 return false; 155 } 156 157 $this->_ActiveRecordInstance->transactionComplete(); 158 return true; 159 } 160 161 function moveLower() 162 { 163 $this->_ActiveRecordInstance->transactionStart(); 164 if($LowerItem = $this->getLowerItem()){ 165 if($LowerItem->list->decrementPosition() && $this->incrementPosition()){ 166 $this->_ActiveRecordInstance->transactionComplete(); 167 return true; 168 }else{ 169 $this->_ActiveRecordInstance->transactionFail(); 170 } 171 } 172 $this->_ActiveRecordInstance->transactionComplete(); 173 return false; 174 } 175 176 function moveHigher() 177 { 178 $this->_ActiveRecordInstance->transactionStart(); 179 if($HigherItem = $this->getHigherItem()){ 180 if($HigherItem->list->incrementPosition() && $this->decrementPosition()){ 181 $this->_ActiveRecordInstance->transactionComplete(); 182 return true; 183 }else{ 184 $this->_ActiveRecordInstance->transactionFail(); 185 } 186 } 187 $this->_ActiveRecordInstance->transactionComplete(); 188 return false; 189 } 190 191 function moveToBottom() 192 { 193 if($this->isInList()){ 194 $this->_ActiveRecordInstance->transactionStart(); 195 if($this->decrementPositionsOnLowerItems() && $this->assumeBottomPosition()){ 196 $this->_ActiveRecordInstance->transactionComplete(); 197 return true; 198 }else{ 199 $this->_ActiveRecordInstance->transactionFail(); 200 } 201 $this->_ActiveRecordInstance->transactionComplete(); 202 } 203 return false; 204 } 205 206 function moveToTop() 207 { 208 if($this->isInList()){ 209 $this->_ActiveRecordInstance->transactionStart(); 210 if($this->incrementPositionsOnHigherItems() && $this->assumeTopPosition()){ 211 $this->_ActiveRecordInstance->transactionComplete(); 212 return true; 213 }else{ 214 $this->_ActiveRecordInstance->transactionFail(); 215 } 216 $this->_ActiveRecordInstance->transactionComplete(); 217 } 218 return false; 219 } 220 221 function assumeBottomPosition() 222 { 223 return $this->_ActiveRecordInstance->updateAttribute($this->column, $this->getBottomPosition($this->_ActiveRecordInstance->getId()) + 1); 224 } 225 226 function assumeTopPosition() 227 { 228 return $this->_ActiveRecordInstance->updateAttribute($this->column, 1); 229 } 230 231 function getBottomPosition($except = null) 232 { 233 return ($item = $this->getBottomItem($except)) ? $item->getAttribute($this->column) : 0; 234 } 235 236 /** 237 * Returns an instance of the item that's on the very bottom of the list. Returns false if there's none 238 */ 239 function getBottomItem($except = null) 240 { 241 $conditions = $this->getScopeCondition(); 242 243 if(isset($except)){ 244 $conditions .= " AND id != $except"; 245 } 246 return $this->_ActiveRecordInstance->find('first', array('conditions' => $conditions, 'order' => "{$this->column} DESC")); 247 } 248 249 function isInList() 250 { 251 return !empty($this->_ActiveRecordInstance->{$this->column}); 252 } 253 254 /** 255 * This has the effect of moving all the higher items up one. 256 */ 257 function decrementPositionsOnHigherItems($position) 258 { 259 return $this->_ActiveRecordInstance->updateAll("{$this->column} = ({$this->column} - 1)", $this->getScopeCondition()." AND {$this->column} <= $position"); 260 } 261 262 /** 263 * This has the effect of moving all the lower items up one. 264 */ 265 function decrementPositionsOnLowerItems() 266 { 267 if($this->isInList()){ 268 $this->_ActiveRecordInstance->updateAll("{$this->column} = ({$this->column} - 1)", $this->getScopeCondition()." AND {$this->column} > ".$this->_ActiveRecordInstance->getAttribute($this->column)); 269 return true; 270 } 271 return false; 272 } 273 274 /** 275 * This has the effect of moving all the higher items down one. 276 */ 277 function incrementPositionsOnHigherItems() 278 { 279 if($this->isInList()){ 280 $this->_ActiveRecordInstance->updateAll("{$this->column} = ({$this->column} + 1)", $this->getScopeCondition()." AND {$this->column} < ".$this->_ActiveRecordInstance->getAttribute($this->column)); 281 return true; 282 } 283 return false; 284 } 285 286 /** 287 * This has the effect of moving all the lower items down one. 288 */ 289 function incrementPositionsOnLowerItems($position) 290 { 291 return $this->_ActiveRecordInstance->updateAll("{$this->column} = ({$this->column} + 1)", $this->getScopeCondition()." AND {$this->column} >= $position"); 292 } 293 294 function incrementPositionsOnAllItems() 295 { 296 return $this->_ActiveRecordInstance->updateAll("{$this->column} = ({$this->column} + 1)", $this->getScopeCondition()); 297 } 298 299 function removeFromList() 300 { 301 if($this->isInList()){ 302 if($this->decrementPositionsOnLowerItems()){ 303 $this->_ActiveRecordInstance->{$this->column} = null; 304 return true; 305 } 306 } 307 return false; 308 } 309 310 function incrementPosition() 311 { 312 if($this->isInList()){ 313 return $this->_ActiveRecordInstance->updateAttribute($this->column, $this->_ActiveRecordInstance->getAttribute($this->column) + 1); 314 } 315 return false; 316 } 317 318 function decrementPosition() 319 { 320 if($this->isInList()){ 321 return $this->_ActiveRecordInstance->updateAttribute($this->column, $this->_ActiveRecordInstance->getAttribute($this->column) - 1); 322 } 323 return false; 324 } 325 326 function isFirst() 327 { 328 if($this->isInList()){ 329 return $this->_ActiveRecordInstance->getAttribute($this->column) == 1; 330 } 331 return false; 332 } 333 334 function isLast() 335 { 336 if($this->isInList()){ 337 return $this->_ActiveRecordInstance->getAttribute($this->column) == $this->getBottomPosition(); 338 } 339 return false; 340 } 341 342 function getHigherItem() 343 { 344 if($this->isInList()){ 345 return $this->_ActiveRecordInstance->find('first', array('conditions' => $this->getScopeCondition()." AND {$this->column} = ".($this->_ActiveRecordInstance->getAttribute($this->column) - 1))); 346 } 347 return false; 348 } 349 350 function getLowerItem() 351 { 352 if($this->isInList()){ 353 return $this->_ActiveRecordInstance->find('first', array('conditions' => $this->getScopeCondition()." AND {$this->column} = ".($this->_ActiveRecordInstance->getAttribute($this->column) + 1))); 354 } 355 return false; 356 } 357 358 function addToListTop() 359 { 360 $this->incrementPositionsOnAllItems(); 361 } 362 363 function _addToBottom() 364 { 365 $this->_ActiveRecordInstance->{$this->column} = $this->getBottomPosition() + 1; 366 } 367 368 function getScopeCondition() 369 { 370 if (!empty($this->variable_scope_condition)){ 371 return $this->_ActiveRecordInstance->_getVariableSqlCondition($this->variable_scope_condition); 372 373 // True condition in case we don't have a scope 374 }elseif(empty($this->scope_condition) && empty($this->scope)){ 375 $this->scope_condition = ($this->_ActiveRecordInstance->_db->type() == 'postgre') ? 'true' : '1'; 376 }elseif (!empty($this->scope)){ 377 $this->setScopeCondition(join(' AND ',array_map(array(&$this,'getScopedColumn'),(array)$this->scope))); 378 } 379 return $this->scope_condition; 380 } 381 382 function setScopeCondition($scope_condition) 383 { 384 if(!is_array($scope_condition) && strstr($scope_condition, '?')){ 385 $this->variable_scope_condition = $scope_condition; 386 }else{ 387 $this->scope_condition = $scope_condition; 388 } 389 } 390 391 function getScopedColumn($column) 392 { 393 if($this->_ActiveRecordInstance->hasColumn($column)){ 394 $value = $this->_ActiveRecordInstance->get($column); 395 $condition = $this->_ActiveRecordInstance->getAttributeCondition($value); 396 $value = $this->_ActiveRecordInstance->castAttributeForDatabase($column, $value); 397 return $column.' '.str_replace('?', $value, $condition); 398 }else{ 399 return $column; 400 } 401 } 402 } 403 404 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Oct 27 12:43:49 2008 | Cross-referenced by PHPXref 0.6 |