Browse Source

update translateBehavior

Albert Cansado Solà 9 years ago
parent
commit
35cff0db3d

+ 4 - 6
src/ORM/Behavior/TranslateBehavior.php

@@ -329,19 +329,17 @@ class TranslateBehavior extends Behavior
 
     /**
      * Merges `$data` into `$original` entity recursively using Marshaller merge method, if
-     * original entity is null, new one will be created.
+     * original entity not has language entity, new one will be created.
      * The translated entity may only contain the fields defined in the
      * behavior configuration (`fields`), you can use `fieldList` option as a
      * whitelist of fields to be assigned.
      *
      * The result will be and array [entities, errors]:
-     *  - entities indexed by locale name
-     *  - errors indexed by locale name
+     *  - entities: translated entity indexed by locale name
+     *  - errors: array indexed by locale name
      * or null if there are no fields to merge.
      *
-     * ## Note: Translated entity data not will be validated during merge.
-     *
-     * @param \Cake\Datasource\EntityInterface $original The original entity
+     * @param array $original The original entity data
      * @param array $data key value list of languages with fields to be merged into the translate entity
      * @param \Cake\ORM\Marshaller $marshaller Marshaller
      * @param array $options list of options for Marshaller

+ 111 - 136
tests/TestCase/ORM/Behavior/TranslateBehaviorTest.php

@@ -1069,10 +1069,15 @@ class TranslateBehaviorTest extends TestCase
         $this->assertSame($article->title, $result->title);
     }
 
+    /**
+     * Test return pair array with all translated entities and errors if occurs.
+     *
+     * @return void
+     */
     public function testMergeTranslations()
     {
         $table = TableRegistry::get('Articles');
-        $table->addBehavior('Translate', ['fields' => ['title']]);
+        $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
         $table->entityClass(__NAMESPACE__ . '\Article');
 
         $data = [
@@ -1083,38 +1088,36 @@ class TranslateBehaviorTest extends TestCase
             'es' => [
                 'title' => 'Title ES',
                 'body' => 'Body ES'
-            ],
-        ];
-
-        $marshallOptionsExpected = [
-            'validate' => false,
-            'translates' => true,
-            'fieldList' => ['title']
+            ]
         ];
 
-        $marshallMock = $this->getMockBuilder('\Cake\ORM\Marshaller')
-            ->setMethods(['merge'])
-            ->setConstructorArgs([$table])
-            ->getMock();
-        $marshallMock->expects($this->exactly(2))
-            ->method('merge')
-            ->withConsecutive(
-                [$this->isInstanceOf(__NAMESPACE__ . '\Article'), $this->equalTo($data['en']), $this->equalTo($marshallOptionsExpected)],
-                [$this->isInstanceOf(__NAMESPACE__ . '\Article'), $this->equalTo($data['es']), $this->equalTo($marshallOptionsExpected)]
-            );
-
-        $result = $table->mergeTranslations(null, $data, $marshallMock, $options = ['translates' => true]);
+        $marshaller = new \Cake\ORM\Marshaller($table);
+        $result = $table->mergeTranslations(null, $data, $marshaller, []);
 
+        $this->assertInternalType('array', $result, 'should return an array');
         $this->assertCount(2, $result);
+
+        // Entities
         $this->assertInstanceOf(__NAMESPACE__ . '\Article', $result[0]['en']);
         $this->assertInstanceOf(__NAMESPACE__ . '\Article', $result[0]['es']);
-        $this->assertEmpty($result[1]); // Error
+        $this->assertEquals($data['en'], $result[0]['en']->toArray());
+        $this->assertEquals($data['es'], $result[0]['es']->toArray());
+
+        // Errors
+        $this->assertEmpty($result[1], 'array errors should be empty');
+        $this->assertEmpty($result[0]['en']->errors());
+        $this->assertEmpty($result[0]['es']->errors());
     }
 
