Commit c02a6001 by Carsten Brandt

Merge branch 'master' into api-doc-generator

* master: (27 commits) fixed div/0 issue in console progress bar console HelpController use correct script name support table aliases for ActiveQuery::joinWith(). guides fixed/improved CS fix improved fixture controller Added back border to debugger toolbar. #1788 info about retaining the default scenario fixes #1606 Default name and title added to GitHub auth client. added classes to grid, list and detail view fixed basic app travis debugging travis debugging travis added debug toolbar background to have line separators fixed paths in travis.yml reverted 1e4c1eca to get a working debug toolbar fixed issue with too long th columns in debugger enabled acceptance tests for basic application run basic app functional tests within the main repo test chain ...
parents f7e00887 4d99677f
...@@ -13,12 +13,17 @@ services: ...@@ -13,12 +13,17 @@ services:
install: install:
- composer self-update && composer --version - composer self-update && composer --version
# core framework:
# - composer require satooshi/php-coveralls 0.6.* --dev --prefer-dist # - composer require satooshi/php-coveralls 0.6.* --dev --prefer-dist
- composer install --prefer-dist - composer install --prefer-dist
- tests/unit/data/travis/mongodb-setup.sh - tests/unit/data/travis/mongodb-setup.sh
- tests/unit/data/travis/apc-setup.sh - tests/unit/data/travis/apc-setup.sh
- tests/unit/data/travis/memcache-setup.sh - tests/unit/data/travis/memcache-setup.sh
- tests/unit/data/travis/cubrid-setup.sh - tests/unit/data/travis/cubrid-setup.sh
# basic application:
- composer install --dev --prefer-dist -d apps/basic
- cd apps/basic && php vendor/bin/codecept build && cd ../..
- cd apps && php -S localhost:8080 &
before_script: before_script:
- echo 'elasticsearch version ' && curl http://localhost:9200/ - echo 'elasticsearch version ' && curl http://localhost:9200/
...@@ -28,7 +33,9 @@ before_script: ...@@ -28,7 +33,9 @@ before_script:
- mongo yii2test --eval 'db.addUser("travis", "test");' - mongo yii2test --eval 'db.addUser("travis", "test");'
script: script:
- vendor/bin/phpunit --coverage-text --coverage-clover tests/unit/runtime/coveralls/clover.xml --verbose --exclude-group mssql,oci,wincache,xcache,zenddata,vendor # - vendor/bin/phpunit --coverage-clover tests/unit/runtime/coveralls/clover.xml --verbose --exclude-group mssql,oci,wincache,xcache,zenddata,vendor
- vendor/bin/phpunit --verbose --exclude-group mssql,oci,wincache,xcache,zenddata,vendor
- cd apps/basic && php vendor/bin/codecept run
#after_script: #after_script:
# - php vendor/bin/coveralls # - php vendor/bin/coveralls
...@@ -60,6 +60,10 @@ a.desc:after { ...@@ -60,6 +60,10 @@ a.desc:after {
content: "\e156"; content: "\e156";
} }
.grid-view th {
white-space: nowrap;
}
.hint-block { .hint-block {
display: block; display: block;
margin-top: 5px; margin-top: 5px;
......
...@@ -60,6 +60,10 @@ a.desc:after { ...@@ -60,6 +60,10 @@ a.desc:after {
content: "\e156"; content: "\e156";
} }
.grid-view th {
white-space: nowrap;
}
.hint-block { .hint-block {
display: block; display: block;
margin-top: 5px; margin-top: 5px;
......
language: php
php:
- 5.5
- 5.4
install:
- composer require --prefer-dist --dev 'codeception/codeception \*' 'codeception/specify \*'
before_script:
- php vendor/bin/codecept build
script:
- php vendor/bin/codecept run
\ No newline at end of file
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
"require-dev": { "require-dev": {
"yiisoft/yii2-codeception": "*", "yiisoft/yii2-codeception": "*",
"yiisoft/yii2-debug": "*", "yiisoft/yii2-debug": "*",
"yiisoft/yii2-gii": "*" "yiisoft/yii2-gii": "*",
"codeception/codeception": "*",
"codeception/specify": "*"
}, },
"scripts": { "scripts": {
"post-create-project-cmd": [ "post-create-project-cmd": [
......
...@@ -18,7 +18,7 @@ modules: ...@@ -18,7 +18,7 @@ modules:
# - WebDriver # - WebDriver
config: config:
PhpBrowser: PhpBrowser:
url: 'http://localhost' url: 'http://localhost:8080'
# WebDriver: # WebDriver:
# url: 'http://localhost' # url: 'http://localhost'
# browser: firefox # browser: firefox
...@@ -60,6 +60,10 @@ a.desc:after { ...@@ -60,6 +60,10 @@ a.desc:after {
content: "\e156"; content: "\e156";
} }
.grid-view th {
white-space: nowrap;
}
.hint-block { .hint-block {
display: block; display: block;
margin-top: 5px; margin-top: 5px;
......
This folder contains official Yii 2 guides documentation.
To add new guide, take the following steps:
1. Create `guide-name` and put there relevant documentation;
2. If guide has more then one word in name, then it should be with dashes, like: `console-fixture.md`, `module-debug.md`;
3. If your guide is for console commands, than its name should follow convention: `console-{command}.md`;
4. If your guide is for custom modules, than its name should follow convention: `module-{moduleName}.md`.
Database Fixtures
=================
Fixtures are important part of testing. Their main purpose is to populate you with data that needed by testing
different cases. With this data using your tests becoming more efficient and useful.
Yii supports database fixtures via the `yii fixture` command line tool. This tool supports:
* Applying new fixtures to database tables;
* Clearing, database tables (with sequences);
* Auto-generating fixtures and populating it with random data.
Fixtures format
---------------
Fixtures are just plain php files returning array. These files are usually stored under `@tests/unit/fixtures` path, but it
can be [configured](#configure-command-globally) in other way. Example of fixture file:
```
#users.php file under fixtures path
return [
[
'name' => 'Chase',
'login' => 'lmayert',
'email' => 'strosin.vernice@jerde.com',
'auth_key' => 'K3nF70it7tzNsHddEiq0BZ0i-OU8S3xV',
'password' => '$2y$13$WSyE5hHsG1rWN2jV8LRHzubilrCLI5Ev/iK0r3jRuwQEs2ldRu.a2',
],
[
'name' => 'Celestine',
'login' => 'napoleon69',
'email' => 'aileen.barton@heaneyschumm.com',
'auth_key' => 'dZlXsVnIDgIzFgX4EduAqkEPuphhOh9q',
'password' => '$2y$13$kkgpvJ8lnjKo8RuoR30ay.RjDf15bMcHIF7Vz1zz/6viYG5xJExU6',
],
];
```
This data will be loaded to the `users`, but before it will be loaded table `users` will be cleared: all data deleted, sequence reseted.
Above fixture example was auto-generated by `yii2-faker` extension, read more about it in these [section](#auto-generating-fixtures).
Applying fixtures
-----------------
To apply fixture to the table, run the following command:
```
yii fixture/apply <tbl_name>
```
The required `tbl_name` parameter specifies a database table to which data will be loaded. You can load data to several tables at once.
Below are correct formats of this command:
```
// apply fixtures to the "users" table of database
yii fixture/apply users
// same as above, because default action of "fixture" command is "apply"
yii fixture users
// apply several fixtures to several tables. Note that there should not be any whitespace between ",", it should be one string.
yii fixture users,users_profiles
// apply all fixtures
yii fixture/apply all
// same as above
yii fixture all
// apply fixtures to the table users, but fixtures will be taken from different path.
yii fixture users --fixturePath='@app/my/custom/path/to/fixtures'
// apply fixtures to the table users, but for other database connection.
yii fixtures users --db='customDbConnectionId'
```
Clearing tables
---------------
To clear table, run the following command:
```
// clear given table: delete all data and reset sequence.
yii fixture/clear users
// clear several tables. Note that there should not be any whitespace between ",", it should be one string.
yii fixture/clear users,users_profile
// clear all tables of current connection in current schema
yii fixture/clear all
```
Configure Command Globally
--------------------------
While command line options allow us to configure the migration command
on-the-fly, sometimes we may want to configure the command once for all. For example you can configure
different migration path as follows:
```
'controllerMap' => [
'fixture' => [
'class' => 'yii\console\FixtureController',
'fixturePath' => '@app/my/custom/path/to/fixtures',
'db' => 'customDbConnectionId',
],
]
```
Auto-generating fixtures
------------------------
Yii also can auto-generate fixtures for you based on some template. You can generate your fixtures with different data on different languages and formats.
These feature is done by [Faker](https://github.com/fzaninotto/Faker) library and `yii2-faker` extension.
See extension [guide](https://github.com/yiisoft/yii2/tree/master/extensions/yii/faker) for more docs.
...@@ -32,13 +32,13 @@ Database ...@@ -32,13 +32,13 @@ Database
- [Basics](database-basics.md) - Connecting to a database, basic queries, transactions and schema manipulation - [Basics](database-basics.md) - Connecting to a database, basic queries, transactions and schema manipulation
- [Query Builder](query-builder.md) - Querying the database using a simple abstraction layer - [Query Builder](query-builder.md) - Querying the database using a simple abstraction layer
- [ActiveRecord](active-record.md) - The active record ORM, retrieving and manipulatings records and defining relations - [ActiveRecord](active-record.md) - The active record ORM, retrieving and manipulatings records and defining relations
- [Database Migration](migration.md) - Versioning your database with database migrations - [Database Migration](console-migrate.md) - Versioning your database with database migrations
Developers Toolbox Developers Toolbox
================== ==================
- [Automatic Code Generation](gii.md) - [Automatic Code Generation](gii.md)
- [Debug toolbar and debugger](debugger.md) - [Debug toolbar and debugger](module-debug.md)
- [Error Handling](error.md) - [Error Handling](error.md)
- [Logging](logging.md) - [Logging](logging.md)
......
...@@ -81,6 +81,8 @@ If you are using Linux you can create a hard link to make it accessable, using t ...@@ -81,6 +81,8 @@ If you are using Linux you can create a hard link to make it accessable, using t
ln requirements.php ../requirements.php ln requirements.php ../requirements.php
``` ```
For the advanded app the `requirements.php` is two levels up so you have to use `ln requirements.php ../../requirements.php`.
Yii 2 requires PHP 5.4.0 or higher. Yii has been tested with the [Apache HTTP server](http://httpd.apache.org/) and Yii 2 requires PHP 5.4.0 or higher. Yii has been tested with the [Apache HTTP server](http://httpd.apache.org/) and
[Nginx HTTP server](http://nginx.org/) on Windows and Linux. [Nginx HTTP server](http://nginx.org/) on Windows and Linux.
Yii may also be usable on other web servers and platforms, provided that PHP 5.4 or higher is supported. Yii may also be usable on other web servers and platforms, provided that PHP 5.4 or higher is supported.
......
...@@ -112,6 +112,21 @@ class User extends \yii\db\ActiveRecord ...@@ -112,6 +112,21 @@ class User extends \yii\db\ActiveRecord
} }
``` ```
If you want to keep the default scenario available besides your own scenarios, use inheritance to include it:
```php
class User extends \yii\db\ActiveRecord
{
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['login'] = ['username', 'password'];
$scenarios['register'] = ['username', 'email', 'password'];
return $scenarios;
}
}
```
Sometimes, we want to mark an attribute as not safe for massive assignment (but we still want the attribute to be validated). Sometimes, we want to mark an attribute as not safe for massive assignment (but we still want the attribute to be validated).
We may do so by prefixing an exclamation character to the attribute name when declaring it in `scenarios()`. For example: We may do so by prefixing an exclamation character to the attribute name when declaring it in `scenarios()`. For example:
......
...@@ -73,4 +73,20 @@ class GitHub extends OAuth2 ...@@ -73,4 +73,20 @@ class GitHub extends OAuth2
{ {
return $this->api('user', 'GET'); return $this->api('user', 'GET');
} }
/**
* @inheritdoc
*/
protected function defaultName()
{
return 'github';
}
/**
* @inheritdoc
*/
protected function defaultTitle()
{
return 'GitHub';
}
} }
\ No newline at end of file
body {
padding-top: 62px;
}
span.indent { span.indent {
color: #ccc; color: #ccc;
} }
...@@ -28,12 +24,12 @@ ul.trace { ...@@ -28,12 +24,12 @@ ul.trace {
float: right; float: right;
} }
td { td, th {
white-space: pre-line; white-space: pre-line;
word-wrap: break-word; word-wrap: break-word;
} }
th { .detail-grid-view th {
white-space: nowrap; white-space: nowrap;
} }
......
#yii-debug-toolbar { #yii-debug-toolbar {
position: fixed;
left: 0;
right: 0;
z-index: 1000000;
padding: 0; padding: 0;
font: 11px Verdana, Arial, sans-serif; font: 11px Verdana, Arial, sans-serif;
text-align: left; text-align: left;
min-height: 40px; min-height: 40px;
overflow: auto; overflow: auto;
background: rgb(237,237,237); background: rgb(246,246,246);
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2VkZWRlZCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjUzJSIgc3RvcC1jb2xvcj0iI2Y2ZjZmNiIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
background: -moz-linear-gradient(top, rgba(237,237,237,1) 0%, rgba(246,246,246,1) 53%, rgba(255,255,255,1) 100%); background: -moz-linear-gradient(top, rgba(237,237,237,1) 0%, rgba(246,246,246,1) 53%, rgba(255,255,255,1) 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(237,237,237,1)), color-stop(53%,rgba(246,246,246,1)), color-stop(100%,rgba(255,255,255,1))); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(237,237,237,1)), color-stop(53%,rgba(246,246,246,1)), color-stop(100%,rgba(255,255,255,1)));
background: -webkit-linear-gradient(top, rgba(237,237,237,1) 0%,rgba(246,246,246,1) 53%,rgba(255,255,255,1) 100%); background: -webkit-linear-gradient(top, rgba(237,237,237,1) 0%,rgba(246,246,246,1) 53%,rgba(255,255,255,1) 100%);
...@@ -17,18 +12,21 @@ ...@@ -17,18 +12,21 @@
background: -ms-linear-gradient(top, rgba(237,237,237,1) 0%,rgba(246,246,246,1) 53%,rgba(255,255,255,1) 100%); background: -ms-linear-gradient(top, rgba(237,237,237,1) 0%,rgba(246,246,246,1) 53%,rgba(255,255,255,1) 100%);
background: linear-gradient(to bottom, rgba(237,237,237,1) 0%,rgba(246,246,246,1) 53%,rgba(255,255,255,1) 100%); background: linear-gradient(to bottom, rgba(237,237,237,1) 0%,rgba(246,246,246,1) 53%,rgba(255,255,255,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ededed', endColorstr='#ffffff',GradientType=0 ); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ededed', endColorstr='#ffffff',GradientType=0 );
background: rgb(246,246,246) url(data:image/svg+xml;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAoCAYAAAA/tpB3AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94BBQwuINct3v0AAAAjSURBVAjXY3j79u1/JgYGBgYkgpGRkYEYMSpKUGLK+/fvGQAaDAb6F86IsAAAAABJRU5ErkJggg==); /* generated using "cat assets/bg.png | base64" */
} }
.yii-debug-toolbar-top { .yii-debug-toolbar-top {
top: 0;
margin: 0 0 20px 0; margin: 0 0 20px 0;
height: 42px;
border-bottom: 1px solid #e4e4e4; border-bottom: 1px solid #e4e4e4;
} }
.yii-debug-toolbar-bottom { .yii-debug-toolbar-bottom {
position: fixed;
left: 0;
right: 0;
bottom: 0; bottom: 0;
margin: 0; margin: 0;
z-index: 1000000;
border-top: 1px solid #ccc; border-top: 1px solid #ccc;
} }
......
...@@ -9,6 +9,7 @@ use yii\grid\GridView; ...@@ -9,6 +9,7 @@ use yii\grid\GridView;
echo GridView::widget([ echo GridView::widget([
'dataProvider' => $dataProvider, 'dataProvider' => $dataProvider,
'id' => 'db-panel-detailed-grid', 'id' => 'db-panel-detailed-grid',
'options' => ['class' => 'detail-grid-view'],
'filterModel' => $searchModel, 'filterModel' => $searchModel,
'filterUrl' => $panel->getUrl(), 'filterUrl' => $panel->getUrl(),
'columns' => [ 'columns' => [
......
...@@ -10,6 +10,7 @@ use yii\log\Logger; ...@@ -10,6 +10,7 @@ use yii\log\Logger;
echo GridView::widget([ echo GridView::widget([
'dataProvider' => $dataProvider, 'dataProvider' => $dataProvider,
'id' => 'log-panel-detailed-grid', 'id' => 'log-panel-detailed-grid',
'options' => ['class' => 'detail-grid-view'],
'filterModel' => $searchModel, 'filterModel' => $searchModel,
'filterUrl' => $panel->getUrl(), 'filterUrl' => $panel->getUrl(),
'rowOptions' => function ($model, $key, $index, $grid) { 'rowOptions' => function ($model, $key, $index, $grid) {
...@@ -43,7 +44,6 @@ echo GridView::widget([ ...@@ -43,7 +44,6 @@ echo GridView::widget([
Logger::LEVEL_INFO => ' Info ', Logger::LEVEL_INFO => ' Info ',
Logger::LEVEL_WARNING => ' Warning ', Logger::LEVEL_WARNING => ' Warning ',
Logger::LEVEL_ERROR => ' Error ', Logger::LEVEL_ERROR => ' Error ',
Logger::LEVEL_PROFILE => ' Profile ',
], ],
], ],
'category', 'category',
......
...@@ -8,6 +8,7 @@ use yii\helpers\Html; ...@@ -8,6 +8,7 @@ use yii\helpers\Html;
echo GridView::widget([ echo GridView::widget([
'dataProvider' => $dataProvider, 'dataProvider' => $dataProvider,
'id' => 'profile-panel-detailed-grid', 'id' => 'profile-panel-detailed-grid',
'options' => ['class' => 'detail-grid-view'],
'filterModel' => $searchModel, 'filterModel' => $searchModel,
'filterUrl' => $panel->getUrl(), 'filterUrl' => $panel->getUrl(),
'columns' => [ 'columns' => [
......
...@@ -104,7 +104,7 @@ will be created under the fixtures path (by default ```@tests/unit/fixtures```) ...@@ -104,7 +104,7 @@ will be created under the fixtures path (by default ```@tests/unit/fixtures```)
You can generate fixtures for all templates by specifying keyword ```all```. You can generate fixtures for all templates by specifying keyword ```all```.
```php ```php
php yii fixture/generate all_fixtures php yii fixture/generate all
``` ```
This command will generate fixtures for all template files that are stored under template path and This command will generate fixtures for all template files that are stored under template path and
......
...@@ -10,6 +10,7 @@ namespace yii\console\controllers; ...@@ -10,6 +10,7 @@ namespace yii\console\controllers;
use Yii; use Yii;
use yii\console\Controller; use yii\console\Controller;
use yii\console\Exception; use yii\console\Exception;
use yii\helpers\FileHelper;
use yii\test\DbTestTrait; use yii\test\DbTestTrait;
use yii\helpers\Console; use yii\helpers\Console;
...@@ -55,6 +56,11 @@ class FixtureController extends Controller ...@@ -55,6 +56,11 @@ class FixtureController extends Controller
use DbTestTrait; use DbTestTrait;
/** /**
* type of fixture apply to database
*/
const APPLY_ALL = 'all';
/**
* @var string controller default action ID. * @var string controller default action ID.
*/ */
public $defaultAction = 'apply'; public $defaultAction = 'apply';
...@@ -110,14 +116,41 @@ class FixtureController extends Controller ...@@ -110,14 +116,41 @@ class FixtureController extends Controller
throw new Exception('Fixture manager is not configured properly. Please refer to official documentation for this purposes.'); throw new Exception('Fixture manager is not configured properly. Please refer to official documentation for this purposes.');
} }
if (!$this->confirmApply($fixtures)) { $foundFixtures = $this->findFixtures($fixtures);
if (!$this->needToApplyAll($fixtures[0])) {
$notFoundFixtures = array_diff($fixtures, $foundFixtures);
if ($notFoundFixtures) {
$this->notifyNotFound($notFoundFixtures);
}
}
if (!$foundFixtures) {
throw new Exception("No files were found by name: \"" . implode(', ', $fixtures) . "\".\n"
. "Check that fixtures with these name exists, under fixtures path: \n\"" . Yii::getAlias($this->fixturePath) . "\"."
);
}
if (!$this->confirmApply($foundFixtures)) {
return; return;
} }
$this->getFixtureManager()->basePath = $this->fixturePath; $this->getFixtureManager()->basePath = $this->fixturePath;
$this->getFixtureManager()->db = $this->db; $this->getFixtureManager()->db = $this->db;
$this->loadFixtures($fixtures);
$this->notifySuccess($fixtures); $transaction = Yii::$app->db->beginTransaction();
try {
$this->loadFixtures($foundFixtures);
$transaction->commit();
} catch (\Exception $e) {
$transaction->rollback();
$this->stdout("Exception occured, transaction rollback. Tables will be in same state.\n", Console::BG_RED);
throw $e;
}
$this->notifySuccess($foundFixtures);
} }
/** /**
...@@ -128,13 +161,32 @@ class FixtureController extends Controller ...@@ -128,13 +161,32 @@ class FixtureController extends Controller
*/ */
public function actionClear(array $tables) public function actionClear(array $tables)
{ {
if ($this->needToApplyAll($tables[0])) {
$tables = $this->getDbConnection()->schema->getTableNames();
}
if (!$this->confirmClear($tables)) { if (!$this->confirmClear($tables)) {
return; return;
} }
$transaction = Yii::$app->db->beginTransaction();
try {
$this->getDbConnection()->createCommand()->checkIntegrity(false)->execute();
foreach($tables as $table) { foreach($tables as $table) {
$this->getDbConnection()->createCommand()->truncateTable($table)->execute(); $this->getDbConnection()->createCommand()->truncateTable($table)->execute();
$this->stdout("Table \"{$table}\" was successfully cleared. \n", Console::FG_GREEN); $this->getDbConnection()->createCommand()->resetSequence($table)->execute();
$this->stdout(" Table \"{$table}\" was successfully cleared. \n", Console::FG_GREEN);
}
$this->getDbConnection()->createCommand()->checkIntegrity(true)->execute();
$transaction->commit();
} catch (\Exception $e) {
$transaction->rollback();
$this->stdout("Exception occured, transaction rollback. Tables will be in same state.\n", Console::BG_RED);
throw $e;
} }
} }
...@@ -180,6 +232,18 @@ class FixtureController extends Controller ...@@ -180,6 +232,18 @@ class FixtureController extends Controller
} }
/** /**
* Notifies user that fixtures were not found under fixtures path.
* @param array $fixtures
*/
private function notifyNotFound($fixtures)
{
$this->stdout("Some fixtures were not found under path:\n", Console::BG_RED);
$this->stdout(Yii::getAlias($this->fixturePath) . "\n\n", Console::FG_GREEN);
$this->outputList($fixtures);
$this->stdout("\n");
}
/**
* Prompts user with confirmation if fixtures should be loaded. * Prompts user with confirmation if fixtures should be loaded.
* @param array $fixtures * @param array $fixtures
* @return boolean * @return boolean
...@@ -211,7 +275,47 @@ class FixtureController extends Controller ...@@ -211,7 +275,47 @@ class FixtureController extends Controller
private function outputList($data) private function outputList($data)
{ {
foreach($data as $index => $item) { foreach($data as $index => $item) {
$this->stdout(($index + 1) . ". {$item}\n", Console::FG_GREEN); $this->stdout(" " . ($index + 1) . ". {$item}\n", Console::FG_GREEN);
} }
} }
/**
* Checks if needed to apply all fixtures.
* @param string $fixture
* @return bool
*/
public function needToApplyAll($fixture)
{
return $fixture == self::APPLY_ALL;
}
/**
* Returns array of found fixtures. These may differer from input parameter as not all fixtures may exists.
* @param array $fixtures
*/
private function findFixtures(array $fixtures)
{
$fixturesPath = Yii::getAlias($this->fixturePath);
$files = [];
if ($this->needToApplyAll($fixtures[0])) {
$files = FileHelper::findFiles($fixturesPath, ['only' => ['.php']]);
} else {
$filesToSearch = [];
foreach ($fixtures as $fileName) {
$filesToSearch[] = $fileName . '.php';
}
$files = FileHelper::findFiles($fixturesPath, ['only' => $filesToSearch]);
}
$foundFixtures = [];
foreach($files as $fixture) {
$foundFixtures[] = basename($fixture , '.php');
}
return $foundFixtures;
}
} }
...@@ -42,11 +42,6 @@ class HelpController extends Controller ...@@ -42,11 +42,6 @@ class HelpController extends Controller
* Displays available commands or the detailed information * Displays available commands or the detailed information
* about a particular command. For example, * about a particular command. For example,
* *
* ~~~
* yii help # list available commands
* yii help message # display help info about "message"
* ~~~
*
* @param string $command The name of the command to show help about. * @param string $command The name of the command to show help about.
* If not provided, all available commands will be displayed. * If not provided, all available commands will be displayed.
* @return integer the exit status * @return integer the exit status
...@@ -149,8 +144,9 @@ class HelpController extends Controller ...@@ -149,8 +144,9 @@ class HelpController extends Controller
foreach ($commands as $command) { foreach ($commands as $command) {
echo "- " . $this->ansiFormat($command, Console::FG_YELLOW) . "\n"; echo "- " . $this->ansiFormat($command, Console::FG_YELLOW) . "\n";
} }
$scriptName = $this->getScriptName();
$this->stdout("\nTo see the help of each command, enter:\n", Console::BOLD); $this->stdout("\nTo see the help of each command, enter:\n", Console::BOLD);
echo "\n yii " . $this->ansiFormat('help', Console::FG_YELLOW) . ' ' echo "\n $scriptName " . $this->ansiFormat('help', Console::FG_YELLOW) . ' '
. $this->ansiFormat('<command-name>', Console::FG_CYAN) . "\n\n"; . $this->ansiFormat('<command-name>', Console::FG_CYAN) . "\n\n";
} else { } else {
$this->stdout("\nNo commands are found.\n\n", Console::BOLD); $this->stdout("\nNo commands are found.\n\n", Console::BOLD);
...@@ -189,8 +185,9 @@ class HelpController extends Controller ...@@ -189,8 +185,9 @@ class HelpController extends Controller
} }
echo "\n"; echo "\n";
} }
$scriptName = $this->getScriptName();
echo "\nTo see the detailed information about individual sub-commands, enter:\n"; echo "\nTo see the detailed information about individual sub-commands, enter:\n";
echo "\n yii " . $this->ansiFormat('help', Console::FG_YELLOW) . ' ' echo "\n $scriptName " . $this->ansiFormat('help', Console::FG_YELLOW) . ' '
. $this->ansiFormat('<sub-command>', Console::FG_CYAN) . "\n\n"; . $this->ansiFormat('<sub-command>', Console::FG_CYAN) . "\n\n";
} }
} }
...@@ -261,10 +258,11 @@ class HelpController extends Controller ...@@ -261,10 +258,11 @@ class HelpController extends Controller
} }
$this->stdout("\nUSAGE\n\n", Console::BOLD); $this->stdout("\nUSAGE\n\n", Console::BOLD);
$scriptName = $this->getScriptName();
if ($action->id === $controller->defaultAction) { if ($action->id === $controller->defaultAction) {
echo 'yii ' . $this->ansiFormat($controller->getUniqueId(), Console::FG_YELLOW); echo $scriptName . ' ' . $this->ansiFormat($controller->getUniqueId(), Console::FG_YELLOW);
} else { } else {
echo 'yii ' . $this->ansiFormat($action->getUniqueId(), Console::FG_YELLOW); echo $scriptName . ' ' . $this->ansiFormat($action->getUniqueId(), Console::FG_YELLOW);
} }
list ($required, $optional) = $this->getArgHelps($method, isset($tags['param']) ? $tags['param'] : []); list ($required, $optional) = $this->getArgHelps($method, isset($tags['param']) ? $tags['param'] : []);
foreach ($required as $arg => $description) { foreach ($required as $arg => $description) {
...@@ -425,4 +423,12 @@ class HelpController extends Controller ...@@ -425,4 +423,12 @@ class HelpController extends Controller
$name = $required ? "$name (required)" : $name; $name = $required ? "$name (required)" : $name;
return $doc === '' ? $name : "$name: $doc"; return $doc === '' ? $name : "$name: $doc";
} }
/**
* @return string the name of the cli script currently running.
*/
protected function getScriptName()
{
return basename(Yii::$app->request->scriptFile);
}
} }
...@@ -326,19 +326,27 @@ class ActiveQuery extends Query implements ActiveQueryInterface ...@@ -326,19 +326,27 @@ class ActiveQuery extends Query implements ActiveQueryInterface
} }
/** /**
* Returns the table name used by the specified active query. * Returns the table alias (or table name) that can be used to prefix column names.
* @param ActiveQuery $query * @param ActiveQuery $query
* @return string the table name * @return string the table alias (or table name) enclosed within double curly brackets.
*/ */
private function getQueryTableName($query) private function getQueryTableAlias($query)
{ {
if (empty($query->from)) { if (empty($query->from)) {
/** @var ActiveRecord $modelClass */ /** @var ActiveRecord $modelClass */
$modelClass = $query->modelClass; $modelClass = $query->modelClass;
return $modelClass::tableName(); $tableName = $modelClass::tableName();
} else { } else {
return reset($query->from); $tableName = reset($query->from);
}
if (preg_match('/^(.*?)\s+({{\w+}}|\w+)$/', $tableName, $matches)) {
$tableName = $matches[2];
}
if (strpos($tableName, '{{') === false) {
$tableName = '{{' . $tableName . '}}';
} }
return $tableName;
} }
/** /**
...@@ -364,15 +372,8 @@ class ActiveQuery extends Query implements ActiveQueryInterface ...@@ -364,15 +372,8 @@ class ActiveQuery extends Query implements ActiveQueryInterface
return; return;
} }
$parentTable = $this->getQueryTableName($parent); $parentTable = $this->getQueryTableAlias($parent);
$childTable = $this->getQueryTableName($child); $childTable = $this->getQueryTableAlias($child);
if (strpos($parentTable, '{{') === false) {
$parentTable = '{{' . $parentTable . '}}';
}
if (strpos($childTable, '{{') === false) {
$childTable = '{{' . $childTable . '}}';
}
if (!empty($child->link)) { if (!empty($child->link)) {
$on = []; $on = [];
......
...@@ -49,6 +49,11 @@ class GridView extends BaseListView ...@@ -49,6 +49,11 @@ class GridView extends BaseListView
*/ */
public $tableOptions = ['class' => 'table table-striped table-bordered']; public $tableOptions = ['class' => 'table table-striped table-bordered'];
/** /**
* @var array the HTML attributes for the container tag of the grid view.
* The "tag" element specifies the tag name of the container element and defaults to "div".
*/
public $options = ['class' => 'grid-view'];
/**
* @var array the HTML attributes for the table header row * @var array the HTML attributes for the table header row
*/ */
public $headerRowOptions = []; public $headerRowOptions = [];
......
...@@ -861,7 +861,7 @@ class BaseConsole ...@@ -861,7 +861,7 @@ class BaseConsole
} }
$width -= mb_strlen($prefix); $width -= mb_strlen($prefix);
$percent = $done / $total; $percent = ($total == 0) ? 1 : $done / $total;
$info = sprintf("%d%% (%d/%d)", $percent * 100, $done, $total); $info = sprintf("%d%% (%d/%d)", $percent * 100, $done, $total);
if ($done > $total || $done == 0) { if ($done > $total || $done == 0) {
......
...@@ -90,7 +90,7 @@ class DetailView extends Widget ...@@ -90,7 +90,7 @@ class DetailView extends Widget
* @var array the HTML attributes for the container tag of this widget. The "tag" option specifies * @var array the HTML attributes for the container tag of this widget. The "tag" option specifies
* what container tag should be used. It defaults to "table" if not set. * what container tag should be used. It defaults to "table" if not set.
*/ */
public $options = ['class' => 'table table-striped table-bordered']; public $options = ['class' => 'table table-striped table-bordered detail-view'];
/** /**
* @var array|Formatter the formatter used to format model attribute values into displayable texts. * @var array|Formatter the formatter used to format model attribute values into displayable texts.
* This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]] * This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]]
......
...@@ -52,6 +52,11 @@ class ListView extends BaseListView ...@@ -52,6 +52,11 @@ class ListView extends BaseListView
* @var string the HTML code to be displayed between any two consecutive items. * @var string the HTML code to be displayed between any two consecutive items.
*/ */
public $separator = "\n"; public $separator = "\n";
/**
* @var array the HTML attributes for the container tag of the list view.
* The "tag" element specifies the tag name of the container element and defaults to "div".
*/
public $options = ['class' => 'list-view'];
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment