Browse Source

Merge branch 'master' into redis

* master: (179 commits)
  Fixes #312. Additional docs on IDN in EmailValidator and UrlValidator.
  bug fix.
  Added composer extension.
  Added psr-0.
  Fixed breaking test.
  Fixed iii include path.
  reorganized the main repo to satisfy PSR-0.
  Fixed bootstrap asset registration issue.
  Widget::$transition removed, bundles depency fixed
  'yii/bootstrap/popover' bundle depency optimization
  Bundle names fixes, base widget fixes, other widgets fixes
  Fixed join query for AR.
  Responsive bundle depency fix
  Bundle names and depency fixes
  YiiBase move all after class definition
  YiiBase
  Reloaded
  Additional bootstrap packages
  New approach
  minor refactoring.
  ...

Conflicts:
	tests/unit/framework/caching/ApcCacheTest.php
	tests/unit/framework/caching/CacheTest.php
tags/2.0.0-beta
Carsten Brandt 12 years ago
parent
commit
144e73b48a
  1. 5
      .gitignore
  2. 2
      LICENSE.md
  3. 2
      README.md
  4. 32
      apps/bootstrap/LICENSE.md
  5. 61
      apps/bootstrap/README.md
  6. 29
      apps/bootstrap/commands/HelloController.php
  7. 38
      apps/bootstrap/composer.json
  8. 3
      apps/bootstrap/config/assets.php
  9. 26
      apps/bootstrap/config/console.php
  10. 18
      apps/bootstrap/config/main.php
  11. 5
      apps/bootstrap/config/params.php
  12. 3
      apps/bootstrap/controllers/SiteController.php
  13. 9
      apps/bootstrap/css/bootstrap.min.css
  14. 14
      apps/bootstrap/index.php
  15. 2276
      apps/bootstrap/js/bootstrap.js
  16. 6
      apps/bootstrap/js/bootstrap.min.js
  17. 0
      apps/bootstrap/models/ContactForm.php
  18. 0
      apps/bootstrap/models/LoginForm.php
  19. 0
      apps/bootstrap/models/User.php
  20. 96
      apps/bootstrap/requirements.php
  21. 0
      apps/bootstrap/runtime/.gitignore
  22. 1
      apps/bootstrap/vendor/.gitignore
  23. 8
      apps/bootstrap/views/layouts/main.php
  24. 0
      apps/bootstrap/views/site/about.php
  25. 16
      apps/bootstrap/views/site/contact.php
  26. 0
      apps/bootstrap/views/site/index.php
  27. 4
      apps/bootstrap/views/site/login.php
  28. 1
      apps/bootstrap/www/assets/.gitignore
  29. 0
      apps/bootstrap/www/css/site.css
  30. 12
      apps/bootstrap/www/index.php
  31. 22
      apps/bootstrap/yii
  32. 8
      apps/bootstrap/yii.bat
  33. 4
      build/build
  34. 2
      build/build.xml
  35. 2
      build/controllers/LocaleController.php
  36. 212
      composer.lock
  37. 4
      docs/api/db/ActiveRecord.md
  38. 9
      docs/guide/bootstrap.md
  39. 28
      docs/guide/migration.md
  40. 32
      docs/guide/upgrade-from-v1.md
  41. 25
      docs/internals/ar.md
  42. 27
      extensions/composer/composer.json
  43. 53
      extensions/composer/yii/composer/InstallHandler.php
  44. 0
      framework/CHANGELOG.md
  45. 32
      framework/LICENSE.md
  46. 21
      framework/README.md
  47. 9
      framework/UPGRADE.md
  48. 23
      framework/composer.json
  49. 3
      framework/yii/.gitignore
  50. 0
      framework/yii/.htaccess
  51. 0
      framework/yii/Yii.php
  52. 32
      framework/yii/YiiBase.php
  53. 18
      framework/yii/assets.php
  54. 9597
      framework/yii/assets/jquery.js
  55. 0
      framework/yii/assets/jquery.min.js
  56. 278
      framework/yii/assets/punycode/LICENSE-GPL.txt
  57. 20
      framework/yii/assets/punycode/LICENSE-MIT.txt
  58. 502
      framework/yii/assets/punycode/punycode.js
  59. 2
      framework/yii/assets/punycode/punycode.min.js
  60. 2
      framework/yii/assets/yii.activeForm.js
  61. 4
      framework/yii/assets/yii.captcha.js
  62. 2
      framework/yii/assets/yii.debug.js
  63. 0
      framework/yii/assets/yii.js
  64. 28
      framework/yii/assets/yii.validation.js
  65. 0
      framework/yii/base/Action.php
  66. 0
      framework/yii/base/ActionEvent.php
  67. 0
      framework/yii/base/ActionFilter.php
  68. 0
      framework/yii/base/Application.php
  69. 0
      framework/yii/base/Behavior.php
  70. 0
      framework/yii/base/Component.php
  71. 6
      framework/yii/base/Controller.php
  72. 28
      framework/yii/base/ErrorException.php
  73. 7
      framework/yii/base/ErrorHandler.php
  74. 0
      framework/yii/base/Event.php
  75. 2
      framework/yii/base/Exception.php
  76. 2
      framework/yii/base/HttpException.php
  77. 0
      framework/yii/base/InlineAction.php
  78. 2
      framework/yii/base/InvalidCallException.php
  79. 2
      framework/yii/base/InvalidConfigException.php
  80. 2
      framework/yii/base/InvalidParamException.php
  81. 2
      framework/yii/base/InvalidRequestException.php
  82. 2
      framework/yii/base/InvalidRouteException.php
  83. 63
      framework/yii/base/Model.php
  84. 0
      framework/yii/base/ModelEvent.php
  85. 6
      framework/yii/base/Module.php
  86. 2
      framework/yii/base/NotSupportedException.php
  87. 0
      framework/yii/base/Object.php
  88. 0
      framework/yii/base/Request.php
  89. 0
      framework/yii/base/Response.php
  90. 17
      framework/yii/base/Theme.php
  91. 2
      framework/yii/base/UnknownClassException.php
  92. 2
      framework/yii/base/UnknownMethodException.php
  93. 2
      framework/yii/base/UnknownPropertyException.php
  94. 0
      framework/yii/base/UserException.php
  95. 161
      framework/yii/base/View.php
  96. 0
      framework/yii/base/ViewEvent.php
  97. 0
      framework/yii/base/ViewRenderer.php
  98. 101
      framework/yii/base/Widget.php
  99. 106
      framework/yii/behaviors/AutoTimestamp.php
  100. 154
      framework/yii/bootstrap/Alert.php
  101. Some files were not shown because too many files have changed in this diff Show More

5
.gitignore vendored

@ -13,4 +13,7 @@ nbproject
Thumbs.db Thumbs.db
# composer vendor dir # composer vendor dir
/yii/vendor /yii/vendor
# composer itself is not needed
composer.phar

2
license.md → LICENSE.md

