Browse Source

Merge remote branch 'upstream/master'

tags/2.0.0-beta
gevik 12 years ago
parent
commit
004a069c5d
  1. 27
      framework/yii/YiiBase.php
  2. 1
      framework/yii/base/Formatter.php
  3. 63
      framework/yii/base/HttpException.php
  4. 1
      framework/yii/base/InvalidCallException.php
  5. 1
      framework/yii/base/InvalidConfigException.php
  6. 1
      framework/yii/base/InvalidParamException.php
  7. 1
      framework/yii/base/InvalidRouteException.php
  8. 22
      framework/yii/base/Jsonable.php
  9. 13
      framework/yii/base/Model.php
  10. 1
      framework/yii/base/NotSupportedException.php
  11. 19
      framework/yii/base/Object.php
  12. 1
      framework/yii/base/UnknownClassException.php
  13. 1
      framework/yii/base/UnknownMethodException.php
  14. 1
      framework/yii/base/UnknownPropertyException.php
  15. 3
      framework/yii/bootstrap/Button.php
  16. 2
      framework/yii/bootstrap/ButtonDropdown.php
  17. 1
      framework/yii/bootstrap/ButtonGroup.php
  18. 1
      framework/yii/bootstrap/Dropdown.php
  19. 1
      framework/yii/bootstrap/Progress.php
  20. 1
      framework/yii/bootstrap/Widget.php
  21. 1
      framework/yii/caching/XCache.php
  22. 1
      framework/yii/console/Exception.php
  23. 4
      framework/yii/console/controllers/AssetController.php
  24. 3
      framework/yii/console/controllers/MessageController.php
  25. 5
      framework/yii/db/Connection.php
  26. 103
      framework/yii/db/pgsql/PDO.php
  27. 44
      framework/yii/db/pgsql/Schema.php
  28. 1
      framework/yii/helpers/Json.php
  29. 1
      framework/yii/helpers/base/Console.php
  30. 1
      framework/yii/helpers/base/Html.php
  31. 2
      framework/yii/helpers/base/Inflector.php
  32. 6
      framework/yii/helpers/base/Json.php
  33. 158
      framework/yii/i18n/DbMessageSource.php
  34. 9
      framework/yii/i18n/I18N.php
  35. 1
      framework/yii/i18n/MessageSource.php
  36. 2
      framework/yii/jui/Accordion.php
  37. 1
      framework/yii/jui/Menu.php
  38. 1
      framework/yii/jui/Widget.php
  39. 3
      framework/yii/rbac/DbManager.php
  40. 1
      framework/yii/validators/CaptchaValidator.php
  41. 1
      framework/yii/validators/DateValidator.php
  42. 1
      framework/yii/validators/DefaultValueValidator.php
  43. 1
      framework/yii/validators/ExistValidator.php
  44. 1
      framework/yii/validators/FilterValidator.php
  45. 1
      framework/yii/validators/StringValidator.php
  46. 1
      framework/yii/web/HeaderCollection.php
  47. 1
      framework/yii/web/Request.php
  48. 243
      framework/yii/web/Response.php
  49. 2
      framework/yii/web/UploadedFile.php
  50. 1
      framework/yii/widgets/ListPager.php
  51. 3
      tests/unit/data/config.php
  52. 1
      tests/unit/framework/web/ResponseTest.php

27
framework/yii/YiiBase.php