-    public function testMergeWithValidator()
+    /**
+     * Test method only could merge fields that are defined inside behavior's configuration
+     *
+     * @return void
+     */
+    public function testMergeTranslationsOnlyDefinedFields()
     {
         $table = TableRegistry::get('Articles');
-        $table->addBehavior('Translate', ['fields' => ['title'], 'validator' => 'custom']);
+        $table->addBehavior('Translate', ['fields' => ['title']]);
         $table->entityClass(__NAMESPACE__ . '\Article');
 
         $data = [
@@ -1125,64 +1128,22 @@ class TranslateBehaviorTest extends TestCase
             'es' => [
                 'title' => 'Title ES',
                 'body' => 'Body ES'
-            ],
-        ];
-        $marshallOptionsExpected = [
-            'validate' => 'custom',
-            'translates' => true,
-            'fieldList' => ['title']
-        ];
-
-        $marshallMock = $this->getMockBuilder('\Cake\ORM\Marshaller')
-            ->setMethods(['merge'])
-            ->setConstructorArgs([$table])
-            ->getMock();
-        $marshallMock->expects($this->exactly(2))
-            ->method('merge')
-            ->withConsecutive(
-                [$this->isInstanceOf(__NAMESPACE__ . '\Article'), $this->equalTo($data['en']), $this->equalTo($marshallOptionsExpected)],
-                [$this->isInstanceOf(__NAMESPACE__ . '\Article'), $this->equalTo($data['es']), $this->equalTo($marshallOptionsExpected)]
-            );
-
-        $table->mergeTranslations(null, $data, $marshallMock, ['translates' => true]);
-    }
-
-    public function testMergeWithFieldListOption()
-    {
-        $table = TableRegistry::get('Articles');
-        $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
-        $table->entityClass(__NAMESPACE__ . '\Article');
-
-        $data = [
-            'en' => [
-                'title' => 'Title EN',
-                'body' => 'Body EN'
             ]
         ];
-        $options = ['translates' => true, 'fieldList' => ['body', 'author_id']];
 
-        $marshallOptionsExpected = [
-            'validate' => false,
-            'translates' => true,
-            'fieldList' => [1 => 'body']
-        ];
+        $marshaller = new \Cake\ORM\Marshaller($table);
+        $result = $table->mergeTranslations(null, $data, $marshaller, []);
 
-        $marshallMock = $this->getMockBuilder('\Cake\ORM\Marshaller')
-            ->setMethods(['merge'])
-            ->setConstructorArgs([$table])
-            ->getMock();
-        $marshallMock->expects($this->exactly(1))
-            ->method('merge')
-            ->with(
-                $this->isInstanceOf(__NAMESPACE__ . '\Article'),
-                $this->equalTo($data['en']),
-                $this->equalTo($marshallOptionsExpected)
-            );
-
-        $table->mergeTranslations(null, $data, $marshallMock, $options);
+        $this->assertEquals(['title' => 'Title EN'], $result[0]['en']->toArray());
+        $this->assertEmpty($result[1], 'array errors should be empty');
     }
 
-    public function testMergeWithEmptyFieldListOption()
+    /**
+     * Test only use properties defined in fieldList option
+     *
+     * @return void
+     */
+    public function testMergeTranslationsWithFieldList()
     {
         $table = TableRegistry::get('Articles');
         $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
@@ -1192,23 +1153,26 @@ class TranslateBehaviorTest extends TestCase
             'en' => [
                 'title' => 'Title EN',
                 'body' => 'Body EN'
+            ],
+            'es' => [
+                'title' => 'Title ES',
+                'body' => 'Body ES'
             ]
         ];
-        $options = ['validate' => true, 'translates' => true, 'fieldList' => []];
-
-        $marshallMock = $this->getMockBuilder('\Cake\ORM\Marshaller')
-            ->setMethods(['merge'])
-            ->setConstructorArgs([$table])
-            ->getMock();
-        $marshallMock->expects($this->never())
-            ->method('merge');
 
-        $result = $table->mergeTranslations(null, $data, $marshallMock, $options);
+        $marshaller = new \Cake\ORM\Marshaller($table);
+        $result = $table->mergeTranslations(null, $data, $marshaller, ['fieldList' => ['body', 'author_id']]);
 
-        $this->assertNull($result);
+        $this->assertEquals(['body' => 'Body EN'], $result[0]['en']->toArray());
+        $this->assertEmpty($result[1], 'array errors should be empty');
     }
 
-    public function testMergeRealData()
+    /**
+     * Test return null when we not have properties to attach to translated entities
+     *
+     * @return void
+     */
+    public function testMergeTranslationsFieldListNotContainsFields()
     {
         $table = TableRegistry::get('Articles');
         $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
@@ -1222,90 +1186,96 @@ class TranslateBehaviorTest extends TestCase
             'es' => [
                 'title' => 'Title ES',
                 'body' => 'Body ES'
-            ],
+            ]
         ];
 
         $marshaller = new \Cake\ORM\Marshaller($table);
+        $result = $table->mergeTranslations(null, $data, $marshaller, ['fieldList' => []]);
 
-        // Merge All Fields
-        $result = $table->mergeTranslations(null, $data, $marshaller, []);
-        $this->assertEquals($data['en'], $result[0]['en']->toArray());
-        $this->assertEquals($data['es'], $result[0]['es']->toArray());
+        $this->assertNull($result[0]['en'], 'should return null instead of an entity');
+        $this->assertNull($result[0]['es'], 'should return null instead of an entity');
+        $this->assertEmpty($result[1], 'array errors should be empty');
 
-        // Only Merge Title
-        $result = $table->mergeTranslations(null, $data, $marshaller, ['fieldList' => ['title']]);
-        $this->assertArrayNotHasKey('body', $result[0]['en']->toArray());
-
-        // FieldList not has translated fields (or fieldList is empty)
         $result = $table->mergeTranslations(null, $data, $marshaller, ['fieldList' => ['author_id']]);
