Browse Source

Merge branch 'master' into 3.next

Mark Story 8 years ago
parent
commit
1e66a79b99

+ 26 - 23
src/Http/ServerRequestFactory.php

@@ -156,49 +156,52 @@ abstract class ServerRequestFactory extends BaseFactory
             'webroot' => null,
             'baseUrl' => null
         ];
+        $base = $config['base'];
+        $baseUrl = $config['baseUrl'];
+        $webroot = $config['webroot'];
 
-        if ($config['base'] !== false && $config['base'] !== null) {
-            return [$config['base'], $config['base'] . '/'];
+        if ($base !== false && $base !== null) {
+            return [$base, $base . '/'];
         }
 
-        if (!$config['baseUrl']) {
-            $config['base'] = dirname(Hash::get($server, 'PHP_SELF'));
+        if (!$baseUrl) {
+            $base = dirname(Hash::get($server, 'PHP_SELF'));
             // Clean up additional / which cause following code to fail..
-            $config['base'] = preg_replace('#/+#', '/', $config['base']);
+            $base = preg_replace('#/+#', '/', $base);
 
-            $indexPos = strpos($config['base'], '/' . $config['webroot'] . '/index.php');
+            $indexPos = strpos($base, '/' . $webroot . '/index.php');
             if ($indexPos !== false) {
-                $config['base'] = substr($config['base'], 0, $indexPos) . '/' . $config['webroot'];
+                $base = substr($base, 0, $indexPos) . '/' . $webroot;
             }
-            if ($config['webroot'] === basename($config['base'])) {
-                $config['base'] = dirname($config['base']);
+            if ($webroot === basename($base)) {
+                $base = dirname($base);
             }
 
-            if ($config['base'] === DIRECTORY_SEPARATOR || $config['base'] === '.') {
-                $config['base'] = '';
+            if ($base === DIRECTORY_SEPARATOR || $base === '.') {
+                $base = '';
             }
-            $config['base'] = implode('/', array_map('rawurlencode', explode('/', $config['base'])));
+            $base = implode('/', array_map('rawurlencode', explode('/', $base)));
 
-            return [$config['base'], $config['base'] . '/'];
+            return [$base, $base . '/'];
         }
 
-        $file = '/' . basename($config['baseUrl']);
-        $config['base'] = dirname($config['baseUrl']);
+        $file = '/' . basename($baseUrl);
+        $base = dirname($baseUrl);
 
-        if ($config['base'] === DIRECTORY_SEPARATOR || $config['base'] === '.') {
-            $config['base'] = '';
+        if ($base === DIRECTORY_SEPARATOR || $base === '.') {
+            $base = '';
         }
-        $webrootDir = $config['base'] . '/';
+        $webrootDir = $base . '/';
 
         $docRoot = Hash::get($server, 'DOCUMENT_ROOT');
-        $docRootContainsWebroot = strpos($docRoot, $config['webroot']);
+        $docRootContainsWebroot = strpos($docRoot, $webroot);
 
-        if (!empty($config['base']) || !$docRootContainsWebroot) {
-            if (strpos($webrootDir, '/' . $config['webroot'] . '/') === false) {
-                $webrootDir .= $config['webroot'] . '/';
+        if (!empty($base) || !$docRootContainsWebroot) {
+            if (strpos($webrootDir, '/' . $webroot . '/') === false) {
+                $webrootDir .= $webroot . '/';
             }
         }
 
-        return [$config['base'] . $file, $webrootDir];
+        return [$base . $file, $webrootDir];
     }
 }

+ 1 - 1
src/Shell/Helper/ProgressHelper.php

@@ -125,7 +125,7 @@ class ProgressHelper extends Helper
     /**
      * Render the progress bar based on the current state.
      *
-     * @return $this;
+     * @return $this
      */
     public function draw()
     {

+ 6 - 3
src/Shell/Helper/TableHelper.php

@@ -43,8 +43,8 @@ class TableHelper extends Helper
     {
         $widths = [];
         foreach ($rows as $line) {
-            foreach ($line as $k => $v) {
-                $columnLength = mb_strwidth($line[$k]);
+            foreach (array_values($line) as $k => $v) {
+                $columnLength = mb_strwidth($v);
                 if ($columnLength >= (isset($widths[$k]) ? $widths[$k] : 0)) {
                     $widths[$k] = $columnLength;
                 }
@@ -85,7 +85,7 @@ class TableHelper extends Helper
         }
 
         $out = '';
-        foreach ($row as $i => $column) {
+        foreach (array_values($row) as $i => $column) {
             $pad = $widths[$i] - mb_strwidth($column);
             if (!empty($options['style'])) {
                 $column = $this->_addStyle($column, $options['style']);
@@ -99,6 +99,9 @@ class TableHelper extends Helper
     /**
      * Output a table.
      *
+     * Data will be output based on the order of the values
+     * in the array. The keys will not be used to align data.
+     *
      * @param array $rows The data to render out.
      * @return void
      */

+ 39 - 12
src/View/Helper/FormHelper.php

@@ -1567,7 +1567,8 @@ class FormHelper extends Helper
      *    is checked
      * - `hiddenField` - boolean to indicate if you want the results of radio() to include
      *    a hidden input with a value of ''. This is useful for creating radio sets that are non-continuous.
-     * - `disabled` - Set to `true` or `disabled` to disable all the radio buttons.
+     * - `disabled` - Set to `true` or `disabled` to disable all the radio buttons. Use an array of
+     *   values to disable specific radio buttons.
      * - `empty` - Set to `true` to create an input with the value '' as the first option. When `true`
      *   the radio label will be 'empty'. Set this option to a string to control the label value.
      *
@@ -2587,17 +2588,7 @@ class FormHelper extends Helper
         if ($context->hasError($field)) {
             $options = $this->addClass($options, $this->_config['errorClass']);
         }
-        $isDisabled = false;
-        if (isset($options['disabled'])) {
-            $isDisabled = (
-                $options['disabled'] === true ||
-                $options['disabled'] === 'disabled' ||
-                (is_array($options['disabled']) &&
-                    !empty($options['options']) &&
-                    array_diff($options['options'], $options['disabled']) === []
-                )
-            );
-        }
+        $isDisabled = $this->_isDisabled($options);
         if ($isDisabled) {
             $options['secure'] = self::SECURE_SKIP;
         }
@@ -2612,6 +2603,42 @@ class FormHelper extends Helper
     }
 
     /**
+     * Determine if a field is disabled.
+     *
+     * @param array $options The option set.
+     * @return bool Whether or not the field is disabled.
+     */
+    protected function _isDisabled(array $options)
+    {
+        if (!isset($options['disabled'])) {
+            return false;
+        }
+        if (is_scalar($options['disabled'])) {
+            return ($options['disabled'] === true || $options['disabled'] === 'disabled');
+        }
+        if (!isset($options['options'])) {
+            return false;
+        }
+        if (is_array($options['options'])) {
+            // Simple list options
+            $first = $options['options'][array_keys($options['options'])[0]];
+            if (is_scalar($first)) {
+                return array_diff($options['options'], $options['disabled']) === [];
+            }
+            // Complex option types
+            if (is_array($first)) {
+                $disabled = array_filter($options['options'], function ($i) use ($options) {
+                    return in_array($i['value'], $options['disabled']);
+                });
+
+                return count($disabled) > 0;
+            }
+        }
+
+        return false;
+    }
+
+    /**
      * Get the field name for use with _secure().
      *
      * Parses the name attribute to create a dot separated name value for use

+ 32 - 2
tests/TestCase/Shell/Helper/TableHelperTest.php

@@ -58,7 +58,7 @@ class TableHelperTest extends TestCase
      *
      * @return void
      */
-    public function testDefaultOutput()
+    public function testOutputDefaultOutput()
     {
         $data = [
             ['Header 1', 'Header', 'Long Header'],
@@ -78,9 +78,39 @@ class TableHelperTest extends TestCase
     }
 
     /**
+     * Test output with inconsistent keys.
+     *
+     * When outputting entities or other structured data,
+     * headers shouldn't need to have the same keys as it is
+     * annoying to use.
+     *
+     * @return void
+     */
+    public function testOutputInconsistentKeys()
+    {
+        $data = [
+            ['Header 1', 'Header', 'Long Header'],
+            ['a' => 'short', 'b' => 'Longish thing', 'c' => 'short'],
+            ['c' => 'Longer thing', 'a' => 'short', 'b' => 'Longest Value'],
+        ];
+        $this->helper->output($data);
+        $expected = [
+            '+--------------+---------------+---------------+',
+            '| <info>Header 1</info>     | <info>Header</info>        | <info>Long Header</info>   |',
+            '+--------------+---------------+---------------+',
+            '| short        | Longish thing | short         |',
+            '| Longer thing | short         | Longest Value |',
+            '+--------------+---------------+---------------+',
+        ];
+        $this->assertEquals($expected, $this->stub->messages());
+    }
+
+    /**
      * Test that output works when data contains just empty strings.
+     *
+     * @return void
      */
-    public function testEmptyStrings()
+    public function testOutputEmptyStrings()
     {
         $data = [
             ['Header 1', 'Header', 'Empty'],

+ 31 - 0
tests/TestCase/View/Helper/FormHelperTest.php

@@ -4672,6 +4672,37 @@ class FormHelperTest extends TestCase
     }
 
     /**
+     * Test radio with complex options and empty disabled data.
+     *
+     * @return void
+     */
+    public function testRadioComplexDisabled()
+    {
+        $options = [
+            ['value' => 'r', 'text' => 'red'],
+            ['value' => 'b', 'text' => 'blue'],
+        ];
+        $attrs = ['disabled' => []];
+        $result = $this->Form->radio('Model.field', $options, $attrs);
+        $expected = [
+            'input' => ['type' => 'hidden', 'name' => 'Model[field]', 'value' => ''],
+            ['label' => ['for' => 'model-field-r']],
+            ['input' => ['type' => 'radio', 'name' => 'Model[field]', 'value' => 'r', 'id' => 'model-field-r']],
+            'red',
+            '/label',
+            ['label' => ['for' => 'model-field-b']],
+            ['input' => ['type' => 'radio', 'name' => 'Model[field]', 'value' => 'b', 'id' => 'model-field-b']],
+            'blue',
+            '/label',
+        ];
+        $this->assertHtml($expected, $result);
+
+        $attrs = ['disabled' => ['r']];
+        $result = $this->Form->radio('Model.field', $options, $attrs);
+        $this->assertContains('disabled="disabled"', $result);
+    }
+
+    /**
      * testRadioDefaultValue method
      *
      * Test default value setting on radio() method.