@ -606,11 +606,36 @@ class YiiBase
public static function t($category, $message, $params = array(), $language = null)
{
if (self::$app !== null) {
return self::$app->getI18N()->translate($category, $message, $params, $language);
return self::$app->getI18N()->translate($category, $message, $params, $language ?: self::$app->language);
} else {
return is_array($params) ? strtr($message, $params) : $message;
}
}
/**
* Configures an object with the initial property values.
* @param object $object the object to be configured
* @param array $properties the property initial values given in terms of name-value pairs.
*/
public static function configure($object, $properties)
{
foreach ($properties as $name => $value) {
$object->$name = $value;
}
}
/**
* Returns the public member variables of an object.
* This method is provided such that we can get the public member variables of an object.
* It is different from "get_object_vars()" because the latter will return private
* and protected variables if it is called within the object itself.
* @param object $object the object to be handled
* @return array the public member variables of the object
*/
public static function getObjectVars($object)
{
return get_object_vars($object);
}
}
YiiBase::$aliases = array(

1
framework/yii/base/Formatter.php

@ -12,7 +12,6 @@ use DateTime;
use yii\helpers\HtmlPurifier;
use yii\helpers\Html;
/**
* Formatter provides a set of commonly used data formatting methods.
*

63
framework/yii/base/HttpException.php

@ -7,6 +7,7 @@
namespace yii\base;
/**
* HttpException represents an exception caused by an improper request of the end-user.
*
@ -42,66 +43,8 @@ class HttpException extends UserException
*/
public function getName()
{
static $httpCodes = array(
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing',
118 => 'Connection timed out',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status',
210 => 'Content Different',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
307 => 'Temporary Redirect',
310 => 'Too many Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Time-out',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested range unsatisfiable',
417 => 'Expectation failed',
418 => 'I’m a teapot',
422 => 'Unprocessable entity',
423 => 'Locked',
424 => 'Method failure',
425 => 'Unordered Collection',
426 => 'Upgrade Required',
449 => 'Retry With',
450 => 'Blocked by Windows Parental Controls',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway ou Proxy Error',
503 => 'Service Unavailable',
504 => 'Gateway Time-out',
505 => 'HTTP Version not supported',
507 => 'Insufficient storage',
509 => 'Bandwidth Limit Exceeded',
);
if (isset($httpCodes[$this->statusCode])) {
return $httpCodes[$this->statusCode];
if (isset(\yii\web\Response::$statusTexts[$this->statusCode])) {
return \yii\web\Response::$statusTexts[$this->statusCode];
} else {
return 'Error';
}

1
framework/yii/base/InvalidCallException.php

@ -23,4 +23,3 @@ class InvalidCallException extends Exception
return \Yii::t('yii', 'Invalid Call');
}
}

1
framework/yii/base/InvalidConfigException.php

@ -23,4 +23,3 @@ class InvalidConfigException extends Exception
return \Yii::t('yii', 'Invalid Configuration');
}
}

1
framework/yii/base/InvalidParamException.php

@ -23,4 +23,3 @@ class InvalidParamException extends Exception
return \Yii::t('yii', 'Invalid Parameter');
}
}

1
framework/yii/base/InvalidRouteException.php

@ -23,4 +23,3 @@ class InvalidRouteException extends UserException
return \Yii::t('yii', 'Invalid Route');
}
}

22
framework/yii/base/Jsonable.php

@ -0,0 +1,22 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* Jsonable should be implemented by classes that need to be represented in JSON format.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
interface Jsonable
{
/**
* @return string the JSON representation of this object
*/
public function toJson();
}

13
framework/yii/base/Model.php

@ -10,6 +10,7 @@ namespace yii\base;
use ArrayObject;
use ArrayIterator;
use yii\helpers\Inflector;
use yii\helpers\Json;
use yii\validators\RequiredValidator;
use yii\validators\Validator;
@ -41,7 +42,7 @@ use yii\validators\Validator;
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Model extends Component implements \IteratorAggregate, \ArrayAccess
class Model extends Component implements \IteratorAggregate, \ArrayAccess, Jsonable
{
/**
* @event ModelEvent an event raised at the beginning of [[validate()]]. You may set
@ -638,6 +639,16 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
}
/**
* Returns the JSON representation of this object.
* The default implementation will return [[attributes]].
* @return string the JSON representation of this object.
*/
public function toJson()
{
return Json::encode($this->getAttributes());
}
/**
* Returns an iterator for traversing the attributes in the model.
* This method is required by the interface IteratorAggregate.
* @return ArrayIterator an iterator for traversing the items in the list.

1
framework/yii/base/NotSupportedException.php

@ -23,4 +23,3 @@ class NotSupportedException extends Exception
return \Yii::t('yii', 'Not Supported');
}
}

19
framework/yii/base/Object.php

@ -7,12 +7,15 @@
namespace yii\base;
use Yii;
use yii\helpers\Json;
/**
* @include @yii/base/Object.md
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Object
class Object implements Jsonable
{
/**
* @return string the fully qualified name of this class.
@ -38,8 +41,8 @@ class Object
*/
public function __construct($config = array())
{
foreach ($config as $name => $value) {
$this->$name = $value;
if (!empty($config)) {
Yii::configure($this, $config);
}
$this->init();
}
@ -216,4 +219,14 @@ class Object
{
return method_exists($this, 'set' . $name) || $checkVar && property_exists($this, $name);
}
/**
* Returns the JSON representation of this object.
* The default implementation will return all public member variables.
* @return string the JSON representation of this object.
*/
public function toJson()
{
return Json::encode(Yii::getObjectVars($this));
}
}

1
framework/yii/base/UnknownClassException.php

@ -23,4 +23,3 @@ class UnknownClassException extends Exception
return \Yii::t('yii', 'Unknown Class');
}
}

1
framework/yii/base/UnknownMethodException.php

@ -23,4 +23,3 @@ class UnknownMethodException extends Exception
return \Yii::t('yii', 'Unknown Method');
}
}

1
framework/yii/base/UnknownPropertyException.php

