Browse Source

Merge branch 'master' of github.com:yiisoft/yii2 into mongo

tags/2.0.0-beta
Klimov Paul 11 years ago
parent
commit
ac5e1748b7
  1. 4
      .travis.yml
  2. 38
      README.md
  3. 10
      apps/advanced/composer.json
  4. 4
      apps/advanced/frontend/controllers/SiteController.php
  5. 7
      apps/advanced/requirements.php
  6. 10
      apps/basic/composer.json
  7. 2
      apps/benchmark/composer.json
  8. 6
      build/build.xml
  9. 19
      composer.json
  10. 10
      docs/guide/apps-advanced.md
  11. 10
      docs/guide/apps-basic.md
  12. 155
      docs/guide/assets.md
  13. 6
      docs/guide/authorization.md
  14. 39
      docs/guide/behaviors.md
  15. 16
      docs/guide/configuration.md
  16. 85
      docs/guide/console.md
  17. 7
      docs/guide/controller.md
  18. 5
      docs/guide/database-basics.md
  19. 18
      docs/guide/debugger.md
  20. 12
      docs/guide/gii.md
  21. 6
      docs/guide/i18n.md
  22. 2
      docs/guide/index.md
  23. 47
      docs/guide/performance.md
  24. 5
      docs/guide/upgrade-from-v1.md
  25. 71
      docs/guide/url.md
  26. 7
      docs/guide/view.md
  27. 8
      extensions/composer/Installer.php
  28. 2
      extensions/composer/Plugin.php
  29. 4
      extensions/debug/Module.php
  30. 4
      extensions/debug/controllers/DefaultController.php
  31. 6
      extensions/elasticsearch/ActiveQuery.php
  32. 57
      extensions/elasticsearch/ActiveRecord.php
  33. 5
      extensions/elasticsearch/Connection.php
  34. 168
      extensions/elasticsearch/DebugPanel.php
  35. 54
      extensions/elasticsearch/QueryBuilder.php
  36. 26
      extensions/elasticsearch/README.md
  37. 4
      extensions/gii/Generator.php
  38. 8
      extensions/gii/GiiAsset.php
  39. 10
      extensions/gii/Module.php
  40. 14
      extensions/gii/controllers/DefaultController.php
  41. 20
      extensions/gii/generators/controller/Generator.php
  42. 92
      extensions/gii/generators/crud/Generator.php
  43. 11
      extensions/gii/generators/crud/templates/controller.php
  44. 2
      extensions/gii/generators/crud/templates/search.php
  45. 2
      extensions/gii/generators/crud/templates/views/_form.php
  46. 2
      extensions/gii/generators/crud/templates/views/_search.php
  47. 22
      extensions/gii/generators/crud/templates/views/index.php
  48. 12
      extensions/gii/generators/crud/templates/views/view.php
  49. 18
      extensions/gii/generators/form/Generator.php
  50. 18
      extensions/gii/generators/model/Generator.php
  51. 6
      extensions/gii/generators/model/templates/model.php
  52. 16
      extensions/gii/generators/module/Generator.php
  53. 4
      extensions/redis/ActiveQuery.php
  54. 69
      extensions/redis/ActiveRecord.php
  55. 14
      extensions/redis/Cache.php
  56. 16
      extensions/redis/LuaScriptBuilder.php
  57. 4
      extensions/sphinx/ActiveQuery.php
  58. 34
      extensions/sphinx/Command.php
  59. 7
      extensions/sphinx/Connection.php
  60. 30
      extensions/sphinx/README.md
  61. 4
      extensions/sphinx/composer.json
  62. 2
      extensions/swiftmailer/Mailer.php
  63. 42
      extensions/swiftmailer/Message.php
  64. 6
      framework/CHANGELOG.md
  65. 27
      framework/README.md
  66. 17
      framework/composer.json
  67. 4
      framework/yii/assets/yii.js
  68. 9
      framework/yii/base/Application.php
  69. 12
      framework/yii/base/Controller.php
  70. 11
      framework/yii/base/View.php
  71. 5
      framework/yii/base/Widget.php
  72. 2
      framework/yii/caching/WinCache.php
  73. 7
      framework/yii/classes.php
  74. 10
      framework/yii/console/controllers/MessageController.php
  75. 14
      framework/yii/data/ActiveDataProvider.php
  76. 6
      framework/yii/data/ArrayDataProvider.php
  77. 160
      framework/yii/data/SqlDataProvider.php
  78. 1051
      framework/yii/db/ActiveRecord.php
  79. 279
      framework/yii/db/ActiveRecordInterface.php
  80. 4
      framework/yii/db/ActiveRelationTrait.php
  81. 1229
      framework/yii/db/BaseActiveRecord.php
  82. 2
      framework/yii/db/Migration.php
  83. 4
      framework/yii/db/Query.php
  84. 2
      framework/yii/db/cubrid/QueryBuilder.php
  85. 2
      framework/yii/db/mysql/QueryBuilder.php
  86. 2
      framework/yii/db/sqlite/QueryBuilder.php
  87. 34
      framework/yii/grid/ActionColumn.php
  88. 11
      framework/yii/grid/CheckboxColumn.php
  89. 16
      framework/yii/grid/Column.php
  90. 7
      framework/yii/grid/DataColumn.php
  91. 6
      framework/yii/grid/GridView.php
  92. 7
      framework/yii/grid/SerialColumn.php
  93. 8
      framework/yii/helpers/BaseConsole.php
  94. 5
      framework/yii/helpers/BaseFileHelper.php
  95. 18
      framework/yii/helpers/BaseHtml.php
  96. 5
      framework/yii/log/EmailTarget.php
  97. 4
      framework/yii/mail/BaseMessage.php
  98. 11
      framework/yii/rbac/PhpManager.php
  99. 3
      framework/yii/test/DbFixtureManager.php
  100. 2
      framework/yii/validators/SafeValidator.php
  101. Some files were not shown because too many files have changed in this diff Show More

4
.travis.yml

@ -21,8 +21,8 @@ before_script:
- tests/unit/data/travis/cubrid-setup.sh
- tests/unit/data/travis/sphinx-setup.sh
#script:
# - phpunit --coverage-clover tests/unit/runtime/coveralls/clover.xml --verbose --exclude-group mssql,oci,wincache,xcache,zenddata,vendor
script:
- phpunit --coverage-text --coverage-clover tests/unit/runtime/coveralls/clover.xml --verbose --exclude-group mssql,oci,wincache,xcache,zenddata,vendor
#after_script:
# - php vendor/bin/coveralls

38
README.md