@ -1,7 +1,7 @@
The Yii framework is free software. It is released under the terms of The Yii framework is free software. It is released under the terms of
the following BSD License. the following BSD License.
Copyright © 2008-2012 by Yii Software LLC (http://www.yiisoft.com) Copyright © 2008-2013 by Yii Software LLC (http://www.yiisoft.com)
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

2
readme.md → README.md

@ -19,7 +19,7 @@ DIRECTORY STRUCTURE
bootstrap/ a simple app supporting user login and contact page bootstrap/ a simple app supporting user login and contact page
build/ internally used build tools build/ internally used build tools
docs/ documentation docs/ documentation
framework/ framework source files yii/ framework source files
tests/ tests of the core framework code tests/ tests of the core framework code

32
apps/bootstrap/LICENSE.md

@ -0,0 +1,32 @@
The Yii framework is free software. It is released under the terms of
the following BSD License.
Copyright © 2008-2013 by Yii Software LLC (http://www.yiisoft.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Yii Software LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

61
apps/bootstrap/README.md

@ -0,0 +1,61 @@
Yii 2 Bootstrap Application
===========================
**NOTE** Yii 2 and the relevant applications and extensions are still under heavy
development. We may make significant changes without prior notices. Please do not
use them for production. Please consider using [Yii v1.1](https://github.com/yiisoft/yii)
if you have a project to be deployed for production soon.
Thank you for choosing Yii 2 - the new generation of high-performance PHP framework.
The Yii 2 Bootstrap Application is a Web application template that you can easily customize
to fit for your needs. It is particularly suitable for small Websites which mainly contain
a few informational pages.
DIRECTORY STRUCTURE
-------------------
commands/ contains console commands (controllers)
config/ contains application configurations
controllers/ contains Web controller classes
models/ contains model classes
runtime/ contains files generated during runtime
vendor/ contains dependent 3rd-party packages
views/ contains view files for the Web application
www/ contains the entry script and Web resources
REQUIREMENTS
------------
The minimum requirement by Yii is that your Web server supports PHP 5.3.?.
INSTALLATION
------------
### Install via Composer
If you do not have [Composer](http://getcomposer.org/), you may download it from
[http://getcomposer.org/](http://getcomposer.org/) or run the following command on Linux/Unix/MacOS:
~~~
curl -s http://getcomposer.org/installer | php
~~~
You can then install the Bootstrap Application using the following command:
~~~
php composer.phar create-project --stability=dev yiisoft/yii2-bootstrap bootstrap
~~~
Now you should be able to access the Bootstrap Application using the URL `http://localhost/bootstrap/www/`,
assuming `bootstrap` is directly under the document root of your Web server.
### Install from an Archive File
This is not currently available. We will provide it when Yii 2 is formally released.

29
apps/bootstrap/commands/HelloController.php

@ -0,0 +1,29 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace app\commands;
use yii\console\Controller;
/**
* This command echos what the first argument that you have entered.
*
* This command is provided as an example for you to learn how to create console commands.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class HelloController extends Controller
{
/**
* This command echos what you have entered as the message.
* @param string $message the message to be echoed.
*/
public function actionIndex($message = 'hello world')
{
echo $message;
}
}

38
apps/bootstrap/composer.json

@ -0,0 +1,38 @@
{
"name": "yiisoft/yii2-bootstrap",
"description": "Yii 2 Bootstrap Application",
"keywords": ["yii", "framework", "bootstrap"],
"homepage": "http://www.yiiframework.com/",
"type": "project",
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/yii2/issues?state=open",
"forum": "http://www.yiiframework.com/forum/",
"wiki": "http://www.yiiframework.com/wiki/",
"irc": "irc://irc.freenode.net/yii",
"source": "https://github.com/yiisoft/yii2"
},
"minimum-stability": "dev",
"require": {
"php": ">=5.3.0",
"yiisoft/yii2": "dev-master",
"yiisoft/yii2-composer": "dev-master"
},
"scripts": {
"post-install-cmd": [
"yii\\composer\\InstallHandler::setPermissions"
],
"post-update-cmd": [
"yii\\composer\\InstallHandler::setPermissions"
]
},
"extra": {
"writable": [
"runtime",
"www/assets"
],
"executable": [
"yii"
]
}
}

3
apps/bootstrap/protected/config/assets.php → apps/bootstrap/config/assets.php

@ -5,8 +5,6 @@ return array(
'basePath' => '@wwwroot', 'basePath' => '@wwwroot',
'baseUrl' => '@www', 'baseUrl' => '@www',
'css' => array( 'css' => array(
'css/bootstrap.min.css',
'css/bootstrap-responsive.min.css',
'css/site.css', 'css/site.css',
), ),
'js' => array( 'js' => array(
@ -14,6 +12,7 @@ return array(
), ),
'depends' => array( 'depends' => array(
'yii', 'yii',
'yii/bootstrap/responsive',
), ),
), ),
); );

26
apps/bootstrap/config/console.php

@ -0,0 +1,26 @@
<?php
return array(
'id' => 'bootstrap-console',
'basePath' => dirname(__DIR__),
'preload' => array('log'),
'controllerPath' => dirname(__DIR__) . '/commands',
'controllerNamespace' => 'app\commands',
'modules' => array(
),
'components' => array(
'cache' => array(
'class' => 'yii\caching\FileCache',
),
'log' => array(
'class' => 'yii\logging\Router',
'targets' => array(
array(
'class' => 'yii\logging\FileTarget',
'levels' => array('error', 'warning'),
),
),
),
),
'params' => require(__DIR__ . '/params.php'),
);

18
apps/bootstrap/protected/config/main.php → apps/bootstrap/config/main.php

@ -1,13 +1,14 @@
<?php <?php
return array( return array(
'id' => 'hello', 'id' => 'bootstrap',
'basePath' => dirname(__DIR__), 'basePath' => dirname(__DIR__),
'preload' => array('log'), 'preload' => array('log'),
'controllerNamespace' => 'app\controllers',
'modules' => array( 'modules' => array(
'debug' => array( // 'debug' => array(
'class' => 'yii\debug\Module', // 'class' => 'yii\debug\Module',
) // )
), ),
'components' => array( 'components' => array(
'cache' => array( 'cache' => array(
@ -23,14 +24,15 @@ return array(
'log' => array( 'log' => array(
'class' => 'yii\logging\Router', 'class' => 'yii\logging\Router',
'targets' => array( 'targets' => array(
'file' => array( array(
'class' => 'yii\logging\FileTarget', 'class' => 'yii\logging\FileTarget',
'levels' => array('error', 'warning'), 'levels' => array('error', 'warning'),
), ),
// array(
// 'class' => 'yii\logging\DebugTarget',
// )
), ),
), ),
), ),
'params' => array( 'params' => require(__DIR__ . '/params.php'),
'adminEmail' => 'admin@example.com',
),
); );

5
apps/bootstrap/config/params.php

@ -0,0 +1,5 @@
<?php
return array(
'adminEmail' => 'admin@example.com',
);

3
apps/bootstrap/protected/controllers/SiteController.php → apps/bootstrap/controllers/SiteController.php

@ -1,5 +1,8 @@
<?php <?php
namespace app\controllers;
use Yii;
use yii\web\Controller; use yii\web\Controller;
use app\models\LoginForm; use app\models\LoginForm;
use app\models\ContactForm; use app\models\ContactForm;

9
apps/bootstrap/css/bootstrap.min.css vendored

File diff suppressed because one or more lines are too long

14
apps/bootstrap/index.php

@ -1,14 +0,0 @@
<?php
// comment out the following line to disable debug mode
defined('YII_DEBUG') or define('YII_DEBUG', true);
$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);
$application->run();

2276
apps/bootstrap/js/bootstrap.js vendored

File diff suppressed because it is too large Load Diff

6
apps/bootstrap/js/bootstrap.min.js vendored

File diff suppressed because one or more lines are too long

0
apps/bootstrap/protected/models/ContactForm.php → apps/bootstrap/models/ContactForm.php

0
apps/bootstrap/protected/models/LoginForm.php → apps/bootstrap/models/LoginForm.php

0
apps/bootstrap/protected/models/User.php → apps/bootstrap/models/User.php

96
apps/bootstrap/requirements.php

@ -0,0 +1,96 @@
<?php
/**
* Application requirement checker script.
*
* In order to run this script use the following console command:
* php requirements.php
*
* In order to run this script from the web, you should copy it to the web root.
* If you are using Linux you can create a hard link instead, using the following command:
* ln requirements.php ../requirements.php
*/
// you may need to adjust this path to the correct Yii framework path
$frameworkPath = dirname(__FILE__) . '/../../yii';
require_once($frameworkPath . '/requirements/YiiRequirementChecker.php');
$requirementsChecker = new YiiRequirementChecker();
/**
* Adjust requirements according to your application specifics.
*/
$requirements = array(
// Database :
array(
'name' => 'PDO extension',
'mandatory' => true,
'condition' => extension_loaded('pdo'),
'by' => 'All <a href="http://www.yiiframework.com/doc/api/#system.db">DB-related classes</a>',
),
array(
'name' => 'PDO SQLite extension',
'mandatory' => false,
'condition' => extension_loaded('pdo_sqlite'),
'by' => 'All <a href="http://www.yiiframework.com/doc/api/#system.db">DB-related classes</a>',
'memo' => 'Required for SQLite database.',
),
array(
'name' => 'PDO MySQL extension',
'mandatory' => false,
'condition' => extension_loaded('pdo_mysql'),
'by' => 'All <a href="http://www.yiiframework.com/doc/api/#system.db">DB-related classes</a>',
'memo' => 'Required for MySQL database.',
),
// Cache :
array(
'name' => 'Memcache extension',
'mandatory' => false,
'condition' => extension_loaded('memcache') || extension_loaded('memcached'),
'by' => '<a href="http://www.yiiframework.com/doc/api/CMemCache">CMemCache</a>',
'memo' => extension_loaded('memcached') ? 'To use memcached set <a href="http://www.yiiframework.com/doc/api/CMemCache#useMemcached-detail">CMemCache::useMemcached</a> to <code>true</code>.' : ''
),
array(
'name' => 'APC extension',
'mandatory' => false,
'condition' => extension_loaded('apc') || extension_loaded('apc'),
'by' => '<a href="http://www.yiiframework.com/doc/api/CApcCache">CApcCache</a>',
),
// Additional PHP extensions :
array(
'name' => 'Mcrypt extension',
'mandatory' => false,
'condition' => extension_loaded('mcrypt'),
'by' => '<a href="http://www.yiiframework.com/doc/api/CSecurityManager">CSecurityManager</a>',
'memo' => 'Required by encrypt and decrypt methods.'
),
// PHP ini :
'phpSafeMode' => array(
'name' => 'PHP safe mode',
'mandatory' => false,
'condition' => $requirementsChecker->checkPhpIniOff("safe_mode"),
'by' => 'File uploading and console command execution',
'memo' => '"safe_mode" should be disabled at php.ini',
),
'phpExposePhp' => array(
'name' => 'Expose PHP',
'mandatory' => false,
'condition' => $requirementsChecker->checkPhpIniOff("expose_php"),
'by' => 'Security reasons',
'memo' => '"expose_php" should be disabled at php.ini',
),
'phpAllowUrlInclude' => array(
'name' => 'PHP allow url include',
'mandatory' => false,
'condition' => $requirementsChecker->checkPhpIniOff("allow_url_include"),
'by' => 'Security reasons',
'memo' => '"allow_url_include" should be disabled at php.ini',
),
'phpSmtp' => array(
'name' => 'PHP mail SMTP',
'mandatory' => false,
'condition' => strlen(ini_get('SMTP'))>0,
'by' => 'Email sending',
'memo' => 'PHP mail SMTP server required',
),
);
$requirementsChecker->checkYii()->check($requirements)->render();

0
apps/bootstrap/protected/runtime/.gitignore → apps/bootstrap/runtime/.gitignore vendored

1
apps/bootstrap/vendor/.gitignore vendored

@ -0,0 +1 @@
*

8
apps/bootstrap/protected/views/layouts/main.php → apps/bootstrap/views/layouts/main.php

@ -1,6 +1,8 @@
<?php <?php
use yii\helpers\Html; use yii\helpers\Html;
use yii\widgets\Menu; use yii\widgets\Menu;
use yii\widgets\Breadcrumbs;
use yii\debug\Toolbar;
/** /**
* @var $this \yii\base\View * @var $this \yii\base\View
@ -25,7 +27,7 @@ $this->registerAssetBundle('app');
<div class="navbar"> <div class="navbar">
<div class="navbar-inner"> <div class="navbar-inner">
<div class="container"> <div class="container">
<?php $this->widget(Menu::className(), array( <?php echo Menu::widget(array(
'options' => array('class' => 'nav'), 'options' => array('class' => 'nav'),
'items' => array( 'items' => array(
array('label' => 'Home', 'url' => array('/site/index')), array('label' => 'Home', 'url' => array('/site/index')),
@ -42,7 +44,7 @@ $this->registerAssetBundle('app');
<!-- /.navbar --> <!-- /.navbar -->
</div> </div>
<?php $this->widget('yii\widgets\Breadcrumbs', array( <?php echo Breadcrumbs::widget(array(
'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : array(), 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : array(),
)); ?> )); ?>
<?php echo $content; ?> <?php echo $content; ?>
@ -58,7 +60,7 @@ $this->registerAssetBundle('app');
</div> </div>
<?php $this->endBody(); ?> <?php $this->endBody(); ?>
</div> </div>
<?php $this->widget('yii\debug\Toolbar'); ?> <?php echo Toolbar::widget(); ?>
</body> </body>
</html> </html>
<?php $this->endPage(); ?> <?php $this->endPage(); ?>

0
apps/bootstrap/protected/views/site/about.php → apps/bootstrap/views/site/about.php

16
apps/bootstrap/protected/views/site/contact.php → apps/bootstrap/views/site/contact.php

@ -23,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. If you have business inquiries or other questions, please fill out the following form to contact us. Thank you.
</p> </p>
<?php $form = $this->beginWidget(ActiveForm::className(), array( <?php $form = ActiveForm::begin(array(
'options' => array('class' => 'form-horizontal'), 'options' => array('class' => 'form-horizontal'),
'fieldConfig' => array('inputOptions' => array('class' => 'input-xlarge')), 'fieldConfig' => array('inputOptions' => array('class' => 'input-xlarge')),
)); ?> )); ?>
@ -33,14 +33,14 @@ $this->params['breadcrumbs'][] = $this->title;
<?php echo $form->field($model, 'body')->textArea(array('rows' => 6)); ?> <?php echo $form->field($model, 'body')->textArea(array('rows' => 6)); ?>
<?php <?php
$field = $form->field($model, 'verifyCode'); $field = $form->field($model, 'verifyCode');
echo $field->begin(); echo $field->begin()
echo $field->label(); . $field->label()
$this->widget(Captcha::className()); . Captcha::widget()
echo Html::activeTextInput($model, 'verifyCode', array('class' => 'input-medium')); . Html::activeTextInput($model, 'verifyCode', array('class' => 'input-medium'))
echo $field->error(); . $field->error()
echo $field->end(); . $field->end();
?> ?>
<div class="form-actions"> <div class="form-actions">
<?php echo Html::submitButton('Submit', null, null, array('class' => 'btn btn-primary')); ?> <?php echo Html::submitButton('Submit', null, null, array('class' => 'btn btn-primary')); ?>
</div> </div>
<?php $this->endWidget(); ?> <?php ActiveForm::end(); ?>

0
apps/bootstrap/protected/views/site/index.php → apps/bootstrap/views/site/index.php

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

@ -14,11 +14,11 @@ $this->params['breadcrumbs'][] = $this->title;
<p>Please fill out the following fields to login:</p> <p>Please fill out the following fields to login:</p>
<?php $form = $this->beginWidget(ActiveForm::className(), array('options' => array('class' => 'form-horizontal'))); ?> <?php $form = ActiveForm::begin(array('options' => array('class' => 'form-horizontal'))); ?>
<?php echo $form->field($model, 'username')->textInput(); ?> <?php echo $form->field($model, 'username')->textInput(); ?>
<?php echo $form->field($model, 'password')->passwordInput(); ?> <?php echo $form->field($model, 'password')->passwordInput(); ?>
<?php echo $form->field($model, 'rememberMe')->checkbox(); ?> <?php echo $form->field($model, 'rememberMe')->checkbox(); ?>
<div class="form-actions"> <div class="form-actions">
<?php echo Html::submitButton('Login', null, null, array('class' => 'btn btn-primary')); ?> <?php echo Html::submitButton('Login', null, null, array('class' => 'btn btn-primary')); ?>
</div> </div>
<?php $this->endWidget(); ?> <?php ActiveForm::end(); ?>

1
apps/bootstrap/www/assets/.gitignore vendored

@ -0,0 +1 @@
*

0
apps/bootstrap/css/site.css → apps/bootstrap/www/css/site.css vendored

12
apps/bootstrap/www/index.php

@ -0,0 +1,12 @@
<?php
// comment out the following line to disable debug mode
defined('YII_DEBUG') or define('YII_DEBUG', true);
require(__DIR__ . '/../vendor/yiisoft/yii2/yii/Yii.php');
require(__DIR__ . '/../vendor/autoload.php');
$config = require(__DIR__ . '/../config/main.php');
$application = new yii\web\Application($config);
$application->run();

22
apps/bootstrap/yii

@ -0,0 +1,22 @@
#!/usr/bin/env php
<?php
/**
* Yii console bootstrap file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
defined('YII_DEBUG') or define('YII_DEBUG', true);
// fcgi doesn't have STDIN defined by default
defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
require(__DIR__ . '/vendor/yiisoft/yii2/yii/Yii.php');
require(__DIR__ . '/vendor/autoload.php');
$config = require(__DIR__ . '/config/console.php');
$application = new yii\console\Application($config);
$application->run();

8
yii/yiic.bat → apps/bootstrap/yii.bat

@ -1,9 +1,7 @@
@echo off @echo off
rem ------------------------------------------------------------- rem -------------------------------------------------------------
rem Yii command line script for Windows. rem Yii command line bootstrap script for Windows.
rem
rem This is the bootstrap script for running yiic on Windows.
rem rem
rem @author Qiang Xue <qiang.xue@gmail.com> rem @author Qiang Xue <qiang.xue@gmail.com>
rem @link http://www.yiiframework.com/ rem @link http://www.yiiframework.com/
@ -17,6 +15,6 @@ set YII_PATH=%~dp0
if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
"%PHP_COMMAND%" "%YII_PATH%yiic" %* "%PHP_COMMAND%" "%YII_PATH%yii" %*
@endlocal @endlocal

4
build/build

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

2
build/build.xml

@ -94,7 +94,7 @@
</fileset> </fileset>
<fileset dir="." id="executables"> <fileset dir="." id="executables">
<include name="${build.src.dir}/**/yiic" /> <include name="${build.src.dir}/**/yii" />
</fileset> </fileset>
<target name="src" depends="sync"> <target name="src" depends="sync">

2
build/controllers/LocaleController.php

@ -93,7 +93,7 @@ class LocaleController extends Controller
/** /**
* Plural rules. * Plural rules.
* *
* This file is automatically generated by the "yiic locale/plural" command under the "build" folder. * This file is automatically generated by the "yii locale/plural" command under the "build" folder.
* Do not modify it directly. * Do not modify it directly.
* *
* The original plural rule data used for generating this file has the following copyright terms: * The original plural rule data used for generating this file has the following copyright terms:

212
composer.lock generated

@ -1,212 +0,0 @@
{
"_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": [
]
}

4
docs/api/db/ActiveRecord.md

@ -446,3 +446,7 @@ $customers = Customer::find()->olderThan(50)->all();
The parameters should follow after the `$query` parameter when defining the scope method, and they The parameters should follow after the `$query` parameter when defining the scope method, and they
can take default values like shown above. can take default values like shown above.
### Atomic operations and scenarios
TBD

9
docs/guide/bootstrap.md

@ -28,10 +28,9 @@ app/
img/ containing image files img/ containing image files
themes/ containing application themes themes/ containing application themes
protected/ containing protected application files protected/ containing protected application files
yiic yiic command line script for Unix/Linux yii yii command line script for Unix/Linux
yiic.bat yiic command line script for Windows yii.bat yii command line script for Windows
yiic.php yiic command line PHP script commands/ containing customized yii console commands
commands/ containing customized 'yiic' commands
components/ containing reusable user components components/ containing reusable user components
config/ containing configuration files config/ containing configuration files
console.php the console application configuration console.php the console application configuration
@ -60,4 +59,4 @@ app/
~~~ ~~~
TBD TBD

28
docs/guide/migration.md

@ -19,7 +19,7 @@ The following steps show how we can use database migration during development:
4. Doug applies the migration to his local development database 4. Doug applies the migration to his local development database
Yii supports database migration via the `yiic migrate` command line tool. This Yii supports database migration via the `yii migrate` command line tool. This
tool supports creating new migrations, applying/reverting/redoing migrations, and tool supports creating new migrations, applying/reverting/redoing migrations, and
showing migration history and new migrations. showing migration history and new migrations.
@ -29,7 +29,7 @@ Creating Migrations
To create a new migration (e.g. create a news table), we run the following command: To create a new migration (e.g. create a news table), we run the following command:
~~~ ~~~
yiic migrate/create <name> yii migrate/create <name>
~~~ ~~~
The required `name` parameter specifies a very brief description of the migration The required `name` parameter specifies a very brief description of the migration
@ -38,7 +38,7 @@ is used as part of a PHP class name. Therefore, it should only contain letters,
digits and/or underscore characters. digits and/or underscore characters.
~~~ ~~~
yiic migrate/create create_news_table yii migrate/create create_news_table
~~~ ~~~
The above command will create under the `protected/migrations` directory a new The above command will create under the `protected/migrations` directory a new
@ -153,7 +153,7 @@ To apply all available new migrations (i.e., make the local database up-to-date)
run the following command: run the following command:
~~~ ~~~
yiic migrate yii migrate
~~~ ~~~
The command will show the list of all new migrations. If you confirm to apply The command will show the list of all new migrations. If you confirm to apply
@ -170,7 +170,7 @@ Sometimes, we may only want to apply one or a few new migrations. We can use the
following command: following command:
~~~ ~~~
yiic migrate/up 3 yii migrate/up 3
~~~ ~~~
This command will apply the 3 new migrations. Changing the value 3 will allow This command will apply the 3 new migrations. Changing the value 3 will allow
@ -179,7 +179,7 @@ us to change the number of migrations to be applied.
We can also migrate the database to a specific version with the following command: We can also migrate the database to a specific version with the following command:
~~~ ~~~
yiic migrate/to 101129_185401 yii migrate/to 101129_185401
~~~ ~~~
That is, we use the timestamp part of a migration name to specify the version That is, we use the timestamp part of a migration name to specify the version
@ -196,7 +196,7 @@ To revert the last one or several applied migrations, we can use the following
command: command:
~~~ ~~~
yiic migrate/down [step] yii migrate/down [step]
~~~ ~~~
where the optional `step` parameter specifies how many migrations to be reverted where the optional `step` parameter specifies how many migrations to be reverted
@ -213,7 +213,7 @@ Redoing migrations means first reverting and then applying the specified migrati
This can be done with the following command: This can be done with the following command:
~~~ ~~~
yiic migrate/redo [step] yii migrate/redo [step]
~~~ ~~~
where the optional `step` parameter specifies how many migrations to be redone. where the optional `step` parameter specifies how many migrations to be redone.
@ -227,8 +227,8 @@ Besides applying and reverting migrations, the migration tool can also display
the migration history and the new migrations to be applied. the migration history and the new migrations to be applied.
~~~ ~~~
yiic migrate/history [limit] yii migrate/history [limit]
yiic migrate/new [limit] yii migrate/new [limit]
~~~ ~~~
where the optional parameter `limit` specifies the number of migrations to be where the optional parameter `limit` specifies the number of migrations to be
@ -247,10 +247,10 @@ often happens when developing a new migration. We can use the following command
to achieve this goal. to achieve this goal.
~~~ ~~~
yiic migrate/mark 101129_185401 yii migrate/mark 101129_185401
~~~ ~~~
This command is very similar to `yiic migrate/to` command, except that it only This command is very similar to `yii migrate/to` command, except that it only
modifies the migration history table to the specified version without applying modifies the migration history table to the specified version without applying
or reverting the migrations. or reverting the migrations.
@ -291,7 +291,7 @@ line:
To specify these options, execute the migrate command using the following format To specify these options, execute the migrate command using the following format
~~~ ~~~
yiic migrate/up --option1=value1 --option2=value2 ... yii migrate/up --option1=value1 --option2=value2 ...
~~~ ~~~
For example, if we want to migrate for a `forum` module whose migration files For example, if we want to migrate for a `forum` module whose migration files
@ -299,7 +299,7 @@ are located within the module's `migrations` directory, we can use the following
command: command:
~~~ ~~~
yiic migrate/up --migrationPath=ext.forum.migrations yii migrate/up --migrationPath=ext.forum.migrations
~~~ ~~~

32
docs/guide/upgrade-from-v1.md

@ -152,7 +152,7 @@ with significant improvements. For more details, please see the "assets" subsect
While Yii 2.0 continues to use PHP as its main template language, it comes with built-in While Yii 2.0 continues to use PHP as its main template language, it comes with built-in
support for two popular template engines: Smarty and Twig. The Prado template engine is support for two popular template engines: Smarty and Twig. The Prado template engine is
no longer supported. To use these template engines, you just need to use `tpl` as the file no longer supported. To use these template engines, you just need to use `tpl` as the file
extension for your Smarty views, or `twig` for Twig views. You may also configure the extension for your Smarty views, or `twig` for Twig views. You may also configure the
`View::renderers` property to use other template engines. `View::renderers` property to use other template engines.
@ -209,6 +209,26 @@ if (isset($_POST['Post'])) {
``` ```
Widgets
-------
Using a widget is more straightforward in 2.0. You mainly use the `begin()`, `end()` and `widget()`
methods of the `Widget` class. For example,
```php
// $this refers to the View object
// Note that you have to "echo" the result to display it
echo \yii\widgets\Menu::widget(array('items' => $items));
// $this refers to the View object
$form = \yii\widgets\ActiveForm::begin($this);
... form inputs here ...
\yii\widgets\ActiveForm::end();
```
Previously in 1.1, you would have to enter the widget class names as strings via the `beginWidget()`,
`endWidget()` and `widget()` methods of `CBaseController`. The approach above gets better IDE support.
Themes Themes
------ ------
@ -232,7 +252,7 @@ Console applications are now composed by controllers, too, like Web applications
console controllers and Web controllers share the same base controller class. console controllers and Web controllers share the same base controller class.
Each console controller is like `CConsoleCommand` in 1.1. It consists of one or several Each console controller is like `CConsoleCommand` in 1.1. It consists of one or several
actions. You use the `yiic <route>` command to execute a console command, where `<route>` actions. You use the `yii <route>` command to execute a console command, where `<route>`
stands for a controller route (e.g. `sitemap/index`). Additional anonymous arguments stands for a controller route (e.g. `sitemap/index`). Additional anonymous arguments
are passed as the parameters to the corresponding controller action method, and named arguments are passed as the parameters to the corresponding controller action method, and named arguments
are treated as global options declared in `globalOptions()`. are treated as global options declared in `globalOptions()`.
@ -249,10 +269,6 @@ Message translation is still supported, but managed via the "i18n" application c
The component manages a set of message sources, which allows you to use different message The component manages a set of message sources, which allows you to use different message
sources based on message categories. For more information, see the class documentation for `I18N`. sources based on message categories. For more information, see the class documentation for `I18N`.
The message translation method is changed by merging the message category into the message being
translated. For example, `Yii::t('yii|message to be translated')`.
Action Filters Action Filters
-------------- --------------
@ -309,13 +325,13 @@ is a container consisting of a label, an input, and an error message. It is repr
as an `ActiveField` object. Using fields, you can build a form more cleanly than before: as an `ActiveField` object. Using fields, you can build a form more cleanly than before:
```php ```php
<?php $form = $this->beginWidget('yii\widgets\ActiveForm'); ?> <?php $form = yii\widgets\ActiveForm::begin(); ?>
<?php echo $form->field($model, 'username')->textInput(); ?> <?php echo $form->field($model, 'username')->textInput(); ?>
<?php echo $form->field($model, 'password')->passwordInput(); ?> <?php echo $form->field($model, 'password')->passwordInput(); ?>
<div class="form-actions"> <div class="form-actions">
<?php echo Html::submitButton('Login'); ?> <?php echo Html::submitButton('Login'); ?>
</div> </div>
<?php $this->endWidget(); ?> <?php yii\widgets\ActiveForm::end(); ?>
``` ```

25
docs/internals/ar.md

@ -1,15 +1,32 @@
ActiveRecord ActiveRecord
============ ============
Scenarios
---------
Possible scenario formats supported by ActiveRecord:
```php
public function scenarios()
{
return array(
// attributes array, all operations won't be wrapped with transaction
'scenario1' => array('attribute1', 'attribute2'),
// insert and update operations will be wrapped with transaction, delete won't be wrapped
'scenario2' => array(
'attributes' => array('attribute1', 'attribute2'),
'atomic' => array(self::OP_INSERT, self::OP_UPDATE),
),
);
}
```
Query Query
----- -----
### Basic Queries ### Basic Queries
### Relational Queries ### Relational Queries
### Scopes ### Scopes

27
extensions/composer/composer.json

@ -0,0 +1,27 @@
{
"name": "yiisoft/yii2-composer",
"description": "The composer integration for the Yii framework",
"keywords": ["yii", "composer", "install", "update"],
"type": "library",
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/yii2/issues?state=open",
"forum": "http://www.yiiframework.com/forum/",
"wiki": "http://www.yiiframework.com/wiki/",
"irc": "irc://irc.freenode.net/yii",
"source": "https://github.com/yiisoft/yii2"
},
"authors": [
{
"name": "Qiang Xue",
"email": "qiang.xue@gmail.com"
}
],
"minimum-stability": "dev",
"require": {
"yiisoft/yii2": "dev-master"
},
"autoload": {
"psr-0": { "yii\\composer": "" }
}
}

53
extensions/composer/yii/composer/InstallHandler.php

@ -0,0 +1,53 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\composer;
use Composer\Script\CommandEvent;
/**
* InstallHandler is called by Composer after it installs/updates the current package.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class InstallHandler
{
/**
* Sets the correct permissions of files and directories.
* @param CommandEvent $event
*/
public static function setPermissions($event)
{
$options = array_merge(array(
'writable' => array(),
'executable' => array(),
), $event->getComposer()->getPackage()->getExtra());
foreach ((array)$options['writable'] as $path) {
echo "Setting writable: $path ...";
if (is_dir($path)) {
chmod($path, 0777);
echo "done\n";
} else {
echo "The directory was not found: " . getcwd() . DIRECTORY_SEPARATOR . $path;
return;
}
}
foreach ((array)$options['executable'] as $path) {
echo "Setting executable: $path ...";
if (is_file($path)) {
chmod($path, 0755);
echo "done\n";
} else {
echo "\n\tThe file was not found: " . getcwd() . DIRECTORY_SEPARATOR . $path . "\n";
return;
}
}
}
}

0
changelog.md → framework/CHANGELOG.md

32
framework/LICENSE.md

@ -0,0 +1,32 @@
The Yii framework is free software. It is released under the terms of
the following BSD License.
Copyright © 2008-2013 by Yii Software LLC (http://www.yiisoft.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Yii Software LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

21
framework/README.md

@ -0,0 +1,21 @@
Yii 2.0 Public Preview
======================
Thank you for choosing Yii - a high-performance component-based PHP framework.
If you are looking for a production-ready PHP framework, please use
[Yii v1.1](https://github.com/yiisoft/yii).
Yii 2.0 is still under heavy development. We may make significant changes
without prior notices. **Yii 2.0 is not ready for production use yet.**
[![Build Status](https://secure.travis-ci.org/yiisoft/yii2.png)](http://travis-ci.org/yiisoft/yii2)
REQUIREMENTS
------------
The minimum requirement by Yii is that your Web server supports PHP 5.3.?.

9
framework/UPGRADE.md

@ -0,0 +1,9 @@
Upgrading Instructions for Yii Framework v2
===========================================
!!!IMPORTANT!!!
The following upgrading instructions are cumulative. That is,
if you want to upgrade from version A to version C and there is
version B between A and C, you need to following the instructions
for both A and B.

23
composer.json → framework/composer.json

@ -63,17 +63,18 @@
"irc": "irc://irc.freenode.net/yii", "irc": "irc://irc.freenode.net/yii",
"source": "https://github.com/yiisoft/yii2" "source": "https://github.com/yiisoft/yii2"
}, },
"config": {
"vendor-dir": "yii/vendor"
},
"bin": [
"yii/yiic"
],
"require": { "require": {
"php": ">=5.3.0", "php": ">=5.3.11",
"michelf/php-markdown": "1.3", "ext-mbstring": "*",
"twig/twig": "1.12.*", "lib-pcre": "*"
"smarty/smarty": "3.1.*", },
"ezyang/htmlpurifier": "v4.5.0" "autoload": {
"psr-0": { "yii\\": "/" }
},
"suggest": {
"michelf/php-markdown": "Required for Markdown helper.",
"twig/twig": "Required for TwigViewRenderer.",
"smarty/smarty": "Required for SmartyViewRenderer.",
"ezyang/htmlpurifier": "Required for Purifier helper."
} }
} }

3
framework/yii/.gitignore vendored

@ -0,0 +1,3 @@
phpunit.xml
composer.lock

0
apps/bootstrap/protected/.htaccess → framework/yii/.htaccess

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

32
yii/YiiBase.php → framework/yii/YiiBase.php

@ -70,9 +70,7 @@ class YiiBase
* @see getAlias * @see getAlias
* @see setAlias * @see setAlias
*/ */
public static $aliases = array( public static $aliases;
'@yii' => __DIR__,
);
/** /**
* @var array initial property values that will be applied to objects newly created via [[createObject]]. * @var array initial property values that will be applied to objects newly created via [[createObject]].
* The array keys are class names without leading backslashes "\", and the array values are the corresponding * The array keys are class names without leading backslashes "\", and the array values are the corresponding
@ -287,7 +285,11 @@ class YiiBase
if ($path !== null) { if ($path !== null) {
$path = strncmp($path, '@', 1) ? rtrim($path, '\\/') : static::getAlias($path); $path = strncmp($path, '@', 1) ? rtrim($path, '\\/') : static::getAlias($path);
if (!isset(self::$aliases[$root])) { if (!isset(self::$aliases[$root])) {
self::$aliases[$root] = $path; if ($pos === false) {
self::$aliases[$root] = $path;
} else {
self::$aliases[$root] = array($alias => $path);
}
} elseif (is_string(self::$aliases[$root])) { } elseif (is_string(self::$aliases[$root])) {
if ($pos === false) { if ($pos === false) {
self::$aliases[$root] = $path; self::$aliases[$root] = $path;
@ -579,10 +581,9 @@ class YiiBase
/** /**
* Translates a message to the specified language. * Translates a message to the specified language.
* *
* The translation will be conducted according to the message category and the target language. * This is a shortcut method of [[\yii\i18n\I18N::translate()]].
* To specify the category of the message, prefix the message with the category name and separate it *
* with "|". For example, "app|hello world". If the category is not specified, the default category "app" * The translation will be conducted according to the message category and the target language will be used.
* will be used. The actual message translation is done by a [[\yii\i18n\MessageSource|message source]].
* *
* In case when a translated message has different plural forms (separated by "|"), this method * In case when a translated message has different plural forms (separated by "|"), this method
* will also attempt to choose an appropriate one according to a given numeric value which is * will also attempt to choose an appropriate one according to a given numeric value which is
@ -595,21 +596,26 @@ class YiiBase
* For more details on how plural rules are applied, please refer to: * For more details on how plural rules are applied, please refer to:
* [[http://www.unicode.org/cldr/charts/supplemental/language_plural_rules.html]] * [[http://www.unicode.org/cldr/charts/supplemental/language_plural_rules.html]]
* *
* @param string $category the message category.
* @param string $message the message to be translated. * @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 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 * @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. * [[\yii\base\Application::language|application language]] will be used.
* @return string the translated message. * @return string the translated message.
*/ */
public static function t($message, $params = array(), $language = null) public static function t($category, $message, $params = array(), $language = null)
{ {
if (self::$app !== null) { if (self::$app !== null) {
return self::$app->getI18N()->translate($message, $params, $language); return self::$app->getI18N()->translate($category, $message, $params, $language);
} else { } else {
if (strpos($message, '|') !== false && preg_match('/^([\w\-\\/\.\\\\]+)\|(.*)/', $message, $matches)) {
$message = $matches[2];
}
return is_array($params) ? strtr($message, $params) : $message; return is_array($params) ? strtr($message, $params) : $message;
} }
} }
} }
YiiBase::$aliases = array(
'@yii' => array(
'@yii/bootstrap' => __DIR__ . '/bootstrap',
'@yii' => __DIR__,
),
);

