Commit b1047e7f by Qiang Xue

refactored object creation.

added more exception classes. working on request and response classes.
parent d743d9bc
...@@ -309,9 +309,6 @@ class YiiBase ...@@ -309,9 +309,6 @@ class YiiBase
/** /**
* Creates a new object using the given configuration. * Creates a new object using the given configuration.
* *
* The class of the object can be any class. It does not have to
* extend from [[Object]] or [[Component]].
*
* The configuration can be either a string or an array. * The configuration can be either a string or an array.
* If a string, it is treated as the *object type*; if an array, * If a string, it is treated as the *object type*; if an array,
* it must contain a `class` element specifying the *object type*, and * it must contain a `class` element specifying the *object type*, and
...@@ -321,17 +318,9 @@ class YiiBase ...@@ -321,17 +318,9 @@ class YiiBase
* The object type can be either a class name or the [[getAlias|alias]] of * The object type can be either a class name or the [[getAlias|alias]] of
* the class. For example, * the class. For example,
* *
* - `\app\components\GoogleMap`: full qualified namespaced class. * - `\app\components\GoogleMap`: fully-qualified namespaced class.
* - `@app/components/GoogleMap`: an alias * - `@app/components/GoogleMap`: an alias
* *
* This method does the following steps to create an object:
*
* - create the object using the PHP `new` operator;
* - if [[objectConfig]] contains the configuration for the object class,
* it will be merged with the configuration passed to this method;
* - initialize the object properties using the configuration passed to this method;
* - call the `init` method of the object if it implements the [[\yii\base\Initable]] interface.
*
* Below are some usage examples: * Below are some usage examples:
* *
* ~~~ * ~~~
...@@ -342,16 +331,26 @@ class YiiBase ...@@ -342,16 +331,26 @@ class YiiBase
* )); * ));
* ~~~ * ~~~
* *
* Any additional parameters passed to this method will be * This method can be used to create any object as long as the object's constructor is
* passed to the constructor of the object being created. * defined like the following:
*
* ~~~
* public function __construct(..., $config = array()) {
* }
* ~~~
*
* The method will pass the given configuration as the last parameter of the constructor,
* and any additional parameters to this method will be passed as the rest of the constructor parameters.
* *
* @param string|array $config the configuration. It can be either a string or an array. * @param string|array $config the configuration. It can be either a string representing the class name
* or an array representing the object configuration.
* @return mixed the created object * @return mixed the created object
* @throws Exception if the configuration is invalid. * @throws \yii\base\BadConfigException if the configuration is invalid.
* @see \yii\base\Object::newInstance()
*/ */
public static function createObject($config) public static function createObject($config)
{ {
static $reflections = array();
if (is_string($config)) { if (is_string($config)) {
$class = $config; $class = $config;
$config = array(); $config = array();
...@@ -359,7 +358,7 @@ class YiiBase ...@@ -359,7 +358,7 @@ class YiiBase
$class = $config['class']; $class = $config['class'];
unset($config['class']); unset($config['class']);
} else { } else {
throw new Exception('Object configuration must be an array containing a "class" element.'); throw new \yii\base\BadConfigException('Object configuration must be an array containing a "class" element.');
} }
if (!class_exists($class, false)) { if (!class_exists($class, false)) {
...@@ -367,37 +366,21 @@ class YiiBase ...@@ -367,37 +366,21 @@ class YiiBase
} }
if (($n = func_num_args()) > 1) { if (($n = func_num_args()) > 1) {
$args = func_get_args(); /** @var $reflection \ReflectionClass */
if ($n === 2) { if (isset($reflections[$class])) {
$object = new $class($args[1]); $reflection = $reflections[$class];
} elseif ($n === 3) {
$object = new $class($args[1], $args[2]);
} elseif ($n === 4) {
$object = new $class($args[1], $args[2], $args[3]);
} else { } else {
$reflection = $reflections[$class] = new \ReflectionClass($class);
}
$args = func_get_args();
array_shift($args); // remove $config array_shift($args); // remove $config
$r = new \ReflectionClass($class); if ($config !== array()) {
$object = $r->newInstanceArgs($args); $args[] = $config;
} }
return $reflection->newInstanceArgs($args);
} else { } else {
$object = new $class; return $config === array() ? new $class : new $class($config);
}
$class = get_class($object);
if (isset(\Yii::$objectConfig[$class])) {
$config = array_merge(\Yii::$objectConfig[$class], $config);
} }
foreach ($config as $name => $value) {
$object->$name = $value;
}
if ($object instanceof \yii\base\Initable) {
$object->init();
}
return $object;
} }
/** /**
...@@ -545,14 +528,22 @@ class YiiBase ...@@ -545,14 +528,22 @@ class YiiBase
if (self::$application !== null) if (self::$application !== null)
{ {
if ($source === null) if ($source === null)
{
$source = $category === 'yii' ? 'coreMessages' : 'messages'; $source = $category === 'yii' ? 'coreMessages' : 'messages';
}
if (($source = self::$application->getComponent($source)) !== null) if (($source = self::$application->getComponent($source)) !== null)
{
$message = $source->translate($category, $message, $language); $message = $source->translate($category, $message, $language);
} }
}
if ($params === array()) if ($params === array())
{
return $message; return $message;
}
if (!is_array($params)) if (!is_array($params))
{
$params = array($params); $params = array($params);
}
if (isset($params[0])) // number choice if (isset($params[0])) // number choice
{ {
if (strpos($message, '|') !== false) if (strpos($message, '|') !== false)
...@@ -563,8 +554,10 @@ class YiiBase ...@@ -563,8 +554,10 @@ class YiiBase
$expressions = self::$application->getLocale($language)->getPluralRules(); $expressions = self::$application->getLocale($language)->getPluralRules();
if ($n = min(count($chunks), count($expressions))) if ($n = min(count($chunks), count($expressions)))
{ {
for ($i = 0;$i < $n;$i++) for ($i = 0; $i < $n; $i++)
{
$chunks[$i] = $expressions[$i] . '#' . $chunks[$i]; $chunks[$i] = $expressions[$i] . '#' . $chunks[$i];
}
$message = implode('|', $chunks); $message = implode('|', $chunks);
} }
...@@ -572,7 +565,9 @@ class YiiBase ...@@ -572,7 +565,9 @@ class YiiBase
$message = CChoiceFormat::format($message, $params[0]); $message = CChoiceFormat::format($message, $params[0]);
} }
if (!isset($params['{n}'])) if (!isset($params['{n}']))
{
$params['{n}'] = $params[0]; $params['{n}'] = $params[0];
}
unset($params[0]); unset($params[0]);
} }
return $params !== array() ? strtr($message, $params) : $message; return $params !== array() ? strtr($message, $params) : $message;
......
...@@ -202,14 +202,15 @@ class Application extends Module ...@@ -202,14 +202,15 @@ class Application extends Module
* @param string $route the route (e.g. `post/create`) * @param string $route the route (e.g. `post/create`)
* @param array $params the parameters to be passed to the controller action * @param array $params the parameters to be passed to the controller action
* @return integer the exit status (0 means normal, non-zero values mean abnormal) * @return integer the exit status (0 means normal, non-zero values mean abnormal)
* @throws Exception if the route cannot be resolved into a controller * @throws BadRequestException if the route cannot be resolved into a controller
*/ */
public function runController($route, $params = array()) public function runController($route, $params = array())
{ {
$result = $this->createController($route); $result = $this->createController($route);
if ($result === false) { if ($result === false) {
throw new Exception(\Yii::t('yii', 'Unable to resolve the request.')); throw new BadRequestException(\Yii::t('yii', 'Unable to resolve the request.'));
} }
/** @var $controller Controller */
list($controller, $action) = $result; list($controller, $action) = $result;
$priorController = $this->controller; $priorController = $this->controller;
$this->controller = $controller; $this->controller = $controller;
...@@ -233,13 +234,13 @@ class Application extends Module ...@@ -233,13 +234,13 @@ class Application extends Module
/** /**
* Sets the directory that stores runtime files. * Sets the directory that stores runtime files.
* @param string $path the directory that stores runtime files. * @param string $path the directory that stores runtime files.
* @throws Exception if the directory does not exist or is not writable * @throws BadParamException if the directory does not exist or is not writable
*/ */
public function setRuntimePath($path) public function setRuntimePath($path)
{ {
$p = \Yii::getAlias($path); $p = \Yii::getAlias($path);
if ($p === false || !is_dir($p) || !is_writable($path)) { if ($p === false || !is_dir($p) || !is_writable($path)) {
throw new Exception("Application runtime path \"$path\" is invalid. Please make sure it is a directory writable by the Web server process."); throw new BadParamException("Application runtime path \"$path\" is invalid. Please make sure it is a directory writable by the Web server process.");
} else { } else {
$this->_runtimePath = $p; $this->_runtimePath = $p;
} }
......
...@@ -15,7 +15,7 @@ namespace yii\base; ...@@ -15,7 +15,7 @@ namespace yii\base;
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
abstract class ApplicationComponent extends Component implements Initable abstract class ApplicationComponent extends Component
{ {
/** /**
* Initializes the application component. * Initializes the application component.
......
<?php <?php
/** /**
* Initable interface file. * BadConfigException class file.
* *
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC * @copyright Copyright &copy; 2008-2012 Yii Software LLC
...@@ -10,23 +10,12 @@ ...@@ -10,23 +10,12 @@
namespace yii\base; namespace yii\base;
/** /**
* Initable is an interface indicating a class needs initialization to work properly. * BadConfigException represents an exception caused by incorrect object configuration.
*
* Initable requires a class to implement the [[init()]] method.
* When [[\Yii::createObject()]] is being used to create a new component which implements
* Initable, it will call the [[init()]] method after setting the initial values of the
* component properties.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
interface Initable class BadConfigException extends \Exception
{ {
/**
* Initializes this component.
* This method is invoked by [[\Yii::createObject]] after its creates the new
* component instance and initializes the component properties. In other words,
* at this stage, the component has been fully configured.
*/
public function init();
} }
<?php
/**
* BadMethodException class file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* BadMethodException represents an exception caused by accessing unknown object methods.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class BadMethodException extends \Exception
{
}
<?php
/**
* BadParamException class file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* BadParamException represents an exception caused by incorrect method parameters.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class BadParamException extends \Exception
{
}
<?php
/**
* BadPropertyException class file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* BadPropertyException represents an exception caused by accessing unknown object properties.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class BadPropertyException extends \Exception
{
}
<?php
/**
* BadRequestException class file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* BadRequestException represents an exception caused by incorrect end user request.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class BadRequestException extends \Exception
{
}
...@@ -40,7 +40,7 @@ class Component extends \yii\base\Object ...@@ -40,7 +40,7 @@ class Component extends \yii\base\Object
* @param string $name the property name * @param string $name the property name
* @return mixed the property value, event handlers attached to the event, * @return mixed the property value, event handlers attached to the event,
* the named behavior, or the value of a behavior's property * the named behavior, or the value of a behavior's property
* @throws Exception if the property is not defined * @throws BadPropertyException if the property is not defined
* @see __set * @see __set
*/ */
public function __get($name) public function __get($name)
...@@ -58,7 +58,7 @@ class Component extends \yii\base\Object ...@@ -58,7 +58,7 @@ class Component extends \yii\base\Object
} }
} }
} }
throw new Exception('Getting unknown property: ' . get_class($this) . '.' . $name); throw new BadPropertyException('Getting unknown property: ' . get_class($this) . '.' . $name);
} }
/** /**
...@@ -74,7 +74,7 @@ class Component extends \yii\base\Object ...@@ -74,7 +74,7 @@ class Component extends \yii\base\Object
* will be implicitly called when executing `$component->property = $value;`. * will be implicitly called when executing `$component->property = $value;`.
* @param string $name the property name or the event name * @param string $name the property name or the event name
* @param mixed $value the property value * @param mixed $value the property value
* @throws Exception if the property is not defined or read-only. * @throws BadPropertyException if the property is not defined or read-only.
* @see __get * @see __get
*/ */
public function __set($name, $value) public function __set($name, $value)
...@@ -104,9 +104,9 @@ class Component extends \yii\base\Object ...@@ -104,9 +104,9 @@ class Component extends \yii\base\Object
} }
} }
if (method_exists($this, 'get' . $name)) { if (method_exists($this, 'get' . $name)) {
throw new Exception('Setting read-only property: ' . get_class($this) . '.' . $name); throw new BadPropertyException('Setting read-only property: ' . get_class($this) . '.' . $name);
} else { } else {
throw new Exception('Setting unknown property: ' . get_class($this) . '.' . $name); throw new BadPropertyException('Setting unknown property: ' . get_class($this) . '.' . $name);
} }
} }
...@@ -150,7 +150,7 @@ class Component extends \yii\base\Object ...@@ -150,7 +150,7 @@ class Component extends \yii\base\Object
* Do not call this method directly as it is a PHP magic method that * Do not call this method directly as it is a PHP magic method that
* will be implicitly called when executing `unset($component->property)`. * will be implicitly called when executing `unset($component->property)`.
* @param string $name the property name * @param string $name the property name
* @throws Exception if the property is read only. * @throws BadPropertyException if the property is read only.
*/ */
public function __unset($name) public function __unset($name)
{ {
...@@ -170,7 +170,7 @@ class Component extends \yii\base\Object ...@@ -170,7 +170,7 @@ class Component extends \yii\base\Object
} }
} }
if (method_exists($this, 'get' . $name)) { if (method_exists($this, 'get' . $name)) {
throw new Exception('Unsetting read-only property: ' . get_class($this) . '.' . $name); throw new BadPropertyException('Unsetting read-only property: ' . get_class($this) . '.' . $name);
} }
} }
...@@ -185,8 +185,8 @@ class Component extends \yii\base\Object ...@@ -185,8 +185,8 @@ class Component extends \yii\base\Object
* will be implicitly called when an unknown method is being invoked. * will be implicitly called when an unknown method is being invoked.
* @param string $name the method name * @param string $name the method name
* @param array $params method parameters * @param array $params method parameters
* @throws Exception when calling unknown method
* @return mixed the method return value * @return mixed the method return value
* @throws BadMethodException when calling unknown method
*/ */
public function __call($name, $params) public function __call($name, $params)
{ {
...@@ -204,7 +204,7 @@ class Component extends \yii\base\Object ...@@ -204,7 +204,7 @@ class Component extends \yii\base\Object
} }
} }
throw new Exception('Calling unknown method: ' . get_class($this) . "::$name()"); throw new BadMethodException('Calling unknown method: ' . get_class($this) . "::$name()");
} }
/** /**
......
...@@ -25,7 +25,7 @@ namespace yii\base; ...@@ -25,7 +25,7 @@ namespace yii\base;
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
class Controller extends Component implements Initable class Controller extends Component
{ {
/** /**
* @var string ID of this controller * @var string ID of this controller
...@@ -195,11 +195,11 @@ class Controller extends Component implements Initable ...@@ -195,11 +195,11 @@ class Controller extends Component implements Initable
* This method is invoked when the controller cannot find the requested action. * This method is invoked when the controller cannot find the requested action.
* The default implementation simply throws an exception. * The default implementation simply throws an exception.
* @param string $actionID the missing action name * @param string $actionID the missing action name
* @throws Exception whenever this method is invoked * @throws BadRequestException whenever this method is invoked
*/ */
public function missingAction($actionID) public function missingAction($actionID)
{ {
throw new Exception(\Yii::t('yii', 'The system is unable to find the requested action "{action}".', throw new BadRequestException(\Yii::t('yii', 'The system is unable to find the requested action "{action}".',
array('{action}' => $actionID == '' ? $this->defaultAction : $actionID))); array('{action}' => $actionID == '' ? $this->defaultAction : $actionID)));
} }
......
...@@ -182,7 +182,7 @@ class Dictionary extends Object implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -182,7 +182,7 @@ class Dictionary extends Object implements \IteratorAggregate, \ArrayAccess, \Co
* Copies iterable data into the dictionary. * Copies iterable data into the dictionary.
* Note, existing data in the dictionary will be cleared first. * Note, existing data in the dictionary will be cleared first.
* @param mixed $data the data to be copied from, must be an array or an object implementing `Traversable` * @param mixed $data the data to be copied from, must be an array or an object implementing `Traversable`
* @throws Exception if data is neither an array nor an iterator. * @throws BadParamException if data is neither an array nor an iterator.
*/ */
public function copyFrom($data) public function copyFrom($data)
{ {
...@@ -197,7 +197,7 @@ class Dictionary extends Object implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -197,7 +197,7 @@ class Dictionary extends Object implements \IteratorAggregate, \ArrayAccess, \Co
$this->add($key, $value); $this->add($key, $value);
} }
} else { } else {
throw new Exception('Data must be either an array or an object implementing Traversable.'); throw new BadParamException('Data must be either an array or an object implementing Traversable.');
} }
} }
...@@ -214,7 +214,7 @@ class Dictionary extends Object implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -214,7 +214,7 @@ class Dictionary extends Object implements \IteratorAggregate, \ArrayAccess, \Co
* *
* @param array|\Traversable $data the data to be merged with. It must be an array or object implementing Traversable * @param array|\Traversable $data the data to be merged with. It must be an array or object implementing Traversable
* @param boolean $recursive whether the merging should be recursive. * @param boolean $recursive whether the merging should be recursive.
* @throws Exception if data is neither an array nor an object implementing `Traversable`. * @throws BadParamException if data is neither an array nor an object implementing `Traversable`.
*/ */
public function mergeWith($data, $recursive = true) public function mergeWith($data, $recursive = true)
{ {
...@@ -238,7 +238,7 @@ class Dictionary extends Object implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -238,7 +238,7 @@ class Dictionary extends Object implements \IteratorAggregate, \ArrayAccess, \Co
} }
} }
} else { } else {
throw new Exception('The data to be merged with must be an array or an object implementing Traversable.'); throw new BadParamException('The data to be merged with must be an array or an object implementing Traversable.');
} }
} }
......
...@@ -279,6 +279,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess ...@@ -279,6 +279,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
* Creates validator objects based on the validation rules specified in [[rules()]]. * Creates validator objects based on the validation rules specified in [[rules()]].
* Unlike [[getValidators()]], each time this method is called, a new list of validators will be returned. * Unlike [[getValidators()]], each time this method is called, a new list of validators will be returned.
* @return Vector validators * @return Vector validators
* @throws BadConfigException if any validation rule configuration is invalid
*/ */
public function createValidators() public function createValidators()
{ {
...@@ -288,7 +289,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess ...@@ -288,7 +289,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
$validator = \yii\validators\Validator::createValidator($rule[1], $this, $rule[0], array_slice($rule, 2)); $validator = \yii\validators\Validator::createValidator($rule[1], $this, $rule[0], array_slice($rule, 2));
$validators->add($validator); $validators->add($validator);
} else { } else {
throw new Exception('Invalid validation rule: a rule must specify both attribute names and validator type.'); throw new BadConfigException('Invalid validation rule: a rule must specify both attribute names and validator type.');
} }
} }
return $validators; return $validators;
......
...@@ -27,7 +27,7 @@ use yii\util\FileHelper; ...@@ -27,7 +27,7 @@ use yii\util\FileHelper;
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
abstract class Module extends Component implements Initable abstract class Module extends Component
{ {
/** /**
* @var array custom module parameters (name => value). * @var array custom module parameters (name => value).
...@@ -584,7 +584,7 @@ abstract class Module extends Component implements Initable ...@@ -584,7 +584,7 @@ abstract class Module extends Component implements Initable
} }
if (class_exists($className, false) && is_subclass_of($className, '\yii\base\Controller')) { if (class_exists($className, false) && is_subclass_of($className, '\yii\base\Controller')) {
return array( return array(
$className::newInstance(array(), $id, $this), new $className($id, $this),
$route, $route,
); );
} }
......
...@@ -21,8 +21,32 @@ class Object ...@@ -21,8 +21,32 @@ class Object
{ {
/** /**
* Constructor. * Constructor.
* The default implementation does two things:
*
* - Initializes the object with the given configuration `$config`.
* - Call [[init()]].
*
* If this method is overridden in a child class, it is recommended that
*
* - the last parameter of the constructor is a configuration array, like `$config` here.
* - call the parent implementation at the end of the constructor.
*
* @param array $config name-value pairs that will be used to initialize the object properties
*/ */
public function __construct() public function __construct($config = array())
{
foreach ($config as $name => $value) {
$this->$name = $value;
}
$this->init();
}
/**
* Initializes the object.
* This method is invoked at the end of the constructor after the object is initialized with the
* given configuration.
*/
public function init()
{ {
} }
...@@ -34,7 +58,7 @@ class Object ...@@ -34,7 +58,7 @@ class Object
* @param string $name the property name * @param string $name the property name
* @return mixed the property value, event handlers attached to the event, * @return mixed the property value, event handlers attached to the event,
* the named behavior, or the value of a behavior's property * the named behavior, or the value of a behavior's property
* @throws Exception if the property is not defined * @throws BadPropertyException if the property is not defined
* @see __set * @see __set
*/ */
public function __get($name) public function __get($name)
...@@ -43,7 +67,7 @@ class Object ...@@ -43,7 +67,7 @@ class Object
if (method_exists($this, $getter)) { if (method_exists($this, $getter)) {
return $this->$getter(); return $this->$getter();
} else { } else {
throw new Exception('Getting unknown property: ' . get_class($this) . '.' . $name); throw new BadPropertyException('Getting unknown property: ' . get_class($this) . '.' . $name);
} }
} }
...@@ -54,7 +78,7 @@ class Object ...@@ -54,7 +78,7 @@ class Object
* will be implicitly called when executing `$object->property = $value;`. * will be implicitly called when executing `$object->property = $value;`.
* @param string $name the property name or the event name * @param string $name the property name or the event name
* @param mixed $value the property value * @param mixed $value the property value
* @throws Exception if the property is not defined or read-only. * @throws BadPropertyException if the property is not defined or read-only.
* @see __get * @see __get
*/ */
public function __set($name, $value) public function __set($name, $value)
...@@ -63,9 +87,9 @@ class Object ...@@ -63,9 +87,9 @@ class Object
if (method_exists($this, $setter)) { if (method_exists($this, $setter)) {
$this->$setter($value); $this->$setter($value);
} elseif (method_exists($this, 'get' . $name)) { } elseif (method_exists($this, 'get' . $name)) {
throw new Exception('Setting read-only property: ' . get_class($this) . '.' . $name); throw new BadPropertyException('Setting read-only property: ' . get_class($this) . '.' . $name);
} else { } else {
throw new Exception('Setting unknown property: ' . get_class($this) . '.' . $name); throw new BadPropertyException('Setting unknown property: ' . get_class($this) . '.' . $name);
} }
} }
...@@ -99,7 +123,7 @@ class Object ...@@ -99,7 +123,7 @@ class Object
* Note that if the property is not defined, this method will do nothing. * Note that if the property is not defined, this method will do nothing.
* If the property is read-only, it will throw an exception. * If the property is read-only, it will throw an exception.
* @param string $name the property name * @param string $name the property name
* @throws Exception if the property is read only. * @throws BadPropertyException if the property is read only.
*/ */
public function __unset($name) public function __unset($name)
{ {
...@@ -108,7 +132,7 @@ class Object ...@@ -108,7 +132,7 @@ class Object
// write property // write property
$this->$setter(null); $this->$setter(null);
} elseif (method_exists($this, 'get' . $name)) { } elseif (method_exists($this, 'get' . $name)) {
throw new Exception('Unsetting read-only property: ' . get_class($this) . '.' . $name); throw new BadPropertyException('Unsetting read-only property: ' . get_class($this) . '.' . $name);
} }
} }
...@@ -121,7 +145,7 @@ class Object ...@@ -121,7 +145,7 @@ class Object
* will be implicitly called when an unknown method is being invoked. * will be implicitly called when an unknown method is being invoked.
* @param string $name the method name * @param string $name the method name
* @param array $params method parameters * @param array $params method parameters
* @throws Exception when calling unknown method * @throws BadMethodException when calling unknown method
* @return mixed the method return value * @return mixed the method return value
*/ */
public function __call($name, $params) public function __call($name, $params)
...@@ -133,7 +157,7 @@ class Object ...@@ -133,7 +157,7 @@ class Object
return call_user_func_array($func, $params); return call_user_func_array($func, $params);
} }
} }
throw new Exception('Unknown method: ' . get_class($this) . "::$name()"); throw new BadMethodException('Unknown method: ' . get_class($this) . "::$name()");
} }
/** /**
...@@ -148,7 +172,7 @@ class Object ...@@ -148,7 +172,7 @@ class Object
*/ */
public function hasProperty($name, $checkVar = true) public function hasProperty($name, $checkVar = true)
{ {
return $this->canGetProperty($name, false) || $this->canSetProperty($name, false) || $checkVar && property_exists($this, $name); return $this->canGetProperty($name, $checkVar) || $this->canSetProperty($name, false);
} }
/** /**
...@@ -176,86 +200,6 @@ class Object ...@@ -176,86 +200,6 @@ class Object
*/ */
public function canSetProperty($name, $checkVar = true) public function canSetProperty($name, $checkVar = true)
{ {
return $checkVar && property_exists($this, $name) || method_exists($this, 'set' . $name); return method_exists($this, 'set' . $name) || $checkVar && property_exists($this, $name);
}
/**
* Creates a new instance of the calling class.
*
* The newly created object will be initialized with the specified configuration.
*
* Extra parameters passed to this method will be used as the parameters to the object
* constructor.
*
* This method does the following steps to create a object:
*
* - create the object using the PHP `new` operator;
* - if [[Yii::objectConfig]] contains the configuration for the object class,
* it will be merged with the $config parameter;
* - initialize the object properties using the configuration passed to this method;
* - call the `init` method of the object if it implements the [[yii\base\Initable]] interface.
*
* For example,
*
* ~~~
* class Foo extends \yii\base\Object implements \yii\base\Initable
* {
* public $c;
* public function __construct($a, $b)
* {
* ...
* }
* public function init()
* {
* ...
* }
* }
*
* $model = Foo::newInstance(array('c' => 3), 1, 2);
* // which is equivalent to the following lines:
* $model = new Foo(1, 2);
* $model->c = 3;
* $model->init();
* ~~~
*
* @param array $config the object configuration (name-value pairs that will be used to initialize the object)
* @return \yii\base\Object the created object
* @throws Exception if the configuration is invalid.
*/
public static function newInstance($config = array())
{
$class = get_called_class();
if (($n = func_num_args()) > 1) {
$args = func_get_args();
if ($n === 2) {
$object = new $class($args[1]);
} elseif ($n === 3) {
$object = new $class($args[1], $args[2]);
} elseif ($n === 4) {
$object = new $class($args[1], $args[2], $args[3]);
} else {
// remove $config
array_shift($args);
$r = new \ReflectionClass($class);
$object = $r->newInstanceArgs($args);
}
} else {
$object = new $class;
}
if (isset(\Yii::$objectConfig[$class])) {
$config = array_merge(\Yii::$objectConfig[$class], $config);
}
foreach ($config as $name => $value) {
$object->$name = $value;
}
if ($object instanceof Initable) {
$object->init();
}
return $object;
} }
} }
<?php
/**
* Request class file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Request extends ApplicationComponent
{
private $_scriptFile;
/**
* Initializes the application component.
* This method overrides the parent implementation by preprocessing
* the user request data.
*/
public function init()
{
}
/**
* Returns the relative URL of the entry script.
* The implementation of this method referenced Zend_Controller_Request_Http in Zend Framework.
* @return string the relative URL of the entry script.
*/
public function getScriptUrl()
{
if($this->_scriptUrl===null)
{
$scriptName=basename($_SERVER['SCRIPT_FILENAME']);
if(basename($_SERVER['SCRIPT_NAME'])===$scriptName)
$this->_scriptUrl=$_SERVER['SCRIPT_NAME'];
else if(basename($_SERVER['PHP_SELF'])===$scriptName)
$this->_scriptUrl=$_SERVER['PHP_SELF'];
else if(isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME'])===$scriptName)
$this->_scriptUrl=$_SERVER['ORIG_SCRIPT_NAME'];
else if(($pos=strpos($_SERVER['PHP_SELF'],'/'.$scriptName))!==false)
$this->_scriptUrl=substr($_SERVER['SCRIPT_NAME'],0,$pos).'/'.$scriptName;
else if(isset($_SERVER['DOCUMENT_ROOT']) && strpos($_SERVER['SCRIPT_FILENAME'],$_SERVER['DOCUMENT_ROOT'])===0)
$this->_scriptUrl=str_replace('\\','/',str_replace($_SERVER['DOCUMENT_ROOT'],'',$_SERVER['SCRIPT_FILENAME']));
else
throw new Exception(Yii::t('yii','CHttpRequest is unable to determine the entry script URL.'));
}
return $this->_scriptUrl;
}
/**
* Sets the relative URL for the application entry script.
* This setter is provided in case the entry script URL cannot be determined
* on certain Web servers.
* @param string $value the relative URL for the application entry script.
*/
public function setScriptUrl($value)
{
$this->_scriptUrl='/'.trim($value,'/');
}
/**
* Returns whether this is an AJAX (XMLHttpRequest) request.
* @return boolean whether this is an AJAX (XMLHttpRequest) request.
*/
public function getIsAjaxRequest()
{
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest';
}
/**
* Returns whether this is an Adobe Flash or Adobe Flex request.
* @return boolean whether this is an Adobe Flash or Adobe Flex request.
* @since 1.1.11
*/
public function getIsFlashRequest()
{
return isset($_SERVER['HTTP_USER_AGENT']) && (stripos($_SERVER['HTTP_USER_AGENT'],'Shockwave')!==false || stripos($_SERVER['HTTP_USER_AGENT'],'Flash')!==false);
}
/**
* Returns the server name.
* @return string server name
*/
public function getServerName()
{
return $_SERVER['SERVER_NAME'];
}
/**
* Returns the server port number.
* @return integer server port number
*/
public function getServerPort()
{
return $_SERVER['SERVER_PORT'];
}
/**
* Returns the URL referrer, null if not present
* @return string URL referrer, null if not present
*/
public function getUrlReferrer()
{
return isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:null;
}
/**
* Returns the user agent, null if not present.
* @return string user agent, null if not present
*/
public function getUserAgent()
{
return isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:null;
}
/**
* Returns the user IP address.
* @return string user IP address
*/
public function getUserHostAddress()
{
return isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:'127.0.0.1';
}
/**
* Returns the user host name, null if it cannot be determined.
* @return string user host name, null if cannot be determined
*/
public function getUserHost()
{
return isset($_SERVER['REMOTE_HOST'])?$_SERVER['REMOTE_HOST']:null;
}
/**
* Returns entry script file path.
* @return string entry script file path (processed w/ realpath())
*/
public function getScriptFile()
{
if($this->_scriptFile!==null)
return $this->_scriptFile;
else
return $this->_scriptFile=realpath($_SERVER['SCRIPT_FILENAME']);
}
}
<?php
/**
* Response and CCookieCollection class file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* Response encapsulates the $_SERVER variable and resolves its inconsistency among different Web servers.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Response extends ApplicationComponent
{
}
...@@ -25,12 +25,12 @@ class Theme extends ApplicationComponent ...@@ -25,12 +25,12 @@ class Theme extends ApplicationComponent
if ($this->basePath !== null) { if ($this->basePath !== null) {
$this->basePath = \Yii::getAlias($this->basePath, true); $this->basePath = \Yii::getAlias($this->basePath, true);
} else { } else {
throw new Exception("Theme.basePath must be set."); throw new BadConfigException("Theme.basePath must be set.");
} }
if ($this->baseUrl !== null) { if ($this->baseUrl !== null) {
$this->baseUrl = \Yii::getAlias($this->baseUrl, true); $this->baseUrl = \Yii::getAlias($this->baseUrl, true);
} else { } else {
throw new Exception("Theme.baseUrl must be set."); throw new BadConfigException("Theme.baseUrl must be set.");
} }
} }
......
...@@ -99,7 +99,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta ...@@ -99,7 +99,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta
* Returns the item at the specified index. * Returns the item at the specified index.
* @param integer $index the index of the item * @param integer $index the index of the item
* @return mixed the item at the index * @return mixed the item at the index
* @throws Exception if the index is out of range * @throws BadParamException if the index is out of range
*/ */
public function itemAt($index) public function itemAt($index)
{ {
...@@ -108,7 +108,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta ...@@ -108,7 +108,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta
} elseif ($index >= 0 && $index < $this->_c) { // in case the value is null } elseif ($index >= 0 && $index < $this->_c) { // in case the value is null
return $this->_d[$index]; return $this->_d[$index];
} else { } else {
throw new Exception('Index out of range: ' . $index); throw new BadParamException('Index out of range: ' . $index);
} }
} }
...@@ -130,7 +130,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta ...@@ -130,7 +130,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta
* one step towards the end. * one step towards the end.
* @param integer $index the specified position. * @param integer $index the specified position.
* @param mixed $item new item to be inserted into the vector * @param mixed $item new item to be inserted into the vector
* @throws Exception if the index specified is out of range, or the vector is read-only. * @throws BadParamException if the index specified is out of range, or the vector is read-only.
*/ */
public function insertAt($index, $item) public function insertAt($index, $item)
{ {
...@@ -140,7 +140,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta ...@@ -140,7 +140,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta
array_splice($this->_d, $index, 0, array($item)); array_splice($this->_d, $index, 0, array($item));
$this->_c++; $this->_c++;
} else { } else {
throw new Exception('Index out of range: ' . $index); throw new BadParamException('Index out of range: ' . $index);
} }
} }
...@@ -167,7 +167,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta ...@@ -167,7 +167,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta
* Removes an item at the specified position. * Removes an item at the specified position.
* @param integer $index the index of the item to be removed. * @param integer $index the index of the item to be removed.
* @return mixed the removed item. * @return mixed the removed item.
* @throws Exception if the index is out of range, or the vector is read only. * @throws BadParamException if the index is out of range, or the vector is read only.
*/ */
public function removeAt($index) public function removeAt($index)
{ {
...@@ -181,7 +181,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta ...@@ -181,7 +181,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta
return $item; return $item;
} }
} else { } else {
throw new Exception('Index out of range: ' . $index); throw new BadParamException('Index out of range: ' . $index);
} }
} }
...@@ -240,7 +240,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta ...@@ -240,7 +240,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta
* Copies iterable data into the vector. * Copies iterable data into the vector.
* Note, existing data in the vector will be cleared first. * Note, existing data in the vector will be cleared first.
* @param mixed $data the data to be copied from, must be an array or an object implementing `Traversable` * @param mixed $data the data to be copied from, must be an array or an object implementing `Traversable`
* @throws Exception if data is neither an array nor an object implementing `Traversable`. * @throws BadParamException if data is neither an array nor an object implementing `Traversable`.
*/ */
public function copyFrom($data) public function copyFrom($data)
{ {
...@@ -255,7 +255,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta ...@@ -255,7 +255,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta
$this->add($item); $this->add($item);
} }
} else { } else {
throw new Exception('Data must be either an array or an object implementing Traversable.'); throw new BadParamException('Data must be either an array or an object implementing Traversable.');
} }
} }
...@@ -263,7 +263,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta ...@@ -263,7 +263,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta
* Merges iterable data into the vector. * Merges iterable data into the vector.
* New items will be appended to the end of the existing items. * New items will be appended to the end of the existing items.
* @param array|\Traversable $data the data to be merged with. It must be an array or object implementing Traversable * @param array|\Traversable $data the data to be merged with. It must be an array or object implementing Traversable
* @throws Exception if data is neither an array nor an object implementing `Traversable`. * @throws BadParamException if data is neither an array nor an object implementing `Traversable`.
*/ */
public function mergeWith($data) public function mergeWith($data)
{ {
...@@ -275,7 +275,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta ...@@ -275,7 +275,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta
$this->add($item); $this->add($item);
} }
} else { } else {
throw new Exception('The data to be merged with must be an array or an object implementing Traversable.'); throw new BadParamException('The data to be merged with must be an array or an object implementing Traversable.');
} }
} }
......
...@@ -103,7 +103,7 @@ class View extends Component ...@@ -103,7 +103,7 @@ class View extends Component
* @param array $params the parameters that should be made available in the view. The PHP function `extract()` * @param array $params the parameters that should be made available in the view. The PHP function `extract()`
* will be called on this variable to extract the variables from this parameter. * will be called on this variable to extract the variables from this parameter.
* @return string the rendering result * @return string the rendering result
* @throws Exception if the view file cannot be found * @throws BadParamException if the view file cannot be found
*/ */
public function renderPartial($view, $params = array()) public function renderPartial($view, $params = array())
{ {
...@@ -111,7 +111,7 @@ class View extends Component ...@@ -111,7 +111,7 @@ class View extends Component
if ($file !== false) { if ($file !== false) {
return $this->renderFile($file, $params); return $this->renderFile($file, $params);
} else { } else {
throw new Exception("Unable to find the view file for view '$view'."); throw new BadParamException("Unable to find the view file for view '$view'.");
} }
} }
...@@ -170,6 +170,7 @@ class View extends Component ...@@ -170,6 +170,7 @@ class View extends Component
*/ */
public function endWidget() public function endWidget()
{ {
/** @var $widget Widget */
if (($widget = array_pop($this->widgetStack)) !== null) { if (($widget = array_pop($this->widgetStack)) !== null) {
$widget->run(); $widget->run();
return $widget; return $widget;
...@@ -413,7 +414,7 @@ class View extends Component ...@@ -413,7 +414,7 @@ class View extends Component
* The themed layout file will be returned if theme is enabled and the theme contains such a layout file. * The themed layout file will be returned if theme is enabled and the theme contains such a layout file.
* *
* @return string|boolean the layout file path, or false if the context does not need layout. * @return string|boolean the layout file path, or false if the context does not need layout.
* @throws Exception if the layout file cannot be found * @throws BadParamException if the layout file cannot be found
*/ */
public function findLayoutFile() public function findLayoutFile()
{ {
...@@ -451,7 +452,7 @@ class View extends Component ...@@ -451,7 +452,7 @@ class View extends Component
} }
} }
if ($file === false || !is_file($file)) { if ($file === false || !is_file($file)) {
throw new Exception("Unable to find the layout file for layout '{$module->layout}' (specified by " . get_class($module) . ")"); throw new BadParamException("Unable to find the layout file for layout '{$module->layout}' (specified by " . get_class($module) . ")");
} elseif ($this->localizeView) { } elseif ($this->localizeView) {
return FileHelper::localize($file, $this->language, $this->sourceLanguage); return FileHelper::localize($file, $this->language, $this->sourceLanguage);
} else { } else {
......
...@@ -15,7 +15,7 @@ namespace yii\base; ...@@ -15,7 +15,7 @@ namespace yii\base;
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
class Widget extends Component implements Initable class Widget extends Component
{ {
/** /**
* @var Widget|Controller the owner/creator of this widget. It could be either a widget or a controller. * @var Widget|Controller the owner/creator of this widget. It could be either a widget or a controller.
...@@ -62,13 +62,6 @@ class Widget extends Component implements Initable ...@@ -62,13 +62,6 @@ class Widget extends Component implements Initable
} }
/** /**
* Initializes the widget.
*/
public function init()
{
}
/**
* Executes the widget. * Executes the widget.
*/ */
public function run() public function run()
......
...@@ -138,7 +138,7 @@ class MemCache extends Cache ...@@ -138,7 +138,7 @@ class MemCache extends Cache
public function setServers($config) public function setServers($config)
{ {
foreach ($config as $c) { foreach ($config as $c) {
$this->_servers[] = MemCacheServer::newInstance($c); $this->_servers[] = new MemCacheServer($c);
} }
} }
......
...@@ -89,7 +89,7 @@ class ActiveMetaData ...@@ -89,7 +89,7 @@ class ActiveMetaData
if (is_string($config)) { if (is_string($config)) {
$config = array('on' => $config); $config = array('on' => $config);
} }
$relation = ActiveRelation::newInstance($config); $relation = new ActiveRelation($config);
$relation->name = $matches[1]; $relation->name = $matches[1];
$modelClass = $matches[2]; $modelClass = $matches[2];
if (strpos($modelClass, '\\') !== false) { if (strpos($modelClass, '\\') !== false) {
......
...@@ -1034,7 +1034,8 @@ abstract class ActiveRecord extends Model ...@@ -1034,7 +1034,8 @@ abstract class ActiveRecord extends Model
*/ */
public static function instantiate($row) public static function instantiate($row)
{ {
return static::newInstance(); $class = get_called_class();
return new $class;
} }
/** /**
......
...@@ -25,7 +25,7 @@ use yii\db\Exception; ...@@ -25,7 +25,7 @@ use yii\db\Exception;
* the DB connection: * the DB connection:
* *
* ~~~ * ~~~
* $connection = \yii\db\dao\Connection::newInstance(array( * $connection = new \yii\db\dao\Connection(array(
* 'dsn' => $dsn, * 'dsn' => $dsn,
* 'username' => $username, * 'username' => $username,
* 'password' => $password, * 'password' => $password,
......
...@@ -23,7 +23,7 @@ namespace yii\logging; ...@@ -23,7 +23,7 @@ namespace yii\logging;
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
abstract class Target extends \yii\base\Component implements \yii\base\Initable abstract class Target extends \yii\base\Component
{ {
/** /**
* @var boolean whether to enable this log target. Defaults to true. * @var boolean whether to enable this log target. Defaults to true.
...@@ -90,15 +90,6 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable ...@@ -90,15 +90,6 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable
abstract public function exportMessages($final); abstract public function exportMessages($final);
/** /**
* Initializes this component.
* This method is invoked after the component is created and its property values are
* initialized.
*/
public function init()
{
}
/**
* Processes the given log messages. * Processes the given log messages.
* This method will filter the given messages with [[levels]] and [[categories]]. * This method will filter the given messages with [[levels]] and [[categories]].
* And if requested, it will also export the filtering result to specific medium (e.g. email). * And if requested, it will also export the filtering result to specific medium (e.g. email).
......
...@@ -18,4 +18,5 @@ $config = array( ...@@ -18,4 +18,5 @@ $config = array(
$id = 'yiic'; $id = 'yiic';
$basePath = __DIR__ . '/console'; $basePath = __DIR__ . '/console';
yii\console\Application::newInstance($config, $id, $basePath)->run(); $application = new yii\console\Application($id, $basePath, $config);
\ No newline at end of file $application->run();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment