first commit

This commit is contained in:
2023-05-06 20:40:02 +03:00
commit fdf3e1e602
221 changed files with 12262 additions and 0 deletions

4
frontend/Dockerfile Executable file
View File

@ -0,0 +1,4 @@
FROM yiisoftware/yii2-php:8.1-apache
# Change document root for Apache
RUN sed -i -e 's|/app/web|/app/frontend/web|g' /etc/apache2/sites-available/000-default.conf

23
frontend/assets/AppAsset.php Executable file
View File

@ -0,0 +1,23 @@
<?php
namespace frontend\assets;
use yii\web\AssetBundle;
/**
* Main frontend application asset bundle.
*/
class AppAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'css/site.css',
];
public $js = [
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap5\BootstrapAsset',
];
}

15
frontend/codeception.yml Executable file
View File

@ -0,0 +1,15 @@
namespace: frontend\tests
actor_suffix: Tester
paths:
tests: tests
output: tests/_output
data: tests/_data
support: tests/_support
bootstrap: _bootstrap.php
settings:
colors: true
memory_limit: 1024M
modules:
config:
Yii2:
configFile: 'config/codeception-local.php'

4
frontend/config/.gitignore vendored Executable file
View File

@ -0,0 +1,4 @@
codeception-local.php
main-local.php
params-local.php
test-local.php

1
frontend/config/bootstrap.php Executable file
View File

@ -0,0 +1 @@
<?php

50
frontend/config/main.php Executable file
View File

@ -0,0 +1,50 @@
<?php
$params = array_merge(
require __DIR__ . '/../../common/config/params.php',
require __DIR__ . '/../../common/config/params-local.php',
require __DIR__ . '/params.php',
require __DIR__ . '/params-local.php'
);
return [
'id' => 'app-frontend',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'controllerNamespace' => 'frontend\controllers',
'components' => [
'request' => [
'baseUrl' => '',
'csrfParam' => '_csrf-frontend',
],
'user' => [
'identityClass' => 'common\models\User',
'enableAutoLogin' => true,
'identityCookie' => ['name' => '_identity-frontend', 'httpOnly' => true],
],
'session' => [
// this is the name of the session cookie used for login on the frontend
'name' => 'advanced-frontend',
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => \yii\log\FileTarget::class,
'levels' => ['error', 'warning'],
],
],
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'/new/<slug>' => 'news/get-one',
'/text/<id>/<slug>' => 'news/text',
],
],
],
'params' => $params,
];

4
frontend/config/params.php Executable file
View File

@ -0,0 +1,4 @@
<?php
return [
'adminEmail' => 'admin@example.com',
];

18
frontend/config/test.php Executable file
View File

@ -0,0 +1,18 @@
<?php
return [
'id' => 'app-frontend-tests',
'components' => [
'assetManager' => [
'basePath' => __DIR__ . '/../web/assets',
],
'urlManager' => [
'showScriptName' => true,
],
'request' => [
'cookieValidationKey' => 'test',
],
'mailer' => [
'messageClass' => \yii\symfonymailer\Message::class
]
],
];

View File

@ -0,0 +1,117 @@
<?php
namespace frontend\controllers;
use common\models\News;
use common\services\UserService;
use frontend\models\DataForm;
use Yii;
use yii\web\Controller;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
/**
* Site controller
*/
class NewsController extends Controller
{
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['logout', 'signup'],
'rules' => [
[
'actions' => ['signup'],
'allow' => true,
'roles' => ['?'],
],
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['@'],
],
],
],
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'logout' => ['post'],
],
],
];
}
/**
* {@inheritdoc}
*/
public function actions()
{
return [
'error' => [
'class' => \yii\web\ErrorAction::class,
],
'captcha' => [
'class' => \yii\captcha\CaptchaAction::class,
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
],
];
}
/**
* Displays homepage.
*
* @return mixed
*/
public function actionIndex()
{
$news = News::find()->all();
return $this->render('index', [
'news' => $news
]);
}
/**
* @param null $slug
* @return mixed
*/
public function actionGetOne($slug = null)
{
$new = News::find()->where(['slug' => $slug])->one();
return $this->render('one', [
'new' => $new
]);
}
public function actionData()
{
$model = new DataForm();
if (Yii::$app->request->isPost) {
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
Yii::$app->session->setFlash('success', 'Валидация прошла успешно');
} else {
Yii::$app->session->setFlash('error', 'Что-то не так');
}
return $this->refresh();
}
return $this->render('data', [
'model' => $model,
]);
}
public function actionText($id, $slug)
{
$texts = UserService::run()->getTextByLanguage($id, $slug);
return $this->render('text', [
'texts' => $texts
]);
}
}

View File

@ -0,0 +1,259 @@
<?php
namespace frontend\controllers;
use frontend\models\ResendVerificationEmailForm;
use frontend\models\VerifyEmailForm;
use Yii;
use yii\base\InvalidArgumentException;
use yii\web\BadRequestHttpException;
use yii\web\Controller;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use common\models\LoginForm;
use frontend\models\PasswordResetRequestForm;
use frontend\models\ResetPasswordForm;
use frontend\models\SignupForm;
use frontend\models\ContactForm;
/**
* Site controller
*/
class SiteController extends Controller
{
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['logout', 'signup'],
'rules' => [
[
'actions' => ['signup'],
'allow' => true,
'roles' => ['?'],
],
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['@'],
],
],
],
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'logout' => ['post'],
],
],
];
}
/**
* {@inheritdoc}
*/
public function actions()
{
return [
'error' => [
'class' => \yii\web\ErrorAction::class,
],
'captcha' => [
'class' => \yii\captcha\CaptchaAction::class,
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
],
];
}
/**
* Displays homepage.
*
* @return mixed
*/
public function actionIndex()
{
return $this->render('index');
}
/**
* Logs in a user.
*
* @return mixed
*/
public function actionLogin()
{
if (!Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
}
$model->password = '';
return $this->render('login', [
'model' => $model,
]);
}
/**
* Logs out the current user.
*
* @return mixed
*/
public function actionLogout()
{
Yii::$app->user->logout();
return $this->goHome();
}
/**
* Displays contact page.
*
* @return mixed
*/
public function actionContact()
{
$model = new ContactForm();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
if ($model->sendEmail(Yii::$app->params['adminEmail'])) {
Yii::$app->session->setFlash('success', 'Thank you for contacting us. We will respond to you as soon as possible.');
} else {
Yii::$app->session->setFlash('error', 'There was an error sending your message.');
}
return $this->refresh();
}
return $this->render('contact', [
'model' => $model,
]);
}
/**
* Displays about page.
*
* @return mixed
*/
public function actionAbout()
{
return $this->render('about');
}
/**
* Signs user up.
*
* @return mixed
*/
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post()) && $model->signup()) {
Yii::$app->session->setFlash('success', 'Thank you for registration. Please check your inbox for verification email.');
return $this->goHome();
}
return $this->render('signup', [
'model' => $model,
]);
}
/**
* Requests password reset.
*
* @return mixed
*/
public function actionRequestPasswordReset()
{
$model = new PasswordResetRequestForm();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
if ($model->sendEmail()) {
Yii::$app->session->setFlash('success', 'Check your email for further instructions.');
return $this->goHome();
}
Yii::$app->session->setFlash('error', 'Sorry, we are unable to reset password for the provided email address.');
}
return $this->render('requestPasswordResetToken', [
'model' => $model,
]);
}
/**
* Resets password.
*
* @param string $token
* @return mixed
* @throws BadRequestHttpException
*/
public function actionResetPassword($token)
{
try {
$model = new ResetPasswordForm($token);
} catch (InvalidArgumentException $e) {
throw new BadRequestHttpException($e->getMessage());
}
if ($model->load(Yii::$app->request->post()) && $model->validate() && $model->resetPassword()) {
Yii::$app->session->setFlash('success', 'New password saved.');
return $this->goHome();
}
return $this->render('resetPassword', [
'model' => $model,
]);
}
/**
* Verify email address
*
* @param string $token
* @throws BadRequestHttpException
* @return yii\web\Response
*/
public function actionVerifyEmail($token)
{
try {
$model = new VerifyEmailForm($token);
} catch (InvalidArgumentException $e) {
throw new BadRequestHttpException($e->getMessage());
}
if (($user = $model->verifyEmail()) && Yii::$app->user->login($user)) {
Yii::$app->session->setFlash('success', 'Your email has been confirmed!');
return $this->goHome();
}
Yii::$app->session->setFlash('error', 'Sorry, we are unable to verify your account with provided token.');
return $this->goHome();
}
/**
* Resend verification email
*
* @return mixed
*/
public function actionResendVerificationEmail()
{
$model = new ResendVerificationEmailForm();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
if ($model->sendEmail()) {
Yii::$app->session->setFlash('success', 'Check your email for further instructions.');
return $this->goHome();
}
Yii::$app->session->setFlash('error', 'Sorry, we are unable to resend verification email for the provided email address.');
}
return $this->render('resendVerificationEmail', [
'model' => $model
]);
}
}

