Browse Source

Added StringType and BoolType to better handle exceptions

Jose Lorenzo Rodriguez 10 years ago
parent
commit
1cd80f48b8

+ 7 - 10
src/Database/Type.php

@@ -34,12 +34,15 @@ class Type
     protected static $_types = [
         'biginteger' => 'Cake\Database\Type\IntegerType',
         'binary' => 'Cake\Database\Type\BinaryType',
+        'boolean' => 'Cake\Database\Type\BoolType',
         'date' => 'Cake\Database\Type\DateType',
-        'float' => 'Cake\Database\Type\FloatType',
+        'datetime' => 'Cake\Database\Type\DateTimeType',
         'decimal' => 'Cake\Database\Type\FloatType',
+        'float' => 'Cake\Database\Type\FloatType',
         'integer' => 'Cake\Database\Type\IntegerType',
+        'string' => 'Cake\Database\Type\StringType',
+        'text' => 'Cake\Database\Type\StringType',
         'time' => 'Cake\Database\Type\TimeType',
-        'datetime' => 'Cake\Database\Type\DateTimeType',
         'timestamp' => 'Cake\Database\Type\DateTimeType',
         'uuid' => 'Cake\Database\Type\UuidType',
     ];
@@ -49,6 +52,7 @@ class Type
      * for doing conversion on these
      *
      * @var array
+     * @deprecated 3.1 All types will now use a specific class
      */
     protected static $_basicTypes = [
         'string' => ['callback' => ['\Cake\Database\Type', 'strval']],
@@ -95,9 +99,6 @@ class Type
         if (isset(static::$_builtTypes[$name])) {
             return static::$_builtTypes[$name];
         }
-        if (isset(static::$_basicTypes[$name])) {
-            return static::$_builtTypes[$name] = new static($name);
-        }
         if (!isset(static::$_types[$name])) {
             throw new InvalidArgumentException(sprintf('Unknown type "%s"', $name));
         }
@@ -205,6 +206,7 @@ class Type
      *
      * @param mixed $value value to be converted to PHP equivalent
      * @return mixed
+     * @deprecated 3.1 All types should now be a specific class
      */
     protected function _basicTypeCast($value)
     {
@@ -233,11 +235,6 @@ class Type
             return PDO::PARAM_NULL;
         }
 
-        if (!empty(self::$_basicTypes[$this->_name])) {
-            $typeInfo = self::$_basicTypes[$this->_name];
-            return isset($typeInfo['pdo']) ? $typeInfo['pdo'] : PDO::PARAM_STR;
-        }
-
         return PDO::PARAM_STR;
     }
 

+ 103 - 0
src/Database/Type/BoolType.php

@@ -0,0 +1,103 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         3.1.2
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\Database\Type;
+
+use Cake\Database\Driver;
+use Cake\Database\Type;
+use InvalidArgumentException;
+use PDO;
+
+/**
+ * Bool type converter.
+ *
+ * Use to convert bool data between PHP and the database types.
+ */
+class BoolType extends Type
+{
+
+    /**
+     * Convert bool data into the database format.
+     *
+     * @param mixed $value The value to convert.
+     * @param Driver $driver The driver instance to convert with.
+     * @return bool|null
+     */
+    public function toDatabase($value, Driver $driver)
+    {
+        if ($value === true || $value === false) {
+            return $value;
+        }
+
+        if (in_array($value, [1,  0, '1', '0'], true)) {
+            return (bool)$value;
+        }
+
+        throw new InvalidArgumentException('Cannot convert value to bool');
+    }
+
+    /**
+     * Convert bool values to PHP booleans
+     *
+     * @param mixed $value The value to convert.
+     * @param Driver $driver The driver instance to convert with.
+     * @return bool|null
+     */
+    public function toPHP($value, Driver $driver)
+    {
+        if ($value === null) {
+            return null;
+        }
+        if (is_string($value) && !is_numeric($value)) {
+            return strtolower($value) === 'true' ? true : false;
+        }
+        return !empty($value);
+    }
+
+    /**
+     * Get the correct PDO binding type for bool data.
+     *
+     * @param mixed $value The value being bound.
+     * @param Driver $driver The driver.
+     * @return int
+     */
+    public function toStatement($value, Driver $driver)
+    {
+        if ($value === null) {
+            return PDO::PARAM_NULL;
+        }
+
+        return PDO::PARAM_BOOL;
+    }
+
+    /**
+     * Marshalls request data into PHP booleans.
+     *
+     * @param mixed $value The value to convert.
+     * @return mixed Converted value.
+     */
+    public function marshal($value)
+    {
+        if ($value === null) {
+            return null;
+        }
+        if ($value === 'true') {
+            return true;
+        }
+        if ($value === 'false') {
+            return false;
+        }
+        return !empty($value);
+    }
+}

+ 97 - 0
src/Database/Type/StringType.php

@@ -0,0 +1,97 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         3.1.2
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\Database\Type;
+
+use Cake\Database\Driver;
+use Cake\Database\Type;
+use InvalidArgumentException;
+use PDO;
+
+/**
+ * String type converter.
+ *
+ * Use to convert string data between PHP and the database types.
+ */
+class StringType extends Type
+{
+
+    /**
+     * Convert string data into the database format.
+     *
+     * @param mixed $value The value to convert.
+     * @param Driver $driver The driver instance to convert with.
+     * @return string|null
+     */
+    public function toDatabase($value, Driver $driver)
+    {
+        if ($value === null || is_string($value)) {
+            return $value;
+        }
+
+        if (is_object($value) && method_exists($value, '__toString')) {
+            return $value->__toString();
+        }
+
+        if (is_scalar($value)) {
+            return (string)$value;
+        }
+
+        throw new InvalidArgumentException('Cannot convert value to string');
+    }
+
+    /**
+     * Convert string values to PHP integers
+     *
+     * @param mixed $value The value to convert.
+     * @param Driver $driver The driver instance to convert with.
+     * @return string|null
+     */
+    public function toPHP($value, Driver $driver)
+    {
+        if ($value === null) {
+            return null;
+        }
+        return (string)$value;
+    }
+
+    /**
+     * Get the correct PDO binding type for string data.
+     *
+     * @param mixed $value The value being bound.
+     * @param Driver $driver The driver.
+     * @return int
+     */
+    public function toStatement($value, Driver $driver)
+    {
+        return PDO::PARAM_STR;
+    }
+
+    /**
+     * Marshalls request data into PHP floats.
+     *
+     * @param mixed $value The value to convert.
+     * @return mixed Converted value.
+     */
+    public function marshal($value)
+    {
+        if ($value === null) {
+            return null;
+        }
+        if (is_array($value)) {
+            return '';
+        }
+        return (string)$value;
+    }
+}

+ 27 - 4
tests/TestCase/Database/TypeTest.php

@@ -206,7 +206,19 @@ class TypeTest extends TestCase
         $this->assertEquals('foo', $type->toPHP($string, $driver));
         $this->assertEquals('3', $type->toPHP(3, $driver));
         $this->assertEquals('3.14159', $type->toPHP(3.14159, $driver));
-        $this->assertEquals('', $type->toPHP([3, 'elf'], $driver));
+    }
+
+    /**
+     * Tests that passing a non-scalar value will thow an exception
+     *
+     * @expectedException InvalidArgumentException
+     * @return void
+     */
+    public function testStringToDatabaseNoScalar()
+    {
+        $type = Type::build('string');
+        $driver = $this->getMock('\Cake\Database\Driver');
+        $type->toDatabase(['123'], $driver);
     }
 
     /**
@@ -235,7 +247,6 @@ class TypeTest extends TestCase
         $this->assertEquals('foo', $type->toPHP($string, $driver));
         $this->assertEquals('3', $type->toPHP(3, $driver));
         $this->assertEquals('3.14159', $type->toPHP(3.14159, $driver));
-        $this->assertEquals('', $type->toPHP([2, 3], $driver));
     }
 
     /**
@@ -252,7 +263,7 @@ class TypeTest extends TestCase
     }
 
     /**
-     * Test convertring booleans to database types.
+     * Test converting booleans to database types.
      *
      * @return void
      */
@@ -267,6 +278,18 @@ class TypeTest extends TestCase
         $this->assertFalse($type->toDatabase(0, $driver));
         $this->assertTrue($type->toDatabase('1', $driver));
         $this->assertFalse($type->toDatabase('0', $driver));
+    }
+
+    /**
+     * Test converting an array to boolean results in an exception
+     *
+     * @expectedException InvalidArgumentException
+     * @return void
+     */
+    public function testBooleanToDatabaseError()
+    {
+        $type = Type::build('boolean');
+        $driver = $this->getMock('\Cake\Database\Driver');
         $this->assertTrue($type->toDatabase([1, 2], $driver));
     }
 
@@ -325,7 +348,7 @@ class TypeTest extends TestCase
         $this->assertFalse($type->marshal('0'));
         $this->assertFalse($type->marshal(0));
         $this->assertFalse($type->marshal(''));
-        $this->assertFalse($type->marshal('invalid'));
+        $this->assertTrue($type->marshal('not empty'));
         $this->assertTrue($type->marshal(['2', '3']));
     }