18
yii/assets.php → framework/yii/assets.php

@ -1,18 +1,18 @@
<?php <?php
return array( return array(
'jquery' => array( 'yii' => array(
'sourcePath' => __DIR__ . '/assets', 'sourcePath' => __DIR__ . '/assets',
'js' => array( 'js' => array(
'jquery.min.js', 'yii.js',
), ),
'depends' => array('yii/jquery'),
), ),
'yii' => array( 'yii/jquery' => array(
'sourcePath' => __DIR__ . '/assets', 'sourcePath' => __DIR__ . '/assets',
'js' => array( 'js' => array(
'yii.js', YII_DEBUG ? 'jquery.js' : 'jquery.min.js',
), ),
'depends' => array('jquery'),
), ),
'yii/validation' => array( 'yii/validation' => array(
'sourcePath' => __DIR__ . '/assets', 'sourcePath' => __DIR__ . '/assets',
@ -26,7 +26,7 @@ return array(
'js' => array( 'js' => array(
'yii.activeForm.js', 'yii.activeForm.js',
), ),
'depends' => array('yii', 'yii/validation'), 'depends' => array('yii'),
), ),
'yii/captcha' => array( 'yii/captcha' => array(
'sourcePath' => __DIR__ . '/assets', 'sourcePath' => __DIR__ . '/assets',
@ -42,4 +42,10 @@ return array(
), ),
'depends' => array('yii'), 'depends' => array('yii'),
), ),
'yii/punycode' => array(
'sourcePath' => __DIR__ . '/assets',
'js' => array(
YII_DEBUG ? 'punycode/punycode.js' : 'punycode/punycode.min.js',
),
),
); );

