Commit 418b7fab5a7aa0fdcc789e100a201aebd946661c

Authored by Yarik
0 parents

first commit

Showing 156 changed files with 4237 additions and 0 deletions   Show diff stats
LICENSE.md 0 → 100644
  1 +++ a/LICENSE.md
  1 +The Yii framework is free software. It is released under the terms of
  2 +the following BSD License.
  3 +
  4 +Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com)
  5 +All rights reserved.
  6 +
  7 +Redistribution and use in source and binary forms, with or without
  8 +modification, are permitted provided that the following conditions
  9 +are met:
  10 +
  11 + * Redistributions of source code must retain the above copyright
  12 + notice, this list of conditions and the following disclaimer.
  13 + * Redistributions in binary form must reproduce the above copyright
  14 + notice, this list of conditions and the following disclaimer in
  15 + the documentation and/or other materials provided with the
  16 + distribution.
  17 + * Neither the name of Yii Software LLC nor the names of its
  18 + contributors may be used to endorse or promote products derived
  19 + from this software without specific prior written permission.
  20 +
  21 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24 +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25 +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27 +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  29 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30 +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31 +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32 +POSSIBILITY OF SUCH DAMAGE.
... ...
README.md 0 → 100644
  1 +++ a/README.md
  1 +Yii 2 Advanced Project Template
  2 +===============================
  3 +
  4 +Yii 2 Advanced Project Template is a skeleton [Yii 2](http://www.yiiframework.com/) application best for
  5 +developing complex Web applications with multiple tiers.
  6 +
  7 +The template includes three tiers: front end, back end, and console, each of which
  8 +is a separate Yii application.
  9 +
  10 +The template is designed to work in a team development environment. It supports
  11 +deploying the application in different environments.
  12 +
  13 +Documentation is at [docs/guide/README.md](docs/guide/README.md).
  14 +
  15 +[![Latest Stable Version](https://poser.pugx.org/yiisoft/yii2-app-advanced/v/stable.png)](https://packagist.org/packages/yiisoft/yii2-app-advanced)
  16 +[![Total Downloads](https://poser.pugx.org/yiisoft/yii2-app-advanced/downloads.png)](https://packagist.org/packages/yiisoft/yii2-app-advanced)
  17 +[![Build Status](https://travis-ci.org/yiisoft/yii2-app-advanced.svg?branch=master)](https://travis-ci.org/yiisoft/yii2-app-advanced)
  18 +
  19 +DIRECTORY STRUCTURE
  20 +-------------------
  21 +
  22 +```
  23 +common
  24 + config/ contains shared configurations
  25 + mail/ contains view files for e-mails
  26 + models/ contains model classes used in both backend and frontend
  27 + tests/ contains tests for common classes
  28 +console
  29 + config/ contains console configurations
  30 + controllers/ contains console controllers (commands)
  31 + migrations/ contains database migrations
  32 + models/ contains console-specific model classes
  33 + runtime/ contains files generated during runtime
  34 +backend
  35 + assets/ contains application assets such as JavaScript and CSS
  36 + config/ contains backend configurations
  37 + controllers/ contains Web controller classes
  38 + models/ contains backend-specific model classes
  39 + runtime/ contains files generated during runtime
  40 + tests/ contains tests for backend application
  41 + views/ contains view files for the Web application
  42 + web/ contains the entry script and Web resources
  43 +frontend
  44 + assets/ contains application assets such as JavaScript and CSS
  45 + config/ contains frontend configurations
  46 + controllers/ contains Web controller classes
  47 + models/ contains frontend-specific model classes
  48 + runtime/ contains files generated during runtime
  49 + tests/ contains tests for frontend application
  50 + views/ contains view files for the Web application
  51 + web/ contains the entry script and Web resources
  52 + widgets/ contains frontend widgets
  53 +vendor/ contains dependent 3rd-party packages
  54 +environments/ contains environment-based overrides
  55 +```
... ...
Vagrantfile 0 → 100644
  1 +++ a/Vagrantfile
  1 +require 'yaml'
  2 +require 'fileutils'
  3 +
  4 +domains = {
  5 + frontend: 'y2aa-frontend.dev',
  6 + backend: 'y2aa-backend.dev'
  7 +}
  8 +
  9 +config = {
  10 + local: './vagrant/config/vagrant-local.yml',
  11 + example: './vagrant/config/vagrant-local.example.yml'
  12 +}
  13 +
  14 +# copy config from example if local config not exists
  15 +FileUtils.cp config[:example], config[:local] unless File.exist?(config[:local])
  16 +# read config
  17 +options = YAML.load_file config[:local]
  18 +
  19 +# check github token
  20 +if options['github_token'].nil? || options['github_token'].to_s.length != 40
  21 + puts "You must place REAL GitHub token into configuration:\n/yii2-app-advancded/vagrant/config/vagrant-local.yml"
  22 + exit
  23 +end
  24 +
  25 +# vagrant configurate
  26 +Vagrant.configure(2) do |config|
  27 + # select the box
  28 + config.vm.box = 'ubuntu/trusty64'
  29 +
  30 + # should we ask about box updates?
  31 + config.vm.box_check_update = options['box_check_update']
  32 +
  33 + config.vm.provider 'virtualbox' do |vb|
  34 + # machine cpus count
  35 + vb.cpus = options['cpus']
  36 + # machine memory size
  37 + vb.memory = options['memory']
  38 + # machine name (for VirtualBox UI)
  39 + vb.name = options['machine_name']
  40 + end
  41 +
  42 + # machine name (for vagrant console)
  43 + config.vm.define options['machine_name']
  44 +
  45 + # machine name (for guest machine console)
  46 + config.vm.hostname = options['machine_name']
  47 +
  48 + # network settings
  49 + config.vm.network 'private_network', ip: options['ip']
  50 +
  51 + # sync: folder 'yii2-app-advanced' (host machine) -> folder '/app' (guest machine)
  52 + config.vm.synced_folder './', '/app', owner: 'vagrant', group: 'vagrant'
  53 +
  54 + # disable folder '/vagrant' (guest machine)
  55 + config.vm.synced_folder '.', '/vagrant', disabled: true
  56 +
  57 + # hosts settings (host machine)
  58 + config.vm.provision :hostmanager
  59 + config.hostmanager.enabled = true
  60 + config.hostmanager.manage_host = true
  61 + config.hostmanager.ignore_private_ip = false
  62 + config.hostmanager.include_offline = true
  63 + config.hostmanager.aliases = domains.values
  64 +
  65 + # provisioners
  66 + config.vm.provision 'shell', path: './vagrant/provision/once-as-root.sh', args: [options['timezone']]
  67 + config.vm.provision 'shell', path: './vagrant/provision/once-as-vagrant.sh', args: [options['github_token']], privileged: false
  68 + config.vm.provision 'shell', path: './vagrant/provision/always-as-root.sh', run: 'always'
  69 +
  70 + # post-install message (vagrant console)
  71 + config.vm.post_up_message = "Frontend URL: http://#{domains[:frontend]}\nBackend URL: http://#{domains[:backend]}"
  72 +end
... ...
backend/assets/AppAsset.php 0 → 100644
  1 +++ a/backend/assets/AppAsset.php
  1 +<?php
  2 +
  3 +namespace backend\assets;
  4 +
  5 +use yii\web\AssetBundle;
  6 +
  7 +/**
  8 + * Main backend application asset bundle.
  9 + */
  10 +class AppAsset extends AssetBundle
  11 +{
  12 + public $basePath = '@webroot';
  13 + public $baseUrl = '@web';
  14 + public $css = [
  15 + 'css/site.css',
  16 + ];
  17 + public $js = [
  18 + ];
  19 + public $depends = [
  20 + 'yii\web\YiiAsset',
  21 + 'yii\bootstrap\BootstrapAsset',
  22 + ];
  23 +}
... ...
backend/codeception.yml 0 → 100644
  1 +++ a/backend/codeception.yml
  1 +namespace: backend\tests
  2 +actor: Tester
  3 +paths:
  4 + tests: tests
  5 + log: tests/_output
  6 + data: tests/_data
  7 + helpers: tests/_support
  8 +settings:
  9 + bootstrap: _bootstrap.php
  10 + colors: true
  11 + memory_limit: 1024M
  12 +modules:
  13 + config:
  14 + Yii2:
  15 + configFile: 'config/test-local.php'
... ...
backend/config/.gitignore 0 → 100644
  1 +++ a/backend/config/.gitignore
  1 +main-local.php
  2 +params-local.php
  3 +test-local.php
... ...
backend/config/bootstrap.php 0 → 100644
  1 +++ a/backend/config/bootstrap.php
  1 +<?php
... ...
backend/config/main.php 0 → 100644
  1 +++ a/backend/config/main.php
  1 +<?php
  2 +$params = array_merge(
  3 + require(__DIR__ . '/../../common/config/params.php'),
  4 + require(__DIR__ . '/../../common/config/params-local.php'),
  5 + require(__DIR__ . '/params.php'),
  6 + require(__DIR__ . '/params-local.php')
  7 +);
  8 +
  9 +return [
  10 + 'id' => 'app-backend',
  11 + 'basePath' => dirname(__DIR__),
  12 + 'controllerNamespace' => 'backend\controllers',
  13 + 'bootstrap' => ['log'],
  14 + 'modules' => [],
  15 + 'components' => [
  16 + 'request' => [
  17 + 'csrfParam' => '_csrf-backend',
  18 + ],
  19 + 'user' => [
  20 + 'identityClass' => 'common\models\User',
  21 + 'enableAutoLogin' => true,
  22 + 'identityCookie' => ['name' => '_identity-backend', 'httpOnly' => true],
  23 + ],
  24 + 'session' => [
  25 + // this is the name of the session cookie used for login on the backend
  26 + 'name' => 'advanced-backend',
  27 + ],
  28 + 'log' => [
  29 + 'traceLevel' => YII_DEBUG ? 3 : 0,
  30 + 'targets' => [
  31 + [
  32 + 'class' => 'yii\log\FileTarget',
  33 + 'levels' => ['error', 'warning'],
  34 + ],
  35 + ],
  36 + ],
  37 + 'errorHandler' => [
  38 + 'errorAction' => 'site/error',
  39 + ],
  40 + /*
  41 + 'urlManager' => [
  42 + 'enablePrettyUrl' => true,
  43 + 'showScriptName' => false,
  44 + 'rules' => [
  45 + ],
  46 + ],
  47 + */
  48 + ],
  49 + 'params' => $params,
  50 +];
... ...
backend/config/params.php 0 → 100644
  1 +++ a/backend/config/params.php
  1 +<?php
  2 +return [
  3 + 'adminEmail' => 'admin@example.com',
  4 +];
... ...
backend/config/test.php 0 → 100644
  1 +++ a/backend/config/test.php
  1 +<?php
  2 +return [
  3 + 'id' => 'app-backend-tests',
  4 +];
... ...
backend/controllers/SiteController.php 0 → 100644
  1 +++ a/backend/controllers/SiteController.php
  1 +<?php
  2 +namespace backend\controllers;
  3 +
  4 +use Yii;
  5 +use yii\web\Controller;
  6 +use yii\filters\VerbFilter;
  7 +use yii\filters\AccessControl;
  8 +use common\models\LoginForm;
  9 +
  10 +/**
  11 + * Site controller
  12 + */
  13 +class SiteController extends Controller
  14 +{
  15 + /**
  16 + * @inheritdoc
  17 + */
  18 + public function behaviors()
  19 + {
  20 + return [
  21 + 'access' => [
  22 + 'class' => AccessControl::className(),
  23 + 'rules' => [
  24 + [
  25 + 'actions' => ['login', 'error'],
  26 + 'allow' => true,
  27 + ],
  28 + [
  29 + 'actions' => ['logout', 'index'],
  30 + 'allow' => true,
  31 + 'roles' => ['@'],
  32 + ],
  33 + ],
  34 + ],
  35 + 'verbs' => [
  36 + 'class' => VerbFilter::className(),
  37 + 'actions' => [
  38 + 'logout' => ['post'],
  39 + ],
  40 + ],
  41 + ];
  42 + }
  43 +
  44 + /**
  45 + * @inheritdoc
  46 + */
  47 + public function actions()
  48 + {
  49 + return [
  50 + 'error' => [
  51 + 'class' => 'yii\web\ErrorAction',
  52 + ],
  53 + ];
  54 + }
  55 +
  56 + /**
  57 + * Displays homepage.
  58 + *
  59 + * @return string
  60 + */
  61 + public function actionIndex()
  62 + {
  63 + return $this->render('index');
  64 + }
  65 +
  66 + /**
  67 + * Login action.
  68 + *
  69 + * @return string
  70 + */
  71 + public function actionLogin()
  72 + {
  73 + if (!Yii::$app->user->isGuest) {
  74 + return $this->goHome();
  75 + }
  76 +
  77 + $model = new LoginForm();
  78 + if ($model->load(Yii::$app->request->post()) && $model->login()) {
  79 + return $this->goBack();
  80 + } else {
  81 + return $this->render('login', [
  82 + 'model' => $model,
  83 + ]);
  84 + }
  85 + }
  86 +
  87 + /**
  88 + * Logout action.
  89 + *
  90 + * @return string
  91 + */
  92 + public function actionLogout()
  93 + {
  94 + Yii::$app->user->logout();
  95 +
  96 + return $this->goHome();
  97 + }
  98 +}
... ...
backend/models/.gitkeep 0 → 100644
  1 +++ a/backend/models/.gitkeep
  1 +*
... ...
backend/runtime/.gitignore 0 → 100644
  1 +++ a/backend/runtime/.gitignore
  1 +*
  2 +!.gitignore
0 3 \ No newline at end of file
... ...
backend/tests/_bootstrap.php 0 → 100644
  1 +++ a/backend/tests/_bootstrap.php
  1 +<?php
  2 +defined('YII_DEBUG') or define('YII_DEBUG', true);
  3 +defined('YII_ENV') or define('YII_ENV', 'test');
  4 +defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', __DIR__.'/../../');
  5 +
  6 +require_once(YII_APP_BASE_PATH . '/vendor/autoload.php');
  7 +require_once(YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php');
  8 +require_once(YII_APP_BASE_PATH . '/common/config/bootstrap.php');
  9 +require_once(__DIR__ . '/../config/bootstrap.php');
... ...
backend/tests/_data/.gitignore 0 → 100644
  1 +++ a/backend/tests/_data/.gitignore
... ...
backend/tests/_data/login_data.php 0 → 100644
  1 +++ a/backend/tests/_data/login_data.php
  1 +<?php
  2 +return [
  3 + [
  4 + 'username' => 'erau',
  5 + 'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI',
  6 + // password_0
  7 + 'password_hash' => '$2y$13$nJ1WDlBaGcbCdbNC5.5l4.sgy.OMEKCqtDQOdQ2OWpgiKRWYyzzne',
  8 + 'password_reset_token' => 'RkD_Jw0_8HEedzLk7MM-ZKEFfYR7VbMr_1392559490',
  9 + 'created_at' => '1392559490',
  10 + 'updated_at' => '1392559490',
  11 + 'email' => 'sfriesen@jenkins.info',
  12 + ],
  13 +];
... ...
backend/tests/_output/.gitignore 0 → 100644
  1 +++ a/backend/tests/_output/.gitignore
  1 +*
  2 +!.gitignore
... ...
backend/tests/_support/.gitignore 0 → 100644
  1 +++ a/backend/tests/_support/.gitignore
  1 +_generated
... ...
backend/tests/_support/FunctionalTester.php 0 → 100644
  1 +++ a/backend/tests/_support/FunctionalTester.php
  1 +<?php
  2 +namespace backend\tests;
  3 +
  4 +/**
  5 + * Inherited Methods
  6 + * @method void wantToTest($text)
  7 + * @method void wantTo($text)
  8 + * @method void execute($callable)
  9 + * @method void expectTo($prediction)
  10 + * @method void expect($prediction)
  11 + * @method void amGoingTo($argumentation)
  12 + * @method void am($role)
  13 + * @method void lookForwardTo($achieveValue)
  14 + * @method void comment($description)
  15 + * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
  16 + *
  17 + * @SuppressWarnings(PHPMD)
  18 + */
  19 +class FunctionalTester extends \Codeception\Actor
  20 +{
  21 + use _generated\FunctionalTesterActions;
  22 + /**
  23 + * Define custom actions here
  24 + */
  25 +}
... ...
backend/tests/_support/UnitTester.php 0 → 100644
  1 +++ a/backend/tests/_support/UnitTester.php
  1 +<?php
  2 +namespace backend\tests;
  3 +
  4 +/**
  5 + * Inherited Methods
  6 + * @method void wantToTest($text)
  7 + * @method void wantTo($text)
  8 + * @method void execute($callable)
  9 + * @method void expectTo($prediction)
  10 + * @method void expect($prediction)
  11 + * @method void amGoingTo($argumentation)
  12 + * @method void am($role)
  13 + * @method void lookForwardTo($achieveValue)
  14 + * @method void comment($description)
  15 + * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
  16 + *
  17 + * @SuppressWarnings(PHPMD)
  18 + */
  19 +class UnitTester extends \Codeception\Actor
  20 +{
  21 + use _generated\UnitTesterActions;
  22 + /**
  23 + * Define custom actions here
  24 + */
  25 +}
... ...
backend/tests/functional.suite.yml 0 → 100644
  1 +++ a/backend/tests/functional.suite.yml
  1 +class_name: FunctionalTester
  2 +modules:
  3 + enabled:
  4 + - Yii2
... ...
backend/tests/functional/LoginCest.php 0 → 100644
  1 +++ a/backend/tests/functional/LoginCest.php
  1 +<?php
  2 +
  3 +namespace backend\tests\functional;
  4 +
  5 +use \backend\tests\FunctionalTester;
  6 +use common\fixtures\User as UserFixture;
  7 +
  8 +/**
  9 + * Class LoginCest
  10 + */
  11 +class LoginCest
  12 +{
  13 + public function _before(FunctionalTester $I)
  14 + {
  15 + $I->haveFixtures([
  16 + 'user' => [
  17 + 'class' => UserFixture::className(),
  18 + 'dataFile' => codecept_data_dir() . 'login_data.php'
  19 + ]
  20 + ]);
  21 + }
  22 + /**
  23 + * @param FunctionalTester $I
  24 + */
  25 + public function loginUser(FunctionalTester $I)
  26 + {
  27 + $I->amOnPage('/site/login');
  28 + $I->fillField('Username', 'erau');
  29 + $I->fillField('Password', 'password_0');
  30 + $I->click('login-button');
  31 +
  32 + $I->see('Logout (erau)', 'form button[type=submit]');
  33 + $I->dontSeeLink('Login');
  34 + $I->dontSeeLink('Signup');
  35 + }
  36 +}
... ...
backend/tests/functional/_bootstrap.php 0 → 100644
  1 +++ a/backend/tests/functional/_bootstrap.php
  1 +<?php
... ...
backend/tests/unit.suite.yml 0 → 100644
  1 +++ a/backend/tests/unit.suite.yml
  1 +class_name: UnitTester
... ...
backend/tests/unit/_bootstrap.php 0 → 100644
  1 +++ a/backend/tests/unit/_bootstrap.php
  1 +<?php
  2 +// Here you can initialize variables that will for your tests
... ...
backend/views/layouts/main.php 0 → 100644
  1 +++ a/backend/views/layouts/main.php
  1 +<?php
  2 +
  3 +/* @var $this \yii\web\View */
  4 +/* @var $content string */
  5 +
  6 +use backend\assets\AppAsset;
  7 +use yii\helpers\Html;
  8 +use yii\bootstrap\Nav;
  9 +use yii\bootstrap\NavBar;
  10 +use yii\widgets\Breadcrumbs;
  11 +use common\widgets\Alert;
  12 +
  13 +AppAsset::register($this);
  14 +?>
  15 +<?php $this->beginPage() ?>
  16 +<!DOCTYPE html>
  17 +<html lang="<?= Yii::$app->language ?>">
  18 +<head>
  19 + <meta charset="<?= Yii::$app->charset ?>">
  20 + <meta name="viewport" content="width=device-width, initial-scale=1">
  21 + <?= Html::csrfMetaTags() ?>
  22 + <title><?= Html::encode($this->title) ?></title>
  23 + <?php $this->head() ?>
  24 +</head>
  25 +<body>
  26 +<?php $this->beginBody() ?>
  27 +
  28 +<div class="wrap">
  29 + <?php
  30 + NavBar::begin([
  31 + 'brandLabel' => 'My Company',
  32 + 'brandUrl' => Yii::$app->homeUrl,
  33 + 'options' => [
  34 + 'class' => 'navbar-inverse navbar-fixed-top',
  35 + ],
  36 + ]);
  37 + $menuItems = [
  38 + ['label' => 'Home', 'url' => ['/site/index']],
  39 + ];
  40 + if (Yii::$app->user->isGuest) {
  41 + $menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];
  42 + } else {
  43 + $menuItems[] = '<li>'
  44 + . Html::beginForm(['/site/logout'], 'post')
  45 + . Html::submitButton(
  46 + 'Logout (' . Yii::$app->user->identity->username . ')',
  47 + ['class' => 'btn btn-link logout']
  48 + )
  49 + . Html::endForm()
  50 + . '</li>';
  51 + }
  52 + echo Nav::widget([
  53 + 'options' => ['class' => 'navbar-nav navbar-right'],
  54 + 'items' => $menuItems,
  55 + ]);
  56 + NavBar::end();
  57 + ?>
  58 +
  59 + <div class="container">
  60 + <?= Breadcrumbs::widget([
  61 + 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
  62 + ]) ?>
  63 + <?= Alert::widget() ?>
  64 + <?= $content ?>
  65 + </div>
  66 +</div>
  67 +
  68 +<footer class="footer">
  69 + <div class="container">
  70 + <p class="pull-left">&copy; My Company <?= date('Y') ?></p>
  71 +
  72 + <p class="pull-right"><?= Yii::powered() ?></p>
  73 + </div>
  74 +</footer>
  75 +
  76 +<?php $this->endBody() ?>
  77 +</body>
  78 +</html>
  79 +<?php $this->endPage() ?>
... ...
backend/views/site/error.php 0 → 100644
  1 +++ a/backend/views/site/error.php
  1 +<?php
  2 +
  3 +/* @var $this yii\web\View */
  4 +/* @var $name string */
  5 +/* @var $message string */
  6 +/* @var $exception Exception */
  7 +
  8 +use yii\helpers\Html;
  9 +
  10 +$this->title = $name;
  11 +?>
  12 +<div class="site-error">
  13 +
  14 + <h1><?= Html::encode($this->title) ?></h1>
  15 +
  16 + <div class="alert alert-danger">
  17 + <?= nl2br(Html::encode($message)) ?>
  18 + </div>
  19 +
  20 + <p>
  21 + The above error occurred while the Web server was processing your request.
  22 + </p>
  23 + <p>
  24 + Please contact us if you think this is a server error. Thank you.
  25 + </p>
  26 +
  27 +</div>
... ...
backend/views/site/index.php 0 → 100644
  1 +++ a/backend/views/site/index.php
  1 +<?php
  2 +
  3 +/* @var $this yii\web\View */
  4 +
  5 +$this->title = 'My Yii Application';
  6 +?>
  7 +<div class="site-index">
  8 +
  9 + <div class="jumbotron">
  10 + <h1>Congratulations!</h1>
  11 +
  12 + <p class="lead">You have successfully created your Yii-powered application.</p>
  13 +
  14 + <p><a class="btn btn-lg btn-success" href="http://www.yiiframework.com">Get started with Yii</a></p>
  15 + </div>
  16 +
  17 + <div class="body-content">
  18 +
  19 + <div class="row">
  20 + <div class="col-lg-4">
  21 + <h2>Heading</h2>
  22 +
  23 + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
  24 + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
  25 + ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
  26 + fugiat nulla pariatur.</p>
  27 +
  28 + <p><a class="btn btn-default" href="http://www.yiiframework.com/doc/">Yii Documentation &raquo;</a></p>
  29 + </div>
  30 + <div class="col-lg-4">
  31 + <h2>Heading</h2>
  32 +
  33 + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
  34 + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
  35 + ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
  36 + fugiat nulla pariatur.</p>
  37 +
  38 + <p><a class="btn btn-default" href="http://www.yiiframework.com/forum/">Yii Forum &raquo;</a></p>
  39 + </div>
  40 + <div class="col-lg-4">
  41 + <h2>Heading</h2>
  42 +
  43 + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
  44 + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
  45 + ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
  46 + fugiat nulla pariatur.</p>
  47 +
  48 + <p><a class="btn btn-default" href="http://www.yiiframework.com/extensions/">Yii Extensions &raquo;</a></p>
  49 + </div>
  50 + </div>
  51 +
  52 + </div>
  53 +</div>
... ...
backend/views/site/login.php 0 → 100644
  1 +++ a/backend/views/site/login.php
  1 +<?php
  2 +
  3 +/* @var $this yii\web\View */
  4 +/* @var $form yii\bootstrap\ActiveForm */
  5 +/* @var $model \common\models\LoginForm */
  6 +
  7 +use yii\helpers\Html;
  8 +use yii\bootstrap\ActiveForm;
  9 +
  10 +$this->title = 'Login';
  11 +$this->params['breadcrumbs'][] = $this->title;
  12 +?>
  13 +<div class="site-login">
  14 + <h1><?= Html::encode($this->title) ?></h1>
  15 +
  16 + <p>Please fill out the following fields to login:</p>
  17 +
  18 + <div class="row">
  19 + <div class="col-lg-5">
  20 + <?php $form = ActiveForm::begin(['id' => 'login-form']); ?>
  21 +
  22 + <?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
  23 +
  24 + <?= $form->field($model, 'password')->passwordInput() ?>
  25 +
  26 + <?= $form->field($model, 'rememberMe')->checkbox() ?>
  27 +
  28 + <div class="form-group">
  29 + <?= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
  30 + </div>
  31 +
  32 + <?php ActiveForm::end(); ?>
  33 + </div>
  34 + </div>
  35 +</div>
... ...
backend/web/.gitignore 0 → 100644
  1 +++ a/backend/web/.gitignore
  1 +/index.php
  2 +/index-test.php
... ...
backend/web/assets/.gitignore 0 → 100644
  1 +++ a/backend/web/assets/.gitignore
  1 +*
  2 +!.gitignore
... ...
backend/web/css/site.css 0 → 100644
  1 +++ a/backend/web/css/site.css
  1 +html,
  2 +body {
  3 + height: 100%;
  4 +}
  5 +
  6 +.wrap {
  7 + min-height: 100%;
  8 + height: auto;
  9 + margin: 0 auto -60px;
  10 + padding: 0 0 60px;
  11 +}
  12 +
  13 +.wrap > .container {
  14 + padding: 70px 15px 20px;
  15 +}
  16 +
  17 +.footer {
  18 + height: 60px;
  19 + background-color: #f5f5f5;
  20 + border-top: 1px solid #ddd;
  21 + padding-top: 20px;
  22 +}
  23 +
  24 +.jumbotron {
  25 + text-align: center;
  26 + background-color: transparent;
  27 +}
  28 +
  29 +.jumbotron .btn {
  30 + font-size: 21px;
  31 + padding: 14px 24px;
  32 +}
  33 +
  34 +.not-set {
  35 + color: #c55;
  36 + font-style: italic;
  37 +}
  38 +
  39 +/* add sorting icons to gridview sort links */
  40 +a.asc:after, a.desc:after {
  41 + position: relative;
  42 + top: 1px;
  43 + display: inline-block;
  44 + font-family: 'Glyphicons Halflings';
  45 + font-style: normal;
  46 + font-weight: normal;
  47 + line-height: 1;
  48 + padding-left: 5px;
  49 +}
  50 +
  51 +a.asc:after {
  52 + content: /*"\e113"*/ "\e151";
  53 +}
  54 +
  55 +a.desc:after {
  56 + content: /*"\e114"*/ "\e152";
  57 +}
  58 +
  59 +.sort-numerical a.asc:after {
  60 + content: "\e153";
  61 +}
  62 +
  63 +.sort-numerical a.desc:after {
  64 + content: "\e154";
  65 +}
  66 +
  67 +.sort-ordinal a.asc:after {
  68 + content: "\e155";
  69 +}
  70 +
  71 +.sort-ordinal a.desc:after {
  72 + content: "\e156";
  73 +}
  74 +
  75 +.grid-view td {
  76 + white-space: nowrap;
  77 +}
  78 +
  79 +.grid-view .filters input,
  80 +.grid-view .filters select {
  81 + min-width: 50px;
  82 +}
  83 +
  84 +.hint-block {
  85 + display: block;
  86 + margin-top: 5px;
  87 + color: #999;
  88 +}
  89 +
  90 +.error-summary {
  91 + color: #a94442;
  92 + background: #fdf7f7;
  93 + border-left: 3px solid #eed3d7;
  94 + padding: 10px 20px;
  95 + margin: 0 0 15px 0;
  96 +}
  97 +
  98 +/* align the logout "link" (button in form) of the navbar */
  99 +.nav li > form > button.logout {
  100 + padding: 15px;
  101 + border: none;
  102 +}
  103 +
  104 +@media(max-width:767px) {
  105 + .nav li > form > button.logout {
  106 + display:block;
  107 + text-align: left;
  108 + width: 100%;
  109 + padding: 10px 15px;
  110 + }
  111 +}
  112 +
  113 +.nav > li > form > button.logout:focus,
  114 +.nav > li > form > button.logout:hover {
  115 + text-decoration: none;
  116 +}
  117 +
  118 +.nav > li > form > button.logout:focus {
  119 + outline: none;
  120 +}
... ...
backend/web/favicon.ico 0 → 100644
No preview for this file type
backend/web/robots.txt 0 → 100644
  1 +++ a/backend/web/robots.txt
  1 +User-agent: *
  2 +Disallow: /
... ...
codeception.yml 0 → 100644
  1 +++ a/codeception.yml
  1 +# global codeception file to run tests from all apps
  2 +include:
  3 + - common
  4 + - frontend
  5 + - backend
  6 +paths:
  7 + log: console/runtime/logs
  8 +settings:
  9 + colors: true
0 10 \ No newline at end of file
... ...
common/codeception.yml 0 → 100644
  1 +++ a/common/codeception.yml
  1 +namespace: common\tests
  2 +actor: Tester
  3 +paths:
  4 + tests: tests
  5 + log: tests/_output
  6 + data: tests/_data
  7 + helpers: tests/_support
  8 +settings:
  9 + bootstrap: _bootstrap.php
  10 + colors: true
  11 + memory_limit: 1024M
  12 +modules:
  13 + config:
  14 + Yii2:
  15 + configFile: 'config/test-local.php'
... ...
common/config/.gitignore 0 → 100644
  1 +++ a/common/config/.gitignore
  1 +main-local.php
  2 +params-local.php
  3 +test-local.php
... ...
common/config/bootstrap.php 0 → 100644
  1 +++ a/common/config/bootstrap.php
  1 +<?php
  2 +Yii::setAlias('@common', dirname(__DIR__));
  3 +Yii::setAlias('@frontend', dirname(dirname(__DIR__)) . '/frontend');
  4 +Yii::setAlias('@backend', dirname(dirname(__DIR__)) . '/backend');
  5 +Yii::setAlias('@console', dirname(dirname(__DIR__)) . '/console');
... ...
common/config/main.php 0 → 100644
  1 +++ a/common/config/main.php
  1 +<?php
  2 +return [
  3 + 'vendorPath' => dirname(dirname(__DIR__)) . '/vendor',
  4 + 'components' => [
  5 + 'cache' => [
  6 + 'class' => 'yii\caching\FileCache',
  7 + ],
  8 + ],
  9 +];
... ...
common/config/params.php 0 → 100644
  1 +++ a/common/config/params.php
  1 +<?php
  2 +return [
  3 + 'adminEmail' => 'admin@example.com',
  4 + 'supportEmail' => 'support@example.com',
  5 + 'user.passwordResetTokenExpire' => 3600,
  6 +];
... ...
common/config/test.php 0 → 100644
  1 +++ a/common/config/test.php
  1 +<?php
  2 +return [
  3 + 'id' => 'app-common-tests',
  4 + 'basePath' => dirname(__DIR__),
  5 + 'components' => [
  6 + 'user' => [
  7 + 'class' => 'yii\web\User',
  8 + 'identityClass' => 'common\models\User',
  9 + ],
  10 + ],
  11 +];
... ...
common/fixtures/User.php 0 → 100644
  1 +++ a/common/fixtures/User.php
  1 +<?php
  2 +namespace common\fixtures;
  3 +
  4 +use yii\test\ActiveFixture;
  5 +
  6 +class User extends ActiveFixture
  7 +{
  8 + public $modelClass = 'common\models\User';
  9 +}
0 10 \ No newline at end of file
... ...
common/mail/layouts/html.php 0 → 100644
  1 +++ a/common/mail/layouts/html.php
  1 +<?php
  2 +use yii\helpers\Html;
  3 +
  4 +/* @var $this \yii\web\View view component instance */
  5 +/* @var $message \yii\mail\MessageInterface the message being composed */
  6 +/* @var $content string main view render result */
  7 +?>
  8 +<?php $this->beginPage() ?>
  9 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  10 +<html xmlns="http://www.w3.org/1999/xhtml">
  11 +<head>
  12 + <meta http-equiv="Content-Type" content="text/html; charset=<?= Yii::$app->charset ?>" />
  13 + <title><?= Html::encode($this->title) ?></title>
  14 + <?php $this->head() ?>
  15 +</head>
  16 +<body>
  17 + <?php $this->beginBody() ?>
  18 + <?= $content ?>
  19 + <?php $this->endBody() ?>
  20 +</body>
  21 +</html>
  22 +<?php $this->endPage() ?>
... ...
common/mail/layouts/text.php 0 → 100644
  1 +++ a/common/mail/layouts/text.php
  1 +<?php
  2 +
  3 +use yii\helpers\Html;
  4 +
  5 +/** @var \yii\web\View $this view component instance */
  6 +/** @var \yii\mail\MessageInterface $message the message being composed */
  7 +/** @var string $content main view render result */
  8 +?>
  9 +
  10 +<?php $this->beginPage() ?>
  11 +<?php $this->beginBody() ?>
  12 +<?= $content ?>
  13 +<?php $this->endBody() ?>
  14 +<?php $this->endPage() ?>
... ...
common/mail/passwordResetToken-html.php 0 → 100644
  1 +++ a/common/mail/passwordResetToken-html.php
  1 +<?php
  2 +use yii\helpers\Html;
  3 +
  4 +/* @var $this yii\web\View */
  5 +/* @var $user common\models\User */
  6 +
  7 +$resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
  8 +?>
  9 +<div class="password-reset">
  10 + <p>Hello <?= Html::encode($user->username) ?>,</p>
  11 +
  12 + <p>Follow the link below to reset your password:</p>
  13 +
  14 + <p><?= Html::a(Html::encode($resetLink), $resetLink) ?></p>
  15 +</div>
... ...
common/mail/passwordResetToken-text.php 0 → 100644
  1 +++ a/common/mail/passwordResetToken-text.php
  1 +<?php
  2 +
  3 +/* @var $this yii\web\View */
  4 +/* @var $user common\models\User */
  5 +
  6 +$resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
  7 +?>
  8 +Hello <?= $user->username ?>,
  9 +
  10 +Follow the link below to reset your password:
  11 +
  12 +<?= $resetLink ?>
... ...
common/models/LoginForm.php 0 → 100644
  1 +++ a/common/models/LoginForm.php
  1 +<?php
  2 +namespace common\models;
  3 +
  4 +use Yii;
  5 +use yii\base\Model;
  6 +
  7 +/**
  8 + * Login form
  9 + */
  10 +class LoginForm extends Model
  11 +{
  12 + public $username;
  13 + public $password;
  14 + public $rememberMe = true;
  15 +
  16 + private $_user;
  17 +
  18 +
  19 + /**
  20 + * @inheritdoc
  21 + */
  22 + public function rules()
  23 + {
  24 + return [
  25 + // username and password are both required
  26 + [['username', 'password'], 'required'],
  27 + // rememberMe must be a boolean value
  28 + ['rememberMe', 'boolean'],
  29 + // password is validated by validatePassword()
  30 + ['password', 'validatePassword'],
  31 + ];
  32 + }
  33 +
  34 + /**
  35 + * Validates the password.
  36 + * This method serves as the inline validation for password.
  37 + *
  38 + * @param string $attribute the attribute currently being validated
  39 + * @param array $params the additional name-value pairs given in the rule
  40 + */
  41 + public function validatePassword($attribute, $params)
  42 + {
  43 + if (!$this->hasErrors()) {
  44 + $user = $this->getUser();
  45 + if (!$user || !$user->validatePassword($this->password)) {
  46 + $this->addError($attribute, 'Incorrect username or password.');
  47 + }
  48 + }
  49 + }
  50 +
  51 + /**
  52 + * Logs in a user using the provided username and password.
  53 + *
  54 + * @return bool whether the user is logged in successfully
  55 + */
  56 + public function login()
  57 + {
  58 + if ($this->validate()) {
  59 + return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
  60 + } else {
  61 + return false;
  62 + }
  63 + }
  64 +
  65 + /**
  66 + * Finds user by [[username]]
  67 + *
  68 + * @return User|null
  69 + */
  70 + protected function getUser()
  71 + {
  72 + if ($this->_user === null) {
  73 + $this->_user = User::findByUsername($this->username);
  74 + }
  75 +
  76 + return $this->_user;
  77 + }
  78 +}
... ...
common/models/User.php 0 → 100644
  1 +++ a/common/models/User.php
  1 +<?php
  2 +namespace common\models;
  3 +
  4 +use Yii;
  5 +use yii\base\NotSupportedException;
  6 +use yii\behaviors\TimestampBehavior;
  7 +use yii\db\ActiveRecord;
  8 +use yii\web\IdentityInterface;
  9 +
  10 +/**
  11 + * User model
  12 + *
  13 + * @property integer $id
  14 + * @property string $username
  15 + * @property string $password_hash
  16 + * @property string $password_reset_token
  17 + * @property string $email
  18 + * @property string $auth_key
  19 + * @property integer $status
  20 + * @property integer $created_at
  21 + * @property integer $updated_at
  22 + * @property string $password write-only password
  23 + */
  24 +class User extends ActiveRecord implements IdentityInterface
  25 +{
  26 + const STATUS_DELETED = 0;
  27 + const STATUS_ACTIVE = 10;
  28 +
  29 +
  30 + /**
  31 + * @inheritdoc
  32 + */
  33 + public static function tableName()
  34 + {
  35 + return '{{%user}}';
  36 + }
  37 +
  38 + /**
  39 + * @inheritdoc
  40 + */
  41 + public function behaviors()
  42 + {
  43 + return [
  44 + TimestampBehavior::className(),
  45 + ];
  46 + }
  47 +
  48 + /**
  49 + * @inheritdoc
  50 + */
  51 + public function rules()
  52 + {
  53 + return [
  54 + ['status', 'default', 'value' => self::STATUS_ACTIVE],
  55 + ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
  56 + ];
  57 + }
  58 +
  59 + /**
  60 + * @inheritdoc
  61 + */
  62 + public static function findIdentity($id)
  63 + {
  64 + return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
  65 + }
  66 +
  67 + /**
  68 + * @inheritdoc
  69 + */
  70 + public static function findIdentityByAccessToken($token, $type = null)
  71 + {
  72 + throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
  73 + }
  74 +
  75 + /**
  76 + * Finds user by username
  77 + *
  78 + * @param string $username
  79 + * @return static|null
  80 + */
  81 + public static function findByUsername($username)
  82 + {
  83 + return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);
  84 + }
  85 +
  86 + /**
  87 + * Finds user by password reset token
  88 + *
  89 + * @param string $token password reset token
  90 + * @return static|null
  91 + */
  92 + public static function findByPasswordResetToken($token)
  93 + {
  94 + if (!static::isPasswordResetTokenValid($token)) {
  95 + return null;
  96 + }
  97 +
  98 + return static::findOne([
  99 + 'password_reset_token' => $token,
  100 + 'status' => self::STATUS_ACTIVE,
  101 + ]);
  102 + }
  103 +
  104 + /**
  105 + * Finds out if password reset token is valid
  106 + *
  107 + * @param string $token password reset token
  108 + * @return bool
  109 + */
  110 + public static function isPasswordResetTokenValid($token)
  111 + {
  112 + if (empty($token)) {
  113 + return false;
  114 + }
  115 +
  116 + $timestamp = (int) substr($token, strrpos($token, '_') + 1);
  117 + $expire = Yii::$app->params['user.passwordResetTokenExpire'];
  118 + return $timestamp + $expire >= time();
  119 + }
  120 +
  121 + /**
  122 + * @inheritdoc
  123 + */
  124 + public function getId()
  125 + {
  126 + return $this->getPrimaryKey();
  127 + }
  128 +
  129 + /**
  130 + * @inheritdoc
  131 + */
  132 + public function getAuthKey()
  133 + {
  134 + return $this->auth_key;
  135 + }
  136 +
  137 + /**
  138 + * @inheritdoc
  139 + */
  140 + public function validateAuthKey($authKey)
  141 + {
  142 + return $this->getAuthKey() === $authKey;
  143 + }
  144 +
  145 + /**
  146 + * Validates password
  147 + *
  148 + * @param string $password password to validate
  149 + * @return bool if password provided is valid for current user
  150 + */
  151 + public function validatePassword($password)
  152 + {
  153 + return Yii::$app->security->validatePassword($password, $this->password_hash);
  154 + }
  155 +
  156 + /**
  157 + * Generates password hash from password and sets it to the model
  158 + *
  159 + * @param string $password
  160 + */
  161 + public function setPassword($password)
  162 + {
  163 + $this->password_hash = Yii::$app->security->generatePasswordHash($password);
  164 + }
  165 +
  166 + /**
  167 + * Generates "remember me" authentication key
  168 + */
  169 + public function generateAuthKey()
  170 + {
  171 + $this->auth_key = Yii::$app->security->generateRandomString();
  172 + }
  173 +
  174 + /**
  175 + * Generates new password reset token
  176 + */
  177 + public function generatePasswordResetToken()
  178 + {
  179 + $this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
  180 + }
  181 +
  182 + /**
  183 + * Removes password reset token
  184 + */
  185 + public function removePasswordResetToken()
  186 + {
  187 + $this->password_reset_token = null;
  188 + }
  189 +}
... ...
common/tests/_bootstrap.php 0 → 100644
  1 +++ a/common/tests/_bootstrap.php
  1 +<?php
  2 +defined('YII_DEBUG') or define('YII_DEBUG', true);
  3 +defined('YII_ENV') or define('YII_ENV', 'test');
  4 +defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', __DIR__.'/../../');
  5 +
  6 +require_once(__DIR__ . '/../../vendor/autoload.php');
  7 +require_once(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
  8 +require(__DIR__ . '/../config/bootstrap.php');
  9 +
... ...
common/tests/_data/user.php 0 → 100644
  1 +++ a/common/tests/_data/user.php
  1 +<?php
  2 +
  3 +return [
  4 + [
  5 + 'username' => 'bayer.hudson',
  6 + 'auth_key' => 'HP187Mvq7Mmm3CTU80dLkGmni_FUH_lR',
  7 + //password_0
  8 + 'password_hash' => '$2y$13$EjaPFBnZOQsHdGuHI.xvhuDp1fHpo8hKRSk6yshqa9c5EG8s3C3lO',
  9 + 'password_reset_token' => 'ExzkCOaYc1L8IOBs4wdTGGbgNiG3Wz1I_1402312317',
  10 + 'created_at' => '1402312317',
  11 + 'updated_at' => '1402312317',
  12 + 'email' => 'nicole.paucek@schultz.info',
  13 + ],
  14 +];
... ...
common/tests/_output/.gitignore 0 → 100644
  1 +++ a/common/tests/_output/.gitignore
  1 +*
  2 +!.gitignore
... ...
common/tests/_support/.gitignore 0 → 100644
  1 +++ a/common/tests/_support/.gitignore
  1 +_generated
... ...
common/tests/_support/UnitTester.php 0 → 100644
  1 +++ a/common/tests/_support/UnitTester.php
  1 +<?php
  2 +namespace common\tests;
  3 +
  4 +/**
  5 + * Inherited Methods
  6 + * @method void wantToTest($text)
  7 + * @method void wantTo($text)
  8 + * @method void execute($callable)
  9 + * @method void expectTo($prediction)
  10 + * @method void expect($prediction)
  11 + * @method void amGoingTo($argumentation)
  12 + * @method void am($role)
  13 + * @method void lookForwardTo($achieveValue)
  14 + * @method void comment($description)
  15 + * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
  16 + *
  17 + * @SuppressWarnings(PHPMD)
  18 + */
  19 +class UnitTester extends \Codeception\Actor
  20 +{
  21 + use _generated\UnitTesterActions;
  22 + /**
  23 + * Define custom actions here
  24 + */
  25 +}
... ...
common/tests/unit.suite.yml 0 → 100644
  1 +++ a/common/tests/unit.suite.yml
  1 +class_name: UnitTester
  2 +bootstrap: false
  3 +modules:
  4 + enabled:
  5 + - Yii2:
  6 + part: fixtures
... ...
common/tests/unit/models/LoginFormTest.php 0 → 100644
  1 +++ a/common/tests/unit/models/LoginFormTest.php
  1 +<?php
  2 +
  3 +namespace common\tests\unit\models;
  4 +
  5 +use Yii;
  6 +use common\models\LoginForm;
  7 +use common\fixtures\User as UserFixture;
  8 +
  9 +/**
  10 + * Login form test
  11 + */
  12 +class LoginFormTest extends \Codeception\Test\Unit
  13 +{
  14 + /**
  15 + * @var \frontend\tests\UnitTester
  16 + */
  17 + protected $tester;
  18 +
  19 +
  20 + public function _before()
  21 + {
  22 + $this->tester->haveFixtures([
  23 + 'user' => [
  24 + 'class' => UserFixture::className(),
  25 + 'dataFile' => codecept_data_dir() . 'user.php'
  26 + ]
  27 + ]);
  28 + }
  29 +
  30 + public function testLoginNoUser()
  31 + {
  32 + $model = new LoginForm([
  33 + 'username' => 'not_existing_username',
  34 + 'password' => 'not_existing_password',
  35 + ]);
  36 +
  37 + expect('model should not login user', $model->login())->false();
  38 + expect('user should not be logged in', Yii::$app->user->isGuest)->true();
  39 + }
  40 +
  41 + public function testLoginWrongPassword()
  42 + {
  43 + $model = new LoginForm([
  44 + 'username' => 'bayer.hudson',
  45 + 'password' => 'wrong_password',
  46 + ]);
  47 +
  48 + expect('model should not login user', $model->login())->false();
  49 + expect('error message should be set', $model->errors)->hasKey('password');
  50 + expect('user should not be logged in', Yii::$app->user->isGuest)->true();
  51 + }
  52 +
  53 + public function testLoginCorrect()
  54 + {
  55 + $model = new LoginForm([
  56 + 'username' => 'bayer.hudson',
  57 + 'password' => 'password_0',
  58 + ]);
  59 +
  60 + expect('model should login user', $model->login())->true();
  61 + expect('error message should not be set', $model->errors)->hasntKey('password');
  62 + expect('user should be logged in', Yii::$app->user->isGuest)->false();
  63 + }
  64 +}
... ...
common/widgets/Alert.php 0 → 100644
  1 +++ a/common/widgets/Alert.php
  1 +<?php
  2 +namespace common\widgets;
  3 +
  4 +use Yii;
  5 +
  6 +/**
  7 + * Alert widget renders a message from session flash. All flash messages are displayed
  8 + * in the sequence they were assigned using setFlash. You can set message as following:
  9 + *
  10 + * ```php
  11 + * Yii::$app->session->setFlash('error', 'This is the message');
  12 + * Yii::$app->session->setFlash('success', 'This is the message');
  13 + * Yii::$app->session->setFlash('info', 'This is the message');
  14 + * ```
  15 + *
  16 + * Multiple messages could be set as follows:
  17 + *
  18 + * ```php
  19 + * Yii::$app->session->setFlash('error', ['Error 1', 'Error 2']);
  20 + * ```
  21 + *
  22 + * @author Kartik Visweswaran <kartikv2@gmail.com>
  23 + * @author Alexander Makarov <sam@rmcreative.ru>
  24 + */
  25 +class Alert extends \yii\bootstrap\Widget
  26 +{
  27 + /**
  28 + * @var array the alert types configuration for the flash messages.
  29 + * This array is setup as $key => $value, where:
  30 + * - $key is the name of the session flash variable
  31 + * - $value is the bootstrap alert type (i.e. danger, success, info, warning)
  32 + */
  33 + public $alertTypes = [
  34 + 'error' => 'alert-danger',
  35 + 'danger' => 'alert-danger',
  36 + 'success' => 'alert-success',
  37 + 'info' => 'alert-info',
  38 + 'warning' => 'alert-warning'
  39 + ];
  40 + /**
  41 + * @var array the options for rendering the close button tag.
  42 + */
  43 + public $closeButton = [];
  44 +
  45 +
  46 + public function init()
  47 + {
  48 + parent::init();
  49 +
  50 + $session = Yii::$app->session;
  51 + $flashes = $session->getAllFlashes();
  52 + $appendCss = isset($this->options['class']) ? ' ' . $this->options['class'] : '';
  53 +
  54 + foreach ($flashes as $type => $data) {
  55 + if (isset($this->alertTypes[$type])) {
  56 + $data = (array) $data;
  57 + foreach ($data as $i => $message) {
  58 + /* initialize css class for each alert box */
  59 + $this->options['class'] = $this->alertTypes[$type] . $appendCss;
  60 +
  61 + /* assign unique id to each alert box */
  62 + $this->options['id'] = $this->getId() . '-' . $type . '-' . $i;
  63 +
  64 + echo \yii\bootstrap\Alert::widget([
  65 + 'body' => $message,
  66 + 'closeButton' => $this->closeButton,
  67 + 'options' => $this->options,
  68 + ]);
  69 + }
  70 +
  71 + $session->removeFlash($type);
  72 + }
  73 + }
  74 + }
  75 +}
... ...
composer.json 0 → 100644
  1 +++ a/composer.json
  1 +{
  2 + "name": "yiisoft/yii2-app-advanced",
  3 + "description": "Yii 2 Advanced Project Template",
  4 + "keywords": ["yii2", "framework", "advanced", "project template"],
  5 + "homepage": "http://www.yiiframework.com/",
  6 + "type": "project",
  7 + "license": "BSD-3-Clause",
  8 + "support": {
  9 + "issues": "https://github.com/yiisoft/yii2/issues?state=open",
  10 + "forum": "http://www.yiiframework.com/forum/",
  11 + "wiki": "http://www.yiiframework.com/wiki/",
  12 + "irc": "irc://irc.freenode.net/yii",
  13 + "source": "https://github.com/yiisoft/yii2"
  14 + },
  15 + "minimum-stability": "stable",
  16 + "require": {
  17 + "php": ">=5.4.0",
  18 + "yiisoft/yii2": "~2.0.6",
  19 + "yiisoft/yii2-bootstrap": "~2.0.0",
  20 + "yiisoft/yii2-swiftmailer": "~2.0.0"
  21 + },
  22 + "require-dev": {
  23 + "yiisoft/yii2-debug": "~2.0.0",
  24 + "yiisoft/yii2-gii": "~2.0.0",
  25 + "yiisoft/yii2-faker": "~2.0.0",
  26 +
  27 + "codeception/base": "^2.2.3",
  28 + "codeception/verify": "~0.3.1"
  29 + },
  30 + "config": {
  31 + "process-timeout": 1800
  32 + },
  33 + "extra": {
  34 + "asset-installer-paths": {
  35 + "npm-asset-library": "vendor/npm",
  36 + "bower-asset-library": "vendor/bower"
  37 + }
  38 + },
  39 + "scripts": {
  40 + "post-install-cmd": "php init --env=Development --overwrite=n"
  41 + }
  42 +}
... ...
console/config/.gitignore 0 → 100644
  1 +++ a/console/config/.gitignore
  1 +main-local.php
  2 +params-local.php
0 3 \ No newline at end of file
... ...
console/config/bootstrap.php 0 → 100644
  1 +++ a/console/config/bootstrap.php
  1 +<?php
... ...
console/config/main.php 0 → 100644
  1 +++ a/console/config/main.php
  1 +<?php
  2 +$params = array_merge(
  3 + require(__DIR__ . '/../../common/config/params.php'),
  4 + require(__DIR__ . '/../../common/config/params-local.php'),
  5 + require(__DIR__ . '/params.php'),
  6 + require(__DIR__ . '/params-local.php')
  7 +);
  8 +
  9 +return [
  10 + 'id' => 'app-console',
  11 + 'basePath' => dirname(__DIR__),
  12 + 'bootstrap' => ['log'],
  13 + 'controllerNamespace' => 'console\controllers',
  14 + 'components' => [
  15 + 'log' => [
  16 + 'targets' => [
  17 + [
  18 + 'class' => 'yii\log\FileTarget',
  19 + 'levels' => ['error', 'warning'],
  20 + ],
  21 + ],
  22 + ],
  23 + ],
  24 + 'params' => $params,
  25 +];
... ...
console/config/params.php 0 → 100644
  1 +++ a/console/config/params.php
  1 +<?php
  2 +return [
  3 + 'adminEmail' => 'admin@example.com',
  4 +];
... ...
console/controllers/.gitkeep 0 → 100644
  1 +++ a/console/controllers/.gitkeep
... ...
console/migrations/m130524_201442_init.php 0 → 100644
  1 +++ a/console/migrations/m130524_201442_init.php
  1 +<?php
  2 +
  3 +use yii\db\Migration;
  4 +
  5 +class m130524_201442_init extends Migration
  6 +{
  7 + public function up()
  8 + {
  9 + $tableOptions = null;
  10 + if ($this->db->driverName === 'mysql') {
  11 + // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
  12 + $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
  13 + }
  14 +
  15 + $this->createTable('{{%user}}', [
  16 + 'id' => $this->primaryKey(),
  17 + 'username' => $this->string()->notNull()->unique(),
  18 + 'auth_key' => $this->string(32)->notNull(),
  19 + 'password_hash' => $this->string()->notNull(),
  20 + 'password_reset_token' => $this->string()->unique(),
  21 + 'email' => $this->string()->notNull()->unique(),
  22 +
  23 + 'status' => $this->smallInteger()->notNull()->defaultValue(10),
  24 + 'created_at' => $this->integer()->notNull(),
  25 + 'updated_at' => $this->integer()->notNull(),
  26 + ], $tableOptions);
  27 + }
  28 +
  29 + public function down()
  30 + {
  31 + $this->dropTable('{{%user}}');
  32 + }
  33 +}
... ...
console/models/.gitkeep 0 → 100644
  1 +++ a/console/models/.gitkeep
  1 +*
... ...
console/runtime/.gitignore 0 → 100644
  1 +++ a/console/runtime/.gitignore
  1 +*
  2 +!.gitignore
0 3 \ No newline at end of file
... ...
environments/dev/backend/config/main-local.php 0 → 100644
  1 +++ a/environments/dev/backend/config/main-local.php
  1 +<?php
  2 +
  3 +$config = [
  4 + 'components' => [
  5 + 'request' => [
  6 + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
  7 + 'cookieValidationKey' => '',
  8 + ],
  9 + ],
  10 +];
  11 +
  12 +if (!YII_ENV_TEST) {
  13 + // configuration adjustments for 'dev' environment
  14 + $config['bootstrap'][] = 'debug';
  15 + $config['modules']['debug'] = [
  16 + 'class' => 'yii\debug\Module',
  17 + ];
  18 +
  19 + $config['bootstrap'][] = 'gii';
  20 + $config['modules']['gii'] = [
  21 + 'class' => 'yii\gii\Module',
  22 + ];
  23 +}
  24 +
  25 +return $config;
... ...
environments/dev/backend/config/params-local.php 0 → 100644
  1 +++ a/environments/dev/backend/config/params-local.php
  1 +<?php
  2 +return [
  3 +];
... ...
environments/dev/backend/config/test-local.php 0 → 100644
  1 +++ a/environments/dev/backend/config/test-local.php
  1 +<?php
  2 +return yii\helpers\ArrayHelper::merge(
  3 + require(__DIR__ . '/../../common/config/test-local.php'),
  4 + require(__DIR__ . '/main.php'),
  5 + require(__DIR__ . '/main-local.php'),
  6 + require(__DIR__ . '/test.php'),
  7 + [
  8 + ]
  9 +);
... ...
environments/dev/backend/web/index-test.php 0 → 100644
  1 +++ a/environments/dev/backend/web/index-test.php
  1 +<?php
  2 +
  3 +// NOTE: Make sure this file is not accessible when deployed to production
  4 +if (!in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1'])) {
  5 + die('You are not allowed to access this file.');
  6 +}
  7 +
  8 +defined('YII_DEBUG') or define('YII_DEBUG', true);
  9 +defined('YII_ENV') or define('YII_ENV', 'test');
  10 +
  11 +require(__DIR__ . '/../../vendor/autoload.php');
  12 +require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
  13 +require(__DIR__ . '/../../common/config/bootstrap.php');
  14 +require(__DIR__ . '/../config/bootstrap.php');
  15 +
  16 +$config = require(__DIR__ . '/../config/test-local.php');
  17 +
  18 +(new yii\web\Application($config))->run();
... ...
environments/dev/backend/web/index.php 0 → 100644
  1 +++ a/environments/dev/backend/web/index.php
  1 +<?php
  2 +defined('YII_DEBUG') or define('YII_DEBUG', true);
  3 +defined('YII_ENV') or define('YII_ENV', 'dev');
  4 +
  5 +require(__DIR__ . '/../../vendor/autoload.php');
  6 +require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
  7 +require(__DIR__ . '/../../common/config/bootstrap.php');
  8 +require(__DIR__ . '/../config/bootstrap.php');
  9 +
  10 +$config = yii\helpers\ArrayHelper::merge(
  11 + require(__DIR__ . '/../../common/config/main.php'),
  12 + require(__DIR__ . '/../../common/config/main-local.php'),
  13 + require(__DIR__ . '/../config/main.php'),
  14 + require(__DIR__ . '/../config/main-local.php')
  15 +);
  16 +
  17 +(new yii\web\Application($config))->run();
... ...
environments/dev/common/config/main-local.php 0 → 100644
  1 +++ a/environments/dev/common/config/main-local.php
  1 +<?php
  2 +return [
  3 + 'components' => [
  4 + 'db' => [
  5 + 'class' => 'yii\db\Connection',
  6 + 'dsn' => 'mysql:host=localhost;dbname=yii2advanced',
  7 + 'username' => 'root',
  8 + 'password' => '',
  9 + 'charset' => 'utf8',
  10 + ],
  11 + 'mailer' => [
  12 + 'class' => 'yii\swiftmailer\Mailer',
  13 + 'viewPath' => '@common/mail',
  14 + // send all mails to a file by default. You have to set
  15 + // 'useFileTransport' to false and configure a transport
  16 + // for the mailer to send real emails.
  17 + 'useFileTransport' => true,
  18 + ],
  19 + ],
  20 +];
... ...
environments/dev/common/config/params-local.php 0 → 100644
  1 +++ a/environments/dev/common/config/params-local.php
  1 +<?php
  2 +return [
  3 +];
... ...
environments/dev/common/config/test-local.php 0 → 100644
  1 +++ a/environments/dev/common/config/test-local.php
  1 +<?php
  2 +return yii\helpers\ArrayHelper::merge(
  3 + require(__DIR__ . '/main.php'),
  4 + require(__DIR__ . '/main-local.php'),
  5 + require(__DIR__ . '/test.php'),
  6 + [
  7 + 'components' => [
  8 + 'db' => [
  9 + 'dsn' => 'mysql:host=localhost;dbname=yii2advanced_test',
  10 + ]
  11 + ],
  12 + ]
  13 +);
... ...
environments/dev/console/config/main-local.php 0 → 100644
  1 +++ a/environments/dev/console/config/main-local.php
  1 +<?php
  2 +return [
  3 + 'bootstrap' => ['gii'],
  4 + 'modules' => [
  5 + 'gii' => 'yii\gii\Module',
  6 + ],
  7 +];
... ...
environments/dev/console/config/params-local.php 0 → 100644
  1 +++ a/environments/dev/console/config/params-local.php
  1 +<?php
  2 +return [
  3 +];
... ...
environments/dev/frontend/config/main-local.php 0 → 100644
  1 +++ a/environments/dev/frontend/config/main-local.php
  1 +<?php
  2 +
  3 +$config = [
  4 + 'components' => [
  5 + 'request' => [
  6 + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
  7 + 'cookieValidationKey' => '',
  8 + ],
  9 + ],
  10 +];
  11 +
  12 +if (!YII_ENV_TEST) {
  13 + // configuration adjustments for 'dev' environment
  14 + $config['bootstrap'][] = 'debug';
  15 + $config['modules']['debug'] = [
  16 + 'class' => 'yii\debug\Module',
  17 + ];
  18 +
  19 + $config['bootstrap'][] = 'gii';
  20 + $config['modules']['gii'] = [
  21 + 'class' => 'yii\gii\Module',
  22 + ];
  23 +}
  24 +
  25 +return $config;
... ...
environments/dev/frontend/config/params-local.php 0 → 100644
  1 +++ a/environments/dev/frontend/config/params-local.php
  1 +<?php
  2 +return [
  3 +];
... ...
environments/dev/frontend/config/test-local.php 0 → 100644
  1 +++ a/environments/dev/frontend/config/test-local.php
  1 +<?php
  2 +return yii\helpers\ArrayHelper::merge(
  3 + require(__DIR__ . '/../../common/config/test-local.php'),
  4 + require(__DIR__ . '/main.php'),
  5 + require(__DIR__ . '/main-local.php'),
  6 + require(__DIR__ . '/test.php'),
  7 + [
  8 + ]
  9 +);
... ...
environments/dev/frontend/web/index-test.php 0 → 100644
  1 +++ a/environments/dev/frontend/web/index-test.php
  1 +<?php
  2 +
  3 +// NOTE: Make sure this file is not accessible when deployed to production
  4 +if (!in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1'])) {
  5 + die('You are not allowed to access this file.');
  6 +}
  7 +
  8 +defined('YII_DEBUG') or define('YII_DEBUG', true);
  9 +defined('YII_ENV') or define('YII_ENV', 'test');
  10 +
  11 +require(__DIR__ . '/../../vendor/autoload.php');
  12 +require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
  13 +require(__DIR__ . '/../../common/config/bootstrap.php');
  14 +require(__DIR__ . '/../config/bootstrap.php');
  15 +
  16 +$config = require(__DIR__ . '/../config/test-local.php');
  17 +
  18 +(new yii\web\Application($config))->run();
... ...
environments/dev/frontend/web/index.php 0 → 100644
  1 +++ a/environments/dev/frontend/web/index.php
  1 +<?php
  2 +defined('YII_DEBUG') or define('YII_DEBUG', true);
  3 +defined('YII_ENV') or define('YII_ENV', 'dev');
  4 +
  5 +require(__DIR__ . '/../../vendor/autoload.php');
  6 +require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
  7 +require(__DIR__ . '/../../common/config/bootstrap.php');
  8 +require(__DIR__ . '/../config/bootstrap.php');
  9 +
  10 +$config = yii\helpers\ArrayHelper::merge(
  11 + require(__DIR__ . '/../../common/config/main.php'),
  12 + require(__DIR__ . '/../../common/config/main-local.php'),
  13 + require(__DIR__ . '/../config/main.php'),
  14 + require(__DIR__ . '/../config/main-local.php')
  15 +);
  16 +
  17 +(new yii\web\Application($config))->run();
... ...
environments/dev/yii 0 → 100644
  1 +++ a/environments/dev/yii
  1 +#!/usr/bin/env php
  2 +<?php
  3 +/**
  4 + * Yii console bootstrap file.
  5 + *
  6 + * @link http://www.yiiframework.com/
  7 + * @copyright Copyright (c) 2008 Yii Software LLC
  8 + * @license http://www.yiiframework.com/license/
  9 + */
  10 +
  11 +defined('YII_DEBUG') or define('YII_DEBUG', true);
  12 +defined('YII_ENV') or define('YII_ENV', 'dev');
  13 +
  14 +require(__DIR__ . '/vendor/autoload.php');
  15 +require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
  16 +require(__DIR__ . '/common/config/bootstrap.php');
  17 +require(__DIR__ . '/console/config/bootstrap.php');
  18 +
  19 +$config = yii\helpers\ArrayHelper::merge(
  20 + require(__DIR__ . '/common/config/main.php'),
  21 + require(__DIR__ . '/common/config/main-local.php'),
  22 + require(__DIR__ . '/console/config/main.php'),
  23 + require(__DIR__ . '/console/config/main-local.php')
  24 +);
  25 +
  26 +$application = new yii\console\Application($config);
  27 +$exitCode = $application->run();
  28 +exit($exitCode);
... ...
environments/dev/yii_test 0 → 100644
  1 +++ a/environments/dev/yii_test
  1 +#!/usr/bin/env php
  2 +<?php
  3 +/**
  4 + * Yii console bootstrap file.
  5 + *
  6 + * @link http://www.yiiframework.com/
  7 + * @copyright Copyright (c) 2008 Yii Software LLC
  8 + * @license http://www.yiiframework.com/license/
  9 + */
  10 +
  11 +defined('YII_DEBUG') or define('YII_DEBUG', true);
  12 +defined('YII_ENV') or define('YII_ENV', 'test');
  13 +
  14 +require(__DIR__ . '/vendor/autoload.php');
  15 +require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
  16 +require(__DIR__ . '/common/config/bootstrap.php');
  17 +require(__DIR__ . '/console/config/bootstrap.php');
  18 +
  19 +$config = yii\helpers\ArrayHelper::merge(
  20 + require(__DIR__ . '/common/config/test-local.php'),
  21 + require(__DIR__ . '/console/config/main.php'),
  22 + require(__DIR__ . '/console/config/main-local.php')
  23 +);
  24 +
  25 +$application = new yii\console\Application($config);
  26 +$exitCode = $application->run();
  27 +exit($exitCode);
... ...
environments/dev/yii_test.bat 0 → 100644
  1 +++ a/environments/dev/yii_test.bat
  1 +@echo off
  2 +
  3 +rem -------------------------------------------------------------
  4 +rem Yii command line bootstrap script for Windows.
  5 +rem
  6 +rem @author Qiang Xue <qiang.xue@gmail.com>
  7 +rem @link http://www.yiiframework.com/
  8 +rem @copyright Copyright (c) 2008 Yii Software LLC
  9 +rem @license http://www.yiiframework.com/license/
  10 +rem -------------------------------------------------------------
  11 +
  12 +@setlocal
  13 +
  14 +set YII_PATH=%~dp0
  15 +
  16 +if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
  17 +
  18 +"%PHP_COMMAND%" "%YII_PATH%yii_test" %*
  19 +
  20 +@endlocal
... ...
environments/index.php 0 → 100644
  1 +++ a/environments/index.php
  1 +<?php
  2 +/**
  3 + * The manifest of files that are local to specific environment.
  4 + * This file returns a list of environments that the application
  5 + * may be installed under. The returned data must be in the following
  6 + * format:
  7 + *
  8 + * ```php
  9 + * return [
  10 + * 'environment name' => [
  11 + * 'path' => 'directory storing the local files',
  12 + * 'skipFiles' => [
  13 + * // list of files that should only copied once and skipped if they already exist
  14 + * ],
  15 + * 'setWritable' => [
  16 + * // list of directories that should be set writable
  17 + * ],
  18 + * 'setExecutable' => [
  19 + * // list of files that should be set executable
  20 + * ],
  21 + * 'setCookieValidationKey' => [
  22 + * // list of config files that need to be inserted with automatically generated cookie validation keys
  23 + * ],
  24 + * 'createSymlink' => [
  25 + * // list of symlinks to be created. Keys are symlinks, and values are the targets.
  26 + * ],
  27 + * ],
  28 + * ];
  29 + * ```
  30 + */
  31 +return [
  32 + 'Development' => [
  33 + 'path' => 'dev',
  34 + 'setWritable' => [
  35 + 'backend/runtime',
  36 + 'backend/web/assets',
  37 + 'frontend/runtime',
  38 + 'frontend/web/assets',
  39 + ],
  40 + 'setExecutable' => [
  41 + 'yii',
  42 + 'yii_test',
  43 + ],
  44 + 'setCookieValidationKey' => [
  45 + 'backend/config/main-local.php',
  46 + 'frontend/config/main-local.php',
  47 + ],
  48 + ],
  49 + 'Production' => [
  50 + 'path' => 'prod',
  51 + 'setWritable' => [
  52 + 'backend/runtime',
  53 + 'backend/web/assets',
  54 + 'frontend/runtime',
  55 + 'frontend/web/assets',
  56 + ],
  57 + 'setExecutable' => [
  58 + 'yii',
  59 + ],
  60 + 'setCookieValidationKey' => [
  61 + 'backend/config/main-local.php',
  62 + 'frontend/config/main-local.php',
  63 + ],
  64 + ],
  65 +];
... ...
environments/prod/backend/config/main-local.php 0 → 100644
  1 +++ a/environments/prod/backend/config/main-local.php
  1 +<?php
  2 +return [
  3 + 'components' => [
  4 + 'request' => [
  5 + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
  6 + 'cookieValidationKey' => '',
  7 + ],
  8 + ],
  9 +];
... ...
environments/prod/backend/config/params-local.php 0 → 100644
  1 +++ a/environments/prod/backend/config/params-local.php
  1 +<?php
  2 +return [
  3 +];
... ...
environments/prod/backend/web/index.php 0 → 100644
  1 +++ a/environments/prod/backend/web/index.php
  1 +<?php
  2 +defined('YII_DEBUG') or define('YII_DEBUG', false);
  3 +defined('YII_ENV') or define('YII_ENV', 'prod');
  4 +
  5 +require(__DIR__ . '/../../vendor/autoload.php');
  6 +require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
  7 +require(__DIR__ . '/../../common/config/bootstrap.php');
  8 +require(__DIR__ . '/../config/bootstrap.php');
  9 +
  10 +$config = yii\helpers\ArrayHelper::merge(
  11 + require(__DIR__ . '/../../common/config/main.php'),
  12 + require(__DIR__ . '/../../common/config/main-local.php'),
  13 + require(__DIR__ . '/../config/main.php'),
  14 + require(__DIR__ . '/../config/main-local.php')
  15 +);
  16 +
  17 +(new yii\web\Application($config))->run();
... ...
environments/prod/common/config/main-local.php 0 → 100644
  1 +++ a/environments/prod/common/config/main-local.php
  1 +<?php
  2 +return [
  3 + 'components' => [
  4 + 'db' => [
  5 + 'class' => 'yii\db\Connection',
  6 + 'dsn' => 'mysql:host=localhost;dbname=yii2advanced',
  7 + 'username' => 'root',
  8 + 'password' => '',
  9 + 'charset' => 'utf8',
  10 + ],
  11 + 'mailer' => [
  12 + 'class' => 'yii\swiftmailer\Mailer',
  13 + 'viewPath' => '@common/mail',
  14 + ],
  15 + ],
  16 +];
... ...
environments/prod/common/config/params-local.php 0 → 100644
  1 +++ a/environments/prod/common/config/params-local.php
  1 +<?php
  2 +return [
  3 +];
... ...
environments/prod/console/config/main-local.php 0 → 100644
  1 +++ a/environments/prod/console/config/main-local.php
  1 +<?php
  2 +return [
  3 +];
... ...
environments/prod/console/config/params-local.php 0 → 100644
  1 +++ a/environments/prod/console/config/params-local.php
  1 +<?php
  2 +return [
  3 +];
... ...
environments/prod/frontend/config/main-local.php 0 → 100644
  1 +++ a/environments/prod/frontend/config/main-local.php
  1 +<?php
  2 +return [
  3 + 'components' => [
  4 + 'request' => [
  5 + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
  6 + 'cookieValidationKey' => '',
  7 + ],
  8 + ],
  9 +];
... ...
environments/prod/frontend/config/params-local.php 0 → 100644
  1 +++ a/environments/prod/frontend/config/params-local.php
  1 +<?php
  2 +return [
  3 +];
... ...
environments/prod/frontend/web/index.php 0 → 100644
  1 +++ a/environments/prod/frontend/web/index.php
  1 +<?php
  2 +defined('YII_DEBUG') or define('YII_DEBUG', false);
  3 +defined('YII_ENV') or define('YII_ENV', 'prod');
  4 +
  5 +require(__DIR__ . '/../../vendor/autoload.php');
  6 +require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
  7 +require(__DIR__ . '/../../common/config/bootstrap.php');
  8 +require(__DIR__ . '/../config/bootstrap.php');
  9 +
  10 +$config = yii\helpers\ArrayHelper::merge(
  11 + require(__DIR__ . '/../../common/config/main.php'),
  12 + require(__DIR__ . '/../../common/config/main-local.php'),
  13 + require(__DIR__ . '/../config/main.php'),
  14 + require(__DIR__ . '/../config/main-local.php')
  15 +);
  16 +
  17 +(new yii\web\Application($config))->run();
... ...
environments/prod/yii 0 → 100644
  1 +++ a/environments/prod/yii
  1 +#!/usr/bin/env php
  2 +<?php
  3 +/**
  4 + * Yii console bootstrap file.
  5 + *
  6 + * @link http://www.yiiframework.com/
  7 + * @copyright Copyright (c) 2008 Yii Software LLC
  8 + * @license http://www.yiiframework.com/license/
  9 + */
  10 +
  11 +defined('YII_DEBUG') or define('YII_DEBUG', false);
  12 +defined('YII_ENV') or define('YII_ENV', 'prod');
  13 +
  14 +require(__DIR__ . '/vendor/autoload.php');
  15 +require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
  16 +require(__DIR__ . '/common/config/bootstrap.php');
  17 +require(__DIR__ . '/console/config/bootstrap.php');
  18 +
  19 +$config = yii\helpers\ArrayHelper::merge(
  20 + require(__DIR__ . '/common/config/main.php'),
  21 + require(__DIR__ . '/common/config/main-local.php'),
  22 + require(__DIR__ . '/console/config/main.php'),
  23 + require(__DIR__ . '/console/config/main-local.php')
  24 +);
  25 +
  26 +$application = new yii\console\Application($config);
  27 +$exitCode = $application->run();
  28 +exit($exitCode);
... ...
frontend/assets/AppAsset.php 0 → 100644
  1 +++ a/frontend/assets/AppAsset.php
  1 +<?php
  2 +
  3 +namespace frontend\assets;
  4 +
  5 +use yii\web\AssetBundle;
  6 +
  7 +/**
  8 + * Main frontend application asset bundle.
  9 + */
  10 +class AppAsset extends AssetBundle
  11 +{
  12 + public $basePath = '@webroot';
  13 + public $baseUrl = '@web';
  14 + public $css = [
  15 + 'css/site.css',
  16 + ];
  17 + public $js = [
  18 + ];
  19 + public $depends = [
  20 + 'yii\web\YiiAsset',
  21 + 'yii\bootstrap\BootstrapAsset',
  22 + ];
  23 +}
... ...
frontend/codeception.yml 0 → 100644
  1 +++ a/frontend/codeception.yml
  1 +namespace: frontend\tests
  2 +actor: Tester
  3 +paths:
  4 + tests: tests
  5 + log: tests/_output
  6 + data: tests/_data
  7 + helpers: tests/_support
  8 +settings:
  9 + bootstrap: _bootstrap.php
  10 + colors: true
  11 + memory_limit: 1024M
  12 +modules:
  13 + config:
  14 + Yii2:
  15 + configFile: 'config/test-local.php'
... ...
frontend/config/.gitignore 0 → 100644
  1 +++ a/frontend/config/.gitignore
  1 +main-local.php
  2 +params-local.php
  3 +test-local.php
... ...
frontend/config/bootstrap.php 0 → 100644
  1 +++ a/frontend/config/bootstrap.php
  1 +<?php
... ...
frontend/config/main.php 0 → 100644
  1 +++ a/frontend/config/main.php
  1 +<?php
  2 +$params = array_merge(
  3 + require(__DIR__ . '/../../common/config/params.php'),
  4 + require(__DIR__ . '/../../common/config/params-local.php'),
  5 + require(__DIR__ . '/params.php'),
  6 + require(__DIR__ . '/params-local.php')
  7 +);
  8 +
  9 +return [
  10 + 'id' => 'app-frontend',
  11 + 'basePath' => dirname(__DIR__),
  12 + 'bootstrap' => ['log'],
  13 + 'controllerNamespace' => 'frontend\controllers',
  14 + 'components' => [
  15 + 'request' => [
  16 + 'csrfParam' => '_csrf-frontend',
  17 + ],
  18 + 'user' => [
  19 + 'identityClass' => 'common\models\User',
  20 + 'enableAutoLogin' => true,
  21 + 'identityCookie' => ['name' => '_identity-frontend', 'httpOnly' => true],
  22 + ],
  23 + 'session' => [
  24 + // this is the name of the session cookie used for login on the frontend
  25 + 'name' => 'advanced-frontend',
  26 + ],
  27 + 'log' => [
  28 + 'traceLevel' => YII_DEBUG ? 3 : 0,
  29 + 'targets' => [
  30 + [
  31 + 'class' => 'yii\log\FileTarget',
  32 + 'levels' => ['error', 'warning'],
  33 + ],
  34 + ],
  35 + ],
  36 + 'errorHandler' => [
  37 + 'errorAction' => 'site/error',
  38 + ],
  39 + /*
  40 + 'urlManager' => [
  41 + 'enablePrettyUrl' => true,
  42 + 'showScriptName' => false,
  43 + 'rules' => [
  44 + ],
  45 + ],
  46 + */
  47 + ],
  48 + 'params' => $params,
  49 +];
... ...
frontend/config/params.php 0 → 100644
  1 +++ a/frontend/config/params.php
  1 +<?php
  2 +return [
  3 + 'adminEmail' => 'admin@example.com',
  4 +];
... ...
frontend/config/test.php 0 → 100644
  1 +++ a/frontend/config/test.php
  1 +<?php
  2 +return [
  3 + 'id' => 'app-frontend-tests',
  4 +];
... ...
frontend/controllers/SiteController.php 0 → 100644
  1 +++ a/frontend/controllers/SiteController.php
  1 +<?php
  2 +namespace frontend\controllers;
  3 +
  4 +use Yii;
  5 +use yii\base\InvalidParamException;
  6 +use yii\web\BadRequestHttpException;
  7 +use yii\web\Controller;
  8 +use yii\filters\VerbFilter;
  9 +use yii\filters\AccessControl;
  10 +use common\models\LoginForm;
  11 +use frontend\models\PasswordResetRequestForm;
  12 +use frontend\models\ResetPasswordForm;
  13 +use frontend\models\SignupForm;
  14 +use frontend\models\ContactForm;
  15 +
  16 +/**
  17 + * Site controller
  18 + */
  19 +class SiteController extends Controller
  20 +{
  21 + /**
  22 + * @inheritdoc
  23 + */
  24 + public function behaviors()
  25 + {
  26 + return [
  27 + 'access' => [
  28 + 'class' => AccessControl::className(),
  29 + 'only' => ['logout', 'signup'],
  30 + 'rules' => [
  31 + [
  32 + 'actions' => ['signup'],
  33 + 'allow' => true,
  34 + 'roles' => ['?'],
  35 + ],
  36 + [
  37 + 'actions' => ['logout'],
  38 + 'allow' => true,
  39 + 'roles' => ['@'],
  40 + ],
  41 + ],
  42 + ],
  43 + 'verbs' => [
  44 + 'class' => VerbFilter::className(),
  45 + 'actions' => [
  46 + 'logout' => ['post'],
  47 + ],
  48 + ],
  49 + ];
  50 + }
  51 +
  52 + /**
  53 + * @inheritdoc
  54 + */
  55 + public function actions()
  56 + {
  57 + return [
  58 + 'error' => [
  59 + 'class' => 'yii\web\ErrorAction',
  60 + ],
  61 + 'captcha' => [
  62 + 'class' => 'yii\captcha\CaptchaAction',
  63 + 'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
  64 + ],
  65 + ];
  66 + }
  67 +
  68 + /**
  69 + * Displays homepage.
  70 + *
  71 + * @return mixed
  72 + */
  73 + public function actionIndex()
  74 + {
  75 + return $this->render('index');
  76 + }
  77 +
  78 + /**
  79 + * Logs in a user.
  80 + *
  81 + * @return mixed
  82 + */
  83 + public function actionLogin()
  84 + {
  85 + if (!Yii::$app->user->isGuest) {
  86 + return $this->goHome();
  87 + }
  88 +
  89 + $model = new LoginForm();
  90 + if ($model->load(Yii::$app->request->post()) && $model->login()) {
  91 + return $this->goBack();
  92 + } else {
  93 + return $this->render('login', [
  94 + 'model' => $model,
  95 + ]);
  96 + }
  97 + }
  98 +
  99 + /**
  100 + * Logs out the current user.
  101 + *
  102 + * @return mixed
  103 + */
  104 + public function actionLogout()
  105 + {
  106 + Yii::$app->user->logout();
  107 +
  108 + return $this->goHome();
  109 + }
  110 +
  111 + /**
  112 + * Displays contact page.
  113 + *
  114 + * @return mixed
  115 + */
  116 + public function actionContact()
  117 + {
  118 + $model = new ContactForm();
  119 + if ($model->load(Yii::$app->request->post()) && $model->validate()) {
  120 + if ($model->sendEmail(Yii::$app->params['adminEmail'])) {
  121 + Yii::$app->session->setFlash('success', 'Thank you for contacting us. We will respond to you as soon as possible.');
  122 + } else {
  123 + Yii::$app->session->setFlash('error', 'There was an error sending email.');
  124 + }
  125 +
  126 + return $this->refresh();
  127 + } else {
  128 + return $this->render('contact', [
  129 + 'model' => $model,
  130 + ]);
  131 + }
  132 + }
  133 +
  134 + /**
  135 + * Displays about page.
  136 + *
  137 + * @return mixed
  138 + */
  139 + public function actionAbout()
  140 + {
  141 + return $this->render('about');
  142 + }
  143 +
  144 + /**
  145 + * Signs user up.
  146 + *
  147 + * @return mixed
  148 + */
  149 + public function actionSignup()
  150 + {
  151 + $model = new SignupForm();
  152 + if ($model->load(Yii::$app->request->post())) {
  153 + if ($user = $model->signup()) {
  154 + if (Yii::$app->getUser()->login($user)) {
  155 + return $this->goHome();
  156 + }
  157 + }
  158 + }
  159 +
  160 + return $this->render('signup', [
  161 + 'model' => $model,
  162 + ]);
  163 + }
  164 +
  165 + /**
  166 + * Requests password reset.
  167 + *
  168 + * @return mixed
  169 + */
  170 + public function actionRequestPasswordReset()
  171 + {
  172 + $model = new PasswordResetRequestForm();
  173 + if ($model->load(Yii::$app->request->post()) && $model->validate()) {
  174 + if ($model->sendEmail()) {
  175 + Yii::$app->session->setFlash('success', 'Check your email for further instructions.');
  176 +
  177 + return $this->goHome();
  178 + } else {
  179 + Yii::$app->session->setFlash('error', 'Sorry, we are unable to reset password for email provided.');
  180 + }
  181 + }
  182 +
  183 + return $this->render('requestPasswordResetToken', [
  184 + 'model' => $model,
  185 + ]);
  186 + }
  187 +
  188 + /**
  189 + * Resets password.
  190 + *
  191 + * @param string $token
  192 + * @return mixed
  193 + * @throws BadRequestHttpException
  194 + */
  195 + public function actionResetPassword($token)
  196 + {
  197 + try {
  198 + $model = new ResetPasswordForm($token);
  199 + } catch (InvalidParamException $e) {
  200 + throw new BadRequestHttpException($e->getMessage());
  201 + }
  202 +
  203 + if ($model->load(Yii::$app->request->post()) && $model->validate() && $model->resetPassword()) {
  204 + Yii::$app->session->setFlash('success', 'New password was saved.');
  205 +
  206 + return $this->goHome();
  207 + }
  208 +
  209 + return $this->render('resetPassword', [
  210 + 'model' => $model,
  211 + ]);
  212 + }
  213 +}
... ...
frontend/models/ContactForm.php 0 → 100644
  1 +++ a/frontend/models/ContactForm.php
  1 +<?php
  2 +
  3 +namespace frontend\models;
  4 +
  5 +use Yii;
  6 +use yii\base\Model;
  7 +
  8 +/**
  9 + * ContactForm is the model behind the contact form.
  10 + */
  11 +class ContactForm extends Model
  12 +{
  13 + public $name;
  14 + public $email;
  15 + public $subject;
  16 + public $body;
  17 + public $verifyCode;
  18 +
  19 +
  20 + /**
  21 + * @inheritdoc
  22 + */
  23 + public function rules()
  24 + {
  25 + return [
  26 + // name, email, subject and body are required
  27 + [['name', 'email', 'subject', 'body'], 'required'],
  28 + // email has to be a valid email address
  29 + ['email', 'email'],
  30 + // verifyCode needs to be entered correctly
  31 + ['verifyCode', 'captcha'],
  32 + ];
  33 + }
  34 +
  35 + /**
  36 + * @inheritdoc
  37 + */
  38 + public function attributeLabels()
  39 + {
  40 + return [
  41 + 'verifyCode' => 'Verification Code',
  42 + ];
  43 + }
  44 +
  45 + /**
  46 + * Sends an email to the specified email address using the information collected by this model.
  47 + *
  48 + * @param string $email the target email address
  49 + * @return bool whether the email was sent
  50 + */
  51 + public function sendEmail($email)
  52 + {
  53 + return Yii::$app->mailer->compose()
  54 + ->setTo($email)
  55 + ->setFrom([$this->email => $this->name])
  56 + ->setSubject($this->subject)
  57 + ->setTextBody($this->body)
  58 + ->send();
  59 + }
  60 +}
... ...
frontend/models/PasswordResetRequestForm.php 0 → 100644
  1 +++ a/frontend/models/PasswordResetRequestForm.php
  1 +<?php
  2 +namespace frontend\models;
  3 +
  4 +use Yii;
  5 +use yii\base\Model;
  6 +use common\models\User;
  7 +
  8 +/**
  9 + * Password reset request form
  10 + */
  11 +class PasswordResetRequestForm extends Model
  12 +{
  13 + public $email;
  14 +
  15 +
  16 + /**
  17 + * @inheritdoc
  18 + */
  19 + public function rules()
  20 + {
  21 + return [
  22 + ['email', 'trim'],
  23 + ['email', 'required'],
  24 + ['email', 'email'],
  25 + ['email', 'exist',
  26 + 'targetClass' => '\common\models\User',
  27 + 'filter' => ['status' => User::STATUS_ACTIVE],
  28 + 'message' => 'There is no user with such email.'
  29 + ],
  30 + ];
  31 + }
  32 +
  33 + /**
  34 + * Sends an email with a link, for resetting the password.
  35 + *
  36 + * @return bool whether the email was send
  37 + */
  38 + public function sendEmail()
  39 + {
  40 + /* @var $user User */
  41 + $user = User::findOne([
  42 + 'status' => User::STATUS_ACTIVE,
  43 + 'email' => $this->email,
  44 + ]);
  45 +
  46 + if (!$user) {
  47 + return false;
  48 + }
  49 +
  50 + if (!User::isPasswordResetTokenValid($user->password_reset_token)) {
  51 + $user->generatePasswordResetToken();
  52 + if (!$user->save()) {
  53 + return false;
  54 + }
  55 + }
  56 +
  57 + return Yii::$app
  58 + ->mailer
  59 + ->compose(
  60 + ['html' => 'passwordResetToken-html', 'text' => 'passwordResetToken-text'],
  61 + ['user' => $user]
  62 + )
  63 + ->setFrom([Yii::$app->params['supportEmail'] => Yii::$app->name . ' robot'])
  64 + ->setTo($this->email)
  65 + ->setSubject('Password reset for ' . Yii::$app->name)
  66 + ->send();
  67 + }
  68 +}
... ...
frontend/models/ResetPasswordForm.php 0 → 100644
  1 +++ a/frontend/models/ResetPasswordForm.php
  1 +<?php
  2 +namespace frontend\models;
  3 +
  4 +use yii\base\Model;
  5 +use yii\base\InvalidParamException;
  6 +use common\models\User;
  7 +
  8 +/**
  9 + * Password reset form
  10 + */
  11 +class ResetPasswordForm extends Model
  12 +{
  13 + public $password;
  14 +
  15 + /**
  16 + * @var \common\models\User
  17 + */
  18 + private $_user;
  19 +
  20 +
  21 + /**
  22 + * Creates a form model given a token.
  23 + *
  24 + * @param string $token
  25 + * @param array $config name-value pairs that will be used to initialize the object properties
  26 + * @throws \yii\base\InvalidParamException if token is empty or not valid
  27 + */
  28 + public function __construct($token, $config = [])
  29 + {
  30 + if (empty($token) || !is_string($token)) {
  31 + throw new InvalidParamException('Password reset token cannot be blank.');
  32 + }
  33 + $this->_user = User::findByPasswordResetToken($token);
  34 + if (!$this->_user) {
  35 + throw new InvalidParamException('Wrong password reset token.');
  36 + }
  37 + parent::__construct($config);
  38 + }
  39 +
  40 + /**
  41 + * @inheritdoc
  42 + */
  43 + public function rules()
  44 + {
  45 + return [
  46 + ['password', 'required'],
  47 + ['password', 'string', 'min' => 6],
  48 + ];
  49 + }
  50 +
  51 + /**
  52 + * Resets password.
  53 + *
  54 + * @return bool if password was reset.
  55 + */
  56 + public function resetPassword()
  57 + {
  58 + $user = $this->_user;
  59 + $user->setPassword($this->password);
  60 + $user->removePasswordResetToken();
  61 +
  62 + return $user->save(false);
  63 + }
  64 +}
... ...
frontend/models/SignupForm.php 0 → 100644
  1 +++ a/frontend/models/SignupForm.php
  1 +<?php
  2 +namespace frontend\models;
  3 +
  4 +use yii\base\Model;
  5 +use common\models\User;
  6 +
  7 +/**
  8 + * Signup form
  9 + */
  10 +class SignupForm extends Model
  11 +{
  12 + public $username;
  13 + public $email;
  14 + public $password;
  15 +
  16 +
  17 + /**
  18 + * @inheritdoc
  19 + */
  20 + public function rules()
  21 + {
  22 + return [
  23 + ['username', 'trim'],
  24 + ['username', 'required'],
  25 + ['username', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This username has already been taken.'],
  26 + ['username', 'string', 'min' => 2, 'max' => 255],
  27 +
  28 + ['email', 'trim'],
  29 + ['email', 'required'],
  30 + ['email', 'email'],
  31 + ['email', 'string', 'max' => 255],
  32 + ['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'],
  33 +
  34 + ['password', 'required'],
  35 + ['password', 'string', 'min' => 6],
  36 + ];
  37 + }
  38 +
  39 + /**
  40 + * Signs user up.
  41 + *
  42 + * @return User|null the saved model or null if saving fails
  43 + */
  44 + public function signup()
  45 + {
  46 + if (!$this->validate()) {
  47 + return null;
  48 + }
  49 +
  50 + $user = new User();
  51 + $user->username = $this->username;
  52 + $user->email = $this->email;
  53 + $user->setPassword($this->password);
  54 + $user->generateAuthKey();
  55 +
  56 + return $user->save() ? $user : null;
  57 + }
  58 +}
... ...
frontend/runtime/.gitignore 0 → 100644
  1 +++ a/frontend/runtime/.gitignore
  1 +*
  2 +!.gitignore
0 3 \ No newline at end of file
... ...
frontend/tests/_bootstrap.php 0 → 100644
  1 +++ a/frontend/tests/_bootstrap.php
  1 +<?php
  2 +defined('YII_DEBUG') or define('YII_DEBUG', true);
  3 +defined('YII_ENV') or define('YII_ENV', 'test');
  4 +defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', __DIR__.'/../../');
  5 +
  6 +require_once(YII_APP_BASE_PATH . '/vendor/autoload.php');
  7 +require_once(YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php');
  8 +require_once(YII_APP_BASE_PATH . '/common/config/bootstrap.php');
  9 +require_once(__DIR__ . '/../config/bootstrap.php');
... ...
frontend/tests/_data/login_data.php 0 → 100644
  1 +++ a/frontend/tests/_data/login_data.php
  1 +<?php
  2 +return [
  3 + [
  4 + 'username' => 'erau',
  5 + 'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI',
  6 + // password_0
  7 + 'password_hash' => '$2y$13$nJ1WDlBaGcbCdbNC5.5l4.sgy.OMEKCqtDQOdQ2OWpgiKRWYyzzne',
  8 + 'password_reset_token' => 'RkD_Jw0_8HEedzLk7MM-ZKEFfYR7VbMr_1392559490',
  9 + 'created_at' => '1392559490',
  10 + 'updated_at' => '1392559490',
  11 + 'email' => 'sfriesen@jenkins.info',
  12 + ],
  13 +];
... ...
frontend/tests/_data/user.php 0 → 100644
  1 +++ a/frontend/tests/_data/user.php
  1 +<?php
  2 +
  3 +return [
  4 + [
  5 + 'username' => 'okirlin',
  6 + 'auth_key' => 'iwTNae9t34OmnK6l4vT4IeaTk-YWI2Rv',
  7 + 'password_hash' => '$2y$13$CXT0Rkle1EMJ/c1l5bylL.EylfmQ39O5JlHJVFpNn618OUS1HwaIi',
  8 + 'password_reset_token' => 't5GU9NwpuGYSfb7FEZMAxqtuz2PkEvv_' . time(),
  9 + 'created_at' => '1391885313',
  10 + 'updated_at' => '1391885313',
  11 + 'email' => 'brady.renner@rutherford.com',
  12 + ],
  13 + [
  14 + 'username' => 'troy.becker',
  15 + 'auth_key' => 'EdKfXrx88weFMV0vIxuTMWKgfK2tS3Lp',
  16 + 'password_hash' => '$2y$13$g5nv41Px7VBqhS3hVsVN2.MKfgT3jFdkXEsMC4rQJLfaMa7VaJqL2',
  17 + 'password_reset_token' => '4BSNyiZNAuxjs5Mty990c47sVrgllIi_' . time(),
  18 + 'created_at' => '1391885313',
  19 + 'updated_at' => '1391885313',
  20 + 'email' => 'nicolas.dianna@hotmail.com',
  21 + 'status' => '0',
  22 + ],
  23 +];
... ...
frontend/tests/_output/.gitignore 0 → 100644
  1 +++ a/frontend/tests/_output/.gitignore
  1 +*
  2 +!.gitignore
... ...
frontend/tests/_support/.gitignore 0 → 100644
  1 +++ a/frontend/tests/_support/.gitignore
  1 +_generated
... ...
frontend/tests/_support/FunctionalTester.php 0 → 100644
  1 +++ a/frontend/tests/_support/FunctionalTester.php
  1 +<?php
  2 +namespace frontend\tests;
  3 +
  4 +/**
  5 + * Inherited Methods
  6 + * @method void wantToTest($text)
  7 + * @method void wantTo($text)
  8 + * @method void execute($callable)
  9 + * @method void expectTo($prediction)
  10 + * @method void expect($prediction)
  11 + * @method void amGoingTo($argumentation)
  12 + * @method void am($role)
  13 + * @method void lookForwardTo($achieveValue)
  14 + * @method void comment($description)
  15 + * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
  16 + *
  17 + * @SuppressWarnings(PHPMD)
  18 + */
  19 +class FunctionalTester extends \Codeception\Actor
  20 +{
  21 + use _generated\FunctionalTesterActions;
  22 +
  23 +
  24 + public function seeValidationError($message)
  25 + {
  26 + $this->see($message, '.help-block');
  27 + }
  28 +
  29 + public function dontSeeValidationError($message)
  30 + {
  31 + $this->dontSee($message, '.help-block');
  32 + }
  33 +}
... ...
frontend/tests/_support/UnitTester.php 0 → 100644
  1 +++ a/frontend/tests/_support/UnitTester.php
  1 +<?php
  2 +namespace frontend\tests;
  3 +
  4 +/**
  5 + * Inherited Methods
  6 + * @method void wantToTest($text)
  7 + * @method void wantTo($text)
  8 + * @method void execute($callable)
  9 + * @method void expectTo($prediction)
  10 + * @method void expect($prediction)
  11 + * @method void amGoingTo($argumentation)
  12 + * @method void am($role)
  13 + * @method void lookForwardTo($achieveValue)
  14 + * @method void comment($description)
  15 + * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
  16 + *
  17 + * @SuppressWarnings(PHPMD)
  18 + */
  19 +class UnitTester extends \Codeception\Actor
  20 +{
  21 + use _generated\UnitTesterActions;
  22 + /**
  23 + * Define custom actions here
  24 + */
  25 +}
... ...
frontend/tests/acceptance.suite.yml.example 0 → 100644
  1 +++ a/frontend/tests/acceptance.suite.yml.example
  1 +class_name: AcceptanceTester
  2 +modules:
  3 + enabled:
  4 + - WebDriver:
  5 + url: http://localhost:8080
  6 + browser: firefox
  7 + - Yii2:
  8 + part: init
... ...
frontend/tests/acceptance/HomeCest.php 0 → 100644
  1 +++ a/frontend/tests/acceptance/HomeCest.php
  1 +<?php
  2 +namespace frontend\tests\acceptance;
  3 +
  4 +use Yii;
  5 +use frontend\tests\AcceptanceTester;
  6 +use yii\helpers\Url;
  7 +
  8 +class HomeCest
  9 +{
  10 + public function checkHome(AcceptanceTester $I)
  11 + {
  12 + $I->amOnPage(Url::toRoute('/site/index'));
  13 + $I->see('My Company');
  14 + $I->seeLink('About');
  15 + $I->click('About');
  16 + $I->see('This is the About page.');
  17 + }
  18 +}
... ...
frontend/tests/acceptance/_bootstrap.php 0 → 100644
  1 +++ a/frontend/tests/acceptance/_bootstrap.php
  1 +<?php
... ...
frontend/tests/functional.suite.yml 0 → 100644
  1 +++ a/frontend/tests/functional.suite.yml
  1 +class_name: FunctionalTester
  2 +modules:
  3 + enabled:
  4 + - Filesystem
  5 + - Yii2
... ...
frontend/tests/functional/AboutCest.php 0 → 100644
  1 +++ a/frontend/tests/functional/AboutCest.php
  1 +<?php
  2 +namespace frontend\tests\functional;
  3 +
  4 +use frontend\tests\FunctionalTester;
  5 +
  6 +class AboutCest
  7 +{
  8 + public function checkAbout(FunctionalTester $I)
  9 + {
  10 + $I->amOnRoute('site/about');
  11 + $I->see('About', 'h1');
  12 + }
  13 +}
... ...
frontend/tests/functional/ContactCest.php 0 → 100644
  1 +++ a/frontend/tests/functional/ContactCest.php
  1 +<?php
  2 +namespace frontend\tests\functional;
  3 +
  4 +use frontend\tests\FunctionalTester;
  5 +
  6 +/* @var $scenario \Codeception\Scenario */
  7 +
  8 +class ContactCest
  9 +{
  10 + public function _before(FunctionalTester $I)
  11 + {
  12 + $I->amOnPage(['site/contact']);
  13 + }
  14 +
  15 + public function checkContact(FunctionalTester $I)
  16 + {
  17 + $I->see('Contact', 'h1');
  18 + }
  19 +
  20 + public function checkContactSubmitNoData(FunctionalTester $I)
  21 + {
  22 + $I->submitForm('#contact-form', []);
  23 + $I->see('Contact', 'h1');
  24 + $I->seeValidationError('Name cannot be blank');
  25 + $I->seeValidationError('Email cannot be blank');
  26 + $I->seeValidationError('Subject cannot be blank');
  27 + $I->seeValidationError('Body cannot be blank');
  28 + $I->seeValidationError('The verification code is incorrect');
  29 + }
  30 +
  31 + public function checkContactSubmitNotCorrectEmail(FunctionalTester $I)
  32 + {
  33 + $I->submitForm('#contact-form', [
  34 + 'ContactForm[name]' => 'tester',
  35 + 'ContactForm[email]' => 'tester.email',
  36 + 'ContactForm[subject]' => 'test subject',
  37 + 'ContactForm[body]' => 'test content',
  38 + 'ContactForm[verifyCode]' => 'testme',
  39 + ]);
  40 + $I->seeValidationError('Email is not a valid email address.');
  41 + $I->dontSeeValidationError('Name cannot be blank');
  42 + $I->dontSeeValidationError('Subject cannot be blank');
  43 + $I->dontSeeValidationError('Body cannot be blank');
  44 + $I->dontSeeValidationError('The verification code is incorrect');
  45 + }
  46 +
  47 + public function checkContactSubmitCorrectData(FunctionalTester $I)
  48 + {
  49 + $I->submitForm('#contact-form', [
  50 + 'ContactForm[name]' => 'tester',
  51 + 'ContactForm[email]' => 'tester@example.com',
  52 + 'ContactForm[subject]' => 'test subject',
  53 + 'ContactForm[body]' => 'test content',
  54 + 'ContactForm[verifyCode]' => 'testme',
  55 + ]);
  56 + $I->seeEmailIsSent();
  57 + $I->see('Thank you for contacting us. We will respond to you as soon as possible.');
  58 + }
  59 +}
... ...
frontend/tests/functional/HomeCest.php 0 → 100644
  1 +++ a/frontend/tests/functional/HomeCest.php
  1 +<?php
  2 +
  3 +namespace frontend\tests\functional;
  4 +
  5 +use frontend\tests\FunctionalTester;
  6 +
  7 +class HomeCest
  8 +{
  9 + public function checkOpen(FunctionalTester $I)
  10 + {
  11 + $I->amOnPage(\Yii::$app->homeUrl);
  12 + $I->see('My Company');
  13 + $I->seeLink('About');
  14 + $I->click('About');
  15 + $I->see('This is the About page.');
  16 + }
  17 +}
0 18 \ No newline at end of file
... ...
frontend/tests/functional/LoginCest.php 0 → 100644
  1 +++ a/frontend/tests/functional/LoginCest.php
  1 +<?php
  2 +
  3 +namespace frontend\tests\functional;
  4 +
  5 +use frontend\tests\FunctionalTester;
  6 +use common\fixtures\User as UserFixture;
  7 +
  8 +class LoginCest
  9 +{
  10 + function _before(FunctionalTester $I)
  11 + {
  12 + $I->haveFixtures([
  13 + 'user' => [
  14 + 'class' => UserFixture::className(),
  15 + 'dataFile' => codecept_data_dir() . 'login_data.php'
  16 + ]
  17 + ]);
  18 + $I->amOnRoute('site/login');
  19 + }
  20 +
  21 + protected function formParams($login, $password)
  22 + {
  23 + return [
  24 + 'LoginForm[username]' => $login,
  25 + 'LoginForm[password]' => $password,
  26 + ];
  27 + }
  28 +
  29 + public function checkEmpty(FunctionalTester $I)
  30 + {
  31 + $I->submitForm('#login-form', $this->formParams('', ''));
  32 + $I->seeValidationError('Username cannot be blank.');
  33 + $I->seeValidationError('Password cannot be blank.');
  34 + }
  35 +
  36 + public function checkWrongPassword(FunctionalTester $I)
  37 + {
  38 + $I->submitForm('#login-form', $this->formParams('admin', 'wrong'));
  39 + $I->seeValidationError('Incorrect username or password.');
  40 + }
  41 +
  42 + public function checkValidLogin(FunctionalTester $I)
  43 + {
  44 + $I->submitForm('#login-form', $this->formParams('erau', 'password_0'));
  45 + $I->see('Logout (erau)', 'form button[type=submit]');
  46 + $I->dontSeeLink('Login');
  47 + $I->dontSeeLink('Signup');
  48 + }
  49 +}
... ...
frontend/tests/functional/SignupCest.php 0 → 100644
  1 +++ a/frontend/tests/functional/SignupCest.php
  1 +<?php
  2 +
  3 +namespace frontend\tests\functional;
  4 +
  5 +use frontend\tests\FunctionalTester;
  6 +
  7 +class SignupCest
  8 +{
  9 + protected $formId = '#form-signup';
  10 +
  11 +
  12 + public function _before(FunctionalTester $I)
  13 + {
  14 + $I->amOnRoute('site/signup');
  15 + }
  16 +
  17 + public function signupWithEmptyFields(FunctionalTester $I)
  18 + {
  19 + $I->see('Signup', 'h1');
  20 + $I->see('Please fill out the following fields to signup:');
  21 + $I->submitForm($this->formId, []);
  22 + $I->seeValidationError('Username cannot be blank.');
  23 + $I->seeValidationError('Email cannot be blank.');
  24 + $I->seeValidationError('Password cannot be blank.');
  25 +
  26 + }
  27 +
  28 + public function signupWithWrongEmail(FunctionalTester $I)
  29 + {
  30 + $I->submitForm(
  31 + $this->formId, [
  32 + 'SignupForm[username]' => 'tester',
  33 + 'SignupForm[email]' => 'ttttt',
  34 + 'SignupForm[password]' => 'tester_password',
  35 + ]
  36 + );
  37 + $I->dontSee('Username cannot be blank.', '.help-block');
  38 + $I->dontSee('Password cannot be blank.', '.help-block');
  39 + $I->see('Email is not a valid email address.', '.help-block');
  40 + }
  41 +
  42 + public function signupSuccessfully(FunctionalTester $I)
  43 + {
  44 + $I->submitForm($this->formId, [
  45 + 'SignupForm[username]' => 'tester',
  46 + 'SignupForm[email]' => 'tester.email@example.com',
  47 + 'SignupForm[password]' => 'tester_password',
  48 + ]);
  49 +
  50 + $I->seeRecord('common\models\User', [
  51 + 'username' => 'tester',
  52 + 'email' => 'tester.email@example.com',
  53 + ]);
  54 +
  55 + $I->see('Logout (tester)', 'form button[type=submit]');
  56 + }
  57 +}
... ...
frontend/tests/functional/_bootstrap.php 0 → 100644
  1 +++ a/frontend/tests/functional/_bootstrap.php
  1 +<?php
... ...
frontend/tests/unit.suite.yml 0 → 100644
  1 +++ a/frontend/tests/unit.suite.yml
  1 +class_name: UnitTester
  2 +modules:
  3 + enabled:
  4 + - Yii2:
  5 + part: [orm, email, fixtures]
  6 + - Asserts
... ...
frontend/tests/unit/_bootstrap.php 0 → 100644
  1 +++ a/frontend/tests/unit/_bootstrap.php
  1 +<?php
  2 +// Here you can initialize variables that will for your tests
... ...
frontend/tests/unit/models/ContactFormTest.php 0 → 100644
  1 +++ a/frontend/tests/unit/models/ContactFormTest.php
  1 +<?php
  2 +namespace frontend\tests\unit\models;
  3 +
  4 +use Yii;
  5 +use frontend\models\ContactForm;
  6 +
  7 +class ContactFormTest extends \Codeception\Test\Unit
  8 +{
  9 + public function testSendEmail()
  10 + {
  11 + $model = new ContactForm();
  12 +
  13 + $model->attributes = [
  14 + 'name' => 'Tester',
  15 + 'email' => 'tester@example.com',
  16 + 'subject' => 'very important letter subject',
  17 + 'body' => 'body of current message',
  18 + ];
  19 +
  20 + expect_that($model->sendEmail('admin@example.com'));
  21 +
  22 + // using Yii2 module actions to check email was sent
  23 + $this->tester->seeEmailIsSent();
  24 +
  25 + $emailMessage = $this->tester->grabLastSentEmail();
  26 + expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface');
  27 + expect($emailMessage->getTo())->hasKey('admin@example.com');
  28 + expect($emailMessage->getFrom())->hasKey('tester@example.com');
  29 + expect($emailMessage->getSubject())->equals('very important letter subject');
  30 + expect($emailMessage->toString())->contains('body of current message');
  31 + }
  32 +}
... ...
frontend/tests/unit/models/PasswordResetRequestFormTest.php 0 → 100644
  1 +++ a/frontend/tests/unit/models/PasswordResetRequestFormTest.php
  1 +<?php
  2 +
  3 +namespace frontend\tests\unit\models;
  4 +
  5 +use Yii;
  6 +use frontend\models\PasswordResetRequestForm;
  7 +use common\fixtures\User as UserFixture;
  8 +use common\models\User;
  9 +
  10 +class PasswordResetRequestFormTest extends \Codeception\Test\Unit
  11 +{
  12 + /**
  13 + * @var \frontend\tests\UnitTester
  14 + */
  15 + protected $tester;
  16 +
  17 +
  18 + public function _before()
  19 + {
  20 + $this->tester->haveFixtures([
  21 + 'user' => [
  22 + 'class' => UserFixture::className(),
  23 + 'dataFile' => codecept_data_dir() . 'user.php'
  24 + ]
  25 + ]);
  26 + }
  27 +
  28 + public function testSendMessageWithWrongEmailAddress()
  29 + {
  30 + $model = new PasswordResetRequestForm();
  31 + $model->email = 'not-existing-email@example.com';
  32 + expect_not($model->sendEmail());
  33 + }
  34 +
  35 + public function testNotSendEmailsToInactiveUser()
  36 + {
  37 + $user = $this->tester->grabFixture('user', 1);
  38 + $model = new PasswordResetRequestForm();
  39 + $model->email = $user['email'];
  40 + expect_not($model->sendEmail());
  41 + }
  42 +
  43 + public function testSendEmailSuccessfully()
  44 + {
  45 + $userFixture = $this->tester->grabFixture('user', 0);
  46 +
  47 + $model = new PasswordResetRequestForm();
  48 + $model->email = $userFixture['email'];
  49 + $user = User::findOne(['password_reset_token' => $userFixture['password_reset_token']]);
  50 +
  51 + expect_that($model->sendEmail());
  52 + expect_that($user->password_reset_token);
  53 +
  54 + $emailMessage = $this->tester->grabLastSentEmail();
  55 + expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface');
  56 + expect($emailMessage->getTo())->hasKey($model->email);
  57 + expect($emailMessage->getFrom())->hasKey(Yii::$app->params['supportEmail']);
  58 + }
  59 +}
... ...
frontend/tests/unit/models/ResetPasswordFormTest.php 0 → 100644
  1 +++ a/frontend/tests/unit/models/ResetPasswordFormTest.php
  1 +<?php
  2 +
  3 +namespace frontend\tests\unit\models;
  4 +
  5 +use common\fixtures\User as UserFixture;
  6 +use frontend\models\ResetPasswordForm;
  7 +
  8 +class ResetPasswordFormTest extends \Codeception\Test\Unit
  9 +{
  10 + /**
  11 + * @var \frontend\tests\UnitTester
  12 + */
  13 + protected $tester;
  14 +
  15 +
  16 + public function _before()
  17 + {
  18 + $this->tester->haveFixtures([
  19 + 'user' => [
  20 + 'class' => UserFixture::className(),
  21 + 'dataFile' => codecept_data_dir() . 'user.php'
  22 + ],
  23 + ]);
  24 + }
  25 +
  26 + public function testResetWrongToken()
  27 + {
  28 + $this->tester->expectException('yii\base\InvalidParamException', function() {
  29 + new ResetPasswordForm('');
  30 + });
  31 +
  32 + $this->tester->expectException('yii\base\InvalidParamException', function() {
  33 + new ResetPasswordForm('notexistingtoken_1391882543');
  34 + });
  35 + }
  36 +
  37 + public function testResetCorrectToken()
  38 + {
  39 + $user = $this->tester->grabFixture('user', 0);
  40 + $form = new ResetPasswordForm($user['password_reset_token']);
  41 + expect_that($form->resetPassword());
  42 + }
  43 +
  44 +}
... ...
frontend/tests/unit/models/SignupFormTest.php 0 → 100644
  1 +++ a/frontend/tests/unit/models/SignupFormTest.php
  1 +<?php
  2 +namespace frontend\tests\unit\models;
  3 +
  4 +use common\fixtures\User as UserFixture;
  5 +use frontend\models\SignupForm;
  6 +
  7 +class SignupFormTest extends \Codeception\Test\Unit
  8 +{
  9 + /**
  10 + * @var \frontend\tests\UnitTester
  11 + */
  12 + protected $tester;
  13 +
  14 +
  15 + public function _before()
  16 + {
  17 + $this->tester->haveFixtures([
  18 + 'user' => [
  19 + 'class' => UserFixture::className(),
  20 + 'dataFile' => codecept_data_dir() . 'user.php'
  21 + ]
  22 + ]);
  23 + }
  24 +
  25 + public function testCorrectSignup()
  26 + {
  27 + $model = new SignupForm([
  28 + 'username' => 'some_username',
  29 + 'email' => 'some_email@example.com',
  30 + 'password' => 'some_password',
  31 + ]);
  32 +
  33 + $user = $model->signup();
  34 +
  35 + expect($user)->isInstanceOf('common\models\User');
  36 +
  37 + expect($user->username)->equals('some_username');
  38 + expect($user->email)->equals('some_email@example.com');
  39 + expect($user->validatePassword('some_password'))->true();
  40 + }
  41 +
  42 + public function testNotCorrectSignup()
  43 + {
  44 + $model = new SignupForm([
  45 + 'username' => 'troy.becker',
  46 + 'email' => 'nicolas.dianna@hotmail.com',
  47 + 'password' => 'some_password',
  48 + ]);
  49 +
  50 + expect_not($model->signup());
  51 + expect_that($model->getErrors('username'));
  52 + expect_that($model->getErrors('email'));
  53 +
  54 + expect($model->getFirstError('username'))
  55 + ->equals('This username has already been taken.');
  56 + expect($model->getFirstError('email'))
  57 + ->equals('This email address has already been taken.');
  58 + }
  59 +}
... ...
frontend/views/layouts/main.php 0 → 100644
  1 +++ a/frontend/views/layouts/main.php
  1 +<?php
  2 +
  3 +/* @var $this \yii\web\View */
  4 +/* @var $content string */
  5 +
  6 +use yii\helpers\Html;
  7 +use yii\bootstrap\Nav;
  8 +use yii\bootstrap\NavBar;
  9 +use yii\widgets\Breadcrumbs;
  10 +use frontend\assets\AppAsset;
  11 +use common\widgets\Alert;
  12 +
  13 +AppAsset::register($this);
  14 +?>
  15 +<?php $this->beginPage() ?>
  16 +<!DOCTYPE html>
  17 +<html lang="<?= Yii::$app->language ?>">
  18 +<head>
  19 + <meta charset="<?= Yii::$app->charset ?>">
  20 + <meta name="viewport" content="width=device-width, initial-scale=1">
  21 + <?= Html::csrfMetaTags() ?>
  22 + <title><?= Html::encode($this->title) ?></title>
  23 + <?php $this->head() ?>
  24 +</head>
  25 +<body>
  26 +<?php $this->beginBody() ?>
  27 +
  28 +<div class="wrap">
  29 + <?php
  30 + NavBar::begin([
  31 + 'brandLabel' => 'My Company',
  32 + 'brandUrl' => Yii::$app->homeUrl,
  33 + 'options' => [
  34 + 'class' => 'navbar-inverse navbar-fixed-top',
  35 + ],
  36 + ]);
  37 + $menuItems = [
  38 + ['label' => 'Home', 'url' => ['/site/index']],
  39 + ['label' => 'About', 'url' => ['/site/about']],
  40 + ['label' => 'Contact', 'url' => ['/site/contact']],
  41 + ];
  42 + if (Yii::$app->user->isGuest) {
  43 + $menuItems[] = ['label' => 'Signup', 'url' => ['/site/signup']];
  44 + $menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];
  45 + } else {
  46 + $menuItems[] = '<li>'
  47 + . Html::beginForm(['/site/logout'], 'post')
  48 + . Html::submitButton(
  49 + 'Logout (' . Yii::$app->user->identity->username . ')',
  50 + ['class' => 'btn btn-link logout']
  51 + )
  52 + . Html::endForm()
  53 + . '</li>';
  54 + }
  55 + echo Nav::widget([
  56 + 'options' => ['class' => 'navbar-nav navbar-right'],
  57 + 'items' => $menuItems,
  58 + ]);
  59 + NavBar::end();
  60 + ?>
  61 +
  62 + <div class="container">
  63 + <?= Breadcrumbs::widget([
  64 + 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
  65 + ]) ?>
  66 + <?= Alert::widget() ?>
  67 + <?= $content ?>
  68 + </div>
  69 +</div>
  70 +
  71 +<footer class="footer">
  72 + <div class="container">
  73 + <p class="pull-left">&copy; My Company <?= date('Y') ?></p>
  74 +
  75 + <p class="pull-right"><?= Yii::powered() ?></p>
  76 + </div>
  77 +</footer>
  78 +
  79 +<?php $this->endBody() ?>
  80 +</body>
  81 +</html>
  82 +<?php $this->endPage() ?>
... ...
frontend/views/site/about.php 0 → 100644
  1 +++ a/frontend/views/site/about.php
  1 +<?php
  2 +
  3 +/* @var $this yii\web\View */
  4 +
  5 +use yii\helpers\Html;
  6 +
  7 +$this->title = 'About';
  8 +$this->params['breadcrumbs'][] = $this->title;
  9 +?>
  10 +<div class="site-about">
  11 + <h1><?= Html::encode($this->title) ?></h1>
  12 +
  13 + <p>This is the About page. You may modify the following file to customize its content:</p>
  14 +
  15 + <code><?= __FILE__ ?></code>
  16 +</div>
... ...
frontend/views/site/contact.php 0 → 100644
  1 +++ a/frontend/views/site/contact.php
  1 +<?php
  2 +
  3 +/* @var $this yii\web\View */
  4 +/* @var $form yii\bootstrap\ActiveForm */
  5 +/* @var $model \frontend\models\ContactForm */
  6 +
  7 +use yii\helpers\Html;
  8 +use yii\bootstrap\ActiveForm;
  9 +use yii\captcha\Captcha;
  10 +
  11 +$this->title = 'Contact';
  12 +$this->params['breadcrumbs'][] = $this->title;
  13 +?>
  14 +<div class="site-contact">
  15 + <h1><?= Html::encode($this->title) ?></h1>
  16 +
  17 + <p>
  18 + If you have business inquiries or other questions, please fill out the following form to contact us. Thank you.
  19 + </p>
  20 +
  21 + <div class="row">
  22 + <div class="col-lg-5">
  23 + <?php $form = ActiveForm::begin(['id' => 'contact-form']); ?>
  24 +
  25 + <?= $form->field($model, 'name')->textInput(['autofocus' => true]) ?>
  26 +
  27 + <?= $form->field($model, 'email') ?>
  28 +
  29 + <?= $form->field($model, 'subject') ?>
  30 +
  31 + <?= $form->field($model, 'body')->textarea(['rows' => 6]) ?>
  32 +
  33 + <?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [
  34 + 'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>',
  35 + ]) ?>
  36 +
  37 + <div class="form-group">
  38 + <?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?>
  39 + </div>
  40 +
  41 + <?php ActiveForm::end(); ?>
  42 + </div>
  43 + </div>
  44 +
  45 +</div>
... ...
frontend/views/site/error.php 0 → 100644
  1 +++ a/frontend/views/site/error.php
  1 +<?php
  2 +
  3 +/* @var $this yii\web\View */
  4 +/* @var $name string */
  5 +/* @var $message string */
  6 +/* @var $exception Exception */
  7 +
  8 +use yii\helpers\Html;
  9 +
  10 +$this->title = $name;
  11 +?>
  12 +<div class="site-error">
  13 +
  14 + <h1><?= Html::encode($this->title) ?></h1>
  15 +
  16 + <div class="alert alert-danger">
  17 + <?= nl2br(Html::encode($message)) ?>
  18 + </div>
  19 +
  20 + <p>
  21 + The above error occurred while the Web server was processing your request.
  22 + </p>
  23 + <p>
  24 + Please contact us if you think this is a server error. Thank you.
  25 + </p>
  26 +
  27 +</div>
... ...
frontend/views/site/index.php 0 → 100644
  1 +++ a/frontend/views/site/index.php
  1 +<?php
  2 +
  3 +/* @var $this yii\web\View */
  4 +
  5 +$this->title = 'My Yii Application';
  6 +?>
  7 +<div class="site-index">
  8 +
  9 + <div class="jumbotron">
  10 + <h1>Congratulations!</h1>
  11 +
  12 + <p class="lead">You have successfully created your Yii-powered application.</p>
  13 +
  14 + <p><a class="btn btn-lg btn-success" href="http://www.yiiframework.com">Get started with Yii</a></p>
  15 + </div>
  16 +
  17 + <div class="body-content">
  18 +
  19 + <div class="row">
  20 + <div class="col-lg-4">
  21 + <h2>Heading</h2>
  22 +
  23 + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
  24 + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
  25 + ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
  26 + fugiat nulla pariatur.</p>
  27 +
  28 + <p><a class="btn btn-default" href="http://www.yiiframework.com/doc/">Yii Documentation &raquo;</a></p>
  29 + </div>
  30 + <div class="col-lg-4">
  31 + <h2>Heading</h2>
  32 +
  33 + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
  34 + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
  35 + ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
  36 + fugiat nulla pariatur.</p>
  37 +
  38 + <p><a class="btn btn-default" href="http://www.yiiframework.com/forum/">Yii Forum &raquo;</a></p>
  39 + </div>
  40 + <div class="col-lg-4">
  41 + <h2>Heading</h2>
  42 +
  43 + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
  44 + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
  45 + ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
  46 + fugiat nulla pariatur.</p>
  47 +
  48 + <p><a class="btn btn-default" href="http://www.yiiframework.com/extensions/">Yii Extensions &raquo;</a></p>
  49 + </div>
  50 + </div>
  51 +
  52 + </div>
  53 +</div>
... ...
frontend/views/site/login.php 0 → 100644
  1 +++ a/frontend/views/site/login.php
  1 +<?php
  2 +
  3 +/* @var $this yii\web\View */
  4 +/* @var $form yii\bootstrap\ActiveForm */
  5 +/* @var $model \common\models\LoginForm */
  6 +
  7 +use yii\helpers\Html;
  8 +use yii\bootstrap\ActiveForm;
  9 +
  10 +$this->title = 'Login';
  11 +$this->params['breadcrumbs'][] = $this->title;
  12 +?>
  13 +<div class="site-login">
  14 + <h1><?= Html::encode($this->title) ?></h1>
  15 +
  16 + <p>Please fill out the following fields to login:</p>
  17 +
  18 + <div class="row">
  19 + <div class="col-lg-5">
  20 + <?php $form = ActiveForm::begin(['id' => 'login-form']); ?>
  21 +
  22 + <?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
  23 +
  24 + <?= $form->field($model, 'password')->passwordInput() ?>
  25 +
  26 + <?= $form->field($model, 'rememberMe')->checkbox() ?>
  27 +
  28 + <div style="color:#999;margin:1em 0">
  29 + If you forgot your password you can <?= Html::a('reset it', ['site/request-password-reset']) ?>.
  30 + </div>
  31 +
  32 + <div class="form-group">
  33 + <?= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
  34 + </div>
  35 +
  36 + <?php ActiveForm::end(); ?>
  37 + </div>
  38 + </div>
  39 +</div>
... ...
frontend/views/site/requestPasswordResetToken.php 0 → 100644
  1 +++ a/frontend/views/site/requestPasswordResetToken.php
  1 +<?php
  2 +
  3 +/* @var $this yii\web\View */
  4 +/* @var $form yii\bootstrap\ActiveForm */
  5 +/* @var $model \frontend\models\PasswordResetRequestForm */
  6 +
  7 +use yii\helpers\Html;
  8 +use yii\bootstrap\ActiveForm;
  9 +
  10 +$this->title = 'Request password reset';
  11 +$this->params['breadcrumbs'][] = $this->title;
  12 +?>
  13 +<div class="site-request-password-reset">
  14 + <h1><?= Html::encode($this->title) ?></h1>
  15 +
  16 + <p>Please fill out your email. A link to reset password will be sent there.</p>
  17 +
  18 + <div class="row">
  19 + <div class="col-lg-5">
  20 + <?php $form = ActiveForm::begin(['id' => 'request-password-reset-form']); ?>
  21 +
  22 + <?= $form->field($model, 'email')->textInput(['autofocus' => true]) ?>
  23 +
  24 + <div class="form-group">
  25 + <?= Html::submitButton('Send', ['class' => 'btn btn-primary']) ?>
  26 + </div>
  27 +
  28 + <?php ActiveForm::end(); ?>
  29 + </div>
  30 + </div>
  31 +</div>
... ...
frontend/views/site/resetPassword.php 0 → 100644
  1 +++ a/frontend/views/site/resetPassword.php
  1 +<?php
  2 +
  3 +/* @var $this yii\web\View */
  4 +/* @var $form yii\bootstrap\ActiveForm */
  5 +/* @var $model \frontend\models\ResetPasswordForm */
  6 +
  7 +use yii\helpers\Html;
  8 +use yii\bootstrap\ActiveForm;
  9 +
  10 +$this->title = 'Reset password';
  11 +$this->params['breadcrumbs'][] = $this->title;
  12 +?>
  13 +<div class="site-reset-password">
  14 + <h1><?= Html::encode($this->title) ?></h1>
  15 +
  16 + <p>Please choose your new password:</p>
  17 +
  18 + <div class="row">
  19 + <div class="col-lg-5">
  20 + <?php $form = ActiveForm::begin(['id' => 'reset-password-form']); ?>
  21 +
  22 + <?= $form->field($model, 'password')->passwordInput(['autofocus' => true]) ?>
  23 +
  24 + <div class="form-group">
  25 + <?= Html::submitButton('Save', ['class' => 'btn btn-primary']) ?>
  26 + </div>
  27 +
  28 + <?php ActiveForm::end(); ?>
  29 + </div>
  30 + </div>
  31 +</div>
... ...
frontend/views/site/signup.php 0 → 100644
  1 +++ a/frontend/views/site/signup.php
  1 +<?php
  2 +
  3 +/* @var $this yii\web\View */
  4 +/* @var $form yii\bootstrap\ActiveForm */
  5 +/* @var $model \frontend\models\SignupForm */
  6 +
  7 +use yii\helpers\Html;
  8 +use yii\bootstrap\ActiveForm;
  9 +
  10 +$this->title = 'Signup';
  11 +$this->params['breadcrumbs'][] = $this->title;
  12 +?>
  13 +<div class="site-signup">
  14 + <h1><?= Html::encode($this->title) ?></h1>
  15 +
  16 + <p>Please fill out the following fields to signup:</p>
  17 +
  18 + <div class="row">
  19 + <div class="col-lg-5">
  20 + <?php $form = ActiveForm::begin(['id' => 'form-signup']); ?>
  21 +
  22 + <?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
  23 +
  24 + <?= $form->field($model, 'email') ?>
  25 +
  26 + <?= $form->field($model, 'password')->passwordInput() ?>
  27 +
  28 + <div class="form-group">
  29 + <?= Html::submitButton('Signup', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?>
  30 + </div>
  31 +
  32 + <?php ActiveForm::end(); ?>
  33 + </div>
  34 + </div>
  35 +</div>
... ...
frontend/web/.gitignore 0 → 100644
  1 +++ a/frontend/web/.gitignore
  1 +/index.php
  2 +/index-test.php
... ...
frontend/web/assets/.gitignore 0 → 100644
  1 +++ a/frontend/web/assets/.gitignore
  1 +*
  2 +!.gitignore
... ...
frontend/web/css/site.css 0 → 100644
  1 +++ a/frontend/web/css/site.css
  1 +html,
  2 +body {
  3 + height: 100%;
  4 +}
  5 +
  6 +.wrap {
  7 + min-height: 100%;
  8 + height: auto;
  9 + margin: 0 auto -60px;
  10 + padding: 0 0 60px;
  11 +}
  12 +
  13 +.wrap > .container {
  14 + padding: 70px 15px 20px;
  15 +}
  16 +
  17 +.footer {
  18 + height: 60px;
  19 + background-color: #f5f5f5;
  20 + border-top: 1px solid #ddd;
  21 + padding-top: 20px;
  22 +}
  23 +
  24 +.jumbotron {
  25 + text-align: center;
  26 + background-color: transparent;
  27 +}
  28 +
  29 +.jumbotron .btn {
  30 + font-size: 21px;
  31 + padding: 14px 24px;
  32 +}
  33 +
  34 +.not-set {
  35 + color: #c55;
  36 + font-style: italic;
  37 +}
  38 +
  39 +/* add sorting icons to gridview sort links */
  40 +a.asc:after, a.desc:after {
  41 + position: relative;
  42 + top: 1px;
  43 + display: inline-block;
  44 + font-family: 'Glyphicons Halflings';
  45 + font-style: normal;
  46 + font-weight: normal;
  47 + line-height: 1;
  48 + padding-left: 5px;
  49 +}
  50 +
  51 +a.asc:after {
  52 + content: "\e151";
  53 +}
  54 +
  55 +a.desc:after {
  56 + content: "\e152";
  57 +}
  58 +
  59 +.sort-numerical a.asc:after {
  60 + content: "\e153";
  61 +}
  62 +
  63 +.sort-numerical a.desc:after {
  64 + content: "\e154";
  65 +}
  66 +
  67 +.sort-ordinal a.asc:after {
  68 + content: "\e155";
  69 +}
  70 +
  71 +.sort-ordinal a.desc:after {
  72 + content: "\e156";
  73 +}
  74 +
  75 +.grid-view td {
  76 + white-space: nowrap;
  77 +}
  78 +
  79 +.grid-view .filters input,
  80 +.grid-view .filters select {
  81 + min-width: 50px;
  82 +}
  83 +
  84 +.hint-block {
  85 + display: block;
  86 + margin-top: 5px;
  87 + color: #999;
  88 +}
  89 +
  90 +.error-summary {
  91 + color: #a94442;
  92 + background: #fdf7f7;
  93 + border-left: 3px solid #eed3d7;
  94 + padding: 10px 20px;
  95 + margin: 0 0 15px 0;
  96 +}
  97 +
  98 +/* align the logout "link" (button in form) of the navbar */
  99 +.nav li > form > button.logout {
  100 + padding: 15px;
  101 + border: none;
  102 +}
  103 +
  104 +@media(max-width:767px) {
  105 + .nav li > form > button.logout {
  106 + display:block;
  107 + text-align: left;
  108 + width: 100%;
  109 + padding: 10px 15px;
  110 + }
  111 +}
  112 +
  113 +.nav > li > form > button.logout:focus,
  114 +.nav > li > form > button.logout:hover {
  115 + text-decoration: none;
  116 +}
  117 +
  118 +.nav > li > form > button.logout:focus {
  119 + outline: none;
  120 +}
... ...
frontend/web/favicon.ico 0 → 100644
No preview for this file type
frontend/web/robots.txt 0 → 100644
  1 +++ a/frontend/web/robots.txt
  1 +User-agent: *
  2 +Disallow:
0 3 \ No newline at end of file
... ...
init 0 → 100755
  1 +++ a/init
  1 +#!/usr/bin/env php
  2 +<?php
  3 +/**
  4 + * Yii Application Initialization Tool
  5 + *
  6 + * In order to run in non-interactive mode:
  7 + *
  8 + * init --env=Development --overwrite=n
  9 + *
  10 + * @author Alexander Makarov <sam@rmcreative.ru>
  11 + *
  12 + * @link http://www.yiiframework.com/
  13 + * @copyright Copyright (c) 2008 Yii Software LLC
  14 + * @license http://www.yiiframework.com/license/
  15 + */
  16 +
  17 +if (!extension_loaded('openssl')) {
  18 + die('The OpenSSL PHP extension is required by Yii2.');
  19 +}
  20 +
  21 +$params = getParams();
  22 +$root = str_replace('\\', '/', __DIR__);
  23 +$envs = require("$root/environments/index.php");
  24 +$envNames = array_keys($envs);
  25 +
  26 +echo "Yii Application Initialization Tool v1.0\n\n";
  27 +
  28 +$envName = null;
  29 +if (empty($params['env']) || $params['env'] === '1') {
  30 + echo "Which environment do you want the application to be initialized in?\n\n";
  31 + foreach ($envNames as $i => $name) {
  32 + echo " [$i] $name\n";
  33 + }
  34 + echo "\n Your choice [0-" . (count($envs) - 1) . ', or "q" to quit] ';
  35 + $answer = trim(fgets(STDIN));
  36 +
  37 + if (!ctype_digit($answer) || !in_array($answer, range(0, count($envs) - 1))) {
  38 + echo "\n Quit initialization.\n";
  39 + exit(0);
  40 + }
  41 +
  42 + if (isset($envNames[$answer])) {
  43 + $envName = $envNames[$answer];
  44 + }
  45 +} else {
  46 + $envName = $params['env'];
  47 +}
  48 +
  49 +if (!in_array($envName, $envNames)) {
  50 + $envsList = implode(', ', $envNames);
  51 + echo "\n $envName is not a valid environment. Try one of the following: $envsList. \n";
  52 + exit(2);
  53 +}
  54 +
  55 +$env = $envs[$envName];
  56 +
  57 +if (empty($params['env'])) {
  58 + echo "\n Initialize the application under '{$envNames[$answer]}' environment? [yes|no] ";
  59 + $answer = trim(fgets(STDIN));
  60 + if (strncasecmp($answer, 'y', 1)) {
  61 + echo "\n Quit initialization.\n";
  62 + exit(0);
  63 + }
  64 +}
  65 +
  66 +echo "\n Start initialization ...\n\n";
  67 +$files = getFileList("$root/environments/{$env['path']}");
  68 +if (isset($env['skipFiles'])) {
  69 + $skipFiles = $env['skipFiles'];
  70 + array_walk($skipFiles, function(&$value) use($env, $root) { $value = "$root/$value"; });
  71 + $files = array_diff($files, array_intersect_key($env['skipFiles'], array_filter($skipFiles, 'file_exists')));
  72 +}
  73 +$all = false;
  74 +foreach ($files as $file) {
  75 + if (!copyFile($root, "environments/{$env['path']}/$file", $file, $all, $params)) {
  76 + break;
  77 + }
  78 +}
  79 +
  80 +$callbacks = ['setCookieValidationKey', 'setWritable', 'setExecutable', 'createSymlink'];
  81 +foreach ($callbacks as $callback) {
  82 + if (!empty($env[$callback])) {
  83 + $callback($root, $env[$callback]);
  84 + }
  85 +}
  86 +
  87 +echo "\n ... initialization completed.\n\n";
  88 +
  89 +function getFileList($root, $basePath = '')
  90 +{
  91 + $files = [];
  92 + $handle = opendir($root);
  93 + while (($path = readdir($handle)) !== false) {
  94 + if ($path === '.git' || $path === '.svn' || $path === '.' || $path === '..') {
  95 + continue;
  96 + }
  97 + $fullPath = "$root/$path";
  98 + $relativePath = $basePath === '' ? $path : "$basePath/$path";
  99 + if (is_dir($fullPath)) {
  100 + $files = array_merge($files, getFileList($fullPath, $relativePath));
  101 + } else {
  102 + $files[] = $relativePath;
  103 + }
  104 + }
  105 + closedir($handle);
  106 + return $files;
  107 +}
  108 +
  109 +function copyFile($root, $source, $target, &$all, $params)
  110 +{
  111 + if (!is_file($root . '/' . $source)) {
  112 + echo " skip $target ($source not exist)\n";
  113 + return true;
  114 + }
  115 + if (is_file($root . '/' . $target)) {
  116 + if (file_get_contents($root . '/' . $source) === file_get_contents($root . '/' . $target)) {
  117 + echo " unchanged $target\n";
  118 + return true;
  119 + }
  120 + if ($all) {
  121 + echo " overwrite $target\n";
  122 + } else {
  123 + echo " exist $target\n";
  124 + echo " ...overwrite? [Yes|No|All|Quit] ";
  125 +
  126 +
  127 + $answer = !empty($params['overwrite']) ? $params['overwrite'] : trim(fgets(STDIN));
  128 + if (!strncasecmp($answer, 'q', 1)) {
  129 + return false;
  130 + } else {
  131 + if (!strncasecmp($answer, 'y', 1)) {
  132 + echo " overwrite $target\n";
  133 + } else {
  134 + if (!strncasecmp($answer, 'a', 1)) {
  135 + echo " overwrite $target\n";
  136 + $all = true;
  137 + } else {
  138 + echo " skip $target\n";
  139 + return true;
  140 + }
  141 + }
  142 + }
  143 + }
  144 + file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
  145 + return true;
  146 + }
  147 + echo " generate $target\n";
  148 + @mkdir(dirname($root . '/' . $target), 0777, true);
  149 + file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
  150 + return true;
  151 +}
  152 +
  153 +function getParams()
  154 +{
  155 + $rawParams = [];
  156 + if (isset($_SERVER['argv'])) {
  157 + $rawParams = $_SERVER['argv'];
  158 + array_shift($rawParams);
  159 + }
  160 +
  161 + $params = [];
  162 + foreach ($rawParams as $param) {
  163 + if (preg_match('/^--(\w+)(=(.*))?$/', $param, $matches)) {
  164 + $name = $matches[1];
  165 + $params[$name] = isset($matches[3]) ? $matches[3] : true;
  166 + } else {
  167 + $params[] = $param;
  168 + }
  169 + }
  170 + return $params;
  171 +}
  172 +
  173 +function setWritable($root, $paths)
  174 +{
  175 + foreach ($paths as $writable) {
  176 + if (is_dir("$root/$writable")) {
  177 + if (@chmod("$root/$writable", 0777)) {
  178 + echo " chmod 0777 $writable\n";
  179 + } else {
  180 + printError("Operation chmod not permitted for directory $writable.");
  181 + }
  182 + } else {
  183 + printError("Directory $writable does not exist.");
  184 + }
  185 + }
  186 +}
  187 +
  188 +function setExecutable($root, $paths)
  189 +{
  190 + foreach ($paths as $executable) {
  191 + if (file_exists("$root/$executable")) {
  192 + if (@chmod("$root/$executable", 0755)) {
  193 + echo " chmod 0755 $executable\n";
  194 + } else {
  195 + printError("Operation chmod not permitted for $executable.");
  196 + }
  197 + } else {
  198 + printError("$executable does not exist.");
  199 + }
  200 + }
  201 +}
  202 +
  203 +function setCookieValidationKey($root, $paths)
  204 +{
  205 + foreach ($paths as $file) {
  206 + echo " generate cookie validation key in $file\n";
  207 + $file = $root . '/' . $file;
  208 + $length = 32;
  209 + $bytes = openssl_random_pseudo_bytes($length);
  210 + $key = strtr(substr(base64_encode($bytes), 0, $length), '+/=', '_-.');
  211 + $content = preg_replace('/(("|\')cookieValidationKey("|\')\s*=>\s*)(""|\'\')/', "\\1'$key'", file_get_contents($file));
  212 + file_put_contents($file, $content);
  213 + }
  214 +}
  215 +
  216 +function createSymlink($root, $links)
  217 +{
  218 + foreach ($links as $link => $target) {
  219 + //first removing folders to avoid errors if the folder already exists
  220 + @rmdir($root . "/" . $link);
  221 + //next removing existing symlink in order to update the target
  222 + if (is_link($root . "/" . $link)) {
  223 + @unlink($root . "/" . $link);
  224 + }
  225 + if (@symlink($root . "/" . $target, $root . "/" . $link)) {
  226 + echo " symlink $root/$target $root/$link\n";
  227 + } else {
  228 + printError("Cannot create symlink $root/$target $root/$link.");
  229 + }
  230 + }
  231 +}
  232 +
  233 +/**
  234 + * Prints error message.
  235 + * @param string $message message
  236 + */
  237 +function printError($message)
  238 +{
  239 + echo "\n " . formatMessage("Error. $message", ['fg-red']) . " \n";
  240 +}
  241 +
  242 +/**
  243 + * Returns true if the stream supports colorization. ANSI colors are disabled if not supported by the stream.
  244 + *
  245 + * - windows without ansicon
  246 + * - not tty consoles
  247 + *
  248 + * @return boolean true if the stream supports ANSI colors, otherwise false.
  249 + */
  250 +function ansiColorsSupported()
  251 +{
  252 + return DIRECTORY_SEPARATOR === '\\'
  253 + ? getenv('ANSICON') !== false || getenv('ConEmuANSI') === 'ON'
  254 + : function_exists('posix_isatty') && @posix_isatty(STDOUT);
  255 +}
  256 +
  257 +/**
  258 + * Get ANSI code of style.
  259 + * @param string $name style name
  260 + * @return integer ANSI code of style.
  261 + */
  262 +function getStyleCode($name)
  263 +{
  264 + $styles = [
  265 + 'bold' => 1,
  266 + 'fg-black' => 30,
  267 + 'fg-red' => 31,
  268 + 'fg-green' => 32,
  269 + 'fg-yellow' => 33,
  270 + 'fg-blue' => 34,
  271 + 'fg-magenta' => 35,
  272 + 'fg-cyan' => 36,
  273 + 'fg-white' => 37,
  274 + 'bg-black' => 40,
  275 + 'bg-red' => 41,
  276 + 'bg-green' => 42,
  277 + 'bg-yellow' => 43,
  278 + 'bg-blue' => 44,
  279 + 'bg-magenta' => 45,
  280 + 'bg-cyan' => 46,
  281 + 'bg-white' => 47,
  282 + ];
  283 + return $styles[$name];
  284 +}
  285 +
  286 +/**
  287 + * Formats message using styles if STDOUT supports it.
  288 + * @param string $message message
  289 + * @param string[] $styles styles
  290 + * @return string formatted message.
  291 + */
  292 +function formatMessage($message, $styles)
  293 +{
  294 + if (empty($styles) || !ansiColorsSupported()) {
  295 + return $message;
  296 + }
  297 +
  298 + return sprintf("\x1b[%sm", implode(';', array_map('getStyleCode', $styles))) . $message . "\x1b[0m";
  299 +}
... ...
init.bat 0 → 100644
  1 +++ a/init.bat
  1 +@echo off
  2 +
  3 +rem -------------------------------------------------------------
  4 +rem Yii command line init script for Windows.
  5 +rem
  6 +rem @author Qiang Xue <qiang.xue@gmail.com>
  7 +rem @link http://www.yiiframework.com/
  8 +rem @copyright Copyright (c) 2008 Yii Software LLC
  9 +rem @license http://www.yiiframework.com/license/
  10 +rem -------------------------------------------------------------
  11 +
  12 +@setlocal
  13 +
  14 +set YII_PATH=%~dp0
  15 +
  16 +if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
  17 +
  18 +"%PHP_COMMAND%" "%YII_PATH%init" %*
  19 +
  20 +@endlocal
... ...
requirements.php 0 → 100644
  1 +++ a/requirements.php
  1 +<?php
  2 +/**
  3 + * Application requirement checker script.
  4 + *
  5 + * In order to run this script use the following console command:
  6 + * php requirements.php
  7 + *
  8 + * In order to run this script from the web, you should copy it to the web root.
  9 + * If you are using Linux you can create a hard link instead, using the following command:
  10 + * ln requirements.php ../requirements.php
  11 + */
  12 +
  13 +// you may need to adjust this path to the correct Yii framework path
  14 +$frameworkPath = dirname(__FILE__) . '/vendor/yiisoft/yii2';
  15 +
  16 +if (!is_dir($frameworkPath)) {
  17 + echo '<h1>Error</h1>';
  18 + echo '<p><strong>The path to yii framework seems to be incorrect.</strong></p>';
  19 + echo '<p>You need to install Yii framework via composer or adjust the framework path in file <abbr title="' . __FILE__ . '">' . basename(__FILE__) . '</abbr>.</p>';
  20 + echo '<p>Please refer to the <abbr title="' . dirname(__FILE__) . '/README.md">README</abbr> on how to install Yii.</p>';
  21 +}
  22 +
  23 +require_once($frameworkPath . '/requirements/YiiRequirementChecker.php');
  24 +$requirementsChecker = new YiiRequirementChecker();
  25 +
  26 +$gdMemo = $imagickMemo = 'Either GD PHP extension with FreeType support or ImageMagick PHP extension with PNG support is required for image CAPTCHA.';
  27 +$gdOK = $imagickOK = false;
  28 +
  29 +if (extension_loaded('imagick')) {
  30 + $imagick = new Imagick();
  31 + $imagickFormats = $imagick->queryFormats('PNG');
  32 + if (in_array('PNG', $imagickFormats)) {
  33 + $imagickOK = true;
  34 + } else {
  35 + $imagickMemo = 'Imagick extension should be installed with PNG support in order to be used for image CAPTCHA.';
  36 + }
  37 +}
  38 +
  39 +if (extension_loaded('gd')) {
  40 + $gdInfo = gd_info();
  41 + if (!empty($gdInfo['FreeType Support'])) {
  42 + $gdOK = true;
  43 + } else {
  44 + $gdMemo = 'GD extension should be installed with FreeType support in order to be used for image CAPTCHA.';
  45 + }
  46 +}
  47 +
  48 +/**
  49 + * Adjust requirements according to your application specifics.
  50 + */
  51 +$requirements = array(
  52 + // Database :
  53 + array(
  54 + 'name' => 'PDO extension',
  55 + 'mandatory' => true,
  56 + 'condition' => extension_loaded('pdo'),
  57 + 'by' => 'All DB-related classes',
  58 + ),
  59 + array(
  60 + 'name' => 'PDO SQLite extension',
  61 + 'mandatory' => false,
  62 + 'condition' => extension_loaded('pdo_sqlite'),
  63 + 'by' => 'All DB-related classes',
  64 + 'memo' => 'Required for SQLite database.',
  65 + ),
  66 + array(
  67 + 'name' => 'PDO MySQL extension',
  68 + 'mandatory' => false,
  69 + 'condition' => extension_loaded('pdo_mysql'),
  70 + 'by' => 'All DB-related classes',
  71 + 'memo' => 'Required for MySQL database.',
  72 + ),
  73 + array(
  74 + 'name' => 'PDO PostgreSQL extension',
  75 + 'mandatory' => false,
  76 + 'condition' => extension_loaded('pdo_pgsql'),
  77 + 'by' => 'All DB-related classes',
  78 + 'memo' => 'Required for PostgreSQL database.',
  79 + ),
  80 + // Cache :
  81 + array(
  82 + 'name' => 'Memcache extension',
  83 + 'mandatory' => false,
  84 + 'condition' => extension_loaded('memcache') || extension_loaded('memcached'),
  85 + 'by' => '<a href="http://www.yiiframework.com/doc-2.0/yii-caching-memcache.html">MemCache</a>',
  86 + 'memo' => extension_loaded('memcached') ? 'To use memcached set <a href="http://www.yiiframework.com/doc-2.0/yii-caching-memcache.html#$useMemcached-detail">MemCache::useMemcached</a> to <code>true</code>.' : ''
  87 + ),
  88 + array(
  89 + 'name' => 'APC extension',
  90 + 'mandatory' => false,
  91 + 'condition' => extension_loaded('apc'),
  92 + 'by' => '<a href="http://www.yiiframework.com/doc-2.0/yii-caching-apccache.html">ApcCache</a>',
  93 + ),
  94 + // CAPTCHA:
  95 + array(
  96 + 'name' => 'GD PHP extension with FreeType support',
  97 + 'mandatory' => false,
  98 + 'condition' => $gdOK,
  99 + 'by' => '<a href="http://www.yiiframework.com/doc-2.0/yii-captcha-captcha.html">Captcha</a>',
  100 + 'memo' => $gdMemo,
  101 + ),
  102 + array(
  103 + 'name' => 'ImageMagick PHP extension with PNG support',
  104 + 'mandatory' => false,
  105 + 'condition' => $imagickOK,
  106 + 'by' => '<a href="http://www.yiiframework.com/doc-2.0/yii-captcha-captcha.html">Captcha</a>',
  107 + 'memo' => $imagickMemo,
  108 + ),
  109 + // PHP ini :
  110 + 'phpExposePhp' => array(
  111 + 'name' => 'Expose PHP',
  112 + 'mandatory' => false,
  113 + 'condition' => $requirementsChecker->checkPhpIniOff("expose_php"),
  114 + 'by' => 'Security reasons',
  115 + 'memo' => '"expose_php" should be disabled at php.ini',
  116 + ),
  117 + 'phpAllowUrlInclude' => array(
  118 + 'name' => 'PHP allow url include',
  119 + 'mandatory' => false,
  120 + 'condition' => $requirementsChecker->checkPhpIniOff("allow_url_include"),
  121 + 'by' => 'Security reasons',
  122 + 'memo' => '"allow_url_include" should be disabled at php.ini',
  123 + ),
  124 + 'phpSmtp' => array(
  125 + 'name' => 'PHP mail SMTP',
  126 + 'mandatory' => false,
  127 + 'condition' => strlen(ini_get('SMTP')) > 0,
  128 + 'by' => 'Email sending',
  129 + 'memo' => 'PHP mail SMTP server required',
  130 + ),
  131 +);
  132 +$requirementsChecker->checkYii()->check($requirements)->render();
... ...
vagrant/config/.gitignore 0 → 100644
  1 +++ a/vagrant/config/.gitignore
  1 +# local configuration
  2 +vagrant-local.yml
0 3 \ No newline at end of file
... ...
vagrant/config/vagrant-local.example.yml 0 → 100644
  1 +++ a/vagrant/config/vagrant-local.example.yml
  1 +# Your personal GitHub token
  2 +github_token: <your-personal-github-token>
  3 +# Read more: https://github.com/blog/1509-personal-api-tokens
  4 +# You can generate it here: https://github.com/settings/tokens
  5 +
  6 +# Guest OS timezone
  7 +timezone: Europe/London
  8 +
  9 +# Are we need check box updates for every 'vagrant up'?
  10 +box_check_update: false
  11 +
  12 +# Virtual machine name
  13 +machine_name: y2aa
  14 +
  15 +# Virtual machine IP
  16 +ip: 192.168.83.137
  17 +
  18 +# Virtual machine CPU cores number
  19 +cpus: 1
  20 +
  21 +# Virtual machine RAM
  22 +memory: 512
... ...
vagrant/nginx/app.conf 0 → 100644
  1 +++ a/vagrant/nginx/app.conf
  1 +server {
  2 + charset utf-8;
  3 + client_max_body_size 128M;
  4 + sendfile off;
  5 +
  6 + listen 80; ## listen for ipv4
  7 + #listen [::]:80 default_server ipv6only=on; ## listen for ipv6
  8 +
  9 + server_name y2aa-frontend.dev;
  10 + root /app/frontend/web/;
  11 + index index.php;
  12 +
  13 + access_log /app/vagrant/nginx/log/frontend-access.log;
  14 + error_log /app/vagrant/nginx/log/frontend-error.log;
  15 +
  16 + location / {
  17 + # Redirect everything that isn't a real file to index.php
  18 + try_files $uri $uri/ /index.php$is_args$args;
  19 + }
  20 +
  21 + # uncomment to avoid processing of calls to non-existing static files by Yii
  22 + #location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
  23 + # try_files $uri =404;
  24 + #}
  25 + #error_page 404 /404.html;
  26 +
  27 + location ~ \.php$ {
  28 + include fastcgi_params;
  29 + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  30 + #fastcgi_pass 127.0.0.1:9000;
  31 + fastcgi_pass unix:/var/run/php5-fpm.sock;
  32 + try_files $uri =404;
  33 + }
  34 +
  35 + location ~ /\.(ht|svn|git) {
  36 + deny all;
  37 + }
  38 +}
  39 +
  40 +server {
  41 + charset utf-8;
  42 + client_max_body_size 128M;
  43 + sendfile off;
  44 +
  45 + listen 80; ## listen for ipv4
  46 + #listen [::]:80 default_server ipv6only=on; ## listen for ipv6
  47 +
  48 + server_name y2aa-backend.dev;
  49 + root /app/backend/web/;
  50 + index index.php;
  51 +
  52 + access_log /app/vagrant/nginx/log/backend-access.log;
  53 + error_log /app/vagrant/nginx/log/backend-error.log;
  54 +
  55 + location / {
  56 + # Redirect everything that isn't a real file to index.php
  57 + try_files $uri $uri/ /index.php$is_args$args;
  58 + }
  59 +
  60 + # uncomment to avoid processing of calls to non-existing static files by Yii
  61 + #location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
  62 + # try_files $uri =404;
  63 + #}
  64 + #error_page 404 /404.html;
  65 +
  66 + location ~ \.php$ {
  67 + include fastcgi_params;
  68 + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  69 + #fastcgi_pass 127.0.0.1:9000;
  70 + fastcgi_pass unix:/var/run/php5-fpm.sock;
  71 + try_files $uri =404;
  72 + }
  73 +
  74 + location ~ /\.(ht|svn|git) {
  75 + deny all;
  76 + }
  77 +}
... ...
vagrant/nginx/log/.gitignore 0 → 100644
  1 +++ a/vagrant/nginx/log/.gitignore
  1 +# nginx logs
  2 +backend-access.log
  3 +backend-error.log
  4 +frontend-access.log
  5 +frontend-error.log
0 6 \ No newline at end of file
... ...
vagrant/provision/always-as-root.sh 0 → 100644
  1 +++ a/vagrant/provision/always-as-root.sh
  1 +#!/usr/bin/env bash
  2 +
  3 +#== Bash helpers ==
  4 +
  5 +function info {
  6 + echo " "
  7 + echo "--> $1"
  8 + echo " "
  9 +}
  10 +
  11 +#== Provision script ==
  12 +
  13 +info "Provision-script user: `whoami`"
  14 +
  15 +info "Restart web-stack"
  16 +service php5-fpm restart
  17 +service nginx restart
  18 +service mysql restart
0 19 \ No newline at end of file
... ...
vagrant/provision/once-as-root.sh 0 → 100644
  1 +++ a/vagrant/provision/once-as-root.sh
  1 +#!/usr/bin/env bash
  2 +
  3 +#== Import script args ==
  4 +
  5 +timezone=$(echo "$1")
  6 +
  7 +#== Bash helpers ==
  8 +
  9 +function info {
  10 + echo " "
  11 + echo "--> $1"
  12 + echo " "
  13 +}
  14 +
  15 +#== Provision script ==
  16 +
  17 +info "Provision-script user: `whoami`"
  18 +
  19 +info "Allocate swap for MySQL 5.6"
  20 +fallocate -l 2048M /swapfile
  21 +chmod 600 /swapfile
  22 +mkswap /swapfile
  23 +swapon /swapfile
  24 +echo '/swapfile none swap defaults 0 0' >> /etc/fstab
  25 +
  26 +info "Configure locales"
  27 +update-locale LC_ALL="C"
  28 +dpkg-reconfigure locales
  29 +
  30 +info "Configure timezone"
  31 +echo ${timezone} | tee /etc/timezone
  32 +dpkg-reconfigure --frontend noninteractive tzdata
  33 +
  34 +info "Prepare root password for MySQL"
  35 +debconf-set-selections <<< "mysql-server-5.6 mysql-server/root_password password \"''\""
  36 +debconf-set-selections <<< "mysql-server-5.6 mysql-server/root_password_again password \"''\""
  37 +echo "Done!"
  38 +
  39 +info "Update OS software"
  40 +apt-get update
  41 +apt-get upgrade -y
  42 +
  43 +info "Install additional software"
  44 +apt-get install -y git php5-curl php5-cli php5-intl php5-mysqlnd php5-gd php5-fpm nginx mysql-server-5.6
  45 +
  46 +info "Configure MySQL"
  47 +sed -i "s/.*bind-address.*/bind-address = 0.0.0.0/" /etc/mysql/my.cnf
  48 +echo "Done!"
  49 +
  50 +info "Configure PHP-FPM"
  51 +sed -i 's/user = www-data/user = vagrant/g' /etc/php5/fpm/pool.d/www.conf
  52 +sed -i 's/group = www-data/group = vagrant/g' /etc/php5/fpm/pool.d/www.conf
  53 +sed -i 's/owner = www-data/owner = vagrant/g' /etc/php5/fpm/pool.d/www.conf
  54 +echo "Done!"
  55 +
  56 +info "Configure NGINX"
  57 +sed -i 's/user www-data/user vagrant/g' /etc/nginx/nginx.conf
  58 +echo "Done!"
  59 +
  60 +info "Enabling site configuration"
  61 +ln -s /app/vagrant/nginx/app.conf /etc/nginx/sites-enabled/app.conf
  62 +echo "Done!"
  63 +
  64 +info "Initailize databases for MySQL"
  65 +mysql -uroot <<< "CREATE DATABASE yii2advanced"
  66 +mysql -uroot <<< "CREATE DATABASE yii2advanced_test"
  67 +echo "Done!"
  68 +
  69 +info "Install composer"
  70 +curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
0 71 \ No newline at end of file
... ...
vagrant/provision/once-as-vagrant.sh 0 → 100644
  1 +++ a/vagrant/provision/once-as-vagrant.sh
  1 +#!/usr/bin/env bash
  2 +
  3 +#== Import script args ==
  4 +
  5 +github_token=$(echo "$1")
  6 +
  7 +#== Bash helpers ==
  8 +
  9 +function info {
  10 + echo " "
  11 + echo "--> $1"
  12 + echo " "
  13 +}
  14 +
  15 +#== Provision script ==
  16 +
  17 +info "Provision-script user: `whoami`"
  18 +
  19 +info "Configure composer"
  20 +composer config --global github-oauth.github.com ${github_token}
  21 +echo "Done!"
  22 +
  23 +info "Install plugins for composer"
  24 +composer global require "fxp/composer-asset-plugin:^1.2.0" --no-progress
  25 +
  26 +info "Install codeception"
  27 +composer global require "codeception/codeception=2.0.*" "codeception/specify=*" "codeception/verify=*" --no-progress
  28 +echo 'export PATH=/home/vagrant/.config/composer/vendor/bin:$PATH' | tee -a /home/vagrant/.profile
  29 +
  30 +info "Install project dependencies"
  31 +cd /app
  32 +composer --no-progress --prefer-dist install
  33 +
  34 +info "Init project"
  35 +./init --env=Development --overwrite=y
  36 +
  37 +info "Apply migrations"
  38 +./yii migrate <<< "yes"
  39 +
  40 +info "Create bash-alias 'app' for vagrant user"
  41 +echo 'alias app="cd /app"' | tee /home/vagrant/.bash_aliases
  42 +
  43 +info "Enabling colorized prompt for guest console"
  44 +sed -i "s/#force_color_prompt=yes/force_color_prompt=yes/" /home/vagrant/.bashrc
... ...
yii.bat 0 → 100644
  1 +++ a/yii.bat
  1 +@echo off
  2 +
  3 +rem -------------------------------------------------------------
  4 +rem Yii command line bootstrap script for Windows.
  5 +rem
  6 +rem @author Qiang Xue <qiang.xue@gmail.com>
  7 +rem @link http://www.yiiframework.com/
  8 +rem @copyright Copyright (c) 2008 Yii Software LLC
  9 +rem @license http://www.yiiframework.com/license/
  10 +rem -------------------------------------------------------------
  11 +
  12 +@setlocal
  13 +
  14 +set YII_PATH=%~dp0
  15 +
  16 +if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
  17 +
  18 +"%PHP_COMMAND%" "%YII_PATH%yii" %*
  19 +
  20 +@endlocal
... ...