@ -1,13 +1,22 @@
Yii 2.0 Public Preview
======================
Yii PHP Framework Version 2
===========================
Thank you for choosing Yii - a high-performance component-based PHP framework.
Thank you for choosing Yii 2 - a modern PHP framework designed for professional Web development.
If you are looking for a production-ready PHP framework, please use
[Yii v1.1](https://github.com/yiisoft/yii).
Yii 2 is a complete rewrite of its previous version Yii 1.1 which is one of the most popular PHP frameworks.
Yii 2 inherits the main spirit behind Yii for being simple, fast and highly extensible.
Yii 2 requires PHP 5.4 and embraces best practices and protocols found in modern Web application development.
**Yii 2 is not ready for production use yet.** We may make significant changes without prior notices.
We expect to make the first stable release of Yii 2 in early 2014.
If you mainly want to learn Yii with no real project development requirement, we highly recommend
you start with Yii 2 as it will be our main focus for the next few years.
If you have a real project with tight schedule, you should stick to [Yii 1.1](https://github.com/yiisoft/yii)
which is the latest stable release of 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.**
[![Latest Stable Version](https://poser.pugx.org/yiisoft/yii2/v/stable.png)](https://packagist.org/packages/yiisoft/yii2)
[![Total Downloads](https://poser.pugx.org/yiisoft/yii2/downloads.png)](https://packagist.org/packages/yiisoft/yii2)
@ -18,15 +27,14 @@ without prior notices. **Yii 2.0 is not ready for production use yet.**
DIRECTORY STRUCTURE
-------------------
apps/ ready-to-use Web apps built on Yii 2
advanced/ advanced app template with complex features
basic/ a simple app supporting user login and contact page
benchmark/ app demonstrating the minimal overhead introduced by the framework
apps/ ready-to-use application templates
advanced/ a template suitable for building sophisticated Web applications
basic/ a template suitable for building simple Web applications
benchmark/ an application demonstrating the performance of Yii
build/ internally used build tools
docs/ documentation
extensions/ extensions
framework/ framework files
yii/ framework source files
framework/ core framework code
tests/ tests of the core framework code
@ -39,11 +47,11 @@ The minimum requirement by Yii is that your Web server supports PHP 5.4.
DOCUMENTATION
-------------
A draft of the [Definitive Guide](docs/guide/index.md) is available.
For 1.1 users, you may refer to [Upgrading from Yii 1.1](docs/guide/upgrade-from-v1.md)
to have a general idea of what has changed in 2.0.
[Definitive Guide draft](docs/guide/index.md) is available. It's not complete yet but main parts are already OK.
HOW TO PARTICIPATE
------------------

10
apps/advanced/composer.json

@ -15,11 +15,11 @@
"minimum-stability": "dev",
"require": {
"php": ">=5.4.0",
"yiisoft/yii2": "dev-master",
"yiisoft/yii2-swiftmailer": "dev-master",
"yiisoft/yii2-bootstrap": "dev-master",
"yiisoft/yii2-debug": "dev-master",
"yiisoft/yii2-gii": "dev-master"
"yiisoft/yii2": "*",
"yiisoft/yii2-swiftmailer": "*",
"yiisoft/yii2-bootstrap": "*",
"yiisoft/yii2-debug": "*",
"yiisoft/yii2-gii": "*"
},
"scripts": {
"post-create-project-cmd": [

4
apps/advanced/frontend/controllers/SiteController.php

@ -7,7 +7,7 @@ use yii\web\Controller;
use common\models\LoginForm;
use frontend\models\ContactForm;
use common\models\User;
use yii\web\HttpException;
use yii\web\BadRequestHttpException;
use yii\helpers\Security;
class SiteController extends Controller
@ -132,7 +132,7 @@ class SiteController extends Controller
]);
if (!$model) {
throw new HttpException(400, 'Wrong password reset token.');
throw new BadRequestHttpException('Wrong password reset token.');
}
$model->scenario = 'resetPassword';

7
apps/advanced/requirements.php

@ -48,6 +48,13 @@ $requirements = [
'by' => 'All <a href="http://www.yiiframework.com/doc/api/#system.db">DB-related classes</a>',
'memo' => 'Required for MySQL database.',
],
[
'name' => 'PDO PostgreSQL extension',
'mandatory' => false,
'condition' => extension_loaded('pdo_pgsql'),
'by' => 'All <a href="http://www.yiiframework.com/doc/api/#system.db">DB-related classes</a>',
'memo' => 'Required for PostgreSQL database.',
],
// Cache :
[
'name' => 'Memcache extension',

10
apps/basic/composer.json

@ -15,11 +15,11 @@
"minimum-stability": "dev",
"require": {
"php": ">=5.4.0",
"yiisoft/yii2": "dev-master",
"yiisoft/yii2-swiftmailer": "dev-master",
"yiisoft/yii2-bootstrap": "dev-master",
"yiisoft/yii2-debug": "dev-master",
"yiisoft/yii2-gii": "dev-master"
"yiisoft/yii2": "*",
"yiisoft/yii2-swiftmailer": "*",
"yiisoft/yii2-bootstrap": "*",
"yiisoft/yii2-debug": "*",
"yiisoft/yii2-gii": "*"
},
"scripts": {
"post-create-project-cmd": [

2
apps/benchmark/composer.json

@ -18,6 +18,6 @@
"minimum-stability": "dev",
"require": {
"php": ">=5.4.0",
"yiisoft/yii2": "dev-master"
"yiisoft/yii2": "*"
}
}

6
build/build.xml

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Phing build file for Yii.
* Phing build file for Yii 2.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2009 Yii Software LLC
* @copyright 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
-->
@ -21,7 +21,7 @@
<!-- these are required external commands -->
<property name="php" value="php" /> <!-- PHP parser -->
<property name="hhc" value="hhc" /> <!-- compile phpdoc into CHM -->
<property name="composer" value="composer" /> <!-- composer -->
<property name="pdflatex" value="pdflatex" /> <!-- generates PDF from LaTex -->
<property name="pkgname" value="${phing.project.name}-${yii.version}.${yii.revision}"/>

19
composer.json

@ -1,6 +1,6 @@
{
"name": "yiisoft/yii2-dev",
"description": "Yii2 Web Programming Framework - Development Package",
"description": "Yii PHP Framework Version 2 - Development Package",
"keywords": ["yii", "framework"],
"homepage": "http://www.yiiframework.com/",
"type": "yii2-extension",
@ -39,21 +39,6 @@
"name": "Paul Klimov",
"email": "klimov.paul@gmail.com",
"role": "Core framework development"
},
{
"name": "Wei Zhuo",
"email": "weizhuo@gmail.com",
"role": "Project site maintenance and development"
},
{
"name": "Sebastián Thierer",
"email": "sebas@artfos.com",
"role": "Component development"
},
{
"name": "Jeffrey Winesett",
"email": "jefftulsa@gmail.com",
"role": "Documentation and marketing"
}
],
"support": {
@ -67,6 +52,7 @@
"replace": {
"yiisoft/yii2-bootstrap": "self.version",
"yiisoft/yii2-debug": "self.version",
"yiisoft/yii2-elasticsearch": "self.version",
"yiisoft/yii2-gii": "self.version",
"yiisoft/yii2-jui": "self.version",
"yiisoft/yii2-redis": "self.version",
@ -94,6 +80,7 @@
"psr-0": {
"yii\\bootstrap\\": "extensions/bootstrap/",
"yii\\debug\\": "extensions/debug/",
"yii\\elasticsearch\\": "extensions/elasticsearch/",
"yii\\gii\\": "extensions/gii/",
"yii\\jui\\": "extensions/jui/",
"yii\\redis\\": "extensions/redis/",

10
docs/guide/apps-advanced.md

@ -139,11 +139,11 @@ directory:
"minimum-stability": "dev",
"require": {
"php": ">=5.4.0",
"yiisoft/yii2": "dev-master",
"yiisoft/yii2-swiftmailer": "dev-master",
"yiisoft/yii2-bootstrap": "dev-master",
"yiisoft/yii2-debug": "dev-master",
"yiisoft/yii2-gii": "dev-master"
"yiisoft/yii2": "*",
"yiisoft/yii2-swiftmailer": "*",
"yiisoft/yii2-bootstrap": "*",
"yiisoft/yii2-debug": "*",
"yiisoft/yii2-gii": "*"
},
"scripts": {
"post-create-project-cmd": [

10
docs/guide/apps-basic.md

@ -130,11 +130,11 @@ directory:
"minimum-stability": "dev",
"require": {
"php": ">=5.4.0",
"yiisoft/yii2": "dev-master",
"yiisoft/yii2-swiftmailer": "dev-master",
"yiisoft/yii2-bootstrap": "dev-master",
"yiisoft/yii2-debug": "dev-master",
"yiisoft/yii2-gii": "dev-master"
"yiisoft/yii2": "*",
"yiisoft/yii2-swiftmailer": "*",
"yiisoft/yii2-bootstrap": "*",
"yiisoft/yii2-debug": "*",
"yiisoft/yii2-gii": "*"
},
"scripts": {
"post-create-project-cmd": [

155
docs/guide/assets.md

@ -114,4 +114,157 @@ return [
```
There are two main benefits in enabling it. First it is faster since no copying is required and second is that assets
will always be up to date with source files.
will always be up to date with source files.
Compressing and combining assets
--------------------------------
To improve application performance you can compress and then combine several CSS or JS files into lesser number of files
therefore reducing number of HTTP requests and overall download size needed to load a web page. Yii provides a console
command that allows you to do both.
### Preparing configuration
In order to use `asset` command you should prepare a configuration first. A template for it can be generated using
```
yii asset/template /path/to/myapp/config.php
```
The template itself looks like the following:
```php
<?php
/**
* Configuration file for the "yii asset" console command.
* Note that in the console environment, some path aliases like '@webroot' and '@web' may not exist.
* Please define these missing path aliases.
*/
return [
// The list of asset bundles to compress:
'bundles' => [
// 'yii\web\YiiAsset',
// 'yii\web\JqueryAsset',
],
// Asset bundle for compression output:
'targets' => [
'app\config\AllAsset' => [
'basePath' => 'path/to/web',
'baseUrl' => '',
'js' => 'js/all-{ts}.js',
'css' => 'css/all-{ts}.css',
],
],
// Asset manager configuration:
'assetManager' => [
'basePath' => __DIR__,
'baseUrl' => '',
],
];
```
In the above keys are `properties` of `AssetController`. `bundles` list contains bundles that should be compressed. These are typically what's used by application.
`targets` contains a list of bundles that define how resulting files will be written. In our case we're writing
everything to `path/to/web` that can be accessed like `http://example.com/` i.e. it is website root directory.
> Note: in the console environment some path aliases like '@webroot' and '@web' may not exist,
so corresponding paths inside the configuration should be specified directly.
JavaScript files are combined, compressed and written to `js/all-{ts}.js` where {ts} is replaced with current UNIX
timestamp.
### Providing compression tools
The command relies on external compression tools that are not bundled with Yii so you need to provide CSS and JS
compressors which are correspondingly specified via `cssCompressor` and `jsCompression` properties. If compressor is
specified as a string it is treated as a shell command template which should contain two placeholders: `{from}` that
is replaced by source file name and `{to}` that is replaced by output file name. Another way to specify compressor is
to use any valid PHP callback.
By default for JavaScript compression Yii tries to use
[Google Closure compiler](https://developers.google.com/closure/compiler/) that is expected to be in a file named
`compiler.jar`.
For CSS compression Yii assumes that [YUI Compressor](https://github.com/yui/yuicompressor/) is looked up in a file
named `yuicompressor.jar`.
In order to compress resources with these two you need to download both and place where your `yii` console bootstrap
file is using named mentioned above. Since both are Java tools you need JRE installed.
### Performing compression
After configuration is adjusted you can run the `compress` action, using created config:
```
yii asset /path/to/myapp/config.php /path/to/myapp/config/assets_compressed.php
```
Now processing takes some time and finally finished. You need to adjust your web application config to use compressed
assets file like the following:
```php
'components' => [
// ...
'assetManager' => [
'bundles' => require /path/to/myapp/config/assets_compressed.php,
],
],
```
Using asset converter
---------------------
Instead of using CSS and JavaScript directly often developers are using their improved versions such as LESS or SCSS
for CSS or Microsoft TypeScript for JavaScript. Using these with Yii is easy.
First of all, corresponding compression tools should be installed and should be availabe from where `yii` console
bootstrap file is. The following lists file extensions and their corresponding conversion tool names that Yii converter
recognizes:
- LESS: `less` - `lessc`
- SCSS: `scss`, `sass` - `sass`
- Stylus: `styl` - `stylus`
- CoffeeScript: `coffee` - `coffee`
- TypeScript: `ts` - `tsc`
So if the corresponding tool is installed you can specify any of these in asset bundle:
```php
class AppAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'css/site.less',
];
public $js = [
'js/site.ts',
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BootstrapAsset',
];
}
```
In order to adjust conversion tool call parameters or add new ones you can use application config:
```php
// ...
'components' => [
'assetManager' => [
'converter' => [
'class' => 'yii\web\AssetConverter',
'commands' => [
'less' => ['css', 'lessc {from} {to} --no-color'],
'ts' => ['js', 'tsc --out {to} {from}'],
],
],
],
],
```
In the above we've left two types of extra file extensions. First one is `less` that can be specified in `css` part
of an asset bundle. Conversion is performed via running `lessc {from} {to} --no-color` where `{from}` is replaced with
LESS file path while `{to}` is replaced with target CSS file path. Second one is `ts` that can be specified in `js` part
of an asset bundle. The command that is run during conversion is in the same format that is used for `less`.

6
docs/guide/authorization.md

@ -234,10 +234,10 @@ public function editArticle($id)
{
$article = Article::find($id);
if (!$article) {
throw new HttpException(404);
throw new NotFoundHttpException;
}
if (!\Yii::$app->user->checkAccess('edit_article', ['article' => $article])) {
throw new HttpException(403);
throw new AccessDeniedHttpException;
}
// ...
}
@ -250,7 +250,7 @@ public function editArticle($id)
{
$article = Article::find(['id' => $id, 'author_id' => \Yii::$app->user->id]);
if (!$article) {
throw new HttpException(404);
throw new NotFoundHttpException;
}
// ...
}

39
docs/guide/behaviors.md

@ -1,4 +1,41 @@
Behaviors
=========
TDB
A behavior (also knows as mixin) can be used to enhance the functionality of an existing component without modifying its
code. In particular, it can "inject" its own methods and properties into the component and make them directly accessible
via the component. It can also respond to the events triggered in the component and thus intercept the normal
code execution. Unlike PHP traits, behaviors could be attached to classes at runtime.
Using behaviors
---------------
Behavior can be attached to any class that extends from `Component`. In order to do so you need to implement `behaviors`
method. Yii provides `AutoTimestamp` behavior that handles updating timestamp fields on saving active record model.
```php
class User extends ActiveRecord
{
// ...
public function behaviors()
{
return [
'timestamp' => [
'class' => 'yii\behaviors\AutoTimestamp',
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['create_time', 'update_time'],
ActiveRecord::EVENT_BEFORE_UPDATE => 'update_time',
],
],
];
}
}
```
In the above `class` value is a string containing fully qualified behavior class name. All the other key-values are
assigned to corresponding properties of the class.
Creating your own behaviors
---------------------------
TBD

16
docs/guide/configuration.md

@ -96,4 +96,18 @@ not be instantiated and configured at all.
Setting component defaults classwide
------------------------------------
TBD
For each component you can specifiy classwide defaults. For example, if we want to change class for all `LinkPager`
widgets without specifying it over and over again when widget is called we can do it like the following:
```php
\Yii::$objectConfig = [
'yii\widgets\LinkPager' => [
'options' => [
'class' => 'pagination',
],
],
];
```
The code above should be executed once before `LinkPager` widget is used. It can be done in `index.php`, application
config or anywhere else.

85
docs/guide/console.md

@ -1,4 +1,83 @@
Building console applications
=============================
Console applications
====================
TDB
Yii has full featured support of console. Console application structure in Yii is very similar to web application. It
consists of one or more [[\yii\console\Controller]] (often referred to as commands). Each has one or more actions.
Usage
-----
You can execute controller action using the following syntax:
```
yii <route> [--param1=value1 --param2 ...]
```
For example, `MigrationController::create` with `MigrationController::$migrationTable` set can be called from command
line like the following:
```
yii migreate/create --migrationTable=my_migration
```
In the above `yii` is console application entry script described below.
Entry script
------------
Console application entry script is typically called `yii`, located in your application root directory and contains
code like the following:
```php
#!/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/autoload.php');
require(__DIR__ . '/vendor/yiisoft/yii2/yii/Yii.php');
$config = require(__DIR__ . '/config/console.php');
$application = new yii\console\Application($config);
$exitCode = $application->run();
exit($exitCode);
```
This script is a part of your application so you're free to adjust it. There `YII_DEBUG` can be turned off if you do
not want to see stacktrace on error and want to improve overall performance. In both basic and advanced application
templates it is enabled to provide more developer-friendly environment.
Configuration
-------------
As can be seen in the code above, console application uses its own config files named `console.php` so you need to
configure database connection and the rest of the components you're going to use there in that file. If web and console
application configs have a lot in common it's a good idea to move matching parts into their own config files as it was
done in advanced application template.
Creating your own console commands
----------------------------------
### Controller
### Action
### Parameters
### Return codes
Using return codes is the best practice of console application development. If command returns `0` it means everything
is OK. If it is a number more than zero, we have an error and integer returned is the error code.

7
docs/guide/controller.md

@ -122,7 +122,7 @@ class BlogController extends Controller
{
$post = Post::find($id);
if (!$post) {
throw new HttpException(404);
throw new NotFoundHttpException;
}
if (\Yii::$app->request->isPost)) {
@ -183,7 +183,7 @@ Action Filters
Action filters are implemented via behaviors. You should extend from `ActionFilter` to
define a new filter. To use a filter, you should attach the filter class to the controller
as a behavior. For example, to use the `AccessControl` filter, you should have the following
as a behavior. For example, to use the [[AccessControl]] filter, you should have the following
code in a controller:
```php
@ -200,7 +200,8 @@ public function behaviors()
}
```
more TDB
In order to learn more about access control check [authorization](authorization.md) section of the guide.
Two other filters, [[PageCache]] and [[HttpCache]] are described in [caching](caching.md) section of the guide.
Catching all incoming requests
------------------------------

5
docs/guide/database-basics.md

@ -9,8 +9,8 @@ uniform API and solves some inconsistencies between different DBMS. By default Y
- [SQLite](http://sqlite.org/)
- [PostgreSQL](http://www.postgresql.org/)
- [CUBRID](http://www.cubrid.org/) (version 9.1.0 and higher).
- Oracle
- MSSQL
- [Oracle](http://www.oracle.com/us/products/database/overview/index.html)
- [MSSQL](https://www.microsoft.com/en-us/sqlserver/default.aspx)
Configuration
@ -42,6 +42,7 @@ return [
// ...
];
```
Please refer to the [PHP manual](http://www.php.net/manual/en/function.PDO-construct.php) for more details
on the format of the DSN string.

18
docs/guide/debugger.md

@ -7,19 +7,21 @@ about currently opened page while using debugger you can analyze data collected
Installing and configuring
--------------------------
How to use it
-------------
Add these lines to your config file:
```
'preload' => ['debug'],
'modules' => [
'debug' => ['yii\debug\Module']
]
'preload' => ['debug'],
'modules' => [
'debug' => ['yii\debug\Module']
]
```
**Watch out: by default the debug module only works when browsing the website from the localhost. If you want to use it on a remote (staging) server, add the parameter allowedIPs to the config to whitelist your IP.**
**Watch out: by default the debug module only works when browsing the website from the localhost. If you want to use it
on a remote (staging) server, add the parameter allowedIPs to the config to whitelist your IP.**
How to use it
-------------
Creating your own panels
------------------------

12
docs/guide/gii.md

@ -7,17 +7,17 @@ as well as complete CRUD controllers.
Installing and configuring
--------------------------
How to use it
-------------
Add these lines to your config file:
```php
'modules' => [
'gii' => ['yii\gii\Module']
]
'modules' => [
'gii' => ['yii\gii\Module']
]
```
How to use it
-------------
Creating your own templates
---------------------------

6
docs/guide/i18n.md

@ -47,7 +47,7 @@ translation of the message from source language into target language. Message it
echo \Yii::t('app', 'This is a string to translate!');
```
Yii tries to load approprite translation from one of the message sources defined via `i18n` component configuration:
Yii tries to load appropriate translation from one of the message sources defined via `i18n` component configuration:
```php
'components' => [
@ -239,7 +239,7 @@ you'll get "Inconsistent types declared for an argument: U_ARGUMENT_TYPE_MISMATC
Total {count, number} {count, plural, one{item} other{items}}.
```
To learn which inflection forms you should specify for your language you can referer to
To learn which inflection forms you should specify for your language you can referrer to
[rules reference at unicode.org](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html).
### Selections
@ -264,3 +264,5 @@ Formatters
In order to use formatters you need to install and enable [intl](http://www.php.net/manual/en/intro.intl.php) PHP
extension.
TBD: provided classes overview.

2
docs/guide/index.md

@ -47,7 +47,7 @@ Extensions and 3rd party libraries
- [Composer](composer.md) - How to manage applications dependencies via composer
- [Extending Yii](extensions.md)
- [Template engines](template.md) - Using template engines such as Smary or Twig
- [Template engines](template.md) - Using template engines such as Smarty or Twig
Security and access control
===========================

47
docs/guide/performance.md

@ -28,9 +28,10 @@ logger may record additional debug information for every message being logged.
### Enabling PHP opcode cache
Enabling the PHP opcode cache improves any PHP application performance and lowers
memory usage significantly. Yii is no exception. It was tested with
[APC PHP extension](http://php.net/manual/en/book.apc.php) that caches
and optimizes PHP intermediate code and avoids the time spent in parsing PHP
memory usage significantly. Yii is no exception. It was tested with both
[PHP 5.5 OPcache](http://php.net/manual/en/book.opcache.php) and
[APC PHP extension](http://php.net/manual/en/book.apc.php). Both cache
and optimize PHP intermediate code and avoid the time spent in parsing PHP
scripts for every incoming request.
### Turning on ActiveRecord database schema caching
@ -69,7 +70,10 @@ Note that `cache` application component should be configured.
### Combining and Minimizing Assets
TBD
It is possible to combine and minimize assets, typically JavaScript and CSS, in order to slightly improve page load
time and therefore deliver better experience for end user of your application.
In order to learn how it can be achieved, refer to [assets](assets.md) guide section.
### Using better storage for sessions
@ -118,7 +122,38 @@ save the rendering cost for the whole page.
### Leveraging HTTP to save processing time and bandwidth
TBD
Leveraging HTTP caching saves both processing time, bandwidth and resources significantly. It can be implemented by
sending either `ETag` or `Last-Modified` header in your application response. If browser is implemented according to
HTTP specification (most browsers are), content will be fetched only if it is different from what it was prevously.
Forming proper headers is time consuming task so Yii provides a shortcut in form of controller filter
[[\yii\web\HttpCache]]. Using it is very easy. In a controller you need to implement `behaviors` method like
the following:
```php
public function behaviors()
{
return [
'httpCache' => [
'class' => \yii\web\HttpCache::className(),
'only' => ['list'],
'lastModified' => function ($action, $params) {
$q = new Query();
return strtotime($q->from('users')->max('updated_timestamp'));
},
// 'etagSeed' => function ($action, $params) {
// return // generate etag seed here
//}
],
];
}
```
In the code above one can use either `etagSeed` or `lastModified`. Implementing both isn't necessary. The goal is to
determine if content was modified in a way that is cheaper than fetching and rendering that content. `lastModified`
should return unix timestamp of the last content modification while `etagSeed` should return a string that is then
used to generate `ETag` header value.
### Database Optimization
@ -140,7 +175,7 @@ to create one or several objects to represent each row of query result. For data
intensive applications, using DAO or database APIs at lower level could be
a better choice.
Last but not least, use LIMIT in your SELECT queries. This avoids fetching
Last but not least, use `LIMIT` in your `SELECT` queries. This avoids fetching
overwhelming data from database and exhausting the memory allocated to PHP.
### Using asArray

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

@ -518,5 +518,8 @@ TBD
Integration with Composer
-------------------------
TBD
Yii is fully inegrated with the package manager for PHP named Composer that resolves dependencies, keeps your code
up to date updating it semi-automatically and manages autoloading for third party libraries no matter which autoloading
these are using.
In order to learn more refer to [composer](composer.md) and [installation](installation.md) sections of the guide.

71
docs/guide/url.md

@ -92,6 +92,8 @@ return [
### Handling REST
TBD: [[\yii\web\VerbFiler]]
URL parsing
-----------
@ -118,3 +120,72 @@ return [
Creating your own rule classes
------------------------------
[[\yii\web\UrlRule]] class is used for both parsing URL into parameters and creating URL based on parameters. Despite
the fact that default implementation is flexible enough for majority of projects, there could be a situation when using
your own rule class is the best choice. For example, in a car dealer website, we may want to support the URL format like
`/Manufacturer/Model`, where `Manufacturer` and `Model` must both match some data in a database table. The default rule
class will not work because it mostly relies on statically declared regular expressions which have no database knowledge.
We can write a new URL rule class by extending from [[\yii\web\UrlRule]] and use it in one or multiple URL rules. Using
the above car dealer website as an example, we may declare the following URL rules in application config:
```php
// ...
'components' => [
'urlManager' => [
'rules' => [
'<action:(login|logout|about)>' => 'site/<action>',
// ...
['class' => 'app\components\CarUrlRule', 'connectionID' => 'db', ...],
],
],
],
```
In the above, we use the custom URL rule class `CarUrlRule` to handle
the URL format `/Manufacturer/Model`. The class can be written like the following:
```php
namespace \app\components;
use \yii\web\UrlRule;
class CarUrlRule extends UrlRule
{
public $connectionID = 'db';
public function createUrl($manager, $route, $params)
{
if ($route === 'car/index') {
if (isset($params['manufacturer'], $params['model'])) {
return $params['manufacturer'] . '/' . $params['model'];
} elseif (isset($params['manufacturer'])) {
return $params['manufacturer'];
}
}
return false; // this rule does not apply
}
public function parseRequest($manager, $request)
{
$pathInfo = $request->getPathInfo();
if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches)) {
// check $matches[1] and $matches[3] to see
// if they match a manufacturer and a model in the database
// If so, set $_GET['manufacturer'] and/or $_GET['model']
// and return 'car/index'
}
return false; // this rule does not apply
}
}
```
Besides the above usage, custom URL rule classes can also be implemented
for many other purposes. For example, we can write a rule class to log the URL parsing
and creation requests. This may be useful during development stage. We can also
write a rule class to display a special 404 error page in case all other URL rules fail
to resolve the current request. Note that in this case, the rule of this special class
must be declared as the last rule.

7
docs/guide/view.md

@ -277,7 +277,12 @@ use yii\helpers\Html;
In the markup above there's some code. First of all, `$content` is a variable that will contain result of views rendered
with controller's `$this->render()` method.
TBD
We are importing `Html` helper via standard PHP `use` statement. This helper is typically used for almost all views
where one need to escape outputted data.
Several special methods such as `beginPage`/`endPage`, `head`, `beginBody`/`endBody` are triggering page rendering events
that are used for registering scripts, links and process page in many other ways. Always include these in your layout in
order for rendering to work correctly.
### Partials

8
extensions/composer/Installer.php

@ -26,7 +26,7 @@ class Installer extends LibraryInstaller
const EXTENSION_FILE = 'yiisoft/extensions.php';
/**
* {@inheritdoc}
* @inheritdoc
*/
public function supports($packageType)
{
@ -34,7 +34,7 @@ class Installer extends LibraryInstaller
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
{
@ -49,7 +49,7 @@ class Installer extends LibraryInstaller
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
{
@ -63,7 +63,7 @@ class Installer extends LibraryInstaller
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
{

2
extensions/composer/Plugin.php

@ -20,7 +20,7 @@ use Composer\Plugin\PluginInterface;
class Plugin implements PluginInterface
{
/**
* {@inheritdoc}
* @inheritdoc
*/
public function activate(Composer $composer, IOInterface $io)
{

4
extensions/debug/Module.php

@ -10,7 +10,7 @@ namespace yii\debug;
use Yii;
use yii\base\Application;
use yii\web\View;
use yii\web\HttpException;
use yii\web\AccessDeniedHttpException;
/**
* The Yii Debug Module provides the debug toolbar and debugger
@ -79,7 +79,7 @@ class Module extends \yii\base\Module
} elseif ($action->id === 'toolbar') {
return false;
} else {
throw new HttpException(403, 'You are not allowed to access this page.');
throw new AccessDeniedHttpException('You are not allowed to access this page.');
}
}

4
extensions/debug/controllers/DefaultController.php

@ -9,7 +9,7 @@ namespace yii\debug\controllers;
use Yii;
use yii\web\Controller;
use yii\web\HttpException;
use yii\web\NotFoundHttpException;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
@ -99,7 +99,7 @@ class DefaultController extends Controller
}
$this->summary = $data['summary'];
} else {
throw new HttpException(404, "Unable to find debug data tagged with '$tag'.");
throw new NotFoundHttpException("Unable to find debug data tagged with '$tag'.");
}
}
}

6
extensions/elasticsearch/ActiveQuery.php

@ -139,7 +139,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function search($db = null, $options = [])
{
@ -161,7 +161,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function scalar($field, $db = null)
{
@ -177,7 +177,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function column($field, $db = null)
{

57
extensions/elasticsearch/ActiveRecord.php

@ -10,6 +10,8 @@ namespace yii\elasticsearch;
use yii\base\InvalidCallException;
use yii\base\InvalidConfigException;
use yii\base\NotSupportedException;
use yii\db\ActiveRecordInterface;
use yii\db\BaseActiveRecord;
use yii\helpers\Inflector;
use yii\helpers\Json;
use yii\helpers\StringHelper;
@ -42,7 +44,7 @@ use yii\helpers\StringHelper;
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class ActiveRecord extends \yii\db\ActiveRecord
class ActiveRecord extends BaseActiveRecord
{
const PRIMARY_KEY_NAME = 'id';
@ -61,7 +63,7 @@ class ActiveRecord extends \yii\db\ActiveRecord
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public static function find($q = null)
{
@ -138,7 +140,7 @@ class ActiveRecord extends \yii\db\ActiveRecord
// TODO add percolate functionality http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-percolate.html
/**
* {@inheritdoc}
* @inheritdoc
*/
public static function createQuery()
{
@ -146,7 +148,7 @@ class ActiveRecord extends \yii\db\ActiveRecord
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public static function createActiveRelation($config = [])
{
@ -175,7 +177,7 @@ class ActiveRecord extends \yii\db\ActiveRecord
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getPrimaryKey($asArray = false)
{
@ -187,7 +189,7 @@ class ActiveRecord extends \yii\db\ActiveRecord
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getOldPrimaryKey($asArray = false)
{
@ -428,47 +430,4 @@ class ActiveRecord extends \yii\db\ActiveRecord
}
return $n;
}
/**
* {@inheritdoc}
*/
public static function updateAllCounters($counters, $condition = null, $params = [])
{
throw new NotSupportedException('Update Counters is not supported by elasticsearch ActiveRecord.');
}
/**
* {@inheritdoc}
*/
public static function getTableSchema()
{
throw new NotSupportedException('getTableSchema() is not supported by elasticsearch ActiveRecord.');
}
/**
* {@inheritdoc}
*/
public static function tableName()
{
return static::index() . '/' . static::type();
}
/**
* {@inheritdoc}
*/
public static function findBySql($sql, $params = [])
{
throw new NotSupportedException('findBySql() is not supported by elasticsearch ActiveRecord.');
}
/**
* Returns a value indicating whether the specified operation is transactional in the current [[scenario]].
* This method will always return false as transactional operations are not supported by elasticsearch.
* @param integer $operation the operation to check. Possible values are [[OP_INSERT]], [[OP_UPDATE]] and [[OP_DELETE]].
* @return boolean whether the specified operation is transactional in the current [[scenario]].
*/
public function isTransactional($operation)
{
return false;
}
}

5
extensions/elasticsearch/Connection.php

@ -15,6 +15,9 @@ use yii\helpers\Json;
/**
* elasticsearch Connection is used to connect to an elasticsearch cluster version 0.20 or higher
*
* @property string $driverName Name of the DB driver. This property is read-only.
* @property boolean $isActive Whether the DB connection is established. This property is read-only.
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
@ -264,7 +267,7 @@ class Connection extends Component
if (strncmp($host, 'inet[/', 6) == 0) {
$host = substr($host, 6, -1);
}
$profile = $q . $requestBody;
$profile = $method . ' ' . $q . '#' . $requestBody;
$url = 'http://' . $host . '/' . $q;
} else {
$profile = false;

168
extensions/elasticsearch/DebugPanel.php

@ -0,0 +1,168 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\elasticsearch;
use yii\debug\Panel;
use yii\log\Logger;
use yii\helpers\Html;
use yii\web\View;
/**
* Debugger panel that collects and displays elasticsearch queries performed.
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class DebugPanel extends Panel
{
public function getName()
{
return 'Elasticsearch';
}
public function getSummary()
{
$timings = $this->calculateTimings();
$queryCount = count($timings);
$queryTime = 0;
foreach ($timings as $timing) {
$queryTime += $timing[3];
}
$queryTime = number_format($queryTime * 1000) . ' ms';
$url = $this->getUrl();
$output = <<<EOD
<div class="yii-debug-toolbar-block">
<a href="$url" title="Executed $queryCount elasticsearch queries which took $queryTime.">
ES <span class="label">$queryCount</span> <span class="label">$queryTime</span>
</a>
</div>
EOD;
return $queryCount > 0 ? $output : '';
}
public function getDetail()
{
$rows = [];
$i = 0;
foreach ($this->data['messages'] as $log) {
list ($message, $level, $category, $time, $traces) = $log;
if ($level == Logger::LEVEL_PROFILE_BEGIN) {
continue;
}
if (($pos = mb_strpos($message, "#")) !== false) {
$url = mb_substr($message, 0, $pos);
$body = mb_substr($message, $pos + 1);
} else {
$url = $message;
$body = null;
}
$traceString = '';
if (!empty($traces)) {
$traceString .= Html::ul($traces, [
'class' => 'trace',
'item' => function ($trace) {
return "<li>{$trace['file']}({$trace['line']})</li>";
},
]);
}
$runLinks = '';
$c = 0;
\Yii::$app->elasticsearch->open();
foreach(\Yii::$app->elasticsearch->nodes as $node) {
$pos = mb_strpos($url, ' ');
$type = mb_substr($url, 0, $pos);
if ($type == 'GET' && !empty($body)) {
$type = 'POST';
}
$host = $node['http_address'];
if (strncmp($host, 'inet[/', 6) == 0) {
$host = substr($host, 6, -1);
}
$nodeUrl = 'http://' . $host . '/' . mb_substr($url, $pos + 1);
$nodeUrl .= (strpos($nodeUrl, '?') === false) ? '?pretty=true' : '&pretty=true';
$nodeBody = json_encode($body);
\Yii::$app->view->registerJs(<<<JS
$('#elastic-link-$i-$c').on('click', function() {
$('#elastic-result-$i').html('Sending $type request to $nodeUrl...');
$('#elastic-result-$i').parent('tr').show();
$.ajax({
type: "$type",
url: "$nodeUrl",
body: $nodeBody,
success: function( data ) {
$('#elastic-result-$i').html(data);
},
dataType: "text"
});
return false;
});
JS
, View::POS_READY);
$runLinks .= Html::a(isset($node['name']) ? $node['name'] : $node['http_address'], '#', ['id' => "elastic-link-$i-$c"]) . '<br/>';
$c++;
}
$rows[] = "<tr><td style=\"width: 80%;\"><div><b>$url</b><br/><p>$body</p>$traceString</div></td><td style=\"width: 20%;\">$runLinks</td></tr><tr style=\"display: none;\"><td colspan=\"2\" id=\"elastic-result-$i\"></td></tr>";
$i++;
}
$rows = implode("\n", $rows);
return <<<HTML
<h1>Elasticsearch Queries</h1>
<table class="table table-condensed table-bordered table-striped table-hover" style="table-layout: fixed;">
<thead>
<tr>
<th style="width: 80%;">Url / Query</th>
<th style="width: 20%;">Run Query on node</th>
</tr>
</thead>
<tbody>
$rows
</tbody>
</table>
HTML;
}
private $_timings;
protected function calculateTimings()
{
if ($this->_timings !== null) {
return $this->_timings;
}
$messages = $this->data['messages'];
$timings = [];
$stack = [];
foreach ($messages as $i => $log) {
list($token, $level, $category, $timestamp) = $log;
$log[5] = $i;
if ($level == Logger::LEVEL_PROFILE_BEGIN) {
$stack[] = $log;
} elseif ($level == Logger::LEVEL_PROFILE_END) {
if (($last = array_pop($stack)) !== null && $last[0] === $token) {
$timings[$last[5]] = [count($stack), $token, $last[3], $timestamp - $last[3], $last[4]];
}
}
}
$now = microtime(true);
while (($last = array_pop($stack)) !== null) {
$delta = $now - $last[3];
$timings[$last[5]] = [count($stack), $last[0], $last[2], $delta, $last[4]];
}
ksort($timings);
return $this->_timings = $timings;
}
public function save()
{
$target = $this->module->logTarget;
$messages = $target->filterMessages($target->messages, Logger::LEVEL_PROFILE, ['yii\elasticsearch\Connection::httpRequest']);
return ['messages' => $messages];
}
}

54
extensions/elasticsearch/QueryBuilder.php

@ -14,7 +14,6 @@ use yii\helpers\Json;
/**
* QueryBuilder builds an elasticsearch query based on the specification given as a [[Query]] object.
*
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
@ -247,7 +246,7 @@ class QueryBuilder extends \yii\base\Object
}
if (count($column) > 1) {
return $this->buildCompositeInCondition($operator, $column, $values, $params);
return $this->buildCompositeInCondition($operator, $column, $values);
} elseif (is_array($column)) {
$column = reset($column);
}
@ -289,61 +288,10 @@ class QueryBuilder extends \yii\base\Object
protected function buildCompositeInCondition($operator, $columns, $values)
{
throw new NotSupportedException('composite in is not supported by elasticsearch.');
$vss = array();
foreach ($values as $value) {
$vs = array();
foreach ($columns as $column) {
if (isset($value[$column])) {
$phName = self::PARAM_PREFIX . count($params);
$params[$phName] = $value[$column];
$vs[] = $phName;
} else {
$vs[] = 'NULL';
}
}
$vss[] = '(' . implode(', ', $vs) . ')';
}
foreach ($columns as $i => $column) {
if (strpos($column, '(') === false) {
$columns[$i] = $this->db->quoteColumnName($column);
}
}
return '(' . implode(', ', $columns) . ") $operator (" . implode(', ', $vss) . ')';
}
private function buildLikeCondition($operator, $operands)
{
throw new NotSupportedException('like conditions is not supported by elasticsearch.');
if (!isset($operands[0], $operands[1])) {
throw new Exception("Operator '$operator' requires two operands.");
}
list($column, $values) = $operands;
$values = (array)$values;
if (empty($values)) {
return $operator === 'LIKE' || $operator === 'OR LIKE' ? '0==1' : '';
}
if ($operator === 'LIKE' || $operator === 'NOT LIKE') {
$andor = ' AND ';
} else {
$andor = ' OR ';
$operator = $operator === 'OR LIKE' ? 'LIKE' : 'NOT LIKE';
}
if (strpos($column, '(') === false) {
$column = $this->db->quoteColumnName($column);
}
$parts = array();
foreach ($values as $value) {
$phName = self::PARAM_PREFIX . count($params);
$params[$phName] = $value;
$parts[] = "$column $operator $phName";
}
return implode($andor, $parts);
}
}

26
extensions/elasticsearch/README.md

@ -146,3 +146,29 @@ $query->search(); // gives you all the records + stats about the visit_count fie
```
And there is so much more in it. "it’s endless what you can build"[¹](http://www.elasticsearch.org/)
Using the elasticsearch DebugPanel
----------------------------------
The yii2 elasticsearch extensions provides a `DebugPanel` that can be integrated with the yii debug module
an shows the executed elasticsearch queries. It also allows to run these queries on different cluster nodes
an view the results.
Add the following to you application config to enable it:
```php
// ...
'preload' => 'debug',
'modules' => [
'debug' => [
'class' => 'yii\\debug\\Module',
'panels' => [
'elasticsearch' => [
'class' => 'yii\\elasticsearch\\DebugPanel',
],
],
],
],
// ...
```

4
extensions/gii/Generator.php

@ -63,7 +63,7 @@ abstract class Generator extends Model
abstract public function generate();
/**
* {@inheritdoc}
* @inheritdoc
*/
public function init()
{
@ -164,7 +164,7 @@ abstract class Generator extends Model
}
/**
* {@inheritdoc}
* @inheritdoc
*
* Child classes should override this method like the following so that the parent
* rules are included:

8
extensions/gii/GiiAsset.php

@ -18,25 +18,25 @@ use yii\web\AssetBundle;
class GiiAsset extends AssetBundle
{
/**
* {@inheritdoc}
* @inheritdoc
*/
public $sourcePath = '@yii/gii/assets';
/**
* {@inheritdoc}
* @inheritdoc
*/
public $css = [
'main.css',
'typeahead.js-bootstrap.css',
];
/**
* {@inheritdoc}
* @inheritdoc
*/
public $js = [
'gii.js',
'typeahead.js',
];
/**
* {@inheritdoc}
* @inheritdoc
*/
public $depends = [
'yii\web\YiiAsset',

10
extensions/gii/Module.php

@ -8,7 +8,7 @@
namespace yii\gii;
use Yii;
use yii\web\HttpException;
use yii\web\AccessDeniedHttpException;
/**
* This is the main module class for the Gii module.
@ -54,7 +54,7 @@ use yii\web\HttpException;
class Module extends \yii\base\Module
{
/**
* {@inheritdoc}
* @inheritdoc
*/
public $controllerNamespace = 'yii\gii\controllers';
/**
@ -92,7 +92,7 @@ class Module extends \yii\base\Module
/**
* {@inheritdoc}
* @inheritdoc
*/
public function init()
{
@ -103,14 +103,14 @@ class Module extends \yii\base\Module
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function beforeAction($action)
{
if ($this->checkAccess()) {
return parent::beforeAction($action);
} else {
throw new HttpException(403, 'You are not allowed to access this page.');
throw new AccessDeniedHttpException('You are not allowed to access this page.');
}
}

14
extensions/gii/controllers/DefaultController.php

@ -9,7 +9,7 @@ namespace yii\gii\controllers;
use Yii;
use yii\web\Controller;
use yii\web\HttpException;
use yii\web\NotFoundHttpException;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
@ -69,7 +69,7 @@ class DefaultController extends Controller
}
}
}
throw new HttpException(404, "Code file not found: $file");
throw new NotFoundHttpException("Code file not found: $file");
}
public function actionDiff($id, $file)
@ -84,7 +84,7 @@ class DefaultController extends Controller
}
}
}
throw new HttpException(404, "Code file not found: $file");
throw new NotFoundHttpException("Code file not found: $file");
}
/**
@ -94,7 +94,7 @@ class DefaultController extends Controller
* @param string $id the ID of the generator
* @param string $name the action name
* @return mixed the result of the action.
* @throws HttpException if the action method does not exist.
* @throws NotFoundHttpException if the action method does not exist.
*/
public function actionAction($id, $name)
{
@ -103,7 +103,7 @@ class DefaultController extends Controller
if (method_exists($generator, $method)) {
return $generator->$method();
} else {
throw new HttpException(400, "Unknown generator action: $name");
throw new NotFoundHttpException("Unknown generator action: $name");
}
}
@ -136,7 +136,7 @@ class DefaultController extends Controller
* Loads the generator with the specified ID.
* @param string $id the ID of the generator to be loaded.
* @return \yii\gii\Generator the loaded generator
* @throws \yii\web\HttpException
* @throws NotFoundHttpException
*/
protected function loadGenerator($id)
{
@ -146,7 +146,7 @@ class DefaultController extends Controller
$this->generator->load($_POST);
return $this->generator;
} else {
throw new HttpException(404, "Code generator not found: $id");
throw new NotFoundHttpException("Code generator not found: $id");
}
}
}

20
extensions/gii/generators/controller/Generator.php

@ -38,7 +38,7 @@ class Generator extends \yii\gii\Generator
public $actions = 'index';
/**
* {@inheritdoc}
* @inheritdoc
*/
public function init()
{
@ -47,7 +47,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getName()
{
@ -55,7 +55,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getDescription()
{
@ -64,7 +64,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function rules()
{
@ -79,7 +79,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function attributeLabels()
{
@ -92,7 +92,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function requiredTemplates()
{
@ -103,7 +103,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function stickyAttributes()
{
@ -111,7 +111,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function hints()
{
@ -134,7 +134,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function successMessage()
{
@ -149,7 +149,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function generate()
{

92
extensions/gii/generators/crud/Generator.php

@ -9,6 +9,7 @@ namespace yii\gii\generators\crud;
use Yii;
use yii\db\ActiveRecord;
use yii\db\BaseActiveRecord;
use yii\db\Schema;
use yii\gii\CodeFile;
use yii\helpers\Inflector;
@ -46,7 +47,7 @@ class Generator extends \yii\gii\Generator
[['modelClass', 'searchModelClass', 'controllerClass', 'baseControllerClass', 'indexWidgetType'], 'required'],
[['searchModelClass'], 'compare', 'compareAttribute' => 'modelClass', 'operator' => '!==', 'message' => 'Search Model Class must not be equal to Model Class.'],
[['modelClass', 'controllerClass', 'baseControllerClass', 'searchModelClass'], 'match', 'pattern' => '/^[\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'],
[['modelClass'], 'validateClass', 'params' => ['extends' => ActiveRecord::className()]],
[['modelClass'], 'validateClass', 'params' => ['extends' => BaseActiveRecord::className()]],
[['baseControllerClass'], 'validateClass', 'params' => ['extends' => Controller::className()]],
[['controllerClass'], 'match', 'pattern' => '/Controller$/', 'message' => 'Controller class name must be suffixed with "Controller".'],
[['controllerClass', 'searchModelClass'], 'validateNewClass'],
@ -69,7 +70,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function hints()
{
@ -95,7 +96,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function stickyAttributes()
{
@ -123,7 +124,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function generate()
{
@ -167,13 +168,13 @@ class Generator extends \yii\gii\Generator
public function getNameAttribute()
{
/** @var \yii\db\ActiveRecord $class */
$class = $this->modelClass;
foreach ($class::getTableSchema()->columnNames as $name) {
foreach ($this->getColumnNames() as $name) {
if (!strcasecmp($name, 'name') || !strcasecmp($name, 'title')) {
return $name;
}
}
/** @var \yii\db\ActiveRecord $class */
$class = $this->modelClass;
$pk = $class::primaryKey();
return $pk[0];
}
@ -185,8 +186,12 @@ class Generator extends \yii\gii\Generator
public function generateActiveField($attribute)
{
$tableSchema = $this->getTableSchema();
if (!isset($tableSchema->columns[$attribute])) {
return "\$form->field(\$model, '$attribute');";
if ($tableSchema === false || !isset($tableSchema->columns[$attribute])) {
if (preg_match('/^(password|pass|passwd|passcode)$/i', $attribute)) {
return "\$form->field(\$model, '$attribute')->passwordInput();";
} else {
return "\$form->field(\$model, '$attribute');";
}
}
$column = $tableSchema->columns[$attribute];
if ($column->phpType === 'boolean') {
@ -214,6 +219,9 @@ class Generator extends \yii\gii\Generator
public function generateActiveSearchField($attribute)
{
$tableSchema = $this->getTableSchema();
if ($tableSchema === false) {
return "\$form->field(\$model, '$attribute')";
}
$column = $tableSchema->columns[$attribute];
if ($column->phpType === 'boolean') {
return "\$form->field(\$model, '$attribute')->checkbox()";
@ -249,7 +257,9 @@ class Generator extends \yii\gii\Generator
*/
public function generateSearchRules()
{
$table = $this->getTableSchema();
if (($table = $this->getTableSchema()) === false) {
return ["[['" . implode("', '", $this->getColumnNames()) . "'], 'safe']"];
}
$types = [];
foreach ($table->columns as $column) {
switch ($column->type) {
@ -286,7 +296,7 @@ class Generator extends \yii\gii\Generator
public function getSearchAttributes()
{
return $this->getTableSchema()->getColumnNames();
return $this->getColumnNames();
}
/**
@ -295,17 +305,16 @@ class Generator extends \yii\gii\Generator
*/
public function generateSearchLabels()
{
$table = $this->getTableSchema();
$labels = [];
foreach ($table->columns as $column) {
if (!strcasecmp($column->name, 'id')) {
$labels[$column->name] = 'ID';
foreach ($this->getColumnNames() as $name) {
if (!strcasecmp($name, 'id')) {
$labels[$name] = 'ID';
} else {
$label = Inflector::camel2words($column->name);
$label = Inflector::camel2words($name);
if (strcasecmp(substr($label, -3), ' id') === 0) {
$label = substr($label, 0, -3) . ' ID';
}
$labels[$column->name] = $label;
$labels[$name] = $label;
}
}
return $labels;
@ -313,10 +322,21 @@ class Generator extends \yii\gii\Generator
public function generateSearchConditions()
{
$table = $this->getTableSchema();
$columns = [];
if (($table = $this->getTableSchema()) === false) {
$class = $this->modelClass;
$model = new $class();
foreach ($model->attributes() as $attribute) {
$columns[$attribute] = 'unknown';
}
} else {
foreach ($table->columns as $column) {
$columns[$column->name] = $column->type;
}
}
$conditions = [];
foreach ($table->columns as $column) {
switch ($column->type) {
foreach ($columns as $column => $type) {
switch ($type) {
case Schema::TYPE_SMALLINT:
case Schema::TYPE_INTEGER:
case Schema::TYPE_BIGINT:
@ -328,10 +348,11 @@ class Generator extends \yii\gii\Generator
case Schema::TYPE_TIME:
case Schema::TYPE_DATETIME:
case Schema::TYPE_TIMESTAMP:
$conditions[] = "\$this->addCondition(\$query, '{$column->name}');";
case
$conditions[] = "\$this->addCondition(\$query, '{$column}');";
break;
default:
$conditions[] = "\$this->addCondition(\$query, '{$column->name}', true);";
$conditions[] = "\$this->addCondition(\$query, '{$column}', true);";
break;
}
}
@ -369,10 +390,16 @@ class Generator extends \yii\gii\Generator
public function generateActionParamComments()
{
$table = $this->getTableSchema();
/** @var ActiveRecord $class */
$class = $this->modelClass;
$pks = $class::primaryKey();
if (($table = $this->getTableSchema()) === false) {
$params = [];
foreach ($pks as $pk) {
$params[] = '@param ' . (substr(strtolower($pk), -2) == 'id' ? 'integer' : 'string') . ' $' . $pk;
}
return $params;
}
if (count($pks) === 1) {
return ['@param ' . $table->columns[$pks[0]]->phpType . ' $id'];
} else {
@ -388,6 +415,23 @@ class Generator extends \yii\gii\Generator
{
/** @var ActiveRecord $class */
$class = $this->modelClass;
return $class::getTableSchema();
if (is_subclass_of($class, 'yii\db\ActiveRecord')) {
return $class::getTableSchema();
} else {
return false;
}
}
public function getColumnNames()
{
/** @var ActiveRecord $class */
$class = $this->modelClass;
if (is_subclass_of($class, 'yii\db\ActiveRecord')) {
return $class::getTableSchema()->getColumnNames();
} else {
$model = new $class();
return $model->attributes();
}
}
}

11
extensions/gii/generators/crud/templates/controller.php

@ -1,5 +1,6 @@
<?php
use yii\db\ActiveRecordInterface;
use yii\helpers\StringHelper;
/**
@ -16,7 +17,9 @@ if ($modelClass === $searchModelClass) {
$searchModelAlias = $searchModelClass.'Search';
}
$pks = $generator->getTableSchema()->primaryKey;
/** @var ActiveRecordInterface $class */
$class = $generator->modelClass;
$pks = $class::primaryKey();
$urlParams = $generator->generateUrlParams();
$actionParams = $generator->generateActionParams();
$actionParamComments = $generator->generateActionParamComments();
@ -29,7 +32,7 @@ namespace <?= StringHelper::dirname(ltrim($generator->controllerClass, '\\')) ?>
use <?= ltrim($generator->modelClass, '\\') ?>;
use <?= ltrim($generator->searchModelClass, '\\') ?><?php if (isset($searchModelAlias)):?> as <?= $searchModelAlias ?><?php endif ?>;
use <?= ltrim($generator->baseControllerClass, '\\') ?>;
use yii\web\HttpException;
use yii\web\NotFoundHttpException;
use yii\web\VerbFilter;
/**
@ -130,7 +133,7 @@ class <?= $controllerClass ?> extends <?= StringHelper::basename($generator->bas
* If the model is not found, a 404 HTTP exception will be thrown.
* <?= implode("\n\t * ", $actionParamComments) . "\n" ?>
* @return <?= $modelClass ?> the loaded model
* @throws HttpException if the model cannot be found
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel(<?= $actionParams ?>)
{
@ -148,7 +151,7 @@ if (count($pks) === 1) {
if (($model = <?= $modelClass ?>::find(<?= $condition ?>)) !== null) {
return $model;
} else {
throw new HttpException(404, 'The requested page does not exist.');
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}

2
extensions/gii/generators/crud/templates/search.php

@ -40,7 +40,7 @@ class <?= $searchModelClass ?> extends Model
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function attributeLabels()
{

2
extensions/gii/generators/crud/templates/views/_form.php

@ -12,7 +12,7 @@ use yii\helpers\StringHelper;
$model = new $generator->modelClass;
$safeAttributes = $model->safeAttributes();
if (empty($safeAttributes)) {
$safeAttributes = $model->getTableSchema()->columnNames;
$safeAttributes = $model->attributes();
}
echo "<?php\n";

2
extensions/gii/generators/crud/templates/views/_search.php

@ -30,7 +30,7 @@ use yii\widgets\ActiveForm;
<?php
$count = 0;
foreach ($generator->getTableSchema()->getColumnNames() as $attribute) {
foreach ($generator->getColumnNames() as $attribute) {
if (++$count < 6) {
echo "\t\t<?= " . $generator->generateActiveSearchField($attribute) . " ?>\n\n";
} else {

22
extensions/gii/generators/crud/templates/views/index.php

@ -45,12 +45,22 @@ $this->params['breadcrumbs'][] = $this->title;
<?php
$count = 0;
foreach ($generator->getTableSchema()->columns as $column) {
$format = $generator->generateColumnFormat($column);
if (++$count < 6) {
echo "\t\t\t'" . $column->name . ($format === 'text' ? "" : ":" . $format) . "',\n";
} else {
echo "\t\t\t// '" . $column->name . ($format === 'text' ? "" : ":" . $format) . "',\n";
if (($tableSchema = $generator->getTableSchema()) === false) {
foreach ($generator->getColumnNames() as $name) {
if (++$count < 6) {
echo "\t\t\t'" . $name . "',\n";
} else {
echo "\t\t\t// '" . $name . "',\n";
}
}
} else {
foreach ($tableSchema->columns as $column) {
$format = $generator->generateColumnFormat($column);
if (++$count < 6) {
echo "\t\t\t'" . $column->name . ($format === 'text' ? "" : ":" . $format) . "',\n";
} else {
echo "\t\t\t// '" . $column->name . ($format === 'text' ? "" : ":" . $format) . "',\n";
}
}
}
?>

12
extensions/gii/generators/crud/templates/views/view.php

@ -42,9 +42,15 @@ $this->params['breadcrumbs'][] = $this->title;
'model' => $model,
'attributes' => [
<?php
foreach ($generator->getTableSchema()->columns as $column) {
$format = $generator->generateColumnFormat($column);
echo "\t\t\t'" . $column->name . ($format === 'text' ? "" : ":" . $format) . "',\n";
if (($tableSchema = $generator->getTableSchema()) === false) {
foreach ($generator->getColumnNames() as $name) {
echo "\t\t\t'" . $name . "',\n";
}
} else {
foreach ($generator->getTableSchema()->columns as $column) {
$format = $generator->generateColumnFormat($column);
echo "\t\t\t'" . $column->name . ($format === 'text' ? "" : ":" . $format) . "',\n";
}
}
?>
],

18
extensions/gii/generators/form/Generator.php

@ -26,7 +26,7 @@ class Generator extends \yii\gii\Generator
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getName()
{
@ -34,7 +34,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getDescription()
{
@ -42,7 +42,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function generate()
{
@ -55,7 +55,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function rules()
{
@ -72,7 +72,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function attributeLabels()
{
@ -85,7 +85,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function requiredTemplates()
{
@ -93,7 +93,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function stickyAttributes()
{
@ -101,7 +101,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function hints()
{
@ -114,7 +114,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function successMessage()
{

18
extensions/gii/generators/model/Generator.php

@ -32,7 +32,7 @@ class Generator extends \yii\gii\Generator
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getName()
{
@ -40,7 +40,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getDescription()
{
@ -48,7 +48,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function rules()
{
@ -68,7 +68,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function attributeLabels()
{
@ -84,7 +84,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function hints()
{
@ -111,7 +111,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function autoCompleteData()
{
@ -128,7 +128,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function requiredTemplates()
{
@ -136,7 +136,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function stickyAttributes()
{
@ -144,7 +144,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function generate()
{

6
extensions/gii/generators/model/templates/model.php

@ -33,7 +33,7 @@ namespace <?= $generator->ns ?>;
class <?= $className ?> extends <?= '\\' . ltrim($generator->baseClass, '\\') . "\n" ?>
{
/**
* {@inheritdoc}
* @inheritdoc
*/
public static function tableName()
{
@ -41,7 +41,7 @@ class <?= $className ?> extends <?= '\\' . ltrim($generator->baseClass, '\\') .
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function rules()
{
@ -49,7 +49,7 @@ class <?= $className ?> extends <?= '\\' . ltrim($generator->baseClass, '\\') .
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function attributeLabels()
{

16
extensions/gii/generators/module/Generator.php

@ -24,7 +24,7 @@ class Generator extends \yii\gii\Generator
public $moduleID;
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getName()
{
@ -32,7 +32,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getDescription()
{
@ -40,7 +40,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function rules()
{
@ -54,7 +54,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function attributeLabels()
{
@ -65,7 +65,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function hints()
{
@ -76,7 +76,7 @@ class Generator extends \yii\gii\Generator
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function successMessage()
{
@ -104,7 +104,7 @@ EOD;
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function requiredTemplates()
{
@ -112,7 +112,7 @@ EOD;
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function generate()
{

4
extensions/redis/ActiveQuery.php

@ -132,7 +132,7 @@ class ActiveQuery extends \yii\base\Component implements ActiveQueryInterface
if ($db === null) {
$db = $modelClass::getDb();
}
return $db->executeCommand('LLEN', [$modelClass::tableName()]);
return $db->executeCommand('LLEN', [$modelClass::keyPrefix()]);
} else {
return $this->executeScript($db, 'Count');
}
@ -296,7 +296,7 @@ class ActiveQuery extends \yii\base\Component implements ActiveQueryInterface
$data = [];
foreach($pks as $pk) {
if (++$i > $start && ($this->limit === null || $i <= $start + $this->limit)) {
$key = $modelClass::tableName() . ':a:' . $modelClass::buildKey($pk);
$key = $modelClass::keyPrefix() . ':a:' . $modelClass::buildKey($pk);
$result = $db->executeCommand('HGETALL', [$key]);
if (!empty($result)) {
$data[] = $result;

69
extensions/redis/ActiveRecord.php

@ -9,6 +9,8 @@ namespace yii\redis;
use yii\base\InvalidConfigException;
use yii\base\NotSupportedException;
use yii\db\BaseActiveRecord;
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
/**
@ -34,7 +36,7 @@ use yii\helpers\StringHelper;
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class ActiveRecord extends \yii\db\ActiveRecord
class ActiveRecord extends BaseActiveRecord
{
/**
* Returns the database connection used by this AR class.
@ -48,7 +50,7 @@ class ActiveRecord extends \yii\db\ActiveRecord
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public static function createQuery()
{
@ -56,7 +58,7 @@ class ActiveRecord extends \yii\db\ActiveRecord
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public static function createActiveRelation($config = [])
{
@ -87,7 +89,19 @@ class ActiveRecord extends \yii\db\ActiveRecord
}
/**
* {@inheritdoc}
* Declares prefix of the key that represents the keys that store this records in redis.
* By default this method returns the class name as the table name by calling [[Inflector::camel2id()]].
* For example, 'Customer' becomes 'customer', and 'OrderItem' becomes
* 'order_item'. You may override this method if you want different key naming.
* @return string the prefix to apply to all AR keys
*/
public static function keyPrefix()
{
return Inflector::camel2id(StringHelper::basename(get_called_class()), '_');
}
/**
* @inheritdoc
*/
public function insert($runValidation = true, $attributes = null)
{
@ -102,15 +116,15 @@ class ActiveRecord extends \yii\db\ActiveRecord
foreach ($this->primaryKey() as $key) {
$pk[$key] = $values[$key] = $this->getAttribute($key);
if ($pk[$key] === null) {
$pk[$key] = $values[$key] = $db->executeCommand('INCR', [static::tableName() . ':s:' . $key]);
$pk[$key] = $values[$key] = $db->executeCommand('INCR', [static::keyPrefix() . ':s:' . $key]);
$this->setAttribute($key, $values[$key]);
}
}
// }
// save pk in a findall pool
$db->executeCommand('RPUSH', [static::tableName(), static::buildKey($pk)]);
$db->executeCommand('RPUSH', [static::keyPrefix(), static::buildKey($pk)]);
$key = static::tableName() . ':a:' . static::buildKey($pk);
$key = static::keyPrefix() . ':a:' . static::buildKey($pk);
// save attributes
$args = [$key];
foreach($values as $attribute => $value) {
@ -150,7 +164,7 @@ class ActiveRecord extends \yii\db\ActiveRecord
foreach(static::fetchPks($condition) as $pk) {
$newPk = $pk;
$pk = static::buildKey($pk);
$key = static::tableName() . ':a:' . $pk;
$key = static::keyPrefix() . ':a:' . $pk;
// save attributes
$args = [$key];
foreach($attributes as $attribute => $value) {
@ -161,13 +175,13 @@ class ActiveRecord extends \yii\db\ActiveRecord
$args[] = $value;
}
$newPk = static::buildKey($newPk);
$newKey = static::tableName() . ':a:' . $newPk;
$newKey = static::keyPrefix() . ':a:' . $newPk;
// rename index if pk changed
if ($newPk != $pk) {
$db->executeCommand('MULTI');
$db->executeCommand('HMSET', $args);
$db->executeCommand('LINSERT', [static::tableName(), 'AFTER', $pk, $newPk]);
$db->executeCommand('LREM', [static::tableName(), 0, $pk]);
$db->executeCommand('LINSERT', [static::keyPrefix(), 'AFTER', $pk, $newPk]);
$db->executeCommand('LREM', [static::keyPrefix(), 0, $pk]);
$db->executeCommand('RENAME', [$key, $newKey]);
$db->executeCommand('EXEC');
} else {
@ -201,7 +215,7 @@ class ActiveRecord extends \yii\db\ActiveRecord
$db = static::getDb();
$n=0;
foreach(static::fetchPks($condition) as $pk) {
$key = static::tableName() . ':a:' . static::buildKey($pk);
$key = static::keyPrefix() . ':a:' . static::buildKey($pk);
foreach($counters as $attribute => $value) {
$db->executeCommand('HINCRBY', [$key, $attribute, $value]);
}
@ -233,8 +247,8 @@ class ActiveRecord extends \yii\db\ActiveRecord
$db->executeCommand('MULTI');
foreach($pks as $pk) {
$pk = static::buildKey($pk);
$db->executeCommand('LREM', [static::tableName(), 0, $pk]);
$attributeKeys[] = static::tableName() . ':a:' . $pk;
$db->executeCommand('LREM', [static::keyPrefix(), 0, $pk]);
$attributeKeys[] = static::keyPrefix() . ':a:' . $pk;
}
if (empty($attributeKeys)) {
$db->executeCommand('EXEC');
@ -292,31 +306,4 @@ class ActiveRecord extends \yii\db\ActiveRecord
}
return md5(json_encode($key));
}
/**
* {@inheritdoc}
*/
public static function getTableSchema()
{
throw new NotSupportedException('getTableSchema() is not supported by redis ActiveRecord.');
}
/**
* {@inheritdoc}
*/
public static function findBySql($sql, $params = [])
{
throw new NotSupportedException('findBySql() is not supported by redis ActiveRecord.');
}
/**
* Returns a value indicating whether the specified operation is transactional in the current [[scenario]].
* This method will always return false as transactional operations are not supported by redis.
* @param integer $operation the operation to check. Possible values are [[OP_INSERT]], [[OP_UPDATE]] and [[OP_DELETE]].
* @return boolean whether the specified operation is transactional in the current [[scenario]].
*/
public function isTransactional($operation)
{
return false;
}
}

14
extensions/redis/Cache.php

@ -105,7 +105,7 @@ class Cache extends \yii\caching\Cache
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function getValue($key)
{
@ -113,7 +113,7 @@ class Cache extends \yii\caching\Cache
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function getValues($keys)
{
@ -127,7 +127,7 @@ class Cache extends \yii\caching\Cache
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function setValue($key, $value, $expire)
{
@ -140,7 +140,7 @@ class Cache extends \yii\caching\Cache
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function setValues($data, $expire)
{
@ -174,7 +174,7 @@ class Cache extends \yii\caching\Cache
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function addValue($key, $value, $expire)
{
@ -187,7 +187,7 @@ class Cache extends \yii\caching\Cache
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function deleteValue($key)
{
@ -195,7 +195,7 @@ class Cache extends \yii\caching\Cache
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function flushValues()
{

16
extensions/redis/LuaScriptBuilder.php

@ -29,7 +29,7 @@ class LuaScriptBuilder extends \yii\base\Object
// TODO add support for orderBy
/** @var ActiveRecord $modelClass */
$modelClass = $query->modelClass;
$key = $this->quoteValue($modelClass::tableName() . ':a:');
$key = $this->quoteValue($modelClass::keyPrefix() . ':a:');
return $this->build($query, "n=n+1 pks[n]=redis.call('HGETALL',$key .. pk)", 'pks');
}
@ -43,7 +43,7 @@ class LuaScriptBuilder extends \yii\base\Object
// TODO add support for orderBy
/** @var ActiveRecord $modelClass */
$modelClass = $query->modelClass;
$key = $this->quoteValue($modelClass::tableName() . ':a:');
$key = $this->quoteValue($modelClass::keyPrefix() . ':a:');
return $this->build($query, "do return redis.call('HGETALL',$key .. pk) end", 'pks');
}
@ -58,7 +58,7 @@ class LuaScriptBuilder extends \yii\base\Object
// TODO add support for orderBy and indexBy
/** @var ActiveRecord $modelClass */
$modelClass = $query->modelClass;
$key = $this->quoteValue($modelClass::tableName() . ':a:');
$key = $this->quoteValue($modelClass::keyPrefix() . ':a:');
return $this->build($query, "n=n+1 pks[n]=redis.call('HGET',$key .. pk," . $this->quoteValue($column) . ")", 'pks');
}
@ -82,7 +82,7 @@ class LuaScriptBuilder extends \yii\base\Object
{
/** @var ActiveRecord $modelClass */
$modelClass = $query->modelClass;
$key = $this->quoteValue($modelClass::tableName() . ':a:');
$key = $this->quoteValue($modelClass::keyPrefix() . ':a:');
return $this->build($query, "n=n+redis.call('HGET',$key .. pk," . $this->quoteValue($column) . ")", 'n');
}
@ -96,7 +96,7 @@ class LuaScriptBuilder extends \yii\base\Object
{
/** @var ActiveRecord $modelClass */
$modelClass = $query->modelClass;
$key = $this->quoteValue($modelClass::tableName() . ':a:');
$key = $this->quoteValue($modelClass::keyPrefix() . ':a:');
return $this->build($query, "n=n+1 if v==nil then v=0 end v=v+redis.call('HGET',$key .. pk," . $this->quoteValue($column) . ")", 'v/n');
}
@ -110,7 +110,7 @@ class LuaScriptBuilder extends \yii\base\Object
{
/** @var ActiveRecord $modelClass */
$modelClass = $query->modelClass;
$key = $this->quoteValue($modelClass::tableName() . ':a:');
$key = $this->quoteValue($modelClass::keyPrefix() . ':a:');
return $this->build($query, "n=redis.call('HGET',$key .. pk," . $this->quoteValue($column) . ") if v==nil or n<v then v=n end", 'v');
}
@ -124,7 +124,7 @@ class LuaScriptBuilder extends \yii\base\Object
{
/** @var ActiveRecord $modelClass */
$modelClass = $query->modelClass;
$key = $this->quoteValue($modelClass::tableName() . ':a:');
$key = $this->quoteValue($modelClass::keyPrefix() . ':a:');
return $this->build($query, "n=redis.call('HGET',$key .. pk," . $this->quoteValue($column) . ") if v==nil or n>v then v=n end", 'v');
}
@ -152,7 +152,7 @@ class LuaScriptBuilder extends \yii\base\Object
/** @var ActiveRecord $modelClass */
$modelClass = $query->modelClass;
$key = $this->quoteValue($modelClass::tableName());
$key = $this->quoteValue($modelClass::keyPrefix());
$loadColumnValues = '';
foreach($columns as $column => $alias) {
$loadColumnValues .= "local $alias=redis.call('HGET',$key .. ':a:' .. pk, '$column')\n";

4
extensions/sphinx/ActiveQuery.php

@ -176,7 +176,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function defaultConnection()
{
@ -201,4 +201,4 @@ class ActiveQuery extends Query implements ActiveQueryInterface
}
return $result;
}
}
}

34
extensions/sphinx/Command.php

@ -197,7 +197,7 @@ class Command extends \yii\db\Command
// Not Supported :
/**
* {@inheritdoc}
* @inheritdoc
*/
public function createTable($table, $columns, $options = null)
{
@ -205,7 +205,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function renameTable($table, $newName)
{
@ -213,7 +213,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function dropTable($table)
{
@ -221,7 +221,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function truncateTable($table)
{
@ -229,7 +229,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function addColumn($table, $column, $type)
{
@ -237,7 +237,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function dropColumn($table, $column)
{
@ -245,7 +245,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function renameColumn($table, $oldName, $newName)
{
@ -253,7 +253,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function alterColumn($table, $column, $type)
{
@ -261,7 +261,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function addPrimaryKey($name, $table, $columns)
{
@ -269,7 +269,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function dropPrimaryKey($name, $table)
{
@ -277,7 +277,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete = null, $update = null)
{
@ -285,7 +285,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function dropForeignKey($name, $table)
{
@ -293,7 +293,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function createIndex($name, $table, $columns, $unique = false)
{
@ -301,7 +301,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function dropIndex($name, $table)
{
@ -309,7 +309,7 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function resetSequence($table, $value = null)
{
@ -317,10 +317,10 @@ class Command extends \yii\db\Command
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function checkIntegrity($check = true, $schema = '')
{
throw new NotSupportedException('"' . __METHOD__ . '" is not supported.');
}
}
}

7
extensions/sphinx/Connection.php

@ -52,9 +52,6 @@ use yii\base\NotSupportedException;
*
* @property string $lastInsertID The row ID of the last row inserted, or the last value retrieved from the
* sequence object. This property is read-only.
* @property Schema $schema The schema information for this Sphinx connection. This property is read-only.
* @property \yii\sphinx\QueryBuilder $queryBuilder The query builder for this Sphinx connection. This property is
* read-only.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
@ -62,7 +59,7 @@ use yii\base\NotSupportedException;
class Connection extends \yii\db\Connection
{
/**
* {@inheritdoc}
* @inheritdoc
*/
public $schemaMap = [
'mysqli' => 'yii\sphinx\Schema', // MySQL
@ -129,4 +126,4 @@ class Connection extends \yii\db\Connection
{
throw new NotSupportedException('"' . __METHOD__ . '" is not supported.');
}
}
}

30
extensions/sphinx/README.md

@ -1,17 +1,7 @@
Yii 2.0 Public Preview - Sphinx Extension
=========================================
Sphinx Extension for Yii 2
==========================
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)
This is the yii2-sphinx extension.
This extension adds [Sphinx](http://sphinxsearch.com/docs) full text search engine extension for the Yii 2 framework.
Installation
@ -20,26 +10,26 @@ Installation
The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
Either run
```
php composer.phar require yiisoft/yii2-sphinx "*"
```
or add
```
```json
"yiisoft/yii2-sphinx": "*"
```
to the require section of your composer.json.
*Note: You might have to run `php composer.phar selfupdate`*
to the require section of your composer.json.
Usage & Documentation
---------------------
This extension adds [Sphinx](http://sphinxsearch.com/docs) full text search engine extension for the Yii framework.
This extension interact with Sphinx search daemon using MySQL protocol and [SphinxQL](http://sphinxsearch.com/docs/current.html#sphinxql) query language.
This extension interacts with Sphinx search daemon using MySQL protocol and [SphinxQL](http://sphinxsearch.com/docs/current.html#sphinxql) query language.
In order to setup Sphinx "searchd" to support MySQL protocol following configuration should be added:
```
searchd
{
@ -115,4 +105,4 @@ $provider = new ActiveDataProvider([
]
]);
$models = $provider->getModels();
```
```

4
extensions/sphinx/composer.json

@ -17,7 +17,6 @@
"email": "klimov.paul@gmail.com"
}
],
"minimum-stability": "dev",
"require": {
"yiisoft/yii2": "*",
"ext-pdo": "*",
@ -25,5 +24,6 @@
},
"autoload": {
"psr-0": { "yii\\sphinx\\": "" }
}
},
"target-dir": "yii/sphinx"
}

2
extensions/swiftmailer/Mailer.php

@ -123,7 +123,7 @@ class Mailer extends BaseMailer
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function sendMessage($message)
{

42
extensions/swiftmailer/Message.php

@ -41,7 +41,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getCharset()
{
@ -49,7 +49,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function setCharset($charset)
{
@ -58,7 +58,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getFrom()
{
@ -66,7 +66,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function setFrom($from)
{
@ -75,7 +75,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getReplyTo()
{
@ -83,7 +83,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function setReplyTo($replyTo)
{
@ -92,7 +92,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getTo()
{
@ -100,7 +100,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function setTo($to)
{
@ -109,7 +109,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getCc()
{
@ -117,7 +117,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function setCc($cc)
{
@ -126,7 +126,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getBcc()
{
@ -134,7 +134,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function setBcc($bcc)
{
@ -143,7 +143,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function getSubject()
{
@ -151,7 +151,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function setSubject($subject)
{
@ -160,7 +160,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function setTextBody($text)
{
@ -169,7 +169,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function setHtmlBody($html)
{
@ -222,7 +222,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function attach($fileName, array $options = [])
{
@ -238,7 +238,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function attachContent($content, array $options = [])
{
@ -254,7 +254,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function embed($fileName, array $options = [])
{
@ -269,7 +269,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function embedContent($content, array $options = [])
{
@ -284,7 +284,7 @@ class Message extends BaseMessage
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function toString()
{

6
framework/CHANGELOG.md

@ -1,7 +1,7 @@
Yii Framework 2 Change Log
==========================
Version 2
---------
Version 2.0 alpha
-----------------
- Initial release.
- Initial release.

27
framework/README.md

@ -1,21 +1,24 @@
Yii 2.0 Public Preview
======================
Yii PHP Framework Version 2
===========================
Thank you for choosing Yii - a high-performance component-based PHP framework.
This is the core framework code of [Yii 2](https://github.com/yiisoft/yii2).
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)
Installation
------------
The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
Either run
REQUIREMENTS
------------
```
php composer.phar require yiisoft/yii2-framework "*"
```
The minimum requirement by Yii is that your Web server supports PHP 5.4.0.
or add
```json
"yiisoft/yii2-framework": "*"
```
to the require section of your composer.json.

17
framework/composer.json

@ -1,6 +1,6 @@
{
"name": "yiisoft/yii2",
"description": "Yii2 Web Programming Framework",
"description": "Yii PHP Framework Version 2",
"keywords": ["yii", "framework"],
"homepage": "http://www.yiiframework.com/",
"type": "library",
@ -39,21 +39,6 @@
"name": "Paul Klimov",
"email": "klimov.paul@gmail.com",
"role": "Core framework development"
},
{
"name": "Wei Zhuo",
"email": "weizhuo@gmail.com",
"role": "Project site maintenance and development"
},
{
"name": "Sebastián Thierer",
"email": "sebas@artfos.com",
"role": "Component development"
},
{
"name": "Jeffrey Winesett",
"email": "jefftulsa@gmail.com",
"role": "Documentation and marketing"
}
],
"support": {

4
framework/yii/assets/yii.js

@ -58,14 +58,14 @@ yii = (function ($) {
changeableSelector: 'select, input, textarea',
/**
* @return string|undefined the CSRF variable name. Undefined is returned is CSRF validation is not enabled.
* @return string|undefined the CSRF variable name. Undefined is returned if CSRF validation is not enabled.
*/
getCsrfVar: function () {
return $('meta[name=csrf-var]').prop('content');
},
/**
* @return string|undefined the CSRF token. Undefined is returned is CSRF validation is not enabled.
* @return string|undefined the CSRF token. Undefined is returned if CSRF validation is not enabled.
*/
getCsrfToken: function () {
return $('meta[name=csrf-token]').prop('content');

9
framework/yii/base/Application.php

@ -23,6 +23,7 @@ use yii\web\HttpException;
* @property \yii\base\Formatter $formatter The formatter application component. This property is read-only.
* @property \yii\i18n\I18N $i18n The internationalization component. This property is read-only.
* @property \yii\log\Logger $log The log component. This property is read-only.
* @property \yii\mail\MailerInterface $mail The mailer interface. This property is read-only.
* @property \yii\web\Request|\yii\console\Request $request The request component. This property is read-only.
* @property string $runtimePath The directory that stores runtime files. Defaults to the "runtime"
* subdirectory under [[basePath]].
@ -199,12 +200,12 @@ abstract class Application extends Module
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function init()
{
parent::init();
$this->initExtensions($this->extensions);
parent::init();
}
/**
@ -634,9 +635,9 @@ abstract class Application extends Module
{
$category = get_class($exception);
if ($exception instanceof HttpException) {
$category .= '\\' . $exception->statusCode;
$category = 'yii\\web\\HttpException:' . $exception->statusCode;
} elseif ($exception instanceof \ErrorException) {
$category .= '\\' . $exception->getSeverity();
$category .= ':' . $exception->getSeverity();
}
Yii::error((string)$exception, $category);
}

12
framework/yii/base/Controller.php

@ -194,7 +194,7 @@ class Controller extends Component implements ViewContextInterface
$actionMap = $this->actions();
if (isset($actionMap[$id])) {
return Yii::createObject($actionMap[$id], $id, $this);
} elseif (preg_match('/^[a-z0-9\\-_]+$/', $id)) {
} elseif (preg_match('/^[a-z0-9\\-_]+$/', $id) && strpos($id, '--') === false && trim($id, '-') === $id) {
$methodName = 'action' . str_replace(' ', '', ucwords(implode(' ', explode('-', $id))));
if (method_exists($this, $methodName)) {
$method = new \ReflectionMethod($this, $methodName);
@ -417,9 +417,13 @@ class Controller extends Component implements ViewContextInterface
$file = $module->getLayoutPath() . DIRECTORY_SEPARATOR . $layout;
}
if (pathinfo($file, PATHINFO_EXTENSION) === '') {
$file .= $view->defaultExtension;
if (pathinfo($file, PATHINFO_EXTENSION) !== '') {
return $file;
}
return $file;
$path = $file . '.' . $view->defaultExtension;
if ($view->defaultExtension !== 'php' && !is_file($path)) {
$path = $file . '.php';
}
return $path;
}
}

11
framework/yii/base/View.php

@ -67,7 +67,7 @@ class View extends Component
/**
* @var string the default view file extension. This will be appended to view file names if they don't have file extensions.
*/
public $defaultExtension = '.php';
public $defaultExtension = 'php';
/**
* @var Theme|array the theme object or the configuration array for creating the theme object.
* If not set, it means theming is not enabled.
@ -171,7 +171,14 @@ class View extends Component
}
}
return pathinfo($file, PATHINFO_EXTENSION) === '' ? $file . $this->defaultExtension : $file;
if (pathinfo($file, PATHINFO_EXTENSION) !== '') {
return $file;
}
$path = $file . '.' . $this->defaultExtension;
if ($this->defaultExtension !== 'php' && !is_file($path)) {
$path = $file . '.php';
}
return $path;
}
/**

5
framework/yii/base/Widget.php

@ -14,7 +14,8 @@ use ReflectionClass;
* Widget is the base class for widgets.
*
* @property string $id ID of the widget.
* @property View $view The view object that can be used to render views or view files.
* @property \yii\web\View $view The view object that can be used to render views or view files. Note that the
* type of this property differs in getter and setter. See [[getView()]] and [[setView()]] for details.
* @property string $viewPath The directory containing the view files for this widget. This property is
* read-only.
*
@ -121,7 +122,7 @@ class Widget extends Component implements ViewContextInterface
* 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.
* @return \yii\web\View the view object that can be used to render views or view files.
*/
public function getView()
{

2
framework/yii/caching/WinCache.php

@ -13,7 +13,7 @@ namespace yii\caching;
* To use this application component, the [WinCache PHP extension](http://www.iis.net/expand/wincacheforphp)
* must be loaded. Also note that "wincache.ucenabled" should be set to "On" in your php.ini file.
*
* See {@link CCache} manual for common cache operations that are supported by WinCache.
* See [[Cache]] manual for common cache operations that are supported by WinCache.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0

7
framework/yii/classes.php

@ -74,13 +74,16 @@ return [
'yii\data\DataProviderInterface' => YII_PATH . '/data/DataProviderInterface.php',
'yii\data\Pagination' => YII_PATH . '/data/Pagination.php',
'yii\data\Sort' => YII_PATH . '/data/Sort.php',
'yii\data\SqlDataProvider' => YII_PATH . '/data/SqlDataProvider.php',
'yii\db\ActiveQuery' => YII_PATH . '/db/ActiveQuery.php',
'yii\db\ActiveQueryInterface' => YII_PATH . '/db/ActiveQueryInterface.php',
'yii\db\ActiveQueryTrait' => YII_PATH . '/db/ActiveQueryTrait.php',
'yii\db\ActiveRecord' => YII_PATH . '/db/ActiveRecord.php',
'yii\db\ActiveRecordInterface' => YII_PATH . '/db/ActiveRecordInterface.php',
'yii\db\ActiveRelation' => YII_PATH . '/db/ActiveRelation.php',
'yii\db\ActiveRelationInterface' => YII_PATH . '/db/ActiveRelationInterface.php',
'yii\db\ActiveRelationTrait' => YII_PATH . '/db/ActiveRelationTrait.php',
'yii\db\BaseActiveRecord' => YII_PATH . '/db/BaseActiveRecord.php',
'yii\db\ColumnSchema' => YII_PATH . '/db/ColumnSchema.php',
'yii\db\Command' => YII_PATH . '/db/Command.php',
'yii\db\Connection' => YII_PATH . '/db/Connection.php',
@ -192,12 +195,14 @@ return [
'yii\validators\ValidationAsset' => YII_PATH . '/validators/ValidationAsset.php',
'yii\validators\Validator' => YII_PATH . '/validators/Validator.php',
'yii\web\AccessControl' => YII_PATH . '/web/AccessControl.php',
'yii\web\AccessDeniedHttpException' => YII_PATH . '/web/AccessDeniedHttpException.php',
'yii\web\AccessRule' => YII_PATH . '/web/AccessRule.php',
'yii\web\Application' => YII_PATH . '/web/Application.php',
'yii\web\AssetBundle' => YII_PATH . '/web/AssetBundle.php',
'yii\web\AssetConverter' => YII_PATH . '/web/AssetConverter.php',
'yii\web\AssetConverterInterface' => YII_PATH . '/web/AssetConverterInterface.php',
'yii\web\AssetManager' => YII_PATH . '/web/AssetManager.php',
'yii\web\BadRequestHttpException' => YII_PATH . '/web/BadRequestHttpException.php',
'yii\web\CacheSession' => YII_PATH . '/web/CacheSession.php',
'yii\web\Controller' => YII_PATH . '/web/Controller.php',
'yii\web\Cookie' => YII_PATH . '/web/Cookie.php',
@ -210,6 +215,8 @@ return [
'yii\web\IdentityInterface' => YII_PATH . '/web/IdentityInterface.php',
'yii\web\JqueryAsset' => YII_PATH . '/web/JqueryAsset.php',
'yii\web\JsExpression' => YII_PATH . '/web/JsExpression.php',
'yii\web\MethodNotAllowedHttpException' => YII_PATH . '/web/MethodNotAllowedHttpException.php',
'yii\web\NotFoundHttpException' => YII_PATH . '/web/NotFoundHttpException.php',
'yii\web\PageCache' => YII_PATH . '/web/PageCache.php',
'yii\web\Request' => YII_PATH . '/web/Request.php',
'yii\web\Response' => YII_PATH . '/web/Response.php',

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

@ -107,11 +107,13 @@ class MessageController extends Controller
@mkdir($dir);
}
foreach ($messages as $category => $msgs) {
$file = str_replace("\\", '/', "$dir/$category.php");
$path = dirname($file);
if (!is_dir($path)) {
mkdir($path, 0755, true);
}
$msgs = array_values(array_unique($msgs));
$this->generateMessageFile($msgs, $dir . DIRECTORY_SEPARATOR . $category . '.php',
$config['overwrite'],
$config['removeUnused'],
$config['sort']);
$this->generateMessageFile($msgs, $file, $config['overwrite'], $config['removeUnused'], $config['sort']);
}
}
}

14
framework/yii/data/ActiveDataProvider.php

@ -86,14 +86,14 @@ class ActiveDataProvider extends BaseDataProvider
parent::init();
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
if (!$this->db instanceof Connection) {
if ($this->db === null) {
throw new InvalidConfigException('The "db" property must be a valid DB Connection application component.');
}
}
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function prepareModels()
{
@ -111,7 +111,7 @@ class ActiveDataProvider extends BaseDataProvider
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function prepareKeys($models)
{
@ -138,9 +138,9 @@ class ActiveDataProvider extends BaseDataProvider
foreach ($models as $model) {
$kk = [];
foreach ($pks as $pk) {
$kk[] = $model[$pk];
$kk[$pk] = $model[$pk];
}
$keys[] = json_encode($kk);
$keys[] = $kk;
}
}
return $keys;
@ -150,7 +150,7 @@ class ActiveDataProvider extends BaseDataProvider
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function prepareTotalCount()
{
@ -162,7 +162,7 @@ class ActiveDataProvider extends BaseDataProvider
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function setSort($value)
{

6
framework/yii/data/ArrayDataProvider.php

@ -66,7 +66,7 @@ class ArrayDataProvider extends BaseDataProvider
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function prepareModels()
{
@ -87,7 +87,7 @@ class ArrayDataProvider extends BaseDataProvider
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function prepareKeys($models)
{
@ -107,7 +107,7 @@ class ArrayDataProvider extends BaseDataProvider
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function prepareTotalCount()
{

160
framework/yii/data/SqlDataProvider.php

@ -0,0 +1,160 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\data;
use Yii;
use yii\base\InvalidConfigException;
use yii\base\Model;
use yii\db\Connection;
/**
* SqlDataProvider implements a data provider based on a plain SQL statement.
*
* SqlDataProvider provides data in terms of arrays, each representing a row of query result.
*
* Like other data providers, SqlDataProvider also supports sorting and pagination.
* It does so by modifying the given [[sql]] statement with "ORDER BY" and "LIMIT"
* clauses. You may configure the [[sort]] and [[pagination]] properties to
* customize sorting and pagination behaviors.
*
* SqlDataProvider may be used in the following way:
*
* ~~~
* $count = Yii::$app->db->createCommand('
* SELECT COUNT(*) FROM tbl_user WHERE status=:status
* ', [':status' => 1])->queryScalar();
*
* $dataProvider = new SqlDataProvider([
* 'sql' => 'SELECT * FROM tbl_user WHERE status=:status',
* 'params' => [':status' => 1],
* 'totalCount' => $count,
* 'sort' => [
* 'attributes' => [
* 'age',
* 'name' => [
* 'asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC],
* 'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC],
* 'default' => SORT_DESC,
* 'label' => 'Name',
* ],
* ],
* ],
* 'pagination' => [
* 'pageSize' => 20,
* ],
* ]);
*
* // get the user records in the current page
* $models = $dataProvider->getModels();
* ~~~
*
* Note: if you want to use the pagination feature, you must configure the [[totalCount]] property
* to be the total number of rows (without pagination). And if you want to use the sorting feature,
* you must configure the [[sort]] property so that the provider knows which columns can be sorted.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class SqlDataProvider extends BaseDataProvider
{
/**
* @var Connection|string the DB connection object or the application component ID of the DB connection.
* If not set, the default DB connection will be used.
*/
public $db;
/**
* @var string the SQL statement to be used for fetching data rows.
*/
public $sql;
/**
* @var array parameters (name=>value) to be bound to the SQL statement.
*/
public $params = [];
/**
* @var string|callable the column that is used as the key of the data models.
* This can be either a column name, or a callable that returns the key value of a given data model.
*
* If this is not set, the keys of the [[models]] array will be used.
*/
public $key;
/**
* Initializes the DB connection component.
* This method will initialize the [[db]] property to make sure it refers to a valid DB connection.
* @throws InvalidConfigException if [[db]] is invalid.
*/
public function init()
{
parent::init();
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
}
if (!$this->db instanceof Connection) {
throw new InvalidConfigException('The "db" property must be a valid DB Connection application component.');
}
if ($this->sql === null) {
throw new InvalidConfigException('The "sql" property must be set.');
}
}
/**
* @inheritdoc
*/
protected function prepareModels()
{
$sql = $this->sql;
$qb = $this->db->getQueryBuilder();
if (($sort = $this->getSort()) !== false) {
$orderBy = $qb->buildOrderBy($sort->getOrders());
if (!empty($orderBy)) {
$orderBy = substr($orderBy, 9);
if (preg_match('/\s+order\s+by\s+[\w\s,\.]+$/i', $sql)) {
$sql .= ', ' . $orderBy;
} else {
$sql .= ' ORDER BY ' . $orderBy;
}
}
}
if (($pagination = $this->getPagination()) !== false) {
$pagination->totalCount = $this->getTotalCount();
$sql .= ' ' . $qb->buildLimit($pagination->getLimit(), $pagination->getOffset());
}
return $this->db->createCommand($sql, $this->params)->queryAll();
}
/**
* @inheritdoc
*/
protected function prepareKeys($models)
{
$keys = [];
if ($this->key !== null) {
foreach ($models as $model) {
if (is_string($this->key)) {
$keys[] = $model[$this->key];
} else {
$keys[] = call_user_func($this->key, $model);
}
}
return $keys;
} else {
return array_keys($models);
}
}
/**
* @inheritdoc
*/
protected function prepareTotalCount()
{
return 0;
}
}

1051
framework/yii/db/ActiveRecord.php

File diff suppressed because it is too large Load Diff

279
framework/yii/db/ActiveRecordInterface.php

@ -0,0 +1,279 @@
<?php
/**
*
*
* @author Carsten Brandt <mail@cebe.cc>
*/
namespace yii\db;
/**
* ActiveRecordInterface
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
interface ActiveRecordInterface
{
/**
* Returns the primary key **name(s)** for this AR class.
*
* Note that an array should be returned even when the record only has a single primary key.
*
* For the primary key **value** see [[getPrimaryKey()]] instead.
*
* @return string[] the primary key name(s) for this AR class.
*/
public static function primaryKey();
/**
* Returns the list of all attribute names of the record.
* @return array list of attribute names.
*/
public function attributes();
/**
* Returns the named attribute value.
* If this record is the result of a query and the attribute is not loaded,
* null will be returned.
* @param string $name the attribute name
* @return mixed the attribute value. Null if the attribute is not set or does not exist.
* @see hasAttribute()
*/
public function getAttribute($name);
/**
* Sets the named attribute value.
* @param string $name the attribute name.
* @param mixed $value the attribute value.
* @see hasAttribute()
*/
public function setAttribute($name, $value);
/**
* Returns a value indicating whether the record has an attribute with the specified name.
* @param string $name the name of the attribute
* @return boolean whether the record has an attribute with the specified name.
*/
public function hasAttribute($name);
/**
* Returns the primary key value(s).
* @param boolean $asArray whether to return the primary key value as an array. If true,
* the return value will be an array with attribute names as keys and attribute values as values.
* Note that for composite primary keys, an array will always be returned regardless of this parameter value.
* @return mixed the primary key value. An array (attribute name => attribute value) is returned if the primary key
* is composite or `$asArray` is true. A string is returned otherwise (null will be returned if
* the key value is null).
*/
public function getPrimaryKey($asArray = false);
/**
* Creates an [[ActiveQueryInterface|ActiveQuery]] instance for query purpose.
*
* This method is usually ment to be used like this:
*
* ```php
* Customer::find(1); // find one customer by primary key
* Customer::find()->all(); // find all customers
* ```
*
* @param mixed $q the query parameter. This can be one of the followings:
*
* - a scalar value (integer or string): query by a single primary key value and return the
* corresponding record.
* - an array of name-value pairs: query by a set of attribute values and return a single record matching all of them.
* - null (not specified): return a new [[ActiveQuery]] object for further query purpose.
*
* @return ActiveQueryInterface|static|null When `$q` is null, a new [[ActiveQuery]] instance
* is returned; when `$q` is a scalar or an array, an ActiveRecord object matching it will be
* returned (null will be returned if there is no matching).
*/
public static function find($q = null);
/**
* Creates an [[ActiveQueryInterface|ActiveQuery]] instance.
* This method is called by [[find()]] to start a SELECT query.
* You may override this method to return a customized query (e.g. `CustomerQuery` specified
* written for querying `Customer` purpose.)
* @return ActiveQueryInterface the newly created [[ActiveQueryInterface|ActiveQuery]] instance.
*/
public static function createQuery();
/**
* Updates records using the provided attribute values and conditions.
* For example, to change the status to be 1 for all customers whose status is 2:
*
* ~~~
* Customer::updateAll(['status' => 1], ['status' => '2']);
* ~~~
*
* @param array $attributes attribute values (name-value pairs) to be saved for the record.
* Unlike [[update()]] these are not going to be validated.
* @param array $condition the condition that matches the records that should get updated.
* Please refer to [[QueryInterface::where()]] on how to specify this parameter.
* An empty condition will match all records.
* @return integer the number of rows updated
*/
public static function updateAll($attributes, $condition = null);
/**
* Deletes records using the provided conditions.
* WARNING: If you do not specify any condition, this method will delete ALL rows in the table.
*
* For example, to delete all customers whose status is 3:
*
* ~~~
* Customer::deleteAll([status = 3]);
* ~~~
*
* @param array $condition the condition that matches the records that should get deleted.
* Please refer to [[QueryInterface::where()]] on how to specify this parameter.
* An empty condition will match all records.
* @return integer the number of rows deleted
*/
public static function deleteAll($condition = null);
/**
* Saves the current record.
*
* This method will call [[insert()]] when [[isNewRecord]] is true, or [[update()]]
* when [[isNewRecord]] is false.
*
* For example, to save a customer record:
*
* ~~~
* $customer = new Customer; // or $customer = Customer::find($id);
* $customer->name = $name;
* $customer->email = $email;
* $customer->save();
* ~~~
*
* @param boolean $runValidation whether to perform validation before saving the record.
* If the validation fails, the record will not be saved to database. `false` will be returned
* in this case.
* @param array $attributes list of attributes that need to be saved. Defaults to null,
* meaning all attributes that are loaded from DB will be saved.
* @return boolean whether the saving succeeds
*/
public function save($runValidation = true, $attributes = null);
/**
* Inserts the record into the database using the attribute values of this record.
*
* Usage example:
*
* ```php
* $customer = new Customer;
* $customer->name = $name;
* $customer->email = $email;
* $customer->insert();
* ```
*
* @param boolean $runValidation whether to perform validation before saving the record.
* If the validation fails, the record will not be inserted into the database.
* @param array $attributes list of attributes that need to be saved. Defaults to null,
* meaning all attributes that are loaded from DB will be saved.
* @return boolean whether the attributes are valid and the record is inserted successfully.
*/
public function insert($runValidation = true, $attributes = null);
/**
* Saves the changes to this active record into the database.
*
* Usage example:
*
* ```php
* $customer = Customer::find($id);
* $customer->name = $name;
* $customer->email = $email;
* $customer->update();
* ```
*
* @param boolean $runValidation whether to perform validation before saving the record.
* If the validation fails, the record will not be inserted into the database.
* @param array $attributes list of attributes that need to be saved. Defaults to null,
* meaning all attributes that are loaded from DB will be saved.
* @return integer|boolean the number of rows affected, or false if validation fails
* or updating process is stopped for other reasons.
* Note that it is possible that the number of rows affected is 0, even though the
* update execution is successful.
*/
public function update($runValidation = true, $attributes = null);
/**
* Deletes the record from the database.
*
* @return integer|boolean the number of rows deleted, or false if the deletion is unsuccessful for some reason.
* Note that it is possible that the number of rows deleted is 0, even though the deletion execution is successful.
*/
public function delete();
/**
* Returns a value indicating whether the current record is new (not saved in the database).
* @return boolean whether the record is new and should be inserted when calling [[save()]].
*/
public function getIsNewRecord();
/**
* Returns a value indicating whether the given active record is the same as the current one.
* Two [[isNewRecord|new]] records are considered to be not equal.
* @param static $record record to compare to
* @return boolean whether the two active records refer to the same row in the same database table.
*/
public function equals($record);
/**
* Creates an [[ActiveRelationInterface|ActiveRelation]] instance.
* This method is called by [[BaseActiveRecord::hasOne()]] and [[BaseActiveRecord::hasMany()]] to
* create a relation instance.
* You may override this method to return a customized relation.
* @param array $config the configuration passed to the ActiveRelation class.
* @return ActiveRelation the newly created [[ActiveRelation]] instance.
*/
public static function createActiveRelation($config = []);
/**
* Returns the relation object with the specified name.
* A relation is defined by a getter method which returns an [[ActiveRelationInterface|ActiveRelation]] object.
* It can be declared in either the ActiveRecord class itself or one of its behaviors.
* @param string $name the relation name
* @return ActiveRelation the relation object
*/
public function getRelation($name);
/**
* Establishes the relationship between two records.
*
* The relationship is established by setting the foreign key value(s) in one record
* to be the corresponding primary key value(s) in the other record.
* The record with the foreign key will be saved into database without performing validation.
*
* If the relationship involves a pivot table, a new row will be inserted into the
* pivot table which contains the primary key values from both records.
*
* This method requires that the primary key value is not null.
*
* @param string $name the case sensitive name of the relationship.
* @param static $model the record to be linked with the current one.
* @param array $extraColumns additional column values to be saved into the pivot table.
* This parameter is only meaningful for a relationship involving a pivot table
* (i.e., a relation set with `[[ActiveRelationInterface::via()]]`.)
*/
public function link($name, $model, $extraColumns = []);
/**
* Destroys the relationship between two records.
*
* The record with the foreign key of the relationship will be deleted if `$delete` is true.
* Otherwise, the foreign key will be set null and the record will be saved without validation.
*
* @param string $name the case sensitive name of the relationship.
* @param static $model the model to be unlinked from the current one.
* @param boolean $delete whether to delete the model that contains the foreign key.
* If false, the model's foreign key will be set null and saved.
* If true, the model containing the foreign key will be deleted.
*/
public function unlink($name, $model, $delete = false);
}

4
framework/yii/db/ActiveRelationTrait.php

@ -104,7 +104,7 @@ trait ActiveRelationTrait
if (count($primaryModels) === 1 && !$this->multiple) {
$model = $this->one();
foreach ($primaryModels as $i => $primaryModel) {
if ($primaryModel instanceof ActiveRecord) {
if ($primaryModel instanceof ActiveRecordInterface) {
$primaryModel->populateRelation($name, $model);
} else {
$primaryModels[$i][$name] = $model;
@ -123,7 +123,7 @@ trait ActiveRelationTrait
foreach ($primaryModels as $i => $primaryModel) {
$key = $this->getModelKey($primaryModel, $link);
$value = isset($buckets[$key]) ? $buckets[$key] : ($this->multiple ? [] : null);
if ($primaryModel instanceof ActiveRecord) {
if ($primaryModel instanceof ActiveRecordInterface) {
$primaryModel->populateRelation($name, $value);
} else {
$primaryModels[$i][$name] = $value;

1229
framework/yii/db/BaseActiveRecord.php

File diff suppressed because it is too large Load Diff

2
framework/yii/db/Migration.php

@ -312,7 +312,7 @@ class Migration extends \yii\base\Component
* Builds and executes a SQL statement for changing the definition of a column.
* @param string $table the table whose column is to be changed. The table name will be properly quoted by the method.
* @param string $column the name of the column to be changed. The name will be properly quoted by the method.
* @param string $type the new column type. The {@link getColumnType} method will be invoked to convert abstract column type (if any)
* @param string $type the new column type. The [[getColumnType()]] method will be invoked to convert abstract column type (if any)
* into the physical one. Anything that is not recognized as abstract type will be kept in the generated SQL.
* For example, 'string' will be turned into 'varchar(255)', while 'string not null' will become 'varchar(255) not null'.
*/

4
framework/yii/db/Query.php

@ -266,6 +266,10 @@ class Query extends Component implements QueryInterface
* Columns can contain table prefixes (e.g. "tbl_user.id") and/or column aliases (e.g. "tbl_user.id AS user_id").
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
*
* Note that if you are selecting an expression like `CONCAT(first_name, ' ', last_name)`, you should
* use an array to specify the columns. Otherwise, the expression may be incorrectly split into several parts.
*
* @param string $option additional option that should be appended to the 'SELECT' keyword. For example,
* in MySQL, the option 'SQL_CALC_FOUND_ROWS' can be used.
* @return static the query object itself

2
framework/yii/db/cubrid/QueryBuilder.php

@ -69,7 +69,7 @@ class QueryBuilder extends \yii\db\QueryBuilder
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function buildLimit($limit, $offset)
{

2
framework/yii/db/mysql/QueryBuilder.php

@ -142,7 +142,7 @@ class QueryBuilder extends \yii\db\QueryBuilder
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function buildLimit($limit, $offset)
{

2
framework/yii/db/sqlite/QueryBuilder.php

@ -255,7 +255,7 @@ class QueryBuilder extends \yii\db\QueryBuilder
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function buildLimit($limit, $offset)
{

34
framework/yii/grid/ActionColumn.php

@ -32,27 +32,27 @@ class ActionColumn extends Column
protected function initDefaultButtons()
{
if (!isset($this->buttons['view'])) {
$this->buttons['view'] = function ($model, $column) {
$this->buttons['view'] = function ($model, $key, $index, $column) {
/** @var ActionColumn $column */
$url = $column->createUrl($model, 'view');
$url = $column->createUrl($model, $key, $index, 'view');
return Html::a('<span class="glyphicon glyphicon-eye-open"></span>', $url, [
'title' => Yii::t('yii', 'View'),
]);
};
}
if (!isset($this->buttons['update'])) {
$this->buttons['update'] = function ($model, $column) {
$this->buttons['update'] = function ($model, $key, $index, $column) {
/** @var ActionColumn $column */
$url = $column->createUrl($model, 'update');
$url = $column->createUrl($model, $key, $index, 'update');
return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, [
'title' => Yii::t('yii', 'Update'),
]);
};
}
if (!isset($this->buttons['delete'])) {
$this->buttons['delete'] = function ($model, $column) {
$this->buttons['delete'] = function ($model, $key, $index, $column) {
/** @var ActionColumn $column */
$url = $column->createUrl($model, 'delete');
$url = $column->createUrl($model, $key, $index, 'delete');
return Html::a('<span class="glyphicon glyphicon-trash"></span>', $url, [
'title' => Yii::t('yii', 'Delete'),
'data-confirm' => Yii::t('yii', 'Are you sure to delete this item?'),
@ -64,34 +64,30 @@ class ActionColumn extends Column
/**
* @param \yii\db\ActiveRecord $model
* @param mixed $key the key associated with the data model
* @param integer $index
* @param string $action
* @return string
*/
public function createUrl($model, $action)
public function createUrl($model, $key, $index, $action)
{
if ($this->urlCreator instanceof Closure) {
return call_user_func($this->urlCreator, $model, $action);
return call_user_func($this->urlCreator, $model, $key, $index, $action);
} else {
$params = $model->getPrimaryKey(true);
if (count($params) === 1) {
$params = ['id' => reset($params)];
}
$params = is_array($key) ? $key : ['id' => $key];
return Yii::$app->controller->createUrl($action, $params);
}
}
/**
* Renders the data cell content.
* @param mixed $model the data model
* @param integer $index the zero-based index of the data model among the models array returned by [[dataProvider]].
* @return string the rendering result
* @inheritdoc
*/
protected function renderDataCellContent($model, $index)
protected function renderDataCellContent($model, $key, $index)
{
return preg_replace_callback('/\\{(\w+)\\}/', function ($matches) use ($model) {
return preg_replace_callback('/\\{(\w+)\\}/', function ($matches) use ($model, $key, $index) {
$name = $matches[1];
if (isset($this->buttons[$name])) {
return call_user_func($this->buttons[$name], $model, $this);
return call_user_func($this->buttons[$name], $model, $key, $index, $this);
} else {
return '';
}

11
framework/yii/grid/CheckboxColumn.php

@ -44,7 +44,7 @@ class CheckboxColumn extends Column
/**
* Renders the header cell content.
* The default implementation simply renders {@link header}.
* The default implementation simply renders [[header]].
* This method may be overridden to customize the rendering of the header cell.
* @return string the rendering result
*/
@ -67,15 +67,12 @@ class CheckboxColumn extends Column
}
/**
* Renders the data cell content.
* @param mixed $model the data model
* @param integer $index the zero-based index of the data model among the models array returned by [[dataProvider]].
* @return string the rendering result
* @inheritdoc
*/
protected function renderDataCellContent($model, $index)
protected function renderDataCellContent($model, $key, $index)
{
if ($this->checkboxOptions instanceof Closure) {
$options = call_user_func($this->checkboxOptions, $model, $index, $this);
$options = call_user_func($this->checkboxOptions, $model, $key, $index, $this);
} else {
$options = $this->checkboxOptions;
}

16
framework/yii/grid/Column.php

@ -71,17 +71,18 @@ class Column extends Object
/**
* Renders a data cell.
* @param mixed $model the data model being rendered
* @param mixed $key the key associated with the data model
* @param integer $index the zero-based index of the data item among the item array returned by [[dataProvider]].
* @return string the rendering result
*/
public function renderDataCell($model, $index)
public function renderDataCell($model, $key, $index)
{
if ($this->contentOptions instanceof Closure) {
$options = call_user_func($this->contentOptions, $model, $index, $this);
$options = call_user_func($this->contentOptions, $model, $key, $index, $this);
} else {
$options = $this->contentOptions;
}
return Html::tag('td', $this->renderDataCellContent($model, $index), $options);
return Html::tag('td', $this->renderDataCellContent($model, $key, $index), $options);
}
/**
@ -94,7 +95,7 @@ class Column extends Object
/**
* Renders the header cell content.
* The default implementation simply renders {@link header}.
* The default implementation simply renders [[header]].
* This method may be overridden to customize the rendering of the header cell.
* @return string the rendering result
*/
@ -105,7 +106,7 @@ class Column extends Object
/**
* Renders the footer cell content.
* The default implementation simply renders {@link footer}.
* The default implementation simply renders [[footer]].
* This method may be overridden to customize the rendering of the footer cell.
* @return string the rendering result
*/
@ -117,13 +118,14 @@ class Column extends Object
/**
* Renders the data cell content.
* @param mixed $model the data model
* @param mixed $key the key associated with the data model
* @param integer $index the zero-based index of the data model among the models array returned by [[dataProvider]].
* @return string the rendering result
*/
protected function renderDataCellContent($model, $index)
protected function renderDataCellContent($model, $key, $index)
{
if ($this->content !== null) {
return call_user_func($this->content, $model, $index, $this);
return call_user_func($this->content, $model, $key, $index, $this);
} else {
return $this->grid->emptyCell;
}

7
framework/yii/grid/DataColumn.php

@ -133,14 +133,17 @@ class DataColumn extends Column
}
}
protected function renderDataCellContent($model, $index)
/**
* @inheritdoc
*/
protected function renderDataCellContent($model, $key, $index)
{
if ($this->value !== null) {
$value = call_user_func($this->value, $model, $index, $this);
} elseif ($this->content === null && $this->attribute !== null) {
$value = ArrayHelper::getValue($model, $this->attribute);
} else {
return parent::renderDataCellContent($model, $index);
return parent::renderDataCellContent($model, $key, $index);
}
return $this->grid->formatter->format($value, $this->format);
}

6
framework/yii/grid/GridView.php

@ -162,7 +162,7 @@ class GridView extends BaseListView
/**
* Initializes the grid view.
* This method will initialize required property values and instantiate {@link columns} objects.
* This method will initialize required property values and instantiate [[columns]] objects.
*/
public function init()
{
@ -366,14 +366,14 @@ class GridView extends BaseListView
$cells = [];
/** @var Column $column */
foreach ($this->columns as $column) {
$cells[] = $column->renderDataCell($model, $index);
$cells[] = $column->renderDataCell($model, $key, $index);
}
if ($this->rowOptions instanceof Closure) {
$options = call_user_func($this->rowOptions, $model, $key, $index, $this);
} else {
$options = $this->rowOptions;
}
$options['data-key'] = $key;
$options['data-key'] = is_array($key) ? json_encode($key) : $key;
return Html::tag('tr', implode('', $cells), $options);
}

7
framework/yii/grid/SerialColumn.php

@ -18,12 +18,9 @@ class SerialColumn extends Column
public $header = '#';
/**
* Renders the data cell content.
* @param mixed $model the data model
* @param integer $index the zero-based index of the data model among the models array returned by [[dataProvider]].
* @return string the rendering result
* @inheritdoc
*/
protected function renderDataCellContent($model, $index)
protected function renderDataCellContent($model, $key, $index)
{
$pagination = $this->grid->dataProvider->getPagination();
if ($pagination !== false) {

8
framework/yii/helpers/BaseConsole.php

@ -142,7 +142,7 @@ class BaseConsole
/**
* Saves the current cursor position by sending ANSI control code SCP to the terminal.
* Position can then be restored with {@link restoreCursorPosition}.
* Position can then be restored with [[restoreCursorPosition()]].
*/
public static function saveCursorPosition()
{
@ -150,7 +150,7 @@ class BaseConsole
}
/**
* Restores the cursor position saved with {@link saveCursorPosition} by sending ANSI control code RCP to the terminal.
* Restores the cursor position saved with [[saveCursorPosition()]] by sending ANSI control code RCP to the terminal.
*/
public static function restoreCursorPosition()
{
@ -159,7 +159,7 @@ class BaseConsole
/**
* Hides the cursor by sending ANSI DECTCEM code ?25l to the terminal.
* Use {@link showCursor} to bring it back.
* Use [[showCursor()]] to bring it back.
* Do not forget to show cursor when your application exits. Cursor might stay hidden in terminal after exit.
*/
public static function hideCursor()
@ -168,7 +168,7 @@ class BaseConsole
}
/**
* Will show a cursor again when it has been hidden by {@link hideCursor} by sending ANSI DECTCEM code ?25h to the terminal.
* Will show a cursor again when it has been hidden by [[hideCursor()]] by sending ANSI DECTCEM code ?25h to the terminal.
*/
public static function showCursor()
{

5
framework/yii/helpers/BaseFileHelper.php

@ -283,6 +283,11 @@ class BaseFileHelper
return $result;
}
}
if (empty($options['except']) && empty($options['only'])) {
return true;
}
$path = str_replace('\\', '/', $path);
if ($isDir = is_dir($path)) {
$path .= '/';

18
framework/yii/helpers/BaseHtml.php

@ -739,6 +739,7 @@ class BaseHtml
* - encode: boolean, whether to HTML-encode the checkbox labels. Defaults to true.
* This option is ignored if `item` option is set.
* - separator: string, the HTML code that separates items.
* - itemOptions: array, the options for generating the radio button tag using [[checkbox()]].
* - item: callable, a callback that can be used to customize the generation of the HTML code
* corresponding to a single item in $items. The signature of this callback must be:
*
@ -758,6 +759,7 @@ class BaseHtml
}
$formatter = isset($options['item']) ? $options['item'] : null;
$itemOptions = isset($options['itemOptions']) ? $options['itemOptions'] : [];
$encode = !isset($options['encode']) || $options['encode'];
$lines = [];
$index = 0;
@ -768,10 +770,10 @@ class BaseHtml
if ($formatter !== null) {
$lines[] = call_user_func($formatter, $index, $label, $name, $checked, $value);
} else {
$lines[] = static::checkbox($name, $checked, [
$lines[] = static::checkbox($name, $checked, array_merge($itemOptions, [
'value' => $value,
'label' => $encode ? static::encode($label) : $label,
]);
]));
}
$index++;
}
@ -786,7 +788,7 @@ class BaseHtml
$separator = isset($options['separator']) ? $options['separator'] : "\n";
$tag = isset($options['tag']) ? $options['tag'] : 'div';
unset($options['tag'], $options['unselect'], $options['encode'], $options['separator'], $options['item']);
unset($options['tag'], $options['unselect'], $options['encode'], $options['separator'], $options['item'], $options['itemOptions']);
return $hidden . static::tag($tag, implode($separator, $lines), $options);
}
@ -797,7 +799,7 @@ class BaseHtml
* @param string $name the name attribute of each radio button.
* @param string|array $selection the selected value(s).
* @param array $items the data item used to generate the radio buttons.
* The array keys are the labels, while the array values are the corresponding radio button values.
* The array values are the labels, while the array keys are the corresponding radio button values.
* @param array $options options (name => config) for the radio button list. The following options are supported:
*
* - unselect: string, the value that should be submitted when none of the radio buttons is selected.
@ -805,6 +807,7 @@ class BaseHtml
* - encode: boolean, whether to HTML-encode the checkbox labels. Defaults to true.
* This option is ignored if `item` option is set.
* - separator: string, the HTML code that separates items.
* - itemOptions: array, the options for generating the radio button tag using [[radio()]].
* - item: callable, a callback that can be used to customize the generation of the HTML code
* corresponding to a single item in $items. The signature of this callback must be:
*
@ -821,6 +824,7 @@ class BaseHtml
{
$encode = !isset($options['encode']) || $options['encode'];
$formatter = isset($options['item']) ? $options['item'] : null;
$itemOptions = isset($options['itemOptions']) ? $options['itemOptions'] : [];
$lines = [];
$index = 0;
foreach ($items as $value => $label) {
@ -830,10 +834,10 @@ class BaseHtml
if ($formatter !== null) {
$lines[] = call_user_func($formatter, $index, $label, $name, $checked, $value);
} else {
$lines[] = static::radio($name, $checked, [
$lines[] = static::radio($name, $checked, array_merge($itemOptions, [
'value' => $value,
'label' => $encode ? static::encode($label) : $label,
]);
]));
}
$index++;
}
@ -847,7 +851,7 @@ class BaseHtml
}
$tag = isset($options['tag']) ? $options['tag'] : 'div';
unset($options['tag'], $options['unselect'], $options['encode'], $options['separator'], $options['item']);
unset($options['tag'], $options['unselect'], $options['encode'], $options['separator'], $options['item'], $options['itemOptions']);
return $hidden . static::tag($tag, implode($separator, $lines), $options);
}

5
framework/yii/log/EmailTarget.php

@ -14,9 +14,8 @@ use yii\mail\MailerInterface;
/**
* EmailTarget sends selected log messages to the specified email addresses.
*
* The target email addresses may be specified via [[emails]] property.
* Optionally, you may set the email [[subject]], [[sentFrom]] address and
* additional [[headers]].
* You may configure the email to be sent by setting the [[message]] property, through which
* you can set the target email addresses, subject, etc.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0

4
framework/yii/mail/BaseMessage.php

@ -18,15 +18,13 @@ use Yii;
*
* @see BaseMailer
*
* @property MailerInterface $mailer The mailer component. This property is read-only.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
abstract class BaseMessage extends Object implements MessageInterface
{
/**
* {@inheritdoc}
* @inheritdoc
*/
public function send(MailerInterface $mailer = null)
{

11
framework/yii/rbac/PhpManager.php

@ -33,13 +33,12 @@ class PhpManager extends Manager
{
/**
* @var string the path of the PHP script that contains the authorization data.
* If not set, it will be using 'protected/data/rbac.php' as the data file.
* Make sure this file is writable by the Web server process if the authorization
* needs to be changed.
* This can be either a file path or a path alias to the file.
* Make sure this file is writable by the Web server process if the authorization needs to be changed online.
* @see loadFromFile()
* @see saveToFile()
*/
public $authFile;
public $authFile = '@app/data/rbac.php';
private $_items = []; // itemName => item
private $_children = []; // itemName, childName => child
@ -53,9 +52,7 @@ class PhpManager extends Manager
public function init()
{
parent::init();
if ($this->authFile === null) {
$this->authFile = Yii::getAlias('@app/data/rbac') . '.php';
}
$this->authFile = Yii::getAlias($this->authFile);
$this->load();
}

3
framework/yii/test/DbFixtureManager.php

@ -11,6 +11,7 @@ use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
use yii\db\ActiveRecord;
use yii\db\ActiveRecordInterface;
use yii\db\Connection;
/**
@ -92,7 +93,7 @@ class DbFixtureManager extends Component
foreach ($fixtures as $name => $fixture) {
if (strpos($fixture, '\\') !== false) {
$model = new $fixture;
if ($model instanceof ActiveRecord) {
if ($model instanceof ActiveRecordInterface) {
$this->_modelClasses[$name] = $fixture;
$fixtures[$name] = $model->getTableSchema()->name;
} else {

2
framework/yii/validators/SafeValidator.php

@ -16,7 +16,7 @@ namespace yii\validators;
class SafeValidator extends Validator
{
/**
* {@inheritdoc}
* @inheritdoc
*/
public function validateAttribute($object, $attribute)
{

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

Loading…
Cancel
Save