9597
framework/yii/assets/jquery.js vendored

File diff suppressed because it is too large Load Diff

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

278
framework/yii/assets/punycode/LICENSE-GPL.txt

@ -0,0 +1,278 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

20
framework/yii/assets/punycode/LICENSE-MIT.txt

@ -0,0 +1,20 @@
Copyright Mathias Bynens <http://mathiasbynens.be/>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

502
framework/yii/assets/punycode/punycode.js

@ -0,0 +1,502 @@
/*! http://mths.be/punycode v1.2.1 by @mathias */
;(function(root) {
/** Detect free variables */
var freeExports = typeof exports == 'object' && exports;
var freeModule = typeof module == 'object' && module &&
module.exports == freeExports && module;
var freeGlobal = typeof global == 'object' && global;
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
root = freeGlobal;
}
/**
* The `punycode` object.
* @name punycode
* @type Object
*/
var punycode,
/** Highest positive signed 32-bit float value */
maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
/** Bootstring parameters */
base = 36,
tMin = 1,
tMax = 26,
skew = 38,
damp = 700,
initialBias = 72,
initialN = 128, // 0x80
delimiter = '-', // '\x2D'
/** Regular expressions */
regexPunycode = /^xn--/,
regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars
regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators
/** Error messages */
errors = {
'overflow': 'Overflow: input needs wider integers to process',
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
'invalid-input': 'Invalid input'
},
/** Convenience shortcuts */
baseMinusTMin = base - tMin,
floor = Math.floor,
stringFromCharCode = String.fromCharCode,
/** Temporary variable */
key;
/*--------------------------------------------------------------------------*/
/**
* A generic error utility function.
* @private
* @param {String} type The error type.
* @returns {Error} Throws a `RangeError` with the applicable error message.
*/
function error(type) {
throw RangeError(errors[type]);
}
/**
* A generic `Array#map` utility function.
* @private
* @param {Array} array The array to iterate over.
* @param {Function} callback The function that gets called for every array
* item.
* @returns {Array} A new array of values returned by the callback function.
*/
function map(array, fn) {
var length = array.length;
while (length--) {
array[length] = fn(array[length]);
}
return array;
}
/**
* A simple `Array#map`-like wrapper to work with domain name strings.
* @private
* @param {String} domain The domain name.
* @param {Function} callback The function that gets called for every
* character.
* @returns {Array} A new string of characters returned by the callback
* function.
*/
function mapDomain(string, fn) {
return map(string.split(regexSeparators), fn).join('.');
}
/**
* Creates an array containing the decimal code points of each Unicode
* character in the string. While JavaScript uses UCS-2 internally,
* this function will convert a pair of surrogate halves (each of which
* UCS-2 exposes as separate characters) into a single code point,
* matching UTF-16.
* @see `punycode.ucs2.encode`
* @see <http://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode.ucs2
* @name decode
* @param {String} string The Unicode input string (UCS-2).
* @returns {Array} The new array of code points.
*/
function ucs2decode(string) {
var output = [],
counter = 0,
length = string.length,
value,
extra;
while (counter < length) {
value = string.charCodeAt(counter++);
if ((value & 0xF800) == 0xD800 && counter < length) {
// high surrogate, and there is a next character
extra = string.charCodeAt(counter++);
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
} else {
output.push(value, extra);
}
} else {
output.push(value);
}
}
return output;
}
/**
* Creates a string based on an array of decimal code points.
* @see `punycode.ucs2.decode`
* @memberOf punycode.ucs2
* @name encode
* @param {Array} codePoints The array of decimal code points.
* @returns {String} The new Unicode string (UCS-2).
*/
function ucs2encode(array) {
return map(array, function(value) {
var output = '';
if (value > 0xFFFF) {
value -= 0x10000;
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
value = 0xDC00 | value & 0x3FF;
}
output += stringFromCharCode(value);
return output;
}).join('');
}
/**
* Converts a basic code point into a digit/integer.
* @see `digitToBasic()`
* @private
* @param {Number} codePoint The basic (decimal) code point.
* @returns {Number} The numeric value of a basic code point (for use in
* representing integers) in the range `0` to `base - 1`, or `base` if
* the code point does not represent a value.
*/
function basicToDigit(codePoint) {
return codePoint - 48 < 10
? codePoint - 22
: codePoint - 65 < 26
? codePoint - 65
: codePoint - 97 < 26
? codePoint - 97
: base;
}
/**
* Converts a digit/integer into a basic code point.
* @see `basicToDigit()`
* @private
* @param {Number} digit The numeric value of a basic code point.
* @returns {Number} The basic code point whose value (when used for
* representing integers) is `digit`, which needs to be in the range
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
* used; else, the lowercase form is used. The behavior is undefined
* if flag is non-zero and `digit` has no uppercase form.
*/
function digitToBasic(digit, flag) {
// 0..25 map to ASCII a..z or A..Z
// 26..35 map to ASCII 0..9
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
}
/**
* Bias adaptation function as per section 3.4 of RFC 3492.
* http://tools.ietf.org/html/rfc3492#section-3.4
* @private
*/
function adapt(delta, numPoints, firstTime) {
var k = 0;
delta = firstTime ? floor(delta / damp) : delta >> 1;
delta += floor(delta / numPoints);
for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
delta = floor(delta / baseMinusTMin);
}
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
}
/**
* Converts a Punycode string of ASCII code points to a string of Unicode
* code points.
* @memberOf punycode
* @param {String} input The Punycode string of ASCII code points.
* @returns {String} The resulting string of Unicode code points.
*/
function decode(input) {
// Don't use UCS-2
var output = [],
inputLength = input.length,
out,
i = 0,
n = initialN,
bias = initialBias,
basic,
j,
index,
oldi,
w,
k,
digit,
t,
length,
/** Cached calculation results */
baseMinusT;
// Handle the basic code points: let `basic` be the number of input code
// points before the last delimiter, or `0` if there is none, then copy
// the first basic code points to the output.
basic = input.lastIndexOf(delimiter);
if (basic < 0) {
basic = 0;
}
for (j = 0; j < basic; ++j) {
// if it's not a basic code point
if (input.charCodeAt(j) >= 0x80) {
error('not-basic');
}
output.push(input.charCodeAt(j));
}
// Main decoding loop: start just after the last delimiter if any basic code
// points were copied; start at the beginning otherwise.
for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
// `index` is the index of the next character to be consumed.
// Decode a generalized variable-length integer into `delta`,
// which gets added to `i`. The overflow checking is easier
// if we increase `i` as we go, then subtract off its starting
// value at the end to obtain `delta`.
for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
if (index >= inputLength) {
error('invalid-input');
}
digit = basicToDigit(input.charCodeAt(index++));
if (digit >= base || digit > floor((maxInt - i) / w)) {
error('overflow');
}
i += digit * w;
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
if (digit < t) {
break;
}
baseMinusT = base - t;
if (w > floor(maxInt / baseMinusT)) {
error('overflow');
}
w *= baseMinusT;
}
out = output.length + 1;
bias = adapt(i - oldi, out, oldi == 0);
// `i` was supposed to wrap around from `out` to `0`,
// incrementing `n` each time, so we'll fix that now:
if (floor(i / out) > maxInt - n) {
error('overflow');
}
n += floor(i / out);
i %= out;
// Insert `n` at position `i` of the output
output.splice(i++, 0, n);
}
return ucs2encode(output);
}
/**
* Converts a string of Unicode code points to a Punycode string of ASCII
* code points.
* @memberOf punycode
* @param {String} input The string of Unicode code points.
* @returns {String} The resulting Punycode string of ASCII code points.
*/
function encode(input) {
var n,
delta,
handledCPCount,
basicLength,
bias,
j,
m,
q,
k,
t,
currentValue,
output = [],
/** `inputLength` will hold the number of code points in `input`. */
inputLength,
/** Cached calculation results */
handledCPCountPlusOne,
baseMinusT,
qMinusT;
// Convert the input in UCS-2 to Unicode
input = ucs2decode(input);
// Cache the length
inputLength = input.length;
// Initialize the state
n = initialN;
delta = 0;
bias = initialBias;
// Handle the basic code points
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < 0x80) {
output.push(stringFromCharCode(currentValue));
}
}
handledCPCount = basicLength = output.length;
// `handledCPCount` is the number of code points that have been handled;
// `basicLength` is the number of basic code points.
// Finish the basic string - if it is not empty - with a delimiter
if (basicLength) {
output.push(delimiter);
}
// Main encoding loop:
while (handledCPCount < inputLength) {
// All non-basic code points < n have been handled already. Find the next
// larger one:
for (m = maxInt, j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue >= n && currentValue < m) {
m = currentValue;
}
}
// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
// but guard against overflow
handledCPCountPlusOne = handledCPCount + 1;
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
error('overflow');
}
delta += (m - n) * handledCPCountPlusOne;
n = m;
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < n && ++delta > maxInt) {
error('overflow');
}
if (currentValue == n) {
// Represent delta as a generalized variable-length integer
for (q = delta, k = base; /* no condition */; k += base) {
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
if (q < t) {
break;
}
qMinusT = q - t;
baseMinusT = base - t;
output.push(
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
);
q = floor(qMinusT / baseMinusT);
}
output.push(stringFromCharCode(digitToBasic(q, 0)));
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
delta = 0;
++handledCPCount;
}
}
++delta;
++n;
}
return output.join('');
}
/**
* Converts a Punycode string representing a domain name to Unicode. Only the
* Punycoded parts of the domain name will be converted, i.e. it doesn't
* matter if you call it on a string that has already been converted to
* Unicode.
* @memberOf punycode
* @param {String} domain The Punycode domain name to convert to Unicode.
* @returns {String} The Unicode representation of the given Punycode
* string.
*/
function toUnicode(domain) {
return mapDomain(domain, function(string) {
return regexPunycode.test(string)
? decode(string.slice(4).toLowerCase())
: string;
});
}
/**
* Converts a Unicode string representing a domain name to Punycode. Only the
* non-ASCII parts of the domain name will be converted, i.e. it doesn't
* matter if you call it with a domain that's already in ASCII.
* @memberOf punycode
* @param {String} domain The domain name to convert, as a Unicode string.
* @returns {String} The Punycode representation of the given domain name.
*/
function toASCII(domain) {
return mapDomain(domain, function(string) {
return regexNonASCII.test(string)
? 'xn--' + encode(string)
: string;
});
}
/*--------------------------------------------------------------------------*/
/** Define the public API */
punycode = {
/**
* A string representing the current Punycode.js version number.
* @memberOf punycode
* @type String
*/
'version': '1.2.1',
/**
* An object of methods to convert from JavaScript's internal character
* representation (UCS-2) to decimal Unicode code points, and back.
* @see <http://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode
* @type Object
*/
'ucs2': {
'decode': ucs2decode,
'encode': ucs2encode
},
'decode': decode,
'encode': encode,
'toASCII': toASCII,
'toUnicode': toUnicode
};
/** Expose `punycode` */
// Some AMD build optimizers, like r.js, check for specific condition patterns
// like the following:
if (
typeof define == 'function' &&
typeof define.amd == 'object' &&
define.amd
) {
define(function() {
return punycode;
});
} else if (freeExports && !freeExports.nodeType) {
if (freeModule) { // in Node.js or RingoJS v0.8.0+
freeModule.exports = punycode;
} else { // in Narwhal or RingoJS v0.7.0-
for (key in punycode) {
punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
}
}
} else { // in Rhino or a web browser
root.punycode = punycode;
}
}(this));

2
framework/yii/assets/punycode/punycode.min.js vendored

@ -0,0 +1,2 @@
/*! http://mths.be/punycode v1.2.1 by @mathias */
(function(o){function e(o){throw RangeError(L[o])}function n(o,e){for(var n=o.length;n--;)o[n]=e(o[n]);return o}function t(o,e){return n(o.split(S),e).join(".")}function r(o){for(var e,n,t=[],r=0,u=o.length;u>r;)e=o.charCodeAt(r++),55296==(63488&e)&&u>r?(n=o.charCodeAt(r++),56320==(64512&n)?t.push(((1023&e)<<10)+(1023&n)+65536):t.push(e,n)):t.push(e);return t}function u(o){return n(o,function(o){var e="";return o>65535&&(o-=65536,e+=R(55296|1023&o>>>10),o=56320|1023&o),e+=R(o)}).join("")}function i(o){return 10>o-48?o-22:26>o-65?o-65:26>o-97?o-97:x}function f(o,e){return o+22+75*(26>o)-((0!=e)<<5)}function c(o,e,n){var t=0;for(o=n?P(o/m):o>>1,o+=P(o/e);o>M*y>>1;t+=x)o=P(o/M);return P(t+(M+1)*o/(o+j))}function l(o){var n,t,r,f,l,d,s,a,p,h,v=[],g=o.length,w=0,j=I,m=A;for(t=o.lastIndexOf(F),0>t&&(t=0),r=0;t>r;++r)o.charCodeAt(r)>=128&&e("not-basic"),v.push(o.charCodeAt(r));for(f=t>0?t+1:0;g>f;){for(l=w,d=1,s=x;f>=g&&e("invalid-input"),a=i(o.charCodeAt(f++)),(a>=x||a>P((b-w)/d))&&e("overflow"),w+=a*d,p=m>=s?C:s>=m+y?y:s-m,!(p>a);s+=x)h=x-p,d>P(b/h)&&e("overflow"),d*=h;n=v.length+1,m=c(w-l,n,0==l),P(w/n)>b-j&&e("overflow"),j+=P(w/n),w%=n,v.splice(w++,0,j)}return u(v)}function d(o){var n,t,u,i,l,d,s,a,p,h,v,g,w,j,m,E=[];for(o=r(o),g=o.length,n=I,t=0,l=A,d=0;g>d;++d)v=o[d],128>v&&E.push(R(v));for(u=i=E.length,i&&E.push(F);g>u;){for(s=b,d=0;g>d;++d)v=o[d],v>=n&&s>v&&(s=v);for(w=u+1,s-n>P((b-t)/w)&&e("overflow"),t+=(s-n)*w,n=s,d=0;g>d;++d)if(v=o[d],n>v&&++t>b&&e("overflow"),v==n){for(a=t,p=x;h=l>=p?C:p>=l+y?y:p-l,!(h>a);p+=x)m=a-h,j=x-h,E.push(R(f(h+m%j,0))),a=P(m/j);E.push(R(f(a,0))),l=c(t,w,u==i),t=0,++u}++t,++n}return E.join("")}function s(o){return t(o,function(o){return E.test(o)?l(o.slice(4).toLowerCase()):o})}function a(o){return t(o,function(o){return O.test(o)?"xn--"+d(o):o})}var p="object"==typeof exports&&exports,h="object"==typeof module&&module&&module.exports==p&&module,v="object"==typeof global&&global;(v.global===v||v.window===v)&&(o=v);var g,w,b=2147483647,x=36,C=1,y=26,j=38,m=700,A=72,I=128,F="-",E=/^xn--/,O=/[^ -~]/,S=/\x2E|\u3002|\uFF0E|\uFF61/g,L={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},M=x-C,P=Math.floor,R=String.fromCharCode;if(g={version:"1.2.1",ucs2:{decode:r,encode:u},decode:l,encode:d,toASCII:a,toUnicode:s},"function"==typeof define&&"object"==typeof define.amd&&define.amd)define(function(){return g});else if(p&&!p.nodeType)if(h)h.exports=g;else for(w in g)g.hasOwnProperty(w)&&(p[w]=g[w]);else o.punycode=g})(this);

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

@ -57,7 +57,7 @@
// whether to perform validation when a change is detected on the input // whether to perform validation when a change is detected on the input
validateOnChange: false, validateOnChange: false,
// whether to perform validation when the user is typing. // whether to perform validation when the user is typing.
validateOnType: false, validateOnType: false,
// number of milliseconds that the validation should be delayed when a user is typing in the input field. // number of milliseconds that the validation should be delayed when a user is typing in the input field.
validationDelay: 200, validationDelay: 200,
// whether to enable AJAX-based validation. // whether to enable AJAX-based validation.

4
yii/assets/yii.captcha.js → framework/yii/assets/yii.captcha.js

@ -51,8 +51,8 @@
dataType: 'json', dataType: 'json',
cache: false, cache: false,
success: function(data) { success: function(data) {
$e.attr('src', data['url']); $e.attr('src', data.url);
$('body').data(settings.hashKey, [data['hash1'], data['hash2']]); $('body').data(settings.hashKey, [data.hash1, data.hash2]);
} }
}); });
}, },

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

@ -18,7 +18,7 @@ yii.debug = (function ($) {
//dataType: 'json', //dataType: 'json',
success: function(data) { success: function(data) {
var $e = $('#' + id); var $e = $('#' + id);
$e.html(data); $e.html(data).show();
} }
}); });
} }

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

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

@ -110,9 +110,19 @@ yii.validation = (function ($) {
return; return;
} }
var valid = value.match(options.pattern) && (!options.allowName || value.match(options.fullPattern)); var valid = true;
if (options.enableIDN) {
var regexp = /^(.*)@(.*)$/,
matches = regexp.exec(value);
if (matches === null) {
valid = false;
} else {
value = punycode.toASCII(matches[1]) + '@' + punycode.toASCII(matches[2]);
}
}
if (!valid) { if (!valid || !(value.match(options.pattern) && (!options.allowName || value.match(options.fullPattern)))) {
messages.push(options.message); messages.push(options.message);
} }
}, },
@ -126,7 +136,19 @@ yii.validation = (function ($) {
value = options.defaultScheme + '://' + value; value = options.defaultScheme + '://' + value;
} }
if (!value.match(options.pattern)) { var valid = true;
if (options.enableIDN) {
var regexp = /^([^:]+):\/\/([^\/]+)(.*)$/,
matches = regexp.exec(value);
if (matches === null) {
valid = false;
} else {
value = matches[1] + '://' + punycode.toASCII(matches[2]) + matches[3];
}
}
if (!valid || !value.match(options.pattern)) {
messages.push(options.message); messages.push(options.message);
} }
}, },

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

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

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

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

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

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

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

@ -8,7 +8,6 @@
namespace yii\base; namespace yii\base;
use Yii; use Yii;
use yii\helpers\StringHelper;
/** /**
* Controller is the base class for classes containing controller logic. * Controller is the base class for classes containing controller logic.
@ -183,7 +182,7 @@ class Controller extends Component
} }
if (!empty($missing)) { if (!empty($missing)) {
throw new InvalidRequestException(Yii::t('yii|Missing required parameters: {params}', array( throw new InvalidRequestException(Yii::t('yii', 'Missing required parameters: {params}', array(
'{params}' => implode(', ', $missing), '{params}' => implode(', ', $missing),
))); )));
} }
@ -226,7 +225,7 @@ class Controller extends Component
if (isset($actionMap[$id])) { if (isset($actionMap[$id])) {
return Yii::createObject($actionMap[$id], $id, $this); return Yii::createObject($actionMap[$id], $id, $this);
} elseif (preg_match('/^[a-z0-9\\-_]+$/', $id)) { } elseif (preg_match('/^[a-z0-9\\-_]+$/', $id)) {
$methodName = 'action' . StringHelper::id2camel($id); $methodName = 'action' . str_replace(' ', '', ucwords(implode(' ', explode('-', $id))));
if (method_exists($this, $methodName)) { if (method_exists($this, $methodName)) {
$method = new \ReflectionMethod($this, $methodName); $method = new \ReflectionMethod($this, $methodName);
if ($method->getName() === $methodName) { if ($method->getName() === $methodName) {
@ -410,6 +409,7 @@ class Controller extends Component
* Returns the view object that can be used to render views or view files. * Returns the view object that can be used to render views or view files.
* The [[render()]], [[renderPartial()]] and [[renderFile()]] methods will use * The [[render()]], [[renderPartial()]] and [[renderFile()]] methods will use
* this view object to implement the actual view rendering. * this view object to implement the actual view rendering.
* If not set, it will default to the "view" application component.
* @return View the view object that can be used to render views or view files. * @return View the view object that can be used to render views or view files.
*/ */
public function getView() public function getView()

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

