Commit 62378c3b by Carsten Brandt

Merge branch 'master' into apidoc-refactoring

* master: (153 commits) rest doc. CS fix Add size attribute to Modal major features and documentation finished for REST API. rest WIP Removed U+FEFF character from pt-PT language file to fixe #2631 Revert "Used ternary operator instead of "or" for constant definition" `User` here REST wip. Changelog reset access cache when user identity is set Keyboard shortcut for previous, next and refresh buttons reset batch query result when rewinding. fixed loading namespaceless controller classes. Fixes #1467: Added support for organizing controllers in subdirectories replace pjax with external resouce via composer fixed > 100 typos introduced by me :-) fixed condition for HHVM test fixed phpdoc updated phpdoc references of BaseAR to the interface ... Conflicts: extensions/apidoc/templates/BaseRenderer.php extensions/apidoc/templates/html/views/constSummary.php extensions/apidoc/templates/html/views/propertyDetails.php
parents 023f4d0a 2c1bd7f2
......@@ -4,7 +4,14 @@ php:
- 5.4
- 5.5
- 5.6
# - hhvm # commented until composer or hhvm get fixed: https://github.com/facebook/hhvm/issues/1347
- hhvm
# run build against PHP 5.6 and hhvm but allow them to fail
# http://docs.travis-ci.com/user/build-configuration/#Rows-That-are-Allowed-To-Fail
matrix:
allow_failures:
- php: hhvm
- php: 5.6
services:
- redis-server
......
......@@ -5,6 +5,7 @@ use Yii;
use yii\web\AccessControl;
use yii\web\Controller;
use common\models\LoginForm;
use yii\web\VerbFilter;
/**
* Site controller
......@@ -31,6 +32,12 @@ class SiteController extends Controller
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
......
......@@ -37,7 +37,11 @@ AppAsset::register($this);
if (Yii::$app->user->isGuest) {
$menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];
} else {
$menuItems[] = ['label' => 'Logout (' . Yii::$app->user->identity->username .')' , 'url' => ['/site/logout']];
$menuItems[] = [
'label' => 'Logout (' . Yii::$app->user->identity->username . ')',
'url' => ['/site/logout'],
'linkOptions' => ['data-method' => 'post']
];
}
echo Nav::widget([
'options' => ['class' => 'navbar-nav navbar-right'],
......
<?php
use yii\helpers\Html;
use yii\mail\BaseMessage;
/**
* @var \yii\web\View $this
* @var BaseMessage $content
* @var \yii\mail\BaseMessage $content
*/
?>
<?php $this->beginPage() ?>
......
<?php
namespace common\models;
use yii\base\NotSupportedException;
use yii\db\ActiveRecord;
use yii\helpers\Security;
use yii\web\IdentityInterface;
......@@ -72,6 +73,14 @@ class User extends ActiveRecord implements IdentityInterface
}
/**
* @inheritdoc
*/
public static function findIdentityByAccessToken($token)
{
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
/**
* Finds user by username
*
* @param string $username
......
......@@ -32,7 +32,7 @@ class FixtureHelper extends Module
* to use in acceptance and functional tests.
* @param array $settings
*/
public function _beforeSuite($settings = array())
public function _beforeSuite($settings = [])
{
$this->loadFixtures();
}
......@@ -54,5 +54,4 @@ class FixtureHelper extends Module
],
];
}
}
......@@ -18,5 +18,4 @@ class LoginPage extends BasePage
$this->guy->fillField('input[name="LoginForm[password]"]', $password);
$this->guy->click('login-button');
}
}
......@@ -25,7 +25,7 @@ class LoginFormTest extends TestCase
$model->username = 'some_username';
$model->password = 'some_password';
$this->specify('user should not be able to login, when there is no identity' , function () use ($model) {
$this->specify('user should not be able to login, when there is no identity', function () use ($model) {
expect('model should not login user', $model->login())->false();
expect('user should not be logged in', Yii::$app->user->isGuest)->true();
});
......@@ -52,7 +52,7 @@ class LoginFormTest extends TestCase
$model->username = 'demo';
$model->password = 'demo';
$this->specify('user should be able to login with correct credentials', function() use ($model) {
$this->specify('user should be able to login with correct credentials', function () use ($model) {
expect('model should login user', $model->login())->true();
expect('error message should not be set', $model->errors)->hasntKey('password');
expect('user should be logged in', Yii::$app->user->isGuest)->false();
......@@ -61,9 +61,8 @@ class LoginFormTest extends TestCase
private function mockUser($user)
{
$loginForm = $this->getMock('common\models\LoginForm',['getUser']);
$loginForm = $this->getMock('common\models\LoginForm', ['getUser']);
$loginForm->expects($this->any())->method('getUser')->will($this->returnValue($user));
return $loginForm;
}
}
{
"name": "yiisoft/yii2-app-advanced",
"description": "Yii 2 Advanced Application Template",
"keywords": ["yii", "framework", "advanced", "application template"],
"keywords": ["yii2", "framework", "advanced", "application template"],
"homepage": "http://www.yiiframework.com/",
"type": "project",
"license": "BSD-3-Clause",
......
......@@ -10,6 +10,7 @@ use yii\base\InvalidParamException;
use yii\web\BadRequestHttpException;
use yii\web\Controller;
use Yii;
use yii\web\VerbFilter;
/**
* Site controller
......@@ -38,6 +39,12 @@ class SiteController extends Controller
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
......
......@@ -20,5 +20,4 @@ class SignupPage extends BasePage
}
$this->guy->click('signup-button');
}
}
......@@ -79,5 +79,4 @@ class SignupCest
$I->expectTo('see that user logged in');
$I->see('Logout (tester)');
}
}
......@@ -79,5 +79,4 @@ class SignupCest
$I->expectTo('see that user logged in');
$I->see('Logout (tester)');
}
}
......@@ -42,7 +42,7 @@ class ContactFormTest extends TestCase
expect('email file should exist', file_exists($this->getMessageFile()))->true();
});
$this->specify('message should contain correct data', function () use($model) {
$this->specify('message should contain correct data', function () use ($model) {
$emailMessage = file_get_contents($this->getMessageFile());
expect('email should contain user name', $emailMessage)->contains($model->name);
......@@ -56,5 +56,4 @@ class ContactFormTest extends TestCase
{
return Yii::getAlias(Yii::$app->mail->fileTransportPath) . '/testing_message.eml';
}
}
......@@ -28,14 +28,14 @@ class PasswordResetRequestFormTest extends DbTestCase
public function testSendEmailWrongUser()
{
$this->specify('no user with such email, message should not be send', function() {
$this->specify('no user with such email, message should not be send', function () {
$model = new PasswordResetRequestForm();
$model->email = 'not-existing-email@example.com';
expect('email not send', $model->sendEmail())->false();
});
$this->specify('user is not active, message should not be send', function() {
$this->specify('user is not active, message should not be send', function () {
$model = new PasswordResetRequestForm();
$model->email = $this->user[1]['email'];
......@@ -52,8 +52,8 @@ class PasswordResetRequestFormTest extends DbTestCase
expect('email sent', $model->sendEmail())->true();
expect('user has valid token', $user->password_reset_token)->notNull();
$this->specify('message has correct format', function() use ($model) {
expect('message file exists', file_exists($this->getMessageFile()))->true();
$this->specify('message has correct format', function () use ($model) {
expect('message file exists', file_exists($this->getMessageFile()))->true();
$message = file_get_contents($this->getMessageFile());
expect('message "from" is correct', $message)->contains(Yii::$app->params['supportEmail']);
......@@ -75,5 +75,4 @@ class PasswordResetRequestFormTest extends DbTestCase
{
return Yii::getAlias(Yii::$app->mail->fileTransportPath) . '/testing_message.eml';
}
}
......@@ -13,13 +13,13 @@ class ResetPasswordFormTest extends DbTestCase
public function testResetPassword()
{
$this->specify('wrong reset token', function() {
$this->setExpectedException('\Exception','Wrong password reset token.');
$this->specify('wrong reset token', function () {
$this->setExpectedException('\Exception', 'Wrong password reset token.');
new ResetPasswordForm('notexistingtoken_1391882543');
});
$this->specify('not correct token', function() {
$this->setExpectedException('yii\base\InvalidParamException','Password reset token cannot be blank.');
$this->specify('not correct token', function () {
$this->setExpectedException('yii\base\InvalidParamException', 'Password reset token cannot be blank.');
new ResetPasswordForm('');
});
}
......@@ -33,5 +33,4 @@ class ResetPasswordFormTest extends DbTestCase
],
];
}
}
......@@ -12,7 +12,7 @@ class SignupFormTest extends DbTestCase
public function testCorrectSignup()
{
$model = $this->getMock('frontend\models\SignupForm',['validate']);
$model = $this->getMock('frontend\models\SignupForm', ['validate']);
$model->expects($this->once())->method('validate')->will($this->returnValue(true));
$model->username = 'some_username';
......@@ -28,7 +28,7 @@ class SignupFormTest extends DbTestCase
public function testNotCorrectSignup()
{
$model = $this->getMock('frontend\models\SignupForm',['validate']);
$model = $this->getMock('frontend\models\SignupForm', ['validate']);
$model->expects($this->once())->method('validate')->will($this->returnValue(false));
expect('user should not be created', $model->signup())->null();
......@@ -43,5 +43,4 @@ class SignupFormTest extends DbTestCase
],
];
}
}
......@@ -41,7 +41,11 @@ AppAsset::register($this);
$menuItems[] = ['label' => 'Signup', 'url' => ['/site/signup']];
$menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];
} else {
$menuItems[] = ['label' => 'Logout (' . Yii::$app->user->identity->username .')' , 'url' => ['/site/logout']];
$menuItems[] = [
'label' => 'Logout (' . Yii::$app->user->identity->username . ')',
'url' => ['/site/logout'],
'linkOptions' => ['data-method' => 'post']
];
}
echo Nav::widget([
'options' => ['class' => 'navbar-nav navbar-right'],
......
{
"name": "yiisoft/yii2-app-basic",
"description": "Yii 2 Basic Application Template",
"keywords": ["yii", "framework", "basic", "application template"],
"keywords": ["yii2", "framework", "basic", "application template"],
"homepage": "http://www.yiiframework.com/",
"type": "project",
"license": "BSD-3-Clause",
......
<?php
use yii\helpers\Html;
use yii\mail\BaseMessage;
/**
* @var \yii\web\View $this
* @var BaseMessage $content
* @var \yii\mail\BaseMessage $content
*/
?>
<?php $this->beginPage() ?>
......
......@@ -8,6 +8,7 @@ class User extends \yii\base\Object implements \yii\web\IdentityInterface
public $username;
public $password;
public $authKey;
public $accessToken;
private static $users = [
'100' => [
......@@ -15,12 +16,14 @@ class User extends \yii\base\Object implements \yii\web\IdentityInterface
'username' => 'admin',
'password' => 'admin',
'authKey' => 'test100key',
'accessToken' => '100-token',
],
'101' => [
'id' => '101',
'username' => 'demo',
'password' => 'demo',
'authKey' => 'test101key',
'accessToken' => '101-token',
],
];
......@@ -33,6 +36,19 @@ class User extends \yii\base\Object implements \yii\web\IdentityInterface
}
/**
* @inheritdoc
*/
public static function findIdentityByAccessToken($token)
{
foreach (self::$users as $user) {
if ($user['accessToken'] === $token) {
return new static($user);
}
}
return null;
}
/**
* Finds user by username
*
* @param string $username
......
......@@ -18,5 +18,6 @@ require_once(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
// set correct script paths
$_SERVER['SCRIPT_FILENAME'] = TEST_ENTRY_FILE;
$_SERVER['SCRIPT_NAME'] = TEST_ENTRY_URL;
$_SERVER['SERVER_NAME'] = 'localhost';
Yii::setAlias('@tests', __DIR__);
{
"name": "yiisoft/yii2-app-benchmark",
"description": "Yii 2 Benchmark Application",
"keywords": ["yii", "framework", "benchmark", "application"],
"keywords": ["yii2", "framework", "benchmark", "application"],
"homepage": "http://www.yiiframework.com/",
"type": "project",
"license": "BSD-3-Clause",
......
......@@ -52,7 +52,7 @@ class ClassmapController extends Controller
$files = FileHelper::findFiles($root, $options);
$map = [];
foreach ($files as $file) {
if (($pos = strpos($file, $root)) !== 0) {
if (strpos($file, $root) !== 0) {
die("Something wrong: $file\n");
}
$path = str_replace('\\', '/', substr($file, strlen($root)));
......
{
"name": "yiisoft/yii2-dev",
"description": "Yii PHP Framework Version 2 - Development Package",
"keywords": ["yii", "framework"],
"keywords": ["yii2", "framework"],
"homepage": "http://www.yiiframework.com/",
"type": "yii2-extension",
"license": "BSD-3-Clause",
......@@ -74,6 +74,7 @@
"lib-pcre": "*",
"yiisoft/yii2-composer": "*",
"yiisoft/jquery": "~2.0 | ~1.10",
"yiisoft/jquery-pjax": "*",
"ezyang/htmlpurifier": "4.6.*",
"cebe/markdown": "0.9.*"
},
......
......@@ -172,7 +172,7 @@ Note that [[yii\db\ActiveRecord::updateAll()|updateAll()]], [[yii\db\ActiveRecor
```php
// to insert a new customer record
$customer = new Customer;
$customer = new Customer();
$customer->name = 'James';
$customer->email = 'james@example.com';
$customer->save(); // equivalent to $customer->insert();
......@@ -634,7 +634,7 @@ order owned by the customer:
```php
$customer = Customer::find(1);
$order = new Order;
$order = new Order();
$order->subtotal = 100;
$customer->link('orders', $order);
```
......
......@@ -81,18 +81,26 @@ following way:
```php
class LanguageAsset extends AssetBundle
{
public $sourcePath = '@app/assets/language';
public $js = [
];
public function init()
{
$this->js[] = 'language-' . Yii::$app->language . '.js';
parent::init();
}
public $language;
public $sourcePath = '@app/assets/language';
public $js = [
];
public function registerAssetFiles($view)
{
$language = $this->language ? $this->language : Yii::$app->language;
$this->js[] = 'language-' . $language . '.js';
parent::registerAssetFiles($view);
}
}
```
In order to set language use the following code when registering an asset bundle in a view:
```php
LanguageAsset::register($this)->language = $language;
```
Registering asset bundle
------------------------
......@@ -114,6 +122,10 @@ To register an asset inside of a widget, the view instance is available as `$thi
AppAsset::register($this->view);
```
> Note: If there is a need to modify third party asset bundles it is recommended to create your own bundles depending
on third party ones and use CSS and JavaScript features to modify behavior instead of editing files directly or
copying them over.
Overriding asset bundles
------------------------
......
......@@ -5,7 +5,7 @@ Authentication is the act of verifying who a user is, and is the basis of the lo
In Yii, this entire process is performed semi-automatically, leaving the developer to merely implement [[yii\web\IdentityInterface]], the most important class in the authentication system. Typically, implementation of `IdentityInterface` is accomplished using the `User` model.
You can find a full featured example of authentication in the
You can find a fully featured example of authentication in the
[advanced application template](installation.md). Below, only the interface methods are listed:
```php
......@@ -25,6 +25,17 @@ class User extends ActiveRecord implements IdentityInterface
}
/**
* Finds an identity by the given token.
*
* @param string $token the token to be looked for
* @return IdentityInterface|null the identity object that matches the given token.
*/
public static function findIdentityByAccessToken($token)
{
return static::find(['access_token' => $token]);
}
/**
* @return int|string current user ID
*/
public function getId()
......
......@@ -81,13 +81,16 @@ Routes
------
Each controller action has a corresponding internal route. In our example above `actionIndex` has `site/index` route
and `actionTest` has `site/test` route. In this route `site` is referred to as controller ID while `test` is referred to
as action ID.
and `actionTest` has `site/test` route. In this route `site` is referred to as controller ID while `test` is action ID.
By default you can access specific controller and action using the `http://example.com/?r=controller/action` URL. This
behavior is fully customizable. For details refer to [URL Management](url.md).
behavior is fully customizable. For more details please refer to [URL Management](url.md).
If controller is located inside a module its action internal route will be `module/controller/action`.
If a controller is located inside a module, the route of its actions will be in the format of `module/controller/action`.
A controller can be located under a subdirectory of the controller directory of an application or module. The route
will be prefixed with the corresponding directory names. For example, you may have a `UserController` under `controllers/admin`.
The route of its `actionIndex` would be `admin/user/index`, and `admin/user` would be the controller ID.
In case module, controller or action specified isn't found Yii will return "not found" page and HTTP status code 404.
......@@ -160,7 +163,7 @@ class BlogController extends Controller
{
$post = Post::find($id);
if (!$post) {
throw new NotFoundHttpException;
throw new NotFoundHttpException();
}
if (\Yii::$app->request->isPost) {
......
Data grid
=========
Data grid or GridView is one of the most powerful Yii widgets. It is extremely useful if you need to quickly build admin
section of the system. It takes data from [data provider](data-provider.md) and renders each row using a set of columns
presenting data in a form of a table.
Each row of the table represents the data of a single data item, and a column usually represents an attribute of
the item (some columns may correspond to complex expression of attributes or static text).
Grid view supports both sorting and pagination of the data items. The sorting and pagination can be done in AJAX mode
or normal page request. A benefit of using GridView is that when the user disables JavaScript, the sorting and pagination
automatically degrade to normal page requests and are still functioning as expected.
The minimal code needed to use CGridView is as follows:
```php
sdf
```
The above code first creates a data provider and then uses GridView to display every attribute in every row taken from
data provider. The displayed table is equiped with sorting and pagination functionality.
Grid columns
------------
Yii grid consists of a number of columns. Depending on column type and settings these are able to present data differently.
These are defined in the columns part of GridView config like the following:
```php
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
// A simple column defined by the data contained in $dataProvider.
// Data from model's column1 will be used.
'id',
'username',
// More complex one.
[
'class' => 'DataColumn', // can be omitted, default
'name' => 'column1',
'value' => function ($data) {
return $data->name;
},
'type'=>'raw',
],
],
]);
```
Note: If columns part of config isn't specified, Yii tries to show all possible data provider model columns.
### Column classes
#### Data column
#### Action column
#### Checkbox column
#### Serial column
TODO: rewrite these:
- https://github.com/samdark/a-guide-to-yii-grids-lists-and-data-providers/blob/master/grid-columns.md
- https://github.com/samdark/a-guide-to-yii-grids-lists-and-data-providers/pull/1
Sorting data
------------
- https://github.com/yiisoft/yii2/issues/1576
Filtering data
--------------
- https://github.com/yiisoft/yii2/issues/1581
\ No newline at end of file
Data and widgets for it
=======================
One of the most powerful aspects of Yii is how it works with data. One may output data directly and that's a good approach
for website frontend but when it comes to backend data components and widgets may save you weeks.
Typically, you would take the following steps when working with one of these data components:
1. Configure data provider. It may take its data from array, SQL, AR query etc.
2. Pass data provider to one of the widgets such as list view or grid view.
3. Customize the widget to reflect the presentational style that you are after.
That's it. After doing these simple steps you can get a full featured data grid supporting pagination, sorting and
filtering that is ideal for admin part of your project.
\ No newline at end of file
Data providers
==============
Data provider abstracts data set via [[yii\data\DataProviderInterface]] and handles pagination and sorting.
It can be used by [grids](data-grid.md), [lists and other data widgets](data-widgets.md).
In Yii there are three built-in data providers: [[yii\data\ActiveDataProvider]], [[yii\data\ArrayDataProvider]] and
[[yii\data\SqlDataProvider]].
Active data provider
--------------------
`ActiveDataProvider` provides data by performing DB queries using [[\yii\db\Query]] and [[\yii\db\ActiveQuery]].
The following is an example of using it to provide ActiveRecord instances:
```php
$provider = new ActiveDataProvider([
'query' => Post::find(),
'pagination' => [
'pageSize' => 20,
],
]);
// get the posts in the current page
$posts = $provider->getModels();
~~~
And the following example shows how to use ActiveDataProvider without ActiveRecord:
```php
$query = new Query();
$provider = new ActiveDataProvider([
'query' => $query->from('tbl_post'),
'pagination' => [
'pageSize' => 20,
],
]);
// get the posts in the current page
$posts = $provider->getModels();
```
Array data provider
-------------------
ArrayDataProvider implements a data provider based on a data array.
The [[allModels]] property contains all data models that may be sorted and/or paginated.
ArrayDataProvider will provide the data after sorting and/or pagination.
You may configure the [[sort]] and [[pagination]] properties to
customize the sorting and pagination behaviors.
Elements in the [[allModels]] array may be either objects (e.g. model objects)
or associative arrays (e.g. query results of DAO).
Make sure to set the [[key]] property to the name of the field that uniquely
identifies a data record or false if you do not have such a field.
Compared to `ActiveDataProvider`, `ArrayDataProvider` could be less efficient
because it needs to have [[allModels]] ready.
ArrayDataProvider may be used in the following way:
```php
$query = new Query();
$provider = new ArrayDataProvider([
'allModels' => $query->from('tbl_post')->all(),
'sort' => [
'attributes' => ['id', 'username', 'email'],
],
'pagination' => [
'pageSize' => 10,
],
]);
// get the posts in the current page
$posts = $provider->getModels();
```
> Note: if you want to use the sorting feature, you must configure the [[sort]] property
so that the provider knows which columns can be sorted.
SQL data provider
-----------------
SqlDataProvider implements a data provider based on a plain SQL statement. It 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:
```php
$count = Yii::$app->db->createCommand('
SELECT COUNT(*) FROM tbl_user WHERE status=:status
', [':status' => 1])->queryScalar();
$dataProvider = new SqlDataProvider([
'sql' => 'SELECTFROM 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.
Implementing your own custom data provider
------------------------------------------
Data widgets
============
ListView
--------
DetailView
----------
DetailView displays the detail of a single data [[model]].
It is best used for displaying a model in a regular format (e.g. each model attribute is displayed as a row in a table).
The model can be either an instance of [[Model]] or an associative array.
DetailView uses the [[attributes]] property to determines which model attributes should be displayed and how they
should be formatted.
A typical usage of DetailView is as follows:
```php
echo DetailView::widget([
'model' => $model,
'attributes' => [
'title', // title attribute (in plain text)
'description:html', // description attribute in HTML
[ // the owner name of the model
'label' => 'Owner',
'value' => $model->owner->name,
],
],
]);
```
......@@ -72,10 +72,10 @@ Security and access control
Data providers, lists and grids
-------------------------------
- Overview
- Data providers
- Grids
- Lists
- [Overview](data-overview.md)
- [Data providers](data-providers.md)
- [Data widgets](data-widgets.md)
- [Grid](data-grid.md)
Advanced Topics
---------------
......
......@@ -24,7 +24,7 @@ be accessed like the member variables of any object. For example, a `Post` model
may contain a `title` attribute and a `content` attribute, accessible as follows:
```php
$post = new Post;
$post = new Post();
$post->title = 'Hello, world';
$post->content = 'Something interesting is happening.';
echo $post->title;
......@@ -35,7 +35,7 @@ Since [[yii\base\Model|Model]] implements the [ArrayAccess](http://php.net/manua
you can also access the attributes as if they were array elements:
```php
$post = new Post;
$post = new Post();
$post['title'] = 'Hello, world';
$post['content'] = 'Something interesting is happening';
echo $post['title'];
......@@ -160,7 +160,7 @@ class EmployeeController extends \yii\web\Controller
$employee = new Employee(['scenario' => 'managementPanel']);
// second way
$employee = new Employee;
$employee = new Employee();
$employee->scenario = 'managementPanel';
// third way
......@@ -187,7 +187,7 @@ only, etc. If errors are found in validation, they may be presented to the user
The following example shows how the validation is performed:
```php
$model = new LoginForm;
$model = new LoginForm();
$model->username = $_POST['username'];
$model->password = $_POST['password'];
if ($model->validate()) {
......@@ -331,7 +331,7 @@ For the code above mass assignment will be allowed stsrictly according to `scena
$user = User::find(42);
$data = ['password' => '123'];
$user->attributes = $data;
print_r($data);
print_r($user->attributes);
```
Will give you empty array because there's no default scenario defined in our `scenarios()`.
......@@ -345,7 +345,7 @@ $data = [
'hashcode' => 'test',
];
$user->attributes = $data;
print_r($data);
print_r($user->attributes);
```
Will give you the following:
......@@ -386,7 +386,7 @@ $data = [
'password' => '123',
];
$user->attributes = $data;
print_r($data);
print_r($user->attributes);
```
Will give you the following:
......
......@@ -110,7 +110,7 @@ class ViewsPanel extends Panel
{
parent::init();
Event::on(View::className(), View::EVENT_BEFORE_RENDER, function (ViewEvent $event) {
$this->_viewFiles[] = $event->viewFile;
$this->_viewFiles[] = $event->sender->getViewFile();
});
}
......
......@@ -9,7 +9,7 @@ The Query Builder provides an object-oriented vehicle for generating queries to
A typical usage of the query builder looks like the following:
```php
$rows = (new \yii\db\Query)
$rows = (new \yii\db\Query())
->select('id, name')
->from('tbl_user')
->limit(10)
......@@ -17,7 +17,7 @@ $rows = (new \yii\db\Query)
// which is equivalent to the following code:
$query = (new \yii\db\Query)
$query = (new \yii\db\Query())
->select('id, name')
->from('tbl_user')
->limit(10);
......@@ -116,7 +116,7 @@ You may specify a sub-query using a `Query` object. In this case, the correspond
as the alias for the sub-query.
```php
$subQuery = (new Query)->select('id')->from('tbl_user')->where('status=1');
$subQuery = (new Query())->select('id')->from('tbl_user')->where('status=1');
$query->select('*')->from(['u' => $subQuery]);
```
......@@ -324,10 +324,10 @@ $query->leftJoin(['u' => $subQuery], 'u.id=author_id');
In Yii in order to build it you can first form two query objects and then use `union` method:
```php
$query = new Query;
$query = new Query();
$query->select("id, 'post' as type, name")->from('tbl_post')->limit(10);
$anotherQuery = new Query;
$anotherQuery = new Query();
$anotherQuery->select('id, 'user' as type, name')->from('tbl_user')->limit(10);
$query->union($anotherQuery);
......@@ -347,7 +347,7 @@ Batch query can be used like the following:
```php
use yii\db\Query;
$query = (new Query)
$query = (new Query())
->from('tbl_user')
->orderBy('id');
......@@ -376,7 +376,7 @@ will still keep the proper index. For example,
```php
use yii\db\Query;
$query = (new Query)
$query = (new Query())
->from('tbl_user')
->indexBy('username');
......
Theming
=======
TBD
A theme is a directory of view and layout files. Each file of the theme overrides corresponding file of an application
when rendered. A single application may use multiple themes and each may provide totally different experience. At any
time only one theme can be active.
> Note: Themes usually do not meant to be redistributed since views are too application specific. If you want to
redistribute customized look and feel consider CSS and JavaScript files in form of [asset bundles](assets.md) instead.
Configuring current theme
-------------------------
......@@ -18,4 +23,27 @@ be in your application config file:
],
],
],
```
\ No newline at end of file
```
In the above `pathMap` defines where to look for view files while `baseUrl` defines base URL for resources referenced
from these files. For example, if `pathMap` is `['/web/views' => '/web/themes/basic']`, then the themed version
for a view file `/web/views/site/index.php` will be `/web/themes/basic/site/index.php`.
Using multiple paths
--------------------
It is possible to map a single path to multiple paths. For example,
```php
'pathMap' => [
'/web/views' => [
'/web/themes/christmas',
'/web/themes/basic',
],
]
```
In this case, the view will be searched in `/web/themes/christmas/site/index.php` then if it's not found it will check
`/web/themes/basic/site/index.php`. If there's no view there as well application view will be used.
This ability is especially useful if you want to temporary or conditionally override some views.
......@@ -158,7 +158,7 @@ in controllers or widgets:
```php
$content = Yii::$app->view->renderFile($viewFile, $params);
// You can also explicitly create a new View instance to do the rendering
// $view = new View;
// $view = new View();
// $view->renderFile($viewFile, $params);
```
......@@ -186,7 +186,7 @@ New methods called [[yii\base\Model::load()|load()] and [[yii\base\Model::loadMu
introduced to simplify the data population from user inputs to a model. For example,
```php
$model = new Post;
$model = new Post();
if ($model->load($_POST)) {...}
// which is equivalent to:
if (isset($_POST['Post'])) {
......@@ -329,9 +329,9 @@ public function behaviors()
'class' => 'yii\web\AccessControl',
'rules' => [
['allow' => true, 'actions' => ['admin'], 'roles' => ['@']],
),
),
);
],
],
];
}
```
......@@ -394,7 +394,7 @@ In 1.1, query building is scattered among several classes, including `CDbCommand
and [[yii\db\QueryBuilder|QueryBuilder]] to generate SQL statements from query objects. For example:
```php
$query = new \yii\db\Query;
$query = new \yii\db\Query();
$query->select('id, name')
->from('tbl_user')
->limit(10);
......
{
"name": "yiisoft/yii2-apidoc",
"description": "API Documentation generator for the Yii framework 2.0",
"keywords": ["yii", "phpdoc", "apidoc", "api", "documentation"],
"keywords": ["yii2", "phpdoc", "apidoc", "api", "documentation"],
"type": "yii2-extension",
"license": "BSD-3-Clause",
"support": {
......@@ -22,6 +22,7 @@
"yiisoft/yii2": "*",
"yiisoft/yii2-bootstrap": "*",
"phpdocumentor/reflection": ">=1.0.3",
"phpdocumentor/reflection-docblock": ">2.0.1",
"nikic/php-parser": "0.9.*"
},
"autoload": {
......
......@@ -69,7 +69,7 @@ class PropertyDoc extends BaseDoc
$this->types = $tag->getTypes();
$this->description = ucfirst($tag->getDescription());
if (($pos = strpos($this->description, '.')) !== false) {
$this->shortDescription = substr($this->description, 0, $pos);
$this->shortDescription = substr($this->description, 0, $pos + 1);
} else {
$this->shortDescription = $this->description;
}
......
......@@ -50,3 +50,11 @@ body {
background: #E6ECFF;
border: 1px #BFCFFF solid;
}
blockquote {
font-size: 14px;
}
td p {
margin: 0;
}
\ No newline at end of file
......@@ -36,7 +36,7 @@ ArrayHelper::multisort($constants, 'name');
<tr<?= $constant->definedBy != $type->name ? ' class="inherited"' : '' ?> id="<?= $constant->name ?>">
<td><?= $constant->name ?><a name="<?= $constant->name ?>-detail"></a></td>
<td><?= $constant->value ?></td>
<td><?= APiMarkdown::process($constant->shortDescription . "\n" . $constant->description, $constant->definedBy, true) ?></td>
<td><?= ApiMarkdown::process($constant->shortDescription . "\n" . $constant->description, $constant->definedBy, true) ?></td>
<td><?= $renderer->createTypeLink($constant->definedBy) ?></td>
</tr>
<?php endforeach; ?>
......
......@@ -18,7 +18,7 @@ ArrayHelper::multisort($events, 'name');
<h2>Event Details</h2>
<?php foreach($events as $event): ?>
<div class="detailHeader h3" id="<?= $event->name.'-detail' ?>">
<?php echo $event->name; ?>
<?= $event->name ?>
<span class="detailHeaderTag small">
event
<?php if(!empty($event->since)): ?>
......@@ -32,7 +32,7 @@ ArrayHelper::multisort($events, 'name');
<?php echo $event->trigger->signature; ?>
</div>*/ ?>
<p><?= ApiMarkdown::process($event->description, $type); ?></p>
<?= ApiMarkdown::process($event->description, $type); ?>
<?= $this->render('seeAlso', ['object' => $event]); ?>
......
......@@ -39,11 +39,11 @@ ArrayHelper::multisort($events, 'name');
<td>
<?= ApiMarkdown::process($event->shortDescription, $event->definedBy, true) ?>
<?php if(!empty($event->since)): ?>
(available since version <?php echo $event->since; ?>)
(available since version <?= $event->since ?>)
<?php endif; ?>
</td>
<td><?= $renderer->createTypeLink($event->definedBy) ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
\ No newline at end of file
</div>
......@@ -65,8 +65,8 @@ ArrayHelper::multisort($methods, 'name');
<!-- --><?php //$this->renderPartial('sourceCode',array('object'=>$method)); ?>
<p><?= ApiMarkdown::process($method->shortDescription, $type, true) ?></strong></p>
<p><?= ApiMarkdown::process($method->description, $type) ?></p>
<p><strong><?= ApiMarkdown::process($method->shortDescription, $type, true) ?></strong></p>
<?= ApiMarkdown::process($method->description, $type) ?>
<?= $this->render('seeAlso', ['object' => $method]); ?>
......
......@@ -24,7 +24,7 @@ ArrayHelper::multisort($properties, 'name');
<?php foreach($properties as $property): ?>
<div class="detailHeader h3" id="<?= $property->name.'-detail' ?>">
<?php echo $property->name; ?>
<?= $property->name ?>
<span class="detailHeaderTag small">
<?= $property->visibility ?>
<?php if($property->getIsReadOnly()) echo ' <em>read-only</em> '; ?>
......@@ -38,7 +38,7 @@ ArrayHelper::multisort($properties, 'name');
<div class="signature"><?php echo $renderer->renderPropertySignature($property); ?></div>
<p><?= ApiMarkdown::process($property->description, $type) ?></p>
<?= ApiMarkdown::process($property->description, $type) ?>
<?= $this->render('seeAlso', ['object' => $property]); ?>
......
{
"name": "yiisoft/yii2-authclient",
"description": "External authentication via OAuth and OpenID for the Yii framework",
"keywords": ["yii", "OAuth", "OpenID", "auth"],
"keywords": ["yii2", "OAuth", "OpenID", "auth"],
"type": "yii2-extension",
"license": "BSD-3-Clause",
"support": {
......
......@@ -12,9 +12,11 @@ Yii Framework 2 bootstrap extension Change Log
- Enh #1601: Added support for tagName and encodeLabel parameters in ButtonDropdown (omnilight)
- Enh #1881: Improved `yii\bootstrap\NavBar` with `containerOptions`, `innerContainerOptions` and `renderInnerContainer` (creocoder)
- Enh #2425: Tabs widget now selects first tab if no active tab is specified (samdark)
- Enh #2643: Add size attribute to Modal (tof06)
- Chg #1459: Update Collapse to use bootstrap 3 classes (tonydspaniard)
- Chg #1820: Update Progress to use bootstrap 3 markup (samdark)
2.0.0 alpha, December 1, 2013
-----------------------------
......
......@@ -35,6 +35,10 @@ use yii\helpers\Html;
*/
class Modal extends Widget
{
const SIZE_LARGE = "modal-lg";
const SIZE_SMALL = "modal-sm";
const SIZE_DEFAULT = "";
/**
* @var string the header content in the modal window.
*/
......@@ -44,6 +48,10 @@ class Modal extends Widget
*/
public $footer;
/**
* @var string the modal size. Can be MODAL_LG or MODAL_SM, or empty for default.
*/
public $size;
/**
* @var array the options for rendering the close button tag.
* The close button is displayed in the header of the modal window. Clicking
* on the button will hide the modal window. If this is null, no close button will be rendered.
......@@ -86,7 +94,7 @@ class Modal extends Widget
echo $this->renderToggleButton() . "\n";
echo Html::beginTag('div', $this->options) . "\n";
echo Html::beginTag('div', ['class' => 'modal-dialog']) . "\n";
echo Html::beginTag('div', ['class' => 'modal-dialog ' . $this->size]) . "\n";
echo Html::beginTag('div', ['class' => 'modal-content']) . "\n";
echo $this->renderHeader() . "\n";
echo $this->renderBodyBegin() . "\n";
......
......@@ -92,7 +92,7 @@ class Tabs extends Widget
*/
public $encodeLabels = true;
/**
* @var string, specifies the Bootstrap tab styling.
* @var string specifies the Bootstrap tab styling.
*/
public $navType = 'nav-tabs';
......
{
"name": "yiisoft/yii2-bootstrap",
"description": "The Twitter Bootstrap extension for the Yii framework",
"keywords": ["yii", "bootstrap"],
"keywords": ["yii2", "bootstrap"],
"type": "yii2-extension",
"license": "BSD-3-Clause",
"support": {
......
{
"name": "yiisoft/yii2-codeception",
"description": "The Codeception integration for the Yii framework",
"keywords": ["yii", "codeception"],
"keywords": ["yii2", "codeception"],
"type": "yii2-extension",
"license": "BSD-3-Clause",
"support": {
......
{
"name": "yiisoft/yii2-composer",
"description": "The composer plugin for Yii extension installer",
"keywords": ["yii", "composer", "extension installer"],
"keywords": ["yii2", "composer", "extension installer"],
"type": "composer-plugin",
"license": "BSD-3-Clause",
"support": {
......
{
"name": "yiisoft/yii2-debug",
"description": "The debugger extension for the Yii framework",
"keywords": ["yii", "debug", "debugger"],
"keywords": ["yii2", "debug", "debugger"],
"type": "yii2-extension",
"license": "BSD-3-Clause",
"support": {
......
......@@ -97,7 +97,7 @@ class Mail extends Base
$dataProvider = new ArrayDataProvider([
'allModels' => $models,
'pagination' => [
'pageSize' => 5,
'pageSize' => 20,
],
'sort' => [
'attributes' => ['from', 'to', 'reply', 'cc', 'bcc', 'subject', 'body', 'charset'],
......
<?php
use yii\helpers\Html;
/**
* @var yii\debug\panels\ConfigPanel $panel
*/
......
<?php
use yii\helpers\Html;
/**
* @var yii\debug\panels\ConfigPanel $panel
*/
......
<?php if ($queryCount): ?>
<div class="yii-debug-toolbar-block">
<a href="<?= $panel->getUrl() ?>" title="Executed <?php echo $queryCount; ?> database queries which took <?= $queryTime ?>.">
<a href="<?= $panel->getUrl() ?>" title="Executed <?= $queryCount ?> database queries which took <?= $queryTime ?>.">
DB <span class="label label-info"><?= $queryCount ?></span> <span class="label"><?= $queryTime ?></span>
</a>
</div>
......
......@@ -50,9 +50,6 @@ TBD
> **NOTE:** elasticsearch limits the number of records returned by any query to 10 records by default.
> If you expect to get more records you should specify limit explicitly in relation definition.
* This is also important for relations that use [[via()]] so that if via records are limited to 10
* the relations records can also not be more than 10.
*
Using the ActiveRecord
......@@ -60,14 +57,15 @@ Using the ActiveRecord
For general information on how to use yii's ActiveRecord please refer to the [guide](https://github.com/yiisoft/yii2/blob/master/docs/guide/active-record.md).
For defining an elasticsearch ActiveRecord class your record class needs to extend from `yii\elasticsearch\ActiveRecord` and
implement at least the `attributes()` method to define the attributes of the record.
For defining an elasticsearch ActiveRecord class your record class needs to extend from [[yii\elasticsearch\ActiveRecord]] and
implement at least the [[yii\elasticsearch\ActiveRecord::attributes()|attributes()]] method to define the attributes of the record.
The handling of primary keys is different in elasticsearch as the primary key (the `_id` field in elasticsearch terms)
is not part of the attributes by default. However it is possible to define a [path mapping](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-id-field.html)
for the `_id` field to be part of the attributes.
See [elasticsearch docs](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-id-field.html) on how to define it.
The `_id` field of a document/record can be accessed using [[ActiveRecord::getPrimaryKey()]] and [[ActiveRecord::setPrimaryKey()]].
When path mapping is defined, the attribute name can be defined using the [[primaryKey()]] method.
The `_id` field of a document/record can be accessed using [[yii\elasticsearch\ActiveRecord::getPrimaryKey()|getPrimaryKey()]] and
[[yii\elasticsearch\ActiveRecord::setPrimaryKey()|setPrimaryKey()]].
When path mapping is defined, the attribute name can be defined using the [[yii\elasticsearch\ActiveRecord::primaryKey()|primaryKey()]] method.
The following is an example model called `Customer`:
......@@ -101,7 +99,8 @@ class Customer extends \yii\elasticsearch\ActiveRecord
}
```
You may override [[index()]] and [[type()]] to define the index and type this record represents.
You may override [[yii\elasticsearch\ActiveRecord::index()|index()]] and [[yii\elasticsearch\ActiveRecord::type()|type()]]
to define the index and type this record represents.
The general usage of elasticsearch ActiveRecord is very similar to the database ActiveRecord as described in the
[guide](https://github.com/yiisoft/yii2/blob/master/docs/guide/active-record.md).
......@@ -109,13 +108,18 @@ It supports the same interface and features except the following limitations and
- As elasticsearch does not support SQL, the query API does not support `join()`, `groupBy()`, `having()` and `union()`.
Sorting, limit, offset and conditional where are all supported.
- `from()` does not select the tables, but the [index](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/glossary.html#glossary-index)
- [[yii\elasticsearch\ActiveQuery::from()|from()]] does not select the tables, but the
[index](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/glossary.html#glossary-index)
and [type](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/glossary.html#glossary-type) to query against.
- `select()` has been replaced with `fields()` which basically does the same but `fields` is more elasticsearch terminology.
- `select()` has been replaced with [[yii\elasticsearch\ActiveQuery::fields()|fields()]] which basically does the same but
`fields` is more elasticsearch terminology.
It defines the fields to retrieve from a document.
- `via`-relations can not be defined via a table as there are no tables in elasticsearch. You can only define relations via other records.
- As elasticsearch is not only a data storage but also a search engine there is of course support added for search your records.
There are `query()`, `filter()` and `addFacets()` methods that allows to compose an elasticsearch query.
- [[yii\elasticsearch\ActiveQuery::via()|via]]-relations can not be defined via a table as there are no tables in elasticsearch. You can only define relations via other records.
- As elasticsearch is not only a data storage but also a search engine there is of course support added for searching your records.
There are
[[yii\elasticsearch\ActiveQuery::query()|query()]],
[[yii\elasticsearch\ActiveQuery::filter()|filter()]] and
[[yii\elasticsearch\ActiveQuery::addFacet()|addFacet()]] methods that allows to compose an elasticsearch query.
See the usage example below on how they work and check out the [Query DSL](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html)
on how to compose `query` and `filter` parts.
- It is also possible to define relations from elasticsearch ActiveRecords to normal ActiveRecord classes and vice versa.
......
{
"name": "yiisoft/yii2-elasticsearch",
"description": "Elasticsearch integration and ActiveRecord for the Yii framework",
"keywords": ["yii", "elasticsearch", "active-record", "search", "fulltext"],
"keywords": ["yii2", "elasticsearch", "active-record", "search", "fulltext"],
"type": "yii2-extension",
"license": "BSD-3-Clause",
"support": {
......
{
"name": "yiisoft/yii2-faker",
"description": "Fixture generator. The Faker integration for the Yii framework.",
"keywords": ["yii", "faker", "fixture"],
"keywords": ["yii2", "faker", "fixture"],
"type": "yii2-extension",
"license": "BSD-3-Clause",
"support": {
......
......@@ -13,6 +13,8 @@ Yii Framework 2 gii extension Change Log
- Enh #1897: diff markup is now copy paste friendly (samdark)
- Enh #2327: better visual representation of changed files, added header and refresh button to diff modal (thiagotalma)
- Enh #2491: Added support for using the same base class name of search model and data model in Gii (qiangxue)
- Enh #2595: Browse through all generated files using right and left arrows (thiagotalma)
- Enh #2633: Keyboard shortcuts to browse through files (thiagotalma)
2.0.0 alpha, December 1, 2013
-----------------------------
......
......@@ -141,6 +141,7 @@ class Module extends \yii\base\Module
'controller' => ['class' => 'yii\gii\generators\controller\Generator'],
'form' => ['class' => 'yii\gii\generators\form\Generator'],
'module' => ['class' => 'yii\gii\generators\module\Generator'],
'extension' => ['class' => 'yii\gii\generators\extension\Generator'],
];
}
}
......@@ -35,10 +35,13 @@ yii.gii = (function ($) {
};
var initPreviewDiffLinks = function () {
$('.preview-code, .diff-code, .modal-refresh').on('click', function () {
$('.preview-code, .diff-code, .modal-refresh, .modal-previous, .modal-next').on('click', function () {
var $modal = $('#preview-modal');
var $link = $(this);
$modal.find('.modal-refresh').attr('href', $link.prop('href'));
$modal.find('.modal-refresh').attr('href', $link.attr('href'));
if ($link.hasClass('preview-code') || $link.hasClass('diff-code')) {
$modal.data('action', ($link.hasClass('preview-code') ? 'preview-code' : 'diff-code'))
}
$modal.find('.modal-title').text($link.data('title'));
$modal.find('.modal-body').html('Loading ...');
$modal.modal('show');
......@@ -48,6 +51,15 @@ yii.gii = (function ($) {
url: $link.prop('href'),
data: $('.default-view form').serializeArray(),
success: function (data) {
if (!$link.hasClass('modal-refresh')) {
var filesSelector = 'a.' + $modal.data('action');
var $files = $(filesSelector);
var index = $files.filter('[href="' + $link.attr('href') + '"]').index(filesSelector);
var $prev = $files.eq(index-1);
var $next = $files.eq((index+1 == $files.length ? 0 : index+1));
$modal.find('.modal-previous').attr('href', $prev.attr('href')).data('title', $prev.data('title'));
$modal.find('.modal-next').attr('href', $next.attr('href')).data('title', $next.data('title'));
}
$modal.find('.modal-body').html(data);
$modal.find('.content').css('max-height', ($(window).height() - 200) + 'px');
},
......@@ -57,6 +69,16 @@ yii.gii = (function ($) {
});
return false;
});
$('#preview-modal').on('keydown', function(e) {
if (e.keyCode === 37) {
$('.modal-previous').trigger('click');
} else if(e.keyCode === 39) {
$('.modal-next').trigger('click');
} else if(e.keyCode === 82) {
$('.modal-refresh').trigger('click');
}
});
};
var initConfirmationCheckboxes = function () {
......
{
"name": "yiisoft/yii2-gii",
"description": "The Gii extension for the Yii framework",
"keywords": ["yii", "gii", "code generator"],
"keywords": ["yii2", "gii", "code generator"],
"type": "yii2-extension",
"license": "BSD-3-Clause",
"support": {
......
......@@ -18,5 +18,5 @@ echo "<?php\n";
<p>
You may change the content of this page by modifying
the file <code><?= '<?php' ?> echo __FILE__; ?></code>.
the file <code><?= '<?=' ?> __FILE__; ?></code>.
</p>
......@@ -16,6 +16,7 @@ use yii\helpers\Inflector;
use yii\web\Controller;
/**
* Generates CRUD
*
* @property array $columnNames Model column names. This property is read-only.
* @property string $controllerID The controller ID (without the module ID prefix). This property is
......
......@@ -26,8 +26,8 @@ $this->params['breadcrumbs'][] = $this->title;
<h1><?= "<?= " ?>Html::encode($this->title) ?></h1>
<?= "<?php " ?>echo $this->render('_form', [
<?= "<?= " ?>$this->render('_form', [
'model' => $model,
]); ?>
]) ?>
</div>
......@@ -37,7 +37,7 @@ $this->params['breadcrumbs'][] = $this->title;
</p>
<?php if ($generator->indexWidgetType === 'grid'): ?>
<?= "<?php " ?>echo GridView::widget([
<?= "<?= " ?>GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
......@@ -69,13 +69,13 @@ if (($tableSchema = $generator->getTableSchema()) === false) {
],
]); ?>
<?php else: ?>
<?= "<?php " ?>echo ListView::widget([
<?= "<?= " ?>ListView::widget([
'dataProvider' => $dataProvider,
'itemOptions' => ['class' => 'item'],
'itemView' => function ($model, $key, $index, $widget) {
return Html::a(Html::encode($model-><?= $nameAttribute ?>), ['view', <?= $urlParams ?>]);
},
]); ?>
]) ?>
<?php endif; ?>
</div>
......@@ -29,8 +29,8 @@ $this->params['breadcrumbs'][] = 'Update';
<h1><?= "<?= " ?>Html::encode($this->title) ?></h1>
<?= "<?php " ?>echo $this->render('_form', [
<?= "<?= " ?>$this->render('_form', [
'model' => $model,
]); ?>
]) ?>
</div>
......@@ -31,16 +31,16 @@ $this->params['breadcrumbs'][] = $this->title;
<p>
<?= "<?= " ?>Html::a('Update', ['update', <?= $urlParams ?>], ['class' => 'btn btn-primary']) ?>
<?= "<?php " ?>echo Html::a('Delete', ['delete', <?= $urlParams ?>], [
<?= "<?= " ?>Html::a('Delete', ['delete', <?= $urlParams ?>], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => Yii::t('app', 'Are you sure to delete this item?'),
'method' => 'post',
],
]); ?>
]) ?>
</p>
<?= "<?php " ?>echo DetailView::widget([
<?= "<?= " ?>DetailView::widget([
'model' => $model,
'attributes' => [
<?php
......@@ -56,6 +56,6 @@ if (($tableSchema = $generator->getTableSchema()) === false) {
}
?>
],
]); ?>
]) ?>
</div>
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\gii\generators\extension;
use Yii;
use yii\gii\CodeFile;
/**
* This generator will generate the skeleton files needed by an extension.
*
* @author Tobias Munk <schmunk@usrbin.de>
* @since 2.0
*/
class Generator extends \yii\gii\Generator
{
public $vendorName;
public $packageName = "yii2-";
public $namespace;
public $type = "yii2-extension";
public $keywords = "yii2,extension";
public $title;
public $description;
public $outputPath = "@app/runtime/tmp-extensions";
public $license;
public $authorName;
public $authorEmail;
/**
* @inheritdoc
*/
public function getName()
{
return 'Extension Generator';
}
/**
* @inheritdoc
*/
public function getDescription()
{
return 'This generator helps you to generate the files needed by a Yii extension.';
}
/**
* @inheritdoc
*/
public function rules()
{
return array_merge(
parent::rules(),
[
[['vendorName', 'packageName'], 'filter', 'filter' => 'trim'],
[
[
'vendorName',
'packageName',
'namespace',
'type',
'license',
'title',
'description',
'authorName',
'authorEmail',
'outputPath'
],
'required'
],
[['keywords'], 'safe'],
[['authorEmail'], 'email'],
[
['vendorName', 'packageName'],
'match',
'pattern' => '/^[a-z0-9\-\.]+$/',
'message' => 'Only lowercase word characters, dashes and dots are allowed.'
],
[
['namespace'],
'match',
'pattern' => '/^[a-zA-Z0-9\\\]+\\\$/',
'message' => 'Only letters, numbers and backslashes are allowed. PSR-4 namespaces must end with a namespace separator.'
],
]
);
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'vendorName' => 'Vendor Name',
'packageName' => 'Package Name',
'license' => 'License',
];
}
/**
* @inheritdoc
*/
public function hints()
{
return [
'vendorName' => 'This refers to the name of the publisher, your GitHub user name is usually a good choice, eg. <code>myself</code>.',
'packageName' => 'This is the name of the extension on packagist, eg. <code>yii2-foobar</code>.',
'namespace' => 'PSR-4, eg. <code>myself\foobar\</code> This will be added to your autoloading by composer. Do not use yii or yii2 in the namespace.',
'keywords' => 'Comma separated keywords for this extension.',
'outputPath' => 'The temporary location of the generated files.',
'title' => 'A more descriptive name of your application for the README file.',
'description' => 'A sentence or subline describing the main purpose of the extension.',
];
}
/**
* @inheritdoc
*/
public function stickyAttributes()
{
return ['vendorName', 'outputPath', 'authorName', 'authorEmail'];
}
/**
* @inheritdoc
*/
public function successMessage()
{
$outputPath = realpath(\Yii::getAlias($this->outputPath));
$output1 = <<<EOD
<p><em>The extension has been generated successfully.</em></p>
<p>To enable it in your application, you need to create a git repository
and require it via composer.</p>
EOD;
$code1 = <<<EOD
cd {$outputPath}/{$this->packageName}
git init
git add -A
git commit
git remote add origin https://path.to/your/repo
git push -u origin master
EOD;
$output2 = <<<EOD
<p>The next step is just for <em>initial development</em>, skip it if you directly publish the extension on packagist.org</p>
<p>Add the newly created repo to your composer.json.</p>
EOD;
$code2 = <<<EOD
"repositories":[
{
"type": "git",
"url": "https://path.to/your/repo"
}
]
EOD;
$output3 = <<<EOD
<p class="well">Note: You may use the url <code>file://{$outputPath}/{$this->packageName}</code> for testing.</p>
<p>Require the package with composer</p>
EOD;
$code3 = <<<EOD
composer.phar require {$this->vendorName}/{$this->packageName}:dev-master
EOD;
$output4 = <<<EOD
<p>And use it in your application.</p>
EOD;
$code4 = <<<EOD
\\{$this->namespace}AutoloadExample::widget();
EOD;
$output5 = <<<EOD
<p>When you have finished development register your extension at <a href='https://packagist.org/' target='_blank'>packagist.org</a>.</p>
EOD;
$return = $output1 . '<pre>' . highlight_string($code1, true) . '</pre>';
$return .= $output2 . '<pre>' . highlight_string($code2, true) . '</pre>';
$return .= $output3 . '<pre>' . highlight_string($code3, true) . '</pre>';
$return .= $output4 . '<pre>' . highlight_string($code4, true) . '</pre>';
$return .= $output5;
return $return;
}
/**
* @inheritdoc
*/
public function requiredTemplates()
{
return ['composer.json', 'AutoloadExample.php', 'README.md'];
}
/**
* @inheritdoc
*/
public function generate()
{
$files = [];
$modulePath = $this->getOutputPath();
$files[] = new CodeFile(
$modulePath . '/' . $this->packageName . '/composer.json',
$this->render("composer.json")
);
$files[] = new CodeFile(
$modulePath . '/' . $this->packageName . '/AutoloadExample.php',
$this->render("AutoloadExample.php")
);
$files[] = new CodeFile(
$modulePath . '/' . $this->packageName . '/README.md',
$this->render("README.md")
);
return $files;
}
/**
* @return boolean the directory that contains the module class
*/
public function getOutputPath()
{
return Yii::getAlias($this->outputPath);
}
/**
* @return string a json encoded array with the given keywords
*/
public function getKeywordsArrayJson()
{
return json_encode(explode(',', $this->keywords));
}
/**
* @return array options for type drop-down
*/
public function optsType()
{
$licenses = [
'yii2-extension',
'library',
];
return array_combine($licenses, $licenses);
}
/**
* @return array options for license drop-down
*/
public function optsLicense()
{
$licenses = [
'Apache-2.0',
'BSD-2-Clause',
'BSD-3-Clause',
'BSD-4-Clause',
'GPL-2.0',
'GPL-2.0+',
'GPL-3.0',
'GPL-3.0+',
'LGPL-2.1',
'LGPL-2.1+',
'LGPL-3.0',
'LGPL-3.0+',
'MIT'
];
return array_combine($licenses, $licenses);
}
}
<?php
/**
* @var yii\web\View $this
* @var yii\widgets\ActiveForm $form
* @var yii\gii\generators\module\Generator $generator
*/
?>
<div class="alert alert-info">
Please read the
<?= \yii\helpers\Html::a('Extension Guidelines', 'https://github.com/yiisoft/yii2/blob/master/docs/guide/extensions.md', ['target'=>'new']) ?>
before creating an extension.
</div>
<div class="module-form">
<?php
echo $form->field($generator, 'vendorName');
echo $form->field($generator, 'packageName');
echo $form->field($generator, 'namespace');
echo $form->field($generator, 'type')->dropDownList($generator->optsType());
echo $form->field($generator, 'keywords');
echo $form->field($generator, 'license')->dropDownList($generator->optsLicense(), ['prompt'=>'Choose...']);
echo $form->field($generator, 'title');
echo $form->field($generator, 'description');
echo $form->field($generator, 'authorName');
echo $form->field($generator, 'authorEmail');
echo $form->field($generator, 'outputPath');
?>
</div>
<?php
/**
* This is just an example.
*/
echo "<?php\n";
?>
namespace <?= substr($generator->namespace, 0, -1) ?>;
class AutoloadExample extends \yii\base\widget {
function run() {
return "Hello!";
}
}
<?= $generator->title ?>
<?= str_repeat('=', mb_strlen($generator->title, \Yii::$app->charset)) ?>
<?= $generator->description ?>
Installation
------------
The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
Either run
```
php composer.phar require --prefer-dist <?= $generator->vendorName ?>/<?= $generator->packageName ?> "*"
```
or add
```
"<?= $generator->vendorName ?>/<?= $generator->packageName ?>": "*"
```
to the require section of your `composer.json` file.
Usage
-----
Once the extension is installed, simply use it in your code by :
```php
<?= "<?= \\{$generator->namespace}AutoloadExample::widget(); ?>" ?>
```
\ No newline at end of file
{
"name": "<?= $generator->vendorName ?>/<?= $generator->packageName ?>",
"description": "<?= $generator->description ?>",
"type": "<?= $generator->type ?>",
"keywords": <?= $generator->keywordsArrayJson ?>,
"license": "<?= $generator->license ?>",
"authors": [
{
"name": "<?= $generator->authorName ?>",
"email": "<?= $generator->authorEmail ?>"
}
],
"autoload": {
"psr-4": {
"<?= str_replace('\\','\\\\',$generator->namespace) ?>": ""
}
}
}
......@@ -471,7 +471,7 @@ class Generator extends \yii\gii\Generator
*/
public function validateTableName()
{
if (($pos = strpos($this->tableName, '*')) !== false && substr($this->tableName, -1) !== '*') {
if (strpos($this->tableName, '*') !== false && substr($this->tableName, -1) !== '*') {
$this->addError('tableName', 'Asterisk is only allowed as the last character.');
return;
}
......
......@@ -81,7 +81,14 @@ use yii\gii\CodeFile;
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4><a class="modal-refresh glyphicon glyphicon-refresh" href="#"></a> <span class="modal-title">Modal title</span></h4>
<div class="btn-group pull-left">
<a class="modal-previous btn btn-xs btn-default" href="#" title="Previous File (Left Arrow)"><span class="glyphicon glyphicon-arrow-left"></span></a>
<a class="modal-next btn btn-xs btn-default" href="#" title="Next File (Right Arrow)"><span class="glyphicon glyphicon-arrow-right"></span></a>
<a class="modal-refresh btn btn-xs btn-default" href="#" title="Refresh File (R)"><span class="glyphicon glyphicon-refresh"></span></a>
&nbsp;
</div>
<strong class="modal-title pull-left">Modal title</strong>
<div class="clearfix"></div>
</div>
<div class="modal-body">
<p>Please wait ...</p>
......
{
"name": "yiisoft/yii2-imagine",
"description": "The Imagine integration for the Yii framework",
"keywords": ["yii", "imagine", "image", "helper"],
"keywords": ["yii2", "imagine", "image", "helper"],
"type": "yii2-extension",
"license": "BSD-3-Clause",
"support": {
......
......@@ -6,6 +6,7 @@ Yii Framework 2 jui extension Change Log
- Bug #1550: fixed the issue that JUI input widgets did not property input IDs. (qiangxue)
- Bug #2514: Jui sortable clientEvents were not working because of wrong naming assumptions. (cebe)
- Enh #2573: Jui datepicker now uses the current appliaction language by default. (andy5)
2.0.0 alpha, December 1, 2013
-----------------------------
......
......@@ -7,11 +7,12 @@
namespace yii\jui;
use Yii;
use yii\helpers\Html;
use yii\helpers\Json;
/**
* DatePicker renders an datepicker jQuery UI widget.
* DatePicker renders a datepicker jQuery UI widget.
*
* For example:
*
......@@ -46,9 +47,9 @@ class DatePicker extends InputWidget
{
/**
* @var string the locale ID (eg 'fr', 'de') for the language to be used by the date picker.
* If this property set to false, I18N will not be involved. That is, the date picker will show in English.
* If this property is empty, then the current application language will be used.
*/
public $language = false;
public $language;
/**
* @var boolean If true, shows the widget as an inline calendar and the input as a hidden field.
*/
......@@ -77,15 +78,16 @@ class DatePicker extends InputWidget
{
echo $this->renderWidget() . "\n";
$containerID = $this->inline ? $this->containerOptions['id'] : $this->options['id'];
if ($this->language !== false) {
$language = $this->language ? $this->language : Yii::$app->language;
if ($language != 'en') {
$view = $this->getView();
DatePickerRegionalAsset::register($view);
$options = Json::encode($this->clientOptions);
$view->registerJs("$('#{$containerID}').datepicker($.extend({}, $.datepicker.regional['{$this->language}'], $options));");
$view->registerJs("$('#{$containerID}').datepicker($.extend({}, $.datepicker.regional['{$language}'], $options));");
$options = $this->clientOptions;
$this->clientOptions = false; // the datepicker js widget is already registered
$this->clientOptions = false; // the datepicker js widget is already registered
$this->registerWidget('datepicker', DatePickerAsset::className(), $containerID);
$this->clientOptions = $options;
} else {
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
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