浏览代码

Try auto length restriction and add tests.

euromark 11 年之前
父节点
当前提交
fc2fd2728f
共有 2 个文件被更改,包括 59 次插入84 次删除
  1. 29 28
      Model/Behavior/SluggedBehavior.php
  2. 30 56
      Test/Case/Model/Behavior/SluggedBehaviorTest.php

+ 29 - 28
Model/Behavior/SluggedBehavior.php

@@ -16,24 +16,26 @@ App::uses('ModelBehavior', 'Model');
 class SluggedBehavior extends ModelBehavior {
 
 	/**
-	 * Default settings
+	 * Default config
 	 *
-	 * label
+	 * - length
+	 *  Set to 0 for no length. Will be auto-detected if possible via schema.
+	 * - label
 	 * 	set to the name of a field to use for the slug, an array of fields to use as slugs or leave as null to rely
 	 * 	on the format returned by find('list') to determine the string to use for slugs
-	 * overwrite has 2 values
+	 * - overwrite has 2 values
 	 * 	false - once the slug has been saved, do not change it (use if you are doing lookups based on slugs)
 	 * 	true - if the label field values change, regenerate the slug (use if you are the slug is just window-dressing)
-	 * unique has 2 values
+	 * - unique has 2 values
 	 * 	false - will not enforce a unique slug, whatever the label is is direclty slugged without checking for duplicates
 	 * 	true - use if you are doing lookups based on slugs (see overwrite)
-	 * mode has the following values
+	 * - mode has the following values
 	 * 	ascii - retuns an ascii slug generated using the core Inflector::slug() function
 	 * 	display - a dummy mode which returns a slug legal for display - removes illegal (not unprintable) characters
 	 * 	url - returns a slug appropriate to put in a URL
 	 * 	class - a dummy mode which returns a slug appropriate to put in a html class (there are no restrictions)
 	 * 	id - retuns a slug appropriate to use in a html id
-	 * case has the following values
+	 * - case has the following values
 	 * 	null - don't change the case of the slug
 	 * 	low - force lower case. E.g. "this-is-the-slug"
 	 * 	up - force upper case E.g. "THIS-IS-THE-SLUG"
@@ -42,7 +44,7 @@ class SluggedBehavior extends ModelBehavior {
 	 *
 	 * @var array
 	 */
-	protected $_defaultSettings = array(
+	protected $_defaultConfig = array(
 		'label' => null,
 		'slugField' => 'slug',
 		'overwriteField' => 'overwrite_slug',
@@ -67,15 +69,6 @@ class SluggedBehavior extends ModelBehavior {
 	);
 
 	/**
-	 * StopWords property
-	 *
-	 * A (3 letter) language code indexed array of stop words
-	 *
-	 * @var array
-	 */
-	public $stopWords = array();
-
-	/**
 	 * Setup method
 	 *
 	 * Use the model's label field as the default field on which to base the slug, the label can be made up of multiple
@@ -86,22 +79,28 @@ class SluggedBehavior extends ModelBehavior {
 	 * @return void
 	 */
 	public function setup(Model $Model, $config = array()) {
-		$this->_defaultSettings['notices'] = Configure::read('debug');
-		$this->_defaultSettings['label'] = array($Model->displayField);
-		foreach ($this->_defaultSettings['replace'] as $key => $value) {
-			$this->_defaultSettings['replace'][$key] = __($value);
+		$defaults = array(
+			'notices' => Configure::read('debug'),
+			'label' => array($Model->displayField)
+		);
+		$defaults += $this->_defaultConfig;
+		foreach ($defaults['replace'] as $key => $value) {
+			$defaults['replace'][$key] = __($value);
 		}
-		$this->_defaultSettings = array_merge($this->_defaultSettings, (array)Configure::read('Slugged'));
 
-		$this->settings[$Model->alias] = array_merge($this->_defaultSettings, $config);
+		$config += (array)Configure::read('Slugged');
+		$config += $defaults;
 
-		if (!$this->settings[$Model->alias]['length']) {
-			$schema = $Model->schema($this->settings[$Model->alias]['slugField']);
-			$length = !empty($schema['length']) ? $schema['length'] : 100;
-			$this->settings[$Model->alias]['length'] = $length;
+		if ($config['length'] === null) {
+			$schema = $Model->schema($config['slugField']);
+			$length = !empty($schema['length']) ? $schema['length'] : 0;
+			$config['length'] = $length;
 		}
 
+		$this->settings[$Model->alias] = $config;
+
 		extract($this->settings[$Model->alias]);
+
 		$label = $this->settings[$Model->alias]['label'] = (array)$label;
 		if ($Model->Behaviors->loaded('Translate')) {
 			$notices = false;
@@ -248,6 +247,8 @@ class SluggedBehavior extends ModelBehavior {
 		if ($replace) {
 			$string = str_replace(array_keys($replace), array_values($replace), $string);
 		}
+
+		// TODO: Use `if (function_exists('transliterator_transliterate')) {}` for PHP5.4+
 		if ($mode === 'ascii') {
 			$slug = Inflector::slug($string, $separator);
 		} else {
@@ -265,7 +266,7 @@ class SluggedBehavior extends ModelBehavior {
 				$slug = 'x' . $slug;
 			}
 		}
-		if (strlen($slug) > $length) {
+		if ($length && strlen($slug) > $length) {
 			$slug = mb_substr($slug, 0, $length);
 			while ($slug && strlen($slug) > $length) {
 				$slug = mb_substr($slug, 0, mb_strlen($slug) - 1);
@@ -304,7 +305,7 @@ class SluggedBehavior extends ModelBehavior {
 			while ($Model->hasAny($conditions)) {
 				$i++;
 				$suffix	= $separator . $i;
-				if (strlen($slug . $suffix) > $length) {
+				if ($length && strlen($slug . $suffix) > $length) {
 					$slug = substr($slug, 0, $length - strlen($suffix));
 				}
 				$conditions[$Model->alias . '.' . $slugField] = $slug . $suffix;

+ 30 - 56
Test/Case/Model/Behavior/SluggedBehaviorTest.php

@@ -109,7 +109,7 @@ class SluggedBehaviorTest extends CakeTestCase {
 	 * @return void
 	 */
 	public function testSlugGenerationBasedOnTrigger() {
-		$this->Model->Behaviors->unload('Slugged');
+		$this->Model->Behaviors->unload('Tools.Slugged');
 		$this->Model->Behaviors->load('Tools.Slugged', array(
 			'trigger' => 'generateSlug', 'overwrite' => true));
 
@@ -130,7 +130,7 @@ class SluggedBehaviorTest extends CakeTestCase {
 	 * @return void
 	 */
 	public function testSlugGenerationBeforeSave() {
-		$this->Model->Behaviors->unload('Slugged');
+		$this->Model->Behaviors->unload('Tools.Slugged');
 		$this->Model->Behaviors->load('Tools.Slugged', array(
 			'run' => 'beforeSave', 'overwrite' => true));
 
@@ -147,7 +147,7 @@ class SluggedBehaviorTest extends CakeTestCase {
 	 * @return void
 	 */
 	public function testSlugGenerationI18nReplacementPieces() {
-		$this->Model->Behaviors->unload('Slugged');
+		$this->Model->Behaviors->unload('Tools.Slugged');
 		$this->Model->Behaviors->load('Tools.Slugged', array(
 			'overwrite' => true));
 
@@ -162,7 +162,7 @@ class SluggedBehaviorTest extends CakeTestCase {
 	 * @return void
 	 */
 	public function testSlugDynamicOverwrite() {
-		$this->Model->Behaviors->unload('Slugged');
+		$this->Model->Behaviors->unload('Tools.Slugged');
 		$this->Model->Behaviors->load('Tools.Slugged', array(
 			'overwrite' => false, 'overwriteField' => 'overwrite_my_slug'));
 
@@ -186,7 +186,7 @@ class SluggedBehaviorTest extends CakeTestCase {
 	 * @return void
 	 */
 	public function testSlugGenerationWithScope() {
-		$this->Model->Behaviors->unload('Slugged');
+		$this->Model->Behaviors->unload('Tools.Slugged');
 		$this->Model->Behaviors->load('Tools.Slugged', array('unique' => true));
 
 		$data = array('name' => 'Some Article 12345', 'section' => 0);
@@ -201,7 +201,7 @@ class SluggedBehaviorTest extends CakeTestCase {
 		$this->assertTrue((bool)$result);
 		$this->assertEquals('Some-Article-12345-1', $result[$this->Model->alias]['slug']);
 
-		$this->Model->Behaviors->unload('Slugged');
+		$this->Model->Behaviors->unload('Tools.Slugged');
 		$this->Model->Behaviors->load('Tools.Slugged', array('unique' => true, 'scope' => array('section' => 1)));
 
 		$data = array('name' => 'Some Article 12345', 'section' => 1);
@@ -213,50 +213,6 @@ class SluggedBehaviorTest extends CakeTestCase {
 	}
 
 	/**
-	 * Test remove stop words
-	 */
-	public function testRemoveStopWords() {
-		$this->skipIf(true, 'Does not work anymore');
-
-		$skip = false;
-		$lang = Configure::read('Config.language');
-		if (!$lang) {
-			$lang = 'eng';
-		}
-		if (
-			!App::import('Vendor', 'stop_words_' . $lang, array('file' => "stop_words" . DS . "$lang.txt")) &&
-			!App::import('Vendor', 'Tools.stop_words_' . $lang, array('file' => "stop_words" . DS . "$lang.txt"))
-		) {
-			$skip = true;
-		}
-		$this->skipIf($skip, 'no stop_words/' . $lang . '.txt file found');
-
-		$array = $this->Model->removeStopWords('My name is Michael Paine, and I am a nosey neighbour');
-		$expected = array(
-			'Michael Paine',
-			'nosey neighbour'
-		);
-		$this->assertEquals($expected, $array);
-
-		$wordList = $this->Model->removeStopWords('My name is Michael Paine, and I am a nosey neighbour', array(
-			'splitOnStopWord' => false
-		));
-		$expected = array(
-			'Michael',
-			'Paine',
-			'nosey',
-			'neighbour',
-		);
-		$this->assertEquals($expected, array_values($wordList));
-
-		$string = $this->Model->removeStopWords('My name is Michael Paine, and I am a nosey neighbour', array(
-			'return' => 'string'
-		));
-		$expected = 'Michael Paine nosey neighbour';
-		$this->assertEquals($expected, $string);
-	}
-
-	/**
 	 * TestBuildRegex method
 	 *
 	 * This 'test' is used to compare with the existing, and to optimize the regex pattern
@@ -396,7 +352,7 @@ class SluggedBehaviorTest extends CakeTestCase {
 		$modes = array('id'); // overriden
 		$this->Socket = new HttpSocket('http://validator.w3.org:80');
 		foreach ($modes as $mode) {
-			$this->Model->Behaviors->load('Slugged', array('mode' => $mode));
+			$this->Model->Behaviors->load('Tools.Slugged', array('mode' => $mode));
 			$this->_testMode($mode, 1, 1); // overriden parameters
 		}
 	}
@@ -17995,7 +17951,7 @@ class SluggedBehaviorTest extends CakeTestCase {
 	 * @return void
 	 */
 	public function testUrlMode() {
-		$this->Model->Behaviors->load('Slugged', array('mode' => 'url', 'replace' => false));
+		$this->Model->Behaviors->load('Tools.Slugged', array('mode' => 'url', 'replace' => false));
 		$string = 'standard string';
 		$expects = 'standard-string';
 		$result = $this->Model->slug($string);
@@ -18118,7 +18074,7 @@ class SluggedBehaviorTest extends CakeTestCase {
 		$encoding = Configure::read('App.encoding');
 		Configure::write('App.encoding', 'UTF-8');
 
-		$this->Model->Behaviors->load('Slugged', array('length' => 50));
+		$this->Model->Behaviors->load('Tools.Slugged', array('length' => 50));
 		$result = $this->Model->slug('モデルのデータベースとデータソース');
 		$expects = 'モデルのデータベースとデータソー';
 		$this->assertEquals($expects, $result);
@@ -18126,12 +18082,12 @@ class SluggedBehaviorTest extends CakeTestCase {
 		Configure::write('App.encoding', 'SJIS');
 		$sjisEncoded = mb_convert_encoding($testString, 'SJIS', 'UTF-8');
 
-		$this->Model->Behaviors->load('Slugged', array('length' => 33));
+		$this->Model->Behaviors->load('Tools.Slugged', array('length' => 33));
 		$result = $this->Model->slug($sjisEncoded);
 		$sjisExpects = mb_convert_encoding('モデルのデータベースとデータソー', 'SJIS', 'UTF-8');
 		$this->assertEquals($result, $sjisExpects);
 
-		$this->Model->Behaviors->load('Slugged', array('length' => 50, 'encoding' => 'UTF-8'));
+		$this->Model->Behaviors->load('Tools.Slugged', array('length' => 50, 'encoding' => 'UTF-8'));
 		$result = $this->Model->slug($sjisEncoded);
 		$expects = 'モデルのデータベースとデータソー';
 		$this->assertEquals($expects, $result);
@@ -18147,7 +18103,7 @@ class SluggedBehaviorTest extends CakeTestCase {
 	 * @return void
 	 */
 	public function testDuplicateWithLengthRestriction() {
-		$this->Model->Behaviors->load('Slugged', array('label' => 'name', 'length' => 10, 'unique' => true));
+		$this->Model->Behaviors->load('Tools.Slugged', array('label' => 'name', 'length' => 10, 'unique' => true));
 
 		$this->Model->create();
 		$this->Model->save(array('name' => 'Andy Dawson'));
@@ -18193,6 +18149,24 @@ class SluggedBehaviorTest extends CakeTestCase {
 		$this->assertEquals($expects, $result);
 	}
 
+	/**
+	 * Ensure that you can overwrite length.
+	 *
+	 * @return void
+	 */
+	public function testLengthRestrictions() {
+		// Based on auto-detect of schema
+		$this->Model->create();
+		$result = $this->Model->save(array('name' => str_repeat('foo bar ', 100)));
+		$this->assertEquals(255, strlen($result['MessageSlugged']['slug']));
+
+		// No limit desired
+		$this->Model->Behaviors->load('Tools.Slugged', array('length' => 0, 'label' => 'name', 'unique' => true));
+		$this->Model->create();
+		$result = $this->Model->save(array('name' => str_repeat('foo bar ', 100)));
+		$this->assertEquals(799, strlen($result['MessageSlugged']['slug']));
+	}
+
 }
 
 /**