@ -23,4 +23,3 @@ class UnknownPropertyException extends Exception
return \Yii::t('yii', 'Unknown Property');
}
}

3
framework/yii/bootstrap/Button.php

@ -6,9 +6,8 @@
*/
namespace yii\bootstrap;
use yii\base\InvalidConfigException;
use yii\helpers\Html;
use yii\helpers\Html;
/**
* Button renders a bootstrap button.

2
framework/yii/bootstrap/ButtonDropdown.php

@ -6,8 +6,8 @@
*/
namespace yii\bootstrap;
use yii\helpers\Html;
use yii\helpers\Html;
/**
* ButtonDropdown renders a group or split button dropdown bootstrap component.

1
framework/yii/bootstrap/ButtonGroup.php

@ -10,7 +10,6 @@ namespace yii\bootstrap;
use yii\helpers\base\ArrayHelper;
use yii\helpers\Html;
/**
* ButtonGroup renders a button group bootstrap component.
*

1
framework/yii/bootstrap/Dropdown.php

@ -11,7 +11,6 @@ use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
/**
* Dropdown renders a Bootstrap dropdown menu component.
*

1
framework/yii/bootstrap/Progress.php

@ -11,7 +11,6 @@ use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
/**
* Progress renders a bootstrap progress bar component.
*

1
framework/yii/bootstrap/Widget.php

@ -11,7 +11,6 @@ use Yii;
use yii\base\View;
use yii\helpers\Json;
/**
* \yii\bootstrap\Widget is the base class for all bootstrap widgets.
*

1
framework/yii/caching/XCache.php

@ -86,4 +86,3 @@ class XCache extends Cache
return true;
}
}

1
framework/yii/console/Exception.php

@ -25,4 +25,3 @@ class Exception extends UserException
return \Yii::t('yii', 'Error');
}
}

4
framework/yii/console/controllers/AssetController.php

@ -164,7 +164,6 @@ class AssetController extends Controller
protected function loadConfiguration($configFile)
{
echo "Loading configuration from '{$configFile}'...\n";
foreach (require($configFile) as $name => $value) {
if (property_exists($this, $name) || $this->canSetProperty($name)) {
$this->$name = $value;
@ -221,7 +220,8 @@ class AssetController extends Controller
* @param array $result already loaded bundles list.
* @throws \yii\console\Exception on failure.
*/
protected function loadBundleDependency($name, $bundle, &$result) {
protected function loadBundleDependency($name, $bundle, &$result)
{
if (!empty($bundle->depends)) {
$assetManager = $this->getAssetManager();
foreach ($bundle->depends as $dependencyName) {

3
framework/yii/console/controllers/MessageController.php

@ -179,8 +179,7 @@ class MessageController extends Controller
}
ksort($translated);
foreach ($translated as $message => $translation) {
if (!isset($merged[$message]) && !isset($todo[$message]) && !$removeOld)
{
if (!isset($merged[$message]) && !isset($todo[$message]) && !$removeOld) {
if (substr($translation, 0, 2) === '@@' && substr($translation, -2) === '@@') {
$todo[$message]=$translation;
} else {

5
framework/yii/db/Connection.php

@ -305,8 +305,7 @@ class Connection extends Component
$this->pdo = $this->createPdoInstance();
$this->initConnection();
Yii::endProfile($token, __METHOD__);
}
catch (\PDOException $e) {
} catch (\PDOException $e) {
Yii::endProfile($token, __METHOD__);
Yii::error("Failed to open DB connection ({$this->dsn}): " . $e->getMessage(), __METHOD__);
$message = YII_DEBUG ? 'Failed to open DB connection: ' . $e->getMessage() : 'Failed to open DB connection.';
@ -343,8 +342,6 @@ class Connection extends Component
$driver = strtolower(substr($this->dsn, 0, $pos));
if ($driver === 'mssql' || $driver === 'dblib' || $driver === 'sqlsrv') {
$pdoClass = 'yii\db\mssql\PDO';
} else if ($driver === 'pgsql') {
$pdoClass = 'yii\db\pgsql\PDO';
}
}
return new $pdoClass($this->dsn, $this->username, $this->password, $this->attributes);

103
framework/yii/db/pgsql/PDO.php

@ -1,103 +0,0 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\db\pgsql;
/**
* This is an extension of the default PDO class for PostgreSQL drivers.
* It provides additional low level functionality for setting database
* configuration parameters.
*
* @author Gevik babakhani <gevikb@gmail.com>
* @since 2.0
*/
class PDO extends \PDO
{
const OPT_SEARCH_PATH = 'search_path';
const OPT_DEFAULT_SCHEMA = 'default_schema';
const DEFAULT_SCHEMA = 'public';
private $_currentDatabase;
/**
* Returns value of the last inserted ID.
* @param string|null $sequence the sequence name. Defaults to null.
* @return integer last inserted ID value.
*/
public function lastInsertId($sequence = null) {
if ($sequence !== null) {
$sequence = $this->quote($sequence);
return $this->query("SELECT currval({$sequence})")->fetchColumn();
} else {
return null;
}
}
/**
* Here we override the default PDO constructor in order to
* find and set the default schema search path.
*/
public function __construct($dsn, $username, $passwd, $options) {
$searchPath = null;
if (is_array($options)) {
if (isset($options[self::OPT_SEARCH_PATH])) {
$matches = null;
if (preg_match("/(\s?)+(\w)+((\s+)?,(\s+)?\w+)*/", $options[self::OPT_SEARCH_PATH], $matches) === 1) {
$searchPath = $matches[0];
}
}
if (isset($options[self::OPT_DEFAULT_SCHEMA])) {
$schema = trim($options[self::OPT_DEFAULT_SCHEMA]);
if (!empty($schema)) {
Schema::$DEFAULT_SCHEMA = $schema;
}
}
if (is_null(Schema::$DEFAULT_SCHEMA) || empty(Schema::$DEFAULT_SCHEMA)) {
Schema::$DEFAULT_SCHEMA = self::DEFAULT_SCHEMA;
}
}
parent::__construct($dsn, $username, $passwd, $options);
if (!is_null($searchPath)) {
$this->setSchemaSearchPath($searchPath);
}
}
/**
* Returns the name of the current (connected) database
* @return string
*/
public function getCurrentDatabase() {
if (is_null($this->_currentDatabase)) {
return $this->query('select current_database()')->fetchColumn();
}
}
/**
* Sets the schema search path of the current users session.
* The syntax of the path is a comma separated string with
* your custom search path at the beginning and the "public"
* schema at the end.
*
* This method automatically adds the "public" schema at the
* end of the search path if it is not provied.
* @param string custom schema search path. defaults to public
*/
public function setSchemaSearchPath($searchPath = 'public') {
$schemas = explode(',', str_replace(' ', '', $searchPath));
if (end($schemas) !== 'public') {
$schemas[] = 'public';
}
foreach ($schemas as $k => $item) {
$schemas[$k] = '"' . str_replace(array('"', "'", ';'), '', $item) . '"';
}
$path = implode(', ', $schemas);
$this->exec('SET search_path TO ' . $path);
}
}

44
framework/yii/db/pgsql/Schema.php

@ -22,11 +22,10 @@ class Schema extends \yii\db\Schema
{
/**
* The default schema used for the current session. This value is
* automatically set to "public" by the PDO driver.
* The default schema used for the current session.
* @var string
*/
public static $DEFAULT_SCHEMA;
public $defaultSchema = 'public';
/**
* @var array mapping from physical column types (keys) to abstract
@ -77,7 +76,8 @@ class Schema extends \yii\db\Schema
* Creates a query builder for the MySQL database.
* @return QueryBuilder query builder instance
*/
public function createQueryBuilder() {
public function createQueryBuilder()
{
return new QueryBuilder($this->db);
}
@ -86,7 +86,8 @@ class Schema extends \yii\db\Schema
* @param TableSchema $table the table metadata object
* @param string $name the table name
*/
protected function resolveTableNames($table, $name) {
protected function resolveTableNames($table, $name)
{
$parts = explode('.', str_replace('"', '', $name));
if (isset($parts[1])) {
$table->schemaName = $parts[0];
@ -95,7 +96,7 @@ class Schema extends \yii\db\Schema
$table->name = $parts[0];
}
if ($table->schemaName === null) {
$table->schemaName = self::$DEFAULT_SCHEMA;
$table->schemaName = $this->defaultSchema;
}
}
@ -105,7 +106,8 @@ class Schema extends \yii\db\Schema
* @param string $name table name
* @return string the properly quoted table name
*/
public function quoteSimpleTableName($name) {
public function quoteSimpleTableName($name)
{
return strpos($name, '"') !== false ? $name : '"' . $name . '"';
}
@ -114,12 +116,15 @@ class Schema extends \yii\db\Schema
* @param string $name table name
* @return TableSchema|null driver dependent table metadata. Null if the table does not exist.
*/
public function loadTableSchema($name) {
public function loadTableSchema($name)
{
$table = new TableSchema();
$this->resolveTableNames($table, $name);
if ($this->findColumns($table)) {
$this->findConstraints($table);
return $table;
} else {
return null;
}
}
@ -127,11 +132,11 @@ class Schema extends \yii\db\Schema
* Collects the foreign key column details for the given table.
* @param TableSchema $table the table metadata
*/
protected function findConstraints($table) {
protected function findConstraints($table)
{
$tableName = $this->quoteValue($table->name);
$tableSchema = $this->quoteValue($table->schemaName);
$database = $this->quoteValue($this->db->pdo->getCurrentDatabase());
//We need to extract the constraints de hard way since:
//http://www.postgresql.org/message-id/26677.1086673982@sss.pgh.pa.us
@ -158,14 +163,9 @@ where
ct.contype='f'
and c.relname={$tableName}
and ns.nspname={$tableSchema}
and current_database() = {$database}
SQL;
try {
$constraints = $this->db->createCommand($sql)->queryAll();
} catch (\Exception $e) {
return false;
}
foreach ($constraints as $constraint) {
$columns = explode(',', $constraint['columns']);
$fcolumns = explode(',', $constraint['foreign_columns']);
@ -175,7 +175,6 @@ SQL;
}
$table->foreignKeys[] = $citem;
}
return true;
}
/**
@ -183,8 +182,8 @@ SQL;
* @param TableSchema $table the table metadata
* @return boolean whether the table exists in the database
*/
protected function findColumns($table) {
$dbname = $this->db->quoteValue($this->db->pdo->getCurrentDatabase());
protected function findColumns($table)
{
$tableName = $this->db->quoteValue($table->name);
$schemaName = $this->db->quoteValue($table->schemaName);
$sql = <<<SQL
@ -239,16 +238,15 @@ WHERE
a.attnum > 0
and c.relname = {$tableName}
and d.nspname = {$schemaName}
and current_database() = {$dbname}
ORDER BY
a.attnum;
SQL;
try {
$columns = $this->db->createCommand($sql)->queryAll();
} catch (\Exception $e) {
if (empty($columns)) {
return false;
}
foreach ($columns as $column) {
$column = $this->loadColumnSchema($column);
$table->columns[$column->name] = $column;
@ -267,7 +265,8 @@ SQL;
* @param array $info column information
* @return ColumnSchema the column schema object
*/
protected function loadColumnSchema($info) {
protected function loadColumnSchema($info)
{
$column = new ColumnSchema();
$column->allowNull = $info['is_nullable'];
$column->autoIncrement = $info['is_autoinc'];
@ -290,5 +289,4 @@ SQL;
$column->phpType = $this->getColumnPhpType($column);
return $column;
}
}

1
framework/yii/helpers/Json.php

@ -14,5 +14,4 @@ namespace yii\helpers;
*/
class Json extends base\Json
{
}

1
framework/yii/helpers/base/Console.php

@ -593,7 +593,6 @@ class Console
return $size = array((int)preg_replace('~[^0-9]~', '', $output[3]), (int)preg_replace('~[^0-9]~', '', $output[4]));
}
} else {
// try stty if available
$stty = array();
if (exec('stty -a 2>&1', $stty) && preg_match('/rows\s+(\d+);\s*columns\s+(\d+);/mi', implode(' ', $stty), $matches)) {

1
framework/yii/helpers/base/Html.php

@ -1479,5 +1479,4 @@ class Html
$name = strtolower(static::getInputName($model, $attribute));
return str_replace(array('[]', '][', '[', ']', ' '), array('', '-', '-', '', '-'), $name);
}
}

2
framework/yii/helpers/base/Inflector.php

@ -468,7 +468,7 @@ class Inflector
if (in_array(($number % 100), range(11, 13))) {
return $number . 'th';
}
switch (($number % 10)) {
switch ($number % 10) {
case 1: return $number . 'st';
case 2: return $number . 'nd';
case 3: return $number . 'rd';

6
framework/yii/helpers/base/Json.php

@ -8,6 +8,7 @@
namespace yii\helpers\base;
use yii\base\InvalidParamException;
use yii\base\Jsonable;
use yii\web\JsExpression;
/**
@ -90,7 +91,9 @@ class Json
$token = '!{[' . count($expressions) . ']}!';
$expressions['"' . $token . '"'] = $data->expression;
return $token;
}
} elseif ($data instanceof Jsonable) {
return $data->toJson();
} else {
$result = array();
foreach ($data as $key => $value) {
if (is_array($value) || is_object($value)) {
@ -100,6 +103,7 @@ class Json
}
}
return $result;
}
} else {
return $data;
}

158
framework/yii/i18n/DbMessageSource.php

@ -0,0 +1,158 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\i18n;
use Yii;
use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
use yii\caching\Cache;
use yii\db\Connection;
use yii\db\Query;
/**
* DbMessageSource extends [[MessageSource]] and represents a message source that stores translated
* messages in database.
*
* The database must contain the following two tables:
*
* ~~~
* CREATE TABLE tbl_source_message (
* id INTEGER PRIMARY KEY,
* category VARCHAR(32),
* message TEXT
* );
*
* CREATE TABLE tbl_message (
* id INTEGER,
* language VARCHAR(16),
* translation TEXT,
* PRIMARY KEY (id, language),
* CONSTRAINT fk_message_source_message FOREIGN KEY (id)
* REFERENCES tbl_source_message (id) ON DELETE CASCADE ON UPDATE RESTRICT
* );
* ~~~
*
* The `tbl_source_message` table stores the messages to be translated, and the `tbl_message` table stores
* the translated messages. The name of these two tables can be customized by setting [[sourceMessageTable]]
* and [[messageTable]], respectively.
*
* @author resurtm <resurtm@gmail.com>
* @since 2.0
*/
class DbMessageSource extends MessageSource
{
/**
* Prefix which would be used when generating cache key.
*/
const CACHE_KEY_PREFIX = 'DbMessageSource';
/**
* @var Connection|string the DB connection object or the application component ID of the DB connection.
* After the DbMessageSource object is created, if you want to change this property, you should only assign
* it with a DB connection object.
*/
public $db = 'db';
/**
* @var Cache|string the cache object or the application component ID of the cache object.
* The messages data will be cached using this cache object. Note, this property has meaning only
* in case [[cachingDuration]] set to non-zero value.
* After the DbMessageSource object is created, if you want to change this property, you should only assign
* it with a cache object.
*/
public $cache = 'cache';
/**
* @var string the name of the source message table.
*/
public $sourceMessageTable = 'tbl_source_message';
/**
* @var string the name of the translated message table.
*/
public $messageTable = 'tbl_message';
/**
* @var integer the time in seconds that the messages can remain valid in cache.
* Use 0 to indicate that the cached data will never expire.
* @see enableCaching
*/
public $cachingDuration = 0;
/**
* @var boolean whether to enable caching translated messages
*/
public $enableCaching = false;
/**
* Initializes the DbMessageSource component.
* This method will initialize the [[db]] property to make sure it refers to a valid DB connection.
* Configured [[cache]] component would also be initialized.
* @throws InvalidConfigException if [[db]] is invalid or [[cache]] is invalid.
*/
public function init()
{
parent::init();
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
}
if (!$this->db instanceof Connection) {
throw new InvalidConfigException("DbMessageSource::db must be either a DB connection instance or the application component ID of a DB connection.");
}
if ($this->enableCaching) {
if (is_string($this->cache)) {
$this->cache = Yii::$app->getComponent($this->cache);
}
if (!$this->cache instanceof Cache) {
throw new InvalidConfigException("DbMessageSource::cache must be either a cache object or the application component ID of the cache object.");
}
}
}
/**
* Loads the message translation for the specified language and category.
* Child classes should override this method to return the message translations of
* the specified language and category.
* @param string $category the message category
* @param string $language the target language
* @return array the loaded messages. The keys are original messages, and the values
* are translated messages.
*/
protected function loadMessages($category, $language)
{
if ($this->enableCaching) {
$key = array(
__CLASS__,
$category,
$language,
);
$messages = $this->cache->get($key);
if ($messages === false) {
$messages = $this->loadMessagesFromDb($category, $language);
$this->cache->set($key, $messages, $this->cachingDuration);
}
return $messages;
} else {
return $this->loadMessagesFromDb($category, $language);
}
}
/**
* Loads the messages from database.
* You may override this method to customize the message storage in the database.
* @param string $category the message category.
* @param string $language the target language.
* @return array the messages loaded from database.
*/
protected function loadMessagesFromDb($category, $language)
{
$query = new Query();
$messages = $query->select(array('t1.message message', 't2.translation translation'))
->from(array($this->sourceMessageTable . ' t1', $this->messageTable . ' t2'))
->where('t1.id = t2.id AND t1.category = :category AND t2.language = :language')
->params(array(':category' => $category, ':language' => $language))
->createCommand($this->db)
->queryAll();
return ArrayHelper::map($messages, 'message', 'translation');
}
}

9
framework/yii/i18n/I18N.php

@ -78,16 +78,11 @@ class I18N extends Component
* @param string $category the message category.
* @param string $message the message to be translated.
* @param array $params the parameters that will be used to replace the corresponding placeholders in the message.
* @param string $language the language code (e.g. `en_US`, `en`). If this is null, the current
* [[\yii\base\Application::language|application language]] will be used.
* @param string $language the language code (e.g. `en_US`, `en`).
* @return string the translated message.
*/
public function translate($category, $message, $params = array(), $language = null)
public function translate($category, $message, $params, $language)
{
if ($language === null) {
$language = Yii::$app->language;
}
$message = $this->getMessageSource($category)->translate($category, $message, $language);
if (!is_array($params)) {

1
framework/yii/i18n/MessageSource.php

@ -118,4 +118,3 @@ class MessageSource extends Component
}
}
}

2
framework/yii/jui/Accordion.php

@ -125,7 +125,7 @@ class Accordion extends Widget
$items[] = Html::tag($headerTag, $item['header'], $headerOptions);
$options = array_merge($this->itemOptions, ArrayHelper::getValue($item, 'options', array()));
$tag = ArrayHelper::remove($options, 'tag', 'div');
$items[] = Html::tag($tag, $item['content'], $options);;
$items[] = Html::tag($tag, $item['content'], $options);
}
return implode("\n", $items);

1
framework/yii/jui/Menu.php

@ -10,7 +10,6 @@ namespace yii\jui;
use Yii;
use yii\helpers\Json;
/**
* Menu renders a menu jQuery UI widget.
*

1
framework/yii/jui/Widget.php

@ -10,7 +10,6 @@ namespace yii\jui;
use Yii;
use yii\helpers\Json;
/**
* \yii\jui\Widget is the base class for all jQuery UI widgets.
*

3
framework/yii/rbac/DbManager.php

@ -493,9 +493,10 @@ class DbManager extends Manager
'bizRule' => $row['biz_rule'],
'data' => $data,
));
} else
} else {
return null;
}
}
/**
* Saves an authorization item to persistent storage.

1
framework/yii/validators/CaptchaValidator.php

@ -117,4 +117,3 @@ class CaptchaValidator extends Validator
return 'yii.validation.captcha(value, messages, ' . json_encode($options) . ');';
}
}

1
framework/yii/validators/DateValidator.php

@ -73,4 +73,3 @@ class DateValidator extends Validator
return DateTime::createFromFormat($this->format, $value) !== false;
}
}

1
framework/yii/validators/DefaultValueValidator.php

@ -40,4 +40,3 @@ class DefaultValueValidator extends Validator
}
}
}

1
framework/yii/validators/ExistValidator.php

@ -99,4 +99,3 @@ class ExistValidator extends Validator
return $query->exists();
}
}

1
framework/yii/validators/FilterValidator.php

@ -6,6 +6,7 @@
*/
namespace yii\validators;
use yii\base\InvalidConfigException;
/**

1
framework/yii/validators/StringValidator.php

@ -174,4 +174,3 @@ class StringValidator extends Validator
return 'yii.validation.string(value, messages, ' . json_encode($options) . ');';
}
}

1
framework/yii/web/HeaderCollection.php

@ -11,7 +11,6 @@ use Yii;
use yii\base\Object;
use ArrayIterator;
/**
* HeaderCollection is used by [[Response]] to maintain the currently registered HTTP headers.
*

1
framework/yii/web/Request.php

@ -792,4 +792,3 @@ class Request extends \yii\base\Request
}
}
}

243
framework/yii/web/Response.php

@ -9,8 +9,10 @@ namespace yii\web;
use Yii;
use yii\base\HttpException;
use yii\base\InvalidParamException;
use yii\helpers\FileHelper;
use yii\helpers\Html;
use yii\helpers\Json;
use yii\helpers\StringHelper;
/**
@ -27,9 +29,122 @@ class Response extends \yii\base\Response
* @see redirect
*/
public $ajaxRedirectCode = 278;
/**
* @var string
*/
public $content;
/**
* @var string
*/
public $statusText;
/**
* @var string the charset to use. If not set, [[\yii\base\Application::charset]] will be used.
*/
public $charset;
/**
* @var string the version of the HTTP protocol to use
*/
public $version = '1.0';
/**
* @var array list of HTTP status codes and the corresponding texts
*/
public static $statusTexts = array(
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing',
118 => 'Connection timed out',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status',
208 => 'Already Reported',
210 => 'Content Different',
226 => 'IM Used',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
306 => 'Reserved',
307 => 'Temporary Redirect',
308 => 'Permanent Redirect',
310 => 'Too many Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Time-out',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested range unsatisfiable',
417 => 'Expectation failed',
418 => 'I’m a teapot',
422 => 'Unprocessable entity',
423 => 'Locked',
424 => 'Method failure',
425 => 'Unordered Collection',
426 => 'Upgrade Required',
428 => 'Precondition Required',
429 => 'Too Many Requests',
431 => 'Request Header Fields Too Large',
449 => 'Retry With',
450 => 'Blocked by Windows Parental Controls',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway ou Proxy Error',
503 => 'Service Unavailable',
504 => 'Gateway Time-out',
505 => 'HTTP Version not supported',
507 => 'Insufficient storage',
508 => 'Loop Detected',
509 => 'Bandwidth Limit Exceeded',
510 => 'Not Extended',
511 => 'Network Authentication Required',
);
private $_statusCode = 200;
/**
* @var HeaderCollection
*/
private $_headers;
public function init()
{
if ($this->charset === null) {
$this->charset = Yii::$app->charset;
}
}
public function getStatusCode()
{
return $this->_statusCode;
}
public function setStatusCode($value)
{
$this->_statusCode = (int)$value;
if ($this->isInvalid()) {
throw new InvalidParamException("The HTTP status code is invalid: $value");
}
$this->statusText = isset(self::$statusTexts[$this->_statusCode]) ? self::$statusTexts[$this->_statusCode] : '';
}
/**
* Returns the header collection.
* The header collection contains the currently registered HTTP headers.
@ -43,6 +158,52 @@ class Response extends \yii\base\Response
return $this->_headers;
}
public function renderJson($data)
{
$this->getHeaders()->set('content-type', 'application/json');
$this->content = Json::encode($data);
}
public function renderJsonp($data, $callbackName)
{
$this->getHeaders()->set('content-type', 'text/javascript');
$data = Json::encode($data);
$this->content = "$callbackName($data);";
}
/**
* Sends the response to the client.
* @return boolean true if the response was sent
*/
public function send()
{
$this->sendHeaders();
$this->sendContent();
}
/**
* Sends the response headers to the client
*/
protected function sendHeaders()
{
header("HTTP/{$this->version} " . $this->getStatusCode() . " {$this->statusText}");
foreach ($this->_headers as $name => $values) {
foreach ($values as $value) {
header("$name: $value");
}
}
$this->_headers->removeAll();
}
/**
* Sends the response content to the client
*/
protected function sendContent()
{
echo $this->content;
$this->content = null;
}
/**
* Sends a file to user.
* @param string $fileName file name
@ -201,7 +362,7 @@ class Response extends \yii\base\Response
}
if (!isset($options['mimeType'])) {
if (($options['mimeType'] = CFileHelper::getMimeTypeByExtension($filePath)) === null) {
if (($options['mimeType'] = FileHelper::getMimeTypeByExtension($filePath)) === null) {
$options['mimeType'] = 'text/plain';
}
}
@ -303,4 +464,84 @@ class Response extends \yii\base\Response
{
return Yii::$app->getRequest()->getCookies();
}
/**
* @return boolean whether this response has a valid [[statusCode]].
*/
public function isInvalid()
{
return $this->getStatusCode() < 100 || $this->getStatusCode() >= 600;
}
/**
* @return boolean whether this response is informational
*/
public function isInformational()
{
return $this->getStatusCode() >= 100 && $this->getStatusCode() < 200;
}
/**
* @return boolean whether this response is successfully
*/
public function isSuccessful()
{
return $this->getStatusCode() >= 200 && $this->getStatusCode() < 300;
}
/**
* @return boolean whether this response is a redirection
*/
public function isRedirection()
{
return $this->getStatusCode() >= 300 && $this->getStatusCode() < 400;
}
/**
* @return boolean whether this response indicates a client error
*/
public function isClientError()
{
return $this->getStatusCode() >= 400 && $this->getStatusCode() < 500;
}
/**
* @return boolean whether this response indicates a server error
*/
public function isServerError()
{
return $this->getStatusCode() >= 500 && $this->getStatusCode() < 600;
}
/**
* @return boolean whether this response is OK
*/
public function isOk()
{
return 200 === $this->getStatusCode();
}
/**
* @return boolean whether this response indicates the current request is forbidden
*/
public function isForbidden()
{
return 403 === $this->getStatusCode();
}
/**
* @return boolean whether this response indicates the currently requested resource is not found
*/
public function isNotFound()
{
return 404 === $this->getStatusCode();
}
/**
* @return boolean whether this response is empty
*/
public function isEmpty()
{
return in_array($this->getStatusCode(), array(201, 204, 304));
}
}

2
framework/yii/web/UploadedFile.php

@ -7,7 +7,7 @@
namespace yii\web;
use yii\widgets\Html;
use yii\helpers\Html;
/**
* @author Qiang Xue <qiang.xue@gmail.com>

1
framework/yii/widgets/ListPager.php

@ -91,5 +91,4 @@ class ListPager extends Widget
'{page}' => $page + 1,
));
}
}

3
tests/unit/data/config.php

@ -22,9 +22,6 @@ return array(
'dsn' => 'pgsql:host=localhost;dbname=yiitest;port=5432;',
'username' => 'postgres',
'password' => 'postgres',
'attributes' => array(
'search_path' => 'master,hello'
),
'fixture' => __DIR__ . '/postgres.sql',
)
)

1
tests/unit/framework/web/ResponseTest.php

@ -32,6 +32,7 @@ class ResponseTest extends \yiiunit\TestCase
protected function setUp()
{
parent::setUp();
$this->mockApplication();
$this->reset();
}

Loading…
Cancel
Save