@ -90,20 +90,20 @@ class ErrorException extends Exception
public function getName() public function getName()
{ {
$names = array( $names = array(
E_ERROR => Yii::t('yii|Fatal Error'), E_ERROR => Yii::t('yii', 'Fatal Error'),
E_PARSE => Yii::t('yii|Parse Error'), E_PARSE => Yii::t('yii', 'Parse Error'),
E_CORE_ERROR => Yii::t('yii|Core Error'), E_CORE_ERROR => Yii::t('yii', 'Core Error'),
E_COMPILE_ERROR => Yii::t('yii|Compile Error'), E_COMPILE_ERROR => Yii::t('yii', 'Compile Error'),
E_USER_ERROR => Yii::t('yii|User Error'), E_USER_ERROR => Yii::t('yii', 'User Error'),
E_WARNING => Yii::t('yii|Warning'), E_WARNING => Yii::t('yii', 'Warning'),
E_CORE_WARNING => Yii::t('yii|Core Warning'), E_CORE_WARNING => Yii::t('yii', 'Core Warning'),
E_COMPILE_WARNING => Yii::t('yii|Compile Warning'), E_COMPILE_WARNING => Yii::t('yii', 'Compile Warning'),
E_USER_WARNING => Yii::t('yii|User Warning'), E_USER_WARNING => Yii::t('yii', 'User Warning'),
E_STRICT => Yii::t('yii|Strict'), E_STRICT => Yii::t('yii', 'Strict'),
E_NOTICE => Yii::t('yii|Notice'), E_NOTICE => Yii::t('yii', 'Notice'),
E_RECOVERABLE_ERROR => Yii::t('yii|Recoverable Error'), E_RECOVERABLE_ERROR => Yii::t('yii', 'Recoverable Error'),
E_DEPRECATED => Yii::t('yii|Deprecated'), E_DEPRECATED => Yii::t('yii', 'Deprecated'),
); );
return isset($names[$this->getCode()]) ? $names[$this->getCode()] : Yii::t('yii|Error'); return isset($names[$this->getCode()]) ? $names[$this->getCode()] : Yii::t('yii', 'Error');
} }
} }

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

@ -75,8 +75,11 @@ class ErrorHandler extends Component
\Yii::$app->runAction($this->errorAction); \Yii::$app->runAction($this->errorAction);
} elseif (\Yii::$app instanceof \yii\web\Application) { } elseif (\Yii::$app instanceof \yii\web\Application) {
if (!headers_sent()) { if (!headers_sent()) {
$errorCode = $exception instanceof HttpException ? $exception->statusCode : 500; if ($exception instanceof HttpException) {
header("HTTP/1.0 $errorCode " . get_class($exception)); header('HTTP/1.0 ' . $exception->statusCode . ' ' . $exception->getName());
} else {
header('HTTP/1.0 500 ' . get_class($exception));
}
} }
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') { if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') {
\Yii::$app->renderException($exception); \Yii::$app->renderException($exception);

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

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

@ -20,6 +20,6 @@ class Exception extends \Exception
*/ */
public function getName() public function getName()
{ {
return \Yii::t('yii|Exception'); return \Yii::t('yii', 'Exception');
} }
} }

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

@ -103,7 +103,7 @@ class HttpException extends UserException
if (isset($httpCodes[$this->statusCode])) { if (isset($httpCodes[$this->statusCode])) {
return $httpCodes[$this->statusCode]; return $httpCodes[$this->statusCode];
} else { } else {
return \Yii::t('yii|Error'); return \Yii::t('yii', 'Error');
} }
} }
} }

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

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

@ -20,7 +20,7 @@ class InvalidCallException extends Exception
*/ */
public function getName() public function getName()
{ {
return \Yii::t('yii|Invalid Call'); return \Yii::t('yii', 'Invalid Call');
} }
} }

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

@ -20,7 +20,7 @@ class InvalidConfigException extends Exception
*/ */
public function getName() public function getName()
{ {
return \Yii::t('yii|Invalid Configuration'); return \Yii::t('yii', 'Invalid Configuration');
} }
} }

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

@ -20,7 +20,7 @@ class InvalidParamException extends Exception
*/ */
public function getName() public function getName()
{ {
return \Yii::t('yii|Invalid Parameter'); return \Yii::t('yii', 'Invalid Parameter');
} }
} }

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

@ -20,7 +20,7 @@ class InvalidRequestException extends UserException
*/ */
public function getName() public function getName()
{ {
return \Yii::t('yii|Invalid Request'); return \Yii::t('yii', 'Invalid Request');
} }
} }

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

@ -20,7 +20,7 @@ class InvalidRouteException extends UserException
*/ */
public function getName() public function getName()
{ {
return \Yii::t('yii|Invalid Route'); return \Yii::t('yii', 'Invalid Route');
} }
} }

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

@ -7,6 +7,8 @@
namespace yii\base; namespace yii\base;
use ArrayObject;
use ArrayIterator;
use yii\helpers\StringHelper; use yii\helpers\StringHelper;
use yii\validators\RequiredValidator; use yii\validators\RequiredValidator;
use yii\validators\Validator; use yii\validators\Validator;
@ -30,7 +32,7 @@ use yii\validators\Validator;
* You may directly use Model to store model data, or extend it with customization. * You may directly use Model to store model data, or extend it with customization.
* You may also customize Model by attaching [[ModelBehavior|model behaviors]]. * You may also customize Model by attaching [[ModelBehavior|model behaviors]].
* *
* @property Vector $validators All the validators declared in the model. * @property ArrayObject $validators All the validators declared in the model.
* @property array $activeValidators The validators applicable to the current [[scenario]]. * @property array $activeValidators The validators applicable to the current [[scenario]].
* @property array $errors Errors for all attributes or the specified attribute. Empty array is returned if no error. * @property array $errors Errors for all attributes or the specified attribute. Empty array is returned if no error.
* @property array $attributes Attribute values (name => value). * @property array $attributes Attribute values (name => value).
@ -56,7 +58,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
*/ */
private $_errors; private $_errors;
/** /**
* @var Vector vector of validators * @var ArrayObject list of validators
*/ */
private $_validators; private $_validators;
/** /**
@ -300,15 +302,15 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
* This method differs from [[getActiveValidators()]] in that the latter * This method differs from [[getActiveValidators()]] in that the latter
* only returns the validators applicable to the current [[scenario]]. * only returns the validators applicable to the current [[scenario]].
* *
* Because this method returns a [[Vector]] object, you may * Because this method returns an ArrayObject object, you may
* manipulate it by inserting or removing validators (useful in model behaviors). * manipulate it by inserting or removing validators (useful in model behaviors).
* For example, * For example,
* *
* ~~~ * ~~~
* $model->validators->add($newValidator); * $model->validators[] = $newValidator;
* ~~~ * ~~~
* *
* @return Vector all the validators declared in the model. * @return ArrayObject all the validators declared in the model.
*/ */
public function getValidators() public function getValidators()
{ {
@ -340,18 +342,18 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
/** /**
* Creates validator objects based on the validation rules specified in [[rules()]]. * Creates validator objects based on the validation rules specified in [[rules()]].
* Unlike [[getValidators()]], each time this method is called, a new list of validators will be returned. * Unlike [[getValidators()]], each time this method is called, a new list of validators will be returned.
* @return Vector validators * @return ArrayObject validators
* @throws InvalidConfigException if any validation rule configuration is invalid * @throws InvalidConfigException if any validation rule configuration is invalid
*/ */
public function createValidators() public function createValidators()
{ {
$validators = new Vector; $validators = new ArrayObject;
foreach ($this->rules() as $rule) { foreach ($this->rules() as $rule) {
if ($rule instanceof Validator) { if ($rule instanceof Validator) {
$validators->add($rule); $validators->append($rule);
} elseif (is_array($rule) && isset($rule[0], $rule[1])) { // attributes, validator type } elseif (is_array($rule) && isset($rule[0], $rule[1])) { // attributes, validator type
$validator = Validator::createValidator($rule[1], $this, $rule[0], array_slice($rule, 2)); $validator = Validator::createValidator($rule[1], $this, $rule[0], array_slice($rule, 2));
$validators->add($validator); $validators->append($validator);
} else { } else {
throw new InvalidConfigException('Invalid validation rule: a rule must specify both attribute names and validator type.'); throw new InvalidConfigException('Invalid validation rule: a rule must specify both attribute names and validator type.');
} }
@ -590,18 +592,22 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
/** /**
* Returns the attribute names that are safe to be massively assigned in the current scenario. * Returns the attribute names that are safe to be massively assigned in the current scenario.
* @return array safe attribute names * @return string[] safe attribute names
*/ */
public function safeAttributes() public function safeAttributes()
{ {
$scenario = $this->getScenario(); $scenario = $this->getScenario();
$scenarios = $this->scenarios(); $scenarios = $this->scenarios();
if (!isset($scenarios[$scenario])) {
return array();
}
$attributes = array(); $attributes = array();
if (isset($scenarios[$scenario])) { if (isset($scenarios[$scenario]['attributes']) && is_array($scenarios[$scenario]['attributes'])) {
foreach ($scenarios[$scenario] as $attribute) { $scenarios[$scenario] = $scenarios[$scenario]['attributes'];
if ($attribute[0] !== '!') { }
$attributes[] = $attribute; foreach ($scenarios[$scenario] as $attribute) {
} if ($attribute[0] !== '!') {
$attributes[] = $attribute;
} }
} }
return $attributes; return $attributes;
@ -609,34 +615,37 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
/** /**
* Returns the attribute names that are subject to validation in the current scenario. * Returns the attribute names that are subject to validation in the current scenario.
* @return array safe attribute names * @return string[] safe attribute names
*/ */
public function activeAttributes() public function activeAttributes()
{ {
$scenario = $this->getScenario(); $scenario = $this->getScenario();
$scenarios = $this->scenarios(); $scenarios = $this->scenarios();
if (isset($scenarios[$scenario])) { if (!isset($scenarios[$scenario])) {
$attributes = $scenarios[$this->getScenario()];
foreach ($attributes as $i => $attribute) {
if ($attribute[0] === '!') {
$attributes[$i] = substr($attribute, 1);
}
}
return $attributes;
} else {
return array(); return array();
} }
if (isset($scenarios[$scenario]['attributes']) && is_array($scenarios[$scenario]['attributes'])) {
$attributes = $scenarios[$scenario]['attributes'];
} else {
$attributes = $scenarios[$scenario];
}
foreach ($attributes as $i => $attribute) {
if ($attribute[0] === '!') {
$attributes[$i] = substr($attribute, 1);
}
}
return $attributes;
} }
/** /**
* Returns an iterator for traversing the attributes in the model. * Returns an iterator for traversing the attributes in the model.
* This method is required by the interface IteratorAggregate. * This method is required by the interface IteratorAggregate.
* @return DictionaryIterator an iterator for traversing the items in the list. * @return ArrayIterator an iterator for traversing the items in the list.
*/ */
public function getIterator() public function getIterator()
{ {
$attributes = $this->getAttributes(); $attributes = $this->getAttributes();
return new DictionaryIterator($attributes); return new ArrayIterator($attributes);
} }
/** /**

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

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

@ -8,7 +8,6 @@
namespace yii\base; namespace yii\base;
use Yii; use Yii;
use yii\helpers\StringHelper;
/** /**
* Module is the base class for module and application classes. * Module is the base class for module and application classes.
@ -449,7 +448,7 @@ abstract class Module extends Component
public function getComponent($id, $load = true) public function getComponent($id, $load = true)
{ {
if (isset($this->_components[$id])) { if (isset($this->_components[$id])) {
if ($this->_components[$id] instanceof Component) { if ($this->_components[$id] instanceof Object) {
return $this->_components[$id]; return $this->_components[$id];
} elseif ($load) { } elseif ($load) {
Yii::trace("Loading component: $id", __METHOD__); Yii::trace("Loading component: $id", __METHOD__);
@ -592,6 +591,7 @@ abstract class Module extends Component
if ($route === '') { if ($route === '') {
$route = $this->defaultRoute; $route = $this->defaultRoute;
} }
$route = trim($route, '/');
if (($pos = strpos($route, '/')) !== false) { if (($pos = strpos($route, '/')) !== false) {
$id = substr($route, 0, $pos); $id = substr($route, 0, $pos);
$route = substr($route, $pos + 1); $route = substr($route, $pos + 1);
@ -608,7 +608,7 @@ abstract class Module extends Component
if (isset($this->controllerMap[$id])) { if (isset($this->controllerMap[$id])) {
$controller = Yii::createObject($this->controllerMap[$id], $id, $this); $controller = Yii::createObject($this->controllerMap[$id], $id, $this);
} elseif (preg_match('/^[a-z0-9\\-_]+$/', $id)) { } elseif (preg_match('/^[a-z0-9\\-_]+$/', $id)) {
$className = StringHelper::id2camel($id) . 'Controller'; $className = str_replace(' ', '', ucwords(implode(' ', explode('-', $id)))) . 'Controller';
$classFile = $this->controllerPath . DIRECTORY_SEPARATOR . $className . '.php'; $classFile = $this->controllerPath . DIRECTORY_SEPARATOR . $className . '.php';
if (!is_file($classFile)) { if (!is_file($classFile)) {
return false; return false;

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

@ -20,7 +20,7 @@ class NotSupportedException extends Exception
*/ */
public function getName() public function getName()
{ {
return \Yii::t('yii|Not Supported'); return \Yii::t('yii', 'Not Supported');
} }
} }

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

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

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

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

@ -25,7 +25,22 @@ use yii\helpers\FileHelper;
* then the themed version for a view file `/www/views/site/index.php` will be * then the themed version for a view file `/www/views/site/index.php` will be
* `/www/themes/basic/site/index.php`. * `/www/themes/basic/site/index.php`.
* *
* @property string $baseUrl the base URL for this theme. This is mainly used by [[getUrl()]]. * To use a theme, you should configure the [[View::theme|theme]] property of the "view" application
* component like the following:
*
* ~~~
* 'view' => array(
* 'theme' => array(
* 'basePath' => '@wwwroot/themes/basic',
* 'baseUrl' => '@www/themes/basic',
* ),
* ),
* ~~~
*
* The above configuration specifies a theme located under the "themes/basic" directory of the Web folder
* that contains the entry script of the application. If your theme is designed to handle modules,
* you may configure the [[pathMap]] property like described above.
*
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0

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

@ -20,7 +20,7 @@ class UnknownClassException extends Exception
*/ */
public function getName() public function getName()
{ {
return \Yii::t('yii|Unknown Class'); return \Yii::t('yii', 'Unknown Class');
} }
} }

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

@ -20,7 +20,7 @@ class UnknownMethodException extends Exception
*/ */
public function getName() public function getName()
{ {
return \Yii::t('yii|Unknown Method'); return \Yii::t('yii', 'Unknown Method');
} }
} }

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

@ -20,7 +20,7 @@ class UnknownPropertyException extends Exception
*/ */
public function getName() public function getName()
{ {
return \Yii::t('yii|Unknown Property'); return \Yii::t('yii', 'Unknown Property');
} }
} }

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

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

