├── .editorconfig ├── .env.dist ├── .gitignore ├── .styleci.yml ├── LICENSE.md ├── README.md ├── composer.json ├── config ├── common.php ├── console.php ├── env.php ├── messages.php ├── params.php └── web.php ├── phpunit.xml.dist ├── public └── css │ └── site.css ├── requirements.php ├── runtime └── .gitignore ├── src ├── Assets │ └── AppAsset.php ├── Commands │ └── HelloController.php ├── Controllers │ └── SiteController.php ├── Forms │ ├── ContactForm.php │ └── LoginForm.php ├── Models │ └── User.php ├── Widgets │ └── Alert.php ├── mail │ └── layouts │ │ └── html.php ├── messages │ ├── bg │ │ └── yii-base-web.php │ ├── et │ │ └── yii-base-web.php │ ├── fr │ │ └── yii-base-web.php │ ├── pt-BR │ │ └── yii-base-web.php │ ├── ru │ │ └── yii-base-web.php │ └── uk │ │ └── yii-base-web.php └── views │ ├── layouts │ └── main.php │ └── site │ ├── about.php │ ├── contact.php │ ├── error.php │ ├── index.php │ └── login.php └── tests └── bootstrap.php /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | indent_style = space 10 | indent_size = 4 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /.env.dist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiisoft/yii-base-web/6310f788b4881257e67a567f71621a87db4e2376/.env.dist -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # phpstorm project files 2 | .idea 3 | 4 | # netbeans project files 5 | nbproject 6 | 7 | # zend studio for eclipse project files 8 | .buildpath 9 | .project 10 | .settings 11 | 12 | # windows thumbnail cache 13 | Thumbs.db 14 | 15 | # composer vendor dir 16 | /vendor 17 | /composer.lock 18 | 19 | # composer itself is not needed 20 | composer.phar 21 | 22 | # Mac DS_Store Files 23 | .DS_Store 24 | 25 | # phpunit itself is not needed 26 | phpunit.phar 27 | # local phpunit config 28 | /phpunit.xml 29 | 30 | tests/_output/* 31 | tests/_support/_generated 32 | 33 | #vagrant folder 34 | /.vagrant 35 | 36 | .env 37 | -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: psr12 2 | 3 | finder: 4 | exclude: 5 | - docs 6 | - vendor 7 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com) 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Yii Software LLC nor the names of its 15 | contributors may be used to endorse or promote products derived 16 | from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
The path to yii framework seems to be incorrect.
\n" 34 | . 'You need to install Yii framework via composer or adjust the framework path in file ' . basename(__FILE__) . ".
\n" 35 | . 'Please refer to the README on how to install Yii.
\n"; 36 | 37 | if (!empty($_SERVER['argv'])) { 38 | // do not print HTML when used in console mode 39 | echo strip_tags($message); 40 | } else { 41 | echo $message; 42 | } 43 | exit(1); 44 | } 45 | 46 | require_once($frameworkPath . '/requirements/YiiRequirementChecker.php'); 47 | $requirementsChecker = new YiiRequirementChecker(); 48 | 49 | $gdMemo = $imagickMemo = 'Either GD PHP extension with FreeType support or ImageMagick PHP extension with PNG support is required for image CAPTCHA.'; 50 | $gdOK = $imagickOK = false; 51 | 52 | if (extension_loaded('imagick')) { 53 | $imagick = new Imagick(); 54 | $imagickFormats = $imagick->queryFormats('PNG'); 55 | if (in_array('PNG', $imagickFormats)) { 56 | $imagickOK = true; 57 | } else { 58 | $imagickMemo = 'Imagick extension should be installed with PNG support in order to be used for image CAPTCHA.'; 59 | } 60 | } 61 | 62 | if (extension_loaded('gd')) { 63 | $gdInfo = gd_info(); 64 | if (!empty($gdInfo['FreeType Support'])) { 65 | $gdOK = true; 66 | } else { 67 | $gdMemo = 'GD extension should be installed with FreeType support in order to be used for image CAPTCHA.'; 68 | } 69 | } 70 | 71 | /** 72 | * Adjust requirements according to your application specifics. 73 | */ 74 | $requirements = array( 75 | // Database : 76 | array( 77 | 'name' => 'PDO extension', 78 | 'mandatory' => true, 79 | 'condition' => extension_loaded('pdo'), 80 | 'by' => 'All DB-related classes', 81 | ), 82 | array( 83 | 'name' => 'PDO SQLite extension', 84 | 'mandatory' => false, 85 | 'condition' => extension_loaded('pdo_sqlite'), 86 | 'by' => 'All DB-related classes', 87 | 'memo' => 'Required for SQLite database.', 88 | ), 89 | array( 90 | 'name' => 'PDO MySQL extension', 91 | 'mandatory' => false, 92 | 'condition' => extension_loaded('pdo_mysql'), 93 | 'by' => 'All DB-related classes', 94 | 'memo' => 'Required for MySQL database.', 95 | ), 96 | array( 97 | 'name' => 'PDO PostgreSQL extension', 98 | 'mandatory' => false, 99 | 'condition' => extension_loaded('pdo_pgsql'), 100 | 'by' => 'All DB-related classes', 101 | 'memo' => 'Required for PostgreSQL database.', 102 | ), 103 | // Cache : 104 | array( 105 | 'name' => 'Memcache extension', 106 | 'mandatory' => false, 107 | 'condition' => extension_loaded('memcache') || extension_loaded('memcached'), 108 | 'by' => 'MemCache', 109 | 'memo' => extension_loaded('memcached') ? 'To use memcached set MemCache::useMemcached totrue
.' : ''
110 | ),
111 | // CAPTCHA:
112 | array(
113 | 'name' => 'GD PHP extension with FreeType support',
114 | 'mandatory' => false,
115 | 'condition' => $gdOK,
116 | 'by' => 'Captcha',
117 | 'memo' => $gdMemo,
118 | ),
119 | array(
120 | 'name' => 'ImageMagick PHP extension with PNG support',
121 | 'mandatory' => false,
122 | 'condition' => $imagickOK,
123 | 'by' => 'Captcha',
124 | 'memo' => $imagickMemo,
125 | ),
126 | // PHP ini :
127 | 'phpExposePhp' => array(
128 | 'name' => 'Expose PHP',
129 | 'mandatory' => false,
130 | 'condition' => $requirementsChecker->checkPhpIniOff("expose_php"),
131 | 'by' => 'Security reasons',
132 | 'memo' => '"expose_php" should be disabled at php.ini',
133 | ),
134 | 'phpAllowUrlInclude' => array(
135 | 'name' => 'PHP allow url include',
136 | 'mandatory' => false,
137 | 'condition' => $requirementsChecker->checkPhpIniOff("allow_url_include"),
138 | 'by' => 'Security reasons',
139 | 'memo' => '"allow_url_include" should be disabled at php.ini',
140 | ),
141 | 'phpSmtp' => array(
142 | 'name' => 'PHP mail SMTP',
143 | 'mandatory' => false,
144 | 'condition' => strlen(ini_get('SMTP')) > 0,
145 | 'by' => 'Email sending',
146 | 'memo' => 'PHP mail SMTP server required',
147 | ),
148 | );
149 |
150 | // OPcache check
151 | if (!version_compare(phpversion(), '5.5', '>=')) {
152 | $requirements[] = array(
153 | 'name' => 'APC extension',
154 | 'mandatory' => false,
155 | 'condition' => extension_loaded('apc'),
156 | 'by' => 'ApcCache',
157 | );
158 | }
159 |
160 | $requirementsChecker->checkYii()->check($requirements)->render();
161 |
--------------------------------------------------------------------------------
/runtime/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
--------------------------------------------------------------------------------
/src/Assets/AppAsset.php:
--------------------------------------------------------------------------------
1 |
16 | * @since 2.0
17 | */
18 | class AppAsset extends AssetBundle
19 | {
20 | public $sourcePath = '@Yiisoft/Yii/Base/Web/../public';
21 | public $baseUrl = '@web';
22 | public $css = [
23 | 'css/site.css',
24 | ];
25 | public $js = [
26 | ];
27 | public $depends = [
28 | \Yiisoft\Yii\JQuery\YiiAsset::class,
29 | \Yiisoft\Yii\Bootstrap4\BootstrapAsset::class,
30 | ];
31 | }
32 |
--------------------------------------------------------------------------------
/src/Commands/HelloController.php:
--------------------------------------------------------------------------------
1 |
19 | * @since 2.0
20 | */
21 | class HelloController extends Controller
22 | {
23 | /**
24 | * This command echoes what you have entered as the message.
25 | * @param string $message the message to be echoed.
26 | * @return int Exit code
27 | */
28 | public function actionIndex($message = 'hello world')
29 | {
30 | echo $message . PHP_EOL;
31 |
32 | return ExitCode::OK;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Controllers/SiteController.php:
--------------------------------------------------------------------------------
1 | [
18 | '__class' => AccessControl::class,
19 | 'only' => ['logout'],
20 | 'rules' => [
21 | [
22 | 'actions' => ['logout'],
23 | 'allow' => true,
24 | 'roles' => ['@'],
25 | ],
26 | ],
27 | ],
28 | 'verbs' => [
29 | '__class' => VerbFilter::class,
30 | 'actions' => [
31 | 'logout' => ['POST'],
32 | ],
33 | ],
34 | ];
35 | }
36 |
37 | public function actions()
38 | {
39 | return [
40 | 'error' => [
41 | '__class' => \yii\web\ErrorAction::class,
42 | ],
43 | 'captcha' => [
44 | '__class' => \Yiisoft\Yii\Captcha\CaptchaAction::class,
45 | 'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
46 | ],
47 | ];
48 | }
49 |
50 | /**
51 | * Displays homepage.
52 | *
53 | * @return string
54 | */
55 | public function actionIndex()
56 | {
57 | $this->app->getSession()->addFlash('info', 'Hello World! This is a flash message.');
58 | return $this->render('index');
59 | }
60 |
61 | /**
62 | * Login action.
63 | *
64 | * @return Response|string
65 | */
66 | public function actionLogin()
67 | {
68 | $requiredPackages = [
69 | 'rbac' => \Yiisoft\Rbac\Permission::class,
70 | #'db-mysql' => \Yiisoft\Db\Mysql\Schema::class,
71 | 'yii-bootstrap4' => \Yiisoft\Yii\Bootstrap4\ActiveForm::class,
72 | ];
73 | $setupIncomplete = in_array(false, array_map('class_exists', $requiredPackages));
74 |
75 | if (!$setupIncomplete && !$this->app->user->isGuest) {
76 | return $this->goHome();
77 | }
78 |
79 | $model = new LoginForm();
80 | if ($model->load($this->app->request->post()) && $model->login()) {
81 | return $this->goBack();
82 | }
83 |
84 | $model->password = '';
85 | return $this->render('login', [
86 | 'model' => $model,
87 | 'requiredPackages' => $requiredPackages,
88 | 'setupIncomplete' => $setupIncomplete,
89 | ]);
90 | }
91 |
92 | /**
93 | * Logout action.
94 | *
95 | * @return Response
96 | */
97 | public function actionLogout()
98 | {
99 | $this->app->user->logout();
100 |
101 | return $this->goHome();
102 | }
103 |
104 | /**
105 | * Displays contact page.
106 | *
107 | * @return Response|string
108 | */
109 | public function actionContact()
110 | {
111 | $model = new ContactForm();
112 | if ($model->load($this->app->request->post()) && $model->contact($this->app->params['adminEmail'], $this->app->get('mailer'))) {
113 | $this->app->session->setFlash('contactFormSubmitted');
114 |
115 | return $this->refresh();
116 | }
117 |
118 | $requiredPackages = [
119 | 'yii-jquery' => '\Yiisoft\Yii\JQuery\ActiveFormClientScript',
120 | 'yii-bootstrap4' => '\Yiisoft\Yii\Bootstrap4\ActiveForm',
121 | 'yii-captcha' => '\Yiisoft\Yii\Captcha\Captcha',
122 | ];
123 | $setupIncomplete = in_array(false, array_map('class_exists', $requiredPackages));
124 |
125 | return $this->render('contact', [
126 | 'model' => $model,
127 | 'requiredPackages' => $requiredPackages,
128 | 'setupIncomplete' => $setupIncomplete,
129 | ]);
130 | }
131 |
132 | /**
133 | * Displays about page.
134 | *
135 | * @return string
136 | */
137 | public function actionAbout()
138 | {
139 | return $this->render('about');
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/Forms/ContactForm.php:
--------------------------------------------------------------------------------
1 | '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 | * @param MailerInterface $mailer
50 | * @return bool whether the model passes validation
51 | */
52 | public function contact(string $email, MailerInterface $mailer)
53 | {
54 | if ($this->validate()) {
55 | $mailer->compose()
56 | ->setTo($email)
57 | ->setFrom([$this->email => $this->name])
58 | ->setSubject($this->subject)
59 | ->setTextBody($this->body)
60 | ->send();
61 |
62 | return true;
63 | }
64 | return false;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Forms/LoginForm.php:
--------------------------------------------------------------------------------
1 | hasErrors()) {
49 | $user = $this->getUser();
50 |
51 | if (!$user || !$user->validatePassword($this->password)) {
52 | $this->addError($attribute, 'Incorrect username or password.');
53 | }
54 | }
55 | }
56 |
57 | /**
58 | * Logs in a user using the provided username and password.
59 | * @return bool whether the user is logged in successfully
60 | */
61 | public function login()
62 | {
63 | if ($this->validate()) {
64 | return Yii::getApp()->getUser()->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
65 | }
66 | return false;
67 | }
68 |
69 | /**
70 | * Finds user by [[username]]
71 | *
72 | * @return User|null
73 | */
74 | public function getUser()
75 | {
76 | if ($this->_user === false) {
77 | $this->_user = User::findByUsername($this->username);
78 | }
79 |
80 | return $this->_user;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Models/User.php:
--------------------------------------------------------------------------------
1 | self::STATUS_ACTIVE],
46 | ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
47 | ];
48 | }
49 |
50 | public static function findIdentity($id)
51 | {
52 | return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
53 | }
54 |
55 | public static function findIdentityByAccessToken($token, $type = null)
56 | {
57 | throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
58 | }
59 |
60 | /**
61 | * Finds user by username
62 | *
63 | * @param string $username
64 | * @return static|null
65 | */
66 | public static function findByUsername($username)
67 | {
68 | return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);
69 | }
70 |
71 | /**
72 | * Finds user by password reset token
73 | *
74 | * @param string $token password reset token
75 | * @return static|null
76 | */
77 | public static function findByPasswordResetToken($token)
78 | {
79 | if (!static::isPasswordResetTokenValid($token)) {
80 | return null;
81 | }
82 |
83 | return static::findOne([
84 | 'password_reset_token' => $token,
85 | 'status' => self::STATUS_ACTIVE,
86 | ]);
87 | }
88 |
89 | /**
90 | * Finds out if password reset token is valid
91 | *
92 | * @param string $token password reset token
93 | * @return bool
94 | */
95 | public static function isPasswordResetTokenValid($token)
96 | {
97 | if (empty($token)) {
98 | return false;
99 | }
100 |
101 | $timestamp = (int) substr($token, strrpos($token, '_') + 1);
102 | $expire = Yii::getApp()->params['user.passwordResetTokenExpire'];
103 | return $timestamp + $expire >= time();
104 | }
105 |
106 | public function getId()
107 | {
108 | return $this->getPrimaryKey();
109 | }
110 |
111 | public function getAuthKey()
112 | {
113 | return $this->auth_key;
114 | }
115 |
116 | public function validateAuthKey($authKey)
117 | {
118 | return $this->getAuthKey() === $authKey;
119 | }
120 |
121 | /**
122 | * Validates password
123 | *
124 | * @param string $password password to validate
125 | * @return bool if password provided is valid for current user
126 | */
127 | public function validatePassword($password)
128 | {
129 | return Yii::getApp()->security->validatePassword($password, $this->password_hash);
130 | }
131 |
132 | /**
133 | * Generates password hash from password and sets it to the model
134 | *
135 | * @param string $password
136 | */
137 | public function setPassword($password)
138 | {
139 | $this->password_hash = Yii::getApp()->security->generatePasswordHash($password);
140 | }
141 |
142 | /**
143 | * Generates "remember me" authentication key
144 | */
145 | public function generateAuthKey()
146 | {
147 | $this->auth_key = Yii::getApp()->security->generateRandomString();
148 | }
149 |
150 | /**
151 | * Generates new password reset token
152 | */
153 | public function generatePasswordResetToken()
154 | {
155 | $this->password_reset_token = Yii::getApp()->security->generateRandomString() . '_' . time();
156 | }
157 |
158 | /**
159 | * Removes password reset token
160 | */
161 | public function removePasswordResetToken()
162 | {
163 | $this->password_reset_token = null;
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/src/Widgets/Alert.php:
--------------------------------------------------------------------------------
1 | session->setFlash('error', 'This is the message');
14 | * Yii::$app->session->setFlash('success', 'This is the message');
15 | * Yii::$app->session->setFlash('info', 'This is the message');
16 | * ```
17 | *
18 | * Multiple messages could be set as follows:
19 | *
20 | * ```php
21 | * Yii::$app->session->setFlash('error', ['Error 1', 'Error 2']);
22 | * ```
23 | *
24 | * @author Kartik Visweswaran 14 | This is the About page. Its content is located at: 15 |
16 | 17 |= Html::encode(__FILE__) ?>
18 |
34 | Note that if you turn on the Yii debugger, you should be able
35 | to view the mail message on the mail panel of the debugger.
36 | app->get('mailer')->useFileTransport): ?>
37 | Because the application is in development mode, the email is not sent but saved as
38 | a file under = $this->app->getAlias($this->app->get('mailer')->fileTransportPath) ?>
.
39 | Please configure the useFileTransport
property of the mail
40 | application component to be false to enable email sending.
41 |
42 |
46 | If you have business inquiries or other questions, please fill out the following form to contact us. 47 | Thank you. 48 |
49 | 50 |21 | The above error occurred while the Web server was processing your request. 22 |
23 |24 | Please contact us if you think this is a server error. Thank you. 25 |
26 | 27 |= $this->app->t('yii-base-web', 'You have successfully created your Yii-powered application.') ?>
15 | 16 | 17 |26 | This is the Index page. Its content is located at: 27 |
28 | 29 |= Html::encode(__FILE__) ?>
30 |
31 | List of actions in the application-base site controller:
36 |37 | = Html::a('About', ['about']) ?> 38 | = Html::a('Contact', ['contact']) ?> 39 | = Html::a('Login', ['login']) ?> 40 |
41 |More information about Yii 3.x Framework online:
46 | 47 |= $this->app->t('yii-base-web', 'Yii Forum') ?> »
48 | 49 | 50 |Please fill out the following fields to login:
29 | 30 | 'login-form', 32 | 'layout' => 'horizontal', 33 | 'fieldConfig' => [ 34 | 'template' => "{label}\napp\models\User::$users
.
58 |