diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e4b8278 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +language: php + +php: + - 5.3 + - 5.4 + - 5.5 + +env: + - DB=mysql + +before_script: + - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS yiitest;'; fi" + +script: phpunit \ No newline at end of file diff --git a/app/assets/.gitignore b/apps/bootstrap/assets/.gitignore similarity index 100% rename from app/assets/.gitignore rename to apps/bootstrap/assets/.gitignore diff --git a/app/css/bootstrap-responsive.css b/apps/bootstrap/css/bootstrap-responsive.css similarity index 100% rename from app/css/bootstrap-responsive.css rename to apps/bootstrap/css/bootstrap-responsive.css diff --git a/app/css/bootstrap-responsive.min.css b/apps/bootstrap/css/bootstrap-responsive.min.css similarity index 100% rename from app/css/bootstrap-responsive.min.css rename to apps/bootstrap/css/bootstrap-responsive.min.css diff --git a/app/css/bootstrap.css b/apps/bootstrap/css/bootstrap.css similarity index 100% rename from app/css/bootstrap.css rename to apps/bootstrap/css/bootstrap.css diff --git a/app/css/bootstrap.min.css b/apps/bootstrap/css/bootstrap.min.css similarity index 100% rename from app/css/bootstrap.min.css rename to apps/bootstrap/css/bootstrap.min.css diff --git a/app/css/site.css b/apps/bootstrap/css/site.css similarity index 100% rename from app/css/site.css rename to apps/bootstrap/css/site.css diff --git a/app/img/glyphicons-halflings-white.png b/apps/bootstrap/img/glyphicons-halflings-white.png similarity index 100% rename from app/img/glyphicons-halflings-white.png rename to apps/bootstrap/img/glyphicons-halflings-white.png diff --git a/app/img/glyphicons-halflings.png b/apps/bootstrap/img/glyphicons-halflings.png similarity index 100% rename from app/img/glyphicons-halflings.png rename to apps/bootstrap/img/glyphicons-halflings.png diff --git a/app/index.php b/apps/bootstrap/index.php similarity index 80% rename from app/index.php rename to apps/bootstrap/index.php index 8f98090..e3188c1 100644 --- a/app/index.php +++ b/apps/bootstrap/index.php @@ -2,7 +2,7 @@ defined('YII_DEBUG') or define('YII_DEBUG', true); -require(__DIR__ . '/../framework/yii.php'); +require(__DIR__ . '/../../framework/yii.php'); $config = require(__DIR__ . '/protected/config/main.php'); $application = new yii\web\Application($config); diff --git a/app/js/bootstrap.js b/apps/bootstrap/js/bootstrap.js similarity index 100% rename from app/js/bootstrap.js rename to apps/bootstrap/js/bootstrap.js diff --git a/app/js/bootstrap.min.js b/apps/bootstrap/js/bootstrap.min.js similarity index 100% rename from app/js/bootstrap.min.js rename to apps/bootstrap/js/bootstrap.min.js diff --git a/app/protected/.htaccess b/apps/bootstrap/protected/.htaccess similarity index 100% rename from app/protected/.htaccess rename to apps/bootstrap/protected/.htaccess diff --git a/app/protected/config/assets.php b/apps/bootstrap/protected/config/assets.php similarity index 98% rename from app/protected/config/assets.php rename to apps/bootstrap/protected/config/assets.php index 6602a6e..a3ba847 100644 --- a/app/protected/config/assets.php +++ b/apps/bootstrap/protected/config/assets.php @@ -16,4 +16,4 @@ return array( 'yii', ), ), -); \ No newline at end of file +); diff --git a/app/protected/config/main.php b/apps/bootstrap/protected/config/main.php similarity index 99% rename from app/protected/config/main.php rename to apps/bootstrap/protected/config/main.php index b982506..96e0986 100644 --- a/app/protected/config/main.php +++ b/apps/bootstrap/protected/config/main.php @@ -18,4 +18,4 @@ return array( 'params' => array( 'adminEmail' => 'admin@example.com', ), -); \ No newline at end of file +); diff --git a/app/protected/controllers/SiteController.php b/apps/bootstrap/protected/controllers/SiteController.php similarity index 99% rename from app/protected/controllers/SiteController.php rename to apps/bootstrap/protected/controllers/SiteController.php index 7e6bb15..d1186f6 100644 --- a/app/protected/controllers/SiteController.php +++ b/apps/bootstrap/protected/controllers/SiteController.php @@ -46,4 +46,4 @@ class SiteController extends Controller { echo $this->render('about'); } -} \ No newline at end of file +} diff --git a/app/protected/models/ContactForm.php b/apps/bootstrap/protected/models/ContactForm.php similarity index 99% rename from app/protected/models/ContactForm.php rename to apps/bootstrap/protected/models/ContactForm.php index 8e8f831..5124b2c 100644 --- a/app/protected/models/ContactForm.php +++ b/apps/bootstrap/protected/models/ContactForm.php @@ -60,4 +60,4 @@ class ContactForm extends Model return false; } } -} \ No newline at end of file +} diff --git a/app/protected/models/LoginForm.php b/apps/bootstrap/protected/models/LoginForm.php similarity index 99% rename from app/protected/models/LoginForm.php rename to apps/bootstrap/protected/models/LoginForm.php index 23e8c92..5ba1dc6 100644 --- a/app/protected/models/LoginForm.php +++ b/apps/bootstrap/protected/models/LoginForm.php @@ -55,4 +55,4 @@ class LoginForm extends Model return false; } } -} \ No newline at end of file +} diff --git a/app/protected/models/User.php b/apps/bootstrap/protected/models/User.php similarity index 99% rename from app/protected/models/User.php rename to apps/bootstrap/protected/models/User.php index fcbf14a..afbf9f8 100644 --- a/app/protected/models/User.php +++ b/apps/bootstrap/protected/models/User.php @@ -58,4 +58,4 @@ class User extends \yii\base\Object implements \yii\web\Identity { return $this->password === $password; } -} \ No newline at end of file +} diff --git a/app/protected/runtime/.gitignore b/apps/bootstrap/protected/runtime/.gitignore similarity index 100% rename from app/protected/runtime/.gitignore rename to apps/bootstrap/protected/runtime/.gitignore diff --git a/app/protected/views/layouts/main.php b/apps/bootstrap/protected/views/layouts/main.php similarity index 98% rename from app/protected/views/layouts/main.php rename to apps/bootstrap/protected/views/layouts/main.php index a455f20..8fb915a 100644 --- a/app/protected/views/layouts/main.php +++ b/apps/bootstrap/protected/views/layouts/main.php @@ -54,4 +54,4 @@ $this->registerAssetBundle('app'); -endPage(); ?> \ No newline at end of file +endPage(); ?> diff --git a/app/protected/views/site/about.php b/apps/bootstrap/protected/views/site/about.php similarity index 100% rename from app/protected/views/site/about.php rename to apps/bootstrap/protected/views/site/about.php diff --git a/app/protected/views/site/contact.php b/apps/bootstrap/protected/views/site/contact.php similarity index 97% rename from app/protected/views/site/contact.php rename to apps/bootstrap/protected/views/site/contact.php index 246570d..4ca40f1 100644 --- a/app/protected/views/site/contact.php +++ b/apps/bootstrap/protected/views/site/contact.php @@ -30,4 +30,4 @@ $this->title = 'Contact';
'btn btn-primary')); ?>
-endWidget(); ?> \ No newline at end of file +endWidget(); ?> diff --git a/app/protected/views/site/index.php b/apps/bootstrap/protected/views/site/index.php similarity index 100% rename from app/protected/views/site/index.php rename to apps/bootstrap/protected/views/site/index.php diff --git a/app/protected/views/site/login.php b/apps/bootstrap/protected/views/site/login.php similarity index 96% rename from app/protected/views/site/login.php rename to apps/bootstrap/protected/views/site/login.php index 5608ffb..8672eeb 100644 --- a/app/protected/views/site/login.php +++ b/apps/bootstrap/protected/views/site/login.php @@ -18,4 +18,4 @@ $this->title = 'Login';
'btn btn-primary')); ?>
-endWidget(); ?> \ No newline at end of file +endWidget(); ?> diff --git a/build/build b/build/build index fff4282..691eba9 100755 --- a/build/build +++ b/build/build @@ -16,5 +16,5 @@ require(__DIR__ . '/../framework/yii.php'); $id = 'yiic-build'; $basePath = __DIR__; -$application = new yii\console\Application($id, $basePath); +$application = new yii\console\Application(array('id' => $id, 'basePath' => $basePath)); $application->run(); diff --git a/docs/api/db/ActiveRecord.md b/docs/api/db/ActiveRecord.md index 822c548..4e82793 100644 --- a/docs/api/db/ActiveRecord.md +++ b/docs/api/db/ActiveRecord.md @@ -412,7 +412,7 @@ class Customer extends \yii\db\ActiveRecord /** * @param ActiveQuery $query */ - public function active($query) + public static function active($query) { $query->andWhere('status = 1'); } @@ -435,7 +435,7 @@ class Customer extends \yii\db\ActiveRecord * @param ActiveQuery $query * @param integer $age */ - public function olderThan($query, $age = 30) + public static function olderThan($query, $age = 30) { $query->andWhere('age > :age', array(':age' => $age)); } diff --git a/docs/guide/active-record.md b/docs/guide/active-record.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/authentication.md b/docs/guide/authentication.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/authorization.md b/docs/guide/authorization.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/bootstrap.md b/docs/guide/bootstrap.md index 5f00a75..1bc3fe6 100644 --- a/docs/guide/bootstrap.md +++ b/docs/guide/bootstrap.md @@ -7,7 +7,7 @@ If you have installed Yii under a Web-accessible folder, you should be able to access this application through the following URL: ~~~ -http://localhost/yii/app/index.php +http://localhost/yii/apps/bootstrap/index.php ~~~ diff --git a/docs/guide/caching.md b/docs/guide/caching.md new file mode 100644 index 0000000..cd945e7 --- /dev/null +++ b/docs/guide/caching.md @@ -0,0 +1,3 @@ +Caching +======= + diff --git a/docs/guide/console.md b/docs/guide/console.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/dao.md b/docs/guide/dao.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/error.md b/docs/guide/error.md new file mode 100644 index 0000000..c97fada --- /dev/null +++ b/docs/guide/error.md @@ -0,0 +1,3 @@ +Error Handling +============== + diff --git a/docs/guide/extension.md b/docs/guide/extension.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/form.md b/docs/guide/form.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/gii.md b/docs/guide/gii.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/i18n.md b/docs/guide/i18n.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/installation.md b/docs/guide/installation.md index 6cc5ef8..3f9a803 100644 --- a/docs/guide/installation.md +++ b/docs/guide/installation.md @@ -25,8 +25,8 @@ http://hostname/path/to/yii/requirements/index.php ~~~ Yii requires PHP 5.3, so the server must have PHP 5.3 or above installed and -available to the web server. Yii has been tested with [Apache HTTP server](http://httpd.apache.org/) -on Windows and Linux. It may also run on other Web servers and platforms, +available to the web server. Yii has been tested with [Apache HTTP server](http://httpd.apache.org/) +on Windows and Linux. It may also run on other Web servers and platforms, provided PHP 5.3 is supported. @@ -34,7 +34,7 @@ Recommended Apache Configuration -------------------------------- Yii is ready to work with a default Apache web server configuration. -The `.htaccess` files in Yii framework and application folders restrict +The `.htaccess` files in Yii framework and application folders deny access to the restricted resources. To hide the bootstrap file (usually `index.php`) in your URLs you can add `mod_rewrite` instructions to the `.htaccess` file in your document root or to the virtual host configuration: @@ -63,7 +63,7 @@ server { access_log /www/mysite/log/access.log main; server_name mysite; - root $host_path/htdocs; + root $host_path/htdocs; set $yii_bootstrap "index.php"; charset utf-8; @@ -108,4 +108,5 @@ server { } ~~~ -Using this configuration you can set `cgi.fix_pathinfo=0` in php.ini to avoid many unnecessary system stat() calls. +Using this configuration you can set `cgi.fix_pathinfo=0` in php.ini to avoid +many unnecessary system `stat()` calls. diff --git a/docs/guide/logging.md b/docs/guide/logging.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/migration.md b/docs/guide/migration.md new file mode 100644 index 0000000..bafd293 --- /dev/null +++ b/docs/guide/migration.md @@ -0,0 +1,319 @@ +Database Migration +================== + +Like source code, the structure of a database is evolving as we develop and maintain +a database-driven application. For example, during development, we may want to +add a new table; or after the application is put into production, we may realize +the need of adding an index on a column. It is important to keep track of these +structural database changes (called **migration**) like we do with our source +code. If the source code and the database are out of sync, it is very likely +the whole system may break. For this reason, Yii provides a database migration +tool that can keep track of database migration history, apply new migrations, +or revert existing ones. + +The following steps show how we can use database migration during development: + +1. Tim creates a new migration (e.g. create a new table) +2. Tim commits the new migration into source control system (e.g. GIT, Mercurial) +3. Doug updates from source control system and receives the new migration +4. Doug applies the migration to his local development database + + +Yii supports database migration via the `yiic migrate` command line tool. This +tool supports creating new migrations, applying/reverting/redoing migrations, and +showing migration history and new migrations. + +Creating Migrations +------------------- + +To create a new migration (e.g. create a news table), we run the following command: + +~~~ +yiic migrate/create +~~~ + +The required `name` parameter specifies a very brief description of the migration +(e.g. `create_news_table`). As we will show in the following, the `name` parameter +is used as part of a PHP class name. Therefore, it should only contain letters, +digits and/or underscore characters. + +~~~ +yiic migrate/create create_news_table +~~~ + +The above command will create under the `protected/migrations` directory a new +file named `m101129_185401_create_news_table.php` which contains the following +initial code: + +~~~ +[php] +class m101129_185401_create_news_table extends \yii\db\Migration +{ + public function up() + { + } + + public function down() + { + echo "m101129_185401_create_news_table cannot be reverted.\n"; + return false; + } +} +~~~ + +Notice that the class name is the same as the file name which is of the pattern +`m_`, where `` refers to the UTC timestamp (in the +format of `yymmdd_hhmmss`) when the migration is created, and `` is taken +from the command's `name` parameter. + +The `up()` method should contain the code implementing the actual database +migration, while the `down()` method may contain the code reverting what is +done in `up()`. + +Sometimes, it is impossible to implement `down()`. For example, if we delete +table rows in `up()`, we will not be able to recover them in `down()`. In this +case, the migration is called irreversible, meaning we cannot roll back to +a previous state of the database. In the above generated code, the `down()` +method returns `false` to indicate that the migration cannot be reverted. + +As an example, let's show the migration about creating a news table. + +~~~ +[php] +class m101129_185401_create_news_table extends \yii\db\Migration +{ + public function up() + { + $this->db->createCommand()->createTable('tbl_news, array( + 'id' => 'pk', + 'title' => 'string NOT NULL', + 'content' => 'text', + ))->execute(); + } + + public function down() + { + $this->db->createCommand()->dropTable('tbl_news')->execute(); + } +} +~~~ + +The base class [\yii\db\Migration] exposes a database connection via `db` +property. You can use it for manipulating data and schema of a database. + +Transactional Migrations +------------------------ + +While performing complex DB migrations, we usually want to make sure that each +migration succeed or fail as a whole so that the database maintains the +consistency and integrity. In order to achieve this goal, we can exploit +DB transactions. + +We could explicitly start a DB transaction and enclose the rest of the DB-related +code within the transaction, like the following: + +~~~ +[php] +class m101129_185401_create_news_table extends \yii\db\Migration +{ + public function up() + { + $transaction=$this->getDbConnection()->beginTransaction(); + try + { + $this->db->createCommand()->createTable('tbl_news, array( + 'id' => 'pk', + 'title' => 'string NOT NULL', + 'content' => 'text', + ))->execute(); + $transaction->commit(); + } + catch(Exception $e) + { + echo "Exception: ".$e->getMessage()."\n"; + $transaction->rollback(); + return false; + } + } + + // ...similar code for down() +} +~~~ + +> Note: Not all DBMS support transactions. And some DB queries cannot be put +> into a transaction. In this case, you will have to implement `up()` and +> `down()`, instead. And for MySQL, some SQL statements may cause +> [implicit commit](http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html). + + +Applying Migrations +------------------- + +To apply all available new migrations (i.e., make the local database up-to-date), +run the following command: + +~~~ +yiic migrate +~~~ + +The command will show the list of all new migrations. If you confirm to apply +the migrations, it will run the `up()` method in every new migration class, one +after another, in the order of the timestamp value in the class name. + +After applying a migration, the migration tool will keep a record in a database +table named `tbl_migration`. This allows the tool to identify which migrations +have been applied and which are not. If the `tbl_migration` table does not exist, +the tool will automatically create it in the database specified by the `db` +application component. + +Sometimes, we may only want to apply one or a few new migrations. We can use the +following command: + +~~~ +yiic migrate/up 3 +~~~ + +This command will apply the 3 new migrations. Changing the value 3 will allow +us to change the number of migrations to be applied. + +We can also migrate the database to a specific version with the following command: + +~~~ +yiic migrate/to 101129_185401 +~~~ + +That is, we use the timestamp part of a migration name to specify the version +that we want to migrate the database to. If there are multiple migrations between +the last applied migration and the specified migration, all these migrations +will be applied. If the specified migration has been applied before, then all +migrations applied after it will be reverted (to be described in the next section). + + +Reverting Migrations +-------------------- + +To revert the last one or several applied migrations, we can use the following +command: + +~~~ +yiic migrate/down [step] +~~~ + +where the optional `step` parameter specifies how many migrations to be reverted +back. It defaults to 1, meaning reverting back the last applied migration. + +As we described before, not all migrations can be reverted. Trying to revert +such migrations will throw an exception and stop the whole reverting process. + + +Redoing Migrations +------------------ + +Redoing migrations means first reverting and then applying the specified migrations. +This can be done with the following command: + +~~~ +yiic migrate/redo [step] +~~~ + +where the optional `step` parameter specifies how many migrations to be redone. +It defaults to 1, meaning redoing the last migration. + + +Showing Migration Information +----------------------------- + +Besides applying and reverting migrations, the migration tool can also display +the migration history and the new migrations to be applied. + +~~~ +yiic migrate/history [limit] +yiic migrate/new [limit] +~~~ + +where the optional parameter `limit` specifies the number of migrations to be +displayed. If `limit` is not specified, all available migrations will be displayed. + +The first command shows the migrations that have been applied, while the second +command shows the migrations that have not been applied. + + +Modifying Migration History +--------------------------- + +Sometimes, we may want to modify the migration history to a specific migration +version without actually applying or reverting the relevant migrations. This +often happens when developing a new migration. We can use the following command +to achieve this goal. + +~~~ +yiic migrate/mark 101129_185401 +~~~ + +This command is very similar to `yiic migrate/to` command, except that it only +modifies the migration history table to the specified version without applying +or reverting the migrations. + + +Customizing Migration Command +----------------------------- + +There are several ways to customize the migration command. + +### Use Command Line Options + +The migration command comes with four options that can be specified in command +line: + +* `interactive`: boolean, specifies whether to perform migrations in an + interactive mode. Defaults to true, meaning the user will be prompted when + performing a specific migration. You may set this to false should the + migrations be done in a background process. + +* `migrationPath`: string, specifies the directory storing all migration class + files. This must be specified in terms of a path alias, and the corresponding + directory must exist. If not specified, it will use the `migrations` + sub-directory under the application base path. + +* `migrationTable`: string, specifies the name of the database table for storing + migration history information. It defaults to `tbl_migration`. The table + structure is `version varchar(255) primary key, apply_time integer`. + +* `connectionID`: string, specifies the ID of the database application component. + Defaults to 'db'. + +* `templateFile`: string, specifies the path of the file to be served as the code + template for generating the migration classes. This must be specified in terms + of a path alias (e.g. `application.migrations.template`). If not set, an + internal template will be used. Inside the template, the token `{ClassName}` + will be replaced with the actual migration class name. + +To specify these options, execute the migrate command using the following format + +~~~ +yiic migrate/up --option1=value1 --option2=value2 ... +~~~ + +For example, if we want to migrate for a `forum` module whose migration files +are located within the module's `migrations` directory, we can use the following +command: + +~~~ +yiic migrate/up --migrationPath=ext.forum.migrations +~~~ + + +### 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, we may want to use a different table to store the migration history, +or we may want to use a customized migration template. We can do so by modifying +the console application's configuration file like the following, + +```php +TBD +``` + +Now if we run the `migrate` command, the above configurations will take effect +without requiring us to enter the command line options every time. diff --git a/docs/guide/mvc.md b/docs/guide/mvc.md index 79140ce..a99d043 100644 --- a/docs/guide/mvc.md +++ b/docs/guide/mvc.md @@ -11,7 +11,7 @@ the communication between the model and the view. Besides implementing MVC, Yii also introduces a front-controller, called `Application`, which encapsulates the execution context for the processing -of a request. Application collects some information about a user request and +of a request. Application collects information about a user request and then dispatches it to an appropriate controller for further handling. The following diagram shows the static structure of a Yii application: @@ -21,6 +21,7 @@ The following diagram shows the static structure of a Yii application: A Typical Workflow ------------------ + The following diagram shows a typical workflow of a Yii application when it is handling a user request: diff --git a/docs/guide/performance.md b/docs/guide/performance.md new file mode 100644 index 0000000..9a871dc --- /dev/null +++ b/docs/guide/performance.md @@ -0,0 +1,181 @@ +Performance Tuning +================== + +Application performance consists of two parts. First is the framework performance +and the second is the application itself. Yii has a pretty low performance impact +on your application out of the box and can be fine-tuned further for production +environment. As for the application, we'll provide some of the best practices +along with examples on how to apply them to Yii. + +Preparing framework for production +---------------------------------- + +### Disabling Debug Mode + +First thing you should do before deploying your application to production environment +is to disable debug mode. A Yii application runs in debug mode if the constant +`YII_DEBUG` is defined as `true` in `index.php` so to disable debug the following +should be in your `index.php`: + +```php +defined('YII_DEBUG') or define('YII_DEBUG', false); +``` + +Debug mode is very useful during development stage, but it would impact performance +because some components cause extra burden in debug mode. For example, the message +logger may record additional debug information for every message being logged. + +### Enabling PHP opcode cache + +Enabling the PHP opcode cache improves any PHP application performance and lowers +memory usage significantly. Yii is no exception. It was tested with +[APC PHP extension](http://php.net/manual/en/book.apc.php) that caches +and optimizes PHP intermediate code and avoids the time spent in parsing PHP +scripts for every incoming request. + +### Turning on ActiveRecord database schema caching + +If the application is using Active Record, we should turn on the schema caching +to save the time of parsing database schema. This can be done by setting the +`Connection::enableSchemaCache` property to be `true` via application configuration +`protected/config/main.php`: + +```php +return array( + // ... + 'components' => array( + // ... + 'db' => array( + 'class' => 'yii\db\Connection', + 'dsn' => 'mysql:host=localhost;dbname=mydatabase', + 'username' => 'root', + 'password' => '', + 'enableSchemaCache' => true, + + // Duration of schema cache. + // 'schemaCacheDuration' => 3600, + + // Name of the cache component used. Default is 'cache'. + //'schemaCache' => 'cache', + ), + 'cache' => array( + 'class' => 'yii\caching\FileCache', + ), + ), +); +``` + +Note that `cache` application component should be configured. + +### Combining and Minimizing Assets + +TBD + +### Using better storage for sessions + +By default PHP uses files to handle sessions. It is OK for development and +small projects but when it comes to handling concurrent requests it's better to +switch to another storage such as database. You can do so by configuring your +application via `protected/config/main.php`: + +```php +return array( + // ... + 'components' => array( + 'session' => array( + 'class' => 'yii\web\DbSession', + + // Set the following if want to use DB component other than + // default 'db'. + // 'db' => 'mydb', + + // To override default session table set the following + // 'sessionTable' => 'my_session', + ), + ), +); +``` + +You can use `CacheSession` to store sessions using cache. Note that some +cache storages such as memcached has no guaranteee that session data will not +be lost leading to unexpected logouts. + +Improving application +--------------------- + +### Using Serverside Caching Techniques + +As described in the Caching section, Yii provides several caching solutions that +may improve the performance of a Web application significantly. If the generation +of some data takes long time, we can use the data caching approach to reduce the +data generation frequency; If a portion of page remains relatively static, we +can use the fragment caching approach to reduce its rendering frequency; +If a whole page remains relative static, we can use the page caching approach to +save the rendering cost for the whole page. + + +### Leveraging HTTP to save procesing time and bandwidth + +TBD + +### Database Optimization + +Fetching data from database is often the main performance bottleneck in +a Web application. Although using caching may alleviate the performance hit, +it does not fully solve the problem. When the database contains enormous data +and the cached data is invalid, fetching the latest data could be prohibitively +expensive without proper database and query design. + +Design index wisely in a database. Indexing can make SELECT queries much faster, +but it may slow down INSERT, UPDATE or DELETE queries. + +For complex queries, it is recommended to create a database view for it instead +of issuing the queries inside the PHP code and asking DBMS to parse them repetitively. + +Do not overuse Active Record. Although Active Record is good at modelling data +in an OOP fashion, it actually degrades performance due to the fact that it needs +to create one or several objects to represent each row of query result. For data +intensive applications, using DAO or database APIs at lower level could be +a better choice. + +Last but not least, use LIMIT in your SELECT queries. This avoids fetching +overwhelming data from database and exhausting the memory allocated to PHP. + +### Using asArray + +A good way to save memory and processing time on read-only pages is to use +ActiveRecord's `asArray` method. + +```php +class PostController extends Controller +{ + public function actionIndex() + { + $posts = Post::find()->orderBy('id DESC')->limit(100)->asArray()->all(); + echo $this->render('index', array( + 'posts' => $posts, + )); + } +} +``` + +In the view you should access fields of each invidual record from `$posts` as array: + +```php +foreach($posts as $post) { + echo $post['title']."
"; +} +``` + +Note that you can use array notation even if `asArray` wasn't specified and you're +working with AR objects. + +### Processing data in background + +In order to respond to user requests faster you can process heavy parts of the +request later if there's no need for immediate response. + +- Cron jobs + console. +- queues + handlers. + +TBD \ No newline at end of file diff --git a/docs/guide/query-builder.md b/docs/guide/query-builder.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/security.md b/docs/guide/security.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/template.md b/docs/guide/template.md new file mode 100644 index 0000000..dc83d15 --- /dev/null +++ b/docs/guide/template.md @@ -0,0 +1,3 @@ +Template +======== + diff --git a/docs/guide/testing.md b/docs/guide/testing.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/theming.md b/docs/guide/theming.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/upgrade.md b/docs/guide/upgrade.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/guide/url.md b/docs/guide/url.md new file mode 100644 index 0000000..46bb177 --- /dev/null +++ b/docs/guide/url.md @@ -0,0 +1,3 @@ +URL Management +============== + diff --git a/docs/guide/validation.md b/docs/guide/validation.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/view_renderers.md b/docs/view_renderers.md index 1d88d21..e26fe83 100644 --- a/docs/view_renderers.md +++ b/docs/view_renderers.md @@ -27,6 +27,9 @@ array( ) ``` +Note that Smarty and Twig are not bundled with Yii and you have to download and +unpack these yourself and then specify `twigPath` and `smartyPath` respectively. + Twig ---- diff --git a/framework/YiiBase.php b/framework/YiiBase.php index 9d501b1..ed975c9 100644 --- a/framework/YiiBase.php +++ b/framework/YiiBase.php @@ -600,6 +600,13 @@ class YiiBase */ public static function t($message, $params = array(), $language = null) { - return self::$app->getI18N()->translate($message, $params, $language); + if (self::$app !== null) { + return self::$app->getI18N()->translate($message, $params, $language); + } else { + if (strpos($message, '|') !== false && preg_match('/^([\w\-\\/\.\\\\]+)\|(.*)/', $message, $matches)) { + $message = $matches[2]; + } + return is_array($params) ? strtr($message, $params) : $message; + } } } diff --git a/framework/assets.php b/framework/assets.php index 5cea992..919011b 100644 --- a/framework/assets.php +++ b/framework/assets.php @@ -28,4 +28,4 @@ return array( ), 'depends' => array('yii', 'yii/validation'), ), -); \ No newline at end of file +); diff --git a/framework/base/ActionFilter.php b/framework/base/ActionFilter.php index 1f82e5d..d69c0fe 100644 --- a/framework/base/ActionFilter.php +++ b/framework/base/ActionFilter.php @@ -87,4 +87,4 @@ class ActionFilter extends Behavior { return !in_array($action->id, $this->except, true) && (empty($this->only) || in_array($action->id, $this->only, true)); } -} \ No newline at end of file +} diff --git a/framework/base/Application.php b/framework/base/Application.php index 6dca5cf..5b92f76 100644 --- a/framework/base/Application.php +++ b/framework/base/Application.php @@ -306,6 +306,15 @@ class Application extends Module } /** + * @return null|Component + * @todo + */ + public function getAuthManager() + { + return $this->getComponent('auth'); + } + + /** * Registers the core application components. * @see setComponents */ diff --git a/framework/base/Component.php b/framework/base/Component.php index 80259e7..582cf03 100644 --- a/framework/base/Component.php +++ b/framework/base/Component.php @@ -496,6 +496,7 @@ class Component extends Object */ public function detachBehavior($name) { + $this->ensureBehaviors(); if (isset($this->_behaviors[$name])) { $behavior = $this->_behaviors[$name]; unset($this->_behaviors[$name]); @@ -511,6 +512,7 @@ class Component extends Object */ public function detachBehaviors() { + $this->ensureBehaviors(); if ($this->_behaviors !== null) { foreach ($this->_behaviors as $name => $behavior) { $this->detachBehavior($name); diff --git a/framework/base/Exception.php b/framework/base/Exception.php index 9ee698b..7d26bd0 100644 --- a/framework/base/Exception.php +++ b/framework/base/Exception.php @@ -22,4 +22,4 @@ class Exception extends \Exception { return \Yii::t('yii|Exception'); } -} \ No newline at end of file +} diff --git a/framework/base/View.php b/framework/base/View.php index a72982e..4718d90 100644 --- a/framework/base/View.php +++ b/framework/base/View.php @@ -744,10 +744,10 @@ class View extends Component { $lines = array(); if (!empty($this->metaTags)) { - $lines[] = implode("\n", $this->cssFiles); + $lines[] = implode("\n", $this->metaTags); } if (!empty($this->linkTags)) { - $lines[] = implode("\n", $this->cssFiles); + $lines[] = implode("\n", $this->linkTags); } if (!empty($this->cssFiles)) { $lines[] = implode("\n", $this->cssFiles); @@ -797,4 +797,4 @@ class View extends Component } return implode("\n", $lines); } -} \ No newline at end of file +} diff --git a/framework/base/ViewEvent.php b/framework/base/ViewEvent.php index cac7be4..f1ee7b9 100644 --- a/framework/base/ViewEvent.php +++ b/framework/base/ViewEvent.php @@ -41,4 +41,4 @@ class ViewEvent extends Event $this->viewFile = $viewFile; parent::__construct($config); } -} \ No newline at end of file +} diff --git a/framework/base/Widget.php b/framework/base/Widget.php index 13e6d30..c0c524f 100644 --- a/framework/base/Widget.php +++ b/framework/base/Widget.php @@ -83,7 +83,8 @@ class Widget extends Component */ public function render($view, $params = array()) { - return $this->view->render($view, $params, $this); + $viewFile = $this->findViewFile($view); + return $this->view->renderFile($viewFile, $params, $this); } /** @@ -133,4 +134,4 @@ class Widget extends Component return pathinfo($file, PATHINFO_EXTENSION) === '' ? $file . '.php' : $file; } -} \ No newline at end of file +} diff --git a/framework/caching/Cache.php b/framework/caching/Cache.php index fb56d5e..78f2854 100644 --- a/framework/caching/Cache.php +++ b/framework/caching/Cache.php @@ -349,4 +349,4 @@ abstract class Cache extends Component implements \ArrayAccess { $this->delete($key); } -} \ No newline at end of file +} diff --git a/framework/caching/Dependency.php b/framework/caching/Dependency.php index feb8c07..d1428fc 100644 --- a/framework/caching/Dependency.php +++ b/framework/caching/Dependency.php @@ -49,4 +49,4 @@ abstract class Dependency extends \yii\base\Object * @return mixed the data needed to determine if dependency has been changed. */ abstract protected function generateDependencyData(); -} \ No newline at end of file +} diff --git a/framework/caching/MemCacheServer.php b/framework/caching/MemCacheServer.php index 105137e..dc0de08 100644 --- a/framework/caching/MemCacheServer.php +++ b/framework/caching/MemCacheServer.php @@ -46,4 +46,4 @@ class MemCacheServer extends \yii\base\Object * @var boolean if the server should be flagged as online upon a failure. This is used by memcache only. */ public $status = true; -} \ No newline at end of file +} diff --git a/framework/caching/WinCache.php b/framework/caching/WinCache.php index ee6b4a9..4e07c7f 100644 --- a/framework/caching/WinCache.php +++ b/framework/caching/WinCache.php @@ -89,4 +89,4 @@ class WinCache extends Cache { return wincache_ucache_clear(); } -} \ No newline at end of file +} diff --git a/framework/console/Controller.php b/framework/console/Controller.php index c7c5642..2eaf4b8 100644 --- a/framework/console/Controller.php +++ b/framework/console/Controller.php @@ -147,4 +147,4 @@ class Controller extends \yii\base\Controller { return array(); } -} \ No newline at end of file +} diff --git a/framework/console/controllers/AppController.php b/framework/console/controllers/AppController.php index a47acfe..17f7420 100644 --- a/framework/console/controllers/AppController.php +++ b/framework/console/controllers/AppController.php @@ -321,4 +321,4 @@ class AppController extends Controller closedir($handle); return $list; } -} \ No newline at end of file +} diff --git a/framework/console/controllers/AssetController.php b/framework/console/controllers/AssetController.php index 71a2cae..aab489b 100644 --- a/framework/console/controllers/AssetController.php +++ b/framework/console/controllers/AssetController.php @@ -350,4 +350,4 @@ return array( EOD; file_put_contents($configFile, $template); } -} \ No newline at end of file +} diff --git a/framework/console/controllers/HelpController.php b/framework/console/controllers/HelpController.php index 74c354b..82bd6fe 100644 --- a/framework/console/controllers/HelpController.php +++ b/framework/console/controllers/HelpController.php @@ -418,4 +418,4 @@ class HelpController extends Controller $name = $required ? "$name (required)" : $name; return $doc === '' ? $name : "$name: $doc"; } -} \ No newline at end of file +} diff --git a/framework/console/webapp/config.php b/framework/console/webapp/config.php deleted file mode 100644 index 112fb18..0000000 --- a/framework/console/webapp/config.php +++ /dev/null @@ -1,17 +0,0 @@ - array( - 'index.php' => array( - 'handler' => function($source) use ($controller) { - return $controller->replaceRelativePath($source, realpath(YII_PATH.'/yii.php'), 'yii'); - }, - 'permissions' => 0777, - ), - 'protected/runtime' => array( - 'permissions' => 0755, - ), - ), -); \ No newline at end of file diff --git a/framework/console/webapp/default/index.php b/framework/console/webapp/default/index.php deleted file mode 100644 index b84e257..0000000 --- a/framework/console/webapp/default/index.php +++ /dev/null @@ -1,10 +0,0 @@ -run(); \ No newline at end of file diff --git a/framework/console/webapp/default/protected/config/main.php b/framework/console/webapp/default/protected/config/main.php deleted file mode 100644 index 795811e..0000000 --- a/framework/console/webapp/default/protected/config/main.php +++ /dev/null @@ -1,20 +0,0 @@ - 'webapp', - 'name' => 'My Web Application', - - 'components' => array( - // uncomment the following to use a MySQL database - /* - 'db' => array( - 'class' => 'yii\db\Connection', - 'dsn' => 'mysql:host=localhost;dbname=testdrive', - 'username' => 'root', - 'password' => '', - ), - */ - 'cache' => array( - 'class' => 'yii\caching\DummyCache', - ), - ), -); \ No newline at end of file diff --git a/framework/console/webapp/default/protected/controllers/SiteController.php b/framework/console/webapp/default/protected/controllers/SiteController.php deleted file mode 100644 index b47b93c..0000000 --- a/framework/console/webapp/default/protected/controllers/SiteController.php +++ /dev/null @@ -1,15 +0,0 @@ -render('index', array( - 'name' => 'Qiang', - )); - } -} \ No newline at end of file diff --git a/framework/console/webapp/default/protected/views/layouts/main.php b/framework/console/webapp/default/protected/views/layouts/main.php deleted file mode 100644 index 5c883e6..0000000 --- a/framework/console/webapp/default/protected/views/layouts/main.php +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - <?php echo Html::encode($this->title)?> - - -

title)?>

-
- -
- - - \ No newline at end of file diff --git a/framework/console/webapp/default/protected/views/site/index.php b/framework/console/webapp/default/protected/views/site/index.php deleted file mode 100644 index 0fb8784..0000000 --- a/framework/console/webapp/default/protected/views/site/index.php +++ /dev/null @@ -1 +0,0 @@ -Hello, ! \ No newline at end of file diff --git a/framework/db/ActiveQuery.php b/framework/db/ActiveQuery.php index 43c3059..3999600 100644 --- a/framework/db/ActiveQuery.php +++ b/framework/db/ActiveQuery.php @@ -88,7 +88,8 @@ class ActiveQuery extends Query { if (method_exists($this->modelClass, $name)) { array_unshift($params, $this); - return call_user_func_array(array($this->modelClass, $name), $params); + call_user_func_array(array($this->modelClass, $name), $params); + return $this; } else { return parent::__call($name, $params); } diff --git a/framework/db/ActiveRelation.php b/framework/db/ActiveRelation.php index f1b198b..97e2a8c 100644 --- a/framework/db/ActiveRelation.php +++ b/framework/db/ActiveRelation.php @@ -266,7 +266,7 @@ class ActiveRelation extends ActiveQuery { $attributes = array_keys($this->link); $values = array(); - if (count($attributes) ===1) { + if (count($attributes) === 1) { // single key $attribute = reset($this->link); foreach ($models as $model) { diff --git a/framework/db/Connection.php b/framework/db/Connection.php index 797508a..03b10a8 100644 --- a/framework/db/Connection.php +++ b/framework/db/Connection.php @@ -66,7 +66,7 @@ use yii\caching\Cache; * // ... executing other SQL statements ... * $transaction->commit(); * } catch(Exception $e) { - * $transaction->rollBack(); + * $transaction->rollback(); * } * ~~~ * @@ -517,7 +517,7 @@ class Connection extends Component public function quoteSql($sql) { $db = $this; - return preg_replace_callback('/(\\{\\{([\w\-\. ]+)\\}\\}|\\[\\[([\w\-\. ]+)\\]\\])/', + return preg_replace_callback('/(\\{\\{([%\w\-\. ]+)\\}\\}|\\[\\[([\w\-\. ]+)\\]\\])/', function($matches) use($db) { if (isset($matches[3])) { return $db->quoteColumnName($matches[3]); diff --git a/framework/db/Exception.php b/framework/db/Exception.php index ad97b5a..b7a60b4 100644 --- a/framework/db/Exception.php +++ b/framework/db/Exception.php @@ -41,4 +41,4 @@ class Exception extends \yii\base\Exception { return \Yii::t('yii|Database Exception'); } -} \ No newline at end of file +} diff --git a/framework/db/Expression.php b/framework/db/Expression.php index 4ebcd5f..77e9f60 100644 --- a/framework/db/Expression.php +++ b/framework/db/Expression.php @@ -57,4 +57,4 @@ class Expression extends \yii\base\Object { return $this->expression; } -} \ No newline at end of file +} diff --git a/framework/db/Migration.php b/framework/db/Migration.php index ce2cf97..f51e597 100644 --- a/framework/db/Migration.php +++ b/framework/db/Migration.php @@ -64,14 +64,14 @@ class Migration extends \yii\base\Component $transaction = $this->db->beginTransaction(); try { if ($this->safeUp() === false) { - $transaction->rollBack(); + $transaction->rollback(); return false; } $transaction->commit(); } catch (\Exception $e) { echo "Exception: " . $e->getMessage() . ' (' . $e->getFile() . ':' . $e->getLine() . ")\n"; echo $e->getTraceAsString() . "\n"; - $transaction->rollBack(); + $transaction->rollback(); return false; } return null; @@ -89,14 +89,14 @@ class Migration extends \yii\base\Component $transaction = $this->db->beginTransaction(); try { if ($this->safeDown() === false) { - $transaction->rollBack(); + $transaction->rollback(); return false; } $transaction->commit(); } catch (\Exception $e) { echo "Exception: " . $e->getMessage() . ' (' . $e->getFile() . ':' . $e->getLine() . ")\n"; echo $e->getTraceAsString() . "\n"; - $transaction->rollBack(); + $transaction->rollback(); return false; } return null; @@ -368,4 +368,4 @@ class Migration extends \yii\base\Component $this->db->createCommand()->dropIndex($name, $table)->execute(); echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; } -} \ No newline at end of file +} diff --git a/framework/db/Query.php b/framework/db/Query.php index 2239f5d..6f76265 100644 --- a/framework/db/Query.php +++ b/framework/db/Query.php @@ -483,7 +483,7 @@ class Query extends \yii\base\Component * Sets the ORDER BY part of the query. * @param string|array $columns the columns (and the directions) to be ordered by. * Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array - * (e.g. `array('id' => Query::SORT_ASC ASC, 'name' => Query::SORT_DESC)`). + * (e.g. `array('id' => Query::SORT_ASC, 'name' => Query::SORT_DESC)`). * The method will automatically quote the column names unless a column contains some parenthesis * (which means the column contains a DB expression). * @return Query the query object itself @@ -499,7 +499,7 @@ class Query extends \yii\base\Component * Adds additional ORDER BY columns to the query. * @param string|array $columns the columns (and the directions) to be ordered by. * Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array - * (e.g. `array('id' => Query::SORT_ASC ASC, 'name' => Query::SORT_DESC)`). + * (e.g. `array('id' => Query::SORT_ASC, 'name' => Query::SORT_DESC)`). * The method will automatically quote the column names unless a column contains some parenthesis * (which means the column contains a DB expression). * @return Query the query object itself diff --git a/framework/db/StaleObjectException.php b/framework/db/StaleObjectException.php index 860c9fc..0a04bd3 100644 --- a/framework/db/StaleObjectException.php +++ b/framework/db/StaleObjectException.php @@ -20,4 +20,4 @@ class StaleObjectException extends Exception { return \Yii::t('yii|Stale Object Exception'); } -} \ No newline at end of file +} diff --git a/framework/db/Transaction.php b/framework/db/Transaction.php index d66c38e..195a8c8 100644 --- a/framework/db/Transaction.php +++ b/framework/db/Transaction.php @@ -25,7 +25,7 @@ use yii\base\InvalidConfigException; * //.... other SQL executions * $transaction->commit(); * } catch(Exception $e) { - * $transaction->rollBack(); + * $transaction->rollback(); * } * ~~~ * @@ -42,14 +42,14 @@ class Transaction extends \yii\base\Object public $db; /** * @var boolean whether this transaction is active. Only an active transaction - * can [[commit()]] or [[rollBack()]]. This property is set true when the transaction is started. + * can [[commit()]] or [[rollback()]]. This property is set true when the transaction is started. */ private $_active = false; /** * Returns a value indicating whether this transaction is active. * @return boolean whether this transaction is active. Only an active transaction - * can [[commit()]] or [[rollBack()]]. + * can [[commit()]] or [[rollback()]]. */ public function getIsActive() { diff --git a/framework/helpers/ArrayHelper.php b/framework/helpers/ArrayHelper.php index 3061717..d58341c 100644 --- a/framework/helpers/ArrayHelper.php +++ b/framework/helpers/ArrayHelper.php @@ -16,4 +16,4 @@ namespace yii\helpers; */ class ArrayHelper extends base\ArrayHelper { -} \ No newline at end of file +} diff --git a/framework/helpers/FileHelper.php b/framework/helpers/FileHelper.php index 3fb24e1..04ce4e1 100644 --- a/framework/helpers/FileHelper.php +++ b/framework/helpers/FileHelper.php @@ -18,4 +18,4 @@ namespace yii\helpers; */ class FileHelper extends base\FileHelper { -} \ No newline at end of file +} diff --git a/framework/helpers/JsExpression.php b/framework/helpers/JsExpression.php index 0054b64..5a1f9bd 100644 --- a/framework/helpers/JsExpression.php +++ b/framework/helpers/JsExpression.php @@ -42,4 +42,4 @@ class JsExpression extends Object { return $this->expression; } -} \ No newline at end of file +} diff --git a/framework/helpers/Json.php b/framework/helpers/Json.php index 2a20f3c..5e77c3f 100644 --- a/framework/helpers/Json.php +++ b/framework/helpers/Json.php @@ -15,4 +15,4 @@ namespace yii\helpers; class Json extends base\Json { -} \ No newline at end of file +} diff --git a/framework/helpers/SecurityHelper.php b/framework/helpers/SecurityHelper.php index d3cb2ad..d16e7e6 100644 --- a/framework/helpers/SecurityHelper.php +++ b/framework/helpers/SecurityHelper.php @@ -26,4 +26,4 @@ namespace yii\helpers; */ class SecurityHelper extends base\SecurityHelper { -} \ No newline at end of file +} diff --git a/framework/helpers/VarDumper.php b/framework/helpers/VarDumper.php index 2659188..59a1718 100644 --- a/framework/helpers/VarDumper.php +++ b/framework/helpers/VarDumper.php @@ -25,4 +25,4 @@ namespace yii\helpers; */ class VarDumper extends base\VarDumper { -} \ No newline at end of file +} diff --git a/framework/helpers/base/ArrayHelper.php b/framework/helpers/base/ArrayHelper.php index 9870542..86445d7 100644 --- a/framework/helpers/base/ArrayHelper.php +++ b/framework/helpers/base/ArrayHelper.php @@ -236,15 +236,17 @@ class ArrayHelper * To sort by multiple keys, provide an array of keys here. * @param boolean|array $ascending whether to sort in ascending or descending order. When * sorting by multiple keys with different ascending orders, use an array of ascending flags. - * @param integer|array $sortFlag the PHP sort flag. Valid values include: - * `SORT_REGULAR`, `SORT_NUMERIC`, `SORT_STRING`, and `SORT_STRING | SORT_FLAG_CASE`. The last - * value is for sorting strings in case-insensitive manner. Please refer to - * See [PHP manual](http://php.net/manual/en/function.sort.php) for more details. - * When sorting by multiple keys with different sort flags, use an array of sort flags. + * @param integer|array $sortFlag the PHP sort flag. Valid values include + * `SORT_REGULAR`, `SORT_NUMERIC`, `SORT_STRING` and `SORT_LOCALE_STRING`. + * Please refer to [PHP manual](http://php.net/manual/en/function.sort.php) + * for more details. When sorting by multiple keys with different sort flags, use an array of sort flags. + * @param boolean|array $caseSensitive whether to sort string in case-sensitive manner. This parameter + * is used only when `$sortFlag` is `SORT_STRING`. + * When sorting by multiple keys with different case sensitivities, use an array of boolean values. * @throws InvalidParamException if the $ascending or $sortFlag parameters do not have * correct number of elements as that of $key. */ - public static function multisort(&$array, $key, $ascending = true, $sortFlag = SORT_REGULAR) + public static function multisort(&$array, $key, $ascending = true, $sortFlag = SORT_REGULAR, $caseSensitive = true) { $keys = is_array($key) ? $key : array($key); if (empty($keys) || empty($array)) { @@ -259,20 +261,30 @@ class ArrayHelper if (is_scalar($sortFlag)) { $sortFlag = array_fill(0, $n, $sortFlag); } elseif (count($sortFlag) !== $n) { - throw new InvalidParamException('The length of $ascending parameter must be the same as that of $keys.'); + throw new InvalidParamException('The length of $sortFlag parameter must be the same as that of $keys.'); + } + if (is_scalar($caseSensitive)) { + $caseSensitive = array_fill(0, $n, $caseSensitive); + } elseif (count($caseSensitive) !== $n) { + throw new InvalidParamException('The length of $caseSensitive parameter must be the same as that of $keys.'); } $args = array(); foreach ($keys as $i => $key) { $flag = $sortFlag[$i]; - if ($flag == (SORT_STRING | SORT_FLAG_CASE)) { - $flag = SORT_STRING; - $column = array(); - foreach (static::getColumn($array, $key) as $k => $value) { - $column[$k] = strtolower($value); + $cs = $caseSensitive[$i]; + if (!$cs && ($flag === SORT_STRING)) { + if (defined('SORT_FLAG_CASE')) { + $flag = $flag | SORT_FLAG_CASE; + $args[] = static::getColumn($array, $key); + } else { + $column = array(); + foreach (static::getColumn($array, $key) as $k => $value) { + $column[$k] = mb_strtolower($value); + } + $args[] = $column; } - $args[] = $column; } else { - $args[] = static::getColumn($array, $key); + $args[] = static::getColumn($array, $key); } $args[] = $ascending[$i] ? SORT_ASC : SORT_DESC; $args[] = $flag; @@ -337,4 +349,4 @@ class ArrayHelper } return $d; } -} \ No newline at end of file +} diff --git a/framework/helpers/base/FileHelper.php b/framework/helpers/base/FileHelper.php index 2f62f43..954c86e 100644 --- a/framework/helpers/base/FileHelper.php +++ b/framework/helpers/base/FileHelper.php @@ -169,4 +169,4 @@ class FileHelper } closedir($handle); } -} \ No newline at end of file +} diff --git a/framework/helpers/base/Html.php b/framework/helpers/base/Html.php index 5b8e7db..15db823 100644 --- a/framework/helpers/base/Html.php +++ b/framework/helpers/base/Html.php @@ -95,9 +95,9 @@ class Html public static $attributeOrder = array( 'type', 'id', + 'class', 'name', 'value', - 'class', 'href', 'src', @@ -127,13 +127,15 @@ class Html * Encodes special characters into HTML entities. * The [[yii\base\Application::charset|application charset]] will be used for encoding. * @param string $content the content to be encoded + * @param boolean $doubleEncode whether to encode HTML entities in `$content`. If false, + * HTML entities in `$content` will not be further encoded. * @return string the encoded content * @see decode * @see http://www.php.net/manual/en/function.htmlspecialchars.php */ - public static function encode($content) + public static function encode($content, $doubleEncode = true) { - return htmlspecialchars($content, ENT_QUOTES, Yii::$app->charset); + return htmlspecialchars($content, ENT_QUOTES, Yii::$app->charset, $doubleEncode); } /** @@ -375,7 +377,8 @@ class Html */ public static function mailto($text, $email = null, $options = array()) { - return static::a($text, 'mailto:' . ($email === null ? $text : $email), $options); + $options['href'] = 'mailto:' . ($email === null ? $text : $email); + return static::tag('a', $text, $options); } /** diff --git a/framework/helpers/base/Json.php b/framework/helpers/base/Json.php index 1deb5c2..c92e208 100644 --- a/framework/helpers/base/Json.php +++ b/framework/helpers/base/Json.php @@ -104,4 +104,4 @@ class Json return $data; } } -} \ No newline at end of file +} diff --git a/framework/helpers/base/SecurityHelper.php b/framework/helpers/base/SecurityHelper.php index 6ba48ba..3f69fee 100644 --- a/framework/helpers/base/SecurityHelper.php +++ b/framework/helpers/base/SecurityHelper.php @@ -42,7 +42,8 @@ class SecurityHelper public static function encrypt($data, $key) { $module = static::openCryptModule(); - $key = StringHelper::substr($key, 0, mcrypt_enc_get_key_size($module)); + // 192-bit (24 bytes) key size + $key = StringHelper::substr($key, 0, 24); srand(); $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($module), MCRYPT_RAND); mcrypt_generic_init($module, $key, $iv); @@ -63,7 +64,8 @@ class SecurityHelper public static function decrypt($data, $key) { $module = static::openCryptModule(); - $key = StringHelper::substr($key, 0, mcrypt_enc_get_key_size($module)); + // 192-bit (24 bytes) key size + $key = StringHelper::substr($key, 0, 24); $ivSize = mcrypt_enc_get_iv_size($module); $iv = StringHelper::substr($data, 0, $ivSize); mcrypt_generic_init($module, $key, $iv); @@ -148,7 +150,8 @@ class SecurityHelper if (!extension_loaded('mcrypt')) { throw new InvalidConfigException('The mcrypt PHP extension is not installed.'); } - $module = @mcrypt_module_open('rijndael-256', '', MCRYPT_MODE_CBC, ''); + // AES uses a 128-bit block size + $module = @mcrypt_module_open('rijndael-128', '', 'cbc', ''); if ($module === false) { throw new Exception('Failed to initialize the mcrypt module.'); } @@ -164,11 +167,11 @@ class SecurityHelper * * ~~~ * // generates the hash (usually done during user registration or when the password is changed) - * $hash = SecurityHelper::hashPassword($password); + * $hash = SecurityHelper::generatePasswordHash($password); * // ...save $hash in database... * * // during login, validate if the password entered is correct using $hash fetched from database - * if (PasswordHelper::verifyPassword($password, $hash) { + * if (SecurityHelper::verifyPassword($password, $hash) { * // password is good * } else { * // password is bad @@ -214,7 +217,7 @@ class SecurityHelper throw new InvalidParamException('Password must be a string and cannot be empty.'); } - if (!preg_match('/^\$2[axy]\$(\d\d)\$[\./0-9A-Za-z]{22}/', $hash, $matches) || $matches[1] < 4 || $matches[1] > 30) { + if (!preg_match('/^\$2[axy]\$(\d\d)\$[\.\/0-9A-Za-z]{22}/', $hash, $matches) || $matches[1] < 4 || $matches[1] > 30) { throw new InvalidParamException('Hash is invalid.'); } @@ -269,4 +272,4 @@ class SecurityHelper $salt .= str_replace('+', '.', substr(base64_encode($rand), 0, 22)); return $salt; } -} \ No newline at end of file +} diff --git a/framework/helpers/base/VarDumper.php b/framework/helpers/base/VarDumper.php index fe15d98..730aafe 100644 --- a/framework/helpers/base/VarDumper.php +++ b/framework/helpers/base/VarDumper.php @@ -39,7 +39,7 @@ class VarDumper */ public static function dump($var, $depth = 10, $highlight = false) { - echo self::dumpAsString($var, $depth, $highlight); + echo static::dumpAsString($var, $depth, $highlight); } /** @@ -116,7 +116,7 @@ class VarDumper } elseif (self::$_depth <= $level) { self::$_output .= get_class($var) . '(...)'; } else { - $id = self::$_objects[] = $var; + $id = array_push(self::$_objects, $var); $className = get_class($var); $members = (array)$var; $spaces = str_repeat(' ', $level * 4); @@ -131,4 +131,4 @@ class VarDumper break; } } -} \ No newline at end of file +} diff --git a/framework/i18n/PhpMessageSource.php b/framework/i18n/PhpMessageSource.php index 1ada44a..f62939f 100644 --- a/framework/i18n/PhpMessageSource.php +++ b/framework/i18n/PhpMessageSource.php @@ -76,4 +76,4 @@ class PhpMessageSource extends MessageSource return array(); } } -} \ No newline at end of file +} diff --git a/framework/i18n/data/plurals.php b/framework/i18n/data/plurals.php index 52c733b..468f7e2 100644 --- a/framework/i18n/data/plurals.php +++ b/framework/i18n/data/plurals.php @@ -624,4 +624,4 @@ return array ( array ( 0 => 'in_array(fmod($n,10),array(1,2))||fmod($n,20)==0', ), -); \ No newline at end of file +); diff --git a/framework/logging/EmailTarget.php b/framework/logging/EmailTarget.php index 4c84739..bb02e34 100644 --- a/framework/logging/EmailTarget.php +++ b/framework/logging/EmailTarget.php @@ -69,4 +69,4 @@ class EmailTarget extends Target } mail($sentTo, $subject, $body, implode("\r\n", $headers)); } -} \ No newline at end of file +} diff --git a/framework/logging/ProfileTarget.php b/framework/logging/ProfileTarget.php index 2b6ffe6..335e172 100644 --- a/framework/logging/ProfileTarget.php +++ b/framework/logging/ProfileTarget.php @@ -189,4 +189,4 @@ class CProfileLogRoute extends CWebLogRoute $total += $delta; return array($token, $calls, $min, $max, $total); } -} \ No newline at end of file +} diff --git a/framework/logging/Target.php b/framework/logging/Target.php index e76e8ac..311334d 100644 --- a/framework/logging/Target.php +++ b/framework/logging/Target.php @@ -89,7 +89,7 @@ abstract class Target extends \yii\base\Component */ public function collect($messages, $final) { - $this->_messages = array($this->_messages, $this->filterMessages($messages)); + $this->_messages = array_merge($this->_messages, $this->filterMessages($messages)); $count = count($this->_messages); if ($count > 0 && ($final || $this->exportInterval > 0 && $count >= $this->exportInterval)) { if (($context = $this->getContextMessage()) !== '') { diff --git a/framework/logging/WebTarget.php b/framework/logging/WebTarget.php index b71e1a2..c98fd9f 100644 --- a/framework/logging/WebTarget.php +++ b/framework/logging/WebTarget.php @@ -58,4 +58,4 @@ class CWebLogRoute extends CLogRoute $viewFile = YII_PATH . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . $view . '.php'; include($app->findLocalizedFile($viewFile, 'en')); } -} \ No newline at end of file +} diff --git a/framework/renderers/SmartyViewRenderer.php b/framework/renderers/SmartyViewRenderer.php index 920f3c6..29d7b97 100644 --- a/framework/renderers/SmartyViewRenderer.php +++ b/framework/renderers/SmartyViewRenderer.php @@ -102,4 +102,4 @@ class SmartyViewRenderer extends ViewRenderer return $template->fetch(); } -} \ No newline at end of file +} diff --git a/framework/validators/FileValidator.php b/framework/validators/FileValidator.php index 0fddcf5..ebe6cad 100644 --- a/framework/validators/FileValidator.php +++ b/framework/validators/FileValidator.php @@ -192,11 +192,11 @@ class FileValidator extends Validator break; case UPLOAD_ERR_CANT_WRITE: $this->addError($object, $attribute, $this->message); - Yii::warning('Failed to write the uploaded file to disk: ', $file->getName(), __METHOD__); + Yii::warning('Failed to write the uploaded file to disk: ' . $file->getName(), __METHOD__); break; case UPLOAD_ERR_EXTENSION: $this->addError($object, $attribute, $this->message); - Yii::warning('File upload was stopped by some PHP extension: ', $file->getName(), __METHOD__); + Yii::warning('File upload was stopped by some PHP extension: ' . $file->getName(), __METHOD__); break; default: break; @@ -248,4 +248,4 @@ class FileValidator extends Validator return (int)$sizeStr; } } -} \ No newline at end of file +} diff --git a/framework/validators/InlineValidator.php b/framework/validators/InlineValidator.php index 3689a2f..8af5bbc 100644 --- a/framework/validators/InlineValidator.php +++ b/framework/validators/InlineValidator.php @@ -96,4 +96,4 @@ class InlineValidator extends Validator return null; } } -} \ No newline at end of file +} diff --git a/framework/validators/NumberValidator.php b/framework/validators/NumberValidator.php index d0a4002..c0f81cd 100644 --- a/framework/validators/NumberValidator.php +++ b/framework/validators/NumberValidator.php @@ -151,4 +151,4 @@ class NumberValidator extends Validator return 'yii.validation.number(value, messages, ' . Json::encode($options) . ');'; } -} \ No newline at end of file +} diff --git a/framework/validators/UniqueValidator.php b/framework/validators/UniqueValidator.php index 2240e0a..7072ff4 100644 --- a/framework/validators/UniqueValidator.php +++ b/framework/validators/UniqueValidator.php @@ -97,4 +97,4 @@ class UniqueValidator extends Validator $this->addError($object, $attribute, $this->message); } } -} \ No newline at end of file +} diff --git a/framework/views/error.php b/framework/views/error.php index 548d04b..009050a 100644 --- a/framework/views/error.php +++ b/framework/views/error.php @@ -64,4 +64,4 @@ $title = $context->htmlEncode($exception instanceof \yii\base\Exception ? $excep versionInfo : ''?> - \ No newline at end of file + diff --git a/framework/web/AccessControl.php b/framework/web/AccessControl.php index f5983ae..e890510 100644 --- a/framework/web/AccessControl.php +++ b/framework/web/AccessControl.php @@ -103,4 +103,4 @@ class AccessControl extends ActionFilter throw new HttpException(403, Yii::t('yii|You are not allowed to perform this action.')); } } -} \ No newline at end of file +} diff --git a/framework/web/AccessRule.php b/framework/web/AccessRule.php index 3f8c057..e565e18 100644 --- a/framework/web/AccessRule.php +++ b/framework/web/AccessRule.php @@ -9,9 +9,6 @@ namespace yii\web; use yii\base\Component; use yii\base\Action; -use yii\base\Controller; -use yii\web\User; -use yii\web\Request; /** * @@ -144,7 +141,7 @@ class AccessRule extends Component return true; } elseif ($role === '@' && !$user->getIsGuest()) { return true; - } elseif ($user->hasAccess($role)) { + } elseif ($user->checkAccess($role)) { return true; } } @@ -185,4 +182,4 @@ class AccessRule extends Component { return empty($this->matchCallback) || call_user_func($this->matchCallback, $this, $action); } -} \ No newline at end of file +} diff --git a/framework/web/AssetBundle.php b/framework/web/AssetBundle.php index 4e1eb59..37577dd 100644 --- a/framework/web/AssetBundle.php +++ b/framework/web/AssetBundle.php @@ -173,4 +173,4 @@ class AssetBundle extends Object } } } -} \ No newline at end of file +} diff --git a/framework/web/AssetConverter.php b/framework/web/AssetConverter.php index 8340be5..4fde1fc 100644 --- a/framework/web/AssetConverter.php +++ b/framework/web/AssetConverter.php @@ -53,10 +53,10 @@ class AssetConverter extends Component implements IAssetConverter )); exec($command, $output); Yii::info("Converted $asset into $result: " . implode("\n", $output), __METHOD__); - return "$baseUrl/$result"; } + return "$baseUrl/$result"; } } return "$baseUrl/$asset"; } -} \ No newline at end of file +} diff --git a/framework/web/Controller.php b/framework/web/Controller.php index 099bf96..517f4b4 100644 --- a/framework/web/Controller.php +++ b/framework/web/Controller.php @@ -40,4 +40,4 @@ class Controller extends \yii\base\Controller } return Yii::$app->getUrlManager()->createUrl($route, $params); } -} \ No newline at end of file +} diff --git a/framework/web/HttpCache.php b/framework/web/HttpCache.php index f64b37f..0a3bb86 100644 --- a/framework/web/HttpCache.php +++ b/framework/web/HttpCache.php @@ -128,4 +128,4 @@ class HttpCache extends ActionFilter { return '"' . base64_encode(sha1($seed, true)) . '"'; } -} \ No newline at end of file +} diff --git a/framework/web/IAssetConverter.php b/framework/web/IAssetConverter.php index 4334d3e..d1d1da0 100644 --- a/framework/web/IAssetConverter.php +++ b/framework/web/IAssetConverter.php @@ -24,4 +24,4 @@ interface IAssetConverter * need conversion, "$baseUrl/$asset" should be returned. */ public function convert($asset, $basePath, $baseUrl); -} \ No newline at end of file +} diff --git a/framework/web/Identity.php b/framework/web/Identity.php index 6d67bc0..101ecdb 100644 --- a/framework/web/Identity.php +++ b/framework/web/Identity.php @@ -78,4 +78,4 @@ interface Identity * @see getAuthKey() */ public function validateAuthKey($authKey); -} \ No newline at end of file +} diff --git a/framework/web/PageCache.php b/framework/web/PageCache.php index 5a50825..2fe36b3 100644 --- a/framework/web/PageCache.php +++ b/framework/web/PageCache.php @@ -101,4 +101,4 @@ class PageCache extends ActionFilter { $this->view->endCache(); } -} \ No newline at end of file +} diff --git a/framework/web/Pagination.php b/framework/web/Pagination.php index 1d41c0c..764dbb4 100644 --- a/framework/web/Pagination.php +++ b/framework/web/Pagination.php @@ -205,4 +205,4 @@ class Pagination extends \yii\base\Object { return $this->pageSize < 1 ? -1 : $this->pageSize; } -} \ No newline at end of file +} diff --git a/framework/web/Request.php b/framework/web/Request.php index ac19d5a..5e2f064 100644 --- a/framework/web/Request.php +++ b/framework/web/Request.php @@ -96,7 +96,7 @@ class Request extends \yii\base\Request */ public function getIsPostRequest() { - return isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'], 'POST'); + return $this->getRequestMethod() === 'POST'; } /** diff --git a/framework/web/Sort.php b/framework/web/Sort.php index e5c2451..99084c1 100644 --- a/framework/web/Sort.php +++ b/framework/web/Sort.php @@ -333,4 +333,4 @@ class Sort extends \yii\base\Object return false; } } -} \ No newline at end of file +} diff --git a/framework/web/UploadedFile.php b/framework/web/UploadedFile.php index c67281c..6e685a3 100644 --- a/framework/web/UploadedFile.php +++ b/framework/web/UploadedFile.php @@ -7,7 +7,7 @@ namespace yii\web; -use yii\widgets\ActiveForm; +use yii\widgets\Html; /** * @author Qiang Xue @@ -66,7 +66,7 @@ class UploadedFile extends \yii\base\Object */ public static function getInstance($model, $attribute) { - $name = ActiveForm::getInputName($model, $attribute); + $name = Html::getInputName($model, $attribute); return static::getInstanceByName($name); } @@ -80,7 +80,7 @@ class UploadedFile extends \yii\base\Object */ public static function getInstances($model, $attribute) { - $name = ActiveForm::getInputName($model, $attribute); + $name = Html::getInputName($model, $attribute); return static::getInstancesByName($name); } diff --git a/framework/web/UrlManager.php b/framework/web/UrlManager.php index 318f329..a300033 100644 --- a/framework/web/UrlManager.php +++ b/framework/web/UrlManager.php @@ -51,7 +51,7 @@ class UrlManager extends Component * @var boolean whether to show entry script name in the constructed URL. Defaults to true. * This property is used only if [[enablePrettyUrl]] is true. */ - public $showScriptName = true; + public $showScriptName = false; /** * @var string the GET variable name for route. This property is used only if [[enablePrettyUrl]] is false. */ @@ -174,7 +174,7 @@ class UrlManager extends Component public function createUrl($route, $params = array()) { $anchor = isset($params['#']) ? '#' . $params['#'] : ''; - unset($params['#']); + unset($params['#'], $params[$this->routeVar]); $route = trim($route, '/'); $baseUrl = $this->getBaseUrl(); diff --git a/framework/web/User.php b/framework/web/User.php index b8bf7cd..88fc12d 100644 --- a/framework/web/User.php +++ b/framework/web/User.php @@ -447,4 +447,21 @@ class User extends Component } } } + + /** + * Checks whether the user has access to the specified operation. + * @param $operator + * @param array $params + * @return bool + * @todo + */ + public function checkAccess($operation, $params = array()) + { + $auth = Yii::$app->getAuthManager(); + if ($auth !== null) { + return $auth->checkAccess($this->getId(), $operation, $params); + } else { + return false; + } + } } diff --git a/framework/web/UserEvent.php b/framework/web/UserEvent.php index 7a5d23d..4e39380 100644 --- a/framework/web/UserEvent.php +++ b/framework/web/UserEvent.php @@ -31,4 +31,4 @@ class UserEvent extends Event * This property is only meaningful for [[User::EVENT_BEFORE_LOGIN]] and [[User::EVENT_BEFORE_LOGOUT]] events. */ public $isValid = true; -} \ No newline at end of file +} diff --git a/framework/widgets/ActiveField.php b/framework/widgets/ActiveField.php index da17012..336966f 100644 --- a/framework/widgets/ActiveField.php +++ b/framework/widgets/ActiveField.php @@ -541,4 +541,4 @@ class ActiveField extends Component . '' ); } -} \ No newline at end of file +} diff --git a/framework/widgets/Block.php b/framework/widgets/Block.php index d6f7317..fdd210f 100644 --- a/framework/widgets/Block.php +++ b/framework/widgets/Block.php @@ -46,4 +46,4 @@ class Block extends Widget } $this->view->blocks[$this->id] = $block; } -} \ No newline at end of file +} diff --git a/framework/widgets/FragmentCache.php b/framework/widgets/FragmentCache.php index 637d115..5b37f6e 100644 --- a/framework/widgets/FragmentCache.php +++ b/framework/widgets/FragmentCache.php @@ -171,4 +171,4 @@ class FragmentCache extends Widget } return $this->cache->buildKey($factors); } -} \ No newline at end of file +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..bf37a26 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,13 @@ + + + + + ./tests/unit + + + \ No newline at end of file diff --git a/readme.md b/readme.md index 2e6fcc0..f395e95 100644 --- a/readme.md +++ b/readme.md @@ -1,66 +1,40 @@ -Yii 2 Web Programming Framework -=============================== +Yii 2.0 Public Preview +====================== -Thank you for choosing Yii 2 — a high-performance component-based PHP framework. +Thank you for choosing Yii - a high-performance component-based PHP framework. +If you are looking for a production-ready PHP framework, please use +[Yii v1.1](https://github.com/yiisoft/yii). + +Yii 2.0 is still under heavy development. We may make significant changes +without prior notices. **Yii 2.0 is not ready for production use yet.** -INSTALLATION ------------- -Please make sure the release file is unpacked under a Web-accessible -directory. You shall see the following files and directories: +DIRECTORY STRUCTURE +------------------- - demos/ demos + apps/ ready-to-use Web apps built on Yii 2 + bootstrap/ a simple app supporting user login and contact page + build/ internally used build tools + docs/ documentation framework/ framework source files - requirements/ requirement checker - changelog.md describing changes in every Yii release - license.md license of Yii - readme.md this file - upgrade.md upgrading instructions + tests/ tests of the core framework code REQUIREMENTS ------------ -The minimum requirement by Yii is that your Web server supports -PHP 5.3.8 or above. Yii has been tested with Apache HTTP server -on Windows and Linux operating systems. - -Please access the following URL to check if your Web server reaches -the requirements by Yii, assuming "YiiPath" is where Yii is installed: - - http://hostname/YiiPath/requirements/index.php - - -QUICK START ------------ - -Yii comes with a command line tool called "yiic" that can create -a skeleton Yii application for you to start with. - -On a command line, type in the following commands: - - for Linux - $ cd YiiPath/framework - $ ./yiic webapp ../testdrive - - for Windows - cd YiiPath\framework - yiic webapp ..\testdrive - -The new Yii application will be created at "YiiPath/testdrive". -You can access it with the following URL: - - http://hostname/YiiPath/testdrive/index.php - +The minimum requirement by Yii is that your Web server supports PHP 5.3.?. -WHAT's NEXT ------------ -Please visit the project website for tutorials, class reference -and join discussions with other Yii users. +HOW TO PARTICIPATE +------------------ +You are welcome to participate in Yii 2 development in the following ways: +* [Report issues](https://github.com/yiisoft/yii2/issues) +* [Give us feedback or start a design discussion](http://www.yiiframework.com/forum/index.php/forum/42-design-discussions-for-yii-20/) +* Fix issues, develop features, write/polish documentation + - Before you start, please adopt an existing issue (labelled with "ready for adoption") or start a new one to avoid duplicated efforts. + - Please submit a merge request after you finish development. -The Yii Developer Team -http://www.yiiframework.com \ No newline at end of file diff --git a/tests/unit/MysqlTestCase.php b/tests/unit/MysqlTestCase.php index e1a1f7e..c7ef970 100644 --- a/tests/unit/MysqlTestCase.php +++ b/tests/unit/MysqlTestCase.php @@ -33,4 +33,4 @@ class MysqlTestCase extends TestCase } return $db; } -} \ No newline at end of file +} diff --git a/tests/unit/TestCase.php b/tests/unit/TestCase.php index 458c6f3..dccd3af 100644 --- a/tests/unit/TestCase.php +++ b/tests/unit/TestCase.php @@ -13,4 +13,4 @@ class TestCase extends \yii\test\TestCase } return isset(self::$params[$name]) ? self::$params[$name] : null; } -} \ No newline at end of file +} diff --git a/tests/unit/data/ar/ActiveRecord.php b/tests/unit/data/ar/ActiveRecord.php index 95346de..f1194ea 100644 --- a/tests/unit/data/ar/ActiveRecord.php +++ b/tests/unit/data/ar/ActiveRecord.php @@ -23,4 +23,4 @@ class ActiveRecord extends \yii\db\ActiveRecord { return self::$db; } -} \ No newline at end of file +} diff --git a/tests/unit/data/ar/Customer.php b/tests/unit/data/ar/Customer.php index a090b7f..b26b51b 100644 --- a/tests/unit/data/ar/Customer.php +++ b/tests/unit/data/ar/Customer.php @@ -22,6 +22,6 @@ class Customer extends ActiveRecord public static function active($query) { - return $query->andWhere('status=1'); + $query->andWhere('status=1'); } -} \ No newline at end of file +} diff --git a/tests/unit/data/ar/Item.php b/tests/unit/data/ar/Item.php index 279893f..5d23378 100644 --- a/tests/unit/data/ar/Item.php +++ b/tests/unit/data/ar/Item.php @@ -8,4 +8,4 @@ class Item extends ActiveRecord { return 'tbl_item'; } -} \ No newline at end of file +} diff --git a/tests/unit/data/ar/Order.php b/tests/unit/data/ar/Order.php index 38257d6..f9dd715 100644 --- a/tests/unit/data/ar/Order.php +++ b/tests/unit/data/ar/Order.php @@ -43,4 +43,4 @@ class Order extends ActiveRecord return false; } } -} \ No newline at end of file +} diff --git a/tests/unit/data/ar/OrderItem.php b/tests/unit/data/ar/OrderItem.php index f879749..607133e 100644 --- a/tests/unit/data/ar/OrderItem.php +++ b/tests/unit/data/ar/OrderItem.php @@ -18,4 +18,4 @@ class OrderItem extends ActiveRecord { return $this->hasOne('Item', array('id' => 'item_id')); } -} \ No newline at end of file +} diff --git a/tests/unit/data/base/Singer.php b/tests/unit/data/base/Singer.php index 3305b98..f1b91e1 100644 --- a/tests/unit/data/base/Singer.php +++ b/tests/unit/data/base/Singer.php @@ -18,4 +18,4 @@ class Singer extends Model array('underscore_style', 'yii\validators\CaptchaValidator'), ); } -} \ No newline at end of file +} diff --git a/tests/unit/data/config.php b/tests/unit/data/config.php index fc15690..238a7cc 100644 --- a/tests/unit/data/config.php +++ b/tests/unit/data/config.php @@ -3,7 +3,7 @@ return array( 'mysql' => array( 'dsn' => 'mysql:host=127.0.0.1;dbname=yiitest', - 'username' => 'root', + 'username' => 'travis', 'password' => '', 'fixture' => __DIR__ . '/mysql.sql', ), diff --git a/tests/unit/framework/base/ComponentTest.php b/tests/unit/framework/base/ComponentTest.php index 74b6e9a..7c860e3 100644 --- a/tests/unit/framework/base/ComponentTest.php +++ b/tests/unit/framework/base/ComponentTest.php @@ -387,4 +387,4 @@ class NewComponent2 extends Component $this->b = $b; $this->c = $c; } -} \ No newline at end of file +} diff --git a/tests/unit/framework/base/ObjectTest.php b/tests/unit/framework/base/ObjectTest.php index b47b178..14856e2 100644 --- a/tests/unit/framework/base/ObjectTest.php +++ b/tests/unit/framework/base/ObjectTest.php @@ -181,4 +181,4 @@ class NewObject extends Object { return $this->_items; } -} \ No newline at end of file +} diff --git a/tests/unit/framework/caching/ApcCacheTest.php b/tests/unit/framework/caching/ApcCacheTest.php index 74ede2a..859f6a6 100644 --- a/tests/unit/framework/caching/ApcCacheTest.php +++ b/tests/unit/framework/caching/ApcCacheTest.php @@ -17,6 +17,8 @@ class ApcCacheTest extends CacheTest { if(!extension_loaded("apc")) { $this->markTestSkipped("APC not installed. Skipping."); + } else if ('cli' === PHP_SAPI && !ini_get('apc.enable_cli')) { + $this->markTestSkipped("APC cli is not enabled. Skipping."); } if($this->_cacheInstance === null) { @@ -24,4 +26,4 @@ class ApcCacheTest extends CacheTest } return $this->_cacheInstance; } -} \ No newline at end of file +} diff --git a/tests/unit/framework/caching/DbCacheTest.php b/tests/unit/framework/caching/DbCacheTest.php index 594e946..a41667c 100644 --- a/tests/unit/framework/caching/DbCacheTest.php +++ b/tests/unit/framework/caching/DbCacheTest.php @@ -67,4 +67,4 @@ class DbCacheTest extends CacheTest } return $this->_cacheInstance; } -} \ No newline at end of file +} diff --git a/tests/unit/framework/caching/FileCacheTest.php b/tests/unit/framework/caching/FileCacheTest.php index 1f6debd..37d3222 100644 --- a/tests/unit/framework/caching/FileCacheTest.php +++ b/tests/unit/framework/caching/FileCacheTest.php @@ -22,4 +22,4 @@ class FileCacheTest extends CacheTest } return $this->_cacheInstance; } -} \ No newline at end of file +} diff --git a/tests/unit/framework/caching/MemCacheTest.php b/tests/unit/framework/caching/MemCacheTest.php index e4804d9..40dba12 100644 --- a/tests/unit/framework/caching/MemCacheTest.php +++ b/tests/unit/framework/caching/MemCacheTest.php @@ -24,4 +24,4 @@ class MemCacheTest extends CacheTest } return $this->_cacheInstance; } -} \ No newline at end of file +} diff --git a/tests/unit/framework/caching/MemCachedTest.php b/tests/unit/framework/caching/MemCachedTest.php index 59396df..c9e437c 100644 --- a/tests/unit/framework/caching/MemCachedTest.php +++ b/tests/unit/framework/caching/MemCachedTest.php @@ -26,4 +26,4 @@ class MemCachedTest extends CacheTest } return $this->_cacheInstance; } -} \ No newline at end of file +} diff --git a/tests/unit/framework/caching/WinCacheTest.php b/tests/unit/framework/caching/WinCacheTest.php index b78d57b..c9470bd 100644 --- a/tests/unit/framework/caching/WinCacheTest.php +++ b/tests/unit/framework/caching/WinCacheTest.php @@ -28,4 +28,4 @@ class WinCacheTest extends CacheTest } return $this->_cacheInstance; } -} \ No newline at end of file +} diff --git a/tests/unit/framework/caching/XCacheTest.php b/tests/unit/framework/caching/XCacheTest.php index e1ed844..b5e41a6 100644 --- a/tests/unit/framework/caching/XCacheTest.php +++ b/tests/unit/framework/caching/XCacheTest.php @@ -24,4 +24,4 @@ class XCacheTest extends CacheTest } return $this->_cacheInstance; } -} \ No newline at end of file +} diff --git a/tests/unit/framework/caching/ZendDataCacheTest.php b/tests/unit/framework/caching/ZendDataCacheTest.php index 91dfbb5..86c06c8 100644 --- a/tests/unit/framework/caching/ZendDataCacheTest.php +++ b/tests/unit/framework/caching/ZendDataCacheTest.php @@ -24,4 +24,4 @@ class ZendDataCacheTest extends CacheTest } return $this->_cacheInstance; } -} \ No newline at end of file +} diff --git a/tests/unit/framework/db/ActiveRecordTest.php b/tests/unit/framework/db/ActiveRecordTest.php index 3b8c2b5..f0ea968 100644 --- a/tests/unit/framework/db/ActiveRecordTest.php +++ b/tests/unit/framework/db/ActiveRecordTest.php @@ -356,4 +356,4 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase $customers = Customer::find()->all(); $this->assertEquals(0, count($customers)); } -} \ No newline at end of file +} diff --git a/tests/unit/framework/db/CommandTest.php b/tests/unit/framework/db/CommandTest.php index d505f6d..2576e78 100644 --- a/tests/unit/framework/db/CommandTest.php +++ b/tests/unit/framework/db/CommandTest.php @@ -289,4 +289,4 @@ class CommandTest extends \yiiunit\MysqlTestCase { } -} \ No newline at end of file +} diff --git a/tests/unit/framework/db/QueryTest.php b/tests/unit/framework/db/QueryTest.php index 2c4359f..1c730cd 100644 --- a/tests/unit/framework/db/QueryTest.php +++ b/tests/unit/framework/db/QueryTest.php @@ -113,4 +113,4 @@ class QueryTest extends \yiiunit\MysqlTestCase { } -} \ No newline at end of file +} diff --git a/tests/unit/framework/helpers/ArrayHelperTest.php b/tests/unit/framework/helpers/ArrayHelperTest.php index 187217f..b3ffabf 100644 --- a/tests/unit/framework/helpers/ArrayHelperTest.php +++ b/tests/unit/framework/helpers/ArrayHelperTest.php @@ -40,11 +40,20 @@ class ArrayHelperTest extends \yii\test\TestCase $array = array( array('name' => 'a', 'age' => 3), array('name' => 'b', 'age' => 2), + array('name' => 'B', 'age' => 4), array('name' => 'A', 'age' => 1), ); - ArrayHelper::multisort($array, array('name', 'age'), SORT_ASC, array(SORT_STRING|SORT_FLAG_CASE, SORT_REGULAR)); + + ArrayHelper::multisort($array, array('name', 'age'), SORT_ASC, array(SORT_STRING, SORT_REGULAR)); + $this->assertEquals(array('name' => 'A', 'age' => 1), $array[0]); + $this->assertEquals(array('name' => 'B', 'age' => 4), $array[1]); + $this->assertEquals(array('name' => 'a', 'age' => 3), $array[2]); + $this->assertEquals(array('name' => 'b', 'age' => 2), $array[3]); + + ArrayHelper::multisort($array, array('name', 'age'), SORT_ASC, array(SORT_STRING, SORT_REGULAR), false); $this->assertEquals(array('name' => 'A', 'age' => 1), $array[0]); $this->assertEquals(array('name' => 'a', 'age' => 3), $array[1]); $this->assertEquals(array('name' => 'b', 'age' => 2), $array[2]); + $this->assertEquals(array('name' => 'B', 'age' => 4), $array[3]); } } diff --git a/tests/unit/framework/helpers/JsonTest.php b/tests/unit/framework/helpers/JsonTest.php index 0e06eb3..6a78cd1 100644 --- a/tests/unit/framework/helpers/JsonTest.php +++ b/tests/unit/framework/helpers/JsonTest.php @@ -57,4 +57,4 @@ class JsonTest extends \yii\test\TestCase $this->setExpectedException('yii\base\InvalidParamException'); Json::decode($json); } -} \ No newline at end of file +} diff --git a/tests/unit/framework/helpers/StringHelperTest.php b/tests/unit/framework/helpers/StringHelperTest.php index 4e1266f..c37aafd 100644 --- a/tests/unit/framework/helpers/StringHelperTest.php +++ b/tests/unit/framework/helpers/StringHelperTest.php @@ -70,4 +70,4 @@ class StringHelperTest extends \yii\test\TestCase $this->assertEquals('PostTag', StringHelper::id2camel('post-tag')); $this->assertEquals('PostTag', StringHelper::id2camel('post_tag', '_')); } -} \ No newline at end of file +} diff --git a/tests/unit/framework/helpers/VarDumperTest.php b/tests/unit/framework/helpers/VarDumperTest.php new file mode 100644 index 0000000..a797121 --- /dev/null +++ b/tests/unit/framework/helpers/VarDumperTest.php @@ -0,0 +1,12 @@ +assertTrue($validator->validateValue('sam@rmcreative.ru')); $this->assertFalse($validator->validateValue('test@example.com')); } -} \ No newline at end of file +} diff --git a/tests/unit/phpunit.xml b/tests/unit/phpunit.xml deleted file mode 100644 index 17db94e..0000000 --- a/tests/unit/phpunit.xml +++ /dev/null @@ -1,7 +0,0 @@ - - \ No newline at end of file diff --git a/tests/web/app/protected/config/main.php b/tests/web/app/protected/config/main.php index eed6d54..d5be5de 100644 --- a/tests/web/app/protected/config/main.php +++ b/tests/web/app/protected/config/main.php @@ -1,3 +1,3 @@