Browse Source

Fixed merge

tags/2.0.0-beta
sensorario 12 years ago
parent
commit
dc31ea9892
  1. 2
      .gitignore
  2. 7
      apps/bootstrap/index.php
  3. 15
      apps/bootstrap/protected/config/main.php
  4. 9
      apps/bootstrap/protected/controllers/SiteController.php
  5. 2
      apps/bootstrap/protected/models/ContactForm.php
  6. 26
      apps/bootstrap/protected/views/layouts/main.php
  7. 14
      apps/bootstrap/protected/views/site/contact.php
  8. 4
      apps/bootstrap/protected/views/site/login.php
  9. 2
      build/build
  10. 8
      composer.json
  11. 212
      composer.lock
  12. BIN
      docs/internals/exception_hierarchy.png
  13. BIN
      docs/internals/exception_hierarchy.vsd
  14. 470
      framework/helpers/base/ConsoleColor.php
  15. 282
      framework/widgets/Menu.php
  16. 50
      tests/unit/DatabaseTestCase.php
  17. 2
      tests/unit/bootstrap.php
  18. 18
      tests/unit/data/config.php
  19. BIN
      tests/unit/data/i18n/test.mo
  20. 64
      tests/unit/data/i18n/test.po
  21. 6
      tests/unit/data/mysql.sql
  22. 350
      tests/unit/data/sqlite.sql
  23. 1
      tests/unit/framework/YiiBaseTest.php
  24. 6
      tests/unit/framework/caching/ApcCacheTest.php
  25. 3
      tests/unit/framework/caching/DbCacheTest.php
  26. 3
      tests/unit/framework/db/ActiveRecordTest.php
  27. 2
      tests/unit/framework/db/CommandTest.php
  28. 11
      tests/unit/framework/db/ConnectionTest.php
  29. 2
      tests/unit/framework/db/QueryTest.php
  30. 12
      tests/unit/framework/db/sqlite/SqliteActiveRecordTest.php
  31. 21
      tests/unit/framework/db/sqlite/SqliteCommandTest.php
  32. 47
      tests/unit/framework/db/sqlite/SqliteConnectionTest.php
  33. 20
      tests/unit/framework/db/sqlite/SqliteQueryTest.php
  34. 10
      tests/unit/framework/helpers/ArrayHelperTest.php
  35. 44
      tests/unit/framework/helpers/StringHelperTest.php
  36. 14
      tests/unit/framework/i18n/GettextMessageSourceTest.php
  37. 95
      tests/unit/framework/i18n/GettextMoFileTest.php
  38. 95
      tests/unit/framework/i18n/GettextPoFileTest.php
  39. 248
      tests/unit/framework/rbac/ManagerTestBase.php
  40. 34
      tests/unit/framework/rbac/PhpManagerTest.php
  41. 2
      tests/web/app/index.php
  42. 0
      yii/.htaccess
  43. 0
      yii/Yii.php
  44. 11
      yii/YiiBase.php
  45. 14
      yii/assets.php
  46. 0
      yii/assets/jquery.min.js
  47. 6
      yii/assets/yii.activeForm.js
  48. 72
      yii/assets/yii.captcha.js
  49. 26
      yii/assets/yii.debug.js
  50. 0
      yii/assets/yii.js
  51. 2
      yii/assets/yii.validation.js
  52. 0
      yii/base/Action.php
  53. 0
      yii/base/ActionEvent.php
  54. 0
      yii/base/ActionFilter.php
  55. 16
      yii/base/Application.php
  56. 0
      yii/base/Behavior.php
  57. 0
      yii/base/Component.php
  58. 5
      yii/base/Controller.php
  59. 4
      yii/base/Dictionary.php
  60. 0
      yii/base/DictionaryIterator.php
  61. 0
      yii/base/ErrorException.php
  62. 0
      yii/base/ErrorHandler.php
  63. 0
      yii/base/Event.php
  64. 0
      yii/base/Exception.php
  65. 0
      yii/base/HttpException.php
  66. 0
      yii/base/InlineAction.php
  67. 0
      yii/base/InvalidCallException.php
  68. 0
      yii/base/InvalidConfigException.php
  69. 0
      yii/base/InvalidParamException.php
  70. 0
      yii/base/InvalidRequestException.php
  71. 0
      yii/base/InvalidRouteException.php
  72. 0
      yii/base/Model.php
  73. 0
      yii/base/ModelEvent.php
  74. 0
      yii/base/Module.php
  75. 0
      yii/base/NotSupportedException.php
  76. 8
      yii/base/Object.php
  77. 0
      yii/base/Request.php
  78. 0
      yii/base/Response.php
  79. 0
      yii/base/Theme.php
  80. 0
      yii/base/UnknownClassException.php
  81. 0
      yii/base/UnknownMethodException.php
  82. 0
      yii/base/UnknownPropertyException.php
  83. 0
      yii/base/UserException.php
  84. 2
      yii/base/Vector.php
  85. 0
      yii/base/VectorIterator.php
  86. 12
      yii/base/View.php
  87. 0
      yii/base/ViewEvent.php
  88. 0
      yii/base/ViewRenderer.php
  89. 0
      yii/base/Widget.php
  90. 0
      yii/caching/ApcCache.php
  91. 0
      yii/caching/Cache.php
  92. 0
      yii/caching/ChainedDependency.php
  93. 0
      yii/caching/DbCache.php
  94. 0
      yii/caching/DbDependency.php
  95. 0
      yii/caching/Dependency.php
  96. 0
      yii/caching/DummyCache.php
  97. 0
      yii/caching/ExpressionDependency.php
  98. 0
      yii/caching/FileCache.php
  99. 0
      yii/caching/FileDependency.php
  100. 0
      yii/caching/MemCache.php
  101. Some files were not shown because too many files have changed in this diff Show More

2
.gitignore vendored

@ -13,4 +13,4 @@ nbproject
Thumbs.db
# composer vendor dir
vendor
/yii/vendor

7
apps/bootstrap/index.php

@ -1,8 +1,13 @@
<?php
// comment out the following line to disable debug mode
defined('YII_DEBUG') or define('YII_DEBUG', true);
require(__DIR__ . '/../../framework/yii.php');
$frameworkPath = __DIR__ . '/../../yii';
require($frameworkPath . '/Yii.php');
// Register Composer autoloader
@include($frameworkPath . '/vendor/autoload.php');
$config = require(__DIR__ . '/protected/config/main.php');
$application = new yii\web\Application($config);

15
apps/bootstrap/protected/config/main.php