61
frontend/models/ContactForm.php Executable file
View File

@ -0,0 +1,61 @@
<?php
namespace frontend\models;
use Yii;
use yii\base\Model;
/**
* ContactForm is the model behind the contact form.
*/
class ContactForm extends Model
{
public $name;
public $email;
public $subject;
public $body;
public $verifyCode;
/**
* {@inheritdoc}
*/
public function rules()
{
return [
// name, email, subject and body are required
[['name', 'email', 'subject', 'body'], 'required'],
// email has to be a valid email address
['email', 'email'],
// verifyCode needs to be entered correctly
['verifyCode', 'captcha'],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'verifyCode' => 'Verification Code',
];
}
/**
* Sends an email to the specified email address using the information collected by this model.
*
* @param string $email the target email address
* @return bool whether the email was sent
*/
public function sendEmail($email)
{
return Yii::$app->mailer->compose()
->setTo($email)
->setFrom([Yii::$app->params['senderEmail'] => Yii::$app->params['senderName']])
->setReplyTo([$this->email => $this->name])
->setSubject($this->subject)
->setTextBody($this->body)
->send();
}
}

40
frontend/models/DataForm.php Executable file
View File

@ -0,0 +1,40 @@
<?php
namespace frontend\models;
use yii\base\Model;
/**
* ContactForm is the model behind the contact form.
*/
class DataForm extends Model
{
public $fio;
public $email;
public $phone;
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['fio', 'email', 'phone'], 'required'],
['email', 'email'],
[['fio', 'phone'], 'string'],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'email' => 'Электронная почта',
'fio' => 'ФИО',
'phone' => 'Номер телефона',
];
}
}

View File

