Browse Source

Add test for overwrite and no title present.

mscherer 1 year ago
parent
commit
0da38f2080

+ 81 - 67
src/Model/Behavior/SluggedBehavior.php

@@ -221,18 +221,32 @@ class SluggedBehavior extends Behavior {
 		if (!$overwrite && $entity->get($this->_config['overwriteField'])) {
 			$overwrite = true;
 		}
-		if ($overwrite || $entity->isNew() || !$entity->get($this->_config['field'])) {
-			$pieces = [];
-			foreach ((array)$this->_config['label'] as $v) {
-				$v = $entity->get($v);
-				if ($v !== null && $v !== '') {
-					$pieces[] = $v;
-				}
+		if (!$overwrite && !$entity->isNew() && $entity->get($this->_config['field'])) {
+			return;
+		}
+
+		$pieces = [];
+		$atLeastOneLabelFieldExists = false;
+		foreach ((array)$this->_config['label'] as $v) {
+			if ($entity->has($v)) {
+				$atLeastOneLabelFieldExists = true;
+			}
+			$v = $entity->get($v);
+			if ($v !== null && $v !== '') {
+				$pieces[] = $v;
 			}
-			$slug = implode($this->_config['separator'], $pieces);
-			$slug = $this->generateSlug($slug, $entity);
-			$entity->set($this->_config['field'], $slug);
 		}
+
+		if (!$atLeastOneLabelFieldExists) {
+			return;
+		}
+		if (!$pieces && !$this->needsSlugUpdate($entity)) {
+			return;
+		}
+
+		$slug = implode($this->_config['separator'], $pieces);
+		$slug = $this->generateSlug($slug, $entity);
+		$entity->set($this->_config['field'], $slug);
 	}
 
 	/**
@@ -263,6 +277,63 @@ class SluggedBehavior extends Behavior {
 	}
 
 	/**
+	 * ResetSlugs method.
+	 *
+	 * Regenerate all slugs. On large dbs this can take more than 30 seconds - a time
+	 * limit is set to allow a minimum 100 updates per second as a preventative measure.
+	 *
+	 * Note that you should use the Reset behavior if you need additional functionality such
+	 * as callbacks or timeouts.
+	 *
+	 * @param array<string, mixed> $params
+	 * @throws \RuntimeException
+	 * @return bool Success
+	 */
+	public function resetSlugs($params = []) {
+		if (!$this->_table->hasField($this->_config['field'])) {
+			throw new RuntimeException('Table does not have field ' . $this->_config['field']);
+		}
+		/** @var string $displayField */
+		$displayField = $this->_table->getDisplayField();
+		$defaults = [
+			'page' => 1,
+			'limit' => 100,
+			'fields' => array_merge([$this->_table->getPrimaryKey()], $this->_config['label']),
+			'order' => $displayField . ' ASC',
+			'conditions' => $this->_config['scope'],
+			'overwrite' => true,
+		];
+		$params += $defaults;
+
+		$conditions = $params['conditions'];
+		$count = $this->_table->find('all', compact('conditions'))->count();
+		$max = (int)ini_get('max_execution_time');
+		if ($max) {
+			set_time_limit(max($max, $count / 100));
+		}
+
+		$this->setConfig($params, null, false);
+		while (($records = $this->_table->find('all', $params)->toArray())) {
+			/** @var \Cake\ORM\Entity $record */
+			foreach ($records as $record) {
+				$record->setNew(true);
+
+				$fields = array_merge([$this->_table->getPrimaryKey(), $this->_config['field']], $this->_config['label']);
+				$options = [
+					'validate' => true,
+					'fields' => $fields,
+				];
+				if (!$this->_table->save($record, $options)) {
+					throw new RuntimeException(print_r($record->getErrors(), true));
+				}
+			}
+			$params['page']++;
+		}
+
+		return true;
+	}
+
+	/**
 	 * Slug method
 	 *
 	 * For the given string, generate a slug. The replacements used are based on the mode setting, If tidy is false
@@ -371,63 +442,6 @@ class SluggedBehavior extends Behavior {
 	}
 
 	/**
-	 * ResetSlugs method.
-	 *
-	 * Regenerate all slugs. On large dbs this can take more than 30 seconds - a time
-	 * limit is set to allow a minimum 100 updates per second as a preventative measure.
-	 *
-	 * Note that you should use the Reset behavior if you need additional functionality such
-	 * as callbacks or timeouts.
-	 *
-	 * @param array<string, mixed> $params
-	 * @throws \RuntimeException
-	 * @return bool Success
-	 */
-	public function resetSlugs($params = []) {
-		if (!$this->_table->hasField($this->_config['field'])) {
-			throw new RuntimeException('Table does not have field ' . $this->_config['field']);
-		}
-		/** @var string $displayField */
-		$displayField = $this->_table->getDisplayField();
-		$defaults = [
-			'page' => 1,
-			'limit' => 100,
-			'fields' => array_merge([$this->_table->getPrimaryKey()], $this->_config['label']),
-			'order' => $displayField . ' ASC',
-			'conditions' => $this->_config['scope'],
-			'overwrite' => true,
-		];
-		$params += $defaults;
-
-		$conditions = $params['conditions'];
-		$count = $this->_table->find('all', compact('conditions'))->count();
-		$max = (int)ini_get('max_execution_time');
-		if ($max) {
-			set_time_limit(max($max, $count / 100));
-		}
-
-		$this->setConfig($params, null, false);
-		while (($records = $this->_table->find('all', $params)->toArray())) {
-			/** @var \Cake\ORM\Entity $record */
-			foreach ($records as $record) {
-				$record->setNew(true);
-
-				$fields = array_merge([$this->_table->getPrimaryKey(), $this->_config['field']], $this->_config['label']);
-				$options = [
-					'validate' => true,
-					'fields' => $fields,
-				];
-				if (!$this->_table->save($record, $options)) {
-					throw new RuntimeException(print_r($record->getErrors(), true));
-				}
-			}
-			$params['page']++;
-		}
-
-		return true;
-	}
-
-	/**
 	 * Multi slug method
 	 *
 	 * Handle both slug and label fields using the translate behavior, and being edited

+ 21 - 2
tests/TestCase/Model/Behavior/SluggedBehaviorTest.php

@@ -178,8 +178,6 @@ class SluggedBehaviorTest extends TestCase {
 	}
 
 	/**
-	 * Tests needSlugUpdate()
-	 *
 	 * @return void
 	 */
 	public function testNeedsSlugUpdate() {
@@ -229,6 +227,27 @@ class SluggedBehaviorTest extends TestCase {
 	}
 
 	/**
+	 * @return void
+	 */
+	public function testNeedsNoSlugUpdate() {
+		$entity = $this->articles->newEntity(['title' => 'Some title']);
+		$result = $this->articles->save($entity);
+		$this->assertEquals('Some-title', $result->get('slug'));
+
+		$entity = $this->articles->get($entity->id, ['fields' => ['id', 'slug']]);
+
+		$this->articles->behaviors()->Slugged->setConfig(['overwrite' => true]);
+		// Without title present it should not modify the slug
+		$entity = $this->articles->patchEntity($entity, ['foo' => 'bar']);
+		$result = $this->articles->needsSlugUpdate($entity);
+		$this->assertFalse($result);
+
+		$this->articles->saveOrFail($entity);
+		$entity = $this->articles->get($entity->id);
+		$this->assertEquals('Some-title', $entity->get('slug'));
+	}
+
+	/**
 	 * Tests needSlugUpdate() with deep
 	 *
 	 * @return void