@ -3,6 +3,12 @@
return array(
'id' => 'hello',
'basePath' => dirname(__DIR__),
'preload' => array('log'),
'modules' => array(
'debug' => array(
'class' => 'yii\debug\Module',
)
),
'components' => array(
'cache' => array(
'class' => 'yii\caching\FileCache',
@ -14,6 +20,15 @@ return array(
'assetManager' => array(
'bundles' => require(__DIR__ . '/assets.php'),
),
'log' => array(
'class' => 'yii\logging\Router',
'targets' => array(
'file' => array(
'class' => 'yii\logging\FileTarget',
'levels' => array('error', 'warning'),
),
),
),
),
'params' => array(
'adminEmail' => 'admin@example.com',

9
apps/bootstrap/protected/controllers/SiteController.php

@ -6,6 +6,15 @@ use app\models\ContactForm;
class SiteController extends Controller
{
public function actions()
{
return array(
'captcha' => array(
'class' => 'yii\web\CaptchaAction',
),
);
}
public function actionIndex()
{
echo $this->render('index');

2
apps/bootstrap/protected/models/ContactForm.php

@ -26,7 +26,7 @@ class ContactForm extends Model
// email has to be a valid email address
array('email', 'email'),
// verifyCode needs to be entered correctly
//array('verifyCode', 'captcha', 'allowEmpty' => !Captcha::checkRequirements()),
array('verifyCode', 'captcha'),
);
}

26
apps/bootstrap/protected/views/layouts/main.php

@ -1,9 +1,11 @@
<?php
use yii\helpers\Html;
use yii\widgets\Menu;
/**
* @var $this \yii\base\View
* @var $content string
*/
use yii\helpers\Html;
$this->registerAssetBundle('app');
?>
<?php $this->beginPage(); ?>
@ -23,16 +25,17 @@ $this->registerAssetBundle('app');
<div class="navbar">
<div class="navbar-inner">
<div class="container">
<ul class="nav">
<li><?php echo Html::a('Home', Yii::$app->homeUrl); ?></li>
<li><?php echo Html::a('About', array('/site/about')); ?></li>
<li><?php echo Html::a('Contact', array('/site/contact')); ?></li>
<?php if (Yii::$app->user->isGuest): ?>
<li><?php echo Html::a('Login', array('/site/login')); ?></li>
<?php else: ?>
<li><?php echo Html::a('Logout (' . Html::encode(Yii::$app->user->identity->username) . ')', array('/site/logout')); ?></li>
<?php endif; ?>
</ul>
<?php $this->widget(Menu::className(), array(
'options' => array('class' => 'nav'),
'items' => array(
array('label' => 'Home', 'url' => array('/site/index')),
array('label' => 'About', 'url' => array('/site/about')),
array('label' => 'Contact', 'url' => array('/site/contact')),
Yii::$app->user->isGuest ?
array('label' => 'Login', 'url' => array('/site/login')) :
array('label' => 'Logout (' . Yii::$app->user->identity->username .')' , 'url' => array('/site/logout')),
),
)); ?>
</div>
</div>
</div>
@ -55,6 +58,7 @@ $this->registerAssetBundle('app');
</div>
<?php $this->endBody(); ?>
</div>
<?php $this->widget('yii\debug\Toolbar'); ?>
</body>
</html>
<?php $this->endPage(); ?>

14
apps/bootstrap/protected/views/site/contact.php

@ -1,5 +1,8 @@
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\widgets\Captcha;
/**
* @var yii\base\View $this
* @var yii\widgets\ActiveForm $form
@ -20,7 +23,7 @@ $this->params['breadcrumbs'][] = $this->title;
If you have business inquiries or other questions, please fill out the following form to contact us. Thank you.
</p>
<?php $form = $this->beginWidget('yii\widgets\ActiveForm', array(
<?php $form = $this->beginWidget(ActiveForm::className(), array(
'options' => array('class' => 'form-horizontal'),
'fieldConfig' => array('inputOptions' => array('class' => 'input-xlarge')),
)); ?>
@ -28,6 +31,15 @@ $this->params['breadcrumbs'][] = $this->title;
<?php echo $form->field($model, 'email')->textInput(); ?>
<?php echo $form->field($model, 'subject')->textInput(); ?>
<?php echo $form->field($model, 'body')->textArea(array('rows' => 6)); ?>
<?php
$field = $form->field($model, 'verifyCode');
echo $field->begin();
echo $field->label();
$this->widget(Captcha::className());
echo Html::activeTextInput($model, 'verifyCode', array('class' => 'input-medium'));
echo $field->error();
echo $field->end();
?>
<div class="form-actions">
<?php echo Html::submitButton('Submit', null, null, array('class' => 'btn btn-primary')); ?>
</div>

4
apps/bootstrap/protected/views/site/login.php

@ -1,5 +1,7 @@
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/**
* @var yii\base\View $this
* @var yii\widgets\ActiveForm $form
@ -12,7 +14,7 @@ $this->params['breadcrumbs'][] = $this->title;
<p>Please fill out the following fields to login:</p>
<?php $form = $this->beginWidget('yii\widgets\ActiveForm', array('options' => array('class' => 'form-horizontal'))); ?>
<?php $form = $this->beginWidget(ActiveForm::className(), array('options' => array('class' => 'form-horizontal'))); ?>
<?php echo $form->field($model, 'username')->textInput(); ?>
<?php echo $form->field($model, 'password')->passwordInput(); ?>
<?php echo $form->field($model, 'rememberMe')->checkbox(); ?>

2
build/build

@ -11,7 +11,7 @@
// fcgi doesn't have STDIN defined by default
defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
require(__DIR__ . '/../framework/yii.php');
require(__DIR__ . '/../framework/Yii.php');
$id = 'yiic-build';
$basePath = __DIR__;

8
composer.json

@ -63,13 +63,17 @@
"irc": "irc://irc.freenode.net/yii",
"source": "https://github.com/yiisoft/yii2"
},
"config": {
"vendor-dir": "yii/vendor"
},
"bin": [
"framework/yiic"
"yii/yiic"
],
"require": {
"php": ">=5.3.0",
"michelf/php-markdown": "1.3",
"twig/twig": "1.12.*",
"smarty/smarty": "3.1.*"
"smarty/smarty": "3.1.*",
"ezyang/htmlpurifier": "v4.5.0"
}
}

212
composer.lock generated

@ -0,0 +1,212 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
],
"hash": "7d46ce9c4d8d5f4ecae1611ea8f0b49c",
"packages": [
{
"name": "ezyang/htmlpurifier",
"version": "v4.5.0",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "v4.5.0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/v4.5.0",
"reference": "v4.5.0",
"shasum": ""
},
"require": {
"php": ">=5.2"
},
"type": "library",
"autoload": {
"psr-0": {
"HTMLPurifier": "library/"
},
"files": [
"library/HTMLPurifier.composer.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL"
],
"authors": [
{
"name": "Edward Z. Yang",
"email": "admin@htmlpurifier.org",
"homepage": "http://ezyang.com"
}
],
"description": "Standards compliant HTML filter written in PHP",
"homepage": "http://htmlpurifier.org/",
"keywords": [
"html"
],
"time": "2013-02-18 00:04:08"
},
{
"name": "michelf/php-markdown",
"version": "1.3",
"source": {
"type": "git",
"url": "https://github.com/michelf/php-markdown.git",
"reference": "1.3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/michelf/php-markdown/zipball/1.3",
"reference": "1.3",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-lib": "1.3.x-dev"
}
},
"autoload": {
"psr-0": {
"Michelf": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Michel Fortin",
"email": "michel.fortin@michelf.ca",
"homepage": "http://michelf.ca/",
"role": "Developer"
},
{
"name": "John Gruber",
"homepage": "http://daringfireball.net/"
}
],
"description": "PHP Markdown",
"homepage": "http://michelf.ca/projects/php-markdown/",
"keywords": [
"markdown"
],
"time": "2013-04-11 18:53:11"
},
{
"name": "smarty/smarty",
"version": "v3.1.13",
"source": {
"type": "svn",
"url": "http://smarty-php.googlecode.com/svn",
"reference": "/tags/v3.1.13/@4699"
},
"require": {
"php": ">=5.2"
},
"type": "library",
"autoload": {
"classmap": [
"distribution/libs/Smarty.class.php",
"distribution/libs/SmartyBC.class.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0"
],
"authors": [
{
"name": "Monte Ohrt",
"email": "monte@ohrt.com"
},
{
"name": "Uwe Tews",
"email": "uwe.tews@googlemail.com"
},
{
"name": "Rodney Rehm",
"email": "rodney.rehm@medialize.de"
}
],
"description": "Smarty - the compiling PHP template engine",
"homepage": "http://www.smarty.net",
"keywords": [
"templating"
],
"time": "2013-01-26 12:03:52"
},
{
"name": "twig/twig",
"version": "v1.12.3",
"source": {
"type": "git",
"url": "https://github.com/fabpot/Twig.git",
"reference": "v1.12.3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fabpot/Twig/zipball/v1.12.3",
"reference": "v1.12.3",
"shasum": ""
},
"require": {
"php": ">=5.2.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.12-dev"
}
},
"autoload": {
"psr-0": {
"Twig_": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "http://twig.sensiolabs.org",
"keywords": [
"templating"
],
"time": "2013-04-08 12:40:11"
}
],
"packages-dev": [
],
"aliases": [
],
"minimum-stability": "stable",
"stability-flags": [
],
"platform": {
"php": ">=5.3.0"
},
"platform-dev": [
]
}

BIN
docs/internals/exception_hierarchy.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

BIN
docs/internals/exception_hierarchy.vsd

Binary file not shown.

470
framework/helpers/base/ConsoleColor.php

@ -1,470 +0,0 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\helpers\base;
// todo test this on all kinds of terminals, especially windows (check out lib ncurses)
/**
* Console View is the base class for console view components
*
* A console view provides functionality to create rich console application by allowing to format output
* by adding color and font style to it.
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class ConsoleColor
{
const FG_BLACK = 30;
const FG_RED = 31;
const FG_GREEN = 32;
const FG_YELLOW = 33;
const FG_BLUE = 34;
const FG_PURPLE = 35;
const FG_CYAN = 36;
const FG_GREY = 37;
const BG_BLACK = 40;
const BG_RED = 41;
const BG_GREEN = 42;
const BG_YELLOW = 43;
const BG_BLUE = 44;
const BG_PURPLE = 45;
const BG_CYAN = 46;
const BG_GREY = 47;
const BOLD = 1;
const ITALIC = 3;
const UNDERLINE = 4;
const BLINK = 5;
const NEGATIVE = 7;
const CONCEALED = 8;
const CROSSED_OUT = 9;
const FRAMED = 51;
const ENCIRCLED = 52;
const OVERLINED = 53;
/**
* Moves the terminal cursor up by sending ANSI control code CUU to the terminal.
* If the cursor is already at the edge of the screen, this has no effect.
* @param integer $rows number of rows the cursor should be moved up
*/
public static function moveCursorUp($rows=1)
{
echo "\033[" . (int) $rows . 'A';
}
/**
* Moves the terminal cursor down by sending ANSI control code CUD to the terminal.
* If the cursor is already at the edge of the screen, this has no effect.
* @param integer $rows number of rows the cursor should be moved down
*/
public static function moveCursorDown($rows=1)
{
echo "\033[" . (int) $rows . 'B';
}
/**
* Moves the terminal cursor forward by sending ANSI control code CUF to the terminal.
* If the cursor is already at the edge of the screen, this has no effect.
* @param integer $steps number of steps the cursor should be moved forward
*/
public static function moveCursorForward($steps=1)
{
echo "\033[" . (int) $steps . 'C';
}
/**
* Moves the terminal cursor backward by sending ANSI control code CUB to the terminal.
* If the cursor is already at the edge of the screen, this has no effect.
* @param integer $steps number of steps the cursor should be moved backward
*/
public static function moveCursorBackward($steps=1)
{
echo "\033[" . (int) $steps . 'D';
}
/**
* Moves the terminal cursor to the beginning of the next line by sending ANSI control code CNL to the terminal.
* @param integer $lines number of lines the cursor should be moved down
*/
public static function moveCursorNextLine($lines=1)
{
echo "\033[" . (int) $lines . 'E';
}
/**
* Moves the terminal cursor to the beginning of the previous line by sending ANSI control code CPL to the terminal.
* @param integer $lines number of lines the cursor should be moved up
*/
public static function moveCursorPrevLine($lines=1)
{
echo "\033[" . (int) $lines . 'F';
}
/**
* Moves the cursor to an absolute position given as column and row by sending ANSI control code CUP or CHA to the terminal.
* @param integer $column 1-based column number, 1 is the left edge of the screen.
* @param integer|null $row 1-based row number, 1 is the top edge of the screen. if not set, will move cursor only in current line.
*/
public static function moveCursorTo($column, $row=null)
{
if ($row === null) {
echo "\033[" . (int) $column . 'G';
} else {
echo "\033[" . (int) $row . ';' . (int) $column . 'H';
}
}
/**
* Scrolls whole page up by sending ANSI control code SU to the terminal.
* New lines are added at the bottom. This is not supported by ANSI.SYS used in windows.
* @param int $lines number of lines to scroll up
*/
public static function scrollUp($lines=1)
{
echo "\033[".(int)$lines."S";
}
/**
* Scrolls whole page down by sending ANSI control code SD to the terminal.
* New lines are added at the top. This is not supported by ANSI.SYS used in windows.
* @param int $lines number of lines to scroll down
*/
public static function scrollDown($lines=1)
{
echo "\033[".(int)$lines."T";
}
/**
* Saves the current cursor position by sending ANSI control code SCP to the terminal.
* Position can then be restored with {@link restoreCursorPosition}.
*/
public static function saveCursorPosition()
{
echo "\033[s";
}
/**
* Restores the cursor position saved with {@link saveCursorPosition} by sending ANSI control code RCP to the terminal.
*/
public static function restoreCursorPosition()
{
echo "\033[u";
}
/**
* Hides the cursor by sending ANSI DECTCEM code ?25l to the terminal.
* Use {@link showCursor} to bring it back.
* Do not forget to show cursor when your application exits. Cursor might stay hidden in terminal after exit.
*/
public static function hideCursor()
{
echo "\033[?25l";
}
/**
* Will show a cursor again when it has been hidden by {@link hideCursor} by sending ANSI DECTCEM code ?25h to the terminal.
*/
public static function showCursor()
{
echo "\033[?25h";
}
/**
* Clears entire screen content by sending ANSI control code ED with argument 2 to the terminal.
* Cursor position will not be changed.
* **Note:** ANSI.SYS implementation used in windows will reset cursor position to upper left corner of the screen.
*/
public static function clearScreen()
{
echo "\033[2J";
}
/**
* Clears text from cursor to the beginning of the screen by sending ANSI control code ED with argument 1 to the terminal.
* Cursor position will not be changed.
*/
public static function clearScreenBeforeCursor()
{
echo "\033[1J";
}
/**
* Clears text from cursor to the end of the screen by sending ANSI control code ED with argument 0 to the terminal.
* Cursor position will not be changed.
*/
public static function clearScreenAfterCursor()
{
echo "\033[0J";
}
/**
* Clears the line, the cursor is currently on by sending ANSI control code EL with argument 2 to the terminal.
* Cursor position will not be changed.
*/
public static function clearLine()
{
echo "\033[2K";
}
/**
* Clears text from cursor position to the beginning of the line by sending ANSI control code EL with argument 1 to the terminal.
* Cursor position will not be changed.
*/
public static function clearLineBeforeCursor()
{
echo "\033[1K";
}
/**
* Clears text from cursor position to the end of the line by sending ANSI control code EL with argument 0 to the terminal.
* Cursor position will not be changed.
*/
public static function clearLineAfterCursor()
{
echo "\033[0K";
}
/**
* Will send ANSI format for following output
*
* You can pass any of the FG_*, BG_* and TEXT_* constants and also xterm256ColorBg
* TODO: documentation
*/
public static function ansiStyle()
{
echo "\033[" . implode(';', func_get_args()) . 'm';
}
/**
* Will return a string formatted with the given ANSI style
*
* See {@link ansiStyle} for possible arguments.
* @param string $string the string to be formatted
* @return string
*/
public static function ansiStyleString($string)
{
$args = func_get_args();
array_shift($args);
$code = implode(';', $args);
return "\033[0m" . ($code !== '' ? "\033[" . $code . "m" : '') . $string."\033[0m";
}
//const COLOR_XTERM256 = 38;// http://en.wikipedia.org/wiki/Talk:ANSI_escape_code#xterm-256colors
public static function xterm256ColorFg($i) // TODO naming!
{
return '38;5;'.$i;
}
public static function xterm256ColorBg($i) // TODO naming!
{
return '48;5;'.$i;
}
/**
* Usage: list($w, $h) = ConsoleHelper::getScreenSize();
*
* @return array
*/
public static function getScreenSize()
{
// TODO implement
return array(150,50);
}
/**
* resets any ansi style set by previous method {@link ansiStyle}
* Any output after this is will have default text style.
*/
public static function reset()
{
echo "\033[0m";
}
/**
* Strips ANSI control codes from a string
*
* @param string $string String to strip
* @return string
*/
public static function strip($string)
{
return preg_replace('/\033\[[\d;]+m/', '', $string); // TODO currently only strips color
}
// TODO refactor and review
public static function ansiToHtml($string)
{
$tags = 0;
return preg_replace_callback('/\033\[[\d;]+m/', function($ansi) use (&$tags) {
$styleA = array();
foreach(explode(';', $ansi) as $controlCode)
{
switch($controlCode)
{
case static::FG_BLACK: $style = array('color' => '#000000'); break;
case static::FG_BLUE: $style = array('color' => '#000078'); break;
case static::FG_CYAN: $style = array('color' => '#007878'); break;
case static::FG_GREEN: $style = array('color' => '#007800'); break;
case static::FG_GREY: $style = array('color' => '#787878'); break;
case static::FG_PURPLE: $style = array('color' => '#780078'); break;
case static::FG_RED: $style = array('color' => '#780000'); break;
case static::FG_YELLOW: $style = array('color' => '#787800'); break;
case static::BG_BLACK: $style = array('background-color' => '#000000'); break;
case static::BG_BLUE: $style = array('background-color' => '#000078'); break;
case static::BG_CYAN: $style = array('background-color' => '#007878'); break;
case static::BG_GREEN: $style = array('background-color' => '#007800'); break;
case static::BG_GREY: $style = array('background-color' => '#787878'); break;
case static::BG_PURPLE: $style = array('background-color' => '#780078'); break;
case static::BG_RED: $style = array('background-color' => '#780000'); break;
case static::BG_YELLOW: $style = array('background-color' => '#787800'); break;
case static::BOLD: $style = array('font-weight' => 'bold'); break;
case static::ITALIC: $style = array('font-style' => 'italic'); break;
case static::UNDERLINE: $style = array('text-decoration' => array('underline')); break;
case static::OVERLINED: $style = array('text-decoration' => array('overline')); break;
case static::CROSSED_OUT:$style = array('text-decoration' => array('line-through')); break;
case static::BLINK: $style = array('text-decoration' => array('blink')); break;
case static::NEGATIVE: // ???
case static::CONCEALED:
case static::ENCIRCLED:
case static::FRAMED:
// TODO allow resetting codes
break;
case 0: // ansi reset
$return = '';
for($n=$tags; $tags>0; $tags--) {
$return .= '</span>';
}
return $return;
}
$styleA = ArrayHelper::merge($styleA, $style);
}
$styleString[] = array();
foreach($styleA as $name => $content) {
if ($name === 'text-decoration') {
$content = implode(' ', $content);
}
$styleString[] = $name.':'.$content;
}
$tags++;
return '<span' . (!empty($styleString) ? 'style="' . implode(';', $styleString) : '') . '>';
}, $string);
}
/**
* TODO syntax copied from https://github.com/pear/Console_Color2/blob/master/Console/Color2.php
*
* Converts colorcodes in the format %y (for yellow) into ansi-control
* codes. The conversion table is: ('bold' meaning 'light' on some
* terminals). It's almost the same conversion table irssi uses.
* <pre>
* text text background
* ------------------------------------------------
* %k %K %0 black dark grey black
* %r %R %1 red bold red red
* %g %G %2 green bold green green
* %y %Y %3 yellow bold yellow yellow
* %b %B %4 blue bold blue blue
* %m %M %5 magenta bold magenta magenta
* %p %P magenta (think: purple)
* %c %C %6 cyan bold cyan cyan
* %w %W %7 white bold white white
*
* %F Blinking, Flashing
* %U Underline
* %8 Reverse
* %_,%9 Bold
*
* %n Resets the color
* %% A single %
* </pre>
* First param is the string to convert, second is an optional flag if
* colors should be used. It defaults to true, if set to false, the
* colorcodes will just be removed (And %% will be transformed into %)
*
* @param string $string String to convert
* @param bool $colored Should the string be colored?
*
* @return string
*/
public static function renderColoredString($string)
{
$colored = true;
static $conversions = array ( // static so the array doesn't get built
// everytime
// %y - yellow, and so on... {{{
'%y' => array('color' => 'yellow'),
'%g' => array('color' => 'green' ),
'%b' => array('color' => 'blue' ),
'%r' => array('color' => 'red' ),
'%p' => array('color' => 'purple'),
'%m' => array('color' => 'purple'),
'%c' => array('color' => 'cyan' ),
'%w' => array('color' => 'grey' ),
'%k' => array('color' => 'black' ),
'%n' => array('color' => 'reset' ),
'%Y' => array('color' => 'yellow', 'style' => 'light'),
'%G' => array('color' => 'green', 'style' => 'light'),
'%B' => array('color' => 'blue', 'style' => 'light'),
'%R' => array('color' => 'red', 'style' => 'light'),
'%P' => array('color' => 'purple', 'style' => 'light'),
'%M' => array('color' => 'purple', 'style' => 'light'),
'%C' => array('color' => 'cyan', 'style' => 'light'),
'%W' => array('color' => 'grey', 'style' => 'light'),
'%K' => array('color' => 'black', 'style' => 'light'),
'%N' => array('color' => 'reset', 'style' => 'light'),
'%3' => array('background' => 'yellow'),
'%2' => array('background' => 'green' ),
'%4' => array('background' => 'blue' ),
'%1' => array('background' => 'red' ),
'%5' => array('background' => 'purple'),
'%6' => array('background' => 'cyan' ),
'%7' => array('background' => 'grey' ),
'%0' => array('background' => 'black' ),
// Don't use this, I can't stand flashing text
'%F' => array('style' => 'blink'),
'%U' => array('style' => 'underline'),
'%8' => array('style' => 'inverse'),
'%9' => array('style' => 'bold'),
'%_' => array('style' => 'bold')
// }}}
);
if ($colored) {
$string = str_replace('%%', '% ', $string);
foreach ($conversions as $key => $value) {
$string = str_replace($key, Console_Color::color($value),
$string);
}
$string = str_replace('% ', '%', $string);
} else {
$string = preg_replace('/%((%)|.)/', '$2', $string);
}
return $string;
}
/**
* Escapes % so they don't get interpreted as color codes
*
* @param string $string String to escape
*
* @access public
* @return string
*/
public static function escape($string)
{
return str_replace('%', '%%', $string);
}
}

282
framework/widgets/Menu.php

@ -1,282 +0,0 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\widgets;
use yii\base\Widget;
use yii\helpers\Html;
/**
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Menu extends Widget
{
/**
* @var array list of menu items. Each menu item is specified as an array of name-value pairs.
* Possible option names include the following:
* <ul>
* <li>label: string, optional, specifies the menu item label. When {@link encodeLabel} is true, the label
* will be HTML-encoded. If the label is not specified, it defaults to an empty string.</li>
* <li>url: string or array, optional, specifies the URL of the menu item. It is passed to {@link Html::normalizeUrl}
* to generate a valid URL. If this is not set, the menu item will be rendered as a span text.</li>
* <li>visible: boolean, optional, whether this menu item is visible. Defaults to true.
* This can be used to control the visibility of menu items based on user permissions.</li>
* <li>items: array, optional, specifies the sub-menu items. Its format is the same as the parent items.</li>
* <li>active: boolean, optional, whether this menu item is in active state (currently selected).
* If a menu item is active and {@link activeClass} is not empty, its CSS class will be appended with {@link activeClass}.
* If this option is not set, the menu item will be set active automatically when the current request
* is triggered by {@link url}. Note that the GET parameters not specified in the 'url' option will be ignored.</li>
* <li>template: string, optional, the template used to render this menu item.
* When this option is set, it will override the global setting {@link itemTemplate}.
* Please see {@link itemTemplate} for more details. This option has been available since version 1.1.1.</li>
* <li>linkOptions: array, optional, additional HTML attributes to be rendered for the link or span tag of the menu item.</li>
* <li>itemOptions: array, optional, additional HTML attributes to be rendered for the container tag of the menu item.</li>
* <li>submenuOptions: array, optional, additional HTML attributes to be rendered for the container of the submenu if this menu item has one.
* When this option is set, the {@link submenuHtmlOptions} property will be ignored for this particular submenu.
* This option has been available since version 1.1.6.</li>
* </ul>
*/
public $items = array();
/**
* @var string the template used to render an individual menu item. In this template,
* the token "{menu}" will be replaced with the corresponding menu link or text.
* If this property is not set, each menu will be rendered without any decoration.
* This property will be overridden by the 'template' option set in individual menu items via {@items}.
* @since 1.1.1
*/
public $itemTemplate;
/**
* @var boolean whether the labels for menu items should be HTML-encoded. Defaults to true.
*/
public $encodeLabel = true;
/**
* @var string the CSS class to be appended to the active menu item. Defaults to 'active'.
* If empty, the CSS class of menu items will not be changed.
*/
public $activeCssClass = 'active';
/**
* @var boolean whether to automatically activate items according to whether their route setting
* matches the currently requested route. Defaults to true.
* @since 1.1.3
*/
public $activateItems = true;
/**
* @var boolean whether to activate parent menu items when one of the corresponding child menu items is active.
* The activated parent menu items will also have its CSS classes appended with {@link activeCssClass}.
* Defaults to false.
*/
public $activateParents = false;
/**
* @var boolean whether to hide empty menu items. An empty menu item is one whose 'url' option is not
* set and which doesn't contain visible child menu items. Defaults to true.
*/
public $hideEmptyItems = true;
/**
* @var array HTML attributes for the menu's root container tag
*/
public $options = array();
/**
* @var array HTML attributes for the submenu's container tag.
*/
public $submenuHtmlOptions = array();
/**
* @var string the HTML element name that will be used to wrap the label of all menu links.
* For example, if this property is set as 'span', a menu item may be rendered as
* &lt;li&gt;&lt;a href="url"&gt;&lt;span&gt;label&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
* This is useful when implementing menu items using the sliding window technique.
* Defaults to null, meaning no wrapper tag will be generated.
* @since 1.1.4
*/
public $linkLabelWrapper;
/**
* @var array HTML attributes for the links' wrap element specified in
* {@link linkLabelWrapper}.
* @since 1.1.13
*/
public $linkLabelWrapperHtmlOptions = array();
/**
* @var string the CSS class that will be assigned to the first item in the main menu or each submenu.
* Defaults to null, meaning no such CSS class will be assigned.
* @since 1.1.4
*/
public $firstItemCssClass;
/**
* @var string the CSS class that will be assigned to the last item in the main menu or each submenu.
* Defaults to null, meaning no such CSS class will be assigned.
* @since 1.1.4
*/
public $lastItemCssClass;
/**
* @var string the CSS class that will be assigned to every item.
* Defaults to null, meaning no such CSS class will be assigned.
* @since 1.1.9
*/
public $itemCssClass;
/**
* Initializes the menu widget.
* This method mainly normalizes the {@link items} property.
* If this method is overridden, make sure the parent implementation is invoked.
*/
public function init()
{
$route = $this->getController()->getRoute();
$this->items = $this->normalizeItems($this->items, $route, $hasActiveChild);
}
/**
* Calls {@link renderMenu} to render the menu.
*/
public function run()
{
if (count($this->items)) {
echo Html::beginTag('ul', $this->options) . "\n";
$this->renderItems($this->items);
echo Html::endTag('ul');
}
}
/**
* Recursively renders the menu items.
* @param array $items the menu items to be rendered recursively
*/
protected function renderItems($items)
{
$count = 0;
$n = count($items);
foreach ($items as $item) {
$count++;
$options = isset($item['itemOptions']) ? $item['itemOptions'] : array();
$class = array();
if ($item['active'] && $this->activeCssClass != '') {
$class[] = $this->activeCssClass;
}
if ($count === 1 && $this->firstItemCssClass !== null) {
$class[] = $this->firstItemCssClass;
}
if ($count === $n && $this->lastItemCssClass !== null) {
$class[] = $this->lastItemCssClass;
}
if ($this->itemCssClass !== null) {
$class[] = $this->itemCssClass;
}
if ($class !== array()) {
if (empty($options['class'])) {
$options['class'] = implode(' ', $class);
} else {
$options['class'] .= ' ' . implode(' ', $class);
}
}
echo Html::beginTag('li', $options);
$menu = $this->renderItem($item);
if (isset($this->itemTemplate) || isset($item['template'])) {
$template = isset($item['template']) ? $item['template'] : $this->itemTemplate;
echo strtr($template, array('{menu}' => $menu));
} else {
echo $menu;
}
if (isset($item['items']) && count($item['items'])) {
echo "\n" . Html::beginTag('ul', isset($item['submenuOptions']) ? $item['submenuOptions'] : $this->submenuHtmlOptions) . "\n";
$this->renderItems($item['items']);
echo Html::endTag('ul') . "\n";
}
echo Html::endTag('li') . "\n";
}
}
/**
* Renders the content of a menu item.
* Note that the container and the sub-menus are not rendered here.
* @param array $item the menu item to be rendered. Please see {@link items} on what data might be in the item.
* @return string
* @since 1.1.6
*/
protected function renderItem($item)
{
if (isset($item['url'])) {
$label = $this->linkLabelWrapper === null ? $item['label'] : Html::tag($this->linkLabelWrapper, $this->linkLabelWrapperHtmlOptions, $item['label']);
return Html::a($label, $item['url'], isset($item['linkOptions']) ? $item['linkOptions'] : array());
} else {
return Html::tag('span', isset($item['linkOptions']) ? $item['linkOptions'] : array(), $item['label']);
}
}
/**
* Normalizes the {@link items} property so that the 'active' state is properly identified for every menu item.
* @param array $items the items to be normalized.
* @param string $route the route of the current request.
* @param boolean $active whether there is an active child menu item.
* @return array the normalized menu items
*/
protected function normalizeItems($items, $route, &$active)
{
foreach ($items as $i => $item) {
if (isset($item['visible']) && !$item['visible']) {
unset($items[$i]);
continue;
}
if (!isset($item['label'])) {
$item['label'] = '';
}
if ($this->encodeLabel) {
$items[$i]['label'] = Html::encode($item['label']);
}
$hasActiveChild = false;
if (isset($item['items'])) {
$items[$i]['items'] = $this->normalizeItems($item['items'], $route, $hasActiveChild);
if (empty($items[$i]['items']) && $this->hideEmptyItems) {
unset($items[$i]['items']);
if (!isset($item['url'])) {
unset($items[$i]);
continue;
}
}
}
if (!isset($item['active'])) {
if ($this->activateParents && $hasActiveChild || $this->activateItems && $this->isItemActive($item, $route)) {
$active = $items[$i]['active'] = true;
} else {
$items[$i]['active'] = false;
}
} elseif ($item['active']) {
$active = true;
}
}
return array_values($items);
}
/**
* Checks whether a menu item is active.
* This is done by checking if the currently requested URL is generated by the 'url' option
* of the menu item. Note that the GET parameters not specified in the 'url' option will be ignored.
* @param array $item the menu item to be checked
* @param string $route the route of the current request
* @return boolean whether the menu item is active
*/
protected function isItemActive($item, $route)
{
if (isset($item['url']) && is_array($item['url']) && !strcasecmp(trim($item['url'][0], '/'), $route)) {
unset($item['url']['#']);
if (count($item['url']) > 1) {
foreach (array_splice($item['url'], 1) as $name => $value) {
if (!isset($_GET[$name]) || $_GET[$name] != $value) {
return false;
}
}
}
return true;
}
return false;
}
}

50
tests/unit/DatabaseTestCase.php

@ -0,0 +1,50 @@
<?php
namespace yiiunit;
class DatabaseTestCase extends TestCase
{
protected $database;
protected $driverName = 'mysql';
protected $db;
protected function setUp()
{
$databases = $this->getParam('databases');
$this->database = $databases[$this->driverName];
$pdo_database = 'pdo_'.$this->driverName;
if (!extension_loaded('pdo') || !extension_loaded($pdo_database)) {
$this->markTestSkipped('pdo and pdo_'.$pdo_database.' extension are required.');
}
}
/**
* @param bool $reset whether to clean up the test database
* @param bool $open whether to open and populate test database
* @return \yii\db\Connection
*/
public function getConnection($reset = true, $open = true)
{
if (!$reset && $this->db) {
return $this->db;
}
$db = new \yii\db\Connection;
$db->dsn = $this->database['dsn'];
if (isset($this->database['username'])) {
$db->username = $this->database['username'];
$db->password = $this->database['password'];
}
if ($open) {
$db->open();
$lines = explode(';', file_get_contents($this->database['fixture']));
foreach ($lines as $line) {
if (trim($line) !== '') {
$db->pdo->exec($line);
}
}
}
$this->db = $db;
return $db;
}
}

2
tests/unit/bootstrap.php

@ -5,7 +5,7 @@ define('YII_DEBUG', true);
$_SERVER['SCRIPT_NAME'] = '/' . __DIR__;
$_SERVER['SCRIPT_FILENAME'] = __FILE__;
require_once(__DIR__ . '/../../framework/yii.php');
require_once(__DIR__ . '/../../yii/Yii.php');
Yii::setAlias('@yiiunit', __DIR__);

18
tests/unit/data/config.php

@ -1,10 +1,16 @@
<?php
return array(
'mysql' => array(
'dsn' => 'mysql:host=127.0.0.1;dbname=yiitest',
'username' => 'travis',
'password' => '',
'fixture' => __DIR__ . '/mysql.sql',
),
'databases' => array(
'mysql' => array(
'dsn' => 'mysql:host=127.0.0.1;dbname=yiitest',
'username' => 'travis',
'password' => '',
'fixture' => __DIR__ . '/mysql.sql',
),
'sqlite' => array(
'dsn' => 'sqlite::memory:',
'fixture' => __DIR__ . '/sqlite.sql',
),
)
);

BIN
tests/unit/data/i18n/test.mo

Binary file not shown.

64
tests/unit/data/i18n/test.po

@ -0,0 +1,64 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: resurtm <resurtm@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.5.5\n"
msgctxt "context1"
msgid ""
"Aliquam tempus elit vel purus molestie placerat. In sollicitudin tincidunt\n"
"aliquet. Integer tincidunt gravida tempor. In convallis blandit dui vel "
"malesuada.\n"
"Nunc vel sapien nunc, a pretium nulla."
msgstr ""
"Олицетворение однократно. Представленный лексико-семантический анализ "
"является\n"
"психолингвистическим в своей основе, но механизм сочленений полидисперсен. "
"Впечатление\n"
"однократно. Различное расположение выбирает сюжетный механизм сочленений."
msgctxt "context1"
msgid "String number two."
msgstr "Строка номер два."
msgctxt "context2"
msgid ""
"The other\n"
"\n"
"context.\n"
msgstr ""
"Другой\n"
"\n"
"контекст.\n"
msgctxt "context1"
msgid ""
"Missing\n"
"\r\t\"translation."
msgstr ""
msgctxt "context1"
msgid ""
"Nunc vel sapien nunc, a pretium nulla.\n"
"Pellentesque habitant morbi tristique senectus et netus et malesuada fames "
"ac turpis egestas."
msgstr "Короткий перевод."
msgid "contextless"
msgstr ""
msgctxt "context2"
msgid ""
"test1\\ntest2\n"
"\\\n"
"test3"
msgstr ""
"тест1\\nтест2\n"
"\\\n"
"тест3"

6
tests/unit/data/mysql.sql

@ -1,10 +1,6 @@
/**
* This is the database schema for testing MySQL support of Yii DAO and Active Record.
* The following database setup is required to perform then relevant tests:
* Database name: yiitest
* username: test
* password: test
* charset: utf8
* The database setup in config.php is required to perform then relevant tests:
*/
DROP TABLE IF EXISTS tbl_order_item CASCADE;

350
tests/unit/data/sqlite.sql

@ -1,262 +1,88 @@
CREATE TABLE users
(
id INTEGER NOT NULL PRIMARY KEY,
username VARCHAR(128) NOT NULL,
password VARCHAR(128) NOT NULL,
email VARCHAR(128) NOT NULL
);
INSERT INTO users(id,username,password,email) VALUES (1,'user1','pass1','email1');
INSERT INTO users(id,username,password,email) VALUES (2,'user2','pass2','email2');
INSERT INTO users(id,username,password,email) VALUES (3,'user3','pass3','email3');
INSERT INTO users(id,username,password,email) VALUES (4,'user4','pass4','email4');
CREATE TABLE groups
(
id INTEGER NOT NULL PRIMARY KEY,
name VARCHAR(128) NOT NULL
);
INSERT INTO groups(id,name) VALUES (1,'group1');
INSERT INTO groups(id,name) VALUES (2,'group2');
INSERT INTO groups(id,name) VALUES (3,'group3');
INSERT INTO groups(id,name) VALUES (4,'group4');
INSERT INTO groups(id,name) VALUES (5,'group5');
INSERT INTO groups(id,name) VALUES (6,'group6');
CREATE TABLE groups_descriptions
(
group_id INTEGER NOT NULL PRIMARY KEY,
name VARCHAR(128) NOT NULL
);
INSERT INTO groups_descriptions(group_id,name) VALUES (1,'room1');
INSERT INTO groups_descriptions(group_id,name) VALUES (2,'room2');
INSERT INTO groups_descriptions(group_id,name) VALUES (3,'room3');
INSERT INTO groups_descriptions(group_id,name) VALUES (4,'room4');
CREATE TABLE roles
(
user_id INTEGER NOT NULL,
group_id INTEGER NOT NULL,
name VARCHAR(128) NOT NULL,
PRIMARY KEY(user_id,group_id)
);
INSERT INTO roles(user_id,group_id,name) VALUES (1,1,'dev');
INSERT INTO roles(user_id,group_id,name) VALUES (1,2,'user');
INSERT INTO roles(user_id,group_id,name) VALUES (2,1,'dev');
INSERT INTO roles(user_id,group_id,name) VALUES (2,3,'user');
CREATE TABLE mentorships
(
teacher_id INTEGER NOT NULL,
student_id INTEGER NOT NULL,
progress VARCHAR(128) NOT NULL,
PRIMARY KEY(teacher_id,student_id)
);
INSERT INTO mentorships(teacher_id,student_id,progress) VALUES (1,3,'good');
INSERT INTO mentorships(teacher_id,student_id,progress) VALUES (2,4,'average');
CREATE TABLE profiles
(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
first_name VARCHAR(128) NOT NULL,
last_name VARCHAR(128) NOT NULL,
user_id INTEGER NOT NULL,
CONSTRAINT FK_profile_user FOREIGN KEY (user_id)
REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT
);
INSERT INTO profiles (first_name, last_name, user_id) VALUES ('first 1','last 1',1);
INSERT INTO profiles (first_name, last_name, user_id) VALUES ('first 2','last 2',2);
CREATE TABLE posts
(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
title VARCHAR(128) NOT NULL,
create_time TIMESTAMP NOT NULL,
author_id INTEGER NOT NULL,
content TEXT,
CONSTRAINT FK_post_author FOREIGN KEY (author_id)
REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT
);
INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 1',100000,1,'content 1');
INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 2',100001,2,'content 2');
INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 3',100002,2,'content 3');
INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 4',100003,2,'content 4');
INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 5',100004,3,'content 5');
CREATE TABLE posts_nofk
(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
title VARCHAR(128) NOT NULL,
create_time TIMESTAMP NOT NULL,
author_id INTEGER NOT NULL,
content TEXT
);
INSERT INTO posts_nofk (title, create_time, author_id, content) VALUES ('post 1',100000,1,'content 1');
INSERT INTO posts_nofk (title, create_time, author_id, content) VALUES ('post 2',100001,2,'content 2');
INSERT INTO posts_nofk (title, create_time, author_id, content) VALUES ('post 3',100002,2,'content 3');
INSERT INTO posts_nofk (title, create_time, author_id, content) VALUES ('post 4',100003,2,'content 4');
INSERT INTO posts_nofk (title, create_time, author_id, content) VALUES ('post 5',100004,3,'content 5');
CREATE TABLE comments
(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
content TEXT NOT NULL,
post_id INTEGER NOT NULL,
author_id INTEGER NOT NULL,
CONSTRAINT FK_post_comment FOREIGN KEY (post_id)
REFERENCES posts (id) ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT FK_user_comment FOREIGN KEY (author_id)
REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT
);
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 1',1, 2);
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 2',1, 2);
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 3',1, 2);
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 4',2, 2);
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 5',2, 2);
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 6',3, 2);
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 7',3, 2);
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 8',3, 2);
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 9',3, 2);
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 10',5, 3);
CREATE TABLE categories
(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name VARCHAR(128) NOT NULL,
parent_id INTEGER,
CONSTRAINT FK_category_category FOREIGN KEY (parent_id)
REFERENCES categories (id) ON DELETE CASCADE ON UPDATE RESTRICT
);
INSERT INTO categories (name, parent_id) VALUES ('cat 1',NULL);
INSERT INTO categories (name, parent_id) VALUES ('cat 2',NULL);
INSERT INTO categories (name, parent_id) VALUES ('cat 3',NULL);
INSERT INTO categories (name, parent_id) VALUES ('cat 4',1);
INSERT INTO categories (name, parent_id) VALUES ('cat 5',1);
INSERT INTO categories (name, parent_id) VALUES ('cat 6',5);
INSERT INTO categories (name, parent_id) VALUES ('cat 7',5);
CREATE TABLE post_category
(
category_id INTEGER NOT NULL,
post_id INTEGER NOT NULL,
PRIMARY KEY (category_id, post_id),
CONSTRAINT FK_post_category_post FOREIGN KEY (post_id)
REFERENCES posts (id) ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT FK_post_category_category FOREIGN KEY (category_id)
REFERENCES categories (id) ON DELETE CASCADE ON UPDATE RESTRICT
);
INSERT INTO post_category (category_id, post_id) VALUES (1,1);
INSERT INTO post_category (category_id, post_id) VALUES (2,1);
INSERT INTO post_category (category_id, post_id) VALUES (3,1);
INSERT INTO post_category (category_id, post_id) VALUES (4,2);
INSERT INTO post_category (category_id, post_id) VALUES (1,2);
INSERT INTO post_category (category_id, post_id) VALUES (1,3);
CREATE TABLE orders
(
key1 INTEGER NOT NULL,
key2 INTEGER NOT NULL,
name VARCHAR(128),
PRIMARY KEY (key1, key2)
);
INSERT INTO orders (key1,key2,name) VALUES (1,2,'order 12');
INSERT INTO orders (key1,key2,name) VALUES (1,3,'order 13');
INSERT INTO orders (key1,key2,name) VALUES (2,1,'order 21');
INSERT INTO orders (key1,key2,name) VALUES (2,2,'order 22');
CREATE TABLE items
(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name VARCHAR(128),
col1 INTEGER NOT NULL,
col2 INTEGER NOT NULL,
CONSTRAINT FK_order_item FOREIGN KEY (col1,col2)
REFERENCES orders (key1,key2) ON DELETE CASCADE ON UPDATE RESTRICT
);
INSERT INTO items (name,col1,col2) VALUES ('item 1',1,2);
INSERT INTO items (name,col1,col2) VALUES ('item 2',1,2);
INSERT INTO items (name,col1,col2) VALUES ('item 3',1,3);
INSERT INTO items (name,col1,col2) VALUES ('item 4',2,2);
INSERT INTO items (name,col1,col2) VALUES ('item 5',2,2);
CREATE TABLE types
(
int_col INT NOT NULL,
int_col2 INTEGER DEFAULT 1,
char_col CHAR(100) NOT NULL,
char_col2 VARCHAR(100) DEFAULT 'something',
char_col3 TEXT,
float_col REAL(4,3) NOT NULL,
float_col2 DOUBLE DEFAULT 1.23,
blob_col BLOB,
numeric_col NUMERIC(5,2) DEFAULT 33.22,
time TIMESTAMP DEFAULT 123,
bool_col BOOL NOT NULL,
bool_col2 BOOLEAN DEFAULT 1,
null_col INTEGER DEFAULT NULL
);
CREATE TABLE Content
(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
class VARCHAR(128),
parentID INTEGER NOT NULL,
ownerID INTEGER NOT NULL,
title VARCHAR(100),
CONSTRAINT FK_content_user FOREIGN KEY (ownerID)
REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT
CONSTRAINT FK_content_parent FOREIGN KEY (parentID)
REFERENCES Content (id) ON DELETE CASCADE ON UPDATE RESTRICT
);
INSERT INTO Content (class,parentID,ownerID,title) VALUES ('Article',-1,1,'article 1');
INSERT INTO Content (class,parentID,ownerID,title) VALUES ('Article',-1,2,'article 2');
INSERT INTO Content (class,parentID,ownerID,title) VALUES ('Comment',1,1,'comment 1');
INSERT INTO Content (class,parentID,ownerID,title) VALUES ('Article',-1,2,'article 3');
INSERT INTO Content (class,parentID,ownerID,title) VALUES ('Comment',4,2,'comment 2');
INSERT INTO Content (class,parentID,ownerID,title) VALUES ('Comment',4,1,'comment 3');
CREATE TABLE Article
(
id INTEGER NOT NULL PRIMARY KEY,
authorID INTEGER NOT NULL,
body TEXT,
CONSTRAINT FK_article_content FOREIGN KEY (id)
REFERENCES Content (id) ON DELETE CASCADE ON UPDATE RESTRICT
CONSTRAINT FK_article_author FOREIGN KEY (authorID)
REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT
);
INSERT INTO Article (id,authorID,body) VALUES (1,1,'content for article 1');
INSERT INTO Article (id,authorID,body) VALUES (2,2,'content for article 2');
INSERT INTO Article (id,authorID,body) VALUES (4,1,'content for article 3');
CREATE TABLE Comment
(
id INTEGER NOT NULL PRIMARY KEY,
authorID INTEGER NOT NULL,
body TEXT,
CONSTRAINT FK_comment_content FOREIGN KEY (id)
REFERENCES Content (id) ON DELETE CASCADE ON UPDATE RESTRICT
CONSTRAINT FK_article_author FOREIGN KEY (authorID)
REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT
);
INSERT INTO Comment (id,authorID,body) VALUES (3,1,'content for comment 1');
INSERT INTO Comment (id,authorID,body) VALUES (5,1,'content for comment 2');
INSERT INTO Comment (id,authorID,body) VALUES (6,1,'content for comment 3');
/**
* This is the database schema for testing Sqlite support of Yii DAO and Active Record.
* The database setup in config.php is required to perform then relevant tests:
*/
DROP TABLE IF EXISTS tbl_order_item;
DROP TABLE IF EXISTS tbl_item;
DROP TABLE IF EXISTS tbl_order;
DROP TABLE IF EXISTS tbl_category;
DROP TABLE IF EXISTS tbl_customer;
DROP TABLE IF EXISTS tbl_type;
CREATE TABLE tbl_customer (
id INTEGER NOT NULL,
email varchar(128) NOT NULL,
name varchar(128) NOT NULL,
address text,
status INTEGER DEFAULT 0,
PRIMARY KEY (id)
);
CREATE TABLE tbl_category (
id INTEGER NOT NULL,
name varchar(128) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE tbl_item (
id INTEGER NOT NULL,
name varchar(128) NOT NULL,
category_id INTEGER NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE tbl_order (
id INTEGER NOT NULL,
customer_id INTEGER NOT NULL,
create_time INTEGER NOT NULL,
total decimal(10,0) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE tbl_order_item (
order_id INTEGER NOT NULL,
item_id INTEGER NOT NULL,
quantity INTEGER NOT NULL,
subtotal decimal(10,0) NOT NULL,
PRIMARY KEY (order_id, item_id)
);
CREATE TABLE tbl_type (
int_col INTEGER NOT NULL,
int_col2 INTEGER DEFAULT '1',
char_col char(100) NOT NULL,
char_col2 varchar(100) DEFAULT 'something',
char_col3 text,
float_col double(4,3) NOT NULL,
float_col2 double DEFAULT '1.23',
blob_col blob,
numeric_col decimal(5,2) DEFAULT '33.22',
time timestamp NOT NULL DEFAULT '2002-01-01 00:00:00',
bool_col tinyint(1) NOT NULL,
bool_col2 tinyint(1) DEFAULT '1'
);
INSERT INTO tbl_customer (email, name, address, status) VALUES ('user1@example.com', 'user1', 'address1', 1);
INSERT INTO tbl_customer (email, name, address, status) VALUES ('user2@example.com', 'user2', 'address2', 1);
INSERT INTO tbl_customer (email, name, address, status) VALUES ('user3@example.com', 'user3', 'address3', 2);
INSERT INTO tbl_category (name) VALUES ('Books');
INSERT INTO tbl_category (name) VALUES ('Movies');
INSERT INTO tbl_item (name, category_id) VALUES ('Agile Web Application Development with Yii1.1 and PHP5', 1);
INSERT INTO tbl_item (name, category_id) VALUES ('Yii 1.1 Application Development Cookbook', 1);
INSERT INTO tbl_item (name, category_id) VALUES ('Ice Age', 2);
INSERT INTO tbl_item (name, category_id) VALUES ('Toy Story', 2);
INSERT INTO tbl_item (name, category_id) VALUES ('Cars', 2);
INSERT INTO tbl_order (customer_id, create_time, total) VALUES (1, 1325282384, 110.0);
INSERT INTO tbl_order (customer_id, create_time, total) VALUES (2, 1325334482, 33.0);
INSERT INTO tbl_order (customer_id, create_time, total) VALUES (2, 1325502201, 40.0);
INSERT INTO tbl_order_item (order_id, item_id, quantity, subtotal) VALUES (1, 1, 1, 30.0);
INSERT INTO tbl_order_item (order_id, item_id, quantity, subtotal) VALUES (1, 2, 2, 40.0);
INSERT INTO tbl_order_item (order_id, item_id, quantity, subtotal) VALUES (2, 4, 1, 10.0);
INSERT INTO tbl_order_item (order_id, item_id, quantity, subtotal) VALUES (2, 5, 1, 15.0);
INSERT INTO tbl_order_item (order_id, item_id, quantity, subtotal) VALUES (2, 3, 1, 8.0);
INSERT INTO tbl_order_item (order_id, item_id, quantity, subtotal) VALUES (3, 2, 1, 40.0);

1
tests/unit/framework/YiiBaseTest.php

@ -47,7 +47,6 @@ class YiiBaseTest extends TestCase
public function testGetVersion()
{
echo Yii::getVersion();
$this->assertTrue((boolean)preg_match('~\d+\.\d+(?:\.\d+)?(?:-\w+)?~', \Yii::getVersion()));
}

6
tests/unit/framework/caching/ApcCacheTest.php

@ -15,13 +15,13 @@ class ApcCacheTest extends CacheTest
*/
protected function getCacheInstance()
{
if(!extension_loaded("apc")) {
if (!extension_loaded("apc")) {
$this->markTestSkipped("APC not installed. Skipping.");
} else if ('cli' === PHP_SAPI && !ini_get('apc.enable_cli')) {
} elseif ('cli' === PHP_SAPI && !ini_get('apc.enable_cli')) {
$this->markTestSkipped("APC cli is not enabled. Skipping.");
}
if($this->_cacheInstance === null) {
if ($this->_cacheInstance === null) {
$this->_cacheInstance = new ApcCache();
}
return $this->_cacheInstance;

3
tests/unit/framework/caching/DbCacheTest.php

@ -35,7 +35,8 @@ class DbCacheTest extends CacheTest
function getConnection($reset = true)
{
if($this->_connection === null) {
$params = $this->getParam('mysql');
$databases = $this->getParam('databases');
$params = $databases['mysql'];
$db = new \yii\db\Connection;
$db->dsn = $params['dsn'];
$db->username = $params['username'];

3
tests/unit/framework/db/ActiveRecordTest.php

@ -10,10 +10,11 @@ use yiiunit\data\ar\OrderItem;
use yiiunit\data\ar\Order;
use yiiunit\data\ar\Item;
class ActiveRecordTest extends \yiiunit\MysqlTestCase
class ActiveRecordTest extends \yiiunit\DatabaseTestCase
{
public function setUp()
{
parent::setUp();
ActiveRecord::$db = $this->getConnection();
}

2
tests/unit/framework/db/CommandTest.php

@ -7,7 +7,7 @@ use yii\db\Command;
use yii\db\Query;
use yii\db\DataReader;
class CommandTest extends \yiiunit\MysqlTestCase
class CommandTest extends \yiiunit\DatabaseTestCase
{
function testConstruct()
{

11
tests/unit/framework/db/ConnectionTest.php

@ -4,12 +4,12 @@ namespace yiiunit\framework\db;
use yii\db\Connection;
class ConnectionTest extends \yiiunit\MysqlTestCase
class ConnectionTest extends \yiiunit\DatabaseTestCase
{
function testConstruct()
{
$connection = $this->getConnection(false);
$params = $this->getParam('mysql');
$params = $this->database;
$this->assertEquals($params['dsn'], $connection->dsn);
$this->assertEquals($params['username'], $connection->username);
@ -18,7 +18,7 @@ class ConnectionTest extends \yiiunit\MysqlTestCase
function testOpenClose()
{
$connection = $this->getConnection(false);
$connection = $this->getConnection(false, false);
$this->assertFalse($connection->isActive);
$this->assertEquals(null, $connection->pdo);
@ -39,9 +39,8 @@ class ConnectionTest extends \yiiunit\MysqlTestCase
function testGetDriverName()
{
$connection = $this->getConnection(false);
$this->assertEquals('mysql', $connection->driverName);
$this->assertFalse($connection->isActive);
$connection = $this->getConnection(false, false);
$this->assertEquals($this->driverName, $connection->driverName);
}
function testQuoteValue()

2
tests/unit/framework/db/QueryTest.php

@ -7,7 +7,7 @@ use yii\db\Command;
use yii\db\Query;
use yii\db\DataReader;
class QueryTest extends \yiiunit\MysqlTestCase
class QueryTest extends \yiiunit\DatabaseTestCase
{
function testSelect()
{

12
tests/unit/framework/db/sqlite/SqliteActiveRecordTest.php

@ -0,0 +1,12 @@
<?php
namespace yiiunit\framework\db\sqlite;
class SqliteActiveRecordTest extends \yiiunit\framework\db\ActiveRecordTest
{
public function setUp()
{
$this->driverName = 'sqlite';
parent::setUp();
}
}

21
tests/unit/framework/db/sqlite/SqliteCommandTest.php

@ -0,0 +1,21 @@
<?php
namespace yiiunit\framework\db\sqlite;
class SqliteCommandTest extends \yiiunit\framework\db\CommandTest
{
public function setUp()
{
$this->driverName = 'sqlite';
parent::setUp();
}
function testAutoQuoting()
{
$db = $this->getConnection(false);
$sql = 'SELECT [[id]], [[t.name]] FROM {{tbl_customer}} t';
$command = $db->createCommand($sql);
$this->assertEquals("SELECT \"id\", 't'.\"name\" FROM 'tbl_customer' t", $command->sql);
}
}

47
tests/unit/framework/db/sqlite/SqliteConnectionTest.php

@ -0,0 +1,47 @@
<?php
namespace yiiunit\framework\db\sqlite;
class SqliteConnectionTest extends \yiiunit\framework\db\ConnectionTest
{
public function setUp()
{
$this->driverName = 'sqlite';
parent::setUp();
}
function testConstruct()
{
$connection = $this->getConnection(false);
$params = $this->database;
$this->assertEquals($params['dsn'], $connection->dsn);
}
function testQuoteValue()
{
$connection = $this->getConnection(false);
$this->assertEquals(123, $connection->quoteValue(123));
$this->assertEquals("'string'", $connection->quoteValue('string'));
$this->assertEquals("'It''s interesting'", $connection->quoteValue("It's interesting"));
}
function testQuoteTableName()
{
$connection = $this->getConnection(false);
$this->assertEquals("'table'", $connection->quoteTableName('table'));
$this->assertEquals("'schema'.'table'", $connection->quoteTableName('schema.table'));
$this->assertEquals('{{table}}', $connection->quoteTableName('{{table}}'));
$this->assertEquals('(table)', $connection->quoteTableName('(table)'));
}
function testQuoteColumnName()
{
$connection = $this->getConnection(false);
$this->assertEquals('"column"', $connection->quoteColumnName('column'));
$this->assertEquals("'table'.\"column\"", $connection->quoteColumnName('table.column'));
$this->assertEquals('[[column]]', $connection->quoteColumnName('[[column]]'));
$this->assertEquals('{{column}}', $connection->quoteColumnName('{{column}}'));
$this->assertEquals('(column)', $connection->quoteColumnName('(column)'));
}
}

20
tests/unit/framework/db/sqlite/SqliteQueryTest.php

@ -0,0 +1,20 @@
<?php
/**
* Created by JetBrains PhpStorm.
* User: RusMaxim
* Date: 09.05.13
* Time: 21:41
* To change this template use File | Settings | File Templates.
*/
namespace yiiunit\framework\db\sqlite;
class SqliteQueryTest extends \yiiunit\framework\db\QueryTest
{
public function setUp()
{
$this->driverName = 'sqlite';
parent::setUp();
}
}

10
tests/unit/framework/helpers/ArrayHelperTest.php

@ -12,6 +12,16 @@ class ArrayHelperTest extends \yii\test\TestCase
}
public function testRemove()
{
$array = array('name' => 'b', 'age' => 3);
$name = ArrayHelper::remove($array, 'name');
$this->assertEquals($name, 'b');
$this->assertEquals($array, array('age' => 3));
}
public function testMultisort()
{
// single key

44
tests/unit/framework/helpers/StringHelperTest.php

@ -70,4 +70,48 @@ class StringHelperTest extends \yii\test\TestCase
$this->assertEquals('PostTag', StringHelper::id2camel('post-tag'));
$this->assertEquals('PostTag', StringHelper::id2camel('post_tag', '_'));
}
public function testBasename()
{
$this->assertEquals('', StringHelper::basename(''));
$this->assertEquals('file', StringHelper::basename('file'));
$this->assertEquals('file.test', StringHelper::basename('file.test', '.test2'));
$this->assertEquals('file', StringHelper::basename('file.test', '.test'));
$this->assertEquals('file', StringHelper::basename('/file'));
$this->assertEquals('file.test', StringHelper::basename('/file.test', '.test2'));
$this->assertEquals('file', StringHelper::basename('/file.test', '.test'));
$this->assertEquals('file', StringHelper::basename('/path/to/file'));
$this->assertEquals('file.test', StringHelper::basename('/path/to/file.test', '.test2'));
$this->assertEquals('file', StringHelper::basename('/path/to/file.test', '.test'));
$this->assertEquals('file', StringHelper::basename('\file'));
$this->assertEquals('file.test', StringHelper::basename('\file.test', '.test2'));
$this->assertEquals('file', StringHelper::basename('\file.test', '.test'));
$this->assertEquals('file', StringHelper::basename('C:\file'));
$this->assertEquals('file.test', StringHelper::basename('C:\file.test', '.test2'));
$this->assertEquals('file', StringHelper::basename('C:\file.test', '.test'));
$this->assertEquals('file', StringHelper::basename('C:\path\to\file'));
$this->assertEquals('file.test', StringHelper::basename('C:\path\to\file.test', '.test2'));
$this->assertEquals('file', StringHelper::basename('C:\path\to\file.test', '.test'));
// mixed paths
$this->assertEquals('file.test', StringHelper::basename('/path\to/file.test'));
$this->assertEquals('file.test', StringHelper::basename('/path/to\file.test'));
$this->assertEquals('file.test', StringHelper::basename('\path/to\file.test'));
// \ and / in suffix
$this->assertEquals('file', StringHelper::basename('/path/to/filete/st', 'te/st'));
$this->assertEquals('st', StringHelper::basename('/path/to/filete/st', 'te\st'));
$this->assertEquals('file', StringHelper::basename('/path/to/filete\st', 'te\st'));
$this->assertEquals('st', StringHelper::basename('/path/to/filete\st', 'te/st'));
// http://www.php.net/manual/en/function.basename.php#72254
$this->assertEquals('foo', StringHelper::basename('/bar/foo/'));
$this->assertEquals('foo', StringHelper::basename('\\bar\\foo\\'));
}
}

14
tests/unit/framework/i18n/GettextMessageSourceTest.php

@ -0,0 +1,14 @@
<?php
namespace yiiunit\framework\i18n;
use yii\i18n\GettextMessageSource;
use yiiunit\TestCase;
class GettextMessageSourceTest extends TestCase
{
public function testLoadMessages()
{
$this->markTestSkipped();
}
}

95
tests/unit/framework/i18n/GettextMoFileTest.php

@ -0,0 +1,95 @@
<?php
namespace yiiunit\framework\i18n;
use yii\i18n\GettextMoFile;
use yiiunit\TestCase;
class GettextMoFileTest extends TestCase
{
public function testLoad()
{
$moFile = new GettextMoFile();
$moFilePath = __DIR__ . '/../../data/i18n/test.mo';
$context1 = $moFile->load($moFilePath, 'context1');
$context2 = $moFile->load($moFilePath, 'context2');
// item count
$this->assertCount(3, $context1);
$this->assertCount(2, $context2);
// original messages
$this->assertArrayNotHasKey("Missing\n\r\t\"translation.", $context1);
$this->assertArrayHasKey("Aliquam tempus elit vel purus molestie placerat. In sollicitudin tincidunt\naliquet. Integer tincidunt gravida tempor. In convallis blandit dui vel malesuada.\nNunc vel sapien nunc, a pretium nulla.", $context1);
$this->assertArrayHasKey("String number two.", $context1);
$this->assertArrayHasKey("Nunc vel sapien nunc, a pretium nulla.\nPellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.", $context1);
$this->assertArrayHasKey("The other\n\ncontext.\n", $context2);
$this->assertArrayHasKey("test1\\ntest2\n\\\ntest3", $context2);
// translated messages
$this->assertFalse(in_array("", $context1));
$this->assertTrue(in_array("Олицетворение однократно. Представленный лексико-семантический анализ является\nпсихолингвистическим в своей основе, но механизм сочленений полидисперсен. Впечатление\nоднократно. Различное расположение выбирает сюжетный механизм сочленений.", $context1));
$this->assertTrue(in_array('Строка номер два.', $context1));
$this->assertTrue(in_array('Короткий перевод.', $context1));
$this->assertTrue(in_array("Другой\n\nконтекст.\n", $context2));
$this->assertTrue(in_array("тест1\\nтест2\n\\\nтест3", $context2));
}
public function testSave()
{
// initial data
$s = chr(4);
$messages = array(
'Hello!' => 'Привет!',
"context1{$s}Hello?" => 'Привет?',
'Hello!?' => '',
"context1{$s}Hello!?!" => '',
"context2{$s}\"Quotes\"" => '"Кавычки"',
"context2{$s}\nNew lines\n" => "\nПереносы строк\n",
"context2{$s}\tTabs\t" => "\tТабы\t",
"context2{$s}\rCarriage returns\r" => "\rВозвраты кареток\r",
);
// create temporary directory and dump messages
$poFileDirectory = __DIR__ . '/../../runtime/i18n';
if (!is_dir($poFileDirectory)) {
mkdir($poFileDirectory);
}
if (is_file($poFileDirectory . '/test.mo')) {
unlink($poFileDirectory . '/test.mo');
}
$moFile = new GettextMoFile();
$moFile->save($poFileDirectory . '/test.mo', $messages);
// load messages
$context1 = $moFile->load($poFileDirectory . '/test.mo', 'context1');
$context2 = $moFile->load($poFileDirectory . '/test.mo', 'context2');
// context1
$this->assertCount(2, $context1);
$this->assertArrayHasKey('Hello?', $context1);
$this->assertTrue(in_array('Привет?', $context1));
$this->assertArrayHasKey('Hello!?!', $context1);
$this->assertTrue(in_array('', $context1));
// context2
$this->assertCount(4, $context2);
$this->assertArrayHasKey("\"Quotes\"", $context2);
$this->assertTrue(in_array('"Кавычки"', $context2));
$this->assertArrayHasKey("\nNew lines\n", $context2);
$this->assertTrue(in_array("\nПереносы строк\n", $context2));
$this->assertArrayHasKey("\tTabs\t", $context2);
$this->assertTrue(in_array("\tТабы\t", $context2));
$this->assertArrayHasKey("\rCarriage returns\r", $context2);
$this->assertTrue(in_array("\rВозвраты кареток\r", $context2));
}
}

95
tests/unit/framework/i18n/GettextPoFileTest.php

@ -0,0 +1,95 @@
<?php
namespace yiiunit\framework\i18n;
use yii\i18n\GettextPoFile;
use yiiunit\TestCase;
class GettextPoFileTest extends TestCase
{
public function testLoad()
{
$poFile = new GettextPoFile();
$poFilePath = __DIR__ . '/../../data/i18n/test.po';
$context1 = $poFile->load($poFilePath, 'context1');
$context2 = $poFile->load($poFilePath, 'context2');
// item count
$this->assertCount(4, $context1);
$this->assertCount(2, $context2);
// original messages
$this->assertArrayHasKey("Missing\n\r\t\"translation.", $context1);
$this->assertArrayHasKey("Aliquam tempus elit vel purus molestie placerat. In sollicitudin tincidunt\naliquet. Integer tincidunt gravida tempor. In convallis blandit dui vel malesuada.\nNunc vel sapien nunc, a pretium nulla.", $context1);
$this->assertArrayHasKey("String number two.", $context1);
$this->assertArrayHasKey("Nunc vel sapien nunc, a pretium nulla.\nPellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.", $context1);
$this->assertArrayHasKey("The other\n\ncontext.\n", $context2);
$this->assertArrayHasKey("test1\\\ntest2\n\\\\\ntest3", $context2);
// translated messages
$this->assertTrue(in_array("", $context1));
$this->assertTrue(in_array("Олицетворение однократно. Представленный лексико-семантический анализ является\nпсихолингвистическим в своей основе, но механизм сочленений полидисперсен. Впечатление\nоднократно. Различное расположение выбирает сюжетный механизм сочленений.", $context1));
$this->assertTrue(in_array('Строка номер два.', $context1));
$this->assertTrue(in_array('Короткий перевод.', $context1));
$this->assertTrue(in_array("Другой\n\nконтекст.\n", $context2));
$this->assertTrue(in_array("тест1\\\nтест2\n\\\\\nтест3", $context2));
}
public function testSave()
{
// initial data
$s = chr(4);
$messages = array(
'Hello!' => 'Привет!',
"context1{$s}Hello?" => 'Привет?',
'Hello!?' => '',
"context1{$s}Hello!?!" => '',
"context2{$s}\"Quotes\"" => '"Кавычки"',
"context2{$s}\nNew lines\n" => "\nПереносы строк\n",
"context2{$s}\tTabs\t" => "\tТабы\t",
"context2{$s}\rCarriage returns\r" => "\rВозвраты кареток\r",
);
// create temporary directory and dump messages
$poFileDirectory = __DIR__ . '/../../runtime/i18n';
if (!is_dir($poFileDirectory)) {
mkdir($poFileDirectory);
}
if (is_file($poFileDirectory . '/test.po')) {
unlink($poFileDirectory . '/test.po');
}
$poFile = new GettextPoFile();
$poFile->save($poFileDirectory . '/test.po', $messages);
// load messages
$context1 = $poFile->load($poFileDirectory . '/test.po', 'context1');
$context2 = $poFile->load($poFileDirectory . '/test.po', 'context2');
// context1
$this->assertCount(2, $context1);
$this->assertArrayHasKey('Hello?', $context1);
$this->assertTrue(in_array('Привет?', $context1));
$this->assertArrayHasKey('Hello!?!', $context1);
$this->assertTrue(in_array('', $context1));
// context2
$this->assertCount(4, $context2);
$this->assertArrayHasKey("\"Quotes\"", $context2);
$this->assertTrue(in_array('"Кавычки"', $context2));
$this->assertArrayHasKey("\nNew lines\n", $context2);
$this->assertTrue(in_array("\nПереносы строк\n", $context2));
$this->assertArrayHasKey("\tTabs\t", $context2);
$this->assertTrue(in_array("\tТабы\t", $context2));
$this->assertArrayHasKey("\rCarriage returns\r", $context2);
$this->assertTrue(in_array("\rВозвраты кареток\r", $context2));
}
}

248
tests/unit/framework/rbac/ManagerTestBase.php

@ -0,0 +1,248 @@
<?php
namespace yiiunit\framework\rbac;
use yii\rbac\Assignment;
use yii\rbac\Item;
use yiiunit\TestCase;
abstract class ManagerTestBase extends TestCase
{
/** @var \yii\rbac\PhpManager|\yii\rbac\DbManager */
protected $auth;
public function testCreateItem()
{
$type = Item::TYPE_TASK;
$name = 'editUser';
$description = 'edit a user';
$bizRule = 'checkUserIdentity()';
$data = array(1, 2, 3);
$item = $this->auth->createItem($name, $type, $description, $bizRule, $data);
$this->assertTrue($item instanceof Item);
$this->assertEquals($item->type, $type);
$this->assertEquals($item->name, $name);
$this->assertEquals($item->description, $description);
$this->assertEquals($item->bizRule, $bizRule);
$this->assertEquals($item->data, $data);
// test shortcut
$name2 = 'createUser';
$item2 = $this->auth->createRole($name2, $description, $bizRule, $data);
$this->assertEquals($item2->type, Item::TYPE_ROLE);
// test adding an item with the same name
$this->setExpectedException('Exception');
$this->auth->createItem($name, $type, $description, $bizRule, $data);
}
public function testGetItem()
{
$this->assertTrue($this->auth->getItem('readPost') instanceof Item);
$this->assertTrue($this->auth->getItem('reader') instanceof Item);
$this->assertNull($this->auth->getItem('unknown'));
}
public function testRemoveAuthItem()
{
$this->assertTrue($this->auth->getItem('updatePost') instanceof Item);
$this->assertTrue($this->auth->removeItem('updatePost'));
$this->assertNull($this->auth->getItem('updatePost'));
$this->assertFalse($this->auth->removeItem('updatePost'));
}
public function testChangeItemName()
{
$item = $this->auth->getItem('readPost');
$this->assertTrue($item instanceof Item);
$this->assertTrue($this->auth->hasItemChild('reader', 'readPost'));
$item->name = 'readPost2';
$this->assertNull($this->auth->getItem('readPost'));
$this->assertEquals($this->auth->getItem('readPost2'), $item);
$this->assertFalse($this->auth->hasItemChild('reader', 'readPost'));
$this->assertTrue($this->auth->hasItemChild('reader', 'readPost2'));
}
public function testAddItemChild()
{
$this->auth->addItemChild('createPost', 'updatePost');
// test adding upper level item to lower one
$this->setExpectedException('Exception');
$this->auth->addItemChild('readPost', 'reader');
}
public function testAddItemChild2()
{
// test adding inexistent items
$this->setExpectedException('Exception');
$this->assertFalse($this->auth->addItemChild('createPost2', 'updatePost'));
}
public function testRemoveItemChild()
{
$this->assertTrue($this->auth->hasItemChild('reader', 'readPost'));
$this->assertTrue($this->auth->removeItemChild('reader', 'readPost'));
$this->assertFalse($this->auth->hasItemChild('reader', 'readPost'));
$this->assertFalse($this->auth->removeItemChild('reader', 'readPost'));
}
public function testGetItemChildren()
{
$this->assertEquals(array(), $this->auth->getItemChildren('readPost'));
$children = $this->auth->getItemChildren('author');
$this->assertEquals(3, count($children));
$this->assertTrue(reset($children) instanceof Item);
}
public function testAssign()
{
$auth = $this->auth->assign('new user', 'createPost', 'rule', 'data');
$this->assertTrue($auth instanceof Assignment);
$this->assertEquals($auth->userId, 'new user');
$this->assertEquals($auth->itemName, 'createPost');
$this->assertEquals($auth->bizRule, 'rule');
$this->assertEquals($auth->data, 'data');
$this->setExpectedException('Exception');
$this->auth->assign('new user', 'createPost2', 'rule', 'data');
}
public function testRevoke()
{
$this->assertTrue($this->auth->isAssigned('author B', 'author'));
$auth = $this->auth->getAssignment('author B', 'author');
$this->assertTrue($auth instanceof Assignment);
$this->assertTrue($this->auth->revoke('author B', 'author'));
$this->assertFalse($this->auth->isAssigned('author B', 'author'));
$this->assertFalse($this->auth->revoke('author B', 'author'));
}
public function testGetAssignments()
{
$this->auth->assign('author B', 'deletePost');
$auths = $this->auth->getAssignments('author B');
$this->assertEquals(2, count($auths));
$this->assertTrue(reset($auths) instanceof Assignment);
}
public function testGetItems()
{
$this->assertEquals(count($this->auth->getRoles()), 4);
$this->assertEquals(count($this->auth->getOperations()), 4);
$this->assertEquals(count($this->auth->getTasks()), 1);
$this->assertEquals(count($this->auth->getItems()), 9);
$this->assertEquals(count($this->auth->getItems('author B', null)), 1);
$this->assertEquals(count($this->auth->getItems('author C', null)), 0);
$this->assertEquals(count($this->auth->getItems('author B', Item::TYPE_ROLE)), 1);
$this->assertEquals(count($this->auth->getItems('author B', Item::TYPE_OPERATION)), 0);
}
public function testClearAll()
{
$this->auth->clearAll();
$this->assertEquals(count($this->auth->getRoles()), 0);
$this->assertEquals(count($this->auth->getOperations()), 0);
$this->assertEquals(count($this->auth->getTasks()), 0);
$this->assertEquals(count($this->auth->getItems()), 0);
$this->assertEquals(count($this->auth->getAssignments('author B')), 0);
}
public function testClearAssignments()
{
$this->auth->clearAssignments();
$this->assertEquals(count($this->auth->getAssignments('author B')), 0);
}
public function testDetectLoop()
{
$this->setExpectedException('Exception');
$this->auth->addItemChild('readPost', 'readPost');
}
public function testExecuteBizRule()
{
$this->assertTrue($this->auth->executeBizRule(null, array(), null));
$this->assertTrue($this->auth->executeBizRule('return 1==true;', array(), null));
$this->assertTrue($this->auth->executeBizRule('return $params[0]==$params[1];', array(1, '1'), null));
$this->assertFalse($this->auth->executeBizRule('invalid', array(), null));
}
public function testCheckAccess()
{
$results = array(
'reader A' => array(
'createPost' => false,
'readPost' => true,
'updatePost' => false,
'updateOwnPost' => false,
'deletePost' => false,
),
'author B' => array(
'createPost' => true,
'readPost' => true,
'updatePost' => true,
'updateOwnPost' => true,
'deletePost' => false,
),
'editor C' => array(
'createPost' => false,
'readPost' => true,
'updatePost' => true,
'updateOwnPost' => false,
'deletePost' => false,
),
'admin D' => array(
'createPost' => true,
'readPost' => true,
'updatePost' => true,
'updateOwnPost' => false,
'deletePost' => true,
),
);
$params = array('authorID' => 'author B');
foreach (array('reader A', 'author B', 'editor C', 'admin D') as $user) {
$params['userID'] = $user;
foreach (array('createPost', 'readPost', 'updatePost', 'updateOwnPost', 'deletePost') as $operation) {
$result = $this->auth->checkAccess($user, $operation, $params);
$this->assertEquals($results[$user][$operation], $result);
}
}
}
protected function prepareData()
{
$this->auth->createOperation('createPost', 'create a post');
$this->auth->createOperation('readPost', 'read a post');
$this->auth->createOperation('updatePost', 'update a post');
$this->auth->createOperation('deletePost', 'delete a post');
$task = $this->auth->createTask('updateOwnPost', 'update a post by author himself', 'return $params["authorID"]==$params["userID"];');
$task->addChild('updatePost');
$role = $this->auth->createRole('reader');
$role->addChild('readPost');
$role = $this->auth->createRole('author');
$role->addChild('reader');
$role->addChild('createPost');
$role->addChild('updateOwnPost');
$role = $this->auth->createRole('editor');
$role->addChild('reader');
$role->addChild('updatePost');
$role = $this->auth->createRole('admin');
$role->addChild('editor');
$role->addChild('author');
$role->addChild('deletePost');
$this->auth->assign('reader A', 'reader');
$this->auth->assign('author B', 'author');
$this->auth->assign('editor C', 'editor');
$this->auth->assign('admin D', 'admin');
}
}

34
tests/unit/framework/rbac/PhpManagerTest.php

@ -0,0 +1,34 @@
<?php
namespace yiiunit\framework\rbac;
use Yii;
use yii\rbac\PhpManager;
require_once(__DIR__ . '/ManagerTestBase.php');
class PhpManagerTest extends ManagerTestBase
{
public function setUp()
{
$authFile = Yii::$app->getRuntimePath() . '/rbac.php';
@unlink($authFile);
$this->auth = new PhpManager;
$this->auth->authFile = $authFile;
$this->auth->init();
$this->prepareData();
}
public function tearDown()
{
@unlink($this->auth->authFile);
}
public function testSaveLoad()
{
$this->auth->save();
$this->auth->clearAll();
$this->auth->load();
$this->testCheckAccess();
}
}

2
tests/web/app/index.php

@ -1,6 +1,6 @@
<?php
require(__DIR__ . '/../../../framework/yii.php');
require(__DIR__ . '/../../../yii/Yii.php');
$application = new yii\web\Application('test', __DIR__ . '/protected');
$application->run();

0
framework/.htaccess → yii/.htaccess

0
framework/yii.php → yii/Yii.php

11
framework/YiiBase.php → yii/YiiBase.php

@ -158,8 +158,8 @@ class YiiBase
{
foreach ($namespaces as $name => $path) {
if ($name !== '') {
$name = '@' . str_replace('\\', '/', $name);
static::setAlias($name, $path);
$name = trim(strtr($name, array('\\' => '/', '_' => '/')), '/');
static::setAlias('@' . $name, rtrim($path, '/\\') . '/' . $name);
}
}
}
@ -370,7 +370,8 @@ class YiiBase
include($classFile);
if (class_exists($className, false) || interface_exists($className, false)) {
if (class_exists($className, false) || interface_exists($className, false) ||
function_exists('trait_exists') && trait_exists($className, false)) {
return true;
} else {
throw new UnknownClassException("Unable to find '$className' in file: $classFile");
@ -451,12 +452,12 @@ class YiiBase
}
$args = func_get_args();
array_shift($args); // remove $config
if ($config !== array()) {
if (!empty($config)) {
$args[] = $config;
}
return $reflection->newInstanceArgs($args);
} else {
return $config === array() ? new $class : new $class($config);
return empty($config) ? new $class : new $class($config);
}
}

14
framework/assets.php → yii/assets.php

@ -28,4 +28,18 @@ return array(
),
'depends' => array('yii', 'yii/validation'),
),
'yii/captcha' => array(
'sourcePath' => __DIR__ . '/assets',
'js' => array(
'yii.captcha.js',
),
'depends' => array('yii'),
),
'yii/debug' => array(
'sourcePath' => __DIR__ . '/assets',
'js' => array(
'yii.debug.js',
),
'depends' => array('yii'),
),
);

0
framework/assets/jquery.min.js → yii/assets/jquery.min.js vendored

6
framework/assets/yii.activeForm.js → yii/assets/yii.activeForm.js

@ -116,8 +116,8 @@
});
},
options: function() {
return this.data('yiiActiveForm').settings;
data: function() {
return this.data('yiiActiveForm');
},
submitForm: function () {
@ -384,4 +384,4 @@
}
};
})(window.jQuery);
})(window.jQuery);

72
yii/assets/yii.captcha.js

@ -0,0 +1,72 @@
/**
* Yii Captcha widget.
*
* This is the JavaScript widget used by the yii\widgets\Captcha widget.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
(function ($) {
$.fn.yiiCaptcha = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.yiiCaptcha');
return false;
}
};
var defaults = {
refreshUrl: undefined,
hashKey: undefined
};
var methods = {
init: function (options) {
return this.each(function () {
var $e = $(this);
var settings = $.extend({}, defaults, options || {});
$e.data('yiiCaptcha', {
settings: settings
});
$e.on('click.yiiCaptcha', function() {
methods.refresh.apply($e);
return false;
});
});
},
refresh: function () {
var $e = this,
settings = this.data('yiiCaptcha').settings;
$.ajax({
url: $e.data('yiiCaptcha').settings.refreshUrl,
dataType: 'json',
cache: false,
success: function(data) {
$e.attr('src', data['url']);
$('body').data(settings.hashKey, [data['hash1'], data['hash2']]);
}
});
},
destroy: function () {
return this.each(function () {
$(window).unbind('.yiiCaptcha');
$(this).removeData('yiiCaptcha');
});
},
data: function() {
return this.data('yiiCaptcha');
}
};
})(window.jQuery);

26
yii/assets/yii.debug.js

@ -0,0 +1,26 @@
/**
* Yii debug module.
*
* This JavaScript module provides the functions needed by the Yii debug toolbar.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
yii.debug = (function ($) {
return {
load: function (id, url) {
$.ajax({
url: url,
//dataType: 'json',
success: function(data) {
var $e = $('#' + id);
$e.html(data);
}
});
}
};
})(jQuery);

0
framework/assets/yii.js → yii/assets/yii.js

2
framework/assets/yii.validation.js → yii/assets/yii.validation.js

@ -1,7 +1,7 @@
/**
* Yii validation module.
*
* This JavaScript module provides the validation methods for the built-in validaotrs.
* This JavaScript module provides the validation methods for the built-in validators.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC

0
framework/base/Action.php → yii/base/Action.php

0
framework/base/ActionEvent.php → yii/base/ActionEvent.php

0
framework/base/ActionFilter.php → yii/base/ActionFilter.php

16
framework/base/Application.php → yii/base/Application.php

@ -8,7 +8,6 @@
namespace yii\base;
use Yii;
use yii\helpers\FileHelper;
/**
* Application is the base class for all application classes.
@ -85,6 +84,13 @@ class Application extends Module
} else {
throw new InvalidConfigException('The "basePath" configuration is required.');
}
if (isset($config['timeZone'])) {
$this->setTimeZone($config['timeZone']);
unset($config['timeZone']);
} elseif (!ini_get('date.timezone')) {
$this->setTimeZone('UTC');
}
$this->registerErrorHandlers();
$this->registerCoreComponents();
@ -223,6 +229,8 @@ class Application extends Module
/**
* Returns the time zone used by this application.
* This is a simple wrapper of PHP function date_default_timezone_get().
* If time zone is not configured in php.ini or application config,
* it will be set to UTC by default.
* @return string the time zone used by this application.
* @see http://php.net/manual/en/function.date-default-timezone-get.php
*/
@ -306,12 +314,12 @@ class Application extends Module
}
/**
* @return null|Component
* @todo
* Returns the auth manager for this application.
* @return \yii\rbac\Manager the auth manager for this application.
*/
public function getAuthManager()
{
return $this->getComponent('auth');
return $this->getComponent('authManager');
}
/**

0
framework/base/Behavior.php → yii/base/Behavior.php

0
framework/base/Component.php → yii/base/Component.php

5
framework/base/Controller.php → yii/base/Controller.php

@ -8,7 +8,6 @@
namespace yii\base;
use Yii;
use yii\helpers\FileHelper;
use yii\helpers\StringHelper;
/**
@ -183,7 +182,7 @@ class Controller extends Component
}
}
if ($missing !== array()) {
if (!empty($missing)) {
throw new InvalidRequestException(Yii::t('yii|Missing required parameters: {params}', array(
'{params}' => implode(', ', $missing),
)));
@ -204,7 +203,7 @@ class Controller extends Component
public function forward($route, $params = array())
{
$status = $this->run($route, $params);
exit($status);
Yii::$app->end($status);
}
/**

4
framework/base/Dictionary.php → yii/base/Dictionary.php

@ -51,7 +51,7 @@ class Dictionary extends Object implements \IteratorAggregate, \ArrayAccess, \Co
*/
public function __construct($data = array(), $config = array())
{
if ($data !== array()) {
if (!empty($data)) {
$this->copyFrom($data);
}
parent::__construct($config);
@ -187,7 +187,7 @@ class Dictionary extends Object implements \IteratorAggregate, \ArrayAccess, \Co
public function copyFrom($data)
{
if (is_array($data) || $data instanceof \Traversable) {
if ($this->_d !== array()) {
if (!empty($this->_d)) {
$this->removeAll();
}
if ($data instanceof self) {

0
framework/base/DictionaryIterator.php → yii/base/DictionaryIterator.php

0
framework/base/ErrorException.php → yii/base/ErrorException.php

0
framework/base/ErrorHandler.php → yii/base/ErrorHandler.php

0
framework/base/Event.php → yii/base/Event.php

0
framework/base/Exception.php → yii/base/Exception.php

0
framework/base/HttpException.php → yii/base/HttpException.php

0
framework/base/InlineAction.php → yii/base/InlineAction.php

0
framework/base/InvalidCallException.php → yii/base/InvalidCallException.php

0
framework/base/InvalidConfigException.php → yii/base/InvalidConfigException.php

0
framework/base/InvalidParamException.php → yii/base/InvalidParamException.php

0
framework/base/InvalidRequestException.php → yii/base/InvalidRequestException.php

0
framework/base/InvalidRouteException.php → yii/base/InvalidRouteException.php

0
framework/base/Model.php → yii/base/Model.php

0
framework/base/ModelEvent.php → yii/base/ModelEvent.php

0
framework/base/Module.php → yii/base/Module.php

0
framework/base/NotSupportedException.php → yii/base/NotSupportedException.php

8
framework/base/Object.php → yii/base/Object.php

@ -15,6 +15,14 @@ namespace yii\base;
class Object
{
/**
* @return string the fully qualified name of this class.
*/
public static function className()
{
return get_called_class();
}
/**
* Constructor.
* The default implementation does two things:
*

0
framework/base/Request.php → yii/base/Request.php

0
framework/base/Response.php → yii/base/Response.php

0
framework/base/Theme.php → yii/base/Theme.php

0
framework/base/UnknownClassException.php → yii/base/UnknownClassException.php

0
framework/base/UnknownMethodException.php → yii/base/UnknownMethodException.php

0
framework/base/UnknownPropertyException.php → yii/base/UnknownPropertyException.php

0
framework/base/UserException.php → yii/base/UserException.php

2
framework/base/Vector.php → yii/base/Vector.php

@ -58,7 +58,7 @@ class Vector extends Object implements \IteratorAggregate, \ArrayAccess, \Counta
*/
public function __construct($data = array(), $config = array())
{
if ($data !== array()) {
if (!empty($data)) {
$this->copyFrom($data);
}
parent::__construct($config);

0
framework/base/VectorIterator.php → yii/base/VectorIterator.php

12
framework/base/View.php → yii/base/View.php

@ -23,6 +23,14 @@ use yii\helpers\Html;
class View extends Component
{
/**
* @event ViewEvent an event that is triggered by [[beginPage()]].
*/
const EVENT_BEGIN_PAGE = 'beginPage';
/**
* @event ViewEvent an event that is triggered by [[endPage()]].
*/
const EVENT_END_PAGE = 'endPage';
/**
* @event ViewEvent an event that is triggered by [[renderFile()]] right before it renders a view file.
*/
const EVENT_BEFORE_RENDER = 'beforeRender';
@ -555,6 +563,8 @@ class View extends Component
{
ob_start();
ob_implicit_flush(false);
$this->trigger(self::EVENT_BEGIN_PAGE);
}
/**
@ -562,6 +572,8 @@ class View extends Component
*/
public function endPage()
{
$this->trigger(self::EVENT_END_PAGE);
$content = ob_get_clean();
echo strtr($content, array(
self::PL_HEAD => $this->renderHeadHtml(),

0
framework/base/ViewEvent.php → yii/base/ViewEvent.php

0
framework/base/ViewRenderer.php → yii/base/ViewRenderer.php

0
framework/base/Widget.php → yii/base/Widget.php

0
framework/caching/ApcCache.php → yii/caching/ApcCache.php

0
framework/caching/Cache.php → yii/caching/Cache.php

0
framework/caching/ChainedDependency.php → yii/caching/ChainedDependency.php

0
framework/caching/DbCache.php → yii/caching/DbCache.php

0
framework/caching/DbDependency.php → yii/caching/DbDependency.php

0
framework/caching/Dependency.php → yii/caching/Dependency.php

0
framework/caching/DummyCache.php → yii/caching/DummyCache.php

0
framework/caching/ExpressionDependency.php → yii/caching/ExpressionDependency.php

0
framework/caching/FileCache.php → yii/caching/FileCache.php

0
framework/caching/FileDependency.php → yii/caching/FileDependency.php

0
framework/caching/MemCache.php → yii/caching/MemCache.php

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save