Browse Source

Merge branch 'master' into 3.next

Mark Story 9 years ago
parent
commit
a8b93c75f8

+ 1 - 1
src/Http/Client.php

@@ -200,7 +200,7 @@ class Client
     public function get($url, $data = [], array $options = [])
     {
         $options = $this->_mergeOptions($options);
-        $body = [];
+        $body = null;
         if (isset($data['_content'])) {
             $body = $data['_content'];
             unset($data['_content']);

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

@@ -271,25 +271,49 @@ class TranslateBehavior extends Behavior implements PropertyMarshalInterface
 
         $this->_bundleTranslatedFields($entity);
         $bundled = $entity->get('_i18n') ?: [];
+        $noBundled = count($bundled) === 0;
 
-        if ($locale === $this->config('defaultLocale')) {
+        // No additional translation records need to be saved,
+        // as the entity is in the default locale.
+        if ($noBundled && $locale === $this->config('defaultLocale')) {
             return;
         }
 
         $values = $entity->extract($this->_config['fields'], true);
         $fields = array_keys($values);
+        $noFields = empty($fields);
 
-        if (empty($fields)) {
+        if ($noFields && $noBundled) {
             return;
         }
 
         $primaryKey = (array)$this->_table->primaryKey();
         $key = $entity->get(current($primaryKey));
-        $model = $this->_config['referenceName'];
 
+        // When we have no key and bundled translations, we
+        // need to mark the entity dirty so the root
+        // entity persists.
+        if ($noFields && $bundled && !$key) {
+            foreach ($this->_config['fields'] as $field) {
+                $entity->dirty($field, true);
+            }
+
+            return;
+        }
+
+        if ($noFields) {
+            return;
+        }
+
+        $model = $this->_config['referenceName'];
         $preexistent = $this->_translationTable->find()
             ->select(['id', 'field'])
-            ->where(['field IN' => $fields, 'locale' => $locale, 'foreign_key' => $key, 'model' => $model])
+            ->where([
+                'field IN' => $fields,
+                'locale' => $locale,
+                'foreign_key' => $key,
+                'model' => $model
+            ])
             ->bufferResults(false)
             ->indexBy('field');
 

+ 1 - 1
src/Routing/Route/Route.php

@@ -349,7 +349,7 @@ class Route
         if (empty($this->_extensions)) {
             return [$url, null];
         }
-        preg_match('/\.([0-9a-z]*)$/', $url, $match);
+        preg_match('/\.([0-9a-z\.]*)$/', $url, $match);
         if (empty($match[1])) {
             return [$url, null];
         }

+ 3 - 1
src/View/JsonView.php

@@ -135,7 +135,9 @@ class JsonView extends SerializedView
     {
         $data = $this->_dataToSerialize($serialize);
 
-        $jsonOptions = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT;
+        $jsonOptions = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT |
+            JSON_ERROR_INF_OR_NAN | JSON_PARTIAL_OUTPUT_ON_ERROR;
+
         if (isset($this->viewVars['_jsonOptions'])) {
             if ($this->viewVars['_jsonOptions'] === false) {
                 $jsonOptions = 0;

+ 2 - 0
src/View/View.php

@@ -67,6 +67,8 @@ use RuntimeException;
  * @property \Cake\View\Helper\TimeHelper $Time
  * @property \Cake\View\Helper\UrlHelper $Url
  * @property \Cake\View\ViewBlock $Blocks
+ * @property string $view
+ * @property string $viewPath
  */
 class View implements EventDispatcherInterface
 {

+ 34 - 0
tests/TestCase/Http/ClientTest.php

@@ -194,6 +194,40 @@ class ClientTest extends TestCase
     }
 
     /**
+     * test get request with no data
+     *
+     * @return void
+     */
+    public function testGetNoData()
+    {
+        $response = new Response();
+
+        $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
+            ->setMethods(['send'])
+            ->getMock();
+        $mock->expects($this->once())
+            ->method('send')
+            ->with($this->callback(function ($request) {
+                $this->assertEquals(Request::METHOD_GET, $request->getMethod());
+                $this->assertEmpty($request->getHeaderLine('Content-Type'), 'Should have no content-type set');
+                $this->assertEquals(
+                    'http://cakephp.org/search',
+                    $request->getUri() . ''
+                );
+
+                return true;
+            }))
+            ->will($this->returnValue([$response]));
+
+        $http = new Client([
+            'host' => 'cakephp.org',
+            'adapter' => $mock
+        ]);
+        $result = $http->get('/search');
+        $this->assertSame($result, $response);
+    }
+
+    /**
      * test get request with querystring data
      *
      * @return void

+ 72 - 0
tests/TestCase/ORM/Behavior/TranslateBehaviorTest.php

@@ -45,6 +45,7 @@ class TranslateBehaviorTest extends TestCase
     public $fixtures = [
         'core.articles',
         'core.authors',
+        'core.groups',
         'core.special_tags',
         'core.tags',
         'core.comments',
@@ -1144,6 +1145,77 @@ class TranslateBehaviorTest extends TestCase
     }
 
     /**
+     * Tests adding new translation to a record where the only field is the translated one and it's not the default locale
+     *
+     * @return void
+     */
+    public function testSaveNewRecordWithOnlyTranslationsNotDefaultLocale()
+    {
+        $table = TableRegistry::get('Groups');
+        $table->addBehavior('Translate', [
+            'fields' => ['title'],
+            'validator' => (new \Cake\Validation\Validator)->add('title', 'notBlank', ['rule' => 'notBlank'])
+        ]);
+
+        $data = [
+            '_translations' => [
+                'es' => [
+                    'title' => 'Title ES'
+                ]
+            ]
+        ];
+
+        $group = $table->newEntity($data);
+        $result = $table->save($group);
+        $this->assertNotFalse($result, 'Record should save.');
+
+        $expected = [
+            [
+                'es' => [
+                    'title' => 'Title ES',
+                    'locale' => 'es'
+                ]
+            ]
+        ];
+        $result = $table->find('translations')->where(['id' => $result->id]);
+        $this->assertEquals($expected, $this->_extractTranslations($result)->toArray());
+    }
+
+    /**
+     * Test that existing records can be updated when only translations
+     * are modified/dirty.
+     *
+     * @return void
+     */
+    public function testSaveExistingRecordOnlyTranslations()
+    {
+        $table = TableRegistry::get('Articles');
+        $table->addBehavior('Translate', ['fields' => ['title', 'body']]);
+        $table->entityClass(__NAMESPACE__ . '\Article');
+
+        $data = [
+            '_translations' => [
+                'es' => [
+                    'title' => 'Spanish Translation',
+                ],
+            ]
+        ];
+
+        $article = $table->find()->first();
+        $article = $table->patchEntity($article, $data);
+
+        $this->assertNotFalse($table->save($article));
+
+        $results = $this->_extractTranslations(
+            $table->find('translations')->where(['id' => 1])
+        )->first();
+
+        $this->assertArrayHasKey('es', $results, 'New translation added');
+        $this->assertArrayHasKey('eng', $results, 'Old translations present');
+        $this->assertEquals('Spanish Translation', $results['es']['title']);
+    }
+
+    /**
      * Test update entity with _translations field.
      *
      * @return void

+ 11 - 1
tests/TestCase/Routing/Route/RouteTest.php

@@ -109,7 +109,7 @@ class RouteTest extends TestCase
         $result = $route->parse('/posts/index.pdf', 'GET');
         $this->assertFalse(isset($result['_ext']));
 
-        $route->extensions(['pdf', 'json', 'xml']);
+        $route->extensions(['pdf', 'json', 'xml', 'xml.gz']);
         $result = $route->parse('/posts/index.pdf', 'GET');
         $this->assertEquals('pdf', $result['_ext']);
 
@@ -118,6 +118,9 @@ class RouteTest extends TestCase
 
         $result = $route->parse('/posts/index.xml', 'GET');
         $this->assertEquals('xml', $result['_ext']);
+
+        $result = $route->parse('/posts/index.xml.gz', 'GET');
+        $this->assertEquals('xml.gz', $result['_ext']);
     }
 
     /**
@@ -619,6 +622,13 @@ class RouteTest extends TestCase
             'c' => 'd'
         ]);
         $this->assertEquals('/posts/view/1.json?id=b&c=d', $result);
+
+        $result = $route->match([
+            'controller' => 'posts',
+            'action' => 'index',
+            '_ext' => 'json.gz',
+        ]);
+        $this->assertEquals('/posts/index.json.gz', $result);
     }
 
     /**

+ 25 - 5
tests/TestCase/View/JsonViewTest.php

@@ -39,7 +39,7 @@ class JsonViewTest extends TestCase
      *
      * Note: array($data, $serialize, expected)
      *
-     * @return void
+     * @return array
      */
     public static function renderWithoutViewProvider()
     {
@@ -203,12 +203,32 @@ class JsonViewTest extends TestCase
                 JSON_HEX_TAG | JSON_HEX_APOS,
                 json_encode('<tag> \'quote\' "double-quote" &', JSON_HEX_TAG | JSON_HEX_APOS)
             ],
+
+            // Test render of NAN
+            [
+                ['value' => NAN],
+                true,
+                null,
+                '{"value":0}'
+            ],
+
+            // Test render of INF
+            [
+                ['value' => INF],
+                true,
+                null,
+                '{"value":0}'
+            ],
         ];
     }
 
     /**
      * Test render with a valid string in _serialize.
      *
+     * @param array $data
+     * @param string|null $serialize
+     * @param int|bool|null $jsonOptions
+     * @param string $expected
      * @dataProvider renderWithoutViewProvider
      * @return void
      */
@@ -221,7 +241,7 @@ class JsonViewTest extends TestCase
         $Controller->set($data);
         $Controller->set('_serialize', $serialize);
         $Controller->set('_jsonOptions', $jsonOptions);
-        $Controller->viewClass = 'Json';
+        $Controller->viewBuilder()->className('Json');
         $View = $Controller->createView();
         $output = $View->render(false);
 
@@ -244,7 +264,7 @@ class JsonViewTest extends TestCase
             'tags' => ['cakephp', 'framework'],
             '_serialize' => 'tags'
         ]);
-        $Controller->viewClass = 'Json';
+        $Controller->viewBuilder()->className('Json');
         $View = $Controller->createView();
         $View->render();
 
@@ -268,7 +288,7 @@ class JsonViewTest extends TestCase
             '_serialize' => 'data',
             '_jsonp' => true
         ]);
-        $Controller->viewClass = 'Json';
+        $Controller->viewBuilder()->className('Json');
         $View = $Controller->createView();
         $output = $View->render(false);
 
@@ -310,7 +330,7 @@ class JsonViewTest extends TestCase
             ]
         ];
         $Controller->set('user', $data);
-        $Controller->viewClass = 'Json';
+        $Controller->viewBuilder()->className('Json');
         $View = $Controller->createView();
         $View->viewPath = $Controller->name;
         $output = $View->render('index');