init repo
This commit is contained in:
commit
7694c40a68
|
@ -0,0 +1,33 @@
|
|||
# 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
|
||||
|
||||
# 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
|
|
@ -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,92 @@
|
|||
require 'yaml'
|
||||
require 'fileutils'
|
||||
|
||||
required_plugins_installed = nil
|
||||
required_plugins = %w( vagrant-hostmanager vagrant-vbguest )
|
||||
required_plugins.each do |plugin|
|
||||
unless Vagrant.has_plugin? plugin
|
||||
system "vagrant plugin install #{plugin}"
|
||||
required_plugins_installed = true
|
||||
end
|
||||
end
|
||||
|
||||
# IF plugin[s] was just installed - restart required
|
||||
if required_plugins_installed
|
||||
# Get CLI command[s] and call again
|
||||
system 'vagrant' + ARGV.to_s.gsub(/\[\"|\", \"|\"\]/, ' ')
|
||||
exit
|
||||
end
|
||||
|
||||
domains = {
|
||||
app: 'yii2basic.test'
|
||||
}
|
||||
|
||||
vagrantfile_dir_path = File.dirname(__FILE__)
|
||||
|
||||
config = {
|
||||
local: vagrantfile_dir_path + '/vagrant/config/vagrant-local.yml',
|
||||
example: vagrantfile_dir_path + '/vagrant/config/vagrant-local.example.yml'
|
||||
}
|
||||
|
||||
# copy config from example if local config not exists
|
||||
FileUtils.cp config[:example], config[:local] unless File.exist?(config[:local])
|
||||
# read config
|
||||
options = YAML.load_file config[:local]
|
||||
|
||||
# check github token
|
||||
if options['github_token'].nil? || options['github_token'].to_s.length != 40
|
||||
puts "You must place REAL GitHub token into configuration:\n/yii2-app-basic/vagrant/config/vagrant-local.yml"
|
||||
exit
|
||||
end
|
||||
|
||||
# vagrant configurate
|
||||
Vagrant.configure(2) do |config|
|
||||
# select the box
|
||||
config.vm.box = 'bento/ubuntu-18.04'
|
||||
|
||||
# should we ask about box updates?
|
||||
config.vm.box_check_update = options['box_check_update']
|
||||
|
||||
config.vm.provider 'virtualbox' do |vb|
|
||||
# machine cpus count
|
||||
vb.cpus = options['cpus']
|
||||
# machine memory size
|
||||
vb.memory = options['memory']
|
||||
# machine name (for VirtualBox UI)
|
||||
vb.name = options['machine_name']
|
||||
end
|
||||
|
||||
# machine name (for vagrant console)
|
||||
config.vm.define options['machine_name']
|
||||
|
||||
# machine name (for guest machine console)
|
||||
config.vm.hostname = options['machine_name']
|
||||
|
||||
# network settings
|
||||
config.vm.network 'private_network', ip: options['ip']
|
||||
|
||||
# sync: folder 'yii2-app-advanced' (host machine) -> folder '/app' (guest machine)
|
||||
config.vm.synced_folder './', '/app', owner: 'vagrant', group: 'vagrant'
|
||||
|
||||
# disable folder '/vagrant' (guest machine)
|
||||
config.vm.synced_folder '.', '/vagrant', disabled: true
|
||||
|
||||
# hosts settings (host machine)
|
||||
config.vm.provision :hostmanager
|
||||
config.hostmanager.enabled = true
|
||||
config.hostmanager.manage_host = true
|
||||
config.hostmanager.ignore_private_ip = false
|
||||
config.hostmanager.include_offline = true
|
||||
config.hostmanager.aliases = domains.values
|
||||
|
||||
# quick fix for failed guest additions installations
|
||||
# config.vbguest.auto_update = false
|
||||
|
||||
# provisioners
|
||||
config.vm.provision 'shell', path: './vagrant/provision/once-as-root.sh', args: [options['timezone'], options['ip']]
|
||||
config.vm.provision 'shell', path: './vagrant/provision/once-as-vagrant.sh', args: [options['github_token']], privileged: false
|
||||
config.vm.provision 'shell', path: './vagrant/provision/always-as-root.sh', run: 'always'
|
||||
|
||||
# post-install message (vagrant console)
|
||||
config.vm.post_up_message = "App URL: http://#{domains[:app]}"
|
||||
end
|
|
@ -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,74 @@
|
|||
{
|
||||
"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": "ircs://irc.libera.chat:6697/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",
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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,74 @@
|
|||
<?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' => '0qNaulpEfs2NYedhkKChdCgJqb0hj6jP',
|
||||
],
|
||||
'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,104 @@
|
|||
<?php
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use app\models\Comment;
|
||||
use app\models\CommentEditForm;
|
||||
use app\models\CommentNewForm;
|
||||
use Yii;
|
||||
use yii\web\Controller;
|
||||
use yii\filters\AccessControl;
|
||||
use yii\filters\VerbFilter;
|
||||
use yii\web\Request;
|
||||
|
||||
class CommentsController extends Controller
|
||||
{
|
||||
public function behaviors()
|
||||
{
|
||||
return [
|
||||
'access' => [
|
||||
'class' => AccessControl::class,
|
||||
],
|
||||
'verbs' => [
|
||||
'class' => VerbFilter::class,
|
||||
'actions' => [
|
||||
'post' => ['POST'],
|
||||
'edit' => ['POST'],
|
||||
'delete' => ['DELETE']
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function actionPost(Request $request)
|
||||
{
|
||||
if (!$request->isPost) {
|
||||
return false;
|
||||
}
|
||||
if (Yii::$app->user->id === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = $request->post();
|
||||
$form = new CommentNewForm();
|
||||
$form->load([ ...$data, 'user_id' => Yii::$app->user->id ]);
|
||||
if ($form->validate()) {
|
||||
if ($form->create()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function actionEdit(Request $request)
|
||||
{
|
||||
if (!$request->isPost) {
|
||||
return false;
|
||||
}
|
||||
if (Yii::$app->user->id === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = $request->post();
|
||||
$form = new CommentEditForm();
|
||||
$form->load([ ...$data, 'user_id' => Yii::$app->user->id ]);
|
||||
if ($form->validate()) {
|
||||
if ($form->edit()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function actionDelete(Request $request)
|
||||
{
|
||||
/*
|
||||
Можно конечно поспорить что в этом месте лучше
|
||||
в модель это запихнуть, но мне кажется что это
|
||||
какой-то абсурд для такого маленького кол-ва
|
||||
данных
|
||||
*/
|
||||
|
||||
if (!$request->isDelete) {
|
||||
return false;
|
||||
}
|
||||
if (Yii::$app->user->id === null) {
|
||||
return false;
|
||||
}
|
||||
if ($request->getQueryParam('id') === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$comment = Comment::findOne([ 'id' => $request->getQueryParam('id') ]);
|
||||
if ($comment === null) {
|
||||
return false;
|
||||
}
|
||||
if ($comment->user_id !== Yii::$app->user->id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $comment->delete();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use app\models\UserSearch;
|
||||
use Yii;
|
||||
use yii\filters\AccessControl;
|
||||
use yii\filters\VerbFilter;
|
||||
use yii\web\Controller;
|
||||
use yii\web\Request;
|
||||
|
||||
class UserSearchController extends Controller
|
||||
{
|
||||
public function behaviors()
|
||||
{
|
||||
return [
|
||||
'access' => [
|
||||
'class' => AccessControl::class,
|
||||
'only' => ['search'],
|
||||
'rules' => [
|
||||
[
|
||||
'actions' => ['search'],
|
||||
'allow' => true,
|
||||
'roles' => ['userListViewer']
|
||||
]
|
||||
]
|
||||
],
|
||||
'verbs' => [
|
||||
'class' => VerbFilter::class,
|
||||
'actions' => [
|
||||
'search' => ['POST'],
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function actionSearch(Request $request)
|
||||
{
|
||||
if (!$request->isPost) {
|
||||
return false;
|
||||
}
|
||||
if (Yii::$app->user->id === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$search = new UserSearch();
|
||||
$provider = $search->search($request->post());
|
||||
return $provider->query->all();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
services:
|
||||
php:
|
||||
image: yiisoftware/yii2-php:8.3-fpm-24.3.0-nginx
|
||||
volumes:
|
||||
- ~/.composer-docker/cache:/root/.composer/cache:delegated
|
||||
- ./:/app:delegated
|
||||
ports:
|
||||
- '8000:80'
|
||||
environment:
|
||||
PHP_ENABLE_XDEBUG: 1
|
||||
XDEBUG_CONFIG: 'client_host=host.docker.internal client_port=9003'
|
|
@ -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,39 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
class Blogs extends \yii\db\ActiveRecord
|
||||
{
|
||||
public $id;
|
||||
public $user_id;
|
||||
public $company_id;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['id'], 'required'],
|
||||
[['id'], 'integer'],
|
||||
];
|
||||
}
|
||||
|
||||
public function getUser()
|
||||
{
|
||||
return $this->hasOne(User::class, [ 'id' => 'user_id' ]);
|
||||
}
|
||||
|
||||
public function getCompany()
|
||||
{
|
||||
return $this->hasOne(Companies::class, [ 'id' => 'company_id' ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function tableName()
|
||||
{
|
||||
return "blogs";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
class Comment extends \yii\db\ActiveRecord
|
||||
{
|
||||
public $id;
|
||||
public $user_id;
|
||||
public $material_id;
|
||||
|
||||
public $content;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['id', 'user_id', 'material_id', 'content'], 'required'],
|
||||
[['id', 'user_id', 'material_id'], 'integer'],
|
||||
[['content'], 'string'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->hasOne(User::class, [ 'id' => 'user_id' ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getMaterial()
|
||||
{
|
||||
return $this->hasOne(Material::class, [ 'id' => 'material_id' ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function tableName()
|
||||
{
|
||||
return "comments";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
class CommentEditForm extends \yii\base\Model
|
||||
{
|
||||
public $id;
|
||||
public $user_id;
|
||||
public $content;
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['content', 'id', 'user_id'], 'required'],
|
||||
[['content'], 'string'],
|
||||
[['id'], 'integer']
|
||||
];
|
||||
}
|
||||
|
||||
public function edit()
|
||||
{
|
||||
$comment = Comment::findOne([ 'id' => $this->id ]);
|
||||
if ($comment === null) {
|
||||
return false;
|
||||
}
|
||||
if ($comment->user_id !== $this->user_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$comment->content = $this->content;
|
||||
return $comment->save();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
class CommentNewForm extends \yii\base\Model
|
||||
{
|
||||
public $message;
|
||||
public $user_id;
|
||||
public $material_id;
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function rules() {
|
||||
return [
|
||||
[['message'], 'string'],
|
||||
[['user_id', 'material_id'], 'integer'],
|
||||
[['message', 'user_id', 'material_id'], 'required'],
|
||||
];
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$comment = new Comment();
|
||||
$comment->user_id = $this->user_id;
|
||||
$comment->material_id = $this->material_id;
|
||||
return $comment->save();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
class Companies extends \yii\db\ActiveRecord
|
||||
{
|
||||
public $id;
|
||||
public $title;
|
||||
public $website;
|
||||
public $address;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['id', 'title', 'website', 'address'], 'required'],
|
||||
[['title', 'website', 'address'], 'string'],
|
||||
[['id'], 'integer'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function tableName()
|
||||
{
|
||||
return "companies";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
class Material extends \yii\db\ActiveRecord
|
||||
{
|
||||
public $id;
|
||||
public $title;
|
||||
public $content;
|
||||
public $blog_id;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['id', 'title', 'content', 'blog_id'], 'required'],
|
||||
[['title', 'content', 'blog_id'], 'string'],
|
||||
[['id'], 'integer'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function tableName()
|
||||
{
|
||||
return "materials";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
class Subscriptions extends \yii\db\ActiveRecord
|
||||
{
|
||||
public $user_id;
|
||||
public $company_id;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['user_id'], 'required'],
|
||||
[['id'], 'integer'],
|
||||
];
|
||||
}
|
||||
|
||||
public function getUser()
|
||||
{
|
||||
return $this->hasOne(User::class, [ 'id' => 'user_id' ]);
|
||||
}
|
||||
|
||||
public function getCompany()
|
||||
{
|
||||
return $this->hasOne(Companies::class, [ 'id' => 'company_id' ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function tableName()
|
||||
{
|
||||
return "subscriptions";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use Yii;
|
||||
|
||||
class User extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface
|
||||
{
|
||||
public $id;
|
||||
public $name;
|
||||
public $login;
|
||||
/// Path to a file stored in an imaginatory S3 bucket
|
||||
public $avatar;
|
||||
public $phone;
|
||||
public $website;
|
||||
public $passHash;
|
||||
public $accessToken;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['id', 'name', 'login', 'phone', 'passHash'], 'required'],
|
||||
[['name', 'login', 'avatar', 'phone', 'website', 'passHash'], 'string'],
|
||||
[['id'], 'integer'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function attributeLabels()
|
||||
{
|
||||
return [
|
||||
'id' => 'ID',
|
||||
'name' => 'Имя',
|
||||
'login' => 'Логин',
|
||||
'phone' => 'Телефон',
|
||||
'website' => 'Личный сайт',
|
||||
'accessToken' => '',
|
||||
'passHash' => 'Пароль',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function fields()
|
||||
{
|
||||
return [
|
||||
'id', 'name', 'login', 'avatar', 'phone', 'website', 'accessToken'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function tableName()
|
||||
{
|
||||
return "user";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function findIdentity($id)
|
||||
{
|
||||
return self::findOne([ 'id' => $id ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function findIdentityByAccessToken($token, $type = null)
|
||||
{
|
||||
return self::findOne([ 'accessToken' => $token ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds user by username
|
||||
*
|
||||
* @param string $username
|
||||
* @return static|null
|
||||
*/
|
||||
public static function findByUsername($username)
|
||||
{
|
||||
return self::findOne([ 'login' => $username ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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 Yii::$app->security->validatePassword($password, $this->passHash);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use Yii;
|
||||
use yii\data\ActiveDataProvider;
|
||||
|
||||
class UserSearch extends User
|
||||
{
|
||||
|
||||
public $name;
|
||||
public $sort_comment_count;
|
||||
public $sort_subscribers_count;
|
||||
public $sort_post_count;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['name'], 'string'],
|
||||
[['sort_comment_count', 'sort_subscribers_count', 'sort_post_count'], 'in', 'range' => [ 'desc', 'asc' ]],
|
||||
[['sort_comment_count', 'sort_subscribers_count', 'sort_post_count'], 'onlyOneSort'],
|
||||
|
||||
[['page'], 'integer'],
|
||||
[['page'], 'required'],
|
||||
];
|
||||
}
|
||||
|
||||
public function onlyOneSort($attribute, $params)
|
||||
{
|
||||
$attributes = ['sort_comment_count', 'sort_subscribers_count', 'sort_post_count'];
|
||||
$oneSet = false;
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
if (isset($this->$attribute)) {
|
||||
if ($oneSet) {
|
||||
$this->addError($attribute, Yii::t('validation', 'only one sort is allowed'));
|
||||
return false;
|
||||
}
|
||||
$oneSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function search($params)
|
||||
{
|
||||
$query = User::find();
|
||||
$query->limit(100);
|
||||
$query->offset(((int) $this->page) * 100);
|
||||
|
||||
/**
|
||||
* Впринципе можно наверное и просто query вернуть но это
|
||||
* на всякий чтобы можно было через какую нибудь вьюшку отобразить
|
||||
*/
|
||||
$provider = new ActiveDataProvider([
|
||||
'query' => $query
|
||||
]);
|
||||
|
||||
/**
|
||||
* Запрос скорее всего кривой, но это по большей части псевдокод
|
||||
* так что надеюсь простите если оно выглядит нелепо
|
||||
*/
|
||||
|
||||
if (!($this->load($params)) && $this->validate()) {
|
||||
return $provider;
|
||||
}
|
||||
|
||||
if ($this->name) {
|
||||
$query->andFilterWhere(['like', 'name', $this->name]);
|
||||
}
|
||||
|
||||
if ($this->sort_comment_count === true) {
|
||||
$query->join('outer', 'comments', [ 'user.comment_id' => 'comments.id' ]);
|
||||
$query->orderBy([ 'COUNT(comment.id)' => $this->sort_comment_count ]);
|
||||
}
|
||||
|
||||
if ($this->sort_post_count === true) {
|
||||
$query->join('outer', 'posts', [ 'posts.user_id' => 'user.id' ]);
|
||||
$query->orderBy([ 'COUNT(posts.id)' => $this->sort_post_count ]);
|
||||
}
|
||||
|
||||
if ($this->sort_subscribers_count === true) {
|
||||
/**
|
||||
* Тут бы я вместо под запроса поставил как два джоина прежде чем пускать в прожакшн
|
||||
* но у меня сейчас недостаточно мозговых сил чтобы так сильно продумывать
|
||||
*/
|
||||
$query->join('outer', 'blogs', [ 'blogs.user_id' => 'user.id' ]);
|
||||
$query->orderBy([ 'IF(blogs.id, SELECT COUNT(*) FROM subscriptions s WHERE s.blog_id = blogs.id)' => $this->sort_subscribers_count ]);
|
||||
}
|
||||
|
||||
if (
|
||||
$this->sort_comment_count === true
|
||||
|| $this->sort_post_count === true
|
||||
|| $this->sort_subscribers_count === true
|
||||
) {
|
||||
$query->groupBy('user.id');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,2 @@
|
|||
*
|
||||
!.gitignore
|
|
@ -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 @@
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
|
@ -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 @@
|
|||
<?php
|
|
@ -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 @@
|
|||
<?php
|
|
@ -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,2 @@
|
|||
# local configuration
|
||||
vagrant-local.yml
|
|
@ -0,0 +1,22 @@
|
|||
# Your personal GitHub token
|
||||
github_token: <your-personal-github-token>
|
||||
# Read more: https://github.com/blog/1509-personal-api-tokens
|
||||
# You can generate it here: https://github.com/settings/tokens
|
||||
|
||||
# Guest OS timezone
|
||||
timezone: Europe/London
|
||||
|
||||
# Are we need check box updates for every 'vagrant up'?
|
||||
box_check_update: false
|
||||
|
||||
# Virtual machine name
|
||||
machine_name: yii2basic
|
||||
|
||||
# Virtual machine IP
|
||||
ip: 192.168.83.137
|
||||
|
||||
# Virtual machine CPU cores number
|
||||
cpus: 1
|
||||
|
||||
# Virtual machine RAM
|
||||
memory: 1024
|
|
@ -0,0 +1,38 @@
|
|||
server {
|
||||
charset utf-8;
|
||||
client_max_body_size 128M;
|
||||
sendfile off;
|
||||
|
||||
listen 80; ## listen for ipv4
|
||||
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
|
||||
|
||||
server_name yii2basic.test;
|
||||
root /app/web/;
|
||||
index index.php;
|
||||
|
||||
access_log /app/vagrant/nginx/log/yii2basic.access.log;
|
||||
error_log /app/vagrant/nginx/log/yii2basic.error.log;
|
||||
|
||||
location / {
|
||||
# Redirect everything that isn't a real file to index.php
|
||||
try_files $uri $uri/ /index.php$is_args$args;
|
||||
}
|
||||
|
||||
# uncomment to avoid processing of calls to non-existing static files by Yii
|
||||
#location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
|
||||
# try_files $uri =404;
|
||||
#}
|
||||
#error_page 404 /404.html;
|
||||
|
||||
location ~ \.php$ {
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
#fastcgi_pass 127.0.0.1:9000;
|
||||
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ~ /\.(ht|svn|git) {
|
||||
deny all;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#nginx logs
|
||||
yii2basic.access.log
|
||||
yii2basic.error.log
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
#== Bash helpers ==
|
||||
|
||||
function info {
|
||||
echo " "
|
||||
echo "--> $1"
|
||||
echo " "
|
||||
}
|
||||
|
||||
#== Provision script ==
|
||||
|
||||
info "Provision-script user: `whoami`"
|
||||
|
||||
info "Restart web-stack"
|
||||
service php7.2-fpm restart
|
||||
service nginx restart
|
||||
service mysql restart
|
|
@ -0,0 +1,79 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
#== Import script args ==
|
||||
|
||||
timezone=$(echo "$1")
|
||||
readonly IP=$2
|
||||
|
||||
#== Bash helpers ==
|
||||
|
||||
function info {
|
||||
echo " "
|
||||
echo "--> $1"
|
||||
echo " "
|
||||
}
|
||||
|
||||
#== Provision script ==
|
||||
|
||||
info "Provision-script user: `whoami`"
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
info "Configure timezone"
|
||||
timedatectl set-timezone ${timezone} --no-ask-password
|
||||
|
||||
info "Add the VM IP to the list of allowed IPs"
|
||||
awk -v ip=$IP -f /app/vagrant/provision/provision.awk /app/config/web.php
|
||||
|
||||
info "Prepare root password for MySQL"
|
||||
debconf-set-selections <<< 'mariadb-server mysql-server/root_password password'
|
||||
debconf-set-selections <<< 'mariadb-server mysql-server/root_password_again password'
|
||||
echo "Done!"
|
||||
|
||||
info "Update OS software"
|
||||
apt-get update
|
||||
apt-get upgrade -y
|
||||
|
||||
info "Install additional software"
|
||||
apt-get install -y php7.2-curl php7.2-cli php7.2-intl php7.2-mysqlnd php7.2-gd php7.2-fpm php7.2-mbstring php7.2-xml unzip nginx mariadb-server-10.1 php.xdebug
|
||||
|
||||
info "Configure MySQL"
|
||||
sed -i 's/.*bind-address.*/bind-address = 0.0.0.0/' /etc/mysql/mariadb.conf.d/50-server.cnf
|
||||
mysql <<< "CREATE USER 'root'@'%' IDENTIFIED BY ''"
|
||||
mysql <<< "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'"
|
||||
mysql <<< "DROP USER 'root'@'localhost'"
|
||||
mysql <<< 'FLUSH PRIVILEGES'
|
||||
echo "Done!"
|
||||
|
||||
info "Configure PHP-FPM"
|
||||
sed -i 's/user = www-data/user = vagrant/g' /etc/php/7.2/fpm/pool.d/www.conf
|
||||
sed -i 's/group = www-data/group = vagrant/g' /etc/php/7.2/fpm/pool.d/www.conf
|
||||
sed -i 's/owner = www-data/owner = vagrant/g' /etc/php/7.2/fpm/pool.d/www.conf
|
||||
cat << EOF > /etc/php/7.2/mods-available/xdebug.ini
|
||||
zend_extension=xdebug.so
|
||||
xdebug.remote_enable=1
|
||||
xdebug.remote_connect_back=1
|
||||
xdebug.remote_port=9000
|
||||
xdebug.remote_autostart=1
|
||||
EOF
|
||||
echo "Done!"
|
||||
|
||||
info "Configure NGINX"
|
||||
sed -i 's/user www-data/user vagrant/g' /etc/nginx/nginx.conf
|
||||
echo "Done!"
|
||||
|
||||
info "Enabling site configuration"
|
||||
ln -s /app/vagrant/nginx/app.conf /etc/nginx/sites-enabled/app.conf
|
||||
echo "Done!"
|
||||
|
||||
info "Removing default site configuration"
|
||||
rm /etc/nginx/sites-enabled/default
|
||||
echo "Done!"
|
||||
|
||||
info "Initialize databases for MySQL"
|
||||
mysql <<< 'CREATE DATABASE yii2basic'
|
||||
mysql <<< 'CREATE DATABASE yii2basic_test'
|
||||
echo "Done!"
|
||||
|
||||
info "Install composer"
|
||||
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
#== Import script args ==
|
||||
|
||||
github_token=$(echo "$1")
|
||||
|
||||
#== Bash helpers ==
|
||||
|
||||
function info {
|
||||
echo " "
|
||||
echo "--> $1"
|
||||
echo " "
|
||||
}
|
||||
|
||||
#== Provision script ==
|
||||
|
||||
info "Provision-script user: `whoami`"
|
||||
|
||||
info "Configure composer"
|
||||
composer config --global github-oauth.github.com ${github_token}
|
||||
echo "Done!"
|
||||
|
||||
info "Install project dependencies"
|
||||
cd /app
|
||||
composer --no-progress --prefer-dist install
|
||||
|
||||
info "Create bash-alias 'app' for vagrant user"
|
||||
echo 'alias app="cd /app"' | tee /home/vagrant/.bash_aliases
|
||||
|
||||
info "Enabling colorized prompt for guest console"
|
||||
sed -i "s/#force_color_prompt=yes/force_color_prompt=yes/" /home/vagrant/.bashrc
|
|
@ -0,0 +1,50 @@
|
|||
###
|
||||
# Modifying Yii2's files for Vagrant VM
|
||||
#
|
||||
# @author HA3IK <golubha3ik@gmail.com>
|
||||
# @version 1.0.0
|
||||
|
||||
BEGIN {
|
||||
print "AWK BEGINs its work:"
|
||||
IGNORECASE = 1
|
||||
|
||||
# Correct IP - wildcard last octet
|
||||
match(ip, /(([0-9]+\.)+)/, arr)
|
||||
ip = arr[1] "*"
|
||||
}
|
||||
# BODY
|
||||
{
|
||||
# Check if it's the same file
|
||||
if (FILENAME != isFile["same"]){
|
||||
msg = "- Work with: " FILENAME
|
||||
# Close a previous file
|
||||
close(isFile["same"])
|
||||
# Delete previous data
|
||||
delete isFile
|
||||
# Save current file
|
||||
isFile["same"] = FILENAME
|
||||
# Define array index for the file
|
||||
switch (FILENAME){
|
||||
case /config\/web\.php$/:
|
||||
isFile["IsConfWeb"] = 1
|
||||
msg = msg " - add allowed IP: " ip
|
||||
break
|
||||
}
|
||||
# Print the concatenated message for the file
|
||||
print msg
|
||||
}
|
||||
|
||||
# IF config/web.php
|
||||
if (isFile["IsConfWeb"]){
|
||||
# IF line has "allowedIPs" and doesn't has our IP
|
||||
if (match($0, "allowedIPs") && !match($0, ip)){
|
||||
match($0, /([^\]]+)(.+)/, arr)
|
||||
$0 = sprintf("%s, '%s'%s", arr[1], ip, arr[2])
|
||||
}
|
||||
# Rewrite the file
|
||||
print $0 > FILENAME
|
||||
}
|
||||
}
|
||||
END {
|
||||
print "AWK ENDs its work."
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
/** @var yii\web\View $this */
|
||||
/** @var string $content */
|
||||
|
||||
use app\assets\AppAsset;
|
||||
use app\widgets\Alert;
|
||||
use yii\bootstrap5\Breadcrumbs;
|
||||
use yii\bootstrap5\Html;
|
||||
use yii\bootstrap5\Nav;
|
||||
use yii\bootstrap5\NavBar;
|
||||
|
||||
AppAsset::register($this);
|
||||
|
||||
$this->registerCsrfMetaTags();
|
||||
$this->registerMetaTag(['charset' => Yii::$app->charset], 'charset');
|
||||
$this->registerMetaTag(['name' => 'viewport', 'content' => 'width=device-width, initial-scale=1, shrink-to-fit=no']);
|
||||
$this->registerMetaTag(['name' => 'description', 'content' => $this->params['meta_description'] ?? '']);
|
||||
$this->registerMetaTag(['name' => 'keywords', 'content' => $this->params['meta_keywords'] ?? '']);
|
||||
$this->registerLinkTag(['rel' => 'icon', 'type' => 'image/x-icon', 'href' => Yii::getAlias('@web/favicon.ico')]);
|
||||
?>
|
||||
<?php $this->beginPage() ?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="<?= Yii::$app->language ?>" class="h-100">
|
||||
<head>
|
||||
<title><?= Html::encode($this->title) ?></title>
|
||||
<?php $this->head() ?>
|
||||
</head>
|
||||
<body class="d-flex flex-column h-100">
|
||||
<?php $this->beginBody() ?>
|
||||
|
||||
<header id="header">
|
||||
<?php
|
||||
NavBar::begin([
|
||||
'brandLabel' => Yii::$app->name,
|
||||
'brandUrl' => Yii::$app->homeUrl,
|
||||
'options' => ['class' => 'navbar-expand-md navbar-dark bg-dark fixed-top']
|
||||
]);
|
||||
echo Nav::widget([
|
||||
'options' => ['class' => 'navbar-nav'],
|
||||
'items' => [
|
||||
['label' => 'Home', 'url' => ['/site/index']],
|
||||
['label' => 'About', 'url' => ['/site/about']],
|
||||
['label' => 'Contact', 'url' => ['/site/contact']],
|
||||
Yii::$app->user->isGuest
|
||||
? ['label' => 'Login', 'url' => ['/site/login']]
|
||||
: '<li class="nav-item">'
|
||||
. Html::beginForm(['/site/logout'])
|
||||
. Html::submitButton(
|
||||
'Logout (' . Yii::$app->user->identity->username . ')',
|
||||
['class' => 'nav-link btn btn-link logout']
|
||||
)
|
||||
. Html::endForm()
|
||||
. '</li>'
|
||||
]
|
||||
]);
|
||||
NavBar::end();
|
||||
?>
|
||||
</header>
|
||||
|
||||
<main id="main" class="flex-shrink-0" role="main">
|
||||
<div class="container">
|
||||
<?php if (!empty($this->params['breadcrumbs'])): ?>
|
||||
<?= Breadcrumbs::widget(['links' => $this->params['breadcrumbs']]) ?>
|
||||
<?php endif ?>
|
||||
<?= Alert::widget() ?>
|
||||
<?= $content ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer id="footer" class="mt-auto py-3 bg-light">
|
||||
<div class="container">
|
||||
<div class="row text-muted">
|
||||
<div class="col-md-6 text-center text-md-start">© My Company <?= date('Y') ?></div>
|
||||
<div class="col-md-6 text-center text-md-end"><?= Yii::powered() ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<?php $this->endBody() ?>
|
||||
</body>
|
||||
</html>
|
||||
<?php $this->endPage() ?>
|
|
@ -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,4 @@
|
|||
RewriteEngine on
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule . index.php [L]
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
|
@ -0,0 +1,88 @@
|
|||
main > .container {
|
||||
padding: 70px 15px 20px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
background-color: #f5f5f5;
|
||||
font-size: .9em;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.footer > .container {
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.not-set {
|
||||
color: #c55;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* add sorting icons to gridview sort links */
|
||||
a.asc:after, a.desc:after {
|
||||
content: '';
|
||||
left: 3px;
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: solid 5px transparent;
|
||||
margin: 4px 4px 2px 4px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
a.asc:after {
|
||||
border-bottom: solid 7px #212529;
|
||||
border-top-width: 0;
|
||||
}
|
||||
|
||||
a.desc:after {
|
||||
border-top: solid 7px #212529;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
.grid-view th {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.hint-block {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.error-summary {
|
||||
color: #a94442;
|
||||
background: #fdf7f7;
|
||||
border-left: 3px solid #eed3d7;
|
||||
padding: 10px 20px;
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
|
||||
/* align the logout "link" (button in form) of the navbar */
|
||||
.nav li > form > button.logout {
|
||||
padding-top: 7px;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
@media(max-width:767px) {
|
||||
.nav li > form > button.logout {
|
||||
display:block;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
padding: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.nav > li > form > button.logout:focus,
|
||||
.nav > li > form > button.logout:hover {
|
||||
text-decoration: none;
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
}
|
||||
|
||||
.nav > li > form > button.logout:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1rem;
|
||||
}
|
Binary file not shown.
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,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,2 @@
|
|||
User-agent: *
|
||||
Disallow:
|
|
@ -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