@ -11,6 +11,9 @@ use Yii;
use yii\base\Application; use yii\base\Application;
use yii\helpers\FileHelper; use yii\helpers\FileHelper;
use yii\helpers\Html; use yii\helpers\Html;
use yii\widgets\Block;
use yii\widgets\ContentDecorator;
use yii\widgets\FragmentCache;
/** /**
* View represents a view object in the MVC pattern. * View represents a view object in the MVC pattern.
@ -55,6 +58,11 @@ class View extends Component
*/ */
const POS_END = 3; const POS_END = 3;
/** /**
* The location of registered JavaScript code block.
* This means the JavaScript code block will be enclosed within `jQuery(document).ready()`.
*/
const POS_READY = 4;
/**
* This is internally used as the placeholder for receiving the content registered for the head section. * This is internally used as the placeholder for receiving the content registered for the head section.
*/ */
const PL_HEAD = '<![CDATA[YII-BLOCK-HEAD]]>'; const PL_HEAD = '<![CDATA[YII-BLOCK-HEAD]]>';
@ -108,12 +116,6 @@ class View extends Component
*/ */
public $blocks; public $blocks;
/** /**
* @var Widget[] the widgets that are currently being rendered (not ended). This property
* is maintained by [[beginWidget()]] and [[endWidget()]] methods. Do not modify it directly.
* @internal
*/
public $widgetStack = array();
/**
* @var array a list of currently active fragment cache widgets. This property * @var array a list of currently active fragment cache widgets. This property
* is used internally to implement the content caching feature. Do not modify it directly. * is used internally to implement the content caching feature. Do not modify it directly.
* @internal * @internal
@ -174,6 +176,9 @@ class View extends Component
{ {
parent::init(); parent::init();
if (is_array($this->theme)) { if (is_array($this->theme)) {
if (!isset($this->theme['class'])) {
$this->theme['class'] = 'yii\base\Theme';
}
$this->theme = Yii::createObject($this->theme); $this->theme = Yii::createObject($this->theme);
} }
} }
@ -364,93 +369,19 @@ class View extends Component
} }
/** /**
* Creates a widget.
* This method will use [[Yii::createObject()]] to create the widget.
* @param string $class the widget class name or path alias
* @param array $properties the initial property values of the widget.
* @return Widget the newly created widget instance
*/
public function createWidget($class, $properties = array())
{
$properties['class'] = $class;
if (!isset($properties['view'])) {
$properties['view'] = $this;
}
return Yii::createObject($properties);
}
/**
* Creates and runs a widget.
* Compared with [[createWidget()]], this method does one more thing: it will
* run the widget after it is created.
* @param string $class the widget class name or path alias
* @param array $properties the initial property values of the widget.
* @param boolean $captureOutput whether to capture the output of the widget and return it as a string
* @return string|Widget if $captureOutput is true, the output of the widget will be returned;
* otherwise the widget object will be returned.
*/
public function widget($class, $properties = array(), $captureOutput = false)
{
if ($captureOutput) {
ob_start();
ob_implicit_flush(false);
$widget = $this->createWidget($class, $properties);
$widget->run();
return ob_get_clean();
} else {
$widget = $this->createWidget($class, $properties);
$widget->run();
return $widget;
}
}
/**
* Begins a widget.
* This method is similar to [[createWidget()]] except that it will expect a matching
* [[endWidget()]] call after this.
* @param string $class the widget class name or path alias
* @param array $properties the initial property values of the widget.
* @return Widget the widget instance
*/
public function beginWidget($class, $properties = array())
{
$widget = $this->createWidget($class, $properties);
$this->widgetStack[] = $widget;
return $widget;
}
/**
* Ends a widget.
* Note that the rendering result of the widget is directly echoed out.
* If you want to capture the rendering result of a widget, you may use
* [[createWidget()]] and [[Widget::run()]].
* @return Widget the widget instance
* @throws InvalidCallException if [[beginWidget()]] and [[endWidget()]] calls are not properly nested
*/
public function endWidget()
{
$widget = array_pop($this->widgetStack);
if ($widget instanceof Widget) {
$widget->run();
return $widget;
} else {
throw new InvalidCallException("Unmatched beginWidget() and endWidget() calls.");
}
}
/**
* Begins recording a block. * Begins recording a block.
* This method is a shortcut to beginning [[yii\widgets\Block]] * This method is a shortcut to beginning [[Block]]
* @param string $id the block ID. * @param string $id the block ID.
* @param boolean $renderInPlace whether to render the block content in place. * @param boolean $renderInPlace whether to render the block content in place.
* Defaults to false, meaning the captured block will not be displayed. * Defaults to false, meaning the captured block will not be displayed.
* @return \yii\widgets\Block the Block widget instance * @return Block the Block widget instance
*/ */
public function beginBlock($id, $renderInPlace = false) public function beginBlock($id, $renderInPlace = false)
{ {
return $this->beginWidget('yii\widgets\Block', array( return Block::begin(array(
'id' => $id, 'id' => $id,
'renderInPlace' => $renderInPlace, 'renderInPlace' => $renderInPlace,
'view' => $this,
)); ));
} }
@ -459,16 +390,16 @@ class View extends Component
*/ */
public function endBlock() public function endBlock()
{ {
$this->endWidget(); Block::end();
} }
/** /**
* Begins the rendering of content that is to be decorated by the specified view. * Begins the rendering of content that is to be decorated by the specified view.
* This method can be used to implement nested layout. For example, a layout can be embedded * This method can be used to implement nested layout. For example, a layout can be embedded
* in another layout file specified as '@app/view/layouts/base' like the following: * in another layout file specified as '@app/view/layouts/base.php' like the following:
* *
* ~~~ * ~~~
* <?php $this->beginContent('@app/view/layouts/base'); ?> * <?php $this->beginContent('@app/view/layouts/base.php'); ?>
* ...layout content here... * ...layout content here...
* <?php $this->endContent(); ?> * <?php $this->endContent(); ?>
* ~~~ * ~~~
@ -476,14 +407,15 @@ class View extends Component
* @param string $viewFile the view file that will be used to decorate the content enclosed by this widget. * @param string $viewFile the view file that will be used to decorate the content enclosed by this widget.
* This can be specified as either the view file path or path alias. * This can be specified as either the view file path or path alias.
* @param array $params the variables (name => value) to be extracted and made available in the decorative view. * @param array $params the variables (name => value) to be extracted and made available in the decorative view.
* @return \yii\widgets\ContentDecorator the ContentDecorator widget instance * @return ContentDecorator the ContentDecorator widget instance
* @see \yii\widgets\ContentDecorator * @see ContentDecorator
*/ */
public function beginContent($viewFile, $params = array()) public function beginContent($viewFile, $params = array())
{ {
return $this->beginWidget('yii\widgets\ContentDecorator', array( return ContentDecorator::begin(array(
'viewFile' => $viewFile, 'viewFile' => $viewFile,
'params' => $params, 'params' => $params,
'view' => $this,
)); ));
} }
@ -492,7 +424,7 @@ class View extends Component
*/ */
public function endContent() public function endContent()
{ {
$this->endWidget(); ContentDecorator::end();
} }
/** /**
@ -510,15 +442,16 @@ class View extends Component
* ~~~ * ~~~
* *
* @param string $id a unique ID identifying the fragment to be cached. * @param string $id a unique ID identifying the fragment to be cached.
* @param array $properties initial property values for [[\yii\widgets\FragmentCache]] * @param array $properties initial property values for [[FragmentCache]]
* @return boolean whether you should generate the content for caching. * @return boolean whether you should generate the content for caching.
* False if the cached version is available. * False if the cached version is available.
*/ */
public function beginCache($id, $properties = array()) public function beginCache($id, $properties = array())
{ {
$properties['id'] = $id; $properties['id'] = $id;
/** @var $cache \yii\widgets\FragmentCache */ $properties['view'] = $this;
$cache = $this->beginWidget('yii\widgets\FragmentCache', $properties); /** @var $cache FragmentCache */
$cache = FragmentCache::begin($properties);
if ($cache->getCachedContent() !== false) { if ($cache->getCachedContent() !== false) {
$this->endCache(); $this->endCache();
return false; return false;
@ -532,7 +465,7 @@ class View extends Component
*/ */
public function endCache() public function endCache()
{ {
$this->endWidget(); FragmentCache::end();
} }
@ -681,7 +614,7 @@ class View extends Component
*/ */
public function registerCss($css, $options = array(), $key = null) public function registerCss($css, $options = array(), $key = null)
{ {
$key = $key ?: $css; $key = $key ?: md5($css);
$this->css[$key] = Html::style($css, $options); $this->css[$key] = Html::style($css, $options);
} }
@ -702,24 +635,26 @@ class View extends Component
/** /**
* Registers a JS code block. * Registers a JS code block.
* @param string $js the JS code block to be registered * @param string $js the JS code block to be registered
* @param array $options the HTML attributes for the script tag. A special option * @param integer $position the position at which the JS script tag should be inserted
* named "position" is supported which specifies where the JS script tag should be inserted * in a page. The possible values are:
* in a page. The possible values of "position" are:
* *
* - [[POS_HEAD]]: in the head section * - [[POS_HEAD]]: in the head section
* - [[POS_BEGIN]]: at the beginning of the body section * - [[POS_BEGIN]]: at the beginning of the body section
* - [[POS_END]]: at the end of the body section * - [[POS_END]]: at the end of the body section
* - [[POS_READY]]: enclosed within jQuery(document).ready(). This is the default value.
* Note that by using this position, the method will automatically register the jquery js file.
* *
* @param string $key the key that identifies the JS code block. If null, it will use * @param string $key the key that identifies the JS code block. If null, it will use
* $js as the key. If two JS code blocks are registered with the same key, the latter * $js as the key. If two JS code blocks are registered with the same key, the latter
* will overwrite the former. * will overwrite the former.
*/ */
public function registerJs($js, $options = array(), $key = null) public function registerJs($js, $position = self::POS_READY, $key = null)
{ {
$position = isset($options['position']) ? $options['position'] : self::POS_END; $key = $key ?: md5($js);
unset($options['position']); $this->js[$position][$key] = $js;
$key = $key ?: $js; if ($position === self::POS_READY) {
$this->js[$position][$key] = Html::script($js, $options); $this->registerAssetBundle('yii/jquery');
}
} }
/** /**
@ -731,7 +666,7 @@ class View extends Component
* *
* - [[POS_HEAD]]: in the head section * - [[POS_HEAD]]: in the head section
* - [[POS_BEGIN]]: at the beginning of the body section * - [[POS_BEGIN]]: at the beginning of the body section
* - [[POS_END]]: at the end of the body section * - [[POS_END]]: at the end of the body section. This is the default value.
* *
* @param string $key the key that identifies the JS script file. If null, it will use * @param string $key the key that identifies the JS script file. If null, it will use
* $url as the key. If two JS files are registered with the same key, the latter * $url as the key. If two JS files are registered with the same key, the latter
@ -769,9 +704,9 @@ class View extends Component
$lines[] = implode("\n", $this->jsFiles[self::POS_HEAD]); $lines[] = implode("\n", $this->jsFiles[self::POS_HEAD]);
} }
if (!empty($this->js[self::POS_HEAD])) { if (!empty($this->js[self::POS_HEAD])) {
$lines[] = implode("\n", $this->js[self::POS_HEAD]); $lines[] = Html::script(implode("\n", $this->js[self::POS_HEAD]), array('type' => 'text/javascript'));
} }
return implode("\n", $lines); return empty($lines) ? '' : implode("\n", $lines) . "\n";
} }
/** /**
@ -786,9 +721,9 @@ class View extends Component
$lines[] = implode("\n", $this->jsFiles[self::POS_BEGIN]); $lines[] = implode("\n", $this->jsFiles[self::POS_BEGIN]);
} }
if (!empty($this->js[self::POS_BEGIN])) { if (!empty($this->js[self::POS_BEGIN])) {
$lines[] = implode("\n", $this->js[self::POS_BEGIN]); $lines[] = Html::script(implode("\n", $this->js[self::POS_BEGIN]), array('type' => 'text/javascript'));
} }
return implode("\n", $lines); return empty($lines) ? '' : implode("\n", $lines) . "\n";
} }
/** /**
@ -803,8 +738,12 @@ class View extends Component
$lines[] = implode("\n", $this->jsFiles[self::POS_END]); $lines[] = implode("\n", $this->jsFiles[self::POS_END]);
} }
if (!empty($this->js[self::POS_END])) { if (!empty($this->js[self::POS_END])) {
$lines[] = implode("\n", $this->js[self::POS_END]); $lines[] = Html::script(implode("\n", $this->js[self::POS_END]), array('type' => 'text/javascript'));
}
if (!empty($this->js[self::POS_READY])) {
$js = "jQuery(document).ready(function(){\n" . implode("\n", $this->js[self::POS_READY]) . "\n});";
$lines[] = Html::script($js, array('type' => 'text/javascript'));
} }
return implode("\n", $lines); return empty($lines) ? '' : implode("\n", $lines) . "\n";
} }
} }

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

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

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

@ -8,7 +8,6 @@
namespace yii\base; namespace yii\base;
use Yii; use Yii;
use yii\helpers\FileHelper;
/** /**
* Widget is the base class for widgets. * Widget is the base class for widgets.
@ -19,20 +18,74 @@ use yii\helpers\FileHelper;
class Widget extends Component class Widget extends Component
{ {
/** /**
* @var View the view object that is used to create this widget. * @var integer a counter used to generate [[id]] for widgets.
* This property is automatically set by [[View::createWidget()]]. * @internal
* This property is required by [[render()]] and [[renderFile()]].
*/ */
public $view; public static $_counter = 0;
/** /**
* @var string id of the widget. * @var Widget[] the widgets that are currently being rendered (not ended). This property
* is maintained by [[begin()]] and [[end()]] methods.
* @internal
*/ */
private $_id; public static $_stack = array();
/**
* Begins a widget.
* This method creates an instance of the calling class. It will apply the configuration
* to the created instance. A matching [[end()]] call should be called later.
* @param array $config name-value pairs that will be used to initialize the object properties
* @return Widget the newly created widget instance
*/
public static function begin($config = array())
{
$config['class'] = get_called_class();
/** @var Widget $widget */
$widget = Yii::createObject($config);
self::$_stack[] = $widget;
return $widget;
}
/**
* Ends a widget.
* Note that the rendering result of the widget is directly echoed out.
* @return Widget the widget instance that is ended.
* @throws InvalidCallException if [[begin()]] and [[end()]] calls are not properly nested
*/
public static function end()
{
if (!empty(self::$_stack)) {
$widget = array_pop(self::$_stack);
if (get_class($widget) === get_called_class()) {
$widget->run();
return $widget;
} else {
throw new InvalidCallException("Expecting end() of " . get_class($widget) . ", found " . get_called_class());
}
} else {
throw new InvalidCallException("Unexpected " . get_called_class() . '::end() call. A matching begin() is not found.');
}
}
/** /**
* @var integer a counter used to generate IDs for widgets. * Creates a widget instance and runs it.
* The widget rendering result is returned by this method.
* @param array $config name-value pairs that will be used to initialize the object properties
* @return string the rendering result of the widget.
*/ */
private static $_counter = 0; public static function widget($config = array())
{
ob_start();
ob_implicit_flush(false);
/** @var Widget $widget */
$config['class'] = get_called_class();
$widget = Yii::createObject($config);
$widget->run();
return ob_get_clean();
}
private $_id;
/** /**
* Returns the ID of the widget. * Returns the ID of the widget.
* @param boolean $autoGenerate whether to generate an ID if it is not set previously * @param boolean $autoGenerate whether to generate an ID if it is not set previously
@ -55,6 +108,32 @@ class Widget extends Component
$this->_id = $value; $this->_id = $value;
} }
private $_view;
/**
* Returns the view object that can be used to render views or view files.
* The [[render()]] and [[renderFile()]] methods will use
* this view object to implement the actual view rendering.
* If not set, it will default to the "view" application component.
* @return View the view object that can be used to render views or view files.
*/
public function getView()
{
if ($this->_view === null) {
$this->_view = Yii::$app->getView();
}
return $this->_view;
}
/**
* Sets the view object to be used by this widget.
* @param View $view the view object that can be used to render views or view files.
*/
public function setView($view)
{
$this->_view = $view;
}
/** /**
* Executes the widget. * Executes the widget.
*/ */
@ -84,7 +163,7 @@ class Widget extends Component
public function render($view, $params = array()) public function render($view, $params = array())
{ {
$viewFile = $this->findViewFile($view); $viewFile = $this->findViewFile($view);
return $this->view->renderFile($viewFile, $params, $this); return $this->getView()->renderFile($viewFile, $params, $this);
} }
/** /**
@ -96,7 +175,7 @@ class Widget extends Component
*/ */
public function renderFile($file, $params = array()) public function renderFile($file, $params = array())
{ {
return $this->view->renderFile($file, $params, $this); return $this->getView()->renderFile($file, $params, $this);
} }
/** /**

106
framework/yii/behaviors/AutoTimestamp.php

@ -0,0 +1,106 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\behaviors;
use yii\base\Behavior;
use yii\db\Expression;
use yii\db\ActiveRecord;
/**
* AutoTimestamp will automatically fill the attributes about creation time and updating time.
*
* AutoTimestamp fills the attributes when the associated AR model is being inserted or updated.
* You may specify an AR to use this behavior like the following:
*
* ~~~
* public function behaviors()
* {
* return array(
* 'timestamp' => array(
* 'class' => 'yii\behaviors\AutoTimestamp',
* ),
* );
* }
* ~~~
*
* By default, AutoTimestamp will fill the `create_time` attribute with the current timestamp
* when the associated AR object is being inserted; it will fill the `update_time` attribute
* with the timestamp when the AR object is being updated.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class AutoTimestamp extends Behavior
{
/**
* @var array list of attributes that are to be automatically filled with timestamps.
* The array keys are the ActiveRecord events upon which the attributes are to be filled with timestamps,
* and the array values are the corresponding attribute to be updated. You can use a string to represent
* a single attribute, or an array to represent a list of attributes.
* The default setting is to update the `create_time` attribute upon AR insertion,
* and update the `update_time` attribute upon AR updating.
*/
public $attributes = array(
ActiveRecord::EVENT_BEFORE_INSERT => 'create_time',
ActiveRecord::EVENT_BEFORE_UPDATE => 'update_time',
);
/**
* @var \Closure|Expression The expression that will be used for generating the timestamp.
* This can be either an anonymous function that returns the timestamp value,
* or an [[Expression]] object representing a DB expression (e.g. `new Expression('NOW()')`).
* If not set, it will use the value of `time()` to fill the attributes.
*/
public $timestamp;
/**
* Declares event handlers for the [[owner]]'s events.
* @return array events (array keys) and the corresponding event handler methods (array values).
*/
public function events()
{
$events = array();
$behavior = $this;
foreach ($this->attributes as $event => $attributes) {
if (!is_array($attributes)) {
$attributes = array($attributes);
}
$events[$event] = function () use ($behavior, $attributes) {
$behavior->updateTimestamp($attributes);
};
}
return $events;
}
/**
* Updates the attributes with the current timestamp.
* @param array $attributes list of attributes to be updated.
*/
public function updateTimestamp($attributes)
{
foreach ($attributes as $attribute) {
$this->owner->$attribute = $this->evaluateTimestamp($attribute);
}
}
/**
* Gets the appropriate timestamp for the specified attribute.
* @param string $attribute attribute name
* @return mixed the timestamp value
*/
protected function evaluateTimestamp($attribute)
{
if ($this->timestamp instanceof Expression) {
return $this->timestamp;
} elseif ($this->timestamp !== null) {
return call_user_func($this->timestamp);
} else {
return time();
}
}
}

154
framework/yii/bootstrap/Alert.php

@ -0,0 +1,154 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\bootstrap;
use Yii;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
/**
* Alert renders an alert bootstrap component.
*
* For example,
*
* ```php
* echo Alert::widget(array(
* 'body' => 'Say hello...',
* 'closeButton' => array(
* 'label' => '&times;',
* 'tag' => 'a',
* ),
* ));
* ```
*
* The following example will show the content enclosed between the [[begin()]]
* and [[end()]] calls within the alert box:
*
* ```php
* Alert::begin(array(
* 'closeButton' => array(
* 'label' => '&times;',
* ),
* ));
*
* echo 'Say hello...';
*
* Alert::end();
* ```
*
* @see http://twitter.github.io/bootstrap/javascript.html#alerts
* @author Antonio Ramirez <amigo.cobos@gmail.com>
* @since 2.0
*/
class Alert extends Widget
{
/**
* @var string the body content in the alert component. Note that anything between
* the [[begin()]] and [[end()]] calls of the Alert widget will also be treated
* as the body content, and will be rendered before this.
*/
public $body;
/**
* @var array the options for rendering the close button tag.
* The close button is displayed in the header of the modal window. Clicking
* on the button will hide the modal window. If this is null, no close button will be rendered.
*
* The following special options are supported:
*
* - tag: string, the tag name of the button. Defaults to 'button'.
* - label: string, the label of the button. Defaults to '&times;'.
*
* The rest of the options will be rendered as the HTML attributes of the button tag.
* Please refer to the [Alert plugin help](http://twitter.github.com/bootstrap/javascript.html#alerts)
* for the supported HTML attributes.
*/
public $closeButton = array();
/**
* Initializes the widget.
*/
public function init()
{
parent::init();
$this->getView()->registerAssetBundle('yii/bootstrap/alert');
$this->initOptions();
echo Html::beginTag('div', $this->options) . "\n";
echo $this->renderBodyBegin() . "\n";
}
/**
* Renders the widget.
*/
public function run()
{
echo "\n" . $this->renderBodyEnd();
echo "\n" . Html::endTag('div');
$this->registerPlugin('alert');
}
/**
* Renders the close button if any before rendering the content.
* @return string the rendering result
*/
protected function renderBodyBegin()
{
return $this->renderCloseButton();
}
/**
* Renders the alert body (if any).
* @return string the rendering result
*/
protected function renderBodyEnd()
{
return $this->body . "\n";
}
/**
* Renders the close button.
* @return string the rendering result
*/
protected function renderCloseButton()
{
if ($this->closeButton !== null) {
$tag = ArrayHelper::remove($this->closeButton, 'tag', 'button');
$label = ArrayHelper::remove($this->closeButton, 'label', '&times;');
if ($tag === 'button' && !isset($this->closeButton['type'])) {
$this->closeButton['type'] = 'button';
}
return Html::tag($tag, $label, $this->closeButton);
} else {
return null;
}
}
/**
* Initializes the widget options.
* This method sets the default values for various options.
*/
protected function initOptions()
{
$this->options = array_merge(array(
'class' => 'fade in',
), $this->options);
$this->addCssClass($this->options, 'alert');
if ($this->closeButton !== null) {
$this->closeButton = array_merge(array(
'data-dismiss' => 'alert',
'aria-hidden' => 'true',
'class' => 'close',
), $this->closeButton);
}
}
}

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

Loading…
Cancel
Save