Error202
2 years ago
commit
960876a1bf
85 changed files with 3552 additions and 0 deletions
@ -0,0 +1,39 @@ |
|||||||
|
# phpstorm project files |
||||||
|
.idea |
||||||
|
|
||||||
|
# netbeans project files |
||||||
|
nbproject |
||||||
|
|
||||||
|
# zend studio for eclipse project files |
||||||
|
.buildpath |
||||||
|
.project |
||||||
|
.settings |
||||||
|
|
||||||
|
# windows thumbnail cache |
||||||
|
Thumbs.db |
||||||
|
|
||||||
|
# composer vendor dir |
||||||
|
/vendor |
||||||
|
|
||||||
|
# composer itself is not needed |
||||||
|
composer.phar |
||||||
|
|
||||||
|
# composer lock |
||||||
|
composer.lock |
||||||
|
|
||||||
|
# Mac DS_Store Files |
||||||
|
.DS_Store |
||||||
|
|
||||||
|
# phpunit itself is not needed |
||||||
|
phpunit.phar |
||||||
|
# local phpunit config |
||||||
|
/phpunit.xml |
||||||
|
|
||||||
|
tests/_output/* |
||||||
|
tests/_support/_generated |
||||||
|
|
||||||
|
#vagrant folder |
||||||
|
/.vagrant |
||||||
|
|
||||||
|
# PostgreSQL database files |
||||||
|
/pgdata |
@ -0,0 +1,29 @@ |
|||||||
|
Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com) |
||||||
|
All rights reserved. |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without |
||||||
|
modification, are permitted provided that the following conditions |
||||||
|
are met: |
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright |
||||||
|
notice, this list of conditions and the following disclaimer. |
||||||
|
* Redistributions in binary form must reproduce the above copyright |
||||||
|
notice, this list of conditions and the following disclaimer in |
||||||
|
the documentation and/or other materials provided with the |
||||||
|
distribution. |
||||||
|
* Neither the name of Yii Software LLC nor the names of its |
||||||
|
contributors may be used to endorse or promote products derived |
||||||
|
from this software without specific prior written permission. |
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
||||||
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
||||||
|
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||||
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
||||||
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
POSSIBILITY OF SUCH DAMAGE. |
@ -0,0 +1,14 @@ |
|||||||
|
init: docker-down-clear docker-up |
||||||
|
up: docker-up |
||||||
|
down: docker-down |
||||||
|
restart: down up |
||||||
|
|
||||||
|
docker-up: |
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
docker-down: |
||||||
|
docker-compose down --remove-orphans
|
||||||
|
|
||||||
|
docker-down-clear: |
||||||
|
docker-compose down -v --remove-orphans
|
||||||
|
|
@ -0,0 +1,233 @@ |
|||||||
|
<p align="center"> |
||||||
|
<a href="https://github.com/yiisoft" target="_blank"> |
||||||
|
<img src="https://avatars0.githubusercontent.com/u/993323" height="100px"> |
||||||
|
</a> |
||||||
|
<h1 align="center">Yii 2 Basic Project Template</h1> |
||||||
|
<br> |
||||||
|
</p> |
||||||
|
|
||||||
|
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. |
||||||
|
It includes all commonly used configurations that would allow you to focus on adding new |
||||||
|
features to your application. |
||||||
|
|
||||||
|
[![Latest Stable Version](https://img.shields.io/packagist/v/yiisoft/yii2-app-basic.svg)](https://packagist.org/packages/yiisoft/yii2-app-basic) |
||||||
|
[![Total Downloads](https://img.shields.io/packagist/dt/yiisoft/yii2-app-basic.svg)](https://packagist.org/packages/yiisoft/yii2-app-basic) |
||||||
|
[![build](https://github.com/yiisoft/yii2-app-basic/workflows/build/badge.svg)](https://github.com/yiisoft/yii2-app-basic/actions?query=workflow%3Abuild) |
||||||
|
|
||||||
|
DIRECTORY STRUCTURE |
||||||
|
------------------- |
||||||
|
|
||||||
|
assets/ contains assets definition |
||||||
|
commands/ contains console commands (controllers) |
||||||
|
config/ contains application configurations |
||||||
|
controllers/ contains Web controller classes |
||||||
|
mail/ contains view files for e-mails |
||||||
|
models/ contains model classes |
||||||
|
runtime/ contains files generated during runtime |
||||||
|
tests/ contains various tests for the basic application |
||||||
|
vendor/ contains dependent 3rd-party packages |
||||||
|
views/ contains view files for the Web application |
||||||
|
web/ contains the entry script and Web resources |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
REQUIREMENTS |
||||||
|
------------ |
||||||
|
|
||||||
|
The minimum requirement by this project template that your Web server supports PHP 7.4. |
||||||
|
|
||||||
|
|
||||||
|
INSTALLATION |
||||||
|
------------ |
||||||
|
|
||||||
|
### Install via Composer |
||||||
|
|
||||||
|
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: |
||||||
|
|
||||||
|
~~~ |
||||||
|
composer create-project --prefer-dist yiisoft/yii2-app-basic basic |
||||||
|
~~~ |
||||||
|
|
||||||
|
Now you should be able to access the application through the following URL, assuming `basic` is the directory |
||||||
|
directly under the Web root. |
||||||
|
|
||||||
|
~~~ |
||||||
|
http://localhost/basic/web/ |
||||||
|
~~~ |
||||||
|
|
||||||
|
### Install from an Archive File |
||||||
|
|
||||||
|
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: |
||||||
|
|
||||||
|
```php |
||||||
|
'request' => [ |
||||||
|
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation |
||||||
|
'cookieValidationKey' => '<secret random string goes here>', |
||||||
|
], |
||||||
|
``` |
||||||
|
|
||||||
|
You can then access the application through the following URL: |
||||||
|
|
||||||
|
~~~ |
||||||
|
http://localhost/basic/web/ |
||||||
|
~~~ |
||||||
|
|
||||||
|
|
||||||
|
### Install with Docker |
||||||
|
|
||||||
|
Update your vendor packages |
||||||
|
|
||||||
|
docker-compose run --rm php composer update --prefer-dist |
||||||
|
|
||||||
|
Run the installation triggers (creating cookie validation code) |
||||||
|
|
||||||
|
docker-compose run --rm php composer install |
||||||
|
|
||||||
|
Start the container |
||||||
|
|
||||||
|
docker-compose up -d |
||||||
|
|
||||||
|
You can then access the application through the following URL: |
||||||
|
|
||||||
|
http://127.0.0.1:8000 |
||||||
|
|
||||||
|
**NOTES:** |
||||||
|
- Minimum required Docker engine version `17.04` for development (see [Performance tuning for volume mounts](https://docs.docker.com/docker-for-mac/osxfs-caching/)) |
||||||
|
- The default configuration uses a host-volume in your home directory `.docker-composer` for composer caches |
||||||
|
|
||||||
|
|
||||||
|
CONFIGURATION |
||||||
|
------------- |
||||||
|
|
||||||
|
### Database |
||||||
|
|
||||||
|
Edit the file `config/db.php` with real data, for example: |
||||||
|
|
||||||
|
```php |
||||||
|
return [ |
||||||
|
'class' => 'yii\db\Connection', |
||||||
|
'dsn' => 'mysql:host=localhost;dbname=yii2basic', |
||||||
|
'username' => 'root', |
||||||
|
'password' => '1234', |
||||||
|
'charset' => 'utf8', |
||||||
|
]; |
||||||
|
``` |
||||||
|
|
||||||
|
**NOTES:** |
||||||
|
- Yii won't create the database for you, this has to be done manually before you can access it. |
||||||
|
- Check and edit the other files in the `config/` directory to customize your application as required. |
||||||
|
- Refer to the README in the `tests` directory for information specific to basic application tests. |
||||||
|
|
||||||
|
|
||||||
|
TESTING |
||||||
|
------- |
||||||
|
|
||||||
|
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` |
||||||
|
- `acceptance` |
||||||
|
|
||||||
|
Tests can be executed by running |
||||||
|
|
||||||
|
``` |
||||||
|
vendor/bin/codecept run |
||||||
|
``` |
||||||
|
|
||||||
|
The command above will execute unit and functional tests. Unit tests are testing the system components, while functional |
||||||
|
tests are for testing user interaction. Acceptance tests are disabled by default as they require additional setup since |
||||||
|
they perform testing in real browser. |
||||||
|
|
||||||
|
|
||||||
|
### Running acceptance tests |
||||||
|
|
||||||
|
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 |
||||||
|
version of Codeception |
||||||
|
|
||||||
|
3. Update dependencies with Composer |
||||||
|
|
||||||
|
``` |
||||||
|
composer update |
||||||
|
``` |
||||||
|
|
||||||
|
4. Download [Selenium Server](https://www.seleniumhq.org/download/) and launch it: |
||||||
|
|
||||||
|
``` |
||||||
|
java -jar ~/selenium-server-standalone-x.xx.x.jar |
||||||
|
``` |
||||||
|
|
||||||
|
In case of using Selenium Server 3.0 with Firefox browser since v48 or Google Chrome since v53 you must download [GeckoDriver](https://github.com/mozilla/geckodriver/releases) or [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/downloads) and launch Selenium with it: |
||||||
|
|
||||||
|
``` |
||||||
|
# for Firefox |
||||||
|
java -jar -Dwebdriver.gecko.driver=~/geckodriver ~/selenium-server-standalone-3.xx.x.jar |
||||||
|
|
||||||
|
# for Google Chrome |
||||||
|
java -jar -Dwebdriver.chrome.driver=~/chromedriver ~/selenium-server-standalone-3.xx.x.jar |
||||||
|
``` |
||||||
|
|
||||||
|
As an alternative way you can use already configured Docker container with older versions of Selenium and Firefox: |
||||||
|
|
||||||
|
``` |
||||||
|
docker run --net=host selenium/standalone-firefox:2.53.0 |
||||||
|
``` |
||||||
|
|
||||||
|
5. (Optional) Create `yii2basic_test` database and update it by applying migrations if you have them. |
||||||
|
|
||||||
|
``` |
||||||
|
tests/bin/yii migrate |
||||||
|
``` |
||||||
|
|
||||||
|
The database configuration can be found at `config/test_db.php`. |
||||||
|
|
||||||
|
|
||||||
|
6. Start web server: |
||||||
|
|
||||||
|
``` |
||||||
|
tests/bin/yii serve |
||||||
|
``` |
||||||
|
|
||||||
|
7. Now you can run all available tests |
||||||
|
|
||||||
|
``` |
||||||
|
# run all available tests |
||||||
|
vendor/bin/codecept run |
||||||
|
|
||||||
|
# run acceptance tests |
||||||
|
vendor/bin/codecept run acceptance |
||||||
|
|
||||||
|
# run only unit and functional tests |
||||||
|
vendor/bin/codecept run unit,functional |
||||||
|
``` |
||||||
|
|
||||||
|
### Code coverage support |
||||||
|
|
||||||
|
By default, code coverage is disabled in `codeception.yml` configuration file, you should uncomment needed rows to be able |
||||||
|
to collect code coverage. You can run your tests and collect coverage with the following command: |
||||||
|
|
||||||
|
``` |
||||||
|
#collect coverage for all tests |
||||||
|
vendor/bin/codecept run --coverage --coverage-html --coverage-xml |
||||||
|
|
||||||
|
#collect coverage only for unit tests |
||||||
|
vendor/bin/codecept run unit --coverage --coverage-html --coverage-xml |
||||||
|
|
||||||
|
#collect coverage for unit and functional tests |
||||||
|
vendor/bin/codecept run functional,unit --coverage --coverage-html --coverage-xml |
||||||
|
``` |
||||||
|
|
||||||
|
You can see code coverage output under the `tests/_output` directory. |
@ -0,0 +1,31 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @link https://www.yiiframework.com/ |
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
* @license https://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace app\assets; |
||||||
|
|
||||||
|
use yii\web\AssetBundle; |
||||||
|
|
||||||
|
/** |
||||||
|
* Main application asset bundle. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class AppAsset extends AssetBundle |
||||||
|
{ |
||||||
|
public $basePath = '@webroot'; |
||||||
|
public $baseUrl = '@web'; |
||||||
|
public $css = [ |
||||||
|
'css/site.css', |
||||||
|
]; |
||||||
|
public $js = [ |
||||||
|
]; |
||||||
|
public $depends = [ |
||||||
|
'yii\web\YiiAsset', |
||||||
|
'yii\bootstrap5\BootstrapAsset' |
||||||
|
]; |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
actor: Tester |
||||||
|
bootstrap: _bootstrap.php |
||||||
|
paths: |
||||||
|
tests: tests |
||||||
|
output: tests/_output |
||||||
|
data: tests/_data |
||||||
|
helpers: tests/_support |
||||||
|
settings: |
||||||
|
memory_limit: 1024M |
||||||
|
colors: true |
||||||
|
modules: |
||||||
|
config: |
||||||
|
Yii2: |
||||||
|
configFile: 'config/test.php' |
||||||
|
|
||||||
|
# To enable code coverage: |
||||||
|
#coverage: |
||||||
|
# #c3_url: http://localhost:8080/index-test.php/ |
||||||
|
# enabled: true |
||||||
|
# #remote: true |
||||||
|
# #remote_config: '../codeception.yml' |
||||||
|
# whitelist: |
||||||
|
# include: |
||||||
|
# - models/* |
||||||
|
# - controllers/* |
||||||
|
# - commands/* |
||||||
|
# - mail/* |
@ -0,0 +1,34 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @link https://www.yiiframework.com/ |
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
* @license https://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace app\commands; |
||||||
|
|
||||||
|
use yii\console\Controller; |
||||||
|
use yii\console\ExitCode; |
||||||
|
|
||||||
|
/** |
||||||
|
* This command echoes the first argument that you have entered. |
||||||
|
* |
||||||
|
* This command is provided as an example for you to learn how to create console commands. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class HelloController extends Controller |
||||||
|
{ |
||||||
|
/** |
||||||
|
* This command echoes what you have entered as the message. |
||||||
|
* @param string $message the message to be echoed. |
||||||
|
* @return int Exit code |
||||||
|
*/ |
||||||
|
public function actionIndex($message = 'hello world') |
||||||
|
{ |
||||||
|
echo $message . "\n"; |
||||||
|
|
||||||
|
return ExitCode::OK; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,75 @@ |
|||||||
|
{ |
||||||
|
"name": "yiisoft/yii2-app-basic", |
||||||
|
"description": "Yii 2 Basic Project Template", |
||||||
|
"keywords": ["yii2", "framework", "basic", "project template"], |
||||||
|
"homepage": "https://www.yiiframework.com/", |
||||||
|
"type": "project", |
||||||
|
"license": "BSD-3-Clause", |
||||||
|
"support": { |
||||||
|
"issues": "https://github.com/yiisoft/yii2/issues?state=open", |
||||||
|
"forum": "https://www.yiiframework.com/forum/", |
||||||
|
"wiki": "https://www.yiiframework.com/wiki/", |
||||||
|
"irc": "irc://irc.freenode.net/yii", |
||||||
|
"source": "https://github.com/yiisoft/yii2" |
||||||
|
}, |
||||||
|
"minimum-stability": "stable", |
||||||
|
"require": { |
||||||
|
"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.2.0", |
||||||
|
"yiisoft/yii2-faker": "~2.0.0", |
||||||
|
"phpunit/phpunit": "~9.5.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", |
||||||
|
"symfony/browser-kit": "^6.0 || >=2.7 <=4.2.4" |
||||||
|
}, |
||||||
|
"config": { |
||||||
|
"allow-plugins": { |
||||||
|
"yiisoft/yii2-composer" : true |
||||||
|
}, |
||||||
|
"process-timeout": 1800, |
||||||
|
"fxp-asset": { |
||||||
|
"enabled": false |
||||||
|
} |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"post-install-cmd": [ |
||||||
|
"yii\\composer\\Installer::postInstall" |
||||||
|
], |
||||||
|
"post-create-project-cmd": [ |
||||||
|
"yii\\composer\\Installer::postCreateProject", |
||||||
|
"yii\\composer\\Installer::postInstall" |
||||||
|
] |
||||||
|
}, |
||||||
|
"extra": { |
||||||
|
"yii\\composer\\Installer::postCreateProject": { |
||||||
|
"setPermission": [ |
||||||
|
{ |
||||||
|
"runtime": "0777", |
||||||
|
"web/assets": "0777", |
||||||
|
"yii": "0755" |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
"yii\\composer\\Installer::postInstall": { |
||||||
|
"generateCookieValidationKey": [ |
||||||
|
"config/web.php" |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
"repositories": [ |
||||||
|
{ |
||||||
|
"type": "composer", |
||||||
|
"url": "https://asset-packagist.org" |
||||||
|
} |
||||||
|
] |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* This class only exists here for IDE (PHPStorm/Netbeans/...) autocompletion. |
||||||
|
* This file is never included anywhere. |
||||||
|
* Adjust this file to match classes configured in your application config, to enable IDE autocompletion for custom components. |
||||||
|
* Example: A property phpdoc can be added in `__Application` class as `@property \vendor\package\Rollbar|__Rollbar $rollbar` and adding a class in this file |
||||||
|
* ```php |
||||||
|
* // @property of \vendor\package\Rollbar goes here |
||||||
|
* class __Rollbar { |
||||||
|
* } |
||||||
|
* ``` |
||||||
|
*/ |
||||||
|
class Yii { |
||||||
|
/** |
||||||
|
* @var \yii\web\Application|\yii\console\Application|__Application |
||||||
|
*/ |
||||||
|
public static $app; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @property yii\rbac\DbManager $authManager |
||||||
|
* @property \yii\web\User|__WebUser $user |
||||||
|
* |
||||||
|
*/ |
||||||
|
class __Application { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @property app\models\User $identity |
||||||
|
*/ |
||||||
|
class __WebUser { |
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
$params = require __DIR__ . '/params.php'; |
||||||
|
$db = require __DIR__ . '/db.php'; |
||||||
|
|
||||||
|
$config = [ |
||||||
|
'id' => 'basic-console', |
||||||
|
'basePath' => dirname(__DIR__), |
||||||
|
'bootstrap' => ['log'], |
||||||
|
'controllerNamespace' => 'app\commands', |
||||||
|
'aliases' => [ |
||||||
|
'@bower' => '@vendor/bower-asset', |
||||||
|
'@npm' => '@vendor/npm-asset', |
||||||
|
'@tests' => '@app/tests', |
||||||
|
], |
||||||
|
'components' => [ |
||||||
|
'cache' => [ |
||||||
|
'class' => 'yii\caching\FileCache', |
||||||
|
], |
||||||
|
'log' => [ |
||||||
|
'targets' => [ |
||||||
|
[ |
||||||
|
'class' => 'yii\log\FileTarget', |
||||||
|
'levels' => ['error', 'warning'], |
||||||
|
], |
||||||
|
], |
||||||
|
], |
||||||
|
'db' => $db, |
||||||
|
], |
||||||
|
'params' => $params, |
||||||
|
/* |
||||||
|
'controllerMap' => [ |
||||||
|
'fixture' => [ // Fixture generation command line. |
||||||
|
'class' => 'yii\faker\FixtureController', |
||||||
|
], |
||||||
|
], |
||||||
|
*/ |
||||||
|
]; |
||||||
|
|
||||||
|
if (YII_ENV_DEV) { |
||||||
|
// configuration adjustments for 'dev' environment |
||||||
|
$config['bootstrap'][] = 'gii'; |
||||||
|
$config['modules']['gii'] = [ |
||||||
|
'class' => '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; |
@ -0,0 +1,14 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
return [ |
||||||
|
'class' => 'yii\db\Connection', |
||||||
|
'dsn' => 'mysql:host=localhost;dbname=yii2basic', |
||||||
|
'username' => 'root', |
||||||
|
'password' => '', |
||||||
|
'charset' => 'utf8', |
||||||
|
|
||||||
|
// Schema cache options (for production environment) |
||||||
|
//'enableSchemaCache' => true, |
||||||
|
//'schemaCacheDuration' => 60, |
||||||
|
//'schemaCache' => 'cache', |
||||||
|
]; |
@ -0,0 +1,7 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
return [ |
||||||
|
'adminEmail' => 'admin@example.com', |
||||||
|
'senderEmail' => 'noreply@example.com', |
||||||
|
'senderName' => 'Example.com mailer', |
||||||
|
]; |
@ -0,0 +1,46 @@ |
|||||||
|
<?php |
||||||
|
$params = require __DIR__ . '/params.php'; |
||||||
|
$db = require __DIR__ . '/test_db.php'; |
||||||
|
|
||||||
|
/** |
||||||
|
* Application configuration shared by all test types |
||||||
|
*/ |
||||||
|
return [ |
||||||
|
'id' => 'basic-tests', |
||||||
|
'basePath' => dirname(__DIR__), |
||||||
|
'aliases' => [ |
||||||
|
'@bower' => '@vendor/bower-asset', |
||||||
|
'@npm' => '@vendor/npm-asset', |
||||||
|
], |
||||||
|
'language' => 'en-US', |
||||||
|
'components' => [ |
||||||
|
'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', |
||||||
|
], |
||||||
|
'urlManager' => [ |
||||||
|
'showScriptName' => true, |
||||||
|
], |
||||||
|
'user' => [ |
||||||
|
'identityClass' => 'app\models\User', |
||||||
|
], |
||||||
|
'request' => [ |
||||||
|
'cookieValidationKey' => 'test', |
||||||
|
'enableCsrfValidation' => false, |
||||||
|
// but if you absolutely need it set cookie domain to localhost |
||||||
|
/* |
||||||
|
'csrfCookie' => [ |
||||||
|
'domain' => 'localhost', |
||||||
|
], |
||||||
|
*/ |
||||||
|
], |
||||||
|
], |
||||||
|
'params' => $params, |
||||||
|
]; |
@ -0,0 +1,6 @@ |
|||||||
|
<?php |
||||||
|
$db = require __DIR__ . '/db.php'; |
||||||
|
// test database! Important not to run tests on production or development databases |
||||||
|
$db['dsn'] = 'mysql:host=localhost;dbname=yii2basic_test'; |
||||||
|
|
||||||
|
return $db; |
@ -0,0 +1,72 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
$params = require __DIR__ . '/params.php'; |
||||||
|
$db = require __DIR__ . '/db.php'; |
||||||
|
|
||||||
|
$config = [ |
||||||
|
'id' => 'basic', |
||||||
|
'basePath' => dirname(__DIR__), |
||||||
|
'bootstrap' => ['log'], |
||||||
|
'aliases' => [ |
||||||
|
'@bower' => '@vendor/bower-asset', |
||||||
|
'@npm' => '@vendor/npm-asset', |
||||||
|
], |
||||||
|
'components' => [ |
||||||
|
'request' => [ |
||||||
|
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation |
||||||
|
'cookieValidationKey' => 'kxzoL3hScKXhQzb-QNrA75YJw7mrG_Su', |
||||||
|
], |
||||||
|
'cache' => [ |
||||||
|
'class' => 'yii\caching\FileCache', |
||||||
|
], |
||||||
|
'user' => [ |
||||||
|
'identityClass' => 'app\models\User', |
||||||
|
'enableAutoLogin' => true, |
||||||
|
], |
||||||
|
'errorHandler' => [ |
||||||
|
'errorAction' => 'site/error', |
||||||
|
], |
||||||
|
'mailer' => [ |
||||||
|
'class' => \yii\symfonymailer\Mailer::class, |
||||||
|
'viewPath' => '@app/mail', |
||||||
|
// send all mails to a file by default. |
||||||
|
'useFileTransport' => true, |
||||||
|
], |
||||||
|
'log' => [ |
||||||
|
'traceLevel' => YII_DEBUG ? 3 : 0, |
||||||
|
'targets' => [ |
||||||
|
[ |
||||||
|
'class' => 'yii\log\FileTarget', |
||||||
|
'levels' => ['error', 'warning'], |
||||||
|
], |
||||||
|
], |
||||||
|
], |
||||||
|
'db' => $db, |
||||||
|
'urlManager' => [ |
||||||
|
'enablePrettyUrl' => true, |
||||||
|
'showScriptName' => false, |
||||||
|
'rules' => [ |
||||||
|
], |
||||||
|
], |
||||||
|
], |
||||||
|
'params' => $params, |
||||||
|
]; |
||||||
|
|
||||||
|
if (YII_ENV_DEV) { |
||||||
|
// configuration adjustments for 'dev' environment |
||||||
|
$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'], |
||||||
|
]; |
||||||
|
|
||||||
|
$config['bootstrap'][] = 'gii'; |
||||||
|
$config['modules']['gii'] = [ |
||||||
|
'class' => 'yii\gii\Module', |
||||||
|
// uncomment the following to add your IP if you are not connecting from localhost. |
||||||
|
//'allowedIPs' => ['127.0.0.1', '::1'], |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
return $config; |
@ -0,0 +1,128 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace app\controllers; |
||||||
|
|
||||||
|
use Yii; |
||||||
|
use yii\filters\AccessControl; |
||||||
|
use yii\web\Controller; |
||||||
|
use yii\web\Response; |
||||||
|
use yii\filters\VerbFilter; |
||||||
|
use app\models\LoginForm; |
||||||
|
use app\models\ContactForm; |
||||||
|
|
||||||
|
class SiteController extends Controller |
||||||
|
{ |
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function behaviors() |
||||||
|
{ |
||||||
|
return [ |
||||||
|
'access' => [ |
||||||
|
'class' => AccessControl::class, |
||||||
|
'only' => ['logout'], |
||||||
|
'rules' => [ |
||||||
|
[ |
||||||
|
'actions' => ['logout'], |
||||||
|
'allow' => true, |
||||||
|
'roles' => ['@'], |
||||||
|
], |
||||||
|
], |
||||||
|
], |
||||||
|
'verbs' => [ |
||||||
|
'class' => VerbFilter::class, |
||||||
|
'actions' => [ |
||||||
|
'logout' => ['post'], |
||||||
|
], |
||||||
|
], |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function actions() |
||||||
|
{ |
||||||
|
return [ |
||||||
|
'error' => [ |
||||||
|
'class' => 'yii\web\ErrorAction', |
||||||
|
], |
||||||
|
'captcha' => [ |
||||||
|
'class' => 'yii\captcha\CaptchaAction', |
||||||
|
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null, |
||||||
|
], |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Displays homepage. |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public function actionIndex() |
||||||
|
{ |
||||||
|
return $this->render('index'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Login action. |
||||||
|
* |
||||||
|
* @return Response|string |
||||||
|
*/ |
||||||
|
public function actionLogin() |
||||||
|
{ |
||||||
|
if (!Yii::$app->user->isGuest) { |
||||||
|
return $this->goHome(); |
||||||
|
} |
||||||
|
|
||||||
|
$model = new LoginForm(); |
||||||
|
if ($model->load(Yii::$app->request->post()) && $model->login()) { |
||||||
|
return $this->goBack(); |
||||||
|
} |
||||||
|
|
||||||
|
$model->password = ''; |
||||||
|
return $this->render('login', [ |
||||||
|
'model' => $model, |
||||||
|
]); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Logout action. |
||||||
|
* |
||||||
|
* @return Response |
||||||
|
*/ |
||||||
|
public function actionLogout() |
||||||
|
{ |
||||||
|
Yii::$app->user->logout(); |
||||||
|
|
||||||
|
return $this->goHome(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Displays contact page. |
||||||
|
* |
||||||
|
* @return Response|string |
||||||
|
*/ |
||||||
|
public function actionContact() |
||||||
|
{ |
||||||
|
$model = new ContactForm(); |
||||||
|
if ($model->load(Yii::$app->request->post()) && $model->contact(Yii::$app->params['adminEmail'])) { |
||||||
|
Yii::$app->session->setFlash('contactFormSubmitted'); |
||||||
|
|
||||||
|
return $this->refresh(); |
||||||
|
} |
||||||
|
return $this->render('contact', [ |
||||||
|
'model' => $model, |
||||||
|
]); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Displays about page. |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public function actionAbout() |
||||||
|
{ |
||||||
|
return $this->render('about'); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace app\controllers\api; |
||||||
|
|
||||||
|
use yii\rest\Controller; |
||||||
|
|
||||||
|
class TestController extends Controller |
||||||
|
{ |
||||||
|
public function actionIndex(): array |
||||||
|
{ |
||||||
|
return [ |
||||||
|
'test152', 'test153' |
||||||
|
]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
version: '2' |
||||||
|
services: |
||||||
|
php: |
||||||
|
image: yiisoftware/yii2-php:8.1-apache |
||||||
|
volumes: |
||||||
|
- ~/.composer-docker/cache:/root/.composer/cache:delegated |
||||||
|
- ./:/app:delegated |
||||||
|
ports: |
||||||
|
- '8001:80' |
||||||
|
depends_on: |
||||||
|
- api-postgres |
||||||
|
|
||||||
|
api-postgres: |
||||||
|
image: postgres:14.8-alpine |
||||||
|
environment: |
||||||
|
POSTGRES_USER: app |
||||||
|
POSTGRES_PASSWORD: secret |
||||||
|
POSTGRES_DB: app |
||||||
|
PGDATA: "/var/lib/postgresql/data/pgdata" |
||||||
|
volumes: |
||||||
|
- .:/var/lib/postgresql/data |
||||||
|
# - db-postgres:/var/lib/postgresql/data |
||||||
|
# net stop winnat // перезапуск службы, если бд не запускается (Windows) |
||||||
|
# docker-compose run --rm php composer install // обновление композера, установка расширений, работа с консолью |
||||||
|
ports: |
||||||
|
- "54333:5432" |
||||||
|
|
||||||
|
volumes: |
||||||
|
db-postgres: |
@ -0,0 +1,22 @@ |
|||||||
|
<?php |
||||||
|
use yii\helpers\Html; |
||||||
|
|
||||||
|
/** @var \yii\web\View $this view component instance */ |
||||||
|
/** @var \yii\mail\MessageInterface $message the message being composed */ |
||||||
|
/** @var string $content main view render result */ |
||||||
|
?> |
||||||
|
<?php $this->beginPage() ?> |
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"> |
||||||
|
<head> |
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=<?= Yii::$app->charset ?>" />
|
||||||
|
<title><?= Html::encode($this->title) ?></title>
|
||||||
|
<?php $this->head() ?> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<?php $this->beginBody() ?> |
||||||
|
<?= $content ?> |
||||||
|
<?php $this->endBody() ?> |
||||||
|
</body> |
||||||
|
</html> |
||||||
|
<?php $this->endPage() ?> |
@ -0,0 +1,13 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* @var yii\web\View $this view component instance |
||||||
|
* @var yii\mail\BaseMessage $message the message being composed |
||||||
|
* @var string $content main view render result |
||||||
|
*/ |
||||||
|
|
||||||
|
$this->beginPage(); |
||||||
|
$this->beginBody(); |
||||||
|
echo $content; |
||||||
|
$this->endBody(); |
||||||
|
$this->endPage(); |
@ -0,0 +1,65 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace app\models; |
||||||
|
|
||||||
|
use Yii; |
||||||
|
use yii\base\Model; |
||||||
|
|
||||||
|
/** |
||||||
|
* ContactForm is the model behind the contact form. |
||||||
|
*/ |
||||||
|
class ContactForm extends Model |
||||||
|
{ |
||||||
|
public $name; |
||||||
|
public $email; |
||||||
|
public $subject; |
||||||
|
public $body; |
||||||
|
public $verifyCode; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @return array the validation rules. |
||||||
|
*/ |
||||||
|
public function rules() |
||||||
|
{ |
||||||
|
return [ |
||||||
|
// name, email, subject and body are required |
||||||
|
[['name', 'email', 'subject', 'body'], 'required'], |
||||||
|
// email has to be a valid email address |
||||||
|
['email', 'email'], |
||||||
|
// verifyCode needs to be entered correctly |
||||||
|
['verifyCode', 'captcha'], |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return array customized attribute labels |
||||||
|
*/ |
||||||
|
public function attributeLabels() |
||||||
|
{ |
||||||
|
return [ |
||||||
|
'verifyCode' => 'Verification Code', |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sends an email to the specified email address using the information collected by this model. |
||||||
|
* @param string $email the target email address |
||||||
|
* @return bool whether the model passes validation |
||||||
|
*/ |
||||||
|
public function contact($email) |
||||||
|
{ |
||||||
|
if ($this->validate()) { |
||||||
|
Yii::$app->mailer->compose() |
||||||
|
->setTo($email) |
||||||
|
->setFrom([Yii::$app->params['senderEmail'] => Yii::$app->params['senderName']]) |
||||||
|
->setReplyTo([$this->email => $this->name]) |
||||||
|
->setSubject($this->subject) |
||||||
|
->setTextBody($this->body) |
||||||
|
->send(); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace app\models; |
||||||
|
|
||||||
|
use Yii; |
||||||
|
use yii\base\Model; |
||||||
|
|
||||||
|
/** |
||||||
|
* LoginForm is the model behind the login form. |
||||||
|
* |
||||||
|
* @property-read User|null $user |
||||||
|
* |
||||||
|
*/ |
||||||
|
class LoginForm extends Model |
||||||
|
{ |
||||||
|
public $username; |
||||||
|
public $password; |
||||||
|
public $rememberMe = true; |
||||||
|
|
||||||
|
private $_user = false; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @return array the validation rules. |
||||||
|
*/ |
||||||
|
public function rules() |
||||||
|
{ |
||||||
|
return [ |
||||||
|
// username and password are both required |
||||||
|
[['username', 'password'], 'required'], |
||||||
|
// rememberMe must be a boolean value |
||||||
|
['rememberMe', 'boolean'], |
||||||
|
// password is validated by validatePassword() |
||||||
|
['password', 'validatePassword'], |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Validates the password. |
||||||
|
* This method serves as the inline validation for password. |
||||||
|
* |
||||||
|
* @param string $attribute the attribute currently being validated |
||||||
|
* @param array $params the additional name-value pairs given in the rule |
||||||
|
*/ |
||||||
|
public function validatePassword($attribute, $params) |
||||||
|
{ |
||||||
|
if (!$this->hasErrors()) { |
||||||
|
$user = $this->getUser(); |
||||||
|
|
||||||
|
if (!$user || !$user->validatePassword($this->password)) { |
||||||
|
$this->addError($attribute, 'Incorrect username or password.'); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Logs in a user using the provided username and password. |
||||||
|
* @return bool whether the user is logged in successfully |
||||||
|
*/ |
||||||
|
public function login() |
||||||
|
{ |
||||||
|
if ($this->validate()) { |
||||||
|
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Finds user by [[username]] |
||||||
|
* |
||||||
|
* @return User|null |
||||||
|
*/ |
||||||
|
public function getUser() |
||||||
|
{ |
||||||
|
if ($this->_user === false) { |
||||||
|
$this->_user = User::findByUsername($this->username); |
||||||
|
} |
||||||
|
|
||||||
|
return $this->_user; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,104 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace app\models; |
||||||
|
|
||||||
|
class User extends \yii\base\BaseObject implements \yii\web\IdentityInterface |
||||||
|
{ |
||||||
|
public $id; |
||||||
|
public $username; |
||||||
|
public $password; |
||||||
|
public $authKey; |
||||||
|
public $accessToken; |
||||||
|
|
||||||
|
private static $users = [ |
||||||
|
'100' => [ |
||||||
|
'id' => '100', |
||||||
|
'username' => 'admin', |
||||||
|
'password' => 'admin', |
||||||
|
'authKey' => 'test100key', |
||||||
|
'accessToken' => '100-token', |
||||||
|
], |
||||||
|
'101' => [ |
||||||
|
'id' => '101', |
||||||
|
'username' => 'demo', |
||||||
|
'password' => 'demo', |
||||||
|
'authKey' => 'test101key', |
||||||
|
'accessToken' => '101-token', |
||||||
|
], |
||||||
|
]; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public static function findIdentity($id) |
||||||
|
{ |
||||||
|
return isset(self::$users[$id]) ? new static(self::$users[$id]) : null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public static function findIdentityByAccessToken($token, $type = null) |
||||||
|
{ |
||||||
|
foreach (self::$users as $user) { |
||||||
|
if ($user['accessToken'] === $token) { |
||||||
|
return new static($user); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Finds user by username |
||||||
|
* |
||||||
|
* @param string $username |
||||||
|
* @return static|null |
||||||
|
*/ |
||||||
|
public static function findByUsername($username) |
||||||
|
{ |
||||||
|
foreach (self::$users as $user) { |
||||||
|
if (strcasecmp($user['username'], $username) === 0) { |
||||||
|
return new static($user); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function getId() |
||||||
|
{ |
||||||
|
return $this->id; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function getAuthKey() |
||||||
|
{ |
||||||
|
return $this->authKey; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function validateAuthKey($authKey) |
||||||
|
{ |
||||||
|
return $this->authKey === $authKey; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Validates password |
||||||
|
* |
||||||
|
* @param string $password password to validate |
||||||
|
* @return bool if password provided is valid for current user |
||||||
|
*/ |
||||||
|
public function validatePassword($password) |
||||||
|
{ |
||||||
|
return $this->password === $password; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,162 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* Application requirement checker script. |
||||||
|
* |
||||||
|
* In order to run this script use the following console command: |
||||||
|
* php requirements.php |
||||||
|
* |
||||||
|
* In order to run this script from the web, you should copy it to the web root. |
||||||
|
* If you are using Linux you can create a hard link instead, using the following command: |
||||||
|
* ln ../requirements.php requirements.php |
||||||
|
*/ |
||||||
|
|
||||||
|
// you may need to adjust this path to the correct Yii framework path |
||||||
|
// uncomment and adjust the following line if Yii is not located at the default path |
||||||
|
//$frameworkPath = dirname(__FILE__) . '/vendor/yiisoft/yii2'; |
||||||
|
|
||||||
|
|
||||||
|
if (!isset($frameworkPath)) { |
||||||
|
$searchPaths = array( |
||||||
|
dirname(__FILE__) . '/vendor/yiisoft/yii2', |
||||||
|
dirname(__FILE__) . '/../vendor/yiisoft/yii2', |
||||||
|
); |
||||||
|
foreach ($searchPaths as $path) { |
||||||
|
if (is_dir($path)) { |
||||||
|
$frameworkPath = $path; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (!isset($frameworkPath) || !is_dir($frameworkPath)) { |
||||||
|
$message = "<h1>Error</h1>\n\n" |
||||||
|
. "<p><strong>The path to yii framework seems to be incorrect.</strong></p>\n" |
||||||
|
. '<p>You need to install Yii framework via composer or adjust the framework path in file <abbr title="' . __FILE__ . '">' . basename(__FILE__) . "</abbr>.</p>\n" |
||||||
|
. '<p>Please refer to the <abbr title="' . dirname(__FILE__) . "/README.md\">README</abbr> on how to install Yii.</p>\n"; |
||||||
|
|
||||||
|
if (!empty($_SERVER['argv'])) { |
||||||
|
// do not print HTML when used in console mode |
||||||
|
echo strip_tags($message); |
||||||
|
} else { |
||||||
|
echo $message; |
||||||
|
} |
||||||
|
exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
require_once($frameworkPath . '/requirements/YiiRequirementChecker.php'); |
||||||
|
$requirementsChecker = new YiiRequirementChecker(); |
||||||
|
|
||||||
|
$gdMemo = $imagickMemo = 'Either GD PHP extension with FreeType support or ImageMagick PHP extension with PNG support is required for image CAPTCHA.'; |
||||||
|
$gdOK = $imagickOK = false; |
||||||
|
|
||||||
|
if (extension_loaded('imagick')) { |
||||||
|
$imagick = new Imagick(); |
||||||
|
$imagickFormats = $imagick->queryFormats('PNG'); |
||||||
|
if (in_array('PNG', $imagickFormats)) { |
||||||
|
$imagickOK = true; |
||||||
|
} else { |
||||||
|
$imagickMemo = 'Imagick extension should be installed with PNG support in order to be used for image CAPTCHA.'; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (extension_loaded('gd')) { |
||||||
|
$gdInfo = gd_info(); |
||||||
|
if (!empty($gdInfo['FreeType Support'])) { |
||||||
|
$gdOK = true; |
||||||
|
} else { |
||||||
|
$gdMemo = 'GD extension should be installed with FreeType support in order to be used for image CAPTCHA.'; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Adjust requirements according to your application specifics. |
||||||
|
*/ |
||||||
|
$requirements = array( |
||||||
|
// Database : |
||||||
|
array( |
||||||
|
'name' => 'PDO extension', |
||||||
|
'mandatory' => true, |
||||||
|
'condition' => extension_loaded('pdo'), |
||||||
|
'by' => 'All DB-related classes', |
||||||
|
), |
||||||
|
array( |
||||||
|
'name' => 'PDO SQLite extension', |
||||||
|
'mandatory' => false, |
||||||
|
'condition' => extension_loaded('pdo_sqlite'), |
||||||
|
'by' => 'All DB-related classes', |
||||||
|
'memo' => 'Required for SQLite database.', |
||||||
|
), |
||||||
|
array( |
||||||
|
'name' => 'PDO MySQL extension', |
||||||
|
'mandatory' => false, |
||||||
|
'condition' => extension_loaded('pdo_mysql'), |
||||||
|
'by' => 'All DB-related classes', |
||||||
|
'memo' => 'Required for MySQL database.', |
||||||
|
), |
||||||
|
array( |
||||||
|
'name' => 'PDO PostgreSQL extension', |
||||||
|
'mandatory' => false, |
||||||
|
'condition' => extension_loaded('pdo_pgsql'), |
||||||
|
'by' => 'All DB-related classes', |
||||||
|
'memo' => 'Required for PostgreSQL database.', |
||||||
|
), |
||||||
|
// Cache : |
||||||
|
array( |
||||||
|
'name' => 'Memcache extension', |
||||||
|
'mandatory' => false, |
||||||
|
'condition' => extension_loaded('memcache') || extension_loaded('memcached'), |
||||||
|
'by' => '<a href="https://www.yiiframework.com/doc-2.0/yii-caching-memcache.html">MemCache</a>', |
||||||
|
'memo' => extension_loaded('memcached') ? 'To use memcached set <a href="https://www.yiiframework.com/doc-2.0/yii-caching-memcache.html#$useMemcached-detail">MemCache::useMemcached</a> to <code>true</code>.' : '' |
||||||
|
), |
||||||
|
// CAPTCHA: |
||||||
|
array( |
||||||
|
'name' => 'GD PHP extension with FreeType support', |
||||||
|
'mandatory' => false, |
||||||
|
'condition' => $gdOK, |
||||||
|
'by' => '<a href="https://www.yiiframework.com/doc-2.0/yii-captcha-captcha.html">Captcha</a>', |
||||||
|
'memo' => $gdMemo, |
||||||
|
), |
||||||
|
array( |
||||||
|
'name' => 'ImageMagick PHP extension with PNG support', |
||||||
|
'mandatory' => false, |
||||||
|
'condition' => $imagickOK, |
||||||
|
'by' => '<a href="https://www.yiiframework.com/doc-2.0/yii-captcha-captcha.html">Captcha</a>', |
||||||
|
'memo' => $imagickMemo, |
||||||
|
), |
||||||
|
// PHP ini : |
||||||
|
'phpExposePhp' => array( |
||||||
|
'name' => 'Expose PHP', |
||||||
|
'mandatory' => false, |
||||||
|
'condition' => $requirementsChecker->checkPhpIniOff("expose_php"), |
||||||
|
'by' => 'Security reasons', |
||||||
|
'memo' => '"expose_php" should be disabled at php.ini', |
||||||
|
), |
||||||
|
'phpAllowUrlInclude' => array( |
||||||
|
'name' => 'PHP allow url include', |
||||||
|
'mandatory' => false, |
||||||
|
'condition' => $requirementsChecker->checkPhpIniOff("allow_url_include"), |
||||||
|
'by' => 'Security reasons', |
||||||
|
'memo' => '"allow_url_include" should be disabled at php.ini', |
||||||
|
), |
||||||
|
'phpSmtp' => array( |
||||||
|
'name' => 'PHP mail SMTP', |
||||||
|
'mandatory' => false, |
||||||
|
'condition' => strlen(ini_get('SMTP')) > 0, |
||||||
|
'by' => 'Email sending', |
||||||
|
'memo' => 'PHP mail SMTP server required', |
||||||
|
), |
||||||
|
); |
||||||
|
|
||||||
|
// OPcache check |
||||||
|
if (!version_compare(phpversion(), '5.5', '>=')) { |
||||||
|
$requirements[] = array( |
||||||
|
'name' => 'APC extension', |
||||||
|
'mandatory' => false, |
||||||
|
'condition' => extension_loaded('apc'), |
||||||
|
'by' => '<a href="https://www.yiiframework.com/doc-2.0/yii-caching-apccache.html">ApcCache</a>', |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
$result = $requirementsChecker->checkYii()->check($requirements)->getResult(); |
||||||
|
$requirementsChecker->render(); |
||||||
|
exit($result['summary']['errors'] === 0 ? 0 : 1); |
@ -0,0 +1,6 @@ |
|||||||
|
<?php |
||||||
|
define('YII_ENV', 'test'); |
||||||
|
defined('YII_DEBUG') or define('YII_DEBUG', true); |
||||||
|
|
||||||
|
require_once __DIR__ . '/../vendor/yiisoft/yii2/Yii.php'; |
||||||
|
require __DIR__ .'/../vendor/autoload.php'; |
@ -0,0 +1,26 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Inherited Methods |
||||||
|
* @method void wantToTest($text) |
||||||
|
* @method void wantTo($text) |
||||||
|
* @method void execute($callable) |
||||||
|
* @method void expectTo($prediction) |
||||||
|
* @method void expect($prediction) |
||||||
|
* @method void amGoingTo($argumentation) |
||||||
|
* @method void am($role) |
||||||
|
* @method void lookForwardTo($achieveValue) |
||||||
|
* @method void comment($description) |
||||||
|
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL) |
||||||
|
* |
||||||
|
* @SuppressWarnings(PHPMD) |
||||||
|
*/ |
||||||
|
class AcceptanceTester extends \Codeception\Actor |
||||||
|
{ |
||||||
|
use _generated\AcceptanceTesterActions; |
||||||
|
|
||||||
|
/** |
||||||
|
* Define custom actions here |
||||||
|
*/ |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Inherited Methods |
||||||
|
* @method void wantToTest($text) |
||||||
|
* @method void wantTo($text) |
||||||
|
* @method void execute($callable) |
||||||
|
* @method void expectTo($prediction) |
||||||
|
* @method void expect($prediction) |
||||||
|
* @method void amGoingTo($argumentation) |
||||||
|
* @method void am($role) |
||||||
|
* @method void lookForwardTo($achieveValue) |
||||||
|
* @method void comment($description) |
||||||
|
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL) |
||||||
|
* |
||||||
|
* @SuppressWarnings(PHPMD) |
||||||
|
*/ |
||||||
|
class FunctionalTester extends \Codeception\Actor |
||||||
|
{ |
||||||
|
use _generated\FunctionalTesterActions; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Inherited Methods |
||||||
|
* @method void wantToTest($text) |
||||||
|
* @method void wantTo($text) |
||||||
|
* @method void execute($callable) |
||||||
|
* @method void expectTo($prediction) |
||||||
|
* @method void expect($prediction) |
||||||
|
* @method void amGoingTo($argumentation) |
||||||
|
* @method void am($role) |
||||||
|
* @method void lookForwardTo($achieveValue) |
||||||
|
* @method void comment($description) |
||||||
|
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL) |
||||||
|
* |
||||||
|
* @SuppressWarnings(PHPMD) |
||||||
|
*/ |
||||||
|
class UnitTester extends \Codeception\Actor |
||||||
|
{ |
||||||
|
use _generated\UnitTesterActions; |
||||||
|
|
||||||
|
/** |
||||||
|
* Define custom actions here |
||||||
|
*/ |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
actor: AcceptanceTester |
||||||
|
modules: |
||||||
|
enabled: |
||||||
|
- WebDriver: |
||||||
|
url: http://127.0.0.1:8080/ |
||||||
|
browser: firefox |
||||||
|
- Yii2: |
||||||
|
part: orm |
||||||
|
entryScript: index-test.php |
||||||
|
cleanup: false |
@ -0,0 +1,12 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
use yii\helpers\Url; |
||||||
|
|
||||||
|
class AboutCest |
||||||
|
{ |
||||||
|
public function ensureThatAboutWorks(AcceptanceTester $I) |
||||||
|
{ |
||||||
|
$I->amOnPage(Url::toRoute('/site/about')); |
||||||
|
$I->see('About', 'h1'); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
use yii\helpers\Url; |
||||||
|
|
||||||
|
class ContactCest |
||||||
|
{ |
||||||
|
public function _before(\AcceptanceTester $I) |
||||||
|
{ |
||||||
|
$I->amOnPage(Url::toRoute('/site/contact')); |
||||||
|
} |
||||||
|
|
||||||
|
public function contactPageWorks(AcceptanceTester $I) |
||||||
|
{ |
||||||
|
$I->wantTo('ensure that contact page works'); |
||||||
|
$I->see('Contact', 'h1'); |
||||||
|
} |
||||||
|
|
||||||
|
public function contactFormCanBeSubmitted(AcceptanceTester $I) |
||||||
|
{ |
||||||
|
$I->amGoingTo('submit contact form with correct data'); |
||||||
|
$I->fillField('#contactform-name', 'tester'); |
||||||
|
$I->fillField('#contactform-email', 'tester@example.com'); |
||||||
|
$I->fillField('#contactform-subject', 'test subject'); |
||||||
|
$I->fillField('#contactform-body', 'test content'); |
||||||
|
$I->fillField('#contactform-verifycode', 'testme'); |
||||||
|
|
||||||
|
$I->click('contact-button'); |
||||||
|
|
||||||
|
$I->wait(2); // wait for button to be clicked |
||||||
|
|
||||||
|
$I->dontSeeElement('#contact-form'); |
||||||
|
$I->see('Thank you for contacting us. We will respond to you as soon as possible.'); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
use yii\helpers\Url; |
||||||
|
|
||||||
|
class HomeCest |
||||||
|
{ |
||||||
|
public function ensureThatHomePageWorks(AcceptanceTester $I) |
||||||
|
{ |
||||||
|
$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.'); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
use yii\helpers\Url; |
||||||
|
|
||||||
|
class LoginCest |
||||||
|
{ |
||||||
|
public function ensureThatLoginWorks(AcceptanceTester $I) |
||||||
|
{ |
||||||
|
$I->amOnPage(Url::toRoute('/site/login')); |
||||||
|
$I->see('Login', 'h1'); |
||||||
|
|
||||||
|
$I->amGoingTo('try to login with correct credentials'); |
||||||
|
$I->fillField('input[name="LoginForm[username]"]', 'admin'); |
||||||
|
$I->fillField('input[name="LoginForm[password]"]', 'admin'); |
||||||
|
$I->click('login-button'); |
||||||
|
$I->wait(2); // wait for button to be clicked |
||||||
|
|
||||||
|
$I->expectTo('see user info'); |
||||||
|
$I->see('Logout'); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
#!/usr/bin/env php |
||||||
|
<?php |
||||||
|
/** |
||||||
|
* Yii console bootstrap file. |
||||||
|
* |
||||||
|
* @link https://www.yiiframework.com/ |
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
* @license https://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
defined('YII_DEBUG') or define('YII_DEBUG', true); |
||||||
|
defined('YII_ENV') or define('YII_ENV', 'test'); |
||||||
|
|
||||||
|
require __DIR__ . '/../../vendor/autoload.php'; |
||||||
|
require __DIR__ . '/../../vendor/yiisoft/yii2/Yii.php'; |
||||||
|
|
||||||
|
$config = yii\helpers\ArrayHelper::merge( |
||||||
|
require __DIR__ . '/../../config/console.php', |
||||||
|
[ |
||||||
|
'components' => [ |
||||||
|
'db' => require __DIR__ . '/../../config/test_db.php' |
||||||
|
] |
||||||
|
] |
||||||
|
); |
||||||
|
|
||||||
|
|
||||||
|
$application = new yii\console\Application($config); |
||||||
|
$exitCode = $application->run(); |
||||||
|
exit($exitCode); |
@ -0,0 +1,20 @@ |
|||||||
|
@echo off |
||||||
|
|
||||||
|
rem ------------------------------------------------------------- |
||||||
|
rem Yii command line bootstrap script for Windows. |
||||||
|
rem |
||||||
|
rem @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
rem @link https://www.yiiframework.com/ |
||||||
|
rem @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
rem @license https://www.yiiframework.com/license/ |
||||||
|
rem ------------------------------------------------------------- |
||||||
|
|
||||||
|
@setlocal |
||||||
|
|
||||||
|
set YII_PATH=%~dp0 |
||||||
|
|
||||||
|
if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe |
||||||
|
|
||||||
|
"%PHP_COMMAND%" "%YII_PATH%yii" %* |
||||||
|
|
||||||
|
@endlocal |
@ -0,0 +1,14 @@ |
|||||||
|
# Codeception Test Suite Configuration |
||||||
|
|
||||||
|
# suite for functional (integration) tests. |
||||||
|
# emulate web requests and make application process them. |
||||||
|
# (tip: better to use with frameworks). |
||||||
|
|
||||||
|
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES. |
||||||
|
#basic/web/index.php |
||||||
|
actor: FunctionalTester |
||||||
|
modules: |
||||||
|
enabled: |
||||||
|
- Filesystem |
||||||
|
- Yii2 |
||||||
|
- Asserts |
@ -0,0 +1,57 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
class ContactFormCest |
||||||
|
{ |
||||||
|
public function _before(\FunctionalTester $I) |
||||||
|
{ |
||||||
|
$I->amOnRoute('site/contact'); |
||||||
|
} |
||||||
|
|
||||||
|
public function openContactPage(\FunctionalTester $I) |
||||||
|
{ |
||||||
|
$I->see('Contact', 'h1'); |
||||||
|
} |
||||||
|
|
||||||
|
public function submitEmptyForm(\FunctionalTester $I) |
||||||
|
{ |
||||||
|
$I->submitForm('#contact-form', []); |
||||||
|
$I->expectTo('see validations errors'); |
||||||
|
$I->see('Contact', 'h1'); |
||||||
|
$I->see('Name cannot be blank'); |
||||||
|
$I->see('Email cannot be blank'); |
||||||
|
$I->see('Subject cannot be blank'); |
||||||
|
$I->see('Body cannot be blank'); |
||||||
|
$I->see('The verification code is incorrect'); |
||||||
|
} |
||||||
|
|
||||||
|
public function submitFormWithIncorrectEmail(\FunctionalTester $I) |
||||||
|
{ |
||||||
|
$I->submitForm('#contact-form', [ |
||||||
|
'ContactForm[name]' => 'tester', |
||||||
|
'ContactForm[email]' => 'tester.email', |
||||||
|
'ContactForm[subject]' => 'test subject', |
||||||
|
'ContactForm[body]' => 'test content', |
||||||
|
'ContactForm[verifyCode]' => 'testme', |
||||||
|
]); |
||||||
|
$I->expectTo('see that email address is wrong'); |
||||||
|
$I->dontSee('Name cannot be blank', '.help-inline'); |
||||||
|
$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'); |
||||||
|
} |
||||||
|
|
||||||
|
public function submitFormSuccessfully(\FunctionalTester $I) |
||||||
|
{ |
||||||
|
$I->submitForm('#contact-form', [ |
||||||
|
'ContactForm[name]' => 'tester', |
||||||
|
'ContactForm[email]' => 'tester@example.com', |
||||||
|
'ContactForm[subject]' => 'test subject', |
||||||
|
'ContactForm[body]' => 'test content', |
||||||
|
'ContactForm[verifyCode]' => 'testme', |
||||||
|
]); |
||||||
|
$I->seeEmailIsSent(); |
||||||
|
$I->dontSeeElement('#contact-form'); |
||||||
|
$I->see('Thank you for contacting us. We will respond to you as soon as possible.'); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
class LoginFormCest |
||||||
|
{ |
||||||
|
public function _before(\FunctionalTester $I) |
||||||
|
{ |
||||||
|
$I->amOnRoute('site/login'); |
||||||
|
} |
||||||
|
|
||||||
|
public function openLoginPage(\FunctionalTester $I) |
||||||
|
{ |
||||||
|
$I->see('Login', 'h1'); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// demonstrates `amLoggedInAs` method |
||||||
|
public function internalLoginById(\FunctionalTester $I) |
||||||
|
{ |
||||||
|
$I->amLoggedInAs(100); |
||||||
|
$I->amOnPage('/'); |
||||||
|
$I->see('Logout (admin)'); |
||||||
|
} |
||||||
|
|
||||||
|
// demonstrates `amLoggedInAs` method |
||||||
|
public function internalLoginByInstance(\FunctionalTester $I) |
||||||
|
{ |
||||||
|
$I->amLoggedInAs(\app\models\User::findByUsername('admin')); |
||||||
|
$I->amOnPage('/'); |
||||||
|
$I->see('Logout (admin)'); |
||||||
|
} |
||||||
|
|
||||||
|
public function loginWithEmptyCredentials(\FunctionalTester $I) |
||||||
|
{ |
||||||
|
$I->submitForm('#login-form', []); |
||||||
|
$I->expectTo('see validations errors'); |
||||||
|
$I->see('Username cannot be blank.'); |
||||||
|
$I->see('Password cannot be blank.'); |
||||||
|
} |
||||||
|
|
||||||
|
public function loginWithWrongCredentials(\FunctionalTester $I) |
||||||
|
{ |
||||||
|
$I->submitForm('#login-form', [ |
||||||
|
'LoginForm[username]' => 'admin', |
||||||
|
'LoginForm[password]' => 'wrong', |
||||||
|
]); |
||||||
|
$I->expectTo('see validations errors'); |
||||||
|
$I->see('Incorrect username or password.'); |
||||||
|
} |
||||||
|
|
||||||
|
public function loginSuccessfully(\FunctionalTester $I) |
||||||
|
{ |
||||||
|
$I->submitForm('#login-form', [ |
||||||
|
'LoginForm[username]' => 'admin', |
||||||
|
'LoginForm[password]' => 'admin', |
||||||
|
]); |
||||||
|
$I->see('Logout (admin)'); |
||||||
|
$I->dontSeeElement('form#login-form'); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
# Codeception Test Suite Configuration |
||||||
|
|
||||||
|
# suite for unit (internal) tests. |
||||||
|
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES. |
||||||
|
|
||||||
|
actor: UnitTester |
||||||
|
modules: |
||||||
|
enabled: |
||||||
|
- Asserts |
||||||
|
- Yii2: |
||||||
|
part: [orm, email, fixtures] |
@ -0,0 +1,3 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
// add unit testing specific bootstrap code here |
@ -0,0 +1,41 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace tests\unit\models; |
||||||
|
|
||||||
|
use app\models\ContactForm; |
||||||
|
use yii\mail\MessageInterface; |
||||||
|
|
||||||
|
class ContactFormTest extends \Codeception\Test\Unit |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @var \UnitTester |
||||||
|
*/ |
||||||
|
public $tester; |
||||||
|
|
||||||
|
public function testEmailIsSentOnContact() |
||||||
|
{ |
||||||
|
$model = new ContactForm(); |
||||||
|
|
||||||
|
$model->attributes = [ |
||||||
|
'name' => 'Tester', |
||||||
|
'email' => 'tester@example.com', |
||||||
|
'subject' => 'very important letter subject', |
||||||
|
'body' => 'body of current message', |
||||||
|
'verifyCode' => 'testme', |
||||||
|
]; |
||||||
|
|
||||||
|
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(); |
||||||
|
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'); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace tests\unit\models; |
||||||
|
|
||||||
|
use app\models\LoginForm; |
||||||
|
|
||||||
|
class LoginFormTest extends \Codeception\Test\Unit |
||||||
|
{ |
||||||
|
private $model; |
||||||
|
|
||||||
|
protected function _after() |
||||||
|
{ |
||||||
|
\Yii::$app->user->logout(); |
||||||
|
} |
||||||
|
|
||||||
|
public function testLoginNoUser() |
||||||
|
{ |
||||||
|
$this->model = new LoginForm([ |
||||||
|
'username' => 'not_existing_username', |
||||||
|
'password' => 'not_existing_password', |
||||||
|
]); |
||||||
|
|
||||||
|
verify($this->model->login())->false(); |
||||||
|
verify(\Yii::$app->user->isGuest)->true(); |
||||||
|
} |
||||||
|
|
||||||
|
public function testLoginWrongPassword() |
||||||
|
{ |
||||||
|
$this->model = new LoginForm([ |
||||||
|
'username' => 'demo', |
||||||
|
'password' => 'wrong_password', |
||||||
|
]); |
||||||
|
|
||||||
|
verify($this->model->login())->false(); |
||||||
|
verify(\Yii::$app->user->isGuest)->true(); |
||||||
|
verify($this->model->errors)->arrayHasKey('password'); |
||||||
|
} |
||||||
|
|
||||||
|
public function testLoginCorrect() |
||||||
|
{ |
||||||
|
$this->model = new LoginForm([ |
||||||
|
'username' => 'demo', |
||||||
|
'password' => 'demo', |
||||||
|
]); |
||||||
|
|
||||||
|
verify($this->model->login())->true(); |
||||||
|
verify(\Yii::$app->user->isGuest)->false(); |
||||||
|
verify($this->model->errors)->arrayHasNotKey('password'); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace tests\unit\models; |
||||||
|
|
||||||
|
use app\models\User; |
||||||
|
|
||||||
|
class UserTest extends \Codeception\Test\Unit |
||||||
|
{ |
||||||
|
public function testFindUserById() |
||||||
|
{ |
||||||
|
verify($user = User::findIdentity(100))->notEmpty(); |
||||||
|
verify($user->username)->equals('admin'); |
||||||
|
|
||||||
|
verify(User::findIdentity(999))->empty(); |
||||||
|
} |
||||||
|
|
||||||
|
public function testFindUserByAccessToken() |
||||||
|
{ |
||||||
|
verify($user = User::findIdentityByAccessToken('100-token'))->notEmpty(); |
||||||
|
verify($user->username)->equals('admin'); |
||||||
|
|
||||||
|
verify(User::findIdentityByAccessToken('non-existing'))->empty(); |
||||||
|
} |
||||||
|
|
||||||
|
public function testFindUserByUsername() |
||||||
|
{ |
||||||
|
verify($user = User::findByUsername('admin'))->notEmpty(); |
||||||
|
verify(User::findByUsername('not-admin'))->empty(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @depends testFindUserByUsername |
||||||
|
*/ |
||||||
|
public function testValidateUser() |
||||||
|
{ |
||||||
|
$user = User::findByUsername('admin'); |
||||||
|
verify($user->validateAuthKey('test100key'))->notEmpty(); |
||||||
|
verify($user->validateAuthKey('test102key'))->empty(); |
||||||
|
|
||||||
|
verify($user->validatePassword('admin'))->notEmpty(); |
||||||
|
verify($user->validatePassword('123456'))->empty(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,261 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace tests\unit\widgets; |
||||||
|
|
||||||
|
use app\widgets\Alert; |
||||||
|
use Yii; |
||||||
|
|
||||||
|
class AlertTest extends \Codeception\Test\Unit |
||||||
|
{ |
||||||
|
public function testSingleErrorMessage() |
||||||
|
{ |
||||||
|
$message = 'This is an error message'; |
||||||
|
|
||||||
|
Yii::$app->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); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
<?php |
||||||
|
$html = file_get_contents(Yii::getAlias('@webroot/index.html')); |
||||||
|
//$html = str_replace('http://localhost:9093', '/', $html); |
||||||
|
?> |
||||||
|
|
||||||
|
<?= $html ?> |
@ -0,0 +1,18 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** @var yii\web\View $this */ |
||||||
|
|
||||||
|
use yii\helpers\Html; |
||||||
|
|
||||||
|
$this->title = 'About'; |
||||||
|
$this->params['breadcrumbs'][] = $this->title; |
||||||
|
?> |
||||||
|
<div class="site-about"> |
||||||
|
<h1><?= Html::encode($this->title) ?></h1>
|
||||||
|
|
||||||
|
<p> |
||||||
|
This is the About page. You may modify the following file to customize its content: |
||||||
|
</p> |
||||||
|
|
||||||
|
<code><?= __FILE__ ?></code>
|
||||||
|
</div> |
@ -0,0 +1,68 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** @var yii\web\View $this */ |
||||||
|
/** @var yii\bootstrap5\ActiveForm $form */ |
||||||
|
/** @var app\models\ContactForm $model */ |
||||||
|
|
||||||
|
use yii\bootstrap5\ActiveForm; |
||||||
|
use yii\bootstrap5\Html; |
||||||
|
use yii\captcha\Captcha; |
||||||
|
|
||||||
|
$this->title = 'Contact'; |
||||||
|
$this->params['breadcrumbs'][] = $this->title; |
||||||
|
?> |
||||||
|
<div class="site-contact"> |
||||||
|
<h1><?= Html::encode($this->title) ?></h1>
|
||||||
|
|
||||||
|
<?php if (Yii::$app->session->hasFlash('contactFormSubmitted')): ?> |
||||||
|
|
||||||
|
<div class="alert alert-success"> |
||||||
|
Thank you for contacting us. We will respond to you as soon as possible. |
||||||
|
</div> |
||||||
|
|
||||||
|
<p> |
||||||
|
Note that if you turn on the Yii debugger, you should be able |
||||||
|
to view the mail message on the mail panel of the debugger. |
||||||
|
<?php if (Yii::$app->mailer->useFileTransport): ?> |
||||||
|
Because the application is in development mode, the email is not sent but saved as |
||||||
|
a file under <code><?= Yii::getAlias(Yii::$app->mailer->fileTransportPath) ?></code>.
|
||||||
|
Please configure the <code>useFileTransport</code> property of the <code>mail</code> |
||||||
|
application component to be false to enable email sending. |
||||||
|
<?php endif; ?> |
||||||
|
</p> |
||||||
|
|
||||||
|
<?php else: ?> |
||||||
|
|
||||||
|
<p> |
||||||
|
If you have business inquiries or other questions, please fill out the following form to contact us. |
||||||
|
Thank you. |
||||||
|
</p> |
||||||
|
|
||||||
|
<div class="row"> |
||||||
|
<div class="col-lg-5"> |
||||||
|
|
||||||
|
<?php $form = ActiveForm::begin(['id' => 'contact-form']); ?> |
||||||
|
|
||||||
|
<?= $form->field($model, 'name')->textInput(['autofocus' => true]) ?> |
||||||
|
|
||||||
|
<?= $form->field($model, 'email') ?> |
||||||
|
|
||||||
|
<?= $form->field($model, 'subject') ?> |
||||||
|
|
||||||
|
<?= $form->field($model, 'body')->textarea(['rows' => 6]) ?> |
||||||
|
|
||||||
|
<?= $form->field($model, 'verifyCode')->widget(Captcha::class, [ |
||||||
|
'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>', |
||||||
|
]) ?> |
||||||
|
|
||||||
|
<div class="form-group"> |
||||||
|
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?> |
||||||
|
</div> |
||||||
|
|
||||||
|
<?php ActiveForm::end(); ?> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<?php endif; ?> |
||||||
|
</div> |
@ -0,0 +1,27 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** @var yii\web\View $this */ |
||||||
|
/** @var string $name */ |
||||||
|
/** @var string $message */ |
||||||
|
/** @var Exception$exception */ |
||||||
|
|
||||||
|
use yii\helpers\Html; |
||||||
|
|
||||||
|
$this->title = $name; |
||||||
|
?> |
||||||
|
<div class="site-error"> |
||||||
|
|
||||||
|
<h1><?= Html::encode($this->title) ?></h1>
|
||||||
|
|
||||||
|
<div class="alert alert-danger"> |
||||||
|
<?= nl2br(Html::encode($message)) ?> |
||||||
|
</div> |
||||||
|
|
||||||
|
<p> |
||||||
|
The above error occurred while the Web server was processing your request. |
||||||
|
</p> |
||||||
|
<p> |
||||||
|
Please contact us if you think this is a server error. Thank you. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
@ -0,0 +1,53 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** @var yii\web\View $this */ |
||||||
|
|
||||||
|
$this->title = 'My Yii Application'; |
||||||
|
?> |
||||||
|
<div class="site-index"> |
||||||
|
|
||||||
|
<div class="jumbotron text-center bg-transparent mt-5 mb-5"> |
||||||
|
<h1 class="display-4">Congratulations!</h1> |
||||||
|
|
||||||
|
<p class="lead">You have successfully created your Yii-powered application.</p> |
||||||
|
|
||||||
|
<p><a class="btn btn-lg btn-success" href="https://www.yiiframework.com">Get started with Yii</a></p> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="body-content"> |
||||||
|
|
||||||
|
<div class="row"> |
||||||
|
<div class="col-lg-4 mb-3"> |
||||||
|
<h2>Heading</h2> |
||||||
|
|
||||||
|
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et |
||||||
|
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip |
||||||
|
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu |
||||||
|
fugiat nulla pariatur.</p> |
||||||
|
|
||||||
|
<p><a class="btn btn-outline-secondary" href="https://www.yiiframework.com/doc/">Yii Documentation »</a></p> |
||||||
|
</div> |
||||||
|
<div class="col-lg-4 mb-3"> |
||||||
|
<h2>Heading</h2> |
||||||
|
|
||||||
|
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et |
||||||
|
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip |
||||||
|
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu |
||||||
|
fugiat nulla pariatur.</p> |
||||||
|
|
||||||
|
<p><a class="btn btn-outline-secondary" href="https://www.yiiframework.com/forum/">Yii Forum »</a></p> |
||||||
|
</div> |
||||||
|
<div class="col-lg-4"> |
||||||
|
<h2>Heading</h2> |
||||||
|
|
||||||
|
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et |
||||||
|
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip |
||||||
|
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu |
||||||
|
fugiat nulla pariatur.</p> |
||||||
|
|
||||||
|
<p><a class="btn btn-outline-secondary" href="https://www.yiiframework.com/extensions/">Yii Extensions »</a></p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
@ -0,0 +1,55 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** @var yii\web\View $this */ |
||||||
|
/** @var yii\bootstrap5\ActiveForm $form */ |
||||||
|
|
||||||
|
/** @var app\models\LoginForm $model */ |
||||||
|
|
||||||
|
use yii\bootstrap5\ActiveForm; |
||||||
|
use yii\bootstrap5\Html; |
||||||
|
|
||||||
|
$this->title = 'Login'; |
||||||
|
$this->params['breadcrumbs'][] = $this->title; |
||||||
|
?> |
||||||
|
<div class="site-login"> |
||||||
|
<h1><?= Html::encode($this->title) ?></h1>
|
||||||
|
|
||||||
|
<p>Please fill out the following fields to login:</p> |
||||||
|
|
||||||
|
<div class="row"> |
||||||
|
<div class="col-lg-5"> |
||||||
|
|
||||||
|
<?php $form = ActiveForm::begin([ |
||||||
|
'id' => 'login-form', |
||||||
|
'fieldConfig' => [ |
||||||
|
'template' => "{label}\n{input}\n{error}", |
||||||
|
'labelOptions' => ['class' => 'col-lg-1 col-form-label mr-lg-3'], |
||||||
|
'inputOptions' => ['class' => 'col-lg-3 form-control'], |
||||||
|
'errorOptions' => ['class' => 'col-lg-7 invalid-feedback'], |
||||||
|
], |
||||||
|
]); ?> |
||||||
|
|
||||||
|
<?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?> |
||||||
|
|
||||||
|
<?= $form->field($model, 'password')->passwordInput() ?> |
||||||
|
|
||||||
|
<?= $form->field($model, 'rememberMe')->checkbox([ |
||||||
|
'template' => "<div class=\"custom-control custom-checkbox\">{input} {label}</div>\n<div class=\"col-lg-8\">{error}</div>", |
||||||
|
]) ?> |
||||||
|
|
||||||
|
<div class="form-group"> |
||||||
|
<div> |
||||||
|
<?= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<?php ActiveForm::end(); ?> |
||||||
|
|
||||||
|
<div style="color:#999;"> |
||||||
|
You may login with <strong>admin/admin</strong> or <strong>demo/demo</strong>.<br> |
||||||
|
To modify the username/password, please check out the code <code>app\models\User::$users</code>. |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
@ -0,0 +1,24 @@ |
|||||||
|
# Logs |
||||||
|
logs |
||||||
|
*.log |
||||||
|
npm-debug.log* |
||||||
|
yarn-debug.log* |
||||||
|
yarn-error.log* |
||||||
|
pnpm-debug.log* |
||||||
|
lerna-debug.log* |
||||||
|
|
||||||
|
node_modules |
||||||
|
dist |
||||||
|
dist-ssr |
||||||
|
*.local |
||||||
|
|
||||||
|
# Editor directories and files |
||||||
|
.vscode/* |
||||||
|
!.vscode/extensions.json |
||||||
|
.idea |
||||||
|
.DS_Store |
||||||
|
*.suo |
||||||
|
*.ntvs* |
||||||
|
*.njsproj |
||||||
|
*.sln |
||||||
|
*.sw? |
@ -0,0 +1,3 @@ |
|||||||
|
{ |
||||||
|
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
# Vue 3 + Vite |
||||||
|
|
||||||
|
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more. |
||||||
|
|
||||||
|
## Recommended IDE Setup |
||||||
|
|
||||||
|
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). |
@ -0,0 +1,13 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8" /> |
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||||
|
<title>Vite + Vue</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div id="app"></div> |
||||||
|
<script type="module" src="/src/main.js"></script> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,798 @@ |
|||||||
|
{ |
||||||
|
"name": "yvv", |
||||||
|
"version": "0.0.0", |
||||||
|
"lockfileVersion": 3, |
||||||
|
"requires": true, |
||||||
|
"packages": { |
||||||
|
"": { |
||||||
|
"name": "yvv", |
||||||
|
"version": "0.0.0", |
||||||
|
"dependencies": { |
||||||
|
"axios": "^1.4.0", |
||||||
|
"vue": "^3.2.47" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"@vitejs/plugin-vue": "^4.1.0", |
||||||
|
"vite": "^4.3.9" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@babel/parser": { |
||||||
|
"version": "7.22.5", |
||||||
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz", |
||||||
|
"integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==", |
||||||
|
"bin": { |
||||||
|
"parser": "bin/babel-parser.js" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">=6.0.0" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/android-arm": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", |
||||||
|
"integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", |
||||||
|
"cpu": [ |
||||||
|
"arm" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"android" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/android-arm64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", |
||||||
|
"cpu": [ |
||||||
|
"arm64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"android" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/android-x64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", |
||||||
|
"cpu": [ |
||||||
|
"x64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"android" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/darwin-arm64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", |
||||||
|
"cpu": [ |
||||||
|
"arm64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"darwin" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/darwin-x64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", |
||||||
|
"cpu": [ |
||||||
|
"x64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"darwin" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/freebsd-arm64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", |
||||||
|
"cpu": [ |
||||||
|
"arm64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"freebsd" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/freebsd-x64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", |
||||||
|
"cpu": [ |
||||||
|
"x64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"freebsd" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/linux-arm": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", |
||||||
|
"integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", |
||||||
|
"cpu": [ |
||||||
|
"arm" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"linux" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/linux-arm64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", |
||||||
|
"cpu": [ |
||||||
|
"arm64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"linux" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/linux-ia32": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", |
||||||
|
"integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", |
||||||
|
"cpu": [ |
||||||
|
"ia32" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"linux" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/linux-loong64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", |
||||||
|
"cpu": [ |
||||||
|
"loong64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"linux" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/linux-mips64el": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", |
||||||
|
"integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", |
||||||
|
"cpu": [ |
||||||
|
"mips64el" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"linux" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/linux-ppc64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", |
||||||
|
"cpu": [ |
||||||
|
"ppc64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"linux" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/linux-riscv64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", |
||||||
|
"cpu": [ |
||||||
|
"riscv64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"linux" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/linux-s390x": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", |
||||||
|
"integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", |
||||||
|
"cpu": [ |
||||||
|
"s390x" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"linux" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/linux-x64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", |
||||||
|
"cpu": [ |
||||||
|
"x64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"linux" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/netbsd-x64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", |
||||||
|
"cpu": [ |
||||||
|
"x64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"netbsd" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/openbsd-x64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", |
||||||
|
"cpu": [ |
||||||
|
"x64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"openbsd" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/sunos-x64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", |
||||||
|
"cpu": [ |
||||||
|
"x64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"sunos" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/win32-arm64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", |
||||||
|
"cpu": [ |
||||||
|
"arm64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"win32" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/win32-ia32": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", |
||||||
|
"integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", |
||||||
|
"cpu": [ |
||||||
|
"ia32" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"win32" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@esbuild/win32-x64": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", |
||||||
|
"integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", |
||||||
|
"cpu": [ |
||||||
|
"x64" |
||||||
|
], |
||||||
|
"dev": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"win32" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@jridgewell/sourcemap-codec": { |
||||||
|
"version": "1.4.15", |
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", |
||||||
|
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" |
||||||
|
}, |
||||||
|
"node_modules/@vitejs/plugin-vue": { |
||||||
|
"version": "4.2.3", |
||||||
|
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.2.3.tgz", |
||||||
|
"integrity": "sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==", |
||||||
|
"dev": true, |
||||||
|
"engines": { |
||||||
|
"node": "^14.18.0 || >=16.0.0" |
||||||
|
}, |
||||||
|
"peerDependencies": { |
||||||
|
"vite": "^4.0.0", |
||||||
|
"vue": "^3.2.25" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@vue/compiler-core": { |
||||||
|
"version": "3.3.4", |
||||||
|
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz", |
||||||
|
"integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==", |
||||||
|
"dependencies": { |
||||||
|
"@babel/parser": "^7.21.3", |
||||||
|
"@vue/shared": "3.3.4", |
||||||
|
"estree-walker": "^2.0.2", |
||||||
|
"source-map-js": "^1.0.2" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@vue/compiler-dom": { |
||||||
|
"version": "3.3.4", |
||||||
|
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz", |
||||||
|
"integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==", |
||||||
|
"dependencies": { |
||||||
|
"@vue/compiler-core": "3.3.4", |
||||||
|
"@vue/shared": "3.3.4" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@vue/compiler-sfc": { |
||||||
|
"version": "3.3.4", |
||||||
|
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz", |
||||||
|
"integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==", |
||||||
|
"dependencies": { |
||||||
|
"@babel/parser": "^7.20.15", |
||||||
|
"@vue/compiler-core": "3.3.4", |
||||||
|
"@vue/compiler-dom": "3.3.4", |
||||||
|
"@vue/compiler-ssr": "3.3.4", |
||||||
|
"@vue/reactivity-transform": "3.3.4", |
||||||
|
"@vue/shared": "3.3.4", |
||||||
|
"estree-walker": "^2.0.2", |
||||||
|
"magic-string": "^0.30.0", |
||||||
|
"postcss": "^8.1.10", |
||||||
|
"source-map-js": "^1.0.2" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@vue/compiler-ssr": { |
||||||
|
"version": "3.3.4", |
||||||
|
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz", |
||||||
|
"integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==", |
||||||
|
"dependencies": { |
||||||
|
"@vue/compiler-dom": "3.3.4", |
||||||
|
"@vue/shared": "3.3.4" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@vue/reactivity": { |
||||||
|
"version": "3.3.4", |
||||||
|
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz", |
||||||
|
"integrity": "sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==", |
||||||
|
"dependencies": { |
||||||
|
"@vue/shared": "3.3.4" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@vue/reactivity-transform": { |
||||||
|
"version": "3.3.4", |
||||||
|
"resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz", |
||||||
|
"integrity": "sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==", |
||||||
|
"dependencies": { |
||||||
|
"@babel/parser": "^7.20.15", |
||||||
|
"@vue/compiler-core": "3.3.4", |
||||||
|
"@vue/shared": "3.3.4", |
||||||
|
"estree-walker": "^2.0.2", |
||||||
|
"magic-string": "^0.30.0" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@vue/runtime-core": { |
||||||
|
"version": "3.3.4", |
||||||
|
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.4.tgz", |
||||||
|
"integrity": "sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==", |
||||||
|
"dependencies": { |
||||||
|
"@vue/reactivity": "3.3.4", |
||||||
|
"@vue/shared": "3.3.4" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@vue/runtime-dom": { |
||||||
|
"version": "3.3.4", |
||||||
|
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz", |
||||||
|
"integrity": "sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==", |
||||||
|
"dependencies": { |
||||||
|
"@vue/runtime-core": "3.3.4", |
||||||
|
"@vue/shared": "3.3.4", |
||||||
|
"csstype": "^3.1.1" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@vue/server-renderer": { |
||||||
|
"version": "3.3.4", |
||||||
|
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.4.tgz", |
||||||
|
"integrity": "sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==", |
||||||
|
"dependencies": { |
||||||
|
"@vue/compiler-ssr": "3.3.4", |
||||||
|
"@vue/shared": "3.3.4" |
||||||
|
}, |
||||||
|
"peerDependencies": { |
||||||
|
"vue": "3.3.4" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/@vue/shared": { |
||||||
|
"version": "3.3.4", |
||||||
|
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz", |
||||||
|
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==" |
||||||
|
}, |
||||||
|
"node_modules/asynckit": { |
||||||
|
"version": "0.4.0", |
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", |
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" |
||||||
|
}, |
||||||
|
"node_modules/axios": { |
||||||
|
"version": "1.4.0", |
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", |
||||||
|
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", |
||||||
|
"dependencies": { |
||||||
|
"follow-redirects": "^1.15.0", |
||||||
|
"form-data": "^4.0.0", |
||||||
|
"proxy-from-env": "^1.1.0" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/combined-stream": { |
||||||
|
"version": "1.0.8", |
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", |
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", |
||||||
|
"dependencies": { |
||||||
|
"delayed-stream": "~1.0.0" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/csstype": { |
||||||
|
"version": "3.1.2", |
||||||
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", |
||||||
|
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" |
||||||
|
}, |
||||||
|
"node_modules/delayed-stream": { |
||||||
|
"version": "1.0.0", |
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", |
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", |
||||||
|
"engines": { |
||||||
|
"node": ">=0.4.0" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/esbuild": { |
||||||
|
"version": "0.17.19", |
||||||
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", |
||||||
|
"integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", |
||||||
|
"dev": true, |
||||||
|
"hasInstallScript": true, |
||||||
|
"bin": { |
||||||
|
"esbuild": "bin/esbuild" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
}, |
||||||
|
"optionalDependencies": { |
||||||
|
"@esbuild/android-arm": "0.17.19", |
||||||
|
"@esbuild/android-arm64": "0.17.19", |
||||||
|
"@esbuild/android-x64": "0.17.19", |
||||||
|
"@esbuild/darwin-arm64": "0.17.19", |
||||||
|
"@esbuild/darwin-x64": "0.17.19", |
||||||
|
"@esbuild/freebsd-arm64": "0.17.19", |
||||||
|
"@esbuild/freebsd-x64": "0.17.19", |
||||||
|
"@esbuild/linux-arm": "0.17.19", |
||||||
|
"@esbuild/linux-arm64": "0.17.19", |
||||||
|
"@esbuild/linux-ia32": "0.17.19", |
||||||
|
"@esbuild/linux-loong64": "0.17.19", |
||||||
|
"@esbuild/linux-mips64el": "0.17.19", |
||||||
|
"@esbuild/linux-ppc64": "0.17.19", |
||||||
|
"@esbuild/linux-riscv64": "0.17.19", |
||||||
|
"@esbuild/linux-s390x": "0.17.19", |
||||||
|
"@esbuild/linux-x64": "0.17.19", |
||||||
|
"@esbuild/netbsd-x64": "0.17.19", |
||||||
|
"@esbuild/openbsd-x64": "0.17.19", |
||||||
|
"@esbuild/sunos-x64": "0.17.19", |
||||||
|
"@esbuild/win32-arm64": "0.17.19", |
||||||
|
"@esbuild/win32-ia32": "0.17.19", |
||||||
|
"@esbuild/win32-x64": "0.17.19" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/estree-walker": { |
||||||
|
"version": "2.0.2", |
||||||
|
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", |
||||||
|
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" |
||||||
|
}, |
||||||
|
"node_modules/follow-redirects": { |
||||||
|
"version": "1.15.2", |
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", |
||||||
|
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", |
||||||
|
"funding": [ |
||||||
|
{ |
||||||
|
"type": "individual", |
||||||
|
"url": "https://github.com/sponsors/RubenVerborgh" |
||||||
|
} |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">=4.0" |
||||||
|
}, |
||||||
|
"peerDependenciesMeta": { |
||||||
|
"debug": { |
||||||
|
"optional": true |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/form-data": { |
||||||
|
"version": "4.0.0", |
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", |
||||||
|
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", |
||||||
|
"dependencies": { |
||||||
|
"asynckit": "^0.4.0", |
||||||
|
"combined-stream": "^1.0.8", |
||||||
|
"mime-types": "^2.1.12" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/fsevents": { |
||||||
|
"version": "2.3.2", |
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", |
||||||
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", |
||||||
|
"dev": true, |
||||||
|
"hasInstallScript": true, |
||||||
|
"optional": true, |
||||||
|
"os": [ |
||||||
|
"darwin" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/magic-string": { |
||||||
|
"version": "0.30.0", |
||||||
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", |
||||||
|
"integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", |
||||||
|
"dependencies": { |
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.13" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">=12" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/mime-db": { |
||||||
|
"version": "1.52.0", |
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", |
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/mime-types": { |
||||||
|
"version": "2.1.35", |
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", |
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", |
||||||
|
"dependencies": { |
||||||
|
"mime-db": "1.52.0" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/nanoid": { |
||||||
|
"version": "3.3.6", |
||||||
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", |
||||||
|
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", |
||||||
|
"funding": [ |
||||||
|
{ |
||||||
|
"type": "github", |
||||||
|
"url": "https://github.com/sponsors/ai" |
||||||
|
} |
||||||
|
], |
||||||
|
"bin": { |
||||||
|
"nanoid": "bin/nanoid.cjs" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/picocolors": { |
||||||
|
"version": "1.0.0", |
||||||
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", |
||||||
|
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" |
||||||
|
}, |
||||||
|
"node_modules/postcss": { |
||||||
|
"version": "8.4.24", |
||||||
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", |
||||||
|
"integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", |
||||||
|
"funding": [ |
||||||
|
{ |
||||||
|
"type": "opencollective", |
||||||
|
"url": "https://opencollective.com/postcss/" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"type": "tidelift", |
||||||
|
"url": "https://tidelift.com/funding/github/npm/postcss" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"type": "github", |
||||||
|
"url": "https://github.com/sponsors/ai" |
||||||
|
} |
||||||
|
], |
||||||
|
"dependencies": { |
||||||
|
"nanoid": "^3.3.6", |
||||||
|
"picocolors": "^1.0.0", |
||||||
|
"source-map-js": "^1.0.2" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": "^10 || ^12 || >=14" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/proxy-from-env": { |
||||||
|
"version": "1.1.0", |
||||||
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", |
||||||
|
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" |
||||||
|
}, |
||||||
|
"node_modules/rollup": { |
||||||
|
"version": "3.24.1", |
||||||
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.24.1.tgz", |
||||||
|
"integrity": "sha512-REHe5dx30ERBRFS0iENPHy+t6wtSEYkjrhwNsLyh3qpRaZ1+aylvMUdMBUHWUD/RjjLmLzEvY8Z9XRlpcdIkHA==", |
||||||
|
"dev": true, |
||||||
|
"bin": { |
||||||
|
"rollup": "dist/bin/rollup" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">=14.18.0", |
||||||
|
"npm": ">=8.0.0" |
||||||
|
}, |
||||||
|
"optionalDependencies": { |
||||||
|
"fsevents": "~2.3.2" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/source-map-js": { |
||||||
|
"version": "1.0.2", |
||||||
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", |
||||||
|
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", |
||||||
|
"engines": { |
||||||
|
"node": ">=0.10.0" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/vite": { |
||||||
|
"version": "4.3.9", |
||||||
|
"resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", |
||||||
|
"integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==", |
||||||
|
"dev": true, |
||||||
|
"dependencies": { |
||||||
|
"esbuild": "^0.17.5", |
||||||
|
"postcss": "^8.4.23", |
||||||
|
"rollup": "^3.21.0" |
||||||
|
}, |
||||||
|
"bin": { |
||||||
|
"vite": "bin/vite.js" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": "^14.18.0 || >=16.0.0" |
||||||
|
}, |
||||||
|
"optionalDependencies": { |
||||||
|
"fsevents": "~2.3.2" |
||||||
|
}, |
||||||
|
"peerDependencies": { |
||||||
|
"@types/node": ">= 14", |
||||||
|
"less": "*", |
||||||
|
"sass": "*", |
||||||
|
"stylus": "*", |
||||||
|
"sugarss": "*", |
||||||
|
"terser": "^5.4.0" |
||||||
|
}, |
||||||
|
"peerDependenciesMeta": { |
||||||
|
"@types/node": { |
||||||
|
"optional": true |
||||||
|
}, |
||||||
|
"less": { |
||||||
|
"optional": true |
||||||
|
}, |
||||||
|
"sass": { |
||||||
|
"optional": true |
||||||
|
}, |
||||||
|
"stylus": { |
||||||
|
"optional": true |
||||||
|
}, |
||||||
|
"sugarss": { |
||||||
|
"optional": true |
||||||
|
}, |
||||||
|
"terser": { |
||||||
|
"optional": true |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/vue": { |
||||||
|
"version": "3.3.4", |
||||||
|
"resolved": "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz", |
||||||
|
"integrity": "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==", |
||||||
|
"dependencies": { |
||||||
|
"@vue/compiler-dom": "3.3.4", |
||||||
|
"@vue/compiler-sfc": "3.3.4", |
||||||
|
"@vue/runtime-dom": "3.3.4", |
||||||
|
"@vue/server-renderer": "3.3.4", |
||||||
|
"@vue/shared": "3.3.4" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
{ |
||||||
|
"name": "yvv", |
||||||
|
"private": true, |
||||||
|
"version": "0.0.0", |
||||||
|
"type": "module", |
||||||
|
"scripts": { |
||||||
|
"dev": "vite", |
||||||
|
"build": "vite build", |
||||||
|
"preview": "vite preview" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"axios": "^1.4.0", |
||||||
|
"vue": "^3.2.47" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"@vitejs/plugin-vue": "^4.1.0", |
||||||
|
"vite": "^4.3.9" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
<script setup> |
||||||
|
import TestService from "./services/test.service.js" |
||||||
|
import {ref} from "vue"; |
||||||
|
|
||||||
|
const records = ref([]) |
||||||
|
|
||||||
|
TestService.getRecords().then(response => { |
||||||
|
records.value = response.data |
||||||
|
}) |
||||||
|
</script> |
||||||
|
|
||||||
|
<template> |
||||||
|
<div> |
||||||
|
<a href="https://vitejs.dev" target="_blank"> |
||||||
|
<img src="/vite.svg" class="logo" alt="Vite logo" /> |
||||||
|
</a> |
||||||
|
<a href="https://vuejs.org/" target="_blank"> |
||||||
|
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" /> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
|
||||||
|
<hr> |
||||||
|
<div v-for="record in records">{{record}}</div> |
||||||
|
<hr> |
||||||
|
|
||||||
|
</template> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
.logo { |
||||||
|
height: 6em; |
||||||
|
padding: 1.5em; |
||||||
|
will-change: filter; |
||||||
|
transition: filter 300ms; |
||||||
|
} |
||||||
|
.logo:hover { |
||||||
|
filter: drop-shadow(0 0 2em #646cffaa); |
||||||
|
} |
||||||
|
.logo.vue:hover { |
||||||
|
filter: drop-shadow(0 0 2em #42b883aa); |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,7 @@ |
|||||||
|
import { createApp } from 'vue' |
||||||
|
import './style.css' |
||||||
|
import App from './App.vue' |
||||||
|
|
||||||
|
const app = createApp(App) |
||||||
|
|
||||||
|
app.mount('#app') |
@ -0,0 +1,9 @@ |
|||||||
|
import axios from "axios" |
||||||
|
|
||||||
|
const httpClient = axios.create({ |
||||||
|
baseURL: '/api', |
||||||
|
timeout: 15000, |
||||||
|
headers: {"Content-Type": "application/json"}, |
||||||
|
}) |
||||||
|
|
||||||
|
export default httpClient |
@ -0,0 +1,9 @@ |
|||||||
|
import httpClient from './http.client.js' |
||||||
|
|
||||||
|
class TestService { |
||||||
|
getRecords() { |
||||||
|
return httpClient.get('/test/index').then() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default new TestService() |
@ -0,0 +1,89 @@ |
|||||||
|
:root { |
||||||
|
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; |
||||||
|
line-height: 1.5; |
||||||
|
font-weight: 400; |
||||||
|
|
||||||
|
color-scheme: light dark; |
||||||
|
color: rgba(255, 255, 255, 0.87); |
||||||
|
background-color: #242424; |
||||||
|
|
||||||
|
font-synthesis: none; |
||||||
|
text-rendering: optimizeLegibility; |
||||||
|
-webkit-font-smoothing: antialiased; |
||||||
|
-moz-osx-font-smoothing: grayscale; |
||||||
|
-webkit-text-size-adjust: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
a { |
||||||
|
font-weight: 500; |
||||||
|
color: #646cff; |
||||||
|
text-decoration: inherit; |
||||||
|
} |
||||||
|
a:hover { |
||||||
|
color: #535bf2; |
||||||
|
} |
||||||
|
|
||||||
|
a { |
||||||
|
font-weight: 500; |
||||||
|
color: #646cff; |
||||||
|
text-decoration: inherit; |
||||||
|
} |
||||||
|
a:hover { |
||||||
|
color: #535bf2; |
||||||
|
} |
||||||
|
|
||||||
|
body { |
||||||
|
margin: 0; |
||||||
|
display: flex; |
||||||
|
place-items: center; |
||||||
|
min-width: 320px; |
||||||
|
min-height: 100vh; |
||||||
|
} |
||||||
|
|
||||||
|
h1 { |
||||||
|
font-size: 3.2em; |
||||||
|
line-height: 1.1; |
||||||
|
} |
||||||
|
|
||||||
|
button { |
||||||
|
border-radius: 8px; |
||||||
|
border: 1px solid transparent; |
||||||
|
padding: 0.6em 1.2em; |
||||||
|
font-size: 1em; |
||||||
|
font-weight: 500; |
||||||
|
font-family: inherit; |
||||||
|
background-color: #1a1a1a; |
||||||
|
cursor: pointer; |
||||||
|
transition: border-color 0.25s; |
||||||
|
} |
||||||
|
button:hover { |
||||||
|
border-color: #646cff; |
||||||
|
} |
||||||
|
button:focus, |
||||||
|
button:focus-visible { |
||||||
|
outline: 4px auto -webkit-focus-ring-color; |
||||||
|
} |
||||||
|
|
||||||
|
.card { |
||||||
|
padding: 2em; |
||||||
|
} |
||||||
|
|
||||||
|
#app { |
||||||
|
max-width: 1280px; |
||||||
|
margin: 0 auto; |
||||||
|
padding: 2rem; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) { |
||||||
|
:root { |
||||||
|
color: #213547; |
||||||
|
background-color: #ffffff; |
||||||
|
} |
||||||
|
a:hover { |
||||||
|
color: #747bff; |
||||||
|
} |
||||||
|
button { |
||||||
|
background-color: #f9f9f9; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
import { defineConfig } from 'vite' |
||||||
|
import vue from '@vitejs/plugin-vue' |
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({ |
||||||
|
server: { |
||||||
|
proxy: { |
||||||
|
"/api": { |
||||||
|
target: "http://localhost:8001", |
||||||
|
changeOrigin: true, |
||||||
|
secure: false, |
||||||
|
ws: true, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
build: { |
||||||
|
outDir: '../web', |
||||||
|
}, |
||||||
|
plugins: [vue()], |
||||||
|
}) |
@ -0,0 +1,4 @@ |
|||||||
|
RewriteEngine on |
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d |
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f |
||||||
|
RewriteRule . index.php [L] |
@ -0,0 +1 @@ |
|||||||
|
:root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}a{font-weight:500;color:#646cff;text-decoration:inherit}a:hover{color:#535bf2}body{margin:0;display:flex;place-items:center;min-width:320px;min-height:100vh}h1{font-size:3.2em;line-height:1.1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}.card{padding:2em}#app{max-width:1280px;margin:0 auto;padding:2rem;text-align:center}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}}.logo[data-v-1d75a1d6]{height:6em;padding:1.5em;will-change:filter;transition:filter .3s}.logo[data-v-1d75a1d6]:hover{filter:drop-shadow(0 0 2em #646cffaa)}.logo.vue[data-v-1d75a1d6]:hover{filter:drop-shadow(0 0 2em #42b883aa)} |
@ -0,0 +1 @@ |
|||||||
|
:root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}a{font-weight:500;color:#646cff;text-decoration:inherit}a:hover{color:#535bf2}body{margin:0;display:flex;place-items:center;min-width:320px;min-height:100vh}h1{font-size:3.2em;line-height:1.1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}.card{padding:2em}#app{max-width:1280px;margin:0 auto;padding:2rem;text-align:center}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}}.logo[data-v-46b2d863]{height:6em;padding:1.5em;will-change:filter;transition:filter .3s}.logo[data-v-46b2d863]:hover{filter:drop-shadow(0 0 2em #646cffaa)}.logo.vue[data-v-46b2d863]:hover{filter:drop-shadow(0 0 2em #42b883aa)} |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 318 B |
@ -0,0 +1,16 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
// NOTE: Make sure this file is not accessible when deployed to production |
||||||
|
if (!in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1'])) { |
||||||
|
die('You are not allowed to access this file.'); |
||||||
|
} |
||||||
|
|
||||||
|
defined('YII_DEBUG') or define('YII_DEBUG', true); |
||||||
|
defined('YII_ENV') or define('YII_ENV', 'test'); |
||||||
|
|
||||||
|
require __DIR__ . '/../vendor/autoload.php'; |
||||||
|
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php'; |
||||||
|
|
||||||
|
$config = require __DIR__ . '/../config/test.php'; |
||||||
|
|
||||||
|
(new yii\web\Application($config))->run(); |
@ -0,0 +1,15 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8" /> |
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||||
|
<title>Vite + Vue</title> |
||||||
|
<script type="module" crossorigin src="/assets/index-e54ab67f.js"></script> |
||||||
|
<link rel="stylesheet" href="/assets/index-c05be89e.css"> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div id="app"></div> |
||||||
|
|
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,12 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
// comment out the following two lines when deployed to production |
||||||
|
defined('YII_DEBUG') or define('YII_DEBUG', true); |
||||||
|
defined('YII_ENV') or define('YII_ENV', 'dev'); |
||||||
|
|
||||||
|
require __DIR__ . '/../vendor/autoload.php'; |
||||||
|
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php'; |
||||||
|
|
||||||
|
$config = require __DIR__ . '/../config/web.php'; |
||||||
|
|
||||||
|
(new yii\web\Application($config))->run(); |
@ -0,0 +1,73 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace app\widgets; |
||||||
|
|
||||||
|
use Yii; |
||||||
|
|
||||||
|
/** |
||||||
|
* Alert widget renders a message from session flash. All flash messages are displayed |
||||||
|
* in the sequence they were assigned using setFlash. You can set message as following: |
||||||
|
* |
||||||
|
* ```php |
||||||
|
* Yii::$app->session->setFlash('error', 'This is the message'); |
||||||
|
* Yii::$app->session->setFlash('success', 'This is the message'); |
||||||
|
* Yii::$app->session->setFlash('info', 'This is the message'); |
||||||
|
* ``` |
||||||
|
* |
||||||
|
* Multiple messages could be set as follows: |
||||||
|
* |
||||||
|
* ```php |
||||||
|
* Yii::$app->session->setFlash('error', ['Error 1', 'Error 2']); |
||||||
|
* ``` |
||||||
|
* |
||||||
|
* @author Kartik Visweswaran <kartikv2@gmail.com> |
||||||
|
* @author Alexander Makarov <sam@rmcreative.ru> |
||||||
|
*/ |
||||||
|
class Alert extends \yii\bootstrap5\Widget |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @var array the alert types configuration for the flash messages. |
||||||
|
* This array is setup as $key => $value, where: |
||||||
|
* - key: the name of the session flash variable |
||||||
|
* - value: the bootstrap alert type (i.e. danger, success, info, warning) |
||||||
|
*/ |
||||||
|
public $alertTypes = [ |
||||||
|
'error' => 'alert-danger', |
||||||
|
'danger' => 'alert-danger', |
||||||
|
'success' => 'alert-success', |
||||||
|
'info' => 'alert-info', |
||||||
|
'warning' => 'alert-warning' |
||||||
|
]; |
||||||
|
/** |
||||||
|
* @var array the options for rendering the close button tag. |
||||||
|
* Array will be passed to [[\yii\bootstrap\Alert::closeButton]]. |
||||||
|
*/ |
||||||
|
public $closeButton = []; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritdoc} |
||||||
|
*/ |
||||||
|
public function run() |
||||||
|
{ |
||||||
|
$session = Yii::$app->session; |
||||||
|
$appendClass = isset($this->options['class']) ? ' ' . $this->options['class'] : ''; |
||||||
|
|
||||||
|
foreach (array_keys($this->alertTypes) as $type) { |
||||||
|
$flash = $session->getFlash($type); |
||||||
|
|
||||||
|
foreach ((array) $flash as $i => $message) { |
||||||
|
echo \yii\bootstrap5\Alert::widget([ |
||||||
|
'body' => $message, |
||||||
|
'closeButton' => $this->closeButton, |
||||||
|
'options' => array_merge($this->options, [ |
||||||
|
'id' => $this->getId() . '-' . $type . '-' . $i, |
||||||
|
'class' => $this->alertTypes[$type] . $appendClass, |
||||||
|
]), |
||||||
|
]); |
||||||
|
} |
||||||
|
|
||||||
|
$session->removeFlash($type); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
#!/usr/bin/env php |
||||||
|
<?php |
||||||
|
/** |
||||||
|
* Yii console bootstrap file. |
||||||
|
* |
||||||
|
* @link https://www.yiiframework.com/ |
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
* @license https://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
defined('YII_DEBUG') or define('YII_DEBUG', true); |
||||||
|
defined('YII_ENV') or define('YII_ENV', 'dev'); |
||||||
|
|
||||||
|
require __DIR__ . '/vendor/autoload.php'; |
||||||
|
require __DIR__ . '/vendor/yiisoft/yii2/Yii.php'; |
||||||
|
|
||||||
|
$config = require __DIR__ . '/config/console.php'; |
||||||
|
|
||||||
|
$application = new yii\console\Application($config); |
||||||
|
$exitCode = $application->run(); |
||||||
|
exit($exitCode); |
@ -0,0 +1,20 @@ |
|||||||
|
@echo off |
||||||
|
|
||||||
|
rem ------------------------------------------------------------- |
||||||
|
rem Yii command line bootstrap script for Windows. |
||||||
|
rem |
||||||
|
rem @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
rem @link https://www.yiiframework.com/ |
||||||
|
rem @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
rem @license https://www.yiiframework.com/license/ |
||||||
|
rem ------------------------------------------------------------- |
||||||
|
|
||||||
|
@setlocal |
||||||
|
|
||||||
|
set YII_PATH=%~dp0 |
||||||
|
|
||||||
|
if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe |
||||||
|
|
||||||
|
"%PHP_COMMAND%" "%YII_PATH%yii" %* |
||||||
|
|
||||||
|
@endlocal |
Loading…
Reference in new issue