Browse Source

Adding ability to ExtractTask to inspect models and extract the validation messages from them

Jose Lorenzo Rodriguez 15 years ago
parent
commit
93ac47fa60

+ 67 - 0
lib/Cake/Console/Command/Task/ExtractTask.php

@@ -98,6 +98,13 @@ class ExtractTask extends Shell {
 	protected $_exclude = array();
 
 /**
+ * Holds whether this call should extract model validation messages
+ *
+ * @var boolean
+ */
+	protected $_extractValidation = true;
+
+/**
  * Execution method always used for tasks
  *
  * @return void
@@ -137,6 +144,10 @@ class ExtractTask extends Shell {
 			$this->_exclude = array_merge($this->_exclude, App::path('plugins'));
 		}
 
+		if (!empty($this->params['ignore-model-validation']) || !$this->_isExtractingApp()) {
+			$this->_extractValidation = false;
+		}
+
 		if (isset($this->params['output'])) {
 			$this->_output = $this->params['output'];
 		} else {
@@ -188,10 +199,12 @@ class ExtractTask extends Shell {
 		$this->out(__d('cake_console', 'Output Directory: ') . $this->_output);
 		$this->hr();
 		$this->_extractTokens();
+		$this->_extractValidationMessages();
 		$this->_buildFiles();
 		$this->_writeFiles();
 		$this->_paths = $this->_files = $this->_storage = array();
 		$this->_strings = $this->_tokens = array();
+		$this->_extractValidation = true;
 		$this->out();
 		$this->out(__d('cake_console', 'Done.'));
 	}
@@ -311,6 +324,60 @@ class ExtractTask extends Shell {
 	}
 
 /**
+ * Looks for models in the application and extracts the validation messages
+ * to be added to the translation map
+ *
+ * @return void
+ */
+	protected function _extractValidationMessages() {
+		if (!$this->_extractValidation) {
+			return;
+		}
+		$models = App::objects('Model');
+		App::uses('AppModel', 'Model');
+		foreach ($models as $model) {
+			App::uses($model, 'Model');
+			$reflection = new ReflectionClass($model);
+			$properties = $reflection->getDefaultProperties();
+			$validate = $properties['validate'];
+			if (empty($validate)) {
+				continue;
+			}
+			$file = $reflection->getFileName();
+			$domain = 'default';
+			foreach ($validate as $field => $rules) {
+				$this->_processValidationRules($field, $rules, $file, $domain);
+			}
+		}
+	}
+
+/**
+ * Process a validation rule for a field and looks for a message to be added
+ * to the translation map
+ *
+ * @param string $field the name of the field that is being processed
+ * @param array $rules the set of validation rules for the field
+ * @param string $file the file name where this validation rule was found
+ * @param string domain default domain to bind the validations to
+ * @return void
+ */
+	protected function _processValidationRules($field, $rules, $file, $domain) {
+		if (is_array($rules)) {
+
+			$dims = Set::countDim($rules);
+			if ($dims == 1 || ($dims == 2 && isset($rules['message']))) {
+				$rules = array($rules);
+			}
+
+			foreach ($rules as $rule => $validateProp) {
+				if (isset($validateProp['message'])) {
+					$this->_strings[$domain][$validateProp['message']][$file][] = 'validation for field ' . $field;
+				}
+			}
+		}
+	}
+
+/**
  * Build the translate template file contents out of obtained strings
  *
  * @return void

+ 43 - 5
lib/Cake/Test/Case/Console/Command/Task/ExtractTaskTest.php

@@ -209,19 +209,16 @@ class ExtractTaskTest extends CakeTestCase {
  * @return void
  */
 	public function testExtractExcludePlugins() {
-		$this->Task->params['paths'] = array(
-			CAKE . 'Test' . DS . 'test_app'
-		);
 		App::build(array(
 			'plugins' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
 		));
 		$this->out = $this->getMock('ConsoleOutput', array(), array(), '', false);
 		$this->in = $this->getMock('ConsoleInput', array(), array(), '', false);
 		$this->Task = $this->getMock('ExtractTask',
-			array('_isExtractingApp', 'in', 'out', 'err', 'clear', '_stop'),
+			array('_isExtractingApp', '_extractValidationMessages', 'in', 'out', 'err', 'clear', '_stop'),
 			array($this->out, $this->out, $this->in)
 		);
-		$this->Task->expects($this->once())->method('_isExtractingApp')->will($this->returnValue(true));
+		$this->Task->expects($this->exactly(2))->method('_isExtractingApp')->will($this->returnValue(true));
 
 		$this->Task->params['paths'] = CAKE . 'Test' . DS . 'test_app' . DS;
 		$this->Task->params['output'] = $this->path . DS;
@@ -231,4 +228,45 @@ class ExtractTaskTest extends CakeTestCase {
 		$result = file_get_contents($this->path . DS . 'default.pot');
 		$this->assertNoPattern('#TesPlugin#', $result);
 	}
+
+/**
+ * Tests that the task will inspect application models and extract the validation messages from them
+ *
+ * @return void
+ */
+	public function testExtractModelValidation() {
+		App::build(array(
+			'Model' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS)
+		));
+		$this->out = $this->getMock('ConsoleOutput', array(), array(), '', false);
+		$this->in = $this->getMock('ConsoleInput', array(), array(), '', false);
+		$this->Task = $this->getMock('ExtractTask',
+			array('_isExtractingApp', 'in', 'out', 'err', 'clear', '_stop'),
+			array($this->out, $this->out, $this->in)
+		);
+		$this->Task->expects($this->exactly(2))->method('_isExtractingApp')->will($this->returnValue(true));
+
+		$this->Task->params['paths'] = CAKE . 'Test' . DS . 'test_app' . DS;
+		$this->Task->params['output'] = $this->path . DS;
+		$this->Task->params['exclude-plugins'] = true;
+		$this->Task->params['ignore-model-validation'] = false;
+
+		$this->Task->execute();
+		$result = file_get_contents($this->path . DS . 'default.pot');
+
+		$pattern = '#Model/Post.php:validation for field title#';
+		$this->assertPattern($pattern, $result);
+
+		$pattern = '#Model/Post.php:validation for field body#';
+		$this->assertPattern($pattern, $result);
+
+		$pattern = '#msgid "Post title is required"#';
+		$this->assertPattern($pattern, $result);
+
+		$pattern = '#msgid "Post body is required"#';
+		$this->assertPattern($pattern, $result);
+
+		$pattern = '#msgid "Post body is super required"#';
+		$this->assertPattern($pattern, $result);
+	}
 }

+ 22 - 0
lib/Cake/Test/test_app/Model/Post.php

@@ -21,4 +21,26 @@
 class Post extends AppModel {
 	public $useTable = 'posts';
 	public $name = 'Post';
+	public $validate = array(
+		'title' => array(
+			'rule' => array('custom', '.*'),
+			'allowEmpty' => true,
+			'required' => false,
+			'message' => 'Post title is required'
+		),
+		'body' => array(
+			'first_rule' => array(
+				'rule' => array('custom', '.*'),
+				'allowEmpty' => true,
+				'required' => false,
+				'message' => 'Post body is required'
+			),
+			'second_rule' => array(
+				'rule' => array('custom', '.*'),
+				'allowEmpty' => true,
+				'required' => false,
+				'message' => 'Post body is super required'
+			)
+		),
+	);
 }