ソースを参照

Resolves PR 11

euromark 12 年 前
コミット
8cb6b85edd

+ 38 - 15
Model/Behavior/WhoDidItBehavior.php

@@ -5,19 +5,21 @@
  * @copyright http://www.4webby.com
  * @author Daniel Vecchiato
  * @author Mark Scherer
- * @licence MIT
- */
+ * @author Marc Würth
+ * @version 1.3
+ * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
+ * @link https://github.com/dereuromark/tools
+ **/
 
 App::uses('CakeSession', 'Model/Datasource');
 App::uses('ModelBehavior', 'Model');
 
 /**
- * WhoDidIt Model Behavior
+ * WhoDidIt Behavior
  *
- * Handles created_by, modified_by fields for a given model, if they exist in the model's
- * table scheme.
- * It's similar to the created, modified automagic, but it stores the id of the logged in
- * user in the models that have $actsAs = array('Tools.WhoDidIt').
+ * Handles created_by, modified_by fields for a given Model, if they exist in the Model DB table.
+ * It's similar to the created, modified automagic, but it stores the id of the logged in user
+ * in the models that have $actsAs = array('WhoDidIt').
  *
  * This is useful to track who created records, and the last user that has changed them.
  *
@@ -28,15 +30,20 @@ class WhoDidItBehavior extends ModelBehavior {
 	/**
 	 * Default settings for a model that has this behavior attached.
 	 *
+	 * Setting force_modified to true will have the same effect as overriding the save method as
+	 * described in the code example for "Using created and modified" in the Cookbook.
+	 *
 	 * @var array
+	 * @link http://book.cakephp.org/2.0/en/models/saving-your-data.html#using-created-and-modified
 	 */
 	protected $_defaults = array(
-		'auth_session' => 'Auth', // Name of Auth session key.
-		'user_model' => 'User', // Name of User model.
-		'created_by_field' => 'created_by', // The name of the "created_by" field in DB.
-		'modified_by_field' => 'modified_by', // The name of the "modified_by" field in DB.
-		'confirmed_by_field' => 'confirmed_by', // The name of the "confirmed_by" field in DB.
-		'auto_bind' => true // Automatically bind the model to the User model.
+		'auth_session' => 'Auth', // Name of Auth session key
+		'user_model' => 'User', // Name of the User model
+		'created_by_field' => 'created_by', // Name of the "created_by" field in the model
+		'modified_by_field' => 'modified_by', // Name of the "modified_by" field in the model
+		'confirmed_by_field' => 'confirmed_by', // Name of the "confirmed by" field in the model
+		'auto_bind' => true, // Automatically bind the model to the User model (default true)
+		'force_modified' => false // Force update of the "modified" field even if not empty
 	);
 
 	/**
@@ -93,6 +100,10 @@ class WhoDidItBehavior extends ModelBehavior {
 	 *
 	 * Checks if at least one field is available.
 	 * Reads the current user id from the session.
+	 * If a user id is set it will fill...
+	 * ... the created_by field only when creating a record
+	 * ... the modified by field only if it is not in the data array
+	 * or the "force_modified" setting is set to true.
 	 *
 	 * @param Model $Model The model using this behavior.
 	 * @return boolean True if the operation should continue, false if it should abort.
@@ -105,11 +116,23 @@ class WhoDidItBehavior extends ModelBehavior {
 			$userId = CakeSession::read($AuthSession . '.' . $UserSession . '.id');
 
 			if ($userId) {
-				$data = array($this->settings[$Model->alias]['modified_by_field'] => $userId);
+				$data = array();
+				$modifiedByField = $this->settings[$Model->alias]['modified_by_field'];
+
+				if (!isset($Model->data[$Model->alias][$modifiedByField]) || $this->settings[$Model->alias]['force_modified']) {
+					$data[$this->settings[$Model->alias]['modified_by_field']] = $userId;
+				} else {
+					$pos = strpos($this->settings[$Model->alias]['modified_by_field'], '_');
+					$field = substr($this->settings[$Model->alias]['modified_by_field'], 0, $pos);
+					$data[$field] = false;
+				}
+
 				if (!$Model->exists()) {
 					$data[$this->settings[$Model->alias]['created_by_field']] = $userId;
 				}
-				$Model->set($data);
+				if ($data) {
+					$Model->set($data);
+				}
 			}
 		}
 		return true;

+ 28 - 0
Test/Case/Model/Behavior/WhoDidItBehaviorTest.php

@@ -64,4 +64,32 @@ class WhoDidItBehaviorTest extends MyCakeTestCase {
 		$this->assertEquals('1', $res['WhoDidItPlayer']['modified_by']);
 	}
 
+	/**
+	 * Usually the fields modified_by and created_by should not be present in forms.
+	 * For some admin views this might be the case. Here we don't want to modify then
+	 * in most cases. We also don't want the modified timestamp to be wrongly raised.
+	 *
+	 * @return void
+	 */
+	public function testSaveWithAlreadySetModified() {
+		CakeSession::write('Auth.User.id', '1');
+
+		$data = array(
+			'name' => 'Foo'
+		);
+		$this->Model->create();
+		$res = $this->Model->save($data);
+		$this->assertTrue((bool)$res);
+		$this->assertTrue(count($res['WhoDidItPlayer']) === 6);
+
+		// update (id + name + modified)
+		CakeSession::write('Auth.User.id', '2');
+		$data += array('modified_by' => $res['WhoDidItPlayer']['modified_by']);
+		$res = $this->Model->save($data + array('id' => $this->Model->id));
+		debug($res);ob_flush();
+		$this->assertTrue((bool)$res);
+		$this->assertFalse($res['WhoDidItPlayer']['modified']);
+		$this->assertTrue(count($res['WhoDidItPlayer']) === 4);
+	}
+
 }

+ 2 - 5
Test/Fixture/WhoDidItPlayerFixture.php

@@ -1,18 +1,15 @@
 <?php
 /**
- * Fixture for WhoDidIt
- *
  * PHP 5
  *
- * @author Mark Scherrer
+ * @author Mark Scherer
  * @author Marc Würth
  * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  * @link https://github.com/dereuromark/tools
  */
 
 /**
- * Class WhoDidItPlayerFixture
- *
+ * Fixture for WhoDidIt
  */
 class WhoDidItPlayerFixture extends CakeTestFixture {