From 01e035f726cf26ac04b002c43733b4b6b86f4a32 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 20 Mar 2012 22:36:48 -0400 Subject: [PATCH] Move logic to afterDelete. Because behavior callbacks are fired first, removing data in the beforeDelete could result in data loss if the model prevents deletion. Fixes #2699 --- lib/Cake/Model/Behavior/TreeBehavior.php | 29 +++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Model/Behavior/TreeBehavior.php b/lib/Cake/Model/Behavior/TreeBehavior.php index ff03732cb..03a8f2662 100644 --- a/lib/Cake/Model/Behavior/TreeBehavior.php +++ b/lib/Cake/Model/Behavior/TreeBehavior.php @@ -47,6 +47,13 @@ class TreeBehavior extends ModelBehavior { 'scope' => '1 = 1', 'type' => 'nested', '__parentChange' => false, 'recursive' => -1 ); +/** + * Used to preserve state between delete callbacks. + * + * @var array + */ + protected $_deletedRow = null; + /** * Initiate Tree behavior * @@ -107,13 +114,13 @@ class TreeBehavior extends ModelBehavior { } /** - * Before delete method. Called before all deletes + * Stores the record about to be deleted. * - * Will delete the current node and all children using the deleteAll method and sync the table + * This is used to delete child nodes in the afterDelete. * * @param Model $Model Model instance * @param boolean $cascade - * @return boolean true to continue, false to abort the delete + * @return boolean */ public function beforeDelete(Model $Model, $cascade = true) { extract($this->settings[$Model->alias]); @@ -121,6 +128,22 @@ class TreeBehavior extends ModelBehavior { 'conditions' => array($Model->alias . '.' . $Model->primaryKey => $Model->id), 'fields' => array($Model->alias . '.' . $left, $Model->alias . '.' . $right), 'recursive' => -1))); + $this->_deletedRow = $data; + return true; + } + +/** + * After delete method. + * + * Will delete the current node and all children using the deleteAll method and sync the table + * + * @param Model $Model Model instance + * @return boolean true to continue, false to abort the delete + */ + public function afterDelete(Model $Model) { + extract($this->settings[$Model->alias]); + $data = $this->_deletedRow; + $this->_deletedRow = null; if (!$data[$right] || !$data[$left]) { return true;