-        $this->assertNull($result);
+        $this->assertNull($result[0]['en'], 'should return null instead of an entity');
+        $this->assertNull($result[0]['es'], 'should return null instead of an entity');
+        $this->assertEmpty($result[1], 'array errors should be empty');
     }
 
-    public function testMergeDataWithValidator()
+    /**
+     * Test merge method generates errors during validation
+     *
+     * @return void
+     */
+    public function testMergeTranslationsErrorsWhenValidate()
     {
         $table = TableRegistry::get('Articles');
-
-        $validator = new \Cake\Validation\Validator;
-        $validator->requirePresence('title', 'create')
-            ->notEmpty('title');
-        $validator->requirePresence('body')
-            ->notEmpty('body')
-            ->add('body', [
-                'length' => [
-                    'rule' => ['minLength', 10],
-                    'message' => 'min_length_10',
-                ]
-            ]);
-
-        $table->addBehavior('Translate', ['fields' => ['title', 'body'], 'validator' => $validator]);
+        $table->addBehavior('Translate', [
+            'fields' => ['title', 'body'],
+            'validator' => (new \Cake\Validation\Validator)->add('title', 'notBlank', ['rule' => 'notBlank'])
+        ]);
         $table->entityClass(__NAMESPACE__ . '\Article');
 
         $data = [
             'en' => [
-                'title' => '',
-                'body' => 'Very Looong Body EN'
+                'title' => 'Title EN',
+                'body' => 'Body EN'
             ],
             'es' => [
-                'title' => 'Title ES',
+                'title' => '',
                 'body' => 'Body ES'
-            ],
+            ]
         ];
 
         $marshaller = new \Cake\ORM\Marshaller($table);
+        $result = $table->mergeTranslations(null, $data, $marshaller, []);
 
-        // Fails Title (en) and Body (es)
+        // Entity
+        $this->assertEmpty($result[0]['en']->errors());
+        $this->assertEquals($data['en'], $result[0]['en']->toArray());
+
+        $this->assertNotEmpty($result[0]['es']->errors());
+        $this->assertArrayHasKey('title', $result[0]['es']->invalid());
+        $this->assertEquals(['body' => 'Body ES'], $result[0]['es']->toArray());
+
+        // Errors
         $expectedErrors = [
-            'en' => [
-                'title' => ['_empty' => 'This field cannot be left empty']
-            ],
             'es' => [
-                'body' => ['length' => 'min_length_10']
+                'title' => [
+                    '_empty' => 'This field cannot be left empty'
+                ]
             ]
         ];
+        $this->assertEquals($expectedErrors, $result[1], 'it should be have errors');
+
+        // All title props are empty
+        $data['en']['title'] = '';
+
         $result = $table->mergeTranslations(null, $data, $marshaller, []);
-        $this->assertEquals($expectedErrors, $result[1]);
-        $this->assertArrayHasKey('title', $result[0]['en']->invalid());
 
-        // Add title to en language
-        $data['en']['title'] = 'Title EN';
-        $expectedErrors = [
-            'es' => [
-                'body' => ['length' => 'min_length_10']
+        $this->assertEquals(['body' => 'Body EN'], $result[0]['en']->toArray());
+        $this->assertEquals(['body' => 'Body ES'], $result[0]['es']->toArray());
+
+        $expectedErrors['en'] = [
+            'title' => [
+                '_empty' => 'This field cannot be left empty'
             ]
         ];
-        $result = $table->mergeTranslations(null, $data, $marshaller, []);
-        $this->assertEquals($expectedErrors, $result[1]);
-
-        // All Fields are ok
-        $data['es']['body'] = 'Very Looong Body ES';
-        $result = $table->mergeTranslations(null, $data, $marshaller, []);
-        $this->assertEmpty($result[1]);
+        $this->assertEquals($expectedErrors, $result[1], 'it should be have errors');
     }
 
+    /**
+     * Test save new entity with _translations field
+     *
+     * @return void
+     */
     public function testSaveNewRecordWithTranslatesField()
     {
         $table = TableRegistry::get('Articles');
-        $table->addBehavior('Translate', ['fields' => ['title']]);
+        $table->addBehavior('Translate', [
+            'fields' => ['title'],
+            'validator' => (new \Cake\Validation\Validator)->add('title', 'notBlank', ['rule' => 'notBlank'])
+        ]);
         $table->entityClass(__NAMESPACE__ . '\Article');
 
         $data = [
@@ -1343,6 +1313,11 @@ class TranslateBehaviorTest extends TestCase
         $this->assertEquals($expected, $this->_extractTranslations($result)->toArray());
     }
 
+    /**
+     * Test update entity with _translations field.
+     *
+     * @return void
+     */
     public function testSaveExistingRecordWithTranslatesField()
     {
         $table = TableRegistry::get('Articles');