├── .bowerrc
├── .gitignore
├── .htaccess
├── LICENSE.md
├── README.md
├── Vagrantfile
├── backend
├── assets
│ └── AppAsset.php
├── codeception.yml
├── config
│ ├── .gitignore
│ ├── bootstrap.php
│ ├── main.php
│ ├── params.php
│ └── test.php
├── models
│ └── .gitkeep
├── runtime
│ └── .gitignore
├── tests
│ ├── _bootstrap.php
│ ├── _data
│ │ ├── .gitignore
│ │ └── login_data.php
│ ├── _output
│ │ └── .gitignore
│ ├── _support
│ │ ├── .gitignore
│ │ ├── FunctionalTester.php
│ │ └── UnitTester.php
│ ├── functional.suite.yml
│ ├── functional
│ │ ├── LoginCest.php
│ │ └── _bootstrap.php
│ ├── unit.suite.yml
│ └── unit
│ │ └── _bootstrap.php
├── views
│ └── layouts
│ │ └── main.php
└── web
│ ├── .gitignore
│ ├── .htaccess
│ ├── assets
│ └── .gitignore
│ ├── css
│ └── site.css
│ ├── favicon.ico
│ └── robots.txt
├── codeception.yml
├── common
├── codeception.yml
├── config
│ ├── .gitignore
│ ├── bootstrap.php
│ ├── main.php
│ ├── params.php
│ └── test.php
├── fixtures
│ └── User.php
├── mail
│ ├── layouts
│ │ ├── html.php
│ │ └── text.php
│ ├── passwordResetToken-html.php
│ └── passwordResetToken-text.php
├── models
│ ├── LoginForm.php
│ └── User.php
├── tests
│ ├── _bootstrap.php
│ ├── _data
│ │ └── user.php
│ ├── _output
│ │ └── .gitignore
│ ├── _support
│ │ ├── .gitignore
│ │ └── UnitTester.php
│ ├── unit.suite.yml
│ └── unit
│ │ └── models
│ │ └── LoginFormTest.php
└── widgets
│ └── Alert.php
├── composer.json
├── composer.lock
├── console
├── config
│ ├── .gitignore
│ ├── bootstrap.php
│ ├── main.php
│ └── params.php
├── controllers
│ └── .gitkeep
├── migrations
│ └── m130524_201442_init.php
├── models
│ └── .gitkeep
└── runtime
│ └── .gitignore
├── environments
├── dev
│ ├── backend
│ │ ├── config
│ │ │ ├── main-local.php
│ │ │ ├── params-local.php
│ │ │ └── test-local.php
│ │ └── web
│ │ │ ├── index-test.php
│ │ │ └── index.php
│ ├── common
│ │ └── config
│ │ │ ├── main-local.php
│ │ │ ├── params-local.php
│ │ │ └── test-local.php
│ ├── console
│ │ └── config
│ │ │ ├── main-local.php
│ │ │ └── params-local.php
│ ├── frontend
│ │ ├── config
│ │ │ ├── main-local.php
│ │ │ ├── params-local.php
│ │ │ └── test-local.php
│ │ └── web
│ │ │ ├── index-test.php
│ │ │ └── index.php
│ ├── yii
│ ├── yii_test
│ └── yii_test.bat
├── index.php
└── prod
│ ├── backend
│ ├── config
│ │ ├── main-local.php
│ │ └── params-local.php
│ └── web
│ │ └── index.php
│ ├── common
│ └── config
│ │ ├── main-local.php
│ │ └── params-local.php
│ ├── console
│ └── config
│ │ ├── main-local.php
│ │ └── params-local.php
│ ├── frontend
│ ├── config
│ │ ├── main-local.php
│ │ └── params-local.php
│ └── web
│ │ └── index.php
│ └── yii
├── frontend
├── assets
│ ├── AngularAsset.php
│ └── AppAsset.php
├── codeception.yml
├── config
│ ├── .gitignore
│ ├── bootstrap.php
│ ├── main.php
│ ├── params.php
│ └── test.php
├── runtime
│ └── .gitignore
├── tests
│ ├── _bootstrap.php
│ ├── _data
│ │ ├── login_data.php
│ │ └── user.php
│ ├── _output
│ │ └── .gitignore
│ ├── _support
│ │ ├── .gitignore
│ │ ├── FunctionalTester.php
│ │ └── UnitTester.php
│ ├── acceptance.suite.yml.example
│ ├── acceptance
│ │ ├── HomeCest.php
│ │ └── _bootstrap.php
│ ├── functional.suite.yml
│ ├── functional
│ │ ├── AboutCest.php
│ │ ├── ContactCest.php
│ │ ├── HomeCest.php
│ │ ├── LoginCest.php
│ │ ├── SignupCest.php
│ │ └── _bootstrap.php
│ ├── unit.suite.yml
│ └── unit
│ │ ├── _bootstrap.php
│ │ └── models
│ │ ├── ContactFormTest.php
│ │ ├── PasswordResetRequestFormTest.php
│ │ ├── ResetPasswordFormTest.php
│ │ └── SignupFormTest.php
├── views
│ └── layouts
│ │ └── main.php
└── web
│ ├── .gitignore
│ ├── .htaccess
│ ├── assets
│ └── .gitignore
│ ├── css
│ └── site.css
│ ├── favicon.ico
│ ├── js
│ ├── app.js
│ ├── controllers.js
│ ├── directives.js
│ └── services.js
│ └── robots.txt
├── init
├── init.bat
├── modules
├── autoposting
│ ├── Module.php
│ └── behaviors
│ │ └── AutopostingBehavior.php
├── cars
│ ├── Bootstrap.php
│ ├── Module.php
│ ├── controllers
│ │ ├── backend
│ │ │ └── DefaultController.php
│ │ └── frontend
│ │ │ └── DefaultController.php
│ └── views
│ │ ├── backend
│ │ └── default
│ │ │ └── index.php
│ │ └── frontend
│ │ └── default
│ │ └── index.php
├── lease
│ ├── Bootstrap.php
│ ├── Module.php
│ ├── controllers
│ │ ├── backend
│ │ │ └── DefaultController.php
│ │ └── frontend
│ │ │ ├── ApiController.php
│ │ │ └── DefaultController.php
│ ├── migrations
│ │ └── m150717_132906_create_table_lease.php
│ ├── models
│ │ └── frontend
│ │ │ └── Lease.php
│ └── views
│ │ ├── backend
│ │ └── default
│ │ │ └── index.php
│ │ └── frontend
│ │ └── default
│ │ └── index.php
├── seo
│ ├── Bootstrap.php
│ ├── Module.php
│ ├── components
│ │ └── UrlRule.php
│ ├── helpers
│ │ └── Meta.php
│ ├── migrations
│ │ └── m150729_120945_create_table_route.php
│ ├── models
│ │ └── Route.php
│ └── views
│ │ └── default
│ │ └── index.php
├── site
│ ├── Bootstrap.php
│ ├── Module.php
│ ├── controllers
│ │ ├── backend
│ │ │ └── SiteController.php
│ │ └── frontend
│ │ │ └── SiteController.php
│ ├── models
│ │ └── frontend
│ │ │ ├── ContactForm.php
│ │ │ ├── PasswordResetRequestForm.php
│ │ │ ├── ResetPasswordForm.php
│ │ │ └── SignupForm.php
│ └── views
│ │ ├── backend
│ │ └── site
│ │ │ ├── error.php
│ │ │ ├── index.php
│ │ │ └── login.php
│ │ └── frontend
│ │ └── site
│ │ ├── about.php
│ │ ├── contact.php
│ │ ├── error.php
│ │ ├── index.php
│ │ ├── login.php
│ │ ├── requestPasswordResetToken.php
│ │ ├── resetPassword.php
│ │ └── signup.php
├── users
│ ├── Bootstrap.php
│ ├── Module.php
│ ├── controllers
│ │ ├── backend
│ │ │ └── DefaultController.php
│ │ └── frontend
│ │ │ └── DefaultController.php
│ └── views
│ │ ├── backend
│ │ └── default
│ │ │ └── index.php
│ │ └── frontend
│ │ └── default
│ │ └── index.php
└── zipdata
│ ├── Module.php
│ ├── migrations
│ └── m150722_100330_create_zipdata_table.php
│ └── models
│ ├── Zip.php
│ └── ZipSearch.php
├── requirements.php
├── vagrant
├── config
│ ├── .gitignore
│ └── vagrant-local.example.yml
├── nginx
│ ├── app.conf
│ └── log
│ │ └── .gitignore
└── provision
│ ├── always-as-root.sh
│ ├── once-as-root.sh
│ └── once-as-vagrant.sh
└── yii.bat
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory" : "vendor/bower"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # yii console commands
2 | /yii
3 | /yii_test
4 | /yii_test.bat
5 |
6 | # phpstorm project files
7 | .idea
8 |
9 | # netbeans project files
10 | nbproject
11 |
12 | # zend studio for eclipse project files
13 | .buildpath
14 | .project
15 | .settings
16 |
17 | # windows thumbnail cache
18 | Thumbs.db
19 |
20 | # composer vendor dir
21 | /vendor
22 |
23 | # composer itself is not needed
24 | composer.phar
25 | composer.lock
26 |
27 | # Mac DS_Store Files
28 | .DS_Store
29 |
30 | # phpunit itself is not needed
31 | phpunit.phar
32 | # local phpunit config
33 | /phpunit.xml
34 |
35 | # vagrant runtime
36 | /.vagrant
37 |
--------------------------------------------------------------------------------
/.htaccess:
--------------------------------------------------------------------------------
1 | # Mod_Autoindex
2 |
3 | # Disable Indexes
4 | Options -Indexes
5 |
6 |
7 | # Mod_Rewrite
8 |
9 | # Enable symlinks
10 | Options +FollowSymlinks
11 | # Enable mod_rewrite
12 | RewriteEngine On
13 |
14 | RewriteCond %{REQUEST_URI} ^/backend
15 | RewriteRule ^backend/(.*)$ backend/web/$1 [L]
16 |
17 | # Frontend redirect
18 | RewriteCond %{REQUEST_URI} ^(.*)$
19 | RewriteRule ^(.*)$ frontend/web/$1
20 |
21 |
--------------------------------------------------------------------------------
/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.
33 |
--------------------------------------------------------------------------------
/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 | [](https://packagist.org/packages/yiisoft/yii2-app-advanced)
16 | [](https://packagist.org/packages/yiisoft/yii2-app-advanced)
17 | [](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 | ```
56 |
--------------------------------------------------------------------------------
/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
73 |
--------------------------------------------------------------------------------
/backend/assets/AppAsset.php:
--------------------------------------------------------------------------------
1 | 'app-backend',
11 | 'basePath' => dirname(__DIR__),
12 | 'defaultRoute' => 'site/site/index',
13 | 'bootstrap' => ['log'],
14 | 'modules' => [
15 | 'site' => [
16 | 'isBackend' => true,
17 | ],
18 | 'cars' => [
19 | 'isBackend' => true,
20 | ],
21 | 'lease' => [
22 | 'isBackend' => true,
23 | ],
24 | 'seo' => [
25 | 'isBackend' => true,
26 | ],
27 | 'users' => [
28 | 'isBackend' => true,
29 | ]
30 | ],
31 | 'components' => [
32 | 'request' => [
33 | 'csrfParam' => '_csrf-backend',
34 | ],
35 | 'user' => [
36 | 'identityClass' => 'common\models\User',
37 | 'loginUrl' => ['site/site/login'],
38 | 'enableAutoLogin' => true,
39 | 'identityCookie' => ['name' => '_identity-backend', 'httpOnly' => true],
40 | ],
41 | 'session' => [
42 | // this is the name of the session cookie used for login on the backend
43 | 'name' => 'advanced-backend',
44 | ],
45 | 'log' => [
46 | 'traceLevel' => YII_DEBUG ? 3 : 0,
47 | 'targets' => [
48 | [
49 | 'class' => 'yii\log\FileTarget',
50 | 'levels' => ['error', 'warning'],
51 | ],
52 | ],
53 | ],
54 | 'errorHandler' => [
55 | 'errorAction' => 'site/site/error',
56 | ],
57 | 'urlManager' => [
58 | 'enablePrettyUrl' => true,
59 | 'showScriptName' => false
60 | ],
61 | ],
62 | 'params' => $params,
63 | ];
64 |
--------------------------------------------------------------------------------
/backend/config/params.php:
--------------------------------------------------------------------------------
1 | 'admin@example.com',
4 | ];
5 |
--------------------------------------------------------------------------------
/backend/config/test.php:
--------------------------------------------------------------------------------
1 | 'app-backend-tests',
4 | ];
5 |
--------------------------------------------------------------------------------
/backend/models/.gitkeep:
--------------------------------------------------------------------------------
1 | *
2 |
--------------------------------------------------------------------------------
/backend/runtime/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
--------------------------------------------------------------------------------
/backend/tests/_bootstrap.php:
--------------------------------------------------------------------------------
1 | '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 | ];
14 |
--------------------------------------------------------------------------------
/backend/tests/_output/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/backend/tests/_support/.gitignore:
--------------------------------------------------------------------------------
1 | _generated
2 |
--------------------------------------------------------------------------------
/backend/tests/_support/FunctionalTester.php:
--------------------------------------------------------------------------------
1 | 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/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 | }
37 |
--------------------------------------------------------------------------------
/backend/tests/functional/_bootstrap.php:
--------------------------------------------------------------------------------
1 |
15 | beginPage() ?>
16 |
17 |
18 |
19 |
20 |
21 | = Html::csrfMetaTags() ?>
22 | = Html::encode($this->title) ?>
23 | head() ?>
24 |
25 |
26 | beginBody() ?>
27 |
28 |
29 | '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/site/index']],
39 | ];
40 | if (Yii::$app->user->isGuest) {
41 | $menuItems[] = ['label' => 'Login', 'url' => ['/site/site/login']];
42 | } else {
43 | $menuItems[] = '
'
44 | . Html::beginForm(['/site/site/logout'], 'post')
45 | . Html::submitButton(
46 | 'Logout (' . Yii::$app->user->identity->username . ')',
47 | ['class' => 'btn btn-link logout']
48 | )
49 | . Html::endForm()
50 | . '';
51 | }
52 | echo Nav::widget([
53 | 'options' => ['class' => 'navbar-nav navbar-right'],
54 | 'items' => $menuItems,
55 | ]);
56 | NavBar::end();
57 | ?>
58 |
59 |
60 | = Breadcrumbs::widget([
61 | 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
62 | ]) ?>
63 | = Alert::widget() ?>
64 | = $content ?>
65 |
66 |
67 |
68 |
75 |
76 | endBody() ?>
77 |
78 |
79 | endPage() ?>
80 |
--------------------------------------------------------------------------------
/backend/web/.gitignore:
--------------------------------------------------------------------------------
1 | /index.php
2 | /index-test.php
3 |
--------------------------------------------------------------------------------
/backend/web/.htaccess:
--------------------------------------------------------------------------------
1 | # Mod_Rewrite
2 |
3 | # Enable mod_rewrite
4 | RewriteEngine On
5 |
6 | # If a directory or a file exists, use the request directly
7 | RewriteCond %{REQUEST_FILENAME} !-f
8 | RewriteCond %{REQUEST_FILENAME} !-d
9 | # Otherwise forward the request to index.php
10 | RewriteRule . index.php
11 |
--------------------------------------------------------------------------------
/backend/web/assets/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/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 | }
121 |
--------------------------------------------------------------------------------
/backend/web/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pavelsingree/yii2-angular/46f2c48a4ac0c8e011200944db48c798da2fa30d/backend/web/favicon.ico
--------------------------------------------------------------------------------
/backend/web/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /
3 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/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'
16 |
--------------------------------------------------------------------------------
/common/config/.gitignore:
--------------------------------------------------------------------------------
1 | main-local.php
2 | params-local.php
3 | test-local.php
4 |
--------------------------------------------------------------------------------
/common/config/bootstrap.php:
--------------------------------------------------------------------------------
1 | dirname(dirname(__DIR__)) . '/vendor',
4 | 'components' => [
5 | 'cache' => [
6 | 'class' => 'yii\caching\FileCache',
7 | ],
8 | ],
9 | 'modules' => [
10 | 'site' => [
11 | 'class' => 'modules\site\Module',
12 | ],
13 | 'cars' => [
14 | 'class' => 'modules\cars\Module',
15 | ],
16 | 'lease' => [
17 | 'class' => 'modules\lease\Module',
18 | ],
19 | 'seo' => [
20 | 'class' => 'modules\seo\Module',
21 | ],
22 | 'users' => [
23 | 'class' => 'modules\users\Module',
24 | ],
25 | 'zipdata' => [
26 | 'class' => 'modules\zipdata\Module',
27 | ],
28 | ],
29 | ];
30 |
--------------------------------------------------------------------------------
/common/config/params.php:
--------------------------------------------------------------------------------
1 | 'admin@example.com',
4 | 'supportEmail' => 'support@example.com',
5 | 'user.passwordResetTokenExpire' => 3600,
6 | 'autoposting' => [
7 | 'twitter' => [
8 | 'consumer_key' => "XYNpO5yj0shMgH43j4lYKMDfH",
9 | 'consumer_secret' => "VevyEwrhHxabcQgN2S0KuL1i9Gx9CnPXyM2yVLfQ0LlJSZ7BmF",
10 | 'oauth_token' => "3432829204-6IS6o3hGW3xouvgCso279o4ODU15grLLUy0iWPX",
11 | 'oauth_secret' => "vGzYOtJkcx8PK96YcyUdXM6PtqmhGiVLmHOqCDHM2lkIq",
12 | ],
13 | 'facebook' => [
14 | 'page_id' => '1629966630552080',
15 | 'page_access_token' => '326799827727254|aRtZuU48IqeJ0s8SY6sVOIfPAiA'
16 | ]
17 | ]
18 | ];
19 |
--------------------------------------------------------------------------------
/common/config/test.php:
--------------------------------------------------------------------------------
1 | 'app-common-tests',
4 | 'basePath' => dirname(__DIR__),
5 | 'components' => [
6 | 'user' => [
7 | 'class' => 'yii\web\User',
8 | 'identityClass' => 'common\models\User',
9 | ],
10 | ],
11 | ];
12 |
--------------------------------------------------------------------------------
/common/fixtures/User.php:
--------------------------------------------------------------------------------
1 |
8 | beginPage() ?>
9 |
10 |
11 |
12 |
13 | = Html::encode($this->title) ?>
14 | head() ?>
15 |
16 |
17 | beginBody() ?>
18 | = $content ?>
19 | endBody() ?>
20 |
21 |
22 | endPage() ?>
23 |
--------------------------------------------------------------------------------
/common/mail/layouts/text.php:
--------------------------------------------------------------------------------
1 |
9 |
10 | beginPage() ?>
11 | beginBody() ?>
12 | = $content ?>
13 | endBody() ?>
14 | endPage() ?>
15 |
--------------------------------------------------------------------------------
/common/mail/passwordResetToken-html.php:
--------------------------------------------------------------------------------
1 | urlManager->createAbsoluteUrl(['site/site/reset-password', 'token' => $user->password_reset_token]);
8 | ?>
9 |
10 |
Hello = Html::encode($user->username) ?>,
11 |
12 |
Follow the link below to reset your password:
13 |
14 |
= Html::a(Html::encode($resetLink), $resetLink) ?>
15 |
16 |
--------------------------------------------------------------------------------
/common/mail/passwordResetToken-text.php:
--------------------------------------------------------------------------------
1 | urlManager->createAbsoluteUrl(['site/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 ?>
13 |
--------------------------------------------------------------------------------
/common/models/LoginForm.php:
--------------------------------------------------------------------------------
1 | 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 | }
79 |
--------------------------------------------------------------------------------
/common/models/User.php:
--------------------------------------------------------------------------------
1 | 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 | }
190 |
--------------------------------------------------------------------------------
/common/tests/_bootstrap.php:
--------------------------------------------------------------------------------
1 | '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 | ];
15 |
--------------------------------------------------------------------------------
/common/tests/_output/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/common/tests/_support/.gitignore:
--------------------------------------------------------------------------------
1 | _generated
2 |
--------------------------------------------------------------------------------
/common/tests/_support/UnitTester.php:
--------------------------------------------------------------------------------
1 | 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 | }
65 |
--------------------------------------------------------------------------------
/common/widgets/Alert.php:
--------------------------------------------------------------------------------
1 | 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
23 | * @author Alexander Makarov
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 | }
76 |
--------------------------------------------------------------------------------
/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 | "bower-asset/angular": "^1.5",
22 | "bower-asset/angular-animate": "^1.5",
23 | "bower-asset/angular-bootstrap": "^2.2",
24 | "abraham/twitteroauth": "^0.7.2"
25 | },
26 | "require-dev": {
27 | "yiisoft/yii2-debug": "~2.0.0",
28 | "yiisoft/yii2-gii": "~2.0.0",
29 | "yiisoft/yii2-faker": "~2.0.0",
30 |
31 | "codeception/base": "^2.2.3",
32 | "codeception/verify": "~0.3.1"
33 | },
34 | "config": {
35 | "process-timeout": 1800
36 | },
37 | "extra": {
38 | "asset-installer-paths": {
39 | "npm-asset-library": "vendor/npm",
40 | "bower-asset-library": "vendor/bower"
41 | }
42 | },
43 | "scripts": {
44 | "post-install-cmd": "php init --env=Development --overwrite=n"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/console/config/.gitignore:
--------------------------------------------------------------------------------
1 | main-local.php
2 | params-local.php
--------------------------------------------------------------------------------
/console/config/bootstrap.php:
--------------------------------------------------------------------------------
1 | '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 | ];
26 |
--------------------------------------------------------------------------------
/console/config/params.php:
--------------------------------------------------------------------------------
1 | 'admin@example.com',
4 | ];
5 |
--------------------------------------------------------------------------------
/console/controllers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pavelsingree/yii2-angular/46f2c48a4ac0c8e011200944db48c798da2fa30d/console/controllers/.gitkeep
--------------------------------------------------------------------------------
/console/migrations/m130524_201442_init.php:
--------------------------------------------------------------------------------
1 | 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 | }
34 |
--------------------------------------------------------------------------------
/console/models/.gitkeep:
--------------------------------------------------------------------------------
1 | *
2 |
--------------------------------------------------------------------------------
/console/runtime/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
--------------------------------------------------------------------------------
/environments/dev/backend/config/main-local.php:
--------------------------------------------------------------------------------
1 | [
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;
26 |
--------------------------------------------------------------------------------
/environments/dev/backend/config/params-local.php:
--------------------------------------------------------------------------------
1 | run();
19 |
--------------------------------------------------------------------------------
/environments/dev/backend/web/index.php:
--------------------------------------------------------------------------------
1 | run();
18 |
--------------------------------------------------------------------------------
/environments/dev/common/config/main-local.php:
--------------------------------------------------------------------------------
1 | [
4 | 'db' => [
5 | 'class' => 'yii\db\Connection',
6 | 'dsn' => 'mysql:host=localhost;dbname=yii2-angular',
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 | ];
21 |
--------------------------------------------------------------------------------
/environments/dev/common/config/params-local.php:
--------------------------------------------------------------------------------
1 | [
8 | 'db' => [
9 | 'dsn' => 'mysql:host=localhost;dbname=yii2advanced_test',
10 | ]
11 | ],
12 | ]
13 | );
14 |
--------------------------------------------------------------------------------
/environments/dev/console/config/main-local.php:
--------------------------------------------------------------------------------
1 | ['gii'],
4 | 'modules' => [
5 | 'gii' => 'yii\gii\Module',
6 | ],
7 | ];
8 |
--------------------------------------------------------------------------------
/environments/dev/console/config/params-local.php:
--------------------------------------------------------------------------------
1 | [
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;
26 |
--------------------------------------------------------------------------------
/environments/dev/frontend/config/params-local.php:
--------------------------------------------------------------------------------
1 | run();
19 |
--------------------------------------------------------------------------------
/environments/dev/frontend/web/index.php:
--------------------------------------------------------------------------------
1 | run();
18 |
--------------------------------------------------------------------------------
/environments/dev/yii:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | run();
28 | exit($exitCode);
29 |
--------------------------------------------------------------------------------
/environments/dev/yii_test:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | run();
27 | exit($exitCode);
28 |
--------------------------------------------------------------------------------
/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
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
21 |
--------------------------------------------------------------------------------
/environments/index.php:
--------------------------------------------------------------------------------
1 | [
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 | ];
66 |
--------------------------------------------------------------------------------
/environments/prod/backend/config/main-local.php:
--------------------------------------------------------------------------------
1 | [
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 | ];
10 |
--------------------------------------------------------------------------------
/environments/prod/backend/config/params-local.php:
--------------------------------------------------------------------------------
1 | run();
18 |
--------------------------------------------------------------------------------
/environments/prod/common/config/main-local.php:
--------------------------------------------------------------------------------
1 | [
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 | ];
17 |
--------------------------------------------------------------------------------
/environments/prod/common/config/params-local.php:
--------------------------------------------------------------------------------
1 | [
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 | ];
10 |
--------------------------------------------------------------------------------
/environments/prod/frontend/config/params-local.php:
--------------------------------------------------------------------------------
1 | run();
18 |
--------------------------------------------------------------------------------
/environments/prod/yii:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | run();
28 | exit($exitCode);
29 |
--------------------------------------------------------------------------------
/frontend/assets/AngularAsset.php:
--------------------------------------------------------------------------------
1 | View::POS_HEAD,
19 | ];
20 | }
--------------------------------------------------------------------------------
/frontend/assets/AppAsset.php:
--------------------------------------------------------------------------------
1 | 'app-frontend',
11 | 'basePath' => dirname(__DIR__),
12 | 'bootstrap' => [
13 | 'log',
14 | 'modules\site\Bootstrap',
15 | 'modules\users\Bootstrap',
16 | 'modules\cars\Bootstrap',
17 | 'modules\lease\Bootstrap',
18 | 'modules\seo\Bootstrap'
19 | ],
20 | 'defaultRoute' => 'site/site/index',
21 | 'components' => [
22 | 'request' => [
23 | 'csrfParam' => '_csrf-frontend',
24 | 'baseUrl' => '',
25 | ],
26 | 'user' => [
27 | 'identityClass' => 'common\models\User',
28 | 'enableAutoLogin' => true,
29 | 'identityCookie' => ['name' => '_identity-frontend', 'httpOnly' => true],
30 | ],
31 | 'session' => [
32 | // this is the name of the session cookie used for login on the frontend
33 | 'name' => 'advanced-frontend',
34 | ],
35 | 'log' => [
36 | 'traceLevel' => YII_DEBUG ? 3 : 0,
37 | 'targets' => [
38 | [
39 | 'class' => 'yii\log\FileTarget',
40 | 'levels' => ['error', 'warning'],
41 | ],
42 | ],
43 | ],
44 | 'errorHandler' => [
45 | 'errorAction' => 'site/site/error',
46 | ],
47 | 'urlManager' => [
48 | 'enablePrettyUrl' => true,
49 | 'showScriptName' => false,
50 | //'enableStrictParsing' => true
51 | ],
52 | ],
53 | 'params' => $params,
54 | ];
55 |
--------------------------------------------------------------------------------
/frontend/config/params.php:
--------------------------------------------------------------------------------
1 | 'admin@example.com',
4 | ];
5 |
--------------------------------------------------------------------------------
/frontend/config/test.php:
--------------------------------------------------------------------------------
1 | 'app-frontend-tests',
4 | ];
5 |
--------------------------------------------------------------------------------
/frontend/runtime/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
--------------------------------------------------------------------------------
/frontend/tests/_bootstrap.php:
--------------------------------------------------------------------------------
1 | '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 | ];
14 |
--------------------------------------------------------------------------------
/frontend/tests/_data/user.php:
--------------------------------------------------------------------------------
1 | '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 | ];
24 |
--------------------------------------------------------------------------------
/frontend/tests/_output/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/frontend/tests/_support/.gitignore:
--------------------------------------------------------------------------------
1 | _generated
2 |
--------------------------------------------------------------------------------
/frontend/tests/_support/FunctionalTester.php:
--------------------------------------------------------------------------------
1 | see($message, '.help-block');
27 | }
28 |
29 | public function dontSeeValidationError($message)
30 | {
31 | $this->dontSee($message, '.help-block');
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/frontend/tests/_support/UnitTester.php:
--------------------------------------------------------------------------------
1 | amOnPage(Url::toRoute('/site/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 | }
19 |
--------------------------------------------------------------------------------
/frontend/tests/acceptance/_bootstrap.php:
--------------------------------------------------------------------------------
1 | amOnRoute('site/site/about');
11 | $I->see('About', 'h1');
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/frontend/tests/functional/ContactCest.php:
--------------------------------------------------------------------------------
1 | amOnPage(['site/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 | }
60 |
--------------------------------------------------------------------------------
/frontend/tests/functional/HomeCest.php:
--------------------------------------------------------------------------------
1 | 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 | }
--------------------------------------------------------------------------------
/frontend/tests/functional/LoginCest.php:
--------------------------------------------------------------------------------
1 | haveFixtures([
13 | 'user' => [
14 | 'class' => UserFixture::className(),
15 | 'dataFile' => codecept_data_dir() . 'login_data.php'
16 | ]
17 | ]);
18 | $I->amOnRoute('site/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 | }
50 |
--------------------------------------------------------------------------------
/frontend/tests/functional/SignupCest.php:
--------------------------------------------------------------------------------
1 | amOnRoute('site/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 | }
58 |
--------------------------------------------------------------------------------
/frontend/tests/functional/_bootstrap.php:
--------------------------------------------------------------------------------
1 | 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 | }
33 |
--------------------------------------------------------------------------------
/frontend/tests/unit/models/PasswordResetRequestFormTest.php:
--------------------------------------------------------------------------------
1 | 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 | }
60 |
--------------------------------------------------------------------------------
/frontend/tests/unit/models/ResetPasswordFormTest.php:
--------------------------------------------------------------------------------
1 | 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 | }
45 |
--------------------------------------------------------------------------------
/frontend/tests/unit/models/SignupFormTest.php:
--------------------------------------------------------------------------------
1 | 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 | }
60 |
--------------------------------------------------------------------------------
/frontend/views/layouts/main.php:
--------------------------------------------------------------------------------
1 |
15 | beginPage() ?>
16 |
17 |
18 |
19 |
20 |
21 | = Html::csrfMetaTags() ?>
22 | = Html::encode($this->title) ?>
23 | head() ?>
24 |
25 |
26 | beginBody() ?>
27 |
28 |
29 | '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/site/index']],
39 | ['label' => 'About', 'url' => ['/site/site/about']],
40 | ['label' => 'Contact', 'url' => ['/site/site/contact']],
41 | ];
42 | if (Yii::$app->user->isGuest) {
43 | $menuItems[] = ['label' => 'Signup', 'url' => ['/site/site/signup']];
44 | $menuItems[] = ['label' => 'Login', 'url' => ['/site/site/login']];
45 | } else {
46 | $menuItems[] = '
'
47 | . Html::beginForm(['/site/site/logout'], 'post')
48 | . Html::submitButton(
49 | 'Logout (' . Yii::$app->user->identity->username . ')',
50 | ['class' => 'btn btn-link logout']
51 | )
52 | . Html::endForm()
53 | . '';
54 | }
55 | echo Nav::widget([
56 | 'options' => ['class' => 'navbar-nav navbar-right'],
57 | 'items' => $menuItems,
58 | ]);
59 | NavBar::end();
60 | ?>
61 |
62 |
63 | = Breadcrumbs::widget([
64 | 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
65 | ]) ?>
66 | = Alert::widget() ?>
67 | = $content ?>
68 |
69 |
70 |
71 |
78 |
79 | endBody() ?>
80 |
81 |
82 | endPage() ?>
83 |
--------------------------------------------------------------------------------
/frontend/web/.gitignore:
--------------------------------------------------------------------------------
1 | /index.php
2 | /index-test.php
3 |
--------------------------------------------------------------------------------
/frontend/web/.htaccess:
--------------------------------------------------------------------------------
1 | # Mod_Rewrite
2 |
3 | # Enable mod_rewrite
4 | RewriteEngine On
5 |
6 | # If a directory or a file exists, use the request directly
7 | RewriteCond %{REQUEST_FILENAME} !-f
8 | RewriteCond %{REQUEST_FILENAME} !-d
9 | # Otherwise forward the request to index.php
10 | RewriteRule . index.php
11 |
--------------------------------------------------------------------------------
/frontend/web/assets/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/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 | }
121 |
--------------------------------------------------------------------------------
/frontend/web/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pavelsingree/yii2-angular/46f2c48a4ac0c8e011200944db48c798da2fa30d/frontend/web/favicon.ico
--------------------------------------------------------------------------------
/frontend/web/js/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var app = angular.module('app', [
4 | 'ngAnimate',
5 | 'ui.bootstrap',
6 | 'controllers' //Our module frontend/web/js/controllers.js
7 | ]);
8 |
--------------------------------------------------------------------------------
/frontend/web/js/controllers.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var controllers = angular.module('controllers', []);
4 |
5 | controllers.controller('LeaseController', ['$scope', 'LeaseService',
6 | function ($scope, LeaseService) {
7 | $scope.leases = [];
8 | LeaseService.get().then(function (data) {
9 | if (data.status == 200)
10 | $scope.leases = data.data;
11 | }, function (err) {
12 | console.log(err);
13 | })
14 | }
15 | ]);
--------------------------------------------------------------------------------
/frontend/web/js/directives.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pavelsingree/yii2-angular/46f2c48a4ac0c8e011200944db48c798da2fa30d/frontend/web/js/directives.js
--------------------------------------------------------------------------------
/frontend/web/js/services.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var app = angular.module('app');
4 |
5 | app.service('LeaseService', function($http) {
6 | this.get = function() {
7 | return $http.get('/api/leases');
8 | };
9 | this.post = function (data) {
10 | return $http.post('/api/leases', data);
11 | };
12 | this.put = function (id, data) {
13 | return $http.put('/api/leases/' + id, data);
14 | };
15 | this.delete = function (id) {
16 | return $http.delete('/api/leases/' + id);
17 | };
18 | });
--------------------------------------------------------------------------------
/frontend/web/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
--------------------------------------------------------------------------------
/init:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
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 | }
300 |
--------------------------------------------------------------------------------
/init.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | rem -------------------------------------------------------------
4 | rem Yii command line init script for Windows.
5 | rem
6 | rem @author Qiang Xue
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
21 |
--------------------------------------------------------------------------------
/modules/autoposting/Module.php:
--------------------------------------------------------------------------------
1 | 'postToWall',
24 | ];
25 | }
26 |
27 | /**
28 | * @param \yii\base\Event $event
29 | *
30 | * @throws Exception
31 | */
32 | public function postToWall( $event ) {
33 |
34 | $model = $event->sender;
35 |
36 | if ($model) {
37 | $link = Url::to(['/lease/lease/view', 'state'=>$model->state, 'node'=>$model->url ], true);
38 | $message = "New listing available on our site - $model->make $model->model $model->year in $model->location. \n" . $link;
39 | $this->facebookPost([
40 | 'message' => $message,
41 | 'link' => $link,
42 | // 'picture' => 'http://thepicturetoinclude.jpg', // link to vehicle picture
43 | // 'name' => 'Name of the picture, shown just above it',
44 | // 'description' => 'Full description explaining whether the header or the picture'
45 | ]);
46 | $this->twitterPost($message);
47 | }
48 |
49 | }
50 |
51 | private function facebookPost ($data)
52 | {
53 | // need token
54 | $data['access_token'] = Yii::$app->params['autoposting']['facebook']['page_access_token'];
55 |
56 | $page_id = Yii::$app->params['autoposting']['facebook']['page_id'];;
57 | $post_url = 'https://graph.facebook.com/'.$page_id.'/feed';
58 |
59 | // init
60 | $ch = curl_init();
61 | curl_setopt($ch, CURLOPT_URL, $post_url);
62 | curl_setopt($ch, CURLOPT_POST, 1);
63 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
64 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
65 | // execute and close
66 | $return = curl_exec($ch);
67 | curl_close($ch);
68 | // end
69 | return $return;
70 | }
71 |
72 | private function twitterPost ($message)
73 | {
74 |
75 | $CONSUMER_KEY = Yii::$app->params['autoposting']['twitter']['consumer_key'];
76 | $CONSUMER_SECRET = Yii::$app->params['autoposting']['twitter']['consumer_secret'];
77 | $OAUTH_TOKEN = Yii::$app->params['autoposting']['twitter']['oauth_token'];
78 | $OAUTH_SECRET = Yii::$app->params['autoposting']['twitter']['oauth_secret'];
79 |
80 |
81 | $connection = new \Abraham\TwitterOAuth\TwitterOAuth($CONSUMER_KEY, $CONSUMER_SECRET, $OAUTH_TOKEN, $OAUTH_SECRET);
82 |
83 | $statues = $connection->post("statuses/update", array("status" => $message));
84 |
85 | return $connection->getLastHttpCode() == 200;
86 |
87 | }
88 |
89 | }
--------------------------------------------------------------------------------
/modules/cars/Bootstrap.php:
--------------------------------------------------------------------------------
1 | getUrlManager()->addRules(
13 | [
14 | // rules definition
15 | ]
16 | );
17 | }
18 | }
--------------------------------------------------------------------------------
/modules/cars/Module.php:
--------------------------------------------------------------------------------
1 | isBackend === true) {
28 | $this->controllerNamespace = 'modules\cars\controllers\backend';
29 | $this->setViewPath('@modules/cars/views/backend');
30 | } else {
31 | $this->setViewPath('@modules/cars/views/frontend');
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/modules/cars/controllers/backend/DefaultController.php:
--------------------------------------------------------------------------------
1 | render('index');
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/modules/cars/controllers/frontend/DefaultController.php:
--------------------------------------------------------------------------------
1 | render('index');
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/modules/cars/views/backend/default/index.php:
--------------------------------------------------------------------------------
1 |
2 |
= $this->context->action->uniqueId ?>
3 |
4 | This is the view content for action "= $this->context->action->id ?>".
5 | The action belongs to the controller "= get_class($this->context) ?>"
6 | in the "= $this->context->module->id ?>" module.
7 |
8 |
9 | You may customize this page by editing the following file:
10 | = __FILE__ ?>
11 |
12 |
13 |
--------------------------------------------------------------------------------
/modules/cars/views/frontend/default/index.php:
--------------------------------------------------------------------------------
1 |
2 |
= $this->context->action->uniqueId ?>
3 |
4 | This is the view content for action "= $this->context->action->id ?>".
5 | The action belongs to the controller "= get_class($this->context) ?>"
6 | in the "= $this->context->module->id ?>" module.
7 |
8 |
9 | You may customize this page by editing the following file:
10 | = __FILE__ ?>
11 |
12 |
13 |
--------------------------------------------------------------------------------
/modules/lease/Bootstrap.php:
--------------------------------------------------------------------------------
1 | getUrlManager()->addRules(
13 | [
14 | [
15 | 'class' => 'yii\rest\UrlRule',
16 | 'controller' => ['leases' => 'lease/api'],
17 | 'prefix' => 'api'
18 | ]
19 | ]
20 | );
21 | }
22 | }
--------------------------------------------------------------------------------
/modules/lease/Module.php:
--------------------------------------------------------------------------------
1 | isBackend === true) {
28 | $this->controllerNamespace = 'modules\lease\controllers\backend';
29 | $this->setViewPath('@modules/lease/views/backend');
30 | } else {
31 | $this->setViewPath('@modules/lease/views/frontend');
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/modules/lease/controllers/backend/DefaultController.php:
--------------------------------------------------------------------------------
1 | render('index');
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/modules/lease/controllers/frontend/ApiController.php:
--------------------------------------------------------------------------------
1 | Cors::className(),
21 | ];
22 | $behaviors['contentNegotiator'] = [
23 | 'class' => ContentNegotiator::className(),
24 | 'formats' => [
25 | 'application/json' => Response::FORMAT_JSON,
26 | ],
27 | ];
28 | $behaviors['access'] = [
29 | 'class' => AccessControl::className(),
30 | 'only' => ['create', 'update', 'delete'],
31 | 'rules' => [
32 | [
33 | 'actions' => ['create', 'update', 'delete'],
34 | 'allow' => true,
35 | 'roles' => ['@'],
36 | ],
37 | ],
38 | ];
39 | return $behaviors;
40 | }
41 |
42 | public function checkAccess($action, $model = null, $params = [])
43 | {
44 | if ($action === 'update' || $action === 'delete') {
45 | if ($model->user_id !== \Yii::$app->user->id)
46 | throw new ForbiddenHttpException(sprintf('You can only %s lease that you\'ve created.', $action));
47 | }
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/modules/lease/controllers/frontend/DefaultController.php:
--------------------------------------------------------------------------------
1 | render('index');
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/modules/lease/migrations/m150717_132906_create_table_lease.php:
--------------------------------------------------------------------------------
1 | createTable(
29 | '{{%lease}}',
30 | [
31 | // Basic vehicle info
32 | 'id' => Schema::TYPE_PK,
33 | 'user_id' => Schema::TYPE_INTEGER . ' NOT NULL',
34 | 'year' => Schema::TYPE_SMALLINT . '(4) NOT NULL',
35 | 'make' => Schema::TYPE_STRING . '(100) NOT NULL',
36 | 'model' => Schema::TYPE_STRING . ' NOT NULL',
37 | 'vin' => Schema::TYPE_STRING . '(17) NOT NULL',
38 | 'miles' => Schema::TYPE_INTEGER . ' NOT NULL',
39 | 'zip' => Schema::TYPE_INTEGER . ' NOT NULL',
40 | 'trim' => Schema::TYPE_STRING . '(255) NOT NULL',
41 | 'url' => Schema::TYPE_STRING . '(255) NOT NULL',
42 |
43 | 'status_id' => 'tinyint(4) NOT NULL DEFAULT 0',
44 | 'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',
45 | 'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL'
46 | ],
47 | $tableOptions
48 | );
49 |
50 | // Indexes
51 | $this->createIndex('user_id', '{{%lease}}', 'user_id');
52 | $this->createIndex('vin', '{{%lease}}', 'vin');
53 | $this->createIndex('make', '{{%lease}}', 'make');
54 | $this->createIndex('year', '{{%lease}}', 'year');
55 | $this->createIndex('model', '{{%lease}}', 'model');
56 | $this->createIndex('status_id', '{{%lease}}', 'status_id');
57 | $this->createIndex('created_at', '{{%lease}}', 'created_at');
58 |
59 | // Users table
60 | $this->createTable(
61 | '{{%lease_photos}}',
62 | [
63 | 'id' => Schema::TYPE_PK,
64 | 'lease_id' => Schema::TYPE_INTEGER . ' NOT NULL',
65 | 'url' => Schema::TYPE_STRING . '(50) NOT NULL',
66 | 'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',
67 | 'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL'
68 | ],
69 | $tableOptions
70 | );
71 |
72 | // Foreign Keys
73 | $this->addForeignKey('FK_lease_photos', '{{%lease_photos}}', 'lease_id', '{{%lease}}', 'id', 'CASCADE', 'CASCADE');
74 |
75 | }
76 |
77 | /**
78 | * @inheritdoc
79 | */
80 | public function safeDown()
81 | {
82 | $this->dropTable('{{%lease_photos}}');
83 | $this->dropTable('{{%lease}}');
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/modules/lease/models/frontend/Lease.php:
--------------------------------------------------------------------------------
1 | 100],
48 | [['model', 'trim', 'url'], 'string', 'max' => 255],
49 | [['vin'], 'string', 'max' => 17],
50 | ];
51 | }
52 |
53 | /**
54 | * @inheritdoc
55 | */
56 | public function attributeLabels()
57 | {
58 | return [
59 | 'id' => 'ID',
60 | 'user_id' => 'User ID',
61 | 'year' => 'Year',
62 | 'make' => 'Make',
63 | 'model' => 'Model',
64 | 'vin' => 'Vin',
65 | 'miles' => 'Miles',
66 | 'zip' => 'Zip',
67 | 'trim' => 'Trim',
68 | 'url' => 'Url',
69 | 'status_id' => 'Status',
70 | 'created_at' => 'Created At',
71 | 'updated_at' => 'Updated At',
72 | ];
73 | }
74 |
75 | /**
76 | * @inheritdoc
77 | */
78 | public function behaviors()
79 | {
80 | return [
81 | 'timestampBehavior' => [
82 | 'class' => yii\behaviors\TimestampBehavior::className(),
83 | ],
84 | \modules\autoposting\behaviors\AutopostingBehavior::className(), // Autoposting behavior
85 | ];
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/modules/lease/views/backend/default/index.php:
--------------------------------------------------------------------------------
1 |
2 |
= $this->context->action->uniqueId ?>
3 |
4 | This is the view content for action "= $this->context->action->id ?>".
5 | The action belongs to the controller "= get_class($this->context) ?>"
6 | in the "= $this->context->module->id ?>" module.
7 |
8 |
9 | You may customize this page by editing the following file:
10 | = __FILE__ ?>
11 |
12 |
13 |
--------------------------------------------------------------------------------
/modules/lease/views/frontend/default/index.php:
--------------------------------------------------------------------------------
1 | title = \modules\seo\helpers\Meta::all('lease', $model);
3 | ?>
4 |
5 |
6 |
7 |
All Leases
8 |
9 |
10 |
11 | Year |
12 | Make |
13 | Model |
14 | Trim |
15 |
16 |
17 |
18 | {{lease.year}} |
19 | {{lease.make}} |
20 | {{lease.model}} |
21 | {{lease.trim}} |
22 |
23 |
24 |
25 |
26 |
27 | No results
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/modules/seo/Bootstrap.php:
--------------------------------------------------------------------------------
1 | getUrlManager()->addRules(
13 | [
14 | [
15 | 'class' => 'modules\seo\components\UrlRule',
16 | ],
17 | ]
18 | );
19 | }
20 | }
--------------------------------------------------------------------------------
/modules/seo/Module.php:
--------------------------------------------------------------------------------
1 | url = str_replace(' ', '_', substr($params['url'],1) );
49 | $route->route = 'lease/search/index';
50 | $route->params = json_encode(['make'=>$params['make'], 'model'=>$params['model'], 'location'=>$params['location'] ]);
51 | $route->save();
52 | return '/'.$params['url'];
53 | }
54 | }
55 | if (isset($params['type']) && in_array($params['type'], ['user','dealer'])) {
56 | $type = ($params['type'] == 'dealer')? 'new-lease' : 'lease-transfer';
57 | } else {
58 | return false;
59 | }
60 | if ((isset($params['zip']) && !empty($params['zip'])) || (isset($params['location']) && isset($params['state']))) {
61 | // make model price zip type
62 | if (isset($params['zip']) && !empty($params['zip'])) {
63 | $zipdata = Zip::findOneByZip($params['zip']);
64 | } else {
65 | $zipdata = Zip::findOneByLocation($params['location'], $params['state']);
66 | }
67 | // city state_code
68 | if (!empty($zipdata)) {
69 | $url = $type . '/' . $zipdata['state_code'] . '/' . $params['make'] . '-' . $params['model'] . '-' . $zipdata['city'];
70 | if (!empty($params['year'])) {
71 | $url.='/'.$params['year'];
72 | }
73 | $url = str_replace(' ', '_', $url);
74 | if($search_url = Route::findRouteByUrl($url)) {
75 | return '/'.$url;
76 | } else {
77 | $route = new Route();
78 | $route->url = str_replace(' ','_',$url);
79 | $route->route = 'lease/search/index';
80 | $pars = ['make'=>$params['make'], 'model'=>$params['model'], 'location'=>$zipdata['city'], 'state'=>$zipdata['state_code'] ]; //, 'zip'=>$params['zip'] ];
81 | if (!empty($params['year'])) {
82 | $pars['year']=$params['year'];
83 | }
84 | $route->params = json_encode($pars);
85 | $route->save();
86 | return $route->url;
87 | }
88 | }
89 | }
90 | if (isset($params['make'], $params['model'] )) {
91 | $url = $type . '/' . $params['make'] . '-' . $params['model'] ;
92 | if (!empty($params['year'])) {
93 | $url.='/'.$params['year'];
94 | }
95 | $url = str_replace(' ', '_', $url);
96 | if($search_url = Route::findRouteByUrl($url)) {
97 | return '/'.$url;
98 | } else {
99 | $route = new Route();
100 | $route->url = str_replace(' ','_',$url);
101 | $route->route = 'lease/search/index';
102 | $pars = ['make'=>$params['make'], 'model'=>$params['model'] ];
103 | if (!empty($params['year'])) {
104 | $pars['year']=$params['year'];
105 | }
106 | $route->params = json_encode($pars);
107 | $route->save();
108 | return $route->url;
109 | }
110 | }
111 | }
112 |
113 | return false;
114 | }
115 |
116 | /**
117 | * Parse request
118 | * @param \yii\web\Request|UrlManager $manager
119 | * @param \yii\web\Request $request
120 | * @return array|boolean
121 | */
122 | public function parseRequest($manager, $request)
123 | {
124 | $pathInfo = $request->getPathInfo();
125 |
126 | /**
127 | * Parse request for search URLs with location and year
128 | */
129 | if (preg_match('%^(?Please-transfer|new-lease)\/(?P[A-Za-z]{2})\/(?P[._\sA-Za-z-0-9-]+)\/(?P\d{4})?%', $pathInfo, $matches)) {
130 | $route = Route::findRouteByUrl($pathInfo);
131 | if (!$route) {
132 | return false;
133 | }
134 | $params = [
135 | 'node' => $matches['url'] . '/' . $matches['year'],
136 | 'role' => $matches['role'],
137 | 'state' => $matches['state'],
138 | 'year' => $matches['year']
139 | ];
140 | if (!empty($route['params'])) {
141 | $params = array_merge($params, json_decode($route['params'], true));
142 | }
143 | return [$route['route'], $params];
144 | }
145 |
146 | /**
147 | * Parse request for search URLs with location and with year
148 | */
149 | if (preg_match('%^(?Please-transfer|new-lease)\/(?P[._\sA-Za-z-0-9-]+)\/(?P\d{4})%', $pathInfo, $matches)) {
150 | $route = Route::findRouteByUrl($pathInfo);
151 | if (!$route) {
152 | return false;
153 | }
154 | $params = [
155 | 'node' => $matches['url'] . '/' . $matches['year'],
156 | 'role' => $matches['role'],
157 | 'year' => $matches['year']
158 | ];
159 | if (!empty($route['params'])) {
160 | $params = array_merge($params, json_decode($route['params'], true));
161 | }
162 | return [$route['route'], $params];
163 | }
164 |
165 | /**
166 | * Parse request for leases URLs and search URLs with location
167 | */
168 | if (preg_match('%^(?Please-transfer|new-lease)\/(?P[A-Za-z]{2})\/(?P[_A-Za-z-0-9-]+)?%', $pathInfo, $matches)) {
169 | $route = Route::findRouteByUrl([$matches['url'], $pathInfo]);
170 | if (!$route) {
171 | return false;
172 | }
173 | $params = [
174 | 'role' => $matches['role'],
175 | 'node' => $matches['url'],
176 | 'state' => $matches['state']
177 | ];
178 | if (!empty($route['params'])) {
179 | $params = array_merge($params, json_decode($route['params'], true));
180 | }
181 | return [$route['route'], $params];
182 | }
183 |
184 | /**
185 | * Parse request for search URLs without location and year
186 | */
187 | if (preg_match('%^(?Please-transfer|new-lease)\/(?P[._\sA-Za-z-0-9-]+)?%', $pathInfo, $matches)) {
188 | $route = Route::findRouteByUrl($pathInfo);
189 | if (!$route) {
190 | return false;
191 | }
192 | $params = [
193 | 'node' => $matches['url'],
194 | 'role' => $matches['role'],
195 | ];
196 | if (!empty($route['params'])) {
197 | $params = array_merge($params, json_decode($route['params'], true));
198 | }
199 | return [$route['route'], $params];
200 | }
201 |
202 | /**
203 | * Parse request for Information pages URLs
204 | */
205 | if (preg_match('%^i\/(?P[_A-Za-z-0-9-]+)?%', $pathInfo, $matches)) {
206 | $route = Route::findRouteByUrl($matches['url']);
207 | if (!$route) {
208 | return false;
209 | }
210 | $params = Json::decode($route['params']);
211 | $params['node'] = $route['url'];
212 | return [$route['route'], $params];
213 | }
214 |
215 | return false;
216 | }
217 | }
--------------------------------------------------------------------------------
/modules/seo/helpers/Meta.php:
--------------------------------------------------------------------------------
1 | view->registerMetaTag(['name' => 'keywords','content' => 'lease, car, transfer']);
26 | Yii::$app->view->registerMetaTag(['name' => 'description','content' => 'Carvoy - Change the way you lease! Lease your next new car online and we\'ll deliver it to your doorstep.']);
27 | break;
28 | case 'lease':
29 | $title = $model->make . ' - ' . $model->model . ' - ' . $model->year . ' - ' . $model->exterior_color . ' - ' . $model->engineFuelType . ' for lease in ' . $model->location;
30 | Yii::$app->view->registerMetaTag(['name' => 'keywords','content' => Html::encode($model->year . ', ' . $model->make . ', ' . $model->model . ', ' . $model->exterior_color . ', ' . $model->engineFuelType . ', ' . $model->location . ', for, lease')]);
31 | Yii::$app->view->registerMetaTag(['name' => 'description','content' => Html::encode($model->year . ' ' . $model->make . ' ' . $model->model . ' ' . $model->exterior_color . ' ' . $model->engineFuelType . ' for lease in ' . $model->location)]);
32 | break;
33 | case 'info_page':
34 | $title = $model->make . ' - ' . $model->model . ' - ' . $model->year;
35 | Yii::$app->view->registerMetaTag(['name' => 'keywords','content' => Html::encode($model->year . ', ' . $model->make . ', ' . $model->model)]);
36 | Yii::$app->view->registerMetaTag(['name' => 'description','content' => Html::encode($model->year . ' ' . $model->make . ' ' . $model->model)]);
37 | break;
38 | case 'search':
39 | if ($model['role'] == 'd') $role = 'Dealer Lease';
40 | elseif ($model['role'] == 'u') $role = 'Lease Transfers';
41 | else $role = 'All Leases';
42 | if (isset($model['make']) && isset($model['model'])) {
43 | $_make = (is_array($model['make']))? (( isset($model['make']) && ( count($model['make']) == 1) )? $model['make'][0] : false ) : $model['make'];
44 | $_model = (is_array($model['model']))? (( isset($model['model']) && ( count($model['model']) == 1) )? $model['model'][0] : false ) : $model['model'];
45 | $_year = false;
46 | $_location = false;
47 | if (isset($model['year'])) {
48 | $_year = (is_array($model['year']))? (( isset($model['year']) && ( count($model['year']) == 1) )? $model['year'][0] : false ) : $model['year'];
49 | }
50 | if (isset($model['location'])) {
51 | $_location = (is_array($model['location']))? (( isset($model['location']) && ( count($model['location']) == 1) )? $model['location'][0] : false ) : $model['location'];
52 | }
53 | if ( ($_make || $_model) && !(isset($model['make']) && ( count($model['make']) > 1)) ) {
54 | $title = $_make . (($_model)? ' ' . $_model : '') . (($_year)? ' ' . $_year : '') . ' for Lease' . (($_location)? ' in ' . $_location . '. ' : '. ') . $role . '.';
55 | } else {
56 | $title = 'Vehicle for Lease' . (($_location)? ' in ' . $_location . '. ' : '. ') . $role . '.';
57 | }
58 | Yii::$app->view->registerMetaTag(['name' => 'keywords','content' => Html::encode( ltrim($_make . (($_model)? ', ' . $_model : '') . (($_year)? ', ' . $_year : '') . ', for, Lease' . (($_location)? ', in, ' . $_location : '') . ', ' . implode(', ', (explode(' ', $role))), ', ') ) ]);
59 | Yii::$app->view->registerMetaTag(['name' => 'description','content' => Html::encode( 'List of '. ((!$_model && !$_make)? 'Vehicles' : '') . $_make . (($_model)? ' ' . $_model : '') . (($_year)? ' ' . $_year : '') . (($_location)? ' in ' . $_location : '') . ' available for lease. ' . $role . '.' )]);
60 | } else {
61 | $title = 'Search results';
62 | }
63 | break;
64 | }
65 | return $title;
66 | }
67 | }
--------------------------------------------------------------------------------
/modules/seo/migrations/m150729_120945_create_table_route.php:
--------------------------------------------------------------------------------
1 | createTable(
15 | '{{%route}}',
16 | [
17 | 'id' => Schema::TYPE_PK,
18 | 'url' => Schema::TYPE_STRING . '(255) NOT NULL',
19 | 'route' => Schema::TYPE_STRING . '(50) NOT NULL',
20 | 'params' => Schema::TYPE_TEXT . ' DEFAULT NULL',
21 | 'created_at' => Schema::TYPE_INTEGER . '(11) NOT NULL',
22 | 'updated_at' => Schema::TYPE_INTEGER . '(11) NOT NULL',
23 | ],
24 | $tableOptions
25 | );
26 |
27 | $this->createIndex('url', '{{%route}}', 'url', true);
28 | $this->createIndex('route', '{{%route}}', 'route');
29 | }
30 |
31 | public function safeDown()
32 | {
33 | $this->dropTable('{{%route}}');
34 | echo "m150729_120945_create_table_route cannot be reverted.\n";
35 |
36 | return false;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/modules/seo/models/Route.php:
--------------------------------------------------------------------------------
1 | [
35 | 'class' => TimestampBehavior::className(),
36 | ],
37 | ];
38 | }
39 |
40 | /**
41 | * @inheritdoc
42 | */
43 | public function rules()
44 | {
45 | return [
46 | ['url', 'string', 'max' => 100],
47 | ['route', 'string', 'max' => 50],
48 | ['params', 'string', 'max' => 500],
49 | [['url', 'route'], 'required'],
50 | [['url'], 'unique']
51 | ];
52 | }
53 |
54 | /**
55 | * @inheritdoc
56 | */
57 | public function attributeLabels()
58 | {
59 | return [
60 | 'created_at' => 'Created at',
61 | 'updated_at' => 'Updated at'
62 | ];
63 | }
64 |
65 | /**
66 | * Get route by match url
67 | *
68 | * @param string $url
69 | * @return mixed
70 | */
71 | public static function findRouteByUrl($url)
72 | {
73 | $query = self::find()
74 | ->where(['url' => $url])
75 | ->one();
76 |
77 | return $query;
78 | }
79 |
80 | /**
81 | * Create user url
82 | *
83 | * @param string $url Url
84 | * @param string $route Route
85 | * @return boolean
86 | */
87 | public static function saveUrl($url, $route)
88 | {
89 | $_route = new Route();
90 | $_route->url = $url;
91 | $_route->route = $route;
92 | if($_route->save(false)){
93 | return true;
94 | }
95 | return false;
96 | }
97 |
98 | }
--------------------------------------------------------------------------------
/modules/seo/views/default/index.php:
--------------------------------------------------------------------------------
1 |
2 |
= $this->context->action->uniqueId ?>
3 |
4 | This is the view content for action "= $this->context->action->id ?>".
5 | The action belongs to the controller "= get_class($this->context) ?>"
6 | in the "= $this->context->module->id ?>" module.
7 |
8 |
9 | You may customize this page by editing the following file:
10 | = __FILE__ ?>
11 |
12 |
13 |
--------------------------------------------------------------------------------
/modules/site/Bootstrap.php:
--------------------------------------------------------------------------------
1 | getUrlManager()->addRules(
13 | [
14 | // rules definition
15 | '/' => 'site/site/index',
16 | '<_a:(about|contact)>' => 'site/site/<_a>'
17 | ]
18 | );
19 | }
20 | }
--------------------------------------------------------------------------------
/modules/site/Module.php:
--------------------------------------------------------------------------------
1 | isBackend === true) {
29 | $this->controllerNamespace = 'modules\site\controllers\backend';
30 | $this->setViewPath('@modules/site/views/backend');
31 | } else {
32 | $this->setViewPath('@modules/site/views/frontend');
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/modules/site/controllers/backend/SiteController.php:
--------------------------------------------------------------------------------
1 | [
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 | }
99 |
--------------------------------------------------------------------------------
/modules/site/controllers/frontend/SiteController.php:
--------------------------------------------------------------------------------
1 | [
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 | }
214 |
--------------------------------------------------------------------------------
/modules/site/models/frontend/ContactForm.php:
--------------------------------------------------------------------------------
1 | 'site/site/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 | }
61 |
--------------------------------------------------------------------------------
/modules/site/models/frontend/PasswordResetRequestForm.php:
--------------------------------------------------------------------------------
1 | '\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 | }
69 |
--------------------------------------------------------------------------------
/modules/site/models/frontend/ResetPasswordForm.php:
--------------------------------------------------------------------------------
1 | _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 | }
65 |
--------------------------------------------------------------------------------
/modules/site/models/frontend/SignupForm.php:
--------------------------------------------------------------------------------
1 | '\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 | }
59 |
--------------------------------------------------------------------------------
/modules/site/views/backend/site/error.php:
--------------------------------------------------------------------------------
1 | title = $name;
11 | ?>
12 |
13 |
14 |
= Html::encode($this->title) ?>
15 |
16 |
17 | = nl2br(Html::encode($message)) ?>
18 |
19 |
20 |
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 |
28 |
--------------------------------------------------------------------------------
/modules/site/views/backend/site/index.php:
--------------------------------------------------------------------------------
1 | title = 'My Yii Application';
6 | ?>
7 |
8 |
9 |
10 |
Congratulations!
11 |
12 |
You have successfully created your Yii-powered application.
13 |
14 |
Get started with Yii
15 |
16 |
17 |
18 |
19 |
20 |
21 |
Heading
22 |
23 |
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.
27 |
28 |
Yii Documentation »
29 |
30 |
31 |
Heading
32 |
33 |
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.
37 |
38 |
Yii Forum »
39 |
40 |
41 |
Heading
42 |
43 |
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.
47 |
48 |
Yii Extensions »
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/modules/site/views/backend/site/login.php:
--------------------------------------------------------------------------------
1 | title = 'Login';
11 | $this->params['breadcrumbs'][] = $this->title;
12 | ?>
13 |
14 |
= Html::encode($this->title) ?>
15 |
16 |
Please fill out the following fields to login:
17 |
18 |
19 |
20 | '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 |
29 | = Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/modules/site/views/frontend/site/about.php:
--------------------------------------------------------------------------------
1 | title = 'About';
8 | $this->params['breadcrumbs'][] = $this->title;
9 | ?>
10 |
11 |
= Html::encode($this->title) ?>
12 |
13 |
This is the About page. You may modify the following file to customize its content:
14 |
15 |
= __FILE__ ?>
16 |
17 |
--------------------------------------------------------------------------------
/modules/site/views/frontend/site/contact.php:
--------------------------------------------------------------------------------
1 | title = 'Contact';
12 | $this->params['breadcrumbs'][] = $this->title;
13 | ?>
14 |
46 |
--------------------------------------------------------------------------------
/modules/site/views/frontend/site/error.php:
--------------------------------------------------------------------------------
1 | title = $name;
11 | ?>
12 |
13 |
14 |
= Html::encode($this->title) ?>
15 |
16 |
17 | = nl2br(Html::encode($message)) ?>
18 |
19 |
20 |
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 |
28 |
--------------------------------------------------------------------------------
/modules/site/views/frontend/site/index.php:
--------------------------------------------------------------------------------
1 | title = 'My Yii Application';
6 | ?>
7 |
8 |
9 |
10 |
Congratulations!
11 |
12 |
You have successfully created your Yii-powered application.
13 |
14 |
Get started with Yii
15 |
16 |
17 |
18 |
19 |
20 |
21 |
Heading
22 |
23 |
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.
27 |
28 |
Yii Documentation »
29 |
30 |
31 |
Heading
32 |
33 |
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.
37 |
38 |
Yii Forum »
39 |
40 |
41 |
Heading
42 |
43 |
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.
47 |
48 |
Yii Extensions »
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/modules/site/views/frontend/site/login.php:
--------------------------------------------------------------------------------
1 | title = 'Login';
11 | $this->params['breadcrumbs'][] = $this->title;
12 | ?>
13 |
14 |
= Html::encode($this->title) ?>
15 |
16 |
Please fill out the following fields to login:
17 |
18 |
19 |
20 | '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 |
29 | If you forgot your password you can = Html::a('reset it', ['site/request-password-reset']) ?>.
30 |
31 |
32 |
33 | = Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/modules/site/views/frontend/site/requestPasswordResetToken.php:
--------------------------------------------------------------------------------
1 | title = 'Request password reset';
11 | $this->params['breadcrumbs'][] = $this->title;
12 | ?>
13 |
14 |
= Html::encode($this->title) ?>
15 |
16 |
Please fill out your email. A link to reset password will be sent there.
17 |
18 |
19 |
20 | 'request-password-reset-form']); ?>
21 |
22 | = $form->field($model, 'email')->textInput(['autofocus' => true]) ?>
23 |
24 |
25 | = Html::submitButton('Send', ['class' => 'btn btn-primary']) ?>
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/modules/site/views/frontend/site/resetPassword.php:
--------------------------------------------------------------------------------
1 | title = 'Reset password';
11 | $this->params['breadcrumbs'][] = $this->title;
12 | ?>
13 |
14 |
= Html::encode($this->title) ?>
15 |
16 |
Please choose your new password:
17 |
18 |
19 |
20 | 'reset-password-form']); ?>
21 |
22 | = $form->field($model, 'password')->passwordInput(['autofocus' => true]) ?>
23 |
24 |
25 | = Html::submitButton('Save', ['class' => 'btn btn-primary']) ?>
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/modules/site/views/frontend/site/signup.php:
--------------------------------------------------------------------------------
1 | title = 'Signup';
11 | $this->params['breadcrumbs'][] = $this->title;
12 | ?>
13 |
14 |
= Html::encode($this->title) ?>
15 |
16 |
Please fill out the following fields to signup:
17 |
18 |
19 |
20 | '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 |
29 | = Html::submitButton('Signup', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?>
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/modules/users/Bootstrap.php:
--------------------------------------------------------------------------------
1 | getUrlManager()->addRules(
13 | [
14 | // rules definition
15 | ]
16 | );
17 | }
18 | }
--------------------------------------------------------------------------------
/modules/users/Module.php:
--------------------------------------------------------------------------------
1 | isBackend === true) {
28 | $this->controllerNamespace = 'modules\users\controllers\backend';
29 | $this->setViewPath('@modules/users/views/backend');
30 | } else {
31 | $this->setViewPath('@modules/users/views/frontend');
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/modules/users/controllers/backend/DefaultController.php:
--------------------------------------------------------------------------------
1 | render('index');
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/modules/users/controllers/frontend/DefaultController.php:
--------------------------------------------------------------------------------
1 | render('index');
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/modules/users/views/backend/default/index.php:
--------------------------------------------------------------------------------
1 |
2 |
= $this->context->action->uniqueId ?>
3 |
4 | This is the view content for action "= $this->context->action->id ?>".
5 | The action belongs to the controller "= get_class($this->context) ?>"
6 | in the "= $this->context->module->id ?>" module.
7 |
8 |
9 | You may customize this page by editing the following file:
10 | = __FILE__ ?>
11 |
12 |
13 |
--------------------------------------------------------------------------------
/modules/users/views/frontend/default/index.php:
--------------------------------------------------------------------------------
1 |
2 |
= $this->context->action->uniqueId ?>
3 |
4 | This is the view content for action "= $this->context->action->id ?>".
5 | The action belongs to the controller "= get_class($this->context) ?>"
6 | in the "= $this->context->module->id ?>" module.
7 |
8 |
9 | You may customize this page by editing the following file:
10 | = __FILE__ ?>
11 |
12 |
13 |
--------------------------------------------------------------------------------
/modules/zipdata/Module.php:
--------------------------------------------------------------------------------
1 | createTable(
15 | '{{%zipdata}}',
16 | [
17 | 'city' => Schema::TYPE_STRING . '(50) NOT NULL',
18 | 'state_code' => 'char(2) NOT NULL',
19 | 'zip' => Schema::TYPE_INTEGER . '(5) NOT NULL',
20 | 'latitude' => Schema::TYPE_DOUBLE . ' NOT NULL',
21 | 'longitude' => Schema::TYPE_DOUBLE . ' NOT NULL',
22 | 'country' => Schema::TYPE_STRING . '(50) NOT NULL'
23 | ],
24 | $tableOptions
25 | );
26 | }
27 |
28 | public function down()
29 | {
30 | $this->dropTable('{{%zipdata}}');
31 | echo "m150722_100330_create_zipdata_table cannot be reverted.\n";
32 |
33 | return false;
34 | }
35 |
36 | /*
37 | // Use safeUp/safeDown to run migration code within a transaction
38 | public function safeUp()
39 | {
40 | }
41 |
42 | public function safeDown()
43 | {
44 | }
45 | */
46 | }
47 |
--------------------------------------------------------------------------------
/modules/zipdata/models/Zip.php:
--------------------------------------------------------------------------------
1 | 50],
37 | [['latitude', 'longitude'], 'double'],
38 | ['state_code', 'string', 'max' => 2],
39 | ['zip', 'integer', 'max' => 5],
40 | [['city', 'state_code', 'zip'], 'required']
41 | ];
42 | }
43 |
44 | /**
45 | * @inheritdoc
46 | */
47 | public function attributeLabels()
48 | {
49 | return [
50 | 'city' => 'City',
51 | 'state_code' => 'State abbreviation',
52 | 'zip' => 'ZIP',
53 | 'latitude' => 'Latitude',
54 | 'longitude' => 'Longitude',
55 | 'country' => 'Country'
56 | ];
57 | }
58 |
59 | /**
60 | * Search by zip code
61 | * @param string $zip Zip code
62 | * @return array Zip
63 | */
64 | public static function findOneByZip($zip)
65 | {
66 | return self::find()->where(['zip' => $zip])->asArray()->one();
67 | }
68 |
69 | /**
70 | * Search by Location
71 | * @param string $location Location
72 | * @param string $state State
73 | * @return array Zip
74 | */
75 | public static function findOneByLocation($location, $state)
76 | {
77 | return self::find()->where(['city' => $location, 'state_code' => $state])->asArray()->one();
78 | }
79 |
80 | /**
81 | * @param $zip_one
82 | * @param $zip_second
83 | * @return float|int
84 | */
85 | public static function getDistanceBetweenZip($zip_one, $zip_second)
86 | {
87 | $zip_one_instance = self::find()->where(['zip' => $zip_one])->one();
88 | $zip_second_instance = self::find()->where(['zip' =>$zip_second])->one();
89 | if(!$zip_one_instance || !$zip_second_instance) {
90 | return 0;
91 | }
92 | return floor(self::getDistance($zip_one_instance->latitude, $zip_one_instance->longitude, $zip_second_instance->latitude, $zip_second_instance->longitude, 'M'));
93 | }
94 |
95 | /**
96 | * Get distance between zips
97 | *
98 | * @param integer $lat1
99 | * @param integer $lon1
100 | * @param integer $lat2
101 | * @param integer $lon2
102 | * @param string{"K", "N", "M"} $unit Unit M - miles, N - nautical miles, K - kilometers
103 | * @return float
104 | */
105 | private static function getDistance($lat1, $lon1, $lat2, $lon2, $unit)
106 | {
107 | $theta = $lon1 - $lon2;
108 | $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
109 | $dist = acos($dist);
110 | $dist = rad2deg($dist);
111 | $miles = $dist * 60 * 1.1515;
112 | $unit = strtoupper($unit);
113 |
114 | if ($unit == "K") {
115 | return ($miles * 1.609344);
116 | } else if ($unit == "N") {
117 | return ($miles * 0.8684);
118 | } else {
119 | return $miles;
120 | }
121 | }
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/modules/zipdata/models/ZipSearch.php:
--------------------------------------------------------------------------------
1 | 50],
18 | [['latitude', 'longitude'], 'double'],
19 | ['state_code', 'string', 'max' => 2],
20 | ['zip', 'integer', 'max' => 5],
21 | [['city', 'state_code', 'zip'], 'required']
22 | ];
23 | }
24 |
25 | /**
26 | * @inheritdoc
27 | */
28 | public function scenarios()
29 | {
30 | return Model::scenarios();
31 | }
32 |
33 | public function search($params)
34 | {
35 | $query = Zip::find();
36 |
37 | $dataProvider = new ActiveDataProvider([
38 | 'query' => $query
39 | ]);
40 |
41 | $this->load($params);
42 |
43 | if(!$this->validate()) {
44 | return $dataProvider;
45 | }
46 |
47 | $query->andFilterWhere([
48 | 'city' => $this->city,
49 | 'state_code' => $this->state_code,
50 | 'zip' => $this->zip,
51 | 'latitude' => $this->latitude,
52 | 'longitude' => $this->longitude,
53 | 'country' => $this->country
54 | ]);
55 |
56 | $query->andFilterWhere(['like', 'city', $this->city])
57 | ->andFilterWhere(['like', 'state_code', $this->state_code])
58 | ->andFilterWhere(['like', 'zip', $this->zip])
59 | ->andFilterWhere(['like', 'latitude', $this->latitdude])
60 | ->andFilterWhere(['like', 'longitude', $this->longitude])
61 | ->andFilterWhere(['like', 'country', $this->country]);
62 |
63 | return $dataProvider;
64 | }
65 |
66 | }
--------------------------------------------------------------------------------
/requirements.php:
--------------------------------------------------------------------------------
1 | Error';
18 | echo 'The path to yii framework seems to be incorrect.
';
19 | echo 'You need to install Yii framework via composer or adjust the framework path in file ' . basename(__FILE__) . '.
';
20 | echo 'Please refer to the README on how to install Yii.
';
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' => 'MemCache',
86 | 'memo' => extension_loaded('memcached') ? 'To use memcached set MemCache::useMemcached to true
.' : ''
87 | ),
88 | array(
89 | 'name' => 'APC extension',
90 | 'mandatory' => false,
91 | 'condition' => extension_loaded('apc'),
92 | 'by' => 'ApcCache',
93 | ),
94 | // CAPTCHA:
95 | array(
96 | 'name' => 'GD PHP extension with FreeType support',
97 | 'mandatory' => false,
98 | 'condition' => $gdOK,
99 | 'by' => 'Captcha',
100 | 'memo' => $gdMemo,
101 | ),
102 | array(
103 | 'name' => 'ImageMagick PHP extension with PNG support',
104 | 'mandatory' => false,
105 | 'condition' => $imagickOK,
106 | 'by' => 'Captcha',
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();
133 |
--------------------------------------------------------------------------------
/vagrant/config/.gitignore:
--------------------------------------------------------------------------------
1 | # local configuration
2 | vagrant-local.yml
--------------------------------------------------------------------------------
/vagrant/config/vagrant-local.example.yml:
--------------------------------------------------------------------------------
1 | # Your personal GitHub token
2 | 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
23 |
--------------------------------------------------------------------------------
/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 | }
78 |
--------------------------------------------------------------------------------
/vagrant/nginx/log/.gitignore:
--------------------------------------------------------------------------------
1 | # nginx logs
2 | backend-access.log
3 | backend-error.log
4 | frontend-access.log
5 | frontend-error.log
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/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
45 |
--------------------------------------------------------------------------------
/yii.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | rem -------------------------------------------------------------
4 | rem Yii command line bootstrap script for Windows.
5 | rem
6 | rem @author Qiang Xue
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
21 |
--------------------------------------------------------------------------------