浏览代码

StringBehavior.php

Mark Scherer 10 年之前
父节点
当前提交
c3fda26b74

+ 135 - 0
src/Model/Behavior/StringBehavior.php

@@ -0,0 +1,135 @@
+<?php
+namespace Tools\Model\Behavior;
+
+use Cake\Event\Event;
+use Cake\ORM\Behavior;
+use Cake\ORM\Entity;
+use Cake\ORM\Query;
+use Tools\Utility\Text;
+use Cake\Datasource\ResultSetInterface;
+use Cake\Database\Type;
+
+/**
+ * A behavior that will apply basic string operations for your input.
+ *
+ * Note that most string modification should be done once, on save.
+ * Prevent using output modification if possible as it is done on every fetch.
+ *
+ * Tip: If you have other behaviors that might modify the array data prior to saving, better use a higher priority:
+ *   $this->addBehavior('Tools.String', array('priority' => 11, ...));
+ * So that it is run last.
+ *
+ * Usage: See docs
+ *
+ * @author Mark Scherer
+ * @license MIT
+ */
+class StringBehavior extends Behavior {
+
+	/**
+	 * //TODO: json input/ouput directly, clean
+	 * @var array
+	 */
+	protected $_defaultConfig = [
+		'fields' => [], // Fields to convert
+		'input' => [], // Basic input filters
+		'output' => [], // Basic output filters
+	];
+
+	/**
+	 * JsonableBehavior::initialize()
+	 *
+	 * @param array $config
+	 * @return void
+	 */
+	public function initialize(array $config = []) {
+	}
+
+	/**
+	 * Decode the fields on after find
+	 *
+	 * @param Event $event
+	 * @param Query $query
+	 * @return void
+	 */
+	public function beforeFind(Event $event, Query $query) {
+		$query->formatResults(function (ResultSetInterface $results) {
+			return $results->map(function ($row) {
+				$this->processItems($row, 'output');
+				return $row;
+			});
+		});
+	}
+
+	/**
+	 * Decodes the fields of an array/entity (if the value itself was encoded)
+	 *
+	 * @param Entity $entity
+	 * @param string $type Type (input/output)
+	 * @return void
+	 */
+	public function processItems(Entity $entity, $type = 'input') {
+		$fields = $this->_config['fields'];
+
+		foreach ($fields as $field => $map) {
+			if (is_numeric($field)) {
+				$field = $map;
+				$map = [];
+			} else {
+				$map = (array)$map;
+			}
+
+			$val = $entity->get($field);
+			if (!$val && !is_numeric($val)) {
+				continue;
+			}
+
+			if (!$map) {
+				$map = $this->_config[$type];
+			}
+			if (!$map) {
+				continue;
+			}
+
+			$entity->set($field, $this->_process($val, $map));
+		}
+	}
+
+	/**
+	 * Saves all fields that do not belong to the current Model into 'with' helper model.
+	 *
+	 * @param Event $event
+	 * @return void
+	 */
+	public function beforeSave(Event $event, Entity $entity, \ArrayObject $options) {
+		$this->processItems($entity, 'input');
+	}
+
+	/**
+	 * Process val via map
+	 *
+	 * @param string $val
+	 * @param array $map
+	 * @return string
+	 */
+	public function _process($val, $map) {
+		foreach ($map as $m => $arg) {
+			if (is_numeric($m)) {
+				$m = $arg;
+				$arg = null;
+			}
+
+			if ($arg !== null) {
+				$ret = call_user_func($m, $val, $arg);
+			} else {
+				$ret = call_user_func($m, $val);
+			}
+
+			if ($ret !== false) {
+				$val = $ret;
+			}
+		}
+		return $val;
+	}
+
+}

+ 18 - 0
tests/Fixture/StringCommentsFixture.php

@@ -0,0 +1,18 @@
+<?php
+namespace Tools\Test\Fixture;
+
+use Cake\TestSuite\Fixture\TestFixture;
+
+class StringCommentsFixture extends TestFixture {
+
+	public $fields = [
+		'id' => ['type' => 'integer'],
+		'comment' => ['type' => 'string', 'length' => 255, 'null' => false],
+		'url' => ['type' => 'string', 'length' => 255, 'null' => false],
+		'title' => ['type' => 'string', 'length' => 255, 'null' => false],
+		'_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id']]]
+	];
+
+	public $records = [
+	];
+}

+ 64 - 0
tests/TestCase/Model/Behavior/StringBehaviorTest.php

@@ -0,0 +1,64 @@
+<?php
+
+namespace Tools\Test\TestCase\Model\Behavior;
+
+use Cake\ORM\TableRegistry;
+use Tools\TestSuite\TestCase;
+use Cake\Core\Configure;
+use Tools\Model\Behavior\StringBehavior;
+
+class StringBehaviorTest extends TestCase {
+
+	public $fixtures = [
+		'plugin.tools.string_comments'
+	];
+
+	public $Comments;
+
+	public function setUp() {
+		parent::setUp();
+
+		$this->Comments = TableRegistry::get('StringComments');
+		$this->Comments->addBehavior('Tools.String', ['fields' => ['title'], 'input' => ['ucfirst']]);
+	}
+
+	/**
+	 * StringBehaviorTest::testBasic()
+	 *
+	 * @return void
+	 */
+	public function testBasic() {
+		$data = [
+			'comment' => 'blabla',
+			'url' => 'www.dereuromark.de',
+			'title' => 'some Name',
+		];
+		$entity = $this->Comments->newEntity($data);
+		$res = $this->Comments->save($entity);
+		$this->assertTrue((bool)$res);
+
+		$this->assertSame('Some Name', $res['title']);
+	}
+
+	/**
+	 * StringBehaviorTest::testMultipleFieldsAndMultipleFilters()
+	 *
+	 * @return void
+	 */
+	public function testMultipleFieldsAndMultipleFilters() {
+		$this->Comments->behaviors()->String->config(['fields' => ['title', 'comment'], 'input' => ['strtolower', 'ucwords']]);
+
+		$data = [
+			'comment' => 'blaBla',
+			'url' => 'www.dereuromark.de',
+			'title' => 'some nAme',
+		];
+		$entity = $this->Comments->newEntity($data);
+		$res = $this->Comments->save($entity);
+		$this->assertTrue((bool)$res);
+
+		$this->assertSame('Some Name', $res['title']);
+		$this->assertSame('Blabla', $res['comment']);
+	}
+
+}