diff --git a/framework/yii/base/Application.php b/framework/yii/base/Application.php index 495c1f8..09951bd 100644 --- a/framework/yii/base/Application.php +++ b/framework/yii/base/Application.php @@ -67,10 +67,20 @@ class Application extends Module * Constructor. * @param array $config name-value pairs that will be used to initialize the object properties. * Note that the configuration must contain both [[id]] and [[basePath]]. + * @throws InvalidConfigException if either [[id]] or [[basePath]] configuration is missing. */ public function __construct($config = array()) { Yii::$app = $this; + if (!isset($config['id'])) { + throw new InvalidConfigException('The "id" configuration is required.'); + } + if (isset($config['basePath'])) { + $this->setBasePath($config['basePath']); + unset($config['basePath']); + } else { + throw new InvalidConfigException('The "basePath" configuration is required.'); + } $this->preInit($config); @@ -83,37 +93,24 @@ class Application extends Module /** * Pre-initializes the application. * This method is called at the beginning of the application constructor. - * When this method is called, none of the application properties are initialized yet. - * The default implementation will initialize a few important properties - * that may be referenced during the initialization of the rest of the properties. * @param array $config the application configuration - * @throws InvalidConfigException if either [[id]] or [[basePath]] configuration is missing. */ - public function preInit($config) + public function preInit(&$config) { - if (!isset($config['id'])) { - throw new InvalidConfigException('The "id" configuration is required.'); - } - if (!isset($config['basePath'])) { - throw new InvalidConfigException('The "basePath" configuration is required.'); - } - - $this->setBasePath($config['basePath']); - Yii::setAlias('@app', $this->getBasePath()); - unset($config['basePath']); - - if (isset($config['vendor'])) { - $this->setVendorPath($config['vendor']); + if (isset($config['vendorPath'])) { + $this->setVendorPath($config['vendorPath']); unset($config['vendorPath']); + } else { + // set "@vendor" + $this->getVendorPath(); } - Yii::setAlias('@vendor', $this->getVendorPath()); - - if (isset($config['runtime'])) { - $this->setRuntimePath($config['runtime']); - unset($config['runtime']); + if (isset($config['runtimePath'])) { + $this->setRuntimePath($config['runtimePath']); + unset($config['runtimePath']); + } else { + // set "@runtime" + $this->getRuntimePath(); } - Yii::setAlias('@runtime', $this->getRuntimePath()); - if (isset($config['timeZone'])) { $this->setTimeZone($config['timeZone']); unset($config['timeZone']); @@ -202,7 +199,8 @@ class Application extends Module /** * Returns the directory that stores runtime files. - * @return string the directory that stores runtime files. Defaults to 'protected/runtime'. + * @return string the directory that stores runtime files. + * Defaults to the "runtime" subdirectory under [[basePath]]. */ public function getRuntimePath() { @@ -215,16 +213,11 @@ class Application extends Module /** * Sets the directory that stores runtime files. * @param string $path the directory that stores runtime files. - * @throws InvalidConfigException if the directory does not exist or is not writable */ public function setRuntimePath($path) { - $path = Yii::getAlias($path); - if (is_dir($path) && is_writable($path)) { - $this->_runtimePath = $path; - } else { - throw new InvalidConfigException("Runtime path must be a directory writable by the Web server process: $path"); - } + $this->_runtimePath = Yii::getAlias($path); + Yii::setAlias('@runtime', $this->_runtimePath); } private $_vendorPath; @@ -232,7 +225,7 @@ class Application extends Module /** * Returns the directory that stores vendor files. * @return string the directory that stores vendor files. - * Defaults to 'vendor' directory under applications [[basePath]]. + * Defaults to "vendor" directory under [[basePath]]. */ public function getVendorPath() { @@ -249,6 +242,7 @@ class Application extends Module public function setVendorPath($path) { $this->_vendorPath = Yii::getAlias($path); + Yii::setAlias('@vendor', $this->_vendorPath); } /** diff --git a/framework/yii/base/Formatter.php b/framework/yii/base/Formatter.php index d15e5f2..e62039e 100644 --- a/framework/yii/base/Formatter.php +++ b/framework/yii/base/Formatter.php @@ -39,17 +39,19 @@ class Formatter extends Component public $datetimeFormat = 'Y/m/d h:i:s A'; /** * @var array the text to be displayed when formatting a boolean value. The first element corresponds - * to the text display for false, the second element for true. Defaults to array('No', 'Yes'). + * to the text display for false, the second element for true. Defaults to `array('No', 'Yes')`. */ public $booleanFormat; /** * @var string the character displayed as the decimal point when formatting a number. + * If not set, "." will be used. */ - public $decimalSeparator = '.'; + public $decimalSeparator; /** * @var string the character displayed as the thousands separator character when formatting a number. + * If not set, "," will be used. */ - public $thousandSeparator = ','; + public $thousandSeparator; /** @@ -273,7 +275,11 @@ class Formatter extends Component */ public function asDouble($value, $decimals = 2) { - return str_replace('.', $this->decimalSeparator, sprintf("%.{$decimals}f", $value)); + if ($this->decimalSeparator === null) { + return sprintf("%.{$decimals}f", $value); + } else { + return str_replace('.', $this->decimalSeparator, sprintf("%.{$decimals}f", $value)); + } } /** @@ -287,6 +293,8 @@ class Formatter extends Component */ public function asNumber($value, $decimals = 0) { - return number_format($value, $decimals, $this->decimalSeparator, $this->thousandSeparator); + $ds = isset($this->decimalSeparator) ? $this->decimalSeparator: '.'; + $ts = isset($this->thousandSeparator) ? $this->thousandSeparator: ','; + return number_format($value, $decimals, $ds, $ts); } } diff --git a/framework/yii/base/Module.php b/framework/yii/base/Module.php index fac4164..5f5c376 100644 --- a/framework/yii/base/Module.php +++ b/framework/yii/base/Module.php @@ -236,6 +236,9 @@ abstract class Module extends Component $p = realpath($path); if ($p !== false && is_dir($p)) { $this->_basePath = $p; + if ($this instanceof Application) { + Yii::setAlias('@app', $p); + } } else { throw new InvalidParamException("The directory does not exist: $path"); } diff --git a/framework/yii/db/ActiveRecord.php b/framework/yii/db/ActiveRecord.php index 58411f0..6faebbf 100644 --- a/framework/yii/db/ActiveRecord.php +++ b/framework/yii/db/ActiveRecord.php @@ -275,10 +275,16 @@ class ActiveRecord extends Model /** * Returns the schema information of the DB table associated with this AR class. * @return TableSchema the schema information of the DB table associated with this AR class. + * @throws InvalidConfigException if the table for the AR class does not exist. */ public static function getTableSchema() { - return static::getDb()->getTableSchema(static::tableName()); + $schema = static::getDb()->getTableSchema(static::tableName()); + if ($schema !== null) { + return $schema; + } else { + throw new InvalidConfigException("The table does not exist: " . static::tableName()); + } } /** diff --git a/framework/yii/db/mysql/Schema.php b/framework/yii/db/mysql/Schema.php index 501149a..b42ef15 100644 --- a/framework/yii/db/mysql/Schema.php +++ b/framework/yii/db/mysql/Schema.php @@ -178,6 +178,7 @@ class Schema extends \yii\db\Schema * Collects the metadata of table columns. * @param TableSchema $table the table metadata * @return boolean whether the table exists in the database + * @throws \Exception if DB query fails */ protected function findColumns($table) { @@ -185,7 +186,12 @@ class Schema extends \yii\db\Schema try { $columns = $this->db->createCommand($sql)->queryAll(); } catch (\Exception $e) { - return false; + $previous = $e->getPrevious(); + if ($previous instanceof \PDOException && $previous->getCode() == '42S02') { + // table does not exist + return false; + } + throw $e; } foreach ($columns as $info) { $column = $this->loadColumnSchema($info); diff --git a/framework/yii/i18n/Formatter.php b/framework/yii/i18n/Formatter.php index d688a15..948e277 100644 --- a/framework/yii/i18n/Formatter.php +++ b/framework/yii/i18n/Formatter.php @@ -30,21 +30,40 @@ class Formatter extends \yii\base\Formatter */ public $locale; /** - * @var string the default format string to be used to format a date using PHP date() function. + * @var string the default format string to be used to format a date. + * This can be "short", "medium", "long", or "full", which represents a preset format of different lengths. + * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime). */ public $dateFormat = 'short'; /** - * @var string the default format string to be used to format a time using PHP date() function. + * @var string the default format string to be used to format a time. + * This can be "short", "medium", "long", or "full", which represents a preset format of different lengths. + * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime). */ public $timeFormat = 'short'; /** - * @var string the default format string to be used to format a date and time using PHP date() function. + * @var string the default format string to be used to format a date and time. + * This can be "short", "medium", "long", or "full", which represents a preset format of different lengths. + * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime). */ public $datetimeFormat = 'short'; /** * @var array the options to be set for the NumberFormatter objects. Please refer to + * [PHP manual](http://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants.unumberformatattribute) + * for the possible options. This property is used by [[createNumberFormatter]] when + * creating a new number formatter to format decimals, currencies, etc. */ public $numberFormatOptions = array(); + /** + * @var string the character displayed as the decimal point when formatting a number. + * If not set, the decimal separator corresponding to [[locale]] will be used. + */ + public $decimalSeparator; + /** + * @var string the character displayed as the thousands separator character when formatting a number. + * If not set, the thousand separator corresponding to [[locale]] will be used. + */ + public $thousandSeparator; /** @@ -61,6 +80,16 @@ class Formatter extends \yii\base\Formatter if ($this->locale === null) { $this->locale = Yii::$app->language; } + if ($this->decimalSeparator === null || $this->thousandSeparator === null) { + $formatter = new NumberFormatter($this->locale, NumberFormatter::DECIMAL); + if ($this->decimalSeparator === null) { + $this->decimalSeparator = $formatter->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); + } + if ($this->thousandSeparator === null) { + $this->thousandSeparator = $formatter->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL); + } + } + parent::init(); } @@ -81,8 +110,11 @@ class Formatter extends \yii\base\Formatter * - a PHP DateTime object * * @param string $format the format used to convert the value into a date string. - * If null, [[dateFormat]] will be used. The format string should be the one - * that can be recognized by the PHP `date()` function. + * If null, [[dateFormat]] will be used. + * + * This can be "short", "medium", "long", or "full", which represents a preset format of different lengths. + * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime). + * * @return string the formatted result * @see dateFormat */ @@ -111,8 +143,11 @@ class Formatter extends \yii\base\Formatter * - a PHP DateTime object * * @param string $format the format used to convert the value into a date string. - * If null, [[dateFormat]] will be used. The format string should be the one - * that can be recognized by the PHP `date()` function. + * If null, [[dateFormat]] will be used. + * + * This can be "short", "medium", "long", or "full", which represents a preset format of different lengths. + * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime). + * * @return string the formatted result * @see timeFormat */ @@ -141,8 +176,11 @@ class Formatter extends \yii\base\Formatter * - a PHP DateTime object * * @param string $format the format used to convert the value into a date string. - * If null, [[dateFormat]] will be used. The format string should be the one - * that can be recognized by the PHP `date()` function. + * If null, [[dateFormat]] will be used. + * + * This can be "short", "medium", "long", or "full", which represents a preset format of different lengths. + * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime). + * * @return string the formatted result * @see datetimeFormat */ @@ -213,7 +251,7 @@ class Formatter extends \yii\base\Formatter /** * Creates a number formatter based on the given type and format. * @param integer $type the type of the number formatter - * @param string $format the format to be used + * @param string $format the format to be used. Please refer to [ICU manual](http://www.icu-project.org/apiref/icu4c/classDecimalFormat.html#_details) * @return NumberFormatter the created formatter instance */ protected function createNumberFormatter($type, $format) diff --git a/framework/yii/logging/Target.php b/framework/yii/logging/Target.php index fac8b53..7be7001 100644 --- a/framework/yii/logging/Target.php +++ b/framework/yii/logging/Target.php @@ -204,11 +204,9 @@ abstract class Target extends Component if ($matched) { foreach ($this->except as $category) { $prefix = rtrim($category, '*'); - foreach ($messages as $i => $message) { - if (strpos($message[2], $prefix) === 0 && ($message[2] === $category || $prefix !== $category)) { - $matched = false; - break; - } + if (strpos($message[2], $prefix) === 0 && ($message[2] === $category || $prefix !== $category)) { + $matched = false; + break; } } }