diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 000000000..011c056bb
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,8 @@
+# Reformat code te be PSR-2 compatible
+93cc82c4bf42cea403e1acaab201338bea304b6e
+# Convert to short syntax (array)
+332030325fbad38a64c5e60980d3b14b6434d6dd
+# Convert to short syntax
+b0fcdfab1aecaeb620f75a83f15aa02bc25765a0
+# Fix codestyle
+0f91f32ecff52ef479addb0a5013342d59fe0697
diff --git a/.gitattributes b/.gitattributes
index 3e9092c68..705fb391d 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,6 +1,7 @@
# Ignore all test and documentation for archive
-/.github export-ignore
-/.gitattributes export-ignore
-/.scrutinizer.yml export-ignore
-/.travis.yml export-ignore
-/docs export-ignore
+/.github export-ignore
+/.git-blame-ignore-revs export-ignore
+/.gitattributes export-ignore
+/.scrutinizer.yml export-ignore
+/.travis.yml export-ignore
+/docs export-ignore
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 3d8d32c25..ea75bda5f 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -3,5 +3,5 @@ Contributing to Yii2
- [Report an issue](https://github.com/yiisoft/yii2/blob/master/docs/internals/report-an-issue.md)
- [Translate documentation or messages](https://github.com/yiisoft/yii2/blob/master/docs/internals/translation-workflow.md)
-- [Give us feedback or start a design discussion](http://www.yiiframework.com/forum/index.php/forum/42-general-discussions-for-yii-20/)
+- [Give us feedback or start a design discussion](https://www.yiiframework.com/forum/index.php/forum/42-general-discussions-for-yii-20/)
- [Contribute to the core code or fix bugs](https://github.com/yiisoft/yii2/blob/master/docs/internals/git-workflow.md)
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 52ec8692f..a2ee92439 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -9,6 +9,6 @@
| Q | A
| ---------------- | ---
-| Yii vesion |
+| Yii version |
| PHP version |
| Operating system |
diff --git a/.github/SECURITY.md b/.github/SECURITY.md
index f71384759..405acca4e 100644
--- a/.github/SECURITY.md
+++ b/.github/SECURITY.md
@@ -3,4 +3,4 @@
Please use the [security issue form](https://www.yiiframework.com/security) to report to us any security issue you find in Yii.
DO NOT use the issue tracker or discuss it in the public forum as it will cause more damage than help.
-Please note that as a non-commerial OpenSource project we are not able to pay bounties at the moment.
+Please note that as a non-commercial OpenSource project we are not able to pay bounties at the moment.
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 000000000..a5beac653
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,83 @@
+on:
+ - pull_request
+ - push
+
+name: build
+
+jobs:
+ tests:
+ name: PHP ${{ matrix.php }} - ${{ matrix.os }}
+
+ env:
+ extensions: dom, json, gd, imagick
+ key: cache-v4
+
+ runs-on: ${{ matrix.os }}
+
+ strategy:
+ matrix:
+ os:
+ - ubuntu-latest
+ - windows-latest
+
+ php:
+ - "7.4"
+ - "8.0"
+ - "8.1"
+ - "8.2"
+ - "8.3"
+ - "8.4"
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Setup cache environment
+ id: cache-env
+ uses: shivammathur/cache-extensions@v1
+ with:
+ php-version: ${{ matrix.php }}
+ extensions: ${{ env.extensions }}
+ key: ${{ env.key }}
+
+ - name: Cache extensions
+ uses: actions/cache@v4
+ with:
+ path: ${{ steps.cache-env.outputs.dir }}
+ key: ${{ steps.cache-env.outputs.key }}
+ restore-keys: ${{ steps.cache-env.outputs.key }}
+
+ - name: Install PHP with extensions
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ extensions: ${{ env.extensions }}
+ ini-values: date.timezone='UTC'
+
+ - name: Determine composer cache directory on Linux
+ if: matrix.os == 'ubuntu-latest'
+ run: |
+ echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV
+
+ - name: Determine composer cache directory on Windows
+ if: matrix.os == 'windows-latest'
+ run: |
+ echo "COMPOSER_CACHE_DIR=~\AppData\Local\Composer" >> $GITHUB_ENV
+
+ - name: Cache dependencies installed with composer
+ uses: actions/cache@v4
+ with:
+ path: ${{ steps.cache-env.outputs.dir }}
+ key: php${{ matrix.php }}-composer-${{ matrix.dependencies }}-${{ hashFiles('**/composer.json') }}
+ restore-keys: |
+ php${{ matrix.php }}-composer-${{ matrix.dependencies }}-
+
+ - name: Install dependencies with composer php PHP [5.6 - 8.0]
+ run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
+
+ - name: Run tests with codeception
+ run: |
+ sed -i "s/'cookieValidationKey' => ''/'cookieValidationKey' => 'testkey'/" config/web.php
+ php -S 127.0.0.1:8080 -t public > ./runtime/yii.log 2>&1 &
+ vendor/bin/codecept run
+ shell: bash
diff --git a/.gitignore b/.gitignore
index 5bd9be80b..05fb29d1b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,9 @@
# phpstorm project files
.idea
+# visual studio code project files
+.vscode
+
# netbeans project files
nbproject
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 4583c1bf4..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-language: php
-
-matrix:
- fast_finish: true
- include:
- - php: "7.3"
- - php: "7.2"
- - php: "7.1"
- - php: "7.0"
- - php: "5.6"
-
-# faster builds on new travis setup not using sudo
-sudo: false
-
-# cache vendor dirs
-cache:
- directories:
- - $HOME/.composer/cache
-
-services:
- - mysql
-
-before_install:
- - mysql -e 'CREATE DATABASE IF NOT EXISTS yii2_basic_tests;'
-
-install:
- - travis_retry composer self-update && composer --version
- - travis_retry composer update --dev --prefer-dist --no-interaction
- # install php extensions
- - |
- if (php --version | grep -i HipHop > /dev/null); then
- echo "Skipping imagick and gmagick tests on HHVM"
- else
- pear config-set preferred_state beta
- printf "\n" | pecl install imagick
- # gmagick is not installed on travis currently
- #printf "\n" | pecl install gmagick
- fi
-# setup application:
- - |
- sed -i "s/'cookieValidationKey' => ''/'cookieValidationKey' => 'testkey'/" config/web.php
-
-script:
- - |
- php -S localhost:8080 -t web > /dev/null 2>&1 &
- vendor/bin/codecept run
diff --git a/README.md b/README.md
index fe3c1528f..981a7f9d9 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
-Yii 2 Basic Project Template is a skeleton [Yii 2](http://www.yiiframework.com/) application best for
+Yii 2 Basic Project Template is a skeleton [Yii 2](https://www.yiiframework.com/) application best for
rapidly creating small projects.
The template contains the basic features including user login/logout and a contact page.
@@ -15,7 +15,7 @@ features to your application.
[](https://packagist.org/packages/yiisoft/yii2-app-basic)
[](https://packagist.org/packages/yiisoft/yii2-app-basic)
-[](https://travis-ci.com/yiisoft/yii2-app-basic)
+[](https://github.com/yiisoft/yii2-app-basic/actions?query=workflow%3Abuild)
DIRECTORY STRUCTURE
-------------------
@@ -37,7 +37,7 @@ DIRECTORY STRUCTURE
REQUIREMENTS
------------
-The minimum requirement by this project template that your Web server supports PHP 5.6.0.
+The minimum requirement by this project template that your Web server supports PHP 7.4.
INSTALLATION
@@ -45,8 +45,8 @@ INSTALLATION
### Install via Composer
-If you do not have [Composer](http://getcomposer.org/), you may install it by following the instructions
-at [getcomposer.org](http://getcomposer.org/doc/00-intro.md#installation-nix).
+If you do not have [Composer](https://getcomposer.org/), you may install it by following the instructions
+at [getcomposer.org](https://getcomposer.org/doc/00-intro.md#installation-nix).
You can then install this project template using the following command:
@@ -63,7 +63,7 @@ http://localhost/basic/web/
### Install from an Archive File
-Extract the archive file downloaded from [yiiframework.com](http://www.yiiframework.com/download/) to
+Extract the archive file downloaded from [yiiframework.com](https://www.yiiframework.com/download/) to
a directory named `basic` that is directly under the Web root.
Set cookie validation key in `config/web.php` file to some random secret string:
@@ -131,8 +131,8 @@ return [
TESTING
-------
-Tests are located in `tests` directory. They are developed with [Codeception PHP Testing Framework](http://codeception.com/).
-By default there are 3 test suites:
+Tests are located in `tests` directory. They are developed with [Codeception PHP Testing Framework](https://codeception.com/).
+By default, there are 3 test suites:
- `unit`
- `functional`
@@ -155,7 +155,7 @@ To execute acceptance tests do the following:
1. Rename `tests/acceptance.suite.yml.example` to `tests/acceptance.suite.yml` to enable suite configuration
-2. Replace `codeception/base` package in `composer.json` with `codeception/codeception` to install full featured
+2. Replace `codeception/base` package in `composer.json` with `codeception/codeception` to install full-featured
version of Codeception
3. Update dependencies with Composer
@@ -164,7 +164,7 @@ To execute acceptance tests do the following:
composer update
```
-4. Download [Selenium Server](http://www.seleniumhq.org/download/) and launch it:
+4. Download [Selenium Server](https://www.seleniumhq.org/download/) and launch it:
```
java -jar ~/selenium-server-standalone-x.xx.x.jar
@@ -186,7 +186,7 @@ To execute acceptance tests do the following:
docker run --net=host selenium/standalone-firefox:2.53.0
```
-5. (Optional) Create `yii2_basic_tests` database and update it by applying migrations if you have them.
+5. (Optional) Create `yii2basic_test` database and update it by applying migrations if you have them.
```
tests/bin/yii migrate
@@ -221,13 +221,13 @@ to collect code coverage. You can run your tests and collect coverage with the f
```
#collect coverage for all tests
-vendor/bin/codecept run -- --coverage-html --coverage-xml
+vendor/bin/codecept run --coverage --coverage-html --coverage-xml
#collect coverage only for unit tests
-vendor/bin/codecept run unit -- --coverage-html --coverage-xml
+vendor/bin/codecept run unit --coverage --coverage-html --coverage-xml
#collect coverage for unit and functional tests
-vendor/bin/codecept run functional,unit -- --coverage-html --coverage-xml
+vendor/bin/codecept run functional,unit --coverage --coverage-html --coverage-xml
```
You can see code coverage output under the `tests/_output` directory.
diff --git a/Vagrantfile b/Vagrantfile
index 44fd76c6d..258aea601 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -1,9 +1,20 @@
require 'yaml'
require 'fileutils'
+required_plugins_installed = nil
required_plugins = %w( vagrant-hostmanager vagrant-vbguest )
required_plugins.each do |plugin|
- exec "vagrant plugin install #{plugin}" unless Vagrant.has_plugin? plugin
+ unless Vagrant.has_plugin? plugin
+ system "vagrant plugin install #{plugin}"
+ required_plugins_installed = true
+ end
+end
+
+# IF plugin[s] was just installed - restart required
+if required_plugins_installed
+ # Get CLI command[s] and call again
+ system 'vagrant' + ARGV.to_s.gsub(/\[\"|\", \"|\"\]/, ' ')
+ exit
end
domains = {
@@ -31,7 +42,7 @@ end
# vagrant configurate
Vagrant.configure(2) do |config|
# select the box
- config.vm.box = 'bento/ubuntu-16.04'
+ config.vm.box = 'bento/ubuntu-18.04'
# should we ask about box updates?
config.vm.box_check_update = options['box_check_update']
@@ -72,7 +83,7 @@ Vagrant.configure(2) do |config|
# config.vbguest.auto_update = false
# provisioners
- config.vm.provision 'shell', path: './vagrant/provision/once-as-root.sh', args: [options['timezone']]
+ config.vm.provision 'shell', path: './vagrant/provision/once-as-root.sh', args: [options['timezone'], options['ip']]
config.vm.provision 'shell', path: './vagrant/provision/once-as-vagrant.sh', args: [options['github_token']], privileged: false
config.vm.provision 'shell', path: './vagrant/provision/always-as-root.sh', run: 'always'
diff --git a/assets/AppAsset.php b/assets/AppAsset.php
index 47932b165..d9d4cc430 100644
--- a/assets/AppAsset.php
+++ b/assets/AppAsset.php
@@ -1,8 +1,9 @@
=5.6.0",
- "yiisoft/yii2": "~2.0.14",
- "yiisoft/yii2-bootstrap": "~2.0.0",
- "yiisoft/yii2-swiftmailer": "~2.0.0 || ~2.1.0"
+ "php": ">=7.4.0",
+ "yiisoft/yii2": "~2.0.45",
+ "yiisoft/yii2-bootstrap5": "~2.0.2",
+ "yiisoft/yii2-symfonymailer": "~2.0.3"
},
"require-dev": {
"yiisoft/yii2-debug": "~2.1.0",
- "yiisoft/yii2-gii": "~2.1.0",
+ "yiisoft/yii2-gii": "~2.2.0",
"yiisoft/yii2-faker": "~2.0.0",
- "codeception/codeception": "^4.0",
- "codeception/verify": "~0.5.0 || ~1.1.0",
- "codeception/specify": "~0.4.6",
- "symfony/browser-kit": ">=2.7 <=4.2.4",
- "codeception/module-filesystem": "^1.0.0",
- "codeception/module-yii2": "^1.0.0",
- "codeception/module-asserts": "^1.0.0"
+ "codeception/codeception": "^5.0.0 || ^4.0",
+ "codeception/lib-innerbrowser": "^4.0 || ^3.0 || ^1.1",
+ "codeception/module-asserts": "^3.0 || ^1.1",
+ "codeception/module-yii2": "^1.1",
+ "codeception/module-filesystem": "^3.0 || ^2.0 || ^1.1",
+ "codeception/verify": "^3.0 || ^2.2"
},
"config": {
+ "allow-plugins": {
+ "yiisoft/yii2-composer" : true
+ },
"process-timeout": 1800,
"fxp-asset": {
"enabled": false
diff --git a/config/__autocomplete.php b/config/__autocomplete.php
new file mode 100644
index 000000000..e5e1c00d7
--- /dev/null
+++ b/config/__autocomplete.php
@@ -0,0 +1,35 @@
+ 'yii\gii\Module',
];
+ // configuration adjustments for 'dev' environment
+ // requires version `2.1.21` of yii2-debug module
+ $config['bootstrap'][] = 'debug';
+ $config['modules']['debug'] = [
+ 'class' => 'yii\debug\Module',
+ // uncomment the following to add your IP if you are not connecting from localhost.
+ //'allowedIPs' => ['127.0.0.1', '::1'],
+ ];
}
return $config;
diff --git a/config/test.php b/config/test.php
index f95bc031e..fb5e2929e 100644
--- a/config/test.php
+++ b/config/test.php
@@ -1,4 +1,5 @@
[
'db' => $db,
'mailer' => [
+ 'class' => \yii\symfonymailer\Mailer::class,
+ 'viewPath' => '@app/mail',
+ // send all mails to a file by default.
'useFileTransport' => true,
+ 'messageClass' => 'yii\symfonymailer\Message'
],
'assetManager' => [
'basePath' => __DIR__ . '/../web/assets',
diff --git a/config/test_db.php b/config/test_db.php
index 5d213e135..f10835fe1 100644
--- a/config/test_db.php
+++ b/config/test_db.php
@@ -1,6 +1,7 @@
'site/error',
],
'mailer' => [
- 'class' => 'yii\swiftmailer\Mailer',
- // send all mails to a file by default. You have to set
- // 'useFileTransport' to false and configure a transport
- // for the mailer to send real emails.
+ 'class' => \yii\symfonymailer\Mailer::class,
+ 'viewPath' => '@app/mail',
+ // send all mails to a file by default.
'useFileTransport' => true,
],
'log' => [
diff --git a/controllers/SiteController.php b/controllers/SiteController.php
index 6e8a85d10..67c3f50f8 100644
--- a/controllers/SiteController.php
+++ b/controllers/SiteController.php
@@ -19,7 +19,7 @@ public function behaviors()
{
return [
'access' => [
- 'class' => AccessControl::className(),
+ 'class' => AccessControl::class,
'only' => ['logout'],
'rules' => [
[
@@ -30,7 +30,7 @@ public function behaviors()
],
],
'verbs' => [
- 'class' => VerbFilter::className(),
+ 'class' => VerbFilter::class,
'actions' => [
'logout' => ['post'],
],
diff --git a/docker-compose.yml b/docker-compose.yml
index c3800ff53..86be3bd0d 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,9 +1,9 @@
version: '2'
services:
php:
- image: yiisoftware/yii2-php:7.1-apache
+ image: yiisoftware/yii2-php:7.4-apache
volumes:
- ~/.composer-docker/cache:/root/.composer/cache:delegated
- ./:/app:delegated
ports:
- - '8000:80'
\ No newline at end of file
+ - '8000:80'
diff --git a/mail/layouts/html.php b/mail/layouts/html.php
index bddbc6129..95732cdfa 100644
--- a/mail/layouts/html.php
+++ b/mail/layouts/html.php
@@ -1,9 +1,9 @@
beginPage() ?>
diff --git a/mail/layouts/text.php b/mail/layouts/text.php
new file mode 100644
index 000000000..0873d7728
--- /dev/null
+++ b/mail/layouts/text.php
@@ -0,0 +1,13 @@
+beginPage();
+$this->beginBody();
+echo $content;
+$this->endBody();
+$this->endPage();
diff --git a/models/LoginForm.php b/models/LoginForm.php
index cc6af264c..5304eecf4 100644
--- a/models/LoginForm.php
+++ b/models/LoginForm.php
@@ -8,7 +8,7 @@
/**
* LoginForm is the model behind the login form.
*
- * @property User|null $user This property is read-only.
+ * @property-read User|null $user
*
*/
class LoginForm extends Model
@@ -60,7 +60,7 @@ public function validatePassword($attribute, $params)
public function login()
{
if ($this->validate()) {
- return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
+ return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
}
return false;
}
diff --git a/requirements.php b/requirements.php
index 6cf322eb0..db69a36ee 100644
--- a/requirements.php
+++ b/requirements.php
@@ -1,4 +1,5 @@
'Memcache extension',
'mandatory' => false,
'condition' => extension_loaded('memcache') || extension_loaded('memcached'),
- 'by' => 'MemCache',
- 'memo' => extension_loaded('memcached') ? 'To use memcached set MemCache::useMemcached to true.' : ''
+ 'by' => 'MemCache',
+ 'memo' => extension_loaded('memcached') ? 'To use memcached set MemCache::useMemcached to true.' : ''
),
// CAPTCHA:
array(
'name' => 'GD PHP extension with FreeType support',
'mandatory' => false,
'condition' => $gdOK,
- 'by' => 'Captcha',
+ 'by' => 'Captcha',
'memo' => $gdMemo,
),
array(
'name' => 'ImageMagick PHP extension with PNG support',
'mandatory' => false,
'condition' => $imagickOK,
- 'by' => 'Captcha',
+ 'by' => 'Captcha',
'memo' => $imagickMemo,
),
// PHP ini :
@@ -153,7 +154,7 @@
'name' => 'APC extension',
'mandatory' => false,
'condition' => extension_loaded('apc'),
- 'by' => 'ApcCache',
+ 'by' => 'ApcCache',
);
}
diff --git a/tests/_bootstrap.php b/tests/_bootstrap.php
index 131da42af..4b8424f73 100644
--- a/tests/_bootstrap.php
+++ b/tests/_bootstrap.php
@@ -1,6 +1,7 @@
amOnPage(Url::toRoute('/site/contact'));
}
-
+
public function contactPageWorks(AcceptanceTester $I)
{
$I->wantTo('ensure that contact page works');
@@ -25,7 +25,7 @@ public function contactFormCanBeSubmitted(AcceptanceTester $I)
$I->fillField('#contactform-verifycode', 'testme');
$I->click('contact-button');
-
+
$I->wait(2); // wait for button to be clicked
$I->dontSeeElement('#contact-form');
diff --git a/tests/acceptance/HomeCest.php b/tests/acceptance/HomeCest.php
index e65df16ae..98fb6b9f7 100644
--- a/tests/acceptance/HomeCest.php
+++ b/tests/acceptance/HomeCest.php
@@ -6,13 +6,13 @@ class HomeCest
{
public function ensureThatHomePageWorks(AcceptanceTester $I)
{
- $I->amOnPage(Url::toRoute('/site/index'));
+ $I->amOnPage(Url::toRoute('/site/index'));
$I->see('My Company');
-
+
$I->seeLink('About');
$I->click('About');
$I->wait(2); // wait for page to be opened
-
+
$I->see('This is the About page.');
}
}
diff --git a/tests/bin/yii b/tests/bin/yii
index 4923537fb..39df4013d 100755
--- a/tests/bin/yii
+++ b/tests/bin/yii
@@ -3,9 +3,9 @@
/**
* Yii console bootstrap file.
*
- * @link http://www.yiiframework.com/
+ * @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
- * @license http://www.yiiframework.com/license/
+ * @license https://www.yiiframework.com/license/
*/
defined('YII_DEBUG') or define('YII_DEBUG', true);
diff --git a/tests/bin/yii.bat b/tests/bin/yii.bat
index d516b3a19..ce14c92bc 100644
--- a/tests/bin/yii.bat
+++ b/tests/bin/yii.bat
@@ -4,9 +4,9 @@ rem -------------------------------------------------------------
rem Yii command line bootstrap script for Windows.
rem
rem @author Qiang Xue
-rem @link http://www.yiiframework.com/
+rem @link https://www.yiiframework.com/
rem @copyright Copyright (c) 2008 Yii Software LLC
-rem @license http://www.yiiframework.com/license/
+rem @license https://www.yiiframework.com/license/
rem -------------------------------------------------------------
@setlocal
diff --git a/tests/functional.suite.yml b/tests/functional.suite.yml
index 374c6df45..9d8cf149c 100644
--- a/tests/functional.suite.yml
+++ b/tests/functional.suite.yml
@@ -6,8 +6,9 @@
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
#basic/web/index.php
-class_name: FunctionalTester
+actor: FunctionalTester
modules:
enabled:
- Filesystem
- Yii2
+ - Asserts
diff --git a/tests/functional/ContactFormCest.php b/tests/functional/ContactFormCest.php
index ad8167865..f1ccaf18f 100644
--- a/tests/functional/ContactFormCest.php
+++ b/tests/functional/ContactFormCest.php
@@ -1,15 +1,15 @@
amOnPage(['site/contact']);
+ $I->amOnRoute('site/contact');
}
public function openContactPage(\FunctionalTester $I)
{
- $I->see('Contact', 'h1');
+ $I->see('Contact', 'h1');
}
public function submitEmptyForm(\FunctionalTester $I)
@@ -38,7 +38,7 @@ public function submitFormWithIncorrectEmail(\FunctionalTester $I)
$I->see('Email is not a valid email address.');
$I->dontSee('Subject cannot be blank', '.help-inline');
$I->dontSee('Body cannot be blank', '.help-inline');
- $I->dontSee('The verification code is incorrect', '.help-inline');
+ $I->dontSee('The verification code is incorrect', '.help-inline');
}
public function submitFormSuccessfully(\FunctionalTester $I)
@@ -52,6 +52,6 @@ public function submitFormSuccessfully(\FunctionalTester $I)
]);
$I->seeEmailIsSent();
$I->dontSeeElement('#contact-form');
- $I->see('Thank you for contacting us. We will respond to you as soon as possible.');
+ $I->see('Thank you for contacting us. We will respond to you as soon as possible.');
}
}
diff --git a/tests/functional/LoginFormCest.php b/tests/functional/LoginFormCest.php
index 7a83a27d6..a1545a706 100644
--- a/tests/functional/LoginFormCest.php
+++ b/tests/functional/LoginFormCest.php
@@ -10,7 +10,6 @@ public function _before(\FunctionalTester $I)
public function openLoginPage(\FunctionalTester $I)
{
$I->see('Login', 'h1');
-
}
// demonstrates `amLoggedInAs` method
@@ -54,6 +53,6 @@ public function loginSuccessfully(\FunctionalTester $I)
'LoginForm[password]' => 'admin',
]);
$I->see('Logout (admin)');
- $I->dontSeeElement('form#login-form');
+ $I->dontSeeElement('form#login-form');
}
-}
\ No newline at end of file
+}
diff --git a/tests/unit.suite.yml b/tests/unit.suite.yml
index d2e6622f8..c14e49c37 100644
--- a/tests/unit.suite.yml
+++ b/tests/unit.suite.yml
@@ -3,7 +3,7 @@
# suite for unit (internal) tests.
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
-class_name: UnitTester
+actor: UnitTester
modules:
enabled:
- Asserts
diff --git a/tests/unit/models/ContactFormTest.php b/tests/unit/models/ContactFormTest.php
index 074448771..1bb1bb2d0 100644
--- a/tests/unit/models/ContactFormTest.php
+++ b/tests/unit/models/ContactFormTest.php
@@ -7,7 +7,6 @@
class ContactFormTest extends \Codeception\Test\Unit
{
- private $model;
/**
* @var \UnitTester
*/
@@ -15,34 +14,28 @@ class ContactFormTest extends \Codeception\Test\Unit
public function testEmailIsSentOnContact()
{
- /** @var ContactForm $model */
- $this->model = $this->getMockBuilder('app\models\ContactForm')
- ->setMethods(['validate'])
- ->getMock();
+ $model = new ContactForm();
- $this->model->expects($this->once())
- ->method('validate')
- ->willReturn(true);
-
- $this->model->attributes = [
+ $model->attributes = [
'name' => 'Tester',
'email' => 'tester@example.com',
'subject' => 'very important letter subject',
'body' => 'body of current message',
+ 'verifyCode' => 'testme',
];
- expect_that($this->model->contact('admin@example.com'));
+ verify($model->contact('admin@example.com'))->notEmpty();
// using Yii2 module actions to check email was sent
$this->tester->seeEmailIsSent();
/** @var MessageInterface $emailMessage */
$emailMessage = $this->tester->grabLastSentEmail();
- expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface');
- expect($emailMessage->getTo())->hasKey('admin@example.com');
- expect($emailMessage->getFrom())->hasKey('noreply@example.com');
- expect($emailMessage->getReplyTo())->hasKey('tester@example.com');
- expect($emailMessage->getSubject())->equals('very important letter subject');
- expect($emailMessage->toString())->stringContainsString('body of current message');
+ verify($emailMessage)->instanceOf('yii\mail\MessageInterface');
+ verify($emailMessage->getTo())->arrayHasKey('admin@example.com');
+ verify($emailMessage->getFrom())->arrayHasKey('noreply@example.com');
+ verify($emailMessage->getReplyTo())->arrayHasKey('tester@example.com');
+ verify($emailMessage->getSubject())->equals('very important letter subject');
+ verify($emailMessage->toString())->stringContainsString('body of current message');
}
}
diff --git a/tests/unit/models/LoginFormTest.php b/tests/unit/models/LoginFormTest.php
index ecdb14512..6f96c2377 100644
--- a/tests/unit/models/LoginFormTest.php
+++ b/tests/unit/models/LoginFormTest.php
@@ -20,8 +20,8 @@ public function testLoginNoUser()
'password' => 'not_existing_password',
]);
- expect_not($this->model->login());
- expect_that(\Yii::$app->user->isGuest);
+ verify($this->model->login())->false();
+ verify(\Yii::$app->user->isGuest)->true();
}
public function testLoginWrongPassword()
@@ -31,9 +31,9 @@ public function testLoginWrongPassword()
'password' => 'wrong_password',
]);
- expect_not($this->model->login());
- expect_that(\Yii::$app->user->isGuest);
- expect($this->model->errors)->hasKey('password');
+ verify($this->model->login())->false();
+ verify(\Yii::$app->user->isGuest)->true();
+ verify($this->model->errors)->arrayHasKey('password');
}
public function testLoginCorrect()
@@ -43,9 +43,8 @@ public function testLoginCorrect()
'password' => 'demo',
]);
- expect_that($this->model->login());
- expect_not(\Yii::$app->user->isGuest);
- expect($this->model->errors)->hasntKey('password');
+ verify($this->model->login())->true();
+ verify(\Yii::$app->user->isGuest)->false();
+ verify($this->model->errors)->arrayHasNotKey('password');
}
-
}
diff --git a/tests/unit/models/UserTest.php b/tests/unit/models/UserTest.php
index cb612785f..3db9772a3 100644
--- a/tests/unit/models/UserTest.php
+++ b/tests/unit/models/UserTest.php
@@ -8,37 +8,36 @@ class UserTest extends \Codeception\Test\Unit
{
public function testFindUserById()
{
- expect_that($user = User::findIdentity(100));
- expect($user->username)->equals('admin');
+ verify($user = User::findIdentity(100))->notEmpty();
+ verify($user->username)->equals('admin');
- expect_not(User::findIdentity(999));
+ verify(User::findIdentity(999))->empty();
}
public function testFindUserByAccessToken()
{
- expect_that($user = User::findIdentityByAccessToken('100-token'));
- expect($user->username)->equals('admin');
+ verify($user = User::findIdentityByAccessToken('100-token'))->notEmpty();
+ verify($user->username)->equals('admin');
- expect_not(User::findIdentityByAccessToken('non-existing'));
+ verify(User::findIdentityByAccessToken('non-existing'))->empty();
}
public function testFindUserByUsername()
{
- expect_that($user = User::findByUsername('admin'));
- expect_not(User::findByUsername('not-admin'));
+ verify($user = User::findByUsername('admin'))->notEmpty();
+ verify(User::findByUsername('not-admin'))->empty();
}
/**
* @depends testFindUserByUsername
*/
- public function testValidateUser($user)
+ public function testValidateUser()
{
$user = User::findByUsername('admin');
- expect_that($user->validateAuthKey('test100key'));
- expect_not($user->validateAuthKey('test102key'));
+ verify($user->validateAuthKey('test100key'))->notEmpty();
+ verify($user->validateAuthKey('test102key'))->empty();
- expect_that($user->validatePassword('admin'));
- expect_not($user->validatePassword('123456'));
+ verify($user->validatePassword('admin'))->notEmpty();
+ verify($user->validatePassword('123456'))->empty();
}
-
}
diff --git a/tests/unit/widgets/AlertTest.php b/tests/unit/widgets/AlertTest.php
new file mode 100644
index 000000000..af2db5d21
--- /dev/null
+++ b/tests/unit/widgets/AlertTest.php
@@ -0,0 +1,263 @@
+session->setFlash('error', $message);
+
+ $renderingResult = Alert::widget();
+
+ verify($renderingResult)->stringContainsString($message);
+ verify($renderingResult)->stringContainsString('alert-danger');
+
+ verify($renderingResult)->stringNotContainsString('alert-success');
+ verify($renderingResult)->stringNotContainsString('alert-info');
+ verify($renderingResult)->stringNotContainsString('alert-warning');
+ }
+
+ public function testMultipleErrorMessages()
+ {
+ $firstMessage = 'This is the first error message';
+ $secondMessage = 'This is the second error message';
+
+ Yii::$app->session->setFlash('error', [$firstMessage, $secondMessage]);
+
+ $renderingResult = Alert::widget();
+
+ verify($renderingResult)->stringContainsString($firstMessage);
+ verify($renderingResult)->stringContainsString($secondMessage);
+ verify($renderingResult)->stringContainsString('alert-danger');
+
+ verify($renderingResult)->stringNotContainsString('alert-success');
+ verify($renderingResult)->stringNotContainsString('alert-info');
+ verify($renderingResult)->stringNotContainsString('alert-warning');
+ }
+
+ public function testSingleDangerMessage()
+ {
+ $message = 'This is a danger message';
+
+ Yii::$app->session->setFlash('danger', $message);
+
+ $renderingResult = Alert::widget();
+
+ verify($renderingResult)->stringContainsString($message);
+ verify($renderingResult)->stringContainsString('alert-danger');
+
+ verify($renderingResult)->stringNotContainsString('alert-success');
+ verify($renderingResult)->stringNotContainsString('alert-info');
+ verify($renderingResult)->stringNotContainsString('alert-warning');
+ }
+
+ public function testMultipleDangerMessages()
+ {
+ $firstMessage = 'This is the first danger message';
+ $secondMessage = 'This is the second danger message';
+
+ Yii::$app->session->setFlash('danger', [$firstMessage, $secondMessage]);
+
+ $renderingResult = Alert::widget();
+
+ verify($renderingResult)->stringContainsString($firstMessage);
+ verify($renderingResult)->stringContainsString($secondMessage);
+ verify($renderingResult)->stringContainsString('alert-danger');
+
+ verify($renderingResult)->stringNotContainsString('alert-success');
+ verify($renderingResult)->stringNotContainsString('alert-info');
+ verify($renderingResult)->stringNotContainsString('alert-warning');
+ }
+
+ public function testSingleSuccessMessage()
+ {
+ $message = 'This is a success message';
+
+ Yii::$app->session->setFlash('success', $message);
+
+ $renderingResult = Alert::widget();
+
+ verify($renderingResult)->stringContainsString($message);
+ verify($renderingResult)->stringContainsString('alert-success');
+
+ verify($renderingResult)->stringNotContainsString('alert-danger');
+ verify($renderingResult)->stringNotContainsString('alert-info');
+ verify($renderingResult)->stringNotContainsString('alert-warning');
+ }
+
+ public function testMultipleSuccessMessages()
+ {
+ $firstMessage = 'This is the first danger message';
+ $secondMessage = 'This is the second danger message';
+
+ Yii::$app->session->setFlash('success', [$firstMessage, $secondMessage]);
+
+ $renderingResult = Alert::widget();
+
+ verify($renderingResult)->stringContainsString($firstMessage);
+ verify($renderingResult)->stringContainsString($secondMessage);
+ verify($renderingResult)->stringContainsString('alert-success');
+
+ verify($renderingResult)->stringNotContainsString('alert-danger');
+ verify($renderingResult)->stringNotContainsString('alert-info');
+ verify($renderingResult)->stringNotContainsString('alert-warning');
+ }
+
+ public function testSingleInfoMessage()
+ {
+ $message = 'This is an info message';
+
+ Yii::$app->session->setFlash('info', $message);
+
+ $renderingResult = Alert::widget();
+
+ verify($renderingResult)->stringContainsString($message);
+ verify($renderingResult)->stringContainsString('alert-info');
+
+ verify($renderingResult)->stringNotContainsString('alert-danger');
+ verify($renderingResult)->stringNotContainsString('alert-success');
+ verify($renderingResult)->stringNotContainsString('alert-warning');
+ }
+
+ public function testMultipleInfoMessages()
+ {
+ $firstMessage = 'This is the first info message';
+ $secondMessage = 'This is the second info message';
+
+ Yii::$app->session->setFlash('info', [$firstMessage, $secondMessage]);
+
+ $renderingResult = Alert::widget();
+
+ verify($renderingResult)->stringContainsString($firstMessage);
+ verify($renderingResult)->stringContainsString($secondMessage);
+ verify($renderingResult)->stringContainsString('alert-info');
+
+ verify($renderingResult)->stringNotContainsString('alert-danger');
+ verify($renderingResult)->stringNotContainsString('alert-success');
+ verify($renderingResult)->stringNotContainsString('alert-warning');
+ }
+
+ public function testSingleWarningMessage()
+ {
+ $message = 'This is a warning message';
+
+ Yii::$app->session->setFlash('warning', $message);
+
+ $renderingResult = Alert::widget();
+
+ verify($renderingResult)->stringContainsString($message);
+ verify($renderingResult)->stringContainsString('alert-warning');
+
+ verify($renderingResult)->stringNotContainsString('alert-danger');
+ verify($renderingResult)->stringNotContainsString('alert-success');
+ verify($renderingResult)->stringNotContainsString('alert-info');
+ }
+
+ public function testMultipleWarningMessages()
+ {
+ $firstMessage = 'This is the first warning message';
+ $secondMessage = 'This is the second warning message';
+
+ Yii::$app->session->setFlash('warning', [$firstMessage, $secondMessage]);
+
+ $renderingResult = Alert::widget();
+
+ verify($renderingResult)->stringContainsString($firstMessage);
+ verify($renderingResult)->stringContainsString($secondMessage);
+ verify($renderingResult)->stringContainsString('alert-warning');
+
+ verify($renderingResult)->stringNotContainsString('alert-danger');
+ verify($renderingResult)->stringNotContainsString('alert-success');
+ verify($renderingResult)->stringNotContainsString('alert-info');
+ }
+
+ public function testSingleMixedMessages()
+ {
+ $errorMessage = 'This is an error message';
+ $dangerMessage = 'This is a danger message';
+ $successMessage = 'This is a success message';
+ $infoMessage = 'This is a info message';
+ $warningMessage = 'This is a warning message';
+
+ Yii::$app->session->setFlash('error', $errorMessage);
+ Yii::$app->session->setFlash('danger', $dangerMessage);
+ Yii::$app->session->setFlash('success', $successMessage);
+ Yii::$app->session->setFlash('info', $infoMessage);
+ Yii::$app->session->setFlash('warning', $warningMessage);
+
+ $renderingResult = Alert::widget();
+
+ verify($renderingResult)->stringContainsString($errorMessage);
+ verify($renderingResult)->stringContainsString($dangerMessage);
+ verify($renderingResult)->stringContainsString($successMessage);
+ verify($renderingResult)->stringContainsString($infoMessage);
+ verify($renderingResult)->stringContainsString($warningMessage);
+
+ verify($renderingResult)->stringContainsString('alert-danger');
+ verify($renderingResult)->stringContainsString('alert-success');
+ verify($renderingResult)->stringContainsString('alert-info');
+ verify($renderingResult)->stringContainsString('alert-warning');
+ }
+
+ public function testMultipleMixedMessages()
+ {
+ $firstErrorMessage = 'This is the first error message';
+ $secondErrorMessage = 'This is the second error message';
+ $firstDangerMessage = 'This is the first danger message';
+ $secondDangerMessage = 'This is the second';
+ $firstSuccessMessage = 'This is the first success message';
+ $secondSuccessMessage = 'This is the second success message';
+ $firstInfoMessage = 'This is the first info message';
+ $secondInfoMessage = 'This is the second info message';
+ $firstWarningMessage = 'This is the first warning message';
+ $secondWarningMessage = 'This is the second warning message';
+
+ Yii::$app->session->setFlash('error', [$firstErrorMessage, $secondErrorMessage]);
+ Yii::$app->session->setFlash('danger', [$firstDangerMessage, $secondDangerMessage]);
+ Yii::$app->session->setFlash('success', [$firstSuccessMessage, $secondSuccessMessage]);
+ Yii::$app->session->setFlash('info', [$firstInfoMessage, $secondInfoMessage]);
+ Yii::$app->session->setFlash('warning', [$firstWarningMessage, $secondWarningMessage]);
+
+ $renderingResult = Alert::widget();
+
+ verify($renderingResult)->stringContainsString($firstErrorMessage);
+ verify($renderingResult)->stringContainsString($secondErrorMessage);
+ verify($renderingResult)->stringContainsString($firstDangerMessage);
+ verify($renderingResult)->stringContainsString($secondDangerMessage);
+ verify($renderingResult)->stringContainsString($firstSuccessMessage);
+ verify($renderingResult)->stringContainsString($secondSuccessMessage);
+ verify($renderingResult)->stringContainsString($firstInfoMessage);
+ verify($renderingResult)->stringContainsString($secondInfoMessage);
+ verify($renderingResult)->stringContainsString($firstWarningMessage);
+ verify($renderingResult)->stringContainsString($secondWarningMessage);
+
+ verify($renderingResult)->stringContainsString('alert-danger');
+ verify($renderingResult)->stringContainsString('alert-success');
+ verify($renderingResult)->stringContainsString('alert-info');
+ verify($renderingResult)->stringContainsString('alert-warning');
+ }
+
+ public function testFlashIntegrity()
+ {
+ $errorMessage = 'This is an error message';
+ $unrelatedMessage = 'This is a message that is not related to the alert widget';
+
+ Yii::$app->session->setFlash('error', $errorMessage);
+ Yii::$app->session->setFlash('unrelated', $unrelatedMessage);
+
+ Alert::widget();
+
+ // Simulate redirect
+ Yii::$app->session->close();
+ Yii::$app->session->open();
+
+ verify(Yii::$app->session->getFlash('error'))->empty();
+ verify(Yii::$app->session->getFlash('unrelated'))->equals($unrelatedMessage);
+ }
+}
diff --git a/vagrant/nginx/app.conf b/vagrant/nginx/app.conf
index b22e66106..1bfc0d583 100644
--- a/vagrant/nginx/app.conf
+++ b/vagrant/nginx/app.conf
@@ -28,7 +28,7 @@ server {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#fastcgi_pass 127.0.0.1:9000;
- fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
+ fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
try_files $uri =404;
}
diff --git a/vagrant/provision/always-as-root.sh b/vagrant/provision/always-as-root.sh
index e5d8e33e1..17fb58421 100644
--- a/vagrant/provision/always-as-root.sh
+++ b/vagrant/provision/always-as-root.sh
@@ -13,6 +13,6 @@ function info {
info "Provision-script user: `whoami`"
info "Restart web-stack"
-service php7.0-fpm restart
+service php7.2-fpm restart
service nginx restart
-service mysql restart
\ No newline at end of file
+service mysql restart
diff --git a/vagrant/provision/once-as-root.sh b/vagrant/provision/once-as-root.sh
index 311d77b4c..1d2917016 100644
--- a/vagrant/provision/once-as-root.sh
+++ b/vagrant/provision/once-as-root.sh
@@ -3,6 +3,7 @@
#== Import script args ==
timezone=$(echo "$1")
+readonly IP=$2
#== Bash helpers ==
@@ -21,9 +22,12 @@ export DEBIAN_FRONTEND=noninteractive
info "Configure timezone"
timedatectl set-timezone ${timezone} --no-ask-password
+info "Add the VM IP to the list of allowed IPs"
+awk -v ip=$IP -f /app/vagrant/provision/provision.awk /app/config/web.php
+
info "Prepare root password for MySQL"
-debconf-set-selections <<< "mariadb-server-10.0 mysql-server/root_password password \"''\""
-debconf-set-selections <<< "mariadb-server-10.0 mysql-server/root_password_again password \"''\""
+debconf-set-selections <<< 'mariadb-server mysql-server/root_password password'
+debconf-set-selections <<< 'mariadb-server mysql-server/root_password_again password'
echo "Done!"
info "Update OS software"
@@ -31,21 +35,21 @@ apt-get update
apt-get upgrade -y
info "Install additional software"
-apt-get install -y php7.0-curl php7.0-cli php7.0-intl php7.0-mysqlnd php7.0-gd php7.0-fpm php7.0-mbstring php7.0-xml unzip nginx mariadb-server-10.0 php.xdebug
+apt-get install -y php7.2-curl php7.2-cli php7.2-intl php7.2-mysqlnd php7.2-gd php7.2-fpm php7.2-mbstring php7.2-xml unzip nginx mariadb-server-10.1 php.xdebug
info "Configure MySQL"
-sed -i "s/.*bind-address.*/bind-address = 0.0.0.0/" /etc/mysql/mariadb.conf.d/50-server.cnf
-mysql -uroot <<< "CREATE USER 'root'@'%' IDENTIFIED BY ''"
-mysql -uroot <<< "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'"
-mysql -uroot <<< "DROP USER 'root'@'localhost'"
-mysql -uroot <<< "FLUSH PRIVILEGES"
+sed -i 's/.*bind-address.*/bind-address = 0.0.0.0/' /etc/mysql/mariadb.conf.d/50-server.cnf
+mysql <<< "CREATE USER 'root'@'%' IDENTIFIED BY ''"
+mysql <<< "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'"
+mysql <<< "DROP USER 'root'@'localhost'"
+mysql <<< 'FLUSH PRIVILEGES'
echo "Done!"
info "Configure PHP-FPM"
-sed -i 's/user = www-data/user = vagrant/g' /etc/php/7.0/fpm/pool.d/www.conf
-sed -i 's/group = www-data/group = vagrant/g' /etc/php/7.0/fpm/pool.d/www.conf
-sed -i 's/owner = www-data/owner = vagrant/g' /etc/php/7.0/fpm/pool.d/www.conf
-cat << EOF > /etc/php/7.0/mods-available/xdebug.ini
+sed -i 's/user = www-data/user = vagrant/g' /etc/php/7.2/fpm/pool.d/www.conf
+sed -i 's/group = www-data/group = vagrant/g' /etc/php/7.2/fpm/pool.d/www.conf
+sed -i 's/owner = www-data/owner = vagrant/g' /etc/php/7.2/fpm/pool.d/www.conf
+cat << EOF > /etc/php/7.2/mods-available/xdebug.ini
zend_extension=xdebug.so
xdebug.remote_enable=1
xdebug.remote_connect_back=1
@@ -66,10 +70,10 @@ info "Removing default site configuration"
rm /etc/nginx/sites-enabled/default
echo "Done!"
-info "Initailize databases for MySQL"
-mysql -uroot <<< "CREATE DATABASE yii2basic"
-mysql -uroot <<< "CREATE DATABASE yii2basic_test"
+info "Initialize databases for MySQL"
+mysql <<< 'CREATE DATABASE yii2basic'
+mysql <<< 'CREATE DATABASE yii2basic_test'
echo "Done!"
info "Install composer"
-curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
\ No newline at end of file
+curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
diff --git a/vagrant/provision/provision.awk b/vagrant/provision/provision.awk
new file mode 100644
index 000000000..bcf44d3be
--- /dev/null
+++ b/vagrant/provision/provision.awk
@@ -0,0 +1,50 @@
+###
+# Modifying Yii2's files for Vagrant VM
+#
+# @author HA3IK
+# @version 1.0.0
+
+BEGIN {
+ print "AWK BEGINs its work:"
+ IGNORECASE = 1
+
+ # Correct IP - wildcard last octet
+ match(ip, /(([0-9]+\.)+)/, arr)
+ ip = arr[1] "*"
+}
+# BODY
+{
+ # Check if it's the same file
+ if (FILENAME != isFile["same"]){
+ msg = "- Work with: " FILENAME
+ # Close a previous file
+ close(isFile["same"])
+ # Delete previous data
+ delete isFile
+ # Save current file
+ isFile["same"] = FILENAME
+ # Define array index for the file
+ switch (FILENAME){
+ case /config\/web\.php$/:
+ isFile["IsConfWeb"] = 1
+ msg = msg " - add allowed IP: " ip
+ break
+ }
+ # Print the concatenated message for the file
+ print msg
+ }
+
+ # IF config/web.php
+ if (isFile["IsConfWeb"]){
+ # IF line has "allowedIPs" and doesn't has our IP
+ if (match($0, "allowedIPs") && !match($0, ip)){
+ match($0, /([^\]]+)(.+)/, arr)
+ $0 = sprintf("%s, '%s'%s", arr[1], ip, arr[2])
+ }
+ # Rewrite the file
+ print $0 > FILENAME
+ }
+}
+END {
+ print "AWK ENDs its work."
+}
diff --git a/views/layouts/main.php b/views/layouts/main.php
index 87dfdcbc9..c204435c0 100644
--- a/views/layouts/main.php
+++ b/views/layouts/main.php
@@ -1,77 +1,79 @@
registerCsrfMetaTags();
+$this->registerMetaTag(['charset' => Yii::$app->charset], 'charset');
+$this->registerMetaTag(['name' => 'viewport', 'content' => 'width=device-width, initial-scale=1, shrink-to-fit=no']);
+$this->registerMetaTag(['name' => 'description', 'content' => $this->params['meta_description'] ?? '']);
+$this->registerMetaTag(['name' => 'keywords', 'content' => $this->params['meta_keywords'] ?? '']);
+$this->registerLinkTag(['rel' => 'icon', 'type' => 'image/x-icon', 'href' => Yii::getAlias('@web/favicon.ico')]);
?>
beginPage() ?>
-
+
-
-
-
- registerCsrfMetaTags() ?>
= Html::encode($this->title) ?>
head() ?>
-
+
beginBody() ?>
-
+
+
- = Breadcrumbs::widget([
- 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
- ]) ?>
+ params['breadcrumbs'])): ?>
+ = Breadcrumbs::widget(['links' => $this->params['breadcrumbs']]) ?>
+
= Alert::widget() ?>
= $content ?>
-
+
-