diff --git a/framework/base/Component.php b/framework/base/Component.php index 72e4e3b..730e685 100644 --- a/framework/base/Component.php +++ b/framework/base/Component.php @@ -108,7 +108,7 @@ class Component extends Object return $this->_b[$name]; } elseif (is_array($this->_b)) { // a behavior property foreach ($this->_b as $object) { - if (property_exists($object, $name) || $object->canGetProperty($name)) { + if ($object->canGetProperty($name)) { return $object->$name; } } @@ -145,7 +145,7 @@ class Component extends Object return $this->_e[$name]->add($value); } elseif (is_array($this->_b)) { // behavior foreach ($this->_b as $object) { - if (property_exists($object, $name) || $object->canSetProperty($name)) { + if ($object->canSetProperty($name)) { return $object->$name = $value; } } @@ -182,7 +182,7 @@ class Component extends Object return true; } elseif (is_array($this->_b)) { foreach ($this->_b as $object) { - if (property_exists($object, $name) || $object->canGetProperty($name)) { + if ($object->canGetProperty($name)) { return $object->$name !== null; } } @@ -201,27 +201,25 @@ class Component extends Object * Do not call this method directly as it is a PHP magic method that * will be implicitly called when executing `unset($component->property)`. * @param string $name the property name - * @return null * @throws Exception if the property is read only. */ public function __unset($name) { $setter = 'set' . $name; if (method_exists($this, $setter)) { // write property - $this->$setter(null); + return $this->$setter(null); } elseif (method_exists($this, $name) && strncasecmp($name, 'on', 2) === 0) { // event - unset($this->_e[strtolower($name)]); + return unset($this->_e[strtolower($name)]); } elseif (isset($this->_b[$name])) { // behavior - $this->detachBehavior($name); + return $this->detachBehavior($name); } elseif (is_array($this->_b)) { // behavior property foreach ($this->_b as $object) { - if (property_exists($object, $name)) { + if ($object->canSetProperty($name)) { return $object->$name = null; - } elseif ($object->canSetProperty($name)) { - return $object->$setter(null); } } - } elseif (method_exists($this, 'get' . $name)) { + } + if (method_exists($this, 'get' . $name)) { throw new Exception('Unsetting read-only property: ' . get_class($this) . '.' . $name); } } @@ -236,24 +234,22 @@ class Component extends Object * Do not call this method directly as it is a PHP magic method that * will be implicitly called when an unknown method is being invoked. * @param string $name the method name - * @param array $parameters method parameters + * @param array $params method parameters * @return mixed the method return value */ - public function __call($name, $parameters) + public function __call($name, $params) { - if ($this->canGetProperty($name)) { + if ($this->canGetProperty($name, false)) { $func = $this->$name; if ($func instanceof \Closure) { - return call_user_func_array($func, $parameters); + return call_user_func_array($func, $params); } } - if ($this->_b !== null) - { - foreach ($this->_b as $object) - { + if ($this->_b !== null) { + foreach ($this->_b as $object) { if (method_exists($object, $name)) { - return call_user_func_array(array($object, $name), $parameters); + return call_user_func_array(array($object, $name), $params); } } } diff --git a/framework/base/Object.php b/framework/base/Object.php index 27f9ff0..e396792 100644 --- a/framework/base/Object.php +++ b/framework/base/Object.php @@ -63,6 +63,13 @@ namespace yii\base; class Object { /** + * Constructor. + */ + public function __construct() + { + } + + /** * Returns the value of a object property. * * Do not call this method directly as it is a PHP magic method that @@ -78,8 +85,9 @@ class Object $getter = 'get' . $name; if (method_exists($this, $getter)) { return $this->$getter(); + } else { + throw new Exception('Getting unknown property: ' . get_class($this) . '.' . $name); } - throw new Exception('Getting unknown property: ' . get_class($this) . '.' . $name); } /** @@ -89,7 +97,6 @@ class Object * will be implicitly called when executing `$object->property = $value;`. * @param string $name the property name or the event name * @param mixed $value the property value - * @return mixed value that was set * @throws Exception if the property is not defined or read-only. * @see __get */ @@ -97,9 +104,8 @@ class Object { $setter = 'set' . $name; if (method_exists($this, $setter)) { - return $this->$setter($value); - } - if (method_exists($this, 'get' . $name)) { + $this->$setter($value); + } elseif (method_exists($this, 'get' . $name)) { throw new Exception('Setting read-only property: ' . get_class($this) . '.' . $name); } else { throw new Exception('Setting unknown property: ' . get_class($this) . '.' . $name); @@ -121,8 +127,9 @@ class Object $getter = 'get' . $name; if (method_exists($this, $getter)) { // property is not null return $this->$getter() !== null; + } else { + return false; } - return false; } /** @@ -147,17 +154,42 @@ class Object } /** + * Calls the named method which is not a class method. + * If the name refers to a component property whose value is + * an anonymous function, the method will execute the function. + * + * Do not call this method directly as it is a PHP magic method that + * will be implicitly called when an unknown method is being invoked. + * @param string $name the method name + * @param array $params method parameters + * @return mixed the method return value + */ + public function __call($name, $params) + { + if ($this->canGetProperty($name, false)) { + $getter = 'get' . $name; + $func = $this->$getter; + if ($func instanceof \Closure) { + return call_user_func_array($func, $params); + } + } + throw new Exception('Unknown method: ' . get_class($this) . "::$name()"); + } + + /** * Returns a value indicating whether a property is defined. * A property is defined if there is a getter or setter method * defined in the class. Note that property names are case-insensitive. * @param string $name the property name + * @param boolean $checkVar whether to treat member variables as properties * @return boolean whether the property is defined * @see canGetProperty * @see canSetProperty */ - public function hasProperty($name) + public function hasProperty($name, $checkVar = true) { - return $this->canGetProperty($name) || $this->canSetProperty($name); + return $this->canGetProperty($name, false) || $this->canSetProperty($name, false) + || $checkVar && property_exists($this, $name); } /** @@ -165,12 +197,13 @@ class Object * A property can be read if the class has a getter method * for the property name. Note that property name is case-insensitive. * @param string $name the property name + * @param boolean $checkVar whether to treat member variables as properties * @return boolean whether the property can be read * @see canSetProperty */ - public function canGetProperty($name) + public function canGetProperty($name, $checkVar = true) { - return method_exists($this, 'get' . $name); + return method_exists($this, 'get' . $name) || $checkVar && property_exists($this, $name); } /** @@ -178,12 +211,13 @@ class Object * A property can be written if the class has a setter method * for the property name. Note that property name is case-insensitive. * @param string $name the property name + * @param boolean $checkVar whether to treat member variables as properties * @return boolean whether the property can be written * @see canGetProperty */ - public function canSetProperty($name) + public function canSetProperty($name, $checkVar = true) { - return method_exists($this, 'set' . $name); + return method_exists($this, 'set' . $name) || $checkVar && property_exists($this, $name); } /** diff --git a/framework/db/dao/Command.php b/framework/db/dao/Command.php index 84fb895..8e21514 100644 --- a/framework/db/dao/Command.php +++ b/framework/db/dao/Command.php @@ -20,15 +20,20 @@ use yii\db\Exception; * * To execute a non-query SQL (such as INSERT, DELETE, UPDATE), call [[execute]]. * To execute a SQL statement that returns result data set (such as SELECT), - * use [[query]], [[queryRow]], [[queryColumn]], or [[queryScalar]]. + * use [[queryAll]], [[queryRow]], [[queryColumn]], [[queryScalar]], or [[query]]. + * For example, + * + * ~~~ + * $users = \Yii::app()->db->createCommand('SELECT * FROM tbl_user')->queryAll(); + * ~~~ * * Command supports SQL statement preparation and parameter binding. * Call [[bindValue]] to bind a value to a SQL parameter; * Call [[bindParam]] to bind a PHP variable to a SQL parameter. * When binding a parameter, the SQL statement is automatically prepared. - * You may also call [[prepare]] to explicitly prepare a SQL statement. + * You may also call [[prepare]] explicitly to prepare a SQL statement. * - * Command can also be used as a query builder that builds and executes a SQL statement + * Command can be used as a query builder that builds and executes a SQL statement * from code fragments. For example, * * ~~~ diff --git a/framework/db/dao/DataReader.php b/framework/db/dao/DataReader.php index fa36057..ccb437e 100644 --- a/framework/db/dao/DataReader.php +++ b/framework/db/dao/DataReader.php @@ -37,6 +37,9 @@ use yii\db\Exception; */ class DataReader extends \yii\base\Object implements \Iterator, \Countable { + /** + * @var \PDOStatement the PDOStatement associated with the command + */ private $_statement; private $_closed = false; private $_row; @@ -48,7 +51,7 @@ class DataReader extends \yii\base\Object implements \Iterator, \Countable */ public function __construct(Command $command) { - $this->_statement = $command->getPdoStatement(); + $this->_statement = $command->pdoStatement; $this->_statement->setFetchMode(\PDO::FETCH_ASSOC); } diff --git a/framework/db/dao/Transaction.php b/framework/db/dao/Transaction.php index 172a38d..eaba4af 100644 --- a/framework/db/dao/Transaction.php +++ b/framework/db/dao/Transaction.php @@ -45,7 +45,6 @@ class Transaction extends \yii\base\Object public $active; /** * @var Connection the database connection that this transaction is associated with. - * This property is set true when the transaction is started. */ public $connection; @@ -70,9 +69,8 @@ class Transaction extends \yii\base\Object \Yii::trace('Committing transaction', __CLASS__); $this->connection->pdo->commit(); $this->active = false; - } - else { - throw new Exception('Transaction is inactive and cannot perform commit operation.'); + } else { + throw new Exception('Failed to commit transaction: transaction was inactive.'); } } @@ -86,9 +84,8 @@ class Transaction extends \yii\base\Object \Yii::trace('Rolling back transaction', __CLASS__); $this->connection->pdo->rollBack(); $this->active = false; - } - else { - throw new Exception('Transaction is inactive and cannot perform roll back operation.'); + } else { + throw new Exception('Failed to roll back transaction: transaction was inactive.'); } } } diff --git a/license.md b/license.md index 4caa32b..92a3254 100644 --- a/license.md +++ b/license.md @@ -7,6 +7,7 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright diff --git a/todo.md b/todo.md index 71678cb..ad23eb6 100644 --- a/todo.md +++ b/todo.md @@ -58,6 +58,4 @@ - assets * ability to manage scripts order (store these in a vector?) * http://ryanbigg.com/guides/asset_pipeline.html, http://guides.rubyonrails.org/asset_pipeline.html, use content hash instead of mtime + directory hash. -- collections - * http://code.google.com/p/yii/source/detail?r=3428 - Requirement checker \ No newline at end of file