@ -0,0 +1,69 @@
<?php
namespace frontend\models;
use Yii;
use yii\base\Model;
use common\models\User;
/**
* Password reset request form
*/
class PasswordResetRequestForm extends Model
{
public $email;
/**
* {@inheritdoc}
*/
public function rules()
{
return [
['email', 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'exist',
'targetClass' => '\common\models\User',
'filter' => ['status' => User::STATUS_ACTIVE],
'message' => 'There is no user with this email address.'
],
];
}
/**
* Sends an email with a link, for resetting the password.
*
* @return bool whether the email was send
*/
public function sendEmail()
{
/* @var $user User */
$user = User::findOne([
'status' => User::STATUS_ACTIVE,
'email' => $this->email,
]);
if (!$user) {
return false;
}
if (!User::isPasswordResetTokenValid($user->password_reset_token)) {
$user->generatePasswordResetToken();
if (!$user->save()) {
return false;
}
}
return Yii::$app
->mailer
->compose(
['html' => 'passwordResetToken-html', 'text' => 'passwordResetToken-text'],
['user' => $user]
)
->setFrom([Yii::$app->params['supportEmail'] => Yii::$app->name . ' robot'])
->setTo($this->email)
->setSubject('Password reset for ' . Yii::$app->name)
->send();
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace frontend\models;
use Yii;
use common\models\User;
use yii\base\Model;
class ResendVerificationEmailForm extends Model
{
/**
* @var string
*/
public $email;
/**
* {@inheritdoc}
*/
public function rules()
{
return [
['email', 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'exist',
'targetClass' => '\common\models\User',
'filter' => ['status' => User::STATUS_INACTIVE],
'message' => 'There is no user with this email address.'
],
];
}
/**
* Sends confirmation email to user
*
* @return bool whether the email was sent
*/
public function sendEmail()
{
$user = User::findOne([
'email' => $this->email,
'status' => User::STATUS_INACTIVE
]);
if ($user === null) {
return false;
}
return Yii::$app
->mailer
->compose(
['html' => 'emailVerify-html', 'text' => 'emailVerify-text'],
['user' => $user]
)
->setFrom([Yii::$app->params['supportEmail'] => Yii::$app->name . ' robot'])
->setTo($this->email)
->setSubject('Account registration at ' . Yii::$app->name)
->send();
}
}

View File

@ -0,0 +1,67 @@
<?php
namespace frontend\models;
use yii\base\InvalidArgumentException;
use yii\base\Model;
use Yii;
use common\models\User;
/**
* Password reset form
*/
class ResetPasswordForm extends Model
{
public $password;
/**
* @var \common\models\User
*/
private $_user;
/**
* Creates a form model given a token.
*
* @param string $token
* @param array $config name-value pairs that will be used to initialize the object properties
* @throws InvalidArgumentException if token is empty or not valid
*/
public function __construct($token, $config = [])
{
if (empty($token) || !is_string($token)) {
throw new InvalidArgumentException('Password reset token cannot be blank.');
}
$this->_user = User::findByPasswordResetToken($token);
if (!$this->_user) {
throw new InvalidArgumentException('Wrong password reset token.');
}
parent::__construct($config);
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
['password', 'required'],
['password', 'string', 'min' => Yii::$app->params['user.passwordMinLength']],
];
}
/**
* Resets password.
*
* @return bool if password was reset.
*/
public function resetPassword()
{
$user = $this->_user;
$user->setPassword($this->password);
$user->removePasswordResetToken();
$user->generateAuthKey();
return $user->save(false);
}
}

80
frontend/models/SignupForm.php Executable file
View File

@ -0,0 +1,80 @@
<?php
namespace frontend\models;
use Yii;
use yii\base\Model;
use common\models\User;
/**
* Signup form
*/
class SignupForm extends Model
{
public $username;
public $email;
public $password;
/**
* {@inheritdoc}
*/
public function rules()
{
return [
['username', 'trim'],
['username', 'required'],
['username', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This username has already been taken.'],
['username', 'string', 'min' => 2, 'max' => 255],
['email', 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'string', 'max' => 255],
['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'],
['password', 'required'],
['password', 'string', 'min' => Yii::$app->params['user.passwordMinLength']],
];
}
/**
* Signs user up.
*
* @return bool whether the creating new account was successful and email was sent
*/
public function signup()
{
if (!$this->validate()) {
return null;
}
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
$user->generateEmailVerificationToken();
return $user->save() && $this->sendEmail($user);
}
/**
* Sends confirmation email to user
* @param User $user user model to with email should be send
* @return bool whether the email was sent
*/
protected function sendEmail($user)
{
return Yii::$app
->mailer
->compose(
['html' => 'emailVerify-html', 'text' => 'emailVerify-text'],
['user' => $user]
)
->setFrom([Yii::$app->params['supportEmail'] => Yii::$app->name . ' robot'])
->setTo($this->email)
->setSubject('Account registration at ' . Yii::$app->name)
->send();
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace frontend\models;
use common\models\User;
use yii\base\InvalidArgumentException;
use yii\base\Model;
class VerifyEmailForm extends Model
{
/**
* @var string
*/
public $token;
/**
* @var User
*/
private $_user;
/**
* Creates a form model with given token.
*
* @param string $token
* @param array $config name-value pairs that will be used to initialize the object properties
* @throws InvalidArgumentException if token is empty or not valid
*/
public function __construct($token, array $config = [])
{
if (empty($token) || !is_string($token)) {
throw new InvalidArgumentException('Verify email token cannot be blank.');
}
$this->_user = User::findByVerificationToken($token);
if (!$this->_user) {
throw new InvalidArgumentException('Wrong verify email token.');
}
parent::__construct($config);
}
/**
* Verify email
*
* @return User|null the saved model or null if saving fails
*/
public function verifyEmail()
{
$user = $this->_user;
$user->status = User::STATUS_ACTIVE;
return $user->save(false) ? $user : null;
}
}

2
frontend/runtime/.gitignore vendored Executable file
View File

@ -0,0 +1,2 @@
*
!.gitignore

10
frontend/tests/_bootstrap.php Executable file
View File

@ -0,0 +1,10 @@
<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');
defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', __DIR__.'/../../');
require_once YII_APP_BASE_PATH . '/vendor/autoload.php';
require_once YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php';
require_once YII_APP_BASE_PATH . '/common/config/bootstrap.php';
require_once __DIR__ . '/../config/bootstrap.php';

View File

@ -0,0 +1,25 @@
<?php
return [
[
'username' => 'erau',
'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI',
// password_0
'password_hash' => '$2y$13$nJ1WDlBaGcbCdbNC5.5l4.sgy.OMEKCqtDQOdQ2OWpgiKRWYyzzne',
'password_reset_token' => 'RkD_Jw0_8HEedzLk7MM-ZKEFfYR7VbMr_1392559490',
'created_at' => '1392559490',
'updated_at' => '1392559490',
'email' => 'sfriesen@jenkins.info',
],
[
'username' => 'test.test',
'auth_key' => 'O87GkY3_UfmMHYkyezZ7QLfmkKNsllzT',
// Test1234
'password_hash' => 'O87GkY3_UfmMHYkyezZ7QLfmkKNsllzT',
'email' => 'test@mail.com',
'status' => '9',
'created_at' => '1548675330',
'updated_at' => '1548675330',
'verification_token' => '4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330',
],
];

45
frontend/tests/_data/user.php Executable file
View File

@ -0,0 +1,45 @@
<?php
return [
[
'username' => 'okirlin',
'auth_key' => 'iwTNae9t34OmnK6l4vT4IeaTk-YWI2Rv',
'password_hash' => '$2y$13$CXT0Rkle1EMJ/c1l5bylL.EylfmQ39O5JlHJVFpNn618OUS1HwaIi',
'password_reset_token' => 't5GU9NwpuGYSfb7FEZMAxqtuz2PkEvv_' . time(),
'created_at' => '1391885313',
'updated_at' => '1391885313',
'email' => 'brady.renner@rutherford.com',
],
[
'username' => 'troy.becker',
'auth_key' => 'EdKfXrx88weFMV0vIxuTMWKgfK2tS3Lp',
'password_hash' => '$2y$13$g5nv41Px7VBqhS3hVsVN2.MKfgT3jFdkXEsMC4rQJLfaMa7VaJqL2',
'password_reset_token' => '4BSNyiZNAuxjs5Mty990c47sVrgllIi_' . time(),
'created_at' => '1391885313',
'updated_at' => '1391885313',
'email' => 'nicolas.dianna@hotmail.com',
'status' => '0',
],
[
'username' => 'test.test',
'auth_key' => 'O87GkY3_UfmMHYkyezZ7QLfmkKNsllzT',
//Test1234
'password_hash' => '$2y$13$d17z0w/wKC4LFwtzBcmx6up4jErQuandJqhzKGKczfWuiEhLBtQBK',
'email' => 'test@mail.com',
'status' => '9',
'created_at' => '1548675330',
'updated_at' => '1548675330',
'verification_token' => '4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330',
],
[
'username' => 'test2.test',
'auth_key' => '4XXdVqi3rDpa_a6JH6zqVreFxUPcUPvJ',
//Test1234
'password_hash' => '$2y$13$d17z0w/wKC4LFwtzBcmx6up4jErQuandJqhzKGKczfWuiEhLBtQBK',
'email' => 'test2@mail.com',
'status' => '10',
'created_at' => '1548675330',
'updated_at' => '1548675330',
'verification_token' => 'already_used_token_1548675330',
],
];

2
frontend/tests/_output/.gitignore vendored Executable file
View File

@ -0,0 +1,2 @@
*
!.gitignore

1
frontend/tests/_support/.gitignore vendored Executable file
View File

@ -0,0 +1 @@
_generated

View File

@ -0,0 +1,34 @@
<?php
namespace frontend\tests;
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void verify($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
*
* @SuppressWarnings(PHPMD)
*/
class FunctionalTester extends \Codeception\Actor
{
use _generated\FunctionalTesterActions;
public function seeValidationError($message)
{
$this->see($message, '.invalid-feedback');
}
public function dontSeeValidationError($message)
{
$this->dontSee($message, '.invalid-feedback');
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace frontend\tests;
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void verify($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
*
* @SuppressWarnings(PHPMD)
*/
class UnitTester extends \Codeception\Actor
{
use _generated\UnitTesterActions;
/**
* Define custom actions here
*/
}

View File

@ -0,0 +1,9 @@
suite_namespace: frontend\tests\acceptance
actor: AcceptanceTester
modules:
enabled:
- WebDriver:
url: http://localhost:8080
browser: firefox
- Yii2:
part: init

View File

@ -0,0 +1,21 @@
<?php
namespace frontend\tests\acceptance;
use frontend\tests\AcceptanceTester;
use yii\helpers\Url;
class HomeCest
{
public function checkHome(AcceptanceTester $I)
{
$I->amOnRoute(Url::toRoute('/site/index'));
$I->see('My Application');
$I->seeLink('About');
$I->click('About');
$I->wait(2); // wait for page to be opened
$I->see('This is the About page.');
}
}

View File

@ -0,0 +1,16 @@
<?php
/**
* Here you can initialize variables via \Codeception\Util\Fixtures class
* to store data in global array and use it in Cepts.
*
* ```php
* // Here _bootstrap.php
* \Codeception\Util\Fixtures::add('user1', ['name' => 'davert']);
* ```
*
* In Cept
*
* ```php
* \Codeception\Util\Fixtures::get('user1');
* ```
*/

View File

@ -0,0 +1,7 @@
suite_namespace: frontend\tests\functional
actor: FunctionalTester
modules:
enabled:
- Filesystem
- Yii2
- Asserts

View File

@ -0,0 +1,14 @@
<?php
namespace frontend\tests\functional;
use frontend\tests\FunctionalTester;
class AboutCest
{
public function checkAbout(FunctionalTester $I)
{
$I->amOnRoute('site/about');
$I->see('About', 'h1');
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace frontend\tests\functional;
use frontend\tests\FunctionalTester;
/* @var $scenario \Codeception\Scenario */
class ContactCest
{
public function _before(FunctionalTester $I)
{
$I->amOnRoute('site/contact');
}
public function checkContact(FunctionalTester $I)
{
$I->see('Contact', 'h1');
}
public function checkContactSubmitNoData(FunctionalTester $I)
{
$I->submitForm('#contact-form', []);
$I->see('Contact', 'h1');
$I->seeValidationError('Name cannot be blank');
$I->seeValidationError('Email cannot be blank');
$I->seeValidationError('Subject cannot be blank');
$I->seeValidationError('Body cannot be blank');
$I->seeValidationError('The verification code is incorrect');
}
public function checkContactSubmitNotCorrectEmail(FunctionalTester $I)
{
$I->submitForm('#contact-form', [
'ContactForm[name]' => 'tester',
'ContactForm[email]' => 'tester.email',
'ContactForm[subject]' => 'test subject',
'ContactForm[body]' => 'test content',
'ContactForm[verifyCode]' => 'testme',
]);
$I->seeValidationError('Email is not a valid email address.');
$I->dontSeeValidationError('Name cannot be blank');
$I->dontSeeValidationError('Subject cannot be blank');
$I->dontSeeValidationError('Body cannot be blank');
$I->dontSeeValidationError('The verification code is incorrect');
}
public function checkContactSubmitCorrectData(FunctionalTester $I)
{
$I->submitForm('#contact-form', [
'ContactForm[name]' => 'tester',
'ContactForm[email]' => 'tester@example.com',
'ContactForm[subject]' => 'test subject',
'ContactForm[body]' => 'test content',
'ContactForm[verifyCode]' => 'testme',
]);
$I->seeEmailIsSent();
$I->see('Thank you for contacting us. We will respond to you as soon as possible.');
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace frontend\tests\functional;
use frontend\tests\FunctionalTester;
class HomeCest
{
public function checkOpen(FunctionalTester $I)
{
$I->amOnRoute(\Yii::$app->homeUrl);
$I->see('My Application');
$I->seeLink('About');
$I->click('About');
$I->see('This is the About page.');
}
}

View File

@ -0,0 +1,66 @@
<?php
namespace frontend\tests\functional;
use frontend\tests\FunctionalTester;
use common\fixtures\UserFixture;
class LoginCest
{
/**
* Load fixtures before db transaction begin
* Called in _before()
* @see \Codeception\Module\Yii2::_before()
* @see \Codeception\Module\Yii2::loadFixtures()
* @return array
*/
public function _fixtures()
{
return [
'user' => [
'class' => UserFixture::class,
'dataFile' => codecept_data_dir() . 'login_data.php',
],
];
}
public function _before(FunctionalTester $I)
{
$I->amOnRoute('site/login');
}
protected function formParams($login, $password)
{
return [
'LoginForm[username]' => $login,
'LoginForm[password]' => $password,
];
}
public function checkEmpty(FunctionalTester $I)
{
$I->submitForm('#login-form', $this->formParams('', ''));
$I->seeValidationError('Username cannot be blank.');
$I->seeValidationError('Password cannot be blank.');
}
public function checkWrongPassword(FunctionalTester $I)
{
$I->submitForm('#login-form', $this->formParams('admin', 'wrong'));
$I->seeValidationError('Incorrect username or password.');
}
public function checkInactiveAccount(FunctionalTester $I)
{
$I->submitForm('#login-form', $this->formParams('test.test', 'Test1234'));
$I->seeValidationError('Incorrect username or password');
}
public function checkValidLogin(FunctionalTester $I)
{
$I->submitForm('#login-form', $this->formParams('erau', 'password_0'));
$I->see('Logout (erau)', 'form button[type=submit]');
$I->dontSeeLink('Login');
$I->dontSeeLink('Signup');
}
}

View File

@ -0,0 +1,83 @@
<?php
namespace frontend\tests\functional;
use common\fixtures\UserFixture;
use frontend\tests\FunctionalTester;
class ResendVerificationEmailCest
{
protected $formId = '#resend-verification-email-form';
/**
* Load fixtures before db transaction begin
* Called in _before()
* @see \Codeception\Module\Yii2::_before()
* @see \Codeception\Module\Yii2::loadFixtures()
* @return array
*/
public function _fixtures()
{
return [
'user' => [
'class' => UserFixture::class,
'dataFile' => codecept_data_dir() . 'user.php',
],
];
}
public function _before(FunctionalTester $I)
{
$I->amOnRoute('/site/resend-verification-email');
}
protected function formParams($email)
{
return [
'ResendVerificationEmailForm[email]' => $email
];
}
public function checkPage(FunctionalTester $I)
{
$I->see('Resend verification email', 'h1');
$I->see('Please fill out your email. A verification email will be sent there.');
}
public function checkEmptyField(FunctionalTester $I)
{
$I->submitForm($this->formId, $this->formParams(''));
$I->seeValidationError('Email cannot be blank.');
}
public function checkWrongEmailFormat(FunctionalTester $I)
{
$I->submitForm($this->formId, $this->formParams('abcd.com'));
$I->seeValidationError('Email is not a valid email address.');
}
public function checkWrongEmail(FunctionalTester $I)
{
$I->submitForm($this->formId, $this->formParams('wrong@email.com'));
$I->seeValidationError('There is no user with this email address.');
}
public function checkAlreadyVerifiedEmail(FunctionalTester $I)
{
$I->submitForm($this->formId, $this->formParams('test2@mail.com'));
$I->seeValidationError('There is no user with this email address.');
}
public function checkSendSuccessfully(FunctionalTester $I)
{
$I->submitForm($this->formId, $this->formParams('test@mail.com'));
$I->canSeeEmailIsSent();
$I->seeRecord('common\models\User', [
'email' => 'test@mail.com',
'username' => 'test.test',
'status' => \common\models\User::STATUS_INACTIVE
]);
$I->see('Check your email for further instructions.');
}
}

View File

@ -0,0 +1,59 @@
<?php
namespace frontend\tests\functional;
use frontend\tests\FunctionalTester;
class SignupCest
{
protected $formId = '#form-signup';
public function _before(FunctionalTester $I)
{
$I->amOnRoute('site/signup');
}
public function signupWithEmptyFields(FunctionalTester $I)
{
$I->see('Signup', 'h1');
$I->see('Please fill out the following fields to signup:');
$I->submitForm($this->formId, []);
$I->seeValidationError('Username cannot be blank.');
$I->seeValidationError('Email cannot be blank.');
$I->seeValidationError('Password cannot be blank.');
}
public function signupWithWrongEmail(FunctionalTester $I)
{
$I->submitForm(
$this->formId, [
'SignupForm[username]' => 'tester',
'SignupForm[email]' => 'ttttt',
'SignupForm[password]' => 'tester_password',
]
);
$I->dontSee('Username cannot be blank.', '.invalid-feedback');
$I->dontSee('Password cannot be blank.', '.invalid-feedback');
$I->see('Email is not a valid email address.', '.invalid-feedback');
}
public function signupSuccessfully(FunctionalTester $I)
{
$I->submitForm($this->formId, [
'SignupForm[username]' => 'tester',
'SignupForm[email]' => 'tester.email@example.com',
'SignupForm[password]' => 'tester_password',
]);
$I->seeRecord('common\models\User', [
'username' => 'tester',
'email' => 'tester.email@example.com',
'status' => \common\models\User::STATUS_INACTIVE
]);
$I->seeEmailIsSent();
$I->see('Thank you for registration. Please check your inbox for verification email.');
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace frontend\tests\functional;
use common\fixtures\UserFixture;
use frontend\tests\FunctionalTester;
class VerifyEmailCest
{
/**
* Load fixtures before db transaction begin
* Called in _before()
* @see \Codeception\Module\Yii2::_before()
* @see \Codeception\Module\Yii2::loadFixtures()
* @return array
*/
public function _fixtures()
{
return [
'user' => [
'class' => UserFixture::class,
'dataFile' => codecept_data_dir() . 'user.php',
],
];
}
public function checkEmptyToken(FunctionalTester $I)
{
$I->amOnRoute('site/verify-email', ['token' => '']);
$I->canSee('Bad Request', 'h1');
$I->canSee('Verify email token cannot be blank.');
}
public function checkInvalidToken(FunctionalTester $I)
{
$I->amOnRoute('site/verify-email', ['token' => 'wrong_token']);
$I->canSee('Bad Request', 'h1');
$I->canSee('Wrong verify email token.');
}
public function checkNoToken(FunctionalTester $I)
{
$I->amOnRoute('site/verify-email');
$I->canSee('Bad Request', 'h1');
$I->canSee('Missing required parameters: token');
}
public function checkAlreadyActivatedToken(FunctionalTester $I)
{
$I->amOnRoute('site/verify-email', ['token' => 'already_used_token_1548675330']);
$I->canSee('Bad Request', 'h1');
$I->canSee('Wrong verify email token.');
}
public function checkSuccessVerification(FunctionalTester $I)
{
$I->amOnRoute('site/verify-email', ['token' => '4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330']);
$I->canSee('Your email has been confirmed!');
$I->canSee('Congratulations!', 'h1');
$I->see('Logout (test.test)', 'form button[type=submit]');
$I->seeRecord('common\models\User', [
'username' => 'test.test',
'email' => 'test@mail.com',
'status' => \common\models\User::STATUS_ACTIVE
]);
}
}

View File

@ -0,0 +1,16 @@
<?php
/**
* Here you can initialize variables via \Codeception\Util\Fixtures class
* to store data in global array and use it in Cests.
*
* ```php
* // Here _bootstrap.php
* \Codeception\Util\Fixtures::add('user1', ['name' => 'davert']);
* ```
*
* In Cests
*
* ```php
* \Codeception\Util\Fixtures::get('user1');
* ```
*/

7
frontend/tests/unit.suite.yml Executable file
View File

@ -0,0 +1,7 @@
suite_namespace: frontend\tests\unit
actor: UnitTester
modules:
enabled:
- Yii2:
part: [orm, email, fixtures]
- Asserts

View File

@ -0,0 +1,16 @@
<?php
/**
* Here you can initialize variables via \Codeception\Util\Fixtures class
* to store data in global array and use it in Tests.
*
* ```php
* // Here _bootstrap.php
* \Codeception\Util\Fixtures::add('user1', ['name' => 'davert']);
* ```
*
* In Tests
*
* ```php
* \Codeception\Util\Fixtures::get('user1');
* ```
*/

View File

@ -0,0 +1,35 @@
<?php
namespace frontend\tests\unit\models;
use frontend\models\ContactForm;
use yii\mail\MessageInterface;
class ContactFormTest extends \Codeception\Test\Unit
{
public function testSendEmail()
{
$model = new ContactForm();
$model->attributes = [
'name' => 'Tester',
'email' => 'tester@example.com',
'subject' => 'very important letter subject',
'body' => 'body of current message',
];
verify($model->sendEmail('admin@example.com'))->notEmpty();
// using Yii2 module actions to check email was sent
$this->tester->seeEmailIsSent();
/** @var MessageInterface $emailMessage */
$emailMessage = $this->tester->grabLastSentEmail();
verify($emailMessage)->instanceOf('yii\mail\MessageInterface');
verify($emailMessage->getTo())->arrayHasKey('admin@example.com');
verify($emailMessage->getFrom())->arrayHasKey('noreply@example.com');
verify($emailMessage->getReplyTo())->arrayHasKey('tester@example.com');
verify($emailMessage->getSubject())->equals('very important letter subject');
verify($emailMessage->toString())->stringContainsString('body of current message');
}
}

View File

@ -0,0 +1,59 @@
<?php
namespace frontend\tests\unit\models;
use Yii;
use frontend\models\PasswordResetRequestForm;
use common\fixtures\UserFixture as UserFixture;
use common\models\User;
class PasswordResetRequestFormTest extends \Codeception\Test\Unit
{
/**
* @var \frontend\tests\UnitTester
*/
protected $tester;
public function _before()
{
$this->tester->haveFixtures([
'user' => [
'class' => UserFixture::class,
'dataFile' => codecept_data_dir() . 'user.php'
]
]);
}
public function testSendMessageWithWrongEmailAddress()
{
$model = new PasswordResetRequestForm();
$model->email = 'not-existing-email@example.com';
verify($model->sendEmail())->false();
}
public function testNotSendEmailsToInactiveUser()
{
$user = $this->tester->grabFixture('user', 1);
$model = new PasswordResetRequestForm();
$model->email = $user['email'];
verify($model->sendEmail())->false();
}
public function testSendEmailSuccessfully()
{
$userFixture = $this->tester->grabFixture('user', 0);
$model = new PasswordResetRequestForm();
$model->email = $userFixture['email'];
$user = User::findOne(['password_reset_token' => $userFixture['password_reset_token']]);
verify($model->sendEmail())->notEmpty();
verify($user->password_reset_token)->notEmpty();
$emailMessage = $this->tester->grabLastSentEmail();
verify($emailMessage)->instanceOf('yii\mail\MessageInterface');
verify($emailMessage->getTo())->arrayHasKey($model->email);
verify($emailMessage->getFrom())->arrayHasKey(Yii::$app->params['supportEmail']);
}
}

View File

@ -0,0 +1,85 @@
<?php
namespace frontend\tests\unit\models;
use Codeception\Test\Unit;
use common\fixtures\UserFixture;
use frontend\models\ResendVerificationEmailForm;
class ResendVerificationEmailFormTest extends Unit
{
/**
* @var \frontend\tests\UnitTester
*/
protected $tester;
public function _before()
{
$this->tester->haveFixtures([
'user' => [
'class' => UserFixture::class,
'dataFile' => codecept_data_dir() . 'user.php'
]
]);
}
public function testWrongEmailAddress()
{
$model = new ResendVerificationEmailForm();
$model->attributes = [
'email' => 'aaa@bbb.cc'
];
verify($model->validate())->false();
verify($model->hasErrors())->true();
verify($model->getFirstError('email'))->equals('There is no user with this email address.');
}
public function testEmptyEmailAddress()
{
$model = new ResendVerificationEmailForm();
$model->attributes = [
'email' => ''
];
verify($model->validate())->false();
verify($model->hasErrors())->true();
verify($model->getFirstError('email'))->equals('Email cannot be blank.');
}
public function testResendToActiveUser()
{
$model = new ResendVerificationEmailForm();
$model->attributes = [
'email' => 'test2@mail.com'
];
verify($model->validate())->false();
verify($model->hasErrors())->true();
verify($model->getFirstError('email'))->equals('There is no user with this email address.');
}
public function testSuccessfullyResend()
{
$model = new ResendVerificationEmailForm();
$model->attributes = [
'email' => 'test@mail.com'
];
verify($model->validate())->true();
verify($model->hasErrors())->false();
verify($model->sendEmail())->true();
$this->tester->seeEmailIsSent();
$mail = $this->tester->grabLastSentEmail();
verify($mail)->instanceOf('yii\mail\MessageInterface');
verify($mail->getTo())->arrayHasKey('test@mail.com');
verify($mail->getFrom())->arrayHasKey(\Yii::$app->params['supportEmail']);
verify($mail->getSubject())->equals('Account registration at ' . \Yii::$app->name);
verify($mail->toString())->stringContainsString('4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330');
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace frontend\tests\unit\models;
use common\fixtures\UserFixture;
use frontend\models\ResetPasswordForm;
class ResetPasswordFormTest extends \Codeception\Test\Unit
{
/**
* @var \frontend\tests\UnitTester
*/
protected $tester;
public function _before()
{
$this->tester->haveFixtures([
'user' => [
'class' => UserFixture::class,
'dataFile' => codecept_data_dir() . 'user.php'
],
]);
}
public function testResetWrongToken()
{
$this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() {
new ResetPasswordForm('');
});
$this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() {
new ResetPasswordForm('notexistingtoken_1391882543');
});
}
public function testResetCorrectToken()
{
$user = $this->tester->grabFixture('user', 0);
$form = new ResetPasswordForm($user['password_reset_token']);
verify($form->resetPassword())->notEmpty();
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace frontend\tests\unit\models;
use common\fixtures\UserFixture;
use frontend\models\SignupForm;
class SignupFormTest extends \Codeception\Test\Unit
{
/**
* @var \frontend\tests\UnitTester
*/
protected $tester;
public function _before()
{
$this->tester->haveFixtures([
'user' => [
'class' => UserFixture::class,
'dataFile' => codecept_data_dir() . 'user.php'
]
]);
}
public function testCorrectSignup()
{
$model = new SignupForm([
'username' => 'some_username',
'email' => 'some_email@example.com',
'password' => 'some_password',
]);
$user = $model->signup();
verify($user)->notEmpty();
/** @var \common\models\User $user */
$user = $this->tester->grabRecord('common\models\User', [
'username' => 'some_username',
'email' => 'some_email@example.com',
'status' => \common\models\User::STATUS_INACTIVE
]);
$this->tester->seeEmailIsSent();
$mail = $this->tester->grabLastSentEmail();
verify($mail)->instanceOf('yii\mail\MessageInterface');
verify($mail->getTo())->arrayHasKey('some_email@example.com');
verify($mail->getFrom())->arrayHasKey(\Yii::$app->params['supportEmail']);
verify($mail->getSubject())->equals('Account registration at ' . \Yii::$app->name);
verify($mail->toString())->stringContainsString($user->verification_token);
}
public function testNotCorrectSignup()
{
$model = new SignupForm([
'username' => 'troy.becker',
'email' => 'nicolas.dianna@hotmail.com',
'password' => 'some_password',
]);
verify($model->signup())->empty();
verify($model->getErrors('username'))->notEmpty();
verify($model->getErrors('email'))->notEmpty();
verify($model->getFirstError('username'))
->equals('This username has already been taken.');
verify($model->getFirstError('email'))
->equals('This email address has already been taken.');
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace frontend\tests\unit\models;
use common\fixtures\UserFixture;
use frontend\models\VerifyEmailForm;
class VerifyEmailFormTest extends \Codeception\Test\Unit
{
/**
* @var \frontend\tests\UnitTester
*/
protected $tester;
public function _before()
{
$this->tester->haveFixtures([
'user' => [
'class' => UserFixture::class,
'dataFile' => codecept_data_dir() . 'user.php'
]
]);
}
public function testVerifyWrongToken()
{
$this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() {
new VerifyEmailForm('');
});
$this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() {
new VerifyEmailForm('notexistingtoken_1391882543');
});
}
public function testAlreadyActivatedToken()
{
$this->tester->expectThrowable('\yii\base\InvalidArgumentException', function() {
new VerifyEmailForm('already_used_token_1548675330');
});
}
public function testVerifyCorrectToken()
{
$model = new VerifyEmailForm('4ch0qbfhvWwkcuWqjN8SWRq72SOw1KYT_1548675330');
$user = $model->verifyEmail();
verify($user)->instanceOf('common\models\User');
verify($user->username)->equals('test.test');
verify($user->email)->equals('test@mail.com');
verify($user->status)->equals(\common\models\User::STATUS_ACTIVE);
verify($user->validatePassword('Test1234'))->true();
}
}

86
frontend/views/layouts/main.php Executable file
View File

@ -0,0 +1,86 @@
<?php
/** @var \yii\web\View $this */
/** @var string $content */
use common\widgets\Alert;
use frontend\assets\AppAsset;
use yii\bootstrap5\Breadcrumbs;
use yii\bootstrap5\Html;
use yii\bootstrap5\Nav;
use yii\bootstrap5\NavBar;
AppAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>" class="h-100">
<head>
<meta charset="<?= Yii::$app->charset ?>">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<?php $this->registerCsrfMetaTags() ?>
<title><?= Html::encode($this->title) ?></title>
<?php $this->head() ?>
</head>
<body class="d-flex flex-column h-100">
<?php $this->beginBody() ?>
<header>
<?php
NavBar::begin([
'brandLabel' => Yii::$app->name,
'brandUrl' => Yii::$app->homeUrl,
'options' => [
'class' => 'navbar navbar-expand-md navbar-dark bg-dark fixed-top',
],
]);
$menuItems = [
['label' => 'Home', 'url' => ['/site/index']],
['label' => 'About', 'url' => ['/site/about']],
['label' => 'Contact', 'url' => ['/site/contact']],
['label' => 'Новости', 'url' => ['/news']],
['label' => 'Форма', 'url' => ['/news/data']],
];
if (Yii::$app->user->isGuest) {
$menuItems[] = ['label' => 'Signup', 'url' => ['/site/signup']];
}
echo Nav::widget([
'options' => ['class' => 'navbar-nav me-auto mb-2 mb-md-0'],
'items' => $menuItems,
]);
if (Yii::$app->user->isGuest) {
echo Html::tag('div',Html::a('Login',['/site/login'],['class' => ['btn btn-link login text-decoration-none']]),['class' => ['d-flex']]);
} else {
echo Html::beginForm(['/site/logout'], 'post', ['class' => 'd-flex'])
. Html::submitButton(
'Logout (' . Yii::$app->user->identity->username . ')',
['class' => 'btn btn-link logout text-decoration-none']
)
. Html::endForm();
}
NavBar::end();
?>
</header>
<main role="main" class="flex-shrink-0">
<div class="container">
<?= Breadcrumbs::widget([
'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
]) ?>
<?= Alert::widget() ?>
<?= $content ?>
</div>
</main>
<footer class="footer mt-auto py-3 text-muted">
<div class="container">
<p class="float-start">&copy; <?= Html::encode(Yii::$app->name) ?> <?= date('Y') ?></p>
<p class="float-end"><?= Yii::powered() ?></p>
</div>
</footer>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage();

32
frontend/views/news/data.php Executable file
View File

@ -0,0 +1,32 @@
<?php
/** @var yii\web\View $this */
/** @var yii\bootstrap5\ActiveForm $form */
/** @var \frontend\models\DataForm $model */
use yii\bootstrap5\Html;
use yii\bootstrap5\ActiveForm;
use yii\captcha\Captcha;
?>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'contact-form']); ?>
<?= $form->field($model, 'fio')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($model, 'phone')->widget(\yii\widgets\MaskedInput::class,
['mask' => '+7 (999) 999-99-99']
)->textInput(['placeholder' => '+7 (999) 999-99-99', 'class' => ''])->label('Ваш Телефон'); ?>
<div class="form-group">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>

20
frontend/views/news/index.php Executable file
View File

@ -0,0 +1,20 @@
<?php
use common\models\News;
use yii\helpers\Url;
/** @var yii\web\View $this */
/** @var News $news */
?>
<h1>Новости</h1>
<?php if (!empty($news)):
foreach ($news as $new):
?>
<div>
<a href="<?= Url::base() . '/new/' . $new->slug ?>"><?= $new->title ?></a>
<p><?= $new->text ?></p>
</div>
<?php endforeach; else: ?>
<h2>Новостей нет</h2>
<?php endif; ?>

18
frontend/views/news/one.php Executable file
View File

@ -0,0 +1,18 @@
<?php
use common\models\News;
use yii\helpers\Url;
/** @var yii\web\View $this */
/** @var News $new */
?>
<?php if (!empty($new)):?>
<div>
<h1><?= $new->title ?></h1>
<a href="<?= Url::base() . '/news' ?>">Назад</a>
<p><?= $new->text ?></p>
</div>
<?php else: ?>
<h2>Новость удалена</h2>
<?php endif; ?>

View File

@ -0,0 +1,20 @@
<?php
use common\models\Text;
/** @var yii\web\View $this */
/** @var Text[] $texts */
?>
<h1>Тексты</h1>
<?php if (!empty($texts)):
foreach ($texts as $text):
?>
<div>
<h2><?= $text->title ?></h2>
<p><?= $text->text ?></p>
<img src="<?= '/uploads/' . $text->profile->image ?>"
</div>
<?php endforeach; else: ?>
<h2>текстов нет</h2>
<?php endif; ?>

16
frontend/views/site/about.php Executable file
View File

@ -0,0 +1,16 @@
<?php
/** @var yii\web\View $this */
use yii\helpers\Html;
$this->title = 'About';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-about">
<h1><?= Html::encode($this->title) ?></h1>
<p>This is the About page. You may modify the following file to customize its content:</p>
<code><?= __FILE__ ?></code>
</div>

45
frontend/views/site/contact.php Executable file
View File

@ -0,0 +1,45 @@
<?php
/** @var yii\web\View $this */
/** @var yii\bootstrap5\ActiveForm $form */
/** @var \frontend\models\ContactForm $model */
use yii\bootstrap5\Html;
use yii\bootstrap5\ActiveForm;
use yii\captcha\Captcha;
$this->title = 'Contact';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-contact">
<h1><?= Html::encode($this->title) ?></h1>
<p>
If you have business inquiries or other questions, please fill out the following form to contact us. Thank you.
</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'contact-form']); ?>
<?= $form->field($model, 'name')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($model, 'subject') ?>
<?= $form->field($model, 'body')->textarea(['rows' => 6]) ?>
<?= $form->field($model, 'verifyCode')->widget(Captcha::class, [
'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>',
]) ?>
<div class="form-group">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

27
frontend/views/site/error.php Executable file
View File

@ -0,0 +1,27 @@
<?php
/** @var yii\web\View $this */
/** @var string $name */
/** @var string $message */
/** @var Exception $exception */
use yii\helpers\Html;
$this->title = $name;
?>
<div class="site-error">
<h1><?= Html::encode($this->title) ?></h1>
<div class="alert alert-danger">
<?= nl2br(Html::encode($message)) ?>
</div>
<p>
The above error occurred while the Web server was processing your request.
</p>
<p>
Please contact us if you think this is a server error. Thank you.
</p>
</div>

52
frontend/views/site/index.php Executable file
View File

@ -0,0 +1,52 @@
<?php
/** @var yii\web\View $this */
$this->title = 'My Yii Application';
?>
<div class="site-index">
<div class="p-5 mb-4 bg-transparent rounded-3">
<div class="container-fluid py-5 text-center">
<h1 class="display-4">Congratulations!</h1>
<p class="fs-5 fw-light">You have successfully created your Yii-powered application.</p>
<p><a class="btn btn-lg btn-success" href="http://www.yiiframework.com">Get started with Yii</a></p>
</div>
</div>
<div class="body-content">
<div class="row">
<div class="col-lg-4">
<h2>Heading</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur.</p>
<p><a class="btn btn-outline-secondary" href="http://www.yiiframework.com/doc/">Yii Documentation &raquo;</a></p>
</div>
<div class="col-lg-4">
<h2>Heading</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur.</p>
<p><a class="btn btn-outline-secondary" href="http://www.yiiframework.com/forum/">Yii Forum &raquo;</a></p>
</div>
<div class="col-lg-4">
<h2>Heading</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur.</p>
<p><a class="btn btn-outline-secondary" href="http://www.yiiframework.com/extensions/">Yii Extensions &raquo;</a></p>
</div>
</div>
</div>
</div>

41
frontend/views/site/login.php Executable file
View File

@ -0,0 +1,41 @@
<?php
/** @var yii\web\View $this */
/** @var yii\bootstrap5\ActiveForm $form */
/** @var \common\models\LoginForm $model */
use yii\bootstrap5\Html;
use yii\bootstrap5\ActiveForm;
$this->title = 'Login';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-login">
<h1><?= Html::encode($this->title) ?></h1>
<p>Please fill out the following fields to login:</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'login-form']); ?>
<?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<?= $form->field($model, 'rememberMe')->checkbox() ?>
<div class="my-1 mx-0" style="color:#999;">
If you forgot your password you can <?= Html::a('reset it', ['site/request-password-reset']) ?>.
<br>
Need new verification email? <?= Html::a('Resend', ['site/resend-verification-email']) ?>
</div>
<div class="form-group">
<?= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

View File

@ -0,0 +1,31 @@
<?php
/** @var yii\web\View $this */
/** @var yii\bootstrap5\ActiveForm $form */
/** @var \frontend\models\PasswordResetRequestForm $model */
use yii\bootstrap5\Html;
use yii\bootstrap5\ActiveForm;
$this->title = 'Request password reset';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-request-password-reset">
<h1><?= Html::encode($this->title) ?></h1>
<p>Please fill out your email. A link to reset password will be sent there.</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'request-password-reset-form']); ?>
<?= $form->field($model, 'email')->textInput(['autofocus' => true]) ?>
<div class="form-group">
<?= Html::submitButton('Send', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

View File

@ -0,0 +1,31 @@
<?php
/** @var yii\web\View$this */
/** @var yii\bootstrap5\ActiveForm $form */
/** @var \frontend\models\ResetPasswordForm $model */
use yii\bootstrap5\Html;
use yii\bootstrap5\ActiveForm;
$this->title = 'Resend verification email';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-resend-verification-email">
<h1><?= Html::encode($this->title) ?></h1>
<p>Please fill out your email. A verification email will be sent there.</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'resend-verification-email-form']); ?>
<?= $form->field($model, 'email')->textInput(['autofocus' => true]) ?>
<div class="form-group">
<?= Html::submitButton('Send', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

View File

@ -0,0 +1,31 @@
<?php
/** @var yii\web\View $this */
/** @var yii\bootstrap5\ActiveForm $form */
/** @var \frontend\models\ResetPasswordForm $model */
use yii\bootstrap5\Html;
use yii\bootstrap5\ActiveForm;
$this->title = 'Reset password';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-reset-password">
<h1><?= Html::encode($this->title) ?></h1>
<p>Please choose your new password:</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'reset-password-form']); ?>
<?= $form->field($model, 'password')->passwordInput(['autofocus' => true]) ?>
<div class="form-group">
<?= Html::submitButton('Save', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

35
frontend/views/site/signup.php Executable file
View File

@ -0,0 +1,35 @@
<?php
/** @var yii\web\View $this */
/** @var yii\bootstrap5\ActiveForm $form */
/** @var \frontend\models\SignupForm $model */
use yii\bootstrap5\Html;
use yii\bootstrap5\ActiveForm;
$this->title = 'Signup';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-signup">
<h1><?= Html::encode($this->title) ?></h1>
<p>Please fill out the following fields to signup:</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'form-signup']); ?>
<?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<div class="form-group">
<?= Html::submitButton('Signup', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

2
frontend/web/assets/.gitignore vendored Executable file
View File

@ -0,0 +1,2 @@
*
!.gitignore

103
frontend/web/css/site.css Executable file
View File

@ -0,0 +1,103 @@
main > .container, main > .container-fluid
{
padding: 70px 15px 20px;
}
.footer {
background-color: #f5f5f5;
font-size: .9em;
height: 60px;
}
.footer > .container, .footer > .container-fluid {
padding-right: 15px;
padding-left: 15px;
}
.not-set {
color: #c55;
font-style: italic;
}
/* add sorting icons to gridview sort links */
a.asc:after, a.desc:after {
content: '';
left: 3px;
display: inline-block;
width: 0;
height: 0;
border: solid 5px transparent;
margin: 4px 4px 2px 4px;
background: transparent;
}
a.asc:after {
border-bottom: solid 7px #212529;
border-top-width: 0;
}
a.desc:after {
border-top: solid 7px #212529;
border-bottom-width: 0;
}
.grid-view th,
.grid-view td:last-child {
white-space: nowrap;
}
.grid-view .filters input,
.grid-view .filters select {
min-width: 50px;
}
.hint-block {
display: block;
margin-top: 5px;
color: #999;
}
.error-summary {
color: #a94442;
background: #fdf7f7;
border-left: 3px solid #eed3d7;
padding: 10px 20px;
margin: 0 0 15px 0;
}
/* align the logout "link" (button in form) of the navbar */
.navbar form > button.logout {
padding-top: 7px;
color: rgba(255, 255, 255, 0.5);
}
@media(max-width:767px) {
.navbar form > button.logout {
display:block;
text-align: left;
width: 100%;
padding: 10px 0;
}
}
.navbar form > button.logout:focus,
.navbar form > button.logout:hover {
text-decoration: none;
color: rgba(255, 255, 255, 0.75);
}
.navbar form > button.logout:focus {
outline: none;
}
/* style breadcrumb widget as in previous bootstrap versions */
.breadcrumb {
background-color: var(--bs-gray-200);
border-radius: .25rem;
padding: .75rem 1rem;
}
.breadcrumb-item > a
{
text-decoration: none;
}

BIN
frontend/web/favicon.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 KiB