diff --git a/.bowerrc b/.bowerrc new file mode 100755 index 0000000..1669168 --- /dev/null +++ b/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory" : "vendor/bower" +} diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..6ce6155 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +# yii console commands +/yii +/yii_test +/yii_test.bat + +# phpstorm project files +.idea + +# netbeans project files +nbproject + +# zend studio for eclipse project files +.buildpath +.project +.settings + +# windows thumbnail cache +Thumbs.db + +# composer vendor dir +/vendor + +# composer itself is not needed +composer.phar + +# Mac DS_Store Files +.DS_Store + +# phpunit itself is not needed +phpunit.phar +# local phpunit config +/phpunit.xml + +# vagrant runtime +/.vagrant diff --git a/LICENSE.md b/LICENSE.md new file mode 100755 index 0000000..e98f03d --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,32 @@ +The Yii framework is free software. It is released under the terms of +the following BSD License. + +Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Yii Software LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/Vagrantfile b/Vagrantfile new file mode 100755 index 0000000..4181f83 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,72 @@ +require 'yaml' +require 'fileutils' + +domains = { + frontend: 'y2aa-frontend.dev', + backend: 'y2aa-backend.dev' +} + +config = { + local: './vagrant/config/vagrant-local.yml', + example: './vagrant/config/vagrant-local.example.yml' +} + +# copy config from example if local config not exists +FileUtils.cp config[:example], config[:local] unless File.exist?(config[:local]) +# read config +options = YAML.load_file config[:local] + +# check github token +if options['github_token'].nil? || options['github_token'].to_s.length != 40 + puts "You must place REAL GitHub token into configuration:\n/yii2-app-advanced/vagrant/config/vagrant-local.yml" + exit +end + +# vagrant configurate +Vagrant.configure(2) do |config| + # select the box + config.vm.box = 'ubuntu/trusty64' + + # should we ask about box updates? + config.vm.box_check_update = options['box_check_update'] + + config.vm.provider 'virtualbox' do |vb| + # machine cpus count + vb.cpus = options['cpus'] + # machine memory size + vb.memory = options['memory'] + # machine name (for VirtualBox UI) + vb.name = options['machine_name'] + end + + # machine name (for vagrant console) + config.vm.define options['machine_name'] + + # machine name (for guest machine console) + config.vm.hostname = options['machine_name'] + + # network settings + config.vm.network 'private_network', ip: options['ip'] + + # sync: folder 'yii2-app-advanced' (host machine) -> folder '/app' (guest machine) + config.vm.synced_folder './', '/app', owner: 'vagrant', group: 'vagrant' + + # disable folder '/vagrant' (guest machine) + config.vm.synced_folder '.', '/vagrant', disabled: true + + # hosts settings (host machine) + config.vm.provision :hostmanager + config.hostmanager.enabled = true + config.hostmanager.manage_host = true + config.hostmanager.ignore_private_ip = false + config.hostmanager.include_offline = true + config.hostmanager.aliases = domains.values + + # provisioners + config.vm.provision 'shell', path: './vagrant/provision/once-as-root.sh', args: [options['timezone']] + config.vm.provision 'shell', path: './vagrant/provision/once-as-vagrant.sh', args: [options['github_token']], privileged: false + config.vm.provision 'shell', path: './vagrant/provision/always-as-root.sh', run: 'always' + + # post-install message (vagrant console) + config.vm.post_up_message = "Frontend URL: http://#{domains[:frontend]}\nBackend URL: http://#{domains[:backend]}" +end diff --git a/backend/assets/AppAsset.php b/backend/assets/AppAsset.php new file mode 100755 index 0000000..d85fd95 --- /dev/null +++ b/backend/assets/AppAsset.php @@ -0,0 +1,23 @@ + 'app-backend', + 'basePath' => dirname(__DIR__), + 'controllerNamespace' => 'backend\controllers', + 'bootstrap' => ['log'], + 'modules' => [], + 'components' => [ + 'request' => [ + 'csrfParam' => '_csrf-backend', + ], + 'user' => [ + 'identityClass' => 'common\models\User', + 'enableAutoLogin' => true, + 'identityCookie' => ['name' => '_identity-backend', 'httpOnly' => true], + ], + 'session' => [ + // this is the name of the session cookie used for login on the backend + 'name' => 'advanced-backend', + ], + 'log' => [ + 'traceLevel' => YII_DEBUG ? 3 : 0, + 'targets' => [ + [ + 'class' => 'yii\log\FileTarget', + 'levels' => ['error', 'warning'], + ], + ], + ], + 'errorHandler' => [ + 'errorAction' => 'site/error', + ], + 'urlManager' => [ + 'enablePrettyUrl' => true, + 'showScriptName' => false, + 'enableStrictParsing' => false, + 'rules' => [ + ], + ], + ], + 'params' => $params, +]; diff --git a/backend/config/params.php b/backend/config/params.php new file mode 100755 index 0000000..7f754b9 --- /dev/null +++ b/backend/config/params.php @@ -0,0 +1,4 @@ + 'admin@example.com', +]; diff --git a/backend/config/test.php b/backend/config/test.php new file mode 100755 index 0000000..09536cf --- /dev/null +++ b/backend/config/test.php @@ -0,0 +1,9 @@ + 'app-backend-tests', + 'components' => [ + 'assetManager' => [ + 'basePath' => __DIR__ . '/../web/assets', + ], + ], +]; diff --git a/backend/controllers/ModsController.php b/backend/controllers/ModsController.php new file mode 100644 index 0000000..aaec55f --- /dev/null +++ b/backend/controllers/ModsController.php @@ -0,0 +1,124 @@ + [ + 'class' => VerbFilter::className(), + 'actions' => [ + 'delete' => ['POST'], + ], + ], + ]; + } + + /** + * Lists all Mods models. + * @return mixed + */ + public function actionIndex() + { + $searchModel = new ModsSearch(); + $dataProvider = $searchModel->search(Yii::$app->request->queryParams); + + return $this->render('index', [ + 'searchModel' => $searchModel, + 'dataProvider' => $dataProvider, + ]); + } + + /** + * Displays a single Mods model. + * @param integer $id + * @return mixed + */ + public function actionView($id) + { + return $this->render('view', [ + 'model' => $this->findModel($id), + ]); + } + + /** + * Creates a new Mods model. + * If creation is successful, the browser will be redirected to the 'view' page. + * @return mixed + */ + public function actionCreate() + { + $model = new Mods(); + + if ($model->load(Yii::$app->request->post()) && $model->save()) { + return $this->redirect(['view', 'id' => $model->id]); + } else { + return $this->render('create', [ + 'model' => $model, + ]); + } + } + + /** + * Updates an existing Mods model. + * If update is successful, the browser will be redirected to the 'view' page. + * @param integer $id + * @return mixed + */ + public function actionUpdate($id) + { + $model = $this->findModel($id); + + if ($model->load(Yii::$app->request->post()) && $model->save()) { + return $this->redirect(['view', 'id' => $model->id]); + } else { + return $this->render('update', [ + 'model' => $model, + ]); + } + } + + /** + * Deletes an existing Mods model. + * If deletion is successful, the browser will be redirected to the 'index' page. + * @param integer $id + * @return mixed + */ + public function actionDelete($id) + { + $this->findModel($id)->delete(); + + return $this->redirect(['index']); + } + + /** + * Finds the Mods model based on its primary key value. + * If the model is not found, a 404 HTTP exception will be thrown. + * @param integer $id + * @return Mods the loaded model + * @throws NotFoundHttpException if the model cannot be found + */ + protected function findModel($id) + { + if (($model = Mods::findOne($id)) !== null) { + return $model; + } else { + throw new NotFoundHttpException('The requested page does not exist.'); + } + } +} diff --git a/backend/controllers/ShipController.php b/backend/controllers/ShipController.php new file mode 100644 index 0000000..5f6b4f1 --- /dev/null +++ b/backend/controllers/ShipController.php @@ -0,0 +1,124 @@ + [ + 'class' => VerbFilter::className(), + 'actions' => [ + 'delete' => ['POST'], + ], + ], + ]; + } + + /** + * Lists all Ship models. + * @return mixed + */ + public function actionIndex() + { + $searchModel = new ShipSearch(); + $dataProvider = $searchModel->search(Yii::$app->request->queryParams); + + return $this->render('index', [ + 'searchModel' => $searchModel, + 'dataProvider' => $dataProvider, + ]); + } + + /** + * Displays a single Ship model. + * @param integer $id + * @return mixed + */ + public function actionView($id) + { + return $this->render('view', [ + 'model' => $this->findModel($id), + ]); + } + + /** + * Creates a new Ship model. + * If creation is successful, the browser will be redirected to the 'view' page. + * @return mixed + */ + public function actionCreate() + { + $model = new Ship(); + + if ($model->load(Yii::$app->request->post()) && $model->save()) { + return $this->redirect(['view', 'id' => $model->id]); + } else { + return $this->render('create', [ + 'model' => $model, + ]); + } + } + + /** + * Updates an existing Ship model. + * If update is successful, the browser will be redirected to the 'view' page. + * @param integer $id + * @return mixed + */ + public function actionUpdate($id) + { + $model = $this->findModel($id); + + if ($model->load(Yii::$app->request->post()) && $model->save()) { + return $this->redirect(['view', 'id' => $model->id]); + } else { + return $this->render('update', [ + 'model' => $model, + ]); + } + } + + /** + * Deletes an existing Ship model. + * If deletion is successful, the browser will be redirected to the 'index' page. + * @param integer $id + * @return mixed + */ + public function actionDelete($id) + { + $this->findModel($id)->delete(); + + return $this->redirect(['index']); + } + + /** + * Finds the Ship model based on its primary key value. + * If the model is not found, a 404 HTTP exception will be thrown. + * @param integer $id + * @return Ship the loaded model + * @throws NotFoundHttpException if the model cannot be found + */ + protected function findModel($id) + { + if (($model = Ship::findOne($id)) !== null) { + return $model; + } else { + throw new NotFoundHttpException('The requested page does not exist.'); + } + } +} diff --git a/backend/controllers/SiteController.php b/backend/controllers/SiteController.php new file mode 100755 index 0000000..9624dcc --- /dev/null +++ b/backend/controllers/SiteController.php @@ -0,0 +1,98 @@ + [ + 'class' => AccessControl::className(), + 'rules' => [ + [ + 'actions' => ['login', 'error'], + 'allow' => true, + ], + [ + 'actions' => ['logout', 'index'], + 'allow' => true, + 'roles' => ['@'], + ], + ], + ], + 'verbs' => [ + 'class' => VerbFilter::className(), + 'actions' => [ + 'logout' => ['post'], + ], + ], + ]; + } + + /** + * @inheritdoc + */ + public function actions() + { + return [ + 'error' => [ + 'class' => 'yii\web\ErrorAction', + ], + ]; + } + + /** + * Displays homepage. + * + * @return string + */ + public function actionIndex() + { + return $this->render('index'); + } + + /** + * Login action. + * + * @return string + */ + public function actionLogin() + { + if (!Yii::$app->user->isGuest) { + return $this->goHome(); + } + + $model = new LoginForm(); + if ($model->load(Yii::$app->request->post()) && $model->login()) { + return $this->goBack(); + } else { + return $this->render('login', [ + 'model' => $model, + ]); + } + } + + /** + * Logout action. + * + * @return string + */ + public function actionLogout() + { + Yii::$app->user->logout(); + + return $this->goHome(); + } +} diff --git a/backend/controllers/UserController.php b/backend/controllers/UserController.php new file mode 100644 index 0000000..3bba264 --- /dev/null +++ b/backend/controllers/UserController.php @@ -0,0 +1,124 @@ + [ + 'class' => VerbFilter::className(), + 'actions' => [ + 'delete' => ['POST'], + ], + ], + ]; + } + + /** + * Lists all User models. + * @return mixed + */ + public function actionIndex() + { + $searchModel = new UserSearch(); + $dataProvider = $searchModel->search(Yii::$app->request->queryParams); + + return $this->render('index', [ + 'searchModel' => $searchModel, + 'dataProvider' => $dataProvider, + ]); + } + + /** + * Displays a single User model. + * @param integer $id + * @return mixed + */ + public function actionView($id) + { + return $this->render('view', [ + 'model' => $this->findModel($id), + ]); + } + + /** + * Creates a new User model. + * If creation is successful, the browser will be redirected to the 'view' page. + * @return mixed + */ + public function actionCreate() + { + $model = new User(); + + if ($model->load(Yii::$app->request->post()) && $model->save()) { + return $this->redirect(['view', 'id' => $model->id]); + } else { + return $this->render('create', [ + 'model' => $model, + ]); + } + } + + /** + * Updates an existing User model. + * If update is successful, the browser will be redirected to the 'view' page. + * @param integer $id + * @return mixed + */ + public function actionUpdate($id) + { + $model = $this->findModel($id); + + if ($model->load(Yii::$app->request->post()) && $model->save()) { + return $this->redirect(['view', 'id' => $model->id]); + } else { + return $this->render('update', [ + 'model' => $model, + ]); + } + } + + /** + * Deletes an existing User model. + * If deletion is successful, the browser will be redirected to the 'index' page. + * @param integer $id + * @return mixed + */ + public function actionDelete($id) + { + $this->findModel($id)->delete(); + + return $this->redirect(['index']); + } + + /** + * Finds the User model based on its primary key value. + * If the model is not found, a 404 HTTP exception will be thrown. + * @param integer $id + * @return User the loaded model + * @throws NotFoundHttpException if the model cannot be found + */ + protected function findModel($id) + { + if (($model = User::findOne($id)) !== null) { + return $model; + } else { + throw new NotFoundHttpException('The requested page does not exist.'); + } + } +} diff --git a/backend/models/.gitkeep b/backend/models/.gitkeep new file mode 100755 index 0000000..72e8ffc --- /dev/null +++ b/backend/models/.gitkeep @@ -0,0 +1 @@ +* diff --git a/backend/models/ModsSearch.php b/backend/models/ModsSearch.php new file mode 100644 index 0000000..fcc9801 --- /dev/null +++ b/backend/models/ModsSearch.php @@ -0,0 +1,73 @@ + $query, + ]); + + $this->load($params); + + if (!$this->validate()) { + // uncomment the following line if you do not want to return any records when validation fails + // $query->where('0=1'); + return $dataProvider; + } + + // grid filtering conditions + $query->andFilterWhere([ + 'id' => $this->id, + 'ship_id' => $this->ship_id, + 'mod_gun' => $this->mod_gun, + 'mod_tower' => $this->mod_tower, + 'exp_gun' => $this->exp_gun, + 'exp_tower' => $this->exp_tower, + 'cost_gun' => $this->cost_gun, + 'cost_tower' => $this->cost_tower, + ]); + + return $dataProvider; + } +} diff --git a/backend/models/ShipSearch.php b/backend/models/ShipSearch.php new file mode 100644 index 0000000..4b55ce9 --- /dev/null +++ b/backend/models/ShipSearch.php @@ -0,0 +1,76 @@ + $query, + ]); + + $this->load($params); + + if (!$this->validate()) { + // uncomment the following line if you do not want to return any records when validation fails + // $query->where('0=1'); + return $dataProvider; + } + + // grid filtering conditions + $query->andFilterWhere([ + 'id' => $this->id, + 'lvl' => $this->lvl, + 'stock_gun' => $this->stock_gun, + 'stock_tower' => $this->stock_tower, + 'mod_gun' => $this->mod_gun, + 'mod_tower' => $this->mod_tower, + 'strength' => $this->strength, + 'type' => $this->type, + ]); + + $query->andFilterWhere(['like', 'name', $this->name]); + + return $dataProvider; + } +} diff --git a/backend/models/UserSearch.php b/backend/models/UserSearch.php new file mode 100644 index 0000000..eb125cf --- /dev/null +++ b/backend/models/UserSearch.php @@ -0,0 +1,81 @@ + $query, + ]); + + $this->load($params); + + if (!$this->validate()) { + // uncomment the following line if you do not want to return any records when validation fails + // $query->where('0=1'); + return $dataProvider; + } + + // grid filtering conditions + $query->andFilterWhere([ + 'id' => $this->id, + 'status' => $this->status, + 'created_at' => $this->created_at, + 'updated_at' => $this->updated_at, + 'win' => $this->win, + 'lose' => $this->lose, + 'draw' => $this->draw, + 'credits' => $this->credits, + 'battle_id' => $this->battle_id, + ]); + + $query->andFilterWhere(['like', 'username', $this->username]) + ->andFilterWhere(['like', 'auth_key', $this->auth_key]) + ->andFilterWhere(['like', 'password_hash', $this->password_hash]) + ->andFilterWhere(['like', 'password_reset_token', $this->password_reset_token]) + ->andFilterWhere(['like', 'email', $this->email]); + + return $dataProvider; + } +} diff --git a/backend/runtime/.gitignore b/backend/runtime/.gitignore new file mode 100755 index 0000000..c96a04f --- /dev/null +++ b/backend/runtime/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/backend/tests/_bootstrap.php b/backend/tests/_bootstrap.php new file mode 100755 index 0000000..83a1f26 --- /dev/null +++ b/backend/tests/_bootstrap.php @@ -0,0 +1,9 @@ + 'erau', + 'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI', + // password_0 + 'password_hash' => '$2y$13$nJ1WDlBaGcbCdbNC5.5l4.sgy.OMEKCqtDQOdQ2OWpgiKRWYyzzne', + 'password_reset_token' => 'RkD_Jw0_8HEedzLk7MM-ZKEFfYR7VbMr_1392559490', + 'created_at' => '1392559490', + 'updated_at' => '1392559490', + 'email' => 'sfriesen@jenkins.info', + ], +]; diff --git a/backend/tests/_output/.gitignore b/backend/tests/_output/.gitignore new file mode 100755 index 0000000..d6b7ef3 --- /dev/null +++ b/backend/tests/_output/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/backend/tests/_support/.gitignore b/backend/tests/_support/.gitignore new file mode 100755 index 0000000..36e264c --- /dev/null +++ b/backend/tests/_support/.gitignore @@ -0,0 +1 @@ +_generated diff --git a/backend/tests/_support/FunctionalTester.php b/backend/tests/_support/FunctionalTester.php new file mode 100755 index 0000000..80a79ed --- /dev/null +++ b/backend/tests/_support/FunctionalTester.php @@ -0,0 +1,25 @@ +haveFixtures([ + 'user' => [ + 'class' => UserFixture::className(), + 'dataFile' => codecept_data_dir() . 'login_data.php' + ] + ]); + } + /** + * @param FunctionalTester $I + */ + public function loginUser(FunctionalTester $I) + { + $I->amOnPage('/site/login'); + $I->fillField('Username', 'erau'); + $I->fillField('Password', 'password_0'); + $I->click('login-button'); + + $I->see('Logout (erau)', 'form button[type=submit]'); + $I->dontSeeLink('Login'); + $I->dontSeeLink('Signup'); + } +} diff --git a/backend/tests/functional/_bootstrap.php b/backend/tests/functional/_bootstrap.php new file mode 100755 index 0000000..30ed54b --- /dev/null +++ b/backend/tests/functional/_bootstrap.php @@ -0,0 +1,16 @@ + 'davert']); + * ``` + * + * In Cests + * + * ```php + * \Codeception\Util\Fixtures::get('user1'); + * ``` + */ \ No newline at end of file diff --git a/backend/tests/unit.suite.yml b/backend/tests/unit.suite.yml new file mode 100755 index 0000000..1ba1eb4 --- /dev/null +++ b/backend/tests/unit.suite.yml @@ -0,0 +1 @@ +class_name: UnitTester diff --git a/backend/tests/unit/_bootstrap.php b/backend/tests/unit/_bootstrap.php new file mode 100755 index 0000000..e432ce5 --- /dev/null +++ b/backend/tests/unit/_bootstrap.php @@ -0,0 +1,16 @@ + 'davert']); + * ``` + * + * In Tests + * + * ```php + * \Codeception\Util\Fixtures::get('user1'); + * ``` + */ diff --git a/backend/views/layouts/main.php b/backend/views/layouts/main.php new file mode 100755 index 0000000..08628af --- /dev/null +++ b/backend/views/layouts/main.php @@ -0,0 +1,82 @@ + +beginPage() ?> + + + + + + + <?= Html::encode($this->title) ?> + head() ?> + + +beginBody() ?> + +
+ 'My Company', + 'brandUrl' => Yii::$app->homeUrl, + 'options' => [ + 'class' => 'navbar-inverse navbar-fixed-top', + ], + ]); + $menuItems = [ + ['label' => 'Home', 'url' => ['/site/index']], + ['label' => 'Ships', 'url' => ['/ship']], + ['label' => 'Users', 'url' => ['/user']], + ['label' => 'Mods', 'url' => ['/mods']], + ]; + if (Yii::$app->user->isGuest) { + $menuItems[] = ['label' => 'Login', 'url' => ['/site/login']]; + } else { + $menuItems[] = '
  • ' + . Html::beginForm(['/site/logout'], 'post') + . Html::submitButton( + 'Logout (' . Yii::$app->user->identity->username . ')', + ['class' => 'btn btn-link logout'] + ) + . Html::endForm() + . '
  • '; + } + echo Nav::widget([ + 'options' => ['class' => 'navbar-nav navbar-right'], + 'items' => $menuItems, + ]); + NavBar::end(); + ?> + +
    + isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [], + ]) ?> + + +
    +
    + + + +endBody() ?> + + +endPage() ?> diff --git a/backend/views/mods/_form.php b/backend/views/mods/_form.php new file mode 100644 index 0000000..8cf55db --- /dev/null +++ b/backend/views/mods/_form.php @@ -0,0 +1,27 @@ + + +
    + + + + field($model, 'ship_id')->textInput() ?> + + field($model, 'mod_gun')->textInput() ?> + + field($model, 'mod_tower')->textInput() ?> + +
    + isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> +
    + + + +
    diff --git a/backend/views/mods/_search.php b/backend/views/mods/_search.php new file mode 100644 index 0000000..024587f --- /dev/null +++ b/backend/views/mods/_search.php @@ -0,0 +1,41 @@ + + + diff --git a/backend/views/mods/create.php b/backend/views/mods/create.php new file mode 100644 index 0000000..53a409a --- /dev/null +++ b/backend/views/mods/create.php @@ -0,0 +1,21 @@ +title = 'Create Mods'; +$this->params['breadcrumbs'][] = ['label' => 'Mods', 'url' => ['index']]; +$this->params['breadcrumbs'][] = $this->title; +?> +
    + +

    title) ?>

    + + render('_form', [ + 'model' => $model, + ]) ?> + +
    diff --git a/backend/views/mods/index.php b/backend/views/mods/index.php new file mode 100644 index 0000000..b577399 --- /dev/null +++ b/backend/views/mods/index.php @@ -0,0 +1,39 @@ +title = 'Mods'; +$this->params['breadcrumbs'][] = $this->title; +?> +
    + +

    title) ?>

    + render('_search', ['model' => $searchModel]); ?> + +

    + 'btn btn-success']) ?> +

    + $dataProvider, + // 'filterModel' => $searchModel, + 'columns' => [ + ['class' => 'yii\grid\SerialColumn'], + + //'id', + 'ship_id', + 'mod_gun', + 'mod_tower', + 'exp_gun', + 'exp_tower', + 'cost_gun', + 'cost_tower', + + ['class' => 'yii\grid\ActionColumn'], + ], + ]); ?> +
    diff --git a/backend/views/mods/update.php b/backend/views/mods/update.php new file mode 100644 index 0000000..f0fc517 --- /dev/null +++ b/backend/views/mods/update.php @@ -0,0 +1,21 @@ +title = 'Update Mods: ' . $model->id; +$this->params['breadcrumbs'][] = ['label' => 'Mods', 'url' => ['index']]; +$this->params['breadcrumbs'][] = ['label' => $model->id, 'url' => ['view', 'id' => $model->id]]; +$this->params['breadcrumbs'][] = 'Update'; +?> +
    + +

    title) ?>

    + + render('_form', [ + 'model' => $model, + ]) ?> + +
    diff --git a/backend/views/mods/view.php b/backend/views/mods/view.php new file mode 100644 index 0000000..c579d97 --- /dev/null +++ b/backend/views/mods/view.php @@ -0,0 +1,42 @@ +title = $model->id; +$this->params['breadcrumbs'][] = ['label' => 'Mods', 'url' => ['index']]; +$this->params['breadcrumbs'][] = $this->title; +?> +
    + +

    title) ?>

    + +

    + $model->id], ['class' => 'btn btn-primary']) ?> + $model->id], [ + 'class' => 'btn btn-danger', + 'data' => [ + 'confirm' => 'Are you sure you want to delete this item?', + 'method' => 'post', + ], + ]) ?> +

    + + $model, + 'attributes' => [ + 'id', + 'ship_id', + 'mod_gun', + 'mod_tower', + 'exp_gun', + 'exp_tower', + 'cost_gun', + 'cost_tower', + ], + ]) ?> + +
    diff --git a/backend/views/ship/_form.php b/backend/views/ship/_form.php new file mode 100644 index 0000000..4dd9b72 --- /dev/null +++ b/backend/views/ship/_form.php @@ -0,0 +1,37 @@ + + +
    + + + + field($model, 'id')->textInput() ?> + + field($model, 'name')->textInput(['maxlength' => true]) ?> + + field($model, 'lvl')->textInput() ?> + + field($model, 'stock_gun')->textInput() ?> + + field($model, 'stock_tower')->textInput() ?> + + field($model, 'mod_gun')->textInput() ?> + + field($model, 'mod_tower')->textInput() ?> + + field($model, 'strength')->textInput() ?> + +
    + isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> +
    + + + +
    diff --git a/backend/views/ship/_search.php b/backend/views/ship/_search.php new file mode 100644 index 0000000..e18ee6a --- /dev/null +++ b/backend/views/ship/_search.php @@ -0,0 +1,43 @@ + + + diff --git a/backend/views/ship/create.php b/backend/views/ship/create.php new file mode 100644 index 0000000..c98e149 --- /dev/null +++ b/backend/views/ship/create.php @@ -0,0 +1,21 @@ +title = 'Create Ship'; +$this->params['breadcrumbs'][] = ['label' => 'Ships', 'url' => ['index']]; +$this->params['breadcrumbs'][] = $this->title; +?> +
    + +

    title) ?>

    + + render('_form', [ + 'model' => $model, + ]) ?> + +
    diff --git a/backend/views/ship/index.php b/backend/views/ship/index.php new file mode 100644 index 0000000..2fee3f2 --- /dev/null +++ b/backend/views/ship/index.php @@ -0,0 +1,39 @@ +title = 'Ships'; +$this->params['breadcrumbs'][] = $this->title; +?> +
    + +

    title) ?>

    + render('_search', ['model' => $searchModel]); ?> + +

    + 'btn btn-success'], ['style' => 'width: 240px']) ?> +

    + $dataProvider, + //'filterModel' => $searchModel, + 'columns' => [ + ['class' => 'yii\grid\SerialColumn'], + //'id', + 'name', + 'lvl', + 'stock_gun', + 'stock_tower', + 'mod_gun', + 'mod_tower', + 'strength', + 'type', + + ['class' => 'yii\grid\ActionColumn'], + ], + ]); ?> +
    diff --git a/backend/views/ship/update.php b/backend/views/ship/update.php new file mode 100644 index 0000000..9a35ea6 --- /dev/null +++ b/backend/views/ship/update.php @@ -0,0 +1,21 @@ +title = 'Update Ship: ' . $model->name; +$this->params['breadcrumbs'][] = ['label' => 'Ships', 'url' => ['index']]; +$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]]; +$this->params['breadcrumbs'][] = 'Update'; +?> +
    + +

    title) ?>

    + + render('_form', [ + 'model' => $model, + ]) ?> + +
    diff --git a/backend/views/ship/view.php b/backend/views/ship/view.php new file mode 100644 index 0000000..8d2ea26 --- /dev/null +++ b/backend/views/ship/view.php @@ -0,0 +1,43 @@ +title = $model->name; +$this->params['breadcrumbs'][] = ['label' => 'Ships', 'url' => ['index']]; +$this->params['breadcrumbs'][] = $this->title; +?> +
    + +

    title) ?>

    + +

    + $model->id], ['class' => 'btn btn-primary']) ?> + $model->id], [ + 'class' => 'btn btn-danger', + 'data' => [ + 'confirm' => 'Are you sure you want to delete this item?', + 'method' => 'post', + ], + ]) ?> +

    + + $model, + 'attributes' => [ + 'id', + 'name', + 'lvl', + 'stock_gun', + 'stock_tower', + 'mod_gun', + 'mod_tower', + 'strength', + 'type', + ], + ]) ?> + +
    diff --git a/backend/views/site/error.php b/backend/views/site/error.php new file mode 100755 index 0000000..0ba2574 --- /dev/null +++ b/backend/views/site/error.php @@ -0,0 +1,27 @@ +title = $name; +?> +
    + +

    title) ?>

    + +
    + +
    + +

    + The above error occurred while the Web server was processing your request. +

    +

    + Please contact us if you think this is a server error. Thank you. +

    + +
    diff --git a/backend/views/site/index.php b/backend/views/site/index.php new file mode 100755 index 0000000..f780610 --- /dev/null +++ b/backend/views/site/index.php @@ -0,0 +1,53 @@ +title = 'My Yii Application'; +?> +
    + +
    +

    Congratulations!

    + +

    You have successfully created your Yii-powered application.

    + +

    Get started with Yii

    +
    + +
    + +
    +
    +

    Heading

    + +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip + ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu + fugiat nulla pariatur.

    + +

    Yii Documentation »

    +
    +
    +

    Heading

    + +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip + ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu + fugiat nulla pariatur.

    + +

    Yii Forum »

    +
    +
    +

    Heading

    + +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip + ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu + fugiat nulla pariatur.

    + +

    Yii Extensions »

    +
    +
    + +
    +
    diff --git a/backend/views/site/login.php b/backend/views/site/login.php new file mode 100755 index 0000000..20f3f78 --- /dev/null +++ b/backend/views/site/login.php @@ -0,0 +1,35 @@ +title = 'Login'; +$this->params['breadcrumbs'][] = $this->title; +?> +
    +

    title) ?>

    + +

    Please fill out the following fields to login:

    + +
    +
    + 'login-form']); ?> + + field($model, 'username')->textInput(['autofocus' => true]) ?> + + field($model, 'password')->passwordInput() ?> + + field($model, 'rememberMe')->checkbox() ?> + +
    + 'btn btn-primary', 'name' => 'login-button']) ?> +
    + + +
    +
    +
    diff --git a/backend/views/user/_form.php b/backend/views/user/_form.php new file mode 100644 index 0000000..2fef732 --- /dev/null +++ b/backend/views/user/_form.php @@ -0,0 +1,23 @@ + + +
    + + + + field($model, 'status')->textInput() ?> + +
    + isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> +
    + + + +
    diff --git a/backend/views/user/_search.php b/backend/views/user/_search.php new file mode 100644 index 0000000..b615465 --- /dev/null +++ b/backend/views/user/_search.php @@ -0,0 +1,53 @@ + + + diff --git a/backend/views/user/create.php b/backend/views/user/create.php new file mode 100644 index 0000000..a71baf7 --- /dev/null +++ b/backend/views/user/create.php @@ -0,0 +1,21 @@ +title = 'Create User'; +$this->params['breadcrumbs'][] = ['label' => 'Users', 'url' => ['index']]; +$this->params['breadcrumbs'][] = $this->title; +?> +
    + +

    title) ?>

    + + render('_form', [ + 'model' => $model, + ]) ?> + +
    diff --git a/backend/views/user/index.php b/backend/views/user/index.php new file mode 100644 index 0000000..1b4d7fc --- /dev/null +++ b/backend/views/user/index.php @@ -0,0 +1,45 @@ +title = 'Users'; +$this->params['breadcrumbs'][] = $this->title; +?> +
    + +

    title) ?>

    + render('_search', ['model' => $searchModel]); ?> + +

    + 'btn btn-success']) ?> +

    + $dataProvider, + 'filterModel' => $searchModel, + 'columns' => [ + ['class' => 'yii\grid\SerialColumn'], + + //'id', + 'username', + //'auth_key', + //'password_hash', + //'password_reset_token', + // 'email:email', + // 'status', + // 'created_at', + // 'updated_at', + 'win', + 'lose', + 'draw', + 'credits', + 'battle_id', + + ['class' => 'yii\grid\ActionColumn'], + ], + ]); ?> +
    diff --git a/backend/views/user/update.php b/backend/views/user/update.php new file mode 100644 index 0000000..0dece80 --- /dev/null +++ b/backend/views/user/update.php @@ -0,0 +1,21 @@ +title = 'Update User: ' . $model->id; +$this->params['breadcrumbs'][] = ['label' => 'Users', 'url' => ['index']]; +$this->params['breadcrumbs'][] = ['label' => $model->id, 'url' => ['view', 'id' => $model->id]]; +$this->params['breadcrumbs'][] = 'Update'; +?> +
    + +

    title) ?>

    + + render('_form', [ + 'model' => $model, + ]) ?> + +
    diff --git a/backend/views/user/view.php b/backend/views/user/view.php new file mode 100644 index 0000000..60e011e --- /dev/null +++ b/backend/views/user/view.php @@ -0,0 +1,48 @@ +title = $model->id; +$this->params['breadcrumbs'][] = ['label' => 'Users', 'url' => ['index']]; +$this->params['breadcrumbs'][] = $this->title; +?> +
    + +

    title) ?>

    + +

    + $model->id], ['class' => 'btn btn-primary']) ?> + $model->id], [ + 'class' => 'btn btn-danger', + 'data' => [ + 'confirm' => 'Are you sure you want to delete this item?', + 'method' => 'post', + ], + ]) ?> +

    + + $model, + 'attributes' => [ + 'id', + 'username', + 'auth_key', + 'password_hash', + 'password_reset_token', + 'email:email', + 'status', + 'created_at', + 'updated_at', + 'win', + 'lose', + 'draw', + 'credits', + 'battle_id', + ], + ]) ?> + +
    diff --git a/backend/web/.gitignore b/backend/web/.gitignore new file mode 100755 index 0000000..25c74e6 --- /dev/null +++ b/backend/web/.gitignore @@ -0,0 +1,2 @@ +/index.php +/index-test.php diff --git a/backend/web/.htaccess b/backend/web/.htaccess new file mode 100755 index 0000000..1426180 --- /dev/null +++ b/backend/web/.htaccess @@ -0,0 +1,10 @@ +Options +FollowSymLinks + +RewriteEngine on + +# if a directory or a file exists, use it directly +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d + +# otherwise forward it to index.php +RewriteRule . index.php diff --git a/backend/web/assets/.gitignore b/backend/web/assets/.gitignore new file mode 100755 index 0000000..d6b7ef3 --- /dev/null +++ b/backend/web/assets/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/backend/web/css/site.css b/backend/web/css/site.css new file mode 100755 index 0000000..a4573b8 --- /dev/null +++ b/backend/web/css/site.css @@ -0,0 +1,121 @@ +html, +body { + height: 100%; + background: url('../../../frontend/web/img/bg.jpg'); +} + +.wrap { + min-height: 100%; + height: auto; + margin: 0 auto -60px; + padding: 0 0 60px; +} + +.wrap > .container { + padding: 70px 15px 20px; +} + +.footer { + height: 60px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + padding-top: 20px; +} + +.jumbotron { + text-align: center; + background-color: transparent; +} + +.jumbotron .btn { + font-size: 21px; + padding: 14px 24px; +} + +.not-set { + color: #c55; + font-style: italic; +} + +/* add sorting icons to gridview sort links */ +a.asc:after, a.desc:after { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + padding-left: 5px; +} + +a.asc:after { + content: /*"\e113"*/ "\e151"; +} + +a.desc:after { + content: /*"\e114"*/ "\e152"; +} + +.sort-numerical a.asc:after { + content: "\e153"; +} + +.sort-numerical a.desc:after { + content: "\e154"; +} + +.sort-ordinal a.asc:after { + content: "\e155"; +} + +.sort-ordinal a.desc:after { + content: "\e156"; +} + +.grid-view td { + white-space: nowrap; +} + +.grid-view .filters input, +.grid-view .filters select { + min-width: 50px; +} + +.hint-block { + display: block; + margin-top: 5px; + color: #999; +} + +.error-summary { + color: #a94442; + background: #fdf7f7; + border-left: 3px solid #eed3d7; + padding: 10px 20px; + margin: 0 0 15px 0; +} + +/* align the logout "link" (button in form) of the navbar */ +.nav li > form > button.logout { + padding: 15px; + border: none; +} + +@media(max-width:767px) { + .nav li > form > button.logout { + display:block; + text-align: left; + width: 100%; + padding: 10px 15px; + } +} + +.nav > li > form > button.logout:focus, +.nav > li > form > button.logout:hover { + text-decoration: none; +} + +.nav > li > form > button.logout:focus { + outline: none; +} diff --git a/backend/web/favicon.ico b/backend/web/favicon.ico new file mode 100755 index 0000000..580ed73 Binary files /dev/null and b/backend/web/favicon.ico differ diff --git a/backend/web/robots.txt b/backend/web/robots.txt new file mode 100755 index 0000000..1f53798 --- /dev/null +++ b/backend/web/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / diff --git a/codeception.yml b/codeception.yml new file mode 100755 index 0000000..af20104 --- /dev/null +++ b/codeception.yml @@ -0,0 +1,9 @@ +# global codeception file to run tests from all apps +include: + - common + - frontend + - backend +paths: + log: console/runtime/logs +settings: + colors: true \ No newline at end of file diff --git a/common/codeception.yml b/common/codeception.yml new file mode 100755 index 0000000..de5d76a --- /dev/null +++ b/common/codeception.yml @@ -0,0 +1,15 @@ +namespace: common\tests +actor: Tester +paths: + tests: tests + log: tests/_output + data: tests/_data + helpers: tests/_support +settings: + bootstrap: _bootstrap.php + colors: true + memory_limit: 1024M +modules: + config: + Yii2: + configFile: 'config/test-local.php' diff --git a/common/components/Combat.php b/common/components/Combat.php new file mode 100644 index 0000000..3650072 --- /dev/null +++ b/common/components/Combat.php @@ -0,0 +1,203 @@ +session; + $session->open(); + if (!isset($session['usershiphp']) && !isset($session['bothp'])) { + $session['usershiphp'] = $ship->strength; + $session['bothp'] = $ship->strength; + } + + $playerdmg = $this->dmgPlayer($ship->ship_id, $ship->mod_gun); + $botdmg = $this->dmgBot($ship->ship_id); + + switch ($type) { + case 1: + $i = rand(0,10); + if($i == 7) { + $adddmg = (($ship->strength)*0.3); + } else { + $adddmg = (($ship->strength)*0.1); + } + $session['bothp'] = $session['bothp'] - ceil(($this->shipTypePlayer($ship->type, $playerdmg) + $adddmg)); + $session['usershiphp'] = $session['usershiphp'] - ceil(($this->shipTypeBot($ship->type, $botdmg) + $adddmg)); + $log = Yii::t('app', 'You attacked the bot warship on -').''.ceil(($this->shipTypePlayer($ship->type, $playerdmg) + $adddmg)).'
    '; + $log .= Yii::t('app', 'Our warship were attacked by bot warship on -').''.ceil(($this->shipTypeBot($ship->type, $botdmg) + $adddmg)).''; + break; + case 2: + $adddmg = (($ship->strength)*0.1); + $session['bothp'] = $session['bothp'] - ceil(($this->shipTypePlayer($ship->strength, $playerdmg) + $adddmg)); + $session['usershiphp'] = $session['usershiphp'] - ceil(($this->shipTypeBot($ship->strength, $botdmg) + $adddmg)); + $log = Yii::t('app', 'You attacked the bot warship on -').''.ceil(($this->shipTypePlayer($ship->type, $playerdmg) + $adddmg)).'
    '; + $log .= Yii::t('app', 'Our warship were attacked by bot warship on -').''.ceil(($this->shipTypeBot($ship->type, $botdmg) + $adddmg)).''; + break; + case 3: + $adddmg = (($ship->strength)*0.1); + $session['bothp'] = $session['bothp'] - ceil(($this->shipTypePlayer($ship->strength, $playerdmg) + $adddmg)); + $session['usershiphp'] = $session['usershiphp'] - ceil(($this->shipTypeBot($ship->strength, $botdmg) + $adddmg)); + $log = Yii::t('app', 'You attacked the bot warship on -').''.ceil(($this->shipTypePlayer($ship->type, $playerdmg) + $adddmg)).'
    '; + $log .= Yii::t('app', 'Our warship were attacked by bot warship on -').''.ceil(($this->shipTypeBot($ship->type, $botdmg) + $adddmg)).''; + break; + case 4: + $i = rand(1,30); + if($i == 23) { + $adddmg = $ship->strength; + } else { + $adddmg = ceil(($ship->strength)*0.1); + } + $session['bothp'] = $session['bothp'] - ceil(($this->shipTypePlayer($ship->strength, $playerdmg) + $adddmg)); + $session['usershiphp'] = $session['usershiphp'] - ceil(($this->shipTypeBot($ship->strength, $botdmg) + $adddmg)); + $log = Yii::t('app', 'You attacked the bot warship on -').''.ceil(($this->shipTypePlayer($ship->type, $playerdmg) + $adddmg)).'
    '; + $log .= Yii::t('app', 'Our warship were attacked by bot warship on -').''.ceil(($this->shipTypeBot($ship->type, $botdmg) + $adddmg)).''; + break; + } + $this->writeLog($bid->bid, $log); + /* + * Cheking for state - HP; + */ + if ($session['usershiphp'] <= 0) { + $bid->updateAll(['status' => 1], ['bid' => $bid->bid]); + unset($session['usershiphp']); + unset($session['bothp']); + unset($log); + unset($battleid); + $player->updateCounters(['lose' => 1]); + $player->updateAll(['battle_id' => 0], ['id' => Yii::$app->user->id]); + Controller::redirect('combat/lose'); + } elseif ($session['bothp'] <= 0) { + $bid->updateAll(['status' => 1], ['bid' => $bid->bid]); + unset($session['usershiphp']); + unset($session['bothp']); + unset($log); + unset($battleid); + $ship->updateCounters(['exp' => $this->expirence($ship->ship_id)]); + $player->updateCounters(['win' => 1]); + $player->updateCounters(['credits' => +($this->giveMoney())]); + $player->updateAll(['battle_id' => 0], ['id' => Yii::$app->user->id]); + Controller::redirect('combat/win'); + } + + return [$session['usershiphp'], $session['bothp'], $ship, $player]; + + } + + /** + * @param $user + * @param $item + * @return mixed + */ + public function addHp($user, $item) + { + if(Yii::$app->request->post('gethp')) { + $user = $user + $item; + return $user; + } + } + + /** + * Calculate damage for player; + */ + public function dmgPlayer($id, $gun) + { + $playerdmg = (($id) * rand(80,90)) + ($gun) * 10; + + return $playerdmg; + } + + /** + * @param $id + * @return mixed + */ + public function dmgBot($id) + { + $botdmg = ($id) * rand(80,10); + + return $botdmg; + } + + /** + * @param $id + * @return mixed + */ + public function expirence($id) + { + $expirence = ($id*(10*$this->exp)+rand(10,20)); + + return $expirence; + } + + /** + * @return mixed + */ + public function giveMoney() + { + $givemoney = (($this->credits)*100)+rand(0,50); + + return $givemoney; + } + + /** + * @param $bid + * @param $pdmg + */ + public function writeLog($bid, $pdmg) + { + //$sql = "UPDATE `battles` SET `logs` = CONCAT(`logs`,'".$pdmg."') WHERE `bid` = $bid"; + //$battles = Battles::findBySql($sql)->all(); + + $battleid = Battles::findOne(['bid' => $bid]); + $battleid->updateAll(['logs' => new \yii\db\Expression("CONCAT('".$pdmg."')")], ['bid' => $bid]); + } + + /** + * @param $type + * @param $dmg + * @return mixed + */ + public function shipTypePlayer($type, $dmg) + { + if($type == 3) { + $pdmg = $dmg - (rand(20, 30) * 1.5); + return $pdmg; + } elseif ($type == 2) { + $pdmg = $dmg + (rand(40, 50) * 1.5); + return $pdmg; + } else { + $pdmg = $dmg; + return $pdmg; + } + } + + /** + * @param $type + * @param $dmg + * @return mixed + */ + public function shipTypeBot($type, $dmg) + { + if($type == 3) { + $bdmg = $dmg - (rand(19, 32) * 1.4); + return $bdmg; + } elseif ($type == 2) { + $bdmg = $dmg + (rand(38, 50) * 1.5); + return $bdmg; + } else { + $bdmg = $dmg; + return $bdmg; + } + } +} \ No newline at end of file diff --git a/common/config/.gitignore b/common/config/.gitignore new file mode 100755 index 0000000..42799dd --- /dev/null +++ b/common/config/.gitignore @@ -0,0 +1,3 @@ +main-local.php +params-local.php +test-local.php diff --git a/common/config/bootstrap.php b/common/config/bootstrap.php new file mode 100755 index 0000000..93d0185 --- /dev/null +++ b/common/config/bootstrap.php @@ -0,0 +1,5 @@ + dirname(dirname(__DIR__)) . '/vendor', + 'components' => [ + 'cache' => [ + 'class' => 'yii\caching\FileCache', + ], + 'Combat' => [ + 'class' => 'common\components\Combat', + 'exp' => '10', + 'credits' => '0.5', + ], + ], +]; diff --git a/common/config/params.php b/common/config/params.php new file mode 100755 index 0000000..4ec9ba6 --- /dev/null +++ b/common/config/params.php @@ -0,0 +1,6 @@ + 'admin@example.com', + 'supportEmail' => 'support@example.com', + 'user.passwordResetTokenExpire' => 3600, +]; diff --git a/common/config/test.php b/common/config/test.php new file mode 100755 index 0000000..c952c41 --- /dev/null +++ b/common/config/test.php @@ -0,0 +1,11 @@ + 'app-common-tests', + 'basePath' => dirname(__DIR__), + 'components' => [ + 'user' => [ + 'class' => 'yii\web\User', + 'identityClass' => 'common\models\User', + ], + ], +]; diff --git a/common/fixtures/User.php b/common/fixtures/User.php new file mode 100755 index 0000000..d4b0f36 --- /dev/null +++ b/common/fixtures/User.php @@ -0,0 +1,9 @@ + +beginPage() ?> + + + + + <?= Html::encode($this->title) ?> + head() ?> + + + beginBody() ?> + + endBody() ?> + + +endPage() ?> diff --git a/common/mail/layouts/text.php b/common/mail/layouts/text.php new file mode 100755 index 0000000..aab1d5d --- /dev/null +++ b/common/mail/layouts/text.php @@ -0,0 +1,14 @@ + + +beginPage() ?> +beginBody() ?> + +endBody() ?> +endPage() ?> diff --git a/common/mail/passwordResetToken-html.php b/common/mail/passwordResetToken-html.php new file mode 100755 index 0000000..f3daf49 --- /dev/null +++ b/common/mail/passwordResetToken-html.php @@ -0,0 +1,15 @@ +urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]); +?> +
    +

    Hello username) ?>,

    + +

    Follow the link below to reset your password:

    + +

    +
    diff --git a/common/mail/passwordResetToken-text.php b/common/mail/passwordResetToken-text.php new file mode 100755 index 0000000..244c0cb --- /dev/null +++ b/common/mail/passwordResetToken-text.php @@ -0,0 +1,12 @@ +urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]); +?> +Hello username ?>, + +Follow the link below to reset your password: + + diff --git a/common/models/Battles.php b/common/models/Battles.php new file mode 100644 index 0000000..cb81855 --- /dev/null +++ b/common/models/Battles.php @@ -0,0 +1,63 @@ + true, 'targetClass' => User::className(), 'targetAttribute' => ['creator_id' => 'id']], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'logs' => 'Logs', + 'bid' => 'Bid', + 'creator_id' => 'Creator ID', + 'date' => 'Date', + 'status' => 'Status', + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getCreator() + { + return $this->hasOne(User::className(), ['id' => 'creator_id']); + } +} diff --git a/common/models/Items.php b/common/models/Items.php new file mode 100644 index 0000000..c3fb4e4 --- /dev/null +++ b/common/models/Items.php @@ -0,0 +1,57 @@ + 50], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'hp' => 'Hp', + 'qnt' => 'Qnt', + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getUserItems() + { + return $this->hasMany(UserItems::className(), ['item_id' => 'id']); + } +} diff --git a/common/models/LoginForm.php b/common/models/LoginForm.php new file mode 100755 index 0000000..a4f6c6d --- /dev/null +++ b/common/models/LoginForm.php @@ -0,0 +1,90 @@ + Yii::t('app', 'username'), + 'password' => Yii::t('app', 'password'), + 'rememberMe' => Yii::t('app', 'rememberMe'), + ]; + } + + /** + * Validates the password. + * This method serves as the inline validation for password. + * + * @param string $attribute the attribute currently being validated + * @param array $params the additional name-value pairs given in the rule + */ + public function validatePassword($attribute, $params) + { + if (!$this->hasErrors()) { + $user = $this->getUser(); + if (!$user || !$user->validatePassword($this->password)) { + $this->addError($attribute, 'Incorrect username or password.'); + } + } + } + + /** + * Logs in a user using the provided username and password. + * + * @return bool whether the user is logged in successfully + */ + public function login() + { + if ($this->validate()) { + return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0); + } else { + return false; + } + } + + /** + * Finds user by [[username]] + * + * @return User|null + */ + protected function getUser() + { + if ($this->_user === null) { + $this->_user = User::findByUsername($this->username); + } + + return $this->_user; + } +} diff --git a/common/models/Mods.php b/common/models/Mods.php new file mode 100644 index 0000000..b507c6d --- /dev/null +++ b/common/models/Mods.php @@ -0,0 +1,59 @@ + true, 'targetClass' => Ship::className(), 'targetAttribute' => ['ship_id' => 'id']], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'ship_id' => 'Ship ID', + 'mod_gun' => 'Mod Gun', + 'mod_tower' => 'Mod Tower', + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getShip() + { + return $this->hasOne(Ship::className(), ['id' => 'ship_id']); + } +} diff --git a/common/models/Port.php b/common/models/Port.php new file mode 100755 index 0000000..e99f8ec --- /dev/null +++ b/common/models/Port.php @@ -0,0 +1,88 @@ + true, 'targetClass' => \common\models\User::className(), 'targetAttribute' => ['user_id' => 'id']], + [['ship_id'], 'exist', 'skipOnError' => true, 'targetClass' => Ship::className(), 'targetAttribute' => ['ship_id' => 'id']], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'user_id' => 'User ID', + 'ship_id' => 'Ship ID', + 'exp' => 'Exp', + 'stock_gun' => 'Stock Gun', + 'stock_tower' => 'Stock Tower', + 'mod_gun' => 'Mod Gun', + 'mod_tower' => 'Mod Tower', + 'strength' => 'Strength', + 'type' => 'Type', + 'exp_gun' => 'Exp Gun', + 'exp_tower' => 'Exp Tower', + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getUser() + { + return $this->hasOne(User::className(), ['id' => 'user_id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getShip() + { + return $this->hasOne(Ship::className(), ['id' => 'ship_id']); + } +} diff --git a/common/models/Ship.php b/common/models/Ship.php new file mode 100755 index 0000000..8b3ac8f --- /dev/null +++ b/common/models/Ship.php @@ -0,0 +1,68 @@ + 255], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'name' => 'Name', + 'lvl' => 'Lvl', + 'stock_gun' => 'Stock Gun', + 'stock_tower' => 'Stock Tower', + 'mod_gun' => 'Mod Gun', + 'mod_tower' => 'Mod Tower', + 'strength' => 'Strength', + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getPorts() + { + return $this->hasMany(Port::className(), ['ship_id' => 'id']); + } +} diff --git a/common/models/User.php b/common/models/User.php new file mode 100755 index 0000000..d756436 --- /dev/null +++ b/common/models/User.php @@ -0,0 +1,222 @@ + self::STATUS_ACTIVE], + ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]], + ]; + } + + /** + * @inheritdoc + */ + public static function findIdentity($id) + { + return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]); + } + + /** + * @inheritdoc + */ + public static function findIdentityByAccessToken($token, $type = null) + { + throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.'); + } + + /** + * Finds user by username + * + * @param string $username + * @return static|null + */ + public static function findByUsername($username) + { + return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]); + } + + /** + * Finds user by password reset token + * + * @param string $token password reset token + * @return static|null + */ + public static function findByPasswordResetToken($token) + { + if (!static::isPasswordResetTokenValid($token)) { + return null; + } + + return static::findOne([ + 'password_reset_token' => $token, + 'status' => self::STATUS_ACTIVE, + ]); + } + + /** + * Finds out if password reset token is valid + * + * @param string $token password reset token + * @return bool + */ + public static function isPasswordResetTokenValid($token) + { + if (empty($token)) { + return false; + } + + $timestamp = (int) substr($token, strrpos($token, '_') + 1); + $expire = Yii::$app->params['user.passwordResetTokenExpire']; + return $timestamp + $expire >= time(); + } + + /** + * @inheritdoc + */ + public function getId() + { + return $this->getPrimaryKey(); + } + + /** + * @inheritdoc + */ + public function getAuthKey() + { + return $this->auth_key; + } + + /** + * @inheritdoc + */ + public function validateAuthKey($authKey) + { + return $this->getAuthKey() === $authKey; + } + + /** + * Validates password + * + * @param string $password password to validate + * @return bool if password provided is valid for current user + */ + public function validatePassword($password) + { + return Yii::$app->security->validatePassword($password, $this->password_hash); + } + + /** + * Generates password hash from password and sets it to the model + * + * @param string $password + */ + public function setPassword($password) + { + $this->password_hash = Yii::$app->security->generatePasswordHash($password); + } + + /** + * Generates "remember me" authentication key + */ + public function generateAuthKey() + { + $this->auth_key = Yii::$app->security->generateRandomString(); + } + + /** + * Generates new password reset token + */ + public function generatePasswordResetToken() + { + $this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time(); + } + + /** + * Removes password reset token + */ + public function removePasswordResetToken() + { + $this->password_reset_token = null; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getPorts() + { + return $this->hasMany(Port::className(), ['user_id' => 'id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getBattles() + { + return $this->hasMany(Battles::className(), ['creator_id' => 'id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getUserItems() + { + return $this->hasMany(UserItems::className(), ['user_id' => 'id']); + } +} diff --git a/common/models/UserItems.php b/common/models/UserItems.php new file mode 100644 index 0000000..aa50c79 --- /dev/null +++ b/common/models/UserItems.php @@ -0,0 +1,69 @@ + true, 'targetClass' => Items::className(), 'targetAttribute' => ['item_id' => 'id']], + [['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'id' => 'ID', + 'item_id' => 'Item ID', + 'user_id' => 'User ID', + 'qnt' => 'Qnt', + 'hp' => 'Hp', + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getItem() + { + return $this->hasOne(Items::className(), ['id' => 'item_id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getUser() + { + return $this->hasOne(User::className(), ['id' => 'user_id']); + } +} diff --git a/common/tests/_bootstrap.php b/common/tests/_bootstrap.php new file mode 100755 index 0000000..d5a93de --- /dev/null +++ b/common/tests/_bootstrap.php @@ -0,0 +1,9 @@ + 'bayer.hudson', + 'auth_key' => 'HP187Mvq7Mmm3CTU80dLkGmni_FUH_lR', + //password_0 + 'password_hash' => '$2y$13$EjaPFBnZOQsHdGuHI.xvhuDp1fHpo8hKRSk6yshqa9c5EG8s3C3lO', + 'password_reset_token' => 'ExzkCOaYc1L8IOBs4wdTGGbgNiG3Wz1I_1402312317', + 'created_at' => '1402312317', + 'updated_at' => '1402312317', + 'email' => 'nicole.paucek@schultz.info', + ], +]; diff --git a/common/tests/_output/.gitignore b/common/tests/_output/.gitignore new file mode 100755 index 0000000..d6b7ef3 --- /dev/null +++ b/common/tests/_output/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/common/tests/_support/.gitignore b/common/tests/_support/.gitignore new file mode 100755 index 0000000..36e264c --- /dev/null +++ b/common/tests/_support/.gitignore @@ -0,0 +1 @@ +_generated diff --git a/common/tests/_support/UnitTester.php b/common/tests/_support/UnitTester.php new file mode 100755 index 0000000..91cb34f --- /dev/null +++ b/common/tests/_support/UnitTester.php @@ -0,0 +1,25 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::className(), + 'dataFile' => codecept_data_dir() . 'user.php' + ] + ]); + } + + public function testLoginNoUser() + { + $model = new LoginForm([ + 'username' => 'not_existing_username', + 'password' => 'not_existing_password', + ]); + + expect('model should not login user', $model->login())->false(); + expect('user should not be logged in', Yii::$app->user->isGuest)->true(); + } + + public function testLoginWrongPassword() + { + $model = new LoginForm([ + 'username' => 'bayer.hudson', + 'password' => 'wrong_password', + ]); + + expect('model should not login user', $model->login())->false(); + expect('error message should be set', $model->errors)->hasKey('password'); + expect('user should not be logged in', Yii::$app->user->isGuest)->true(); + } + + public function testLoginCorrect() + { + $model = new LoginForm([ + 'username' => 'bayer.hudson', + 'password' => 'password_0', + ]); + + expect('model should login user', $model->login())->true(); + expect('error message should not be set', $model->errors)->hasntKey('password'); + expect('user should be logged in', Yii::$app->user->isGuest)->false(); + } +} diff --git a/common/widgets/Alert.php b/common/widgets/Alert.php new file mode 100755 index 0000000..69f1c40 --- /dev/null +++ b/common/widgets/Alert.php @@ -0,0 +1,75 @@ +session->setFlash('error', 'This is the message'); + * Yii::$app->session->setFlash('success', 'This is the message'); + * Yii::$app->session->setFlash('info', 'This is the message'); + * ``` + * + * Multiple messages could be set as follows: + * + * ```php + * Yii::$app->session->setFlash('error', ['Error 1', 'Error 2']); + * ``` + * + * @author Kartik Visweswaran + * @author Alexander Makarov + */ +class Alert extends \yii\bootstrap\Widget +{ + /** + * @var array the alert types configuration for the flash messages. + * This array is setup as $key => $value, where: + * - $key is the name of the session flash variable + * - $value is the bootstrap alert type (i.e. danger, success, info, warning) + */ + public $alertTypes = [ + 'error' => 'alert-danger', + 'danger' => 'alert-danger', + 'success' => 'alert-success', + 'info' => 'alert-info', + 'warning' => 'alert-warning' + ]; + /** + * @var array the options for rendering the close button tag. + */ + public $closeButton = []; + + + public function init() + { + parent::init(); + + $session = Yii::$app->session; + $flashes = $session->getAllFlashes(); + $appendCss = isset($this->options['class']) ? ' ' . $this->options['class'] : ''; + + foreach ($flashes as $type => $data) { + if (isset($this->alertTypes[$type])) { + $data = (array) $data; + foreach ($data as $i => $message) { + /* initialize css class for each alert box */ + $this->options['class'] = $this->alertTypes[$type] . $appendCss; + + /* assign unique id to each alert box */ + $this->options['id'] = $this->getId() . '-' . $type . '-' . $i; + + echo \yii\bootstrap\Alert::widget([ + 'body' => $message, + 'closeButton' => $this->closeButton, + 'options' => $this->options, + ]); + } + + $session->removeFlash($type); + } + } + } +} diff --git a/composer.json b/composer.json new file mode 100755 index 0000000..671cdf5 --- /dev/null +++ b/composer.json @@ -0,0 +1,44 @@ +{ + "name": "yiisoft/yii2-app-advanced", + "description": "Yii 2 Advanced Project Template", + "keywords": ["yii2", "framework", "advanced", "project template"], + "homepage": "http://www.yiiframework.com/", + "type": "project", + "license": "BSD-3-Clause", + "support": { + "issues": "https://github.com/yiisoft/yii2/issues?state=open", + "forum": "http://www.yiiframework.com/forum/", + "wiki": "http://www.yiiframework.com/wiki/", + "irc": "irc://irc.freenode.net/yii", + "source": "https://github.com/yiisoft/yii2" + }, + "minimum-stability": "stable", + "require": { + "php": ">=5.4.0", + "yiisoft/yii2": "~2.0.6", + "yiisoft/yii2-bootstrap": "~2.0.0", + "yiisoft/yii2-swiftmailer": "~2.0.0", + "facebook/webdriver": "~1.0", + "codemix/yii2-localeurls": "^1.4" + }, + "require-dev": { + "yiisoft/yii2-debug": "~2.0.0", + "yiisoft/yii2-gii": "~2.0.0", + "yiisoft/yii2-faker": "~2.0.0", + + "codeception/base": "^2.2.3", + "codeception/verify": "~0.3.1" + }, + "config": { + "process-timeout": 1800 + }, + "extra": { + "asset-installer-paths": { + "npm-asset-library": "vendor/npm", + "bower-asset-library": "vendor/bower" + } + }, + "scripts": { + "post-install-cmd": "php init --env=Development --overwrite=n" + } +} diff --git a/composer.lock b/composer.lock new file mode 100755 index 0000000..f0fe768 --- /dev/null +++ b/composer.lock @@ -0,0 +1,3138 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "b8e446f48301bac06b4039ac394db092", + "content-hash": "d33d3619c3997f2e7ca8391a70e23551", + "packages": [ + { + "name": "bower-asset/bootstrap", + "version": "v3.3.7", + "source": { + "type": "git", + "url": "https://github.com/twbs/bootstrap.git", + "reference": "0b9c4a4007c44201dce9a6cc1a38407005c26c86" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twbs/bootstrap/zipball/0b9c4a4007c44201dce9a6cc1a38407005c26c86", + "reference": "0b9c4a4007c44201dce9a6cc1a38407005c26c86", + "shasum": "" + }, + "require": { + "bower-asset/jquery": ">=1.9.1,<4.0" + }, + "type": "bower-asset-library", + "extra": { + "bower-asset-main": [ + "less/bootstrap.less", + "dist/js/bootstrap.js" + ], + "bower-asset-ignore": [ + "/.*", + "_config.yml", + "CNAME", + "composer.json", + "CONTRIBUTING.md", + "docs", + "js/tests", + "test-infra" + ] + }, + "license": [ + "MIT" + ], + "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", + "keywords": [ + "css", + "framework", + "front-end", + "js", + "less", + "mobile-first", + "responsive", + "web" + ] + }, + { + "name": "bower-asset/jquery", + "version": "2.2.4", + "source": { + "type": "git", + "url": "https://github.com/jquery/jquery-dist.git", + "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/c0185ab7c75aab88762c5aae780b9d83b80eda72", + "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72", + "shasum": "" + }, + "type": "bower-asset-library", + "extra": { + "bower-asset-main": "dist/jquery.js", + "bower-asset-ignore": [ + "package.json" + ] + }, + "license": [ + "MIT" + ], + "keywords": [ + "browser", + "javascript", + "jquery", + "library" + ] + }, + { + "name": "bower-asset/jquery.inputmask", + "version": "3.3.4", + "source": { + "type": "git", + "url": "https://github.com/RobinHerbots/Inputmask.git", + "reference": "8a882bc471ba4077c4f8ecbe3d9d61c7558f3ef2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/RobinHerbots/Inputmask/zipball/8a882bc471ba4077c4f8ecbe3d9d61c7558f3ef2", + "reference": "8a882bc471ba4077c4f8ecbe3d9d61c7558f3ef2", + "shasum": "" + }, + "require": { + "bower-asset/jquery": ">=1.7" + }, + "type": "bower-asset-library", + "extra": { + "bower-asset-main": [ + "./dist/inputmask/inputmask.dependencyLib", + "./dist/inputmask/inputmask", + "./dist/inputmask/inputmask.extensions", + "./dist/inputmask/inputmask.date.extensions", + "./dist/inputmask/inputmask.numeric.extensions", + "./dist/inputmask/inputmask.phone.extensions", + "./dist/inputmask/inputmask.regex.extensions", + "./dist/inputmask/jquery.inputmask" + ], + "bower-asset-ignore": [ + "**/*", + "!dist/*", + "!dist/inputmask/*", + "!dist/min/*", + "!dist/min/inputmask/*", + "!extra/bindings/*", + "!extra/dependencyLibs/*", + "!extra/phone-codes/*" + ] + }, + "license": [ + "http://opensource.org/licenses/mit-license.php" + ], + "description": "jquery.inputmask is a jquery plugin which create an input mask.", + "keywords": [ + "form", + "input", + "inputmask", + "jquery", + "mask", + "plugins" + ] + }, + { + "name": "bower-asset/punycode", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/bestiejs/punycode.js.git", + "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bestiejs/punycode.js/zipball/38c8d3131a82567bfef18da09f7f4db68c84f8a3", + "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3", + "shasum": "" + }, + "type": "bower-asset-library", + "extra": { + "bower-asset-main": "punycode.js", + "bower-asset-ignore": [ + "coverage", + "tests", + ".*", + "component.json", + "Gruntfile.js", + "node_modules", + "package.json" + ] + } + }, + { + "name": "bower-asset/yii2-pjax", + "version": "v2.0.6", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/jquery-pjax.git", + "reference": "60728da6ade5879e807a49ce59ef9a72039b8978" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/60728da6ade5879e807a49ce59ef9a72039b8978", + "reference": "60728da6ade5879e807a49ce59ef9a72039b8978", + "shasum": "" + }, + "require": { + "bower-asset/jquery": ">=1.8" + }, + "type": "bower-asset-library", + "extra": { + "bower-asset-main": "./jquery.pjax.js", + "bower-asset-ignore": [ + ".travis.yml", + "Gemfile", + "Gemfile.lock", + "CONTRIBUTING.md", + "vendor/", + "script/", + "test/" + ] + }, + "license": [ + "MIT" + ] + }, + { + "name": "cebe/markdown", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/cebe/markdown.git", + "reference": "c30eb5e01fe021cc5bba2f9ee0eeef96d4931166" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cebe/markdown/zipball/c30eb5e01fe021cc5bba2f9ee0eeef96d4931166", + "reference": "c30eb5e01fe021cc5bba2f9ee0eeef96d4931166", + "shasum": "" + }, + "require": { + "lib-pcre": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "cebe/indent": "*", + "facebook/xhprof": "*@dev", + "phpunit/phpunit": "4.1.*" + }, + "bin": [ + "bin/markdown" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "cebe\\markdown\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Carsten Brandt", + "email": "mail@cebe.cc", + "homepage": "http://cebe.cc/", + "role": "Creator" + } + ], + "description": "A super fast, highly extensible markdown parser for PHP", + "homepage": "https://github.com/cebe/markdown#readme", + "keywords": [ + "extensible", + "fast", + "gfm", + "markdown", + "markdown-extra" + ], + "time": "2016-09-14 20:40:20" + }, + { + "name": "codemix/yii2-localeurls", + "version": "1.4.8", + "source": { + "type": "git", + "url": "https://github.com/codemix/yii2-localeurls.git", + "reference": "785769af625d69430a11ec167b56eef47f933baf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/codemix/yii2-localeurls/zipball/785769af625d69430a11ec167b56eef47f933baf", + "reference": "785769af625d69430a11ec167b56eef47f933baf", + "shasum": "" + }, + "require": { + "yiisoft/yii2": "*" + }, + "type": "yii2-extension", + "autoload": { + "psr-4": { + "codemix\\localeurls\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Härtl", + "email": "haertl.mike@gmail.com" + } + ], + "description": "Automatic locale/language management for URLs.", + "keywords": [ + "i18n", + "locale", + "yii2" + ], + "time": "2017-02-24 10:38:34" + }, + { + "name": "ezyang/htmlpurifier", + "version": "v4.8.0", + "source": { + "type": "git", + "url": "https://github.com/ezyang/htmlpurifier.git", + "reference": "d0c392f77d2f2a3dcf7fcb79e2a1e2b8804e75b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d0c392f77d2f2a3dcf7fcb79e2a1e2b8804e75b2", + "reference": "d0c392f77d2f2a3dcf7fcb79e2a1e2b8804e75b2", + "shasum": "" + }, + "require": { + "php": ">=5.2" + }, + "type": "library", + "autoload": { + "psr-0": { + "HTMLPurifier": "library/" + }, + "files": [ + "library/HTMLPurifier.composer.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL" + ], + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "description": "Standards compliant HTML filter written in PHP", + "homepage": "http://htmlpurifier.org/", + "keywords": [ + "html" + ], + "time": "2016-07-16 12:58:58" + }, + { + "name": "facebook/webdriver", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/facebook/php-webdriver.git", + "reference": "77300c4ab2025d4316635f592ec849ca7323bd8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/77300c4ab2025d4316635f592ec849ca7323bd8c", + "reference": "77300c4ab2025d4316635f592ec849ca7323bd8c", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": "^5.5 || ~7.0", + "symfony/process": "^2.8 || ^3.1" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^1.11", + "php-mock/php-mock-phpunit": "^1.1", + "phpunit/phpunit": "4.6.* || ~5.0", + "satooshi/php-coveralls": "^1.0", + "squizlabs/php_codesniffer": "^2.6" + }, + "suggest": { + "phpdocumentor/phpdocumentor": "2.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "Facebook\\WebDriver\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "A PHP client for WebDriver", + "homepage": "https://github.com/facebook/php-webdriver", + "keywords": [ + "facebook", + "php", + "selenium", + "webdriver" + ], + "time": "2017-01-13 15:48:08" + }, + { + "name": "swiftmailer/swiftmailer", + "version": "v5.4.6", + "source": { + "type": "git", + "url": "https://github.com/swiftmailer/swiftmailer.git", + "reference": "81fdccfaf8bdc5d5d7a1ef6bb3a61bbb1a6c4a3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/81fdccfaf8bdc5d5d7a1ef6bb3a61bbb1a6c4a3e", + "reference": "81fdccfaf8bdc5d5d7a1ef6bb3a61bbb1a6c4a3e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "mockery/mockery": "~0.9.1", + "symfony/phpunit-bridge": "~3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.4-dev" + } + }, + "autoload": { + "files": [ + "lib/swift_required.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Corbyn" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Swiftmailer, free feature-rich PHP mailer", + "homepage": "http://swiftmailer.org", + "keywords": [ + "email", + "mail", + "mailer" + ], + "time": "2017-02-13 07:52:53" + }, + { + "name": "symfony/process", + "version": "v3.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "0ab87c1e7570b3534a6e51eb4ca8e9f6d7327856" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/0ab87c1e7570b3534a6e51eb4ca8e9f6d7327856", + "reference": "0ab87c1e7570b3534a6e51eb4ca8e9f6d7327856", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2017-02-16 14:07:22" + }, + { + "name": "yiisoft/yii2", + "version": "2.0.11.2", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii2-framework.git", + "reference": "ee996adec1dfd7babb67bd0c604f5bd6425fe5ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/ee996adec1dfd7babb67bd0c604f5bd6425fe5ab", + "reference": "ee996adec1dfd7babb67bd0c604f5bd6425fe5ab", + "shasum": "" + }, + "require": { + "bower-asset/jquery": "2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", + "bower-asset/jquery.inputmask": "~3.2.2 | ~3.3.3", + "bower-asset/punycode": "1.3.*", + "bower-asset/yii2-pjax": "~2.0.1", + "cebe/markdown": "~1.0.0 | ~1.1.0", + "ext-ctype": "*", + "ext-mbstring": "*", + "ezyang/htmlpurifier": "~4.6", + "lib-pcre": "*", + "php": ">=5.4.0", + "yiisoft/yii2-composer": "~2.0.4" + }, + "bin": [ + "yii" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "yii\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Qiang Xue", + "email": "qiang.xue@gmail.com", + "homepage": "http://www.yiiframework.com/", + "role": "Founder and project lead" + }, + { + "name": "Alexander Makarov", + "email": "sam@rmcreative.ru", + "homepage": "http://rmcreative.ru/", + "role": "Core framework development" + }, + { + "name": "Maurizio Domba", + "homepage": "http://mdomba.info/", + "role": "Core framework development" + }, + { + "name": "Carsten Brandt", + "email": "mail@cebe.cc", + "homepage": "http://cebe.cc/", + "role": "Core framework development" + }, + { + "name": "Timur Ruziev", + "email": "resurtm@gmail.com", + "homepage": "http://resurtm.com/", + "role": "Core framework development" + }, + { + "name": "Paul Klimov", + "email": "klimov.paul@gmail.com", + "role": "Core framework development" + }, + { + "name": "Dmitry Naumenko", + "email": "d.naumenko.a@gmail.com", + "role": "Core framework development" + }, + { + "name": "Boudewijn Vahrmeijer", + "email": "info@dynasource.eu", + "homepage": "http://dynasource.eu", + "role": "Core framework development" + } + ], + "description": "Yii PHP Framework Version 2", + "homepage": "http://www.yiiframework.com/", + "keywords": [ + "framework", + "yii2" + ], + "time": "2017-02-08 09:04:32" + }, + { + "name": "yiisoft/yii2-bootstrap", + "version": "2.0.6", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii2-bootstrap.git", + "reference": "3fd2b8c950cce79d60e9702d6bcb24eb3c80f6c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii2-bootstrap/zipball/3fd2b8c950cce79d60e9702d6bcb24eb3c80f6c5", + "reference": "3fd2b8c950cce79d60e9702d6bcb24eb3c80f6c5", + "shasum": "" + }, + "require": { + "bower-asset/bootstrap": "3.3.* | 3.2.* | 3.1.*", + "yiisoft/yii2": ">=2.0.6" + }, + "type": "yii2-extension", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + }, + "asset-installer-paths": { + "npm-asset-library": "vendor/npm", + "bower-asset-library": "vendor/bower" + } + }, + "autoload": { + "psr-4": { + "yii\\bootstrap\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Qiang Xue", + "email": "qiang.xue@gmail.com" + } + ], + "description": "The Twitter Bootstrap extension for the Yii framework", + "keywords": [ + "bootstrap", + "yii2" + ], + "time": "2016-03-17 03:29:28" + }, + { + "name": "yiisoft/yii2-composer", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii2-composer.git", + "reference": "3f4923c2bde6caf3f5b88cc22fdd5770f52f8df2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/3f4923c2bde6caf3f5b88cc22fdd5770f52f8df2", + "reference": "3f4923c2bde6caf3f5b88cc22fdd5770f52f8df2", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0" + }, + "require-dev": { + "composer/composer": "^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "yii\\composer\\Plugin", + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "yii\\composer\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Qiang Xue", + "email": "qiang.xue@gmail.com" + } + ], + "description": "The composer plugin for Yii extension installer", + "keywords": [ + "composer", + "extension installer", + "yii2" + ], + "time": "2016-12-20 13:26:02" + }, + { + "name": "yiisoft/yii2-swiftmailer", + "version": "2.0.6", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii2-swiftmailer.git", + "reference": "26b900767f1031ff3a4668dfa36c10595875f0a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii2-swiftmailer/zipball/26b900767f1031ff3a4668dfa36c10595875f0a5", + "reference": "26b900767f1031ff3a4668dfa36c10595875f0a5", + "shasum": "" + }, + "require": { + "swiftmailer/swiftmailer": "~5.0", + "yiisoft/yii2": "~2.0.4" + }, + "type": "yii2-extension", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "yii\\swiftmailer\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Paul Klimov", + "email": "klimov.paul@gmail.com" + } + ], + "description": "The SwiftMailer integration for the Yii framework", + "keywords": [ + "email", + "mail", + "mailer", + "swift", + "swiftmailer", + "yii2" + ], + "time": "2016-09-09 11:48:11" + } + ], + "packages-dev": [ + { + "name": "behat/gherkin", + "version": "v4.4.5", + "source": { + "type": "git", + "url": "https://github.com/Behat/Gherkin.git", + "reference": "5c14cff4f955b17d20d088dec1bde61c0539ec74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/5c14cff4f955b17d20d088dec1bde61c0539ec74", + "reference": "5c14cff4f955b17d20d088dec1bde61c0539ec74", + "shasum": "" + }, + "require": { + "php": ">=5.3.1" + }, + "require-dev": { + "phpunit/phpunit": "~4.5|~5", + "symfony/phpunit-bridge": "~2.7|~3", + "symfony/yaml": "~2.3|~3" + }, + "suggest": { + "symfony/yaml": "If you want to parse features, represented in YAML files" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.4-dev" + } + }, + "autoload": { + "psr-0": { + "Behat\\Gherkin": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Gherkin DSL parser for PHP 5.3", + "homepage": "http://behat.org/", + "keywords": [ + "BDD", + "Behat", + "Cucumber", + "DSL", + "gherkin", + "parser" + ], + "time": "2016-10-30 11:50:56" + }, + { + "name": "bower-asset/typeahead.js", + "version": "v0.11.1", + "source": { + "type": "git", + "url": "https://github.com/twitter/typeahead.js.git", + "reference": "588440f66559714280628a4f9799f0c4eb880a4a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twitter/typeahead.js/zipball/588440f66559714280628a4f9799f0c4eb880a4a", + "reference": "588440f66559714280628a4f9799f0c4eb880a4a", + "shasum": "" + }, + "require": { + "bower-asset/jquery": ">=1.7" + }, + "require-dev": { + "bower-asset/jasmine-ajax": "~1.3.1", + "bower-asset/jasmine-jquery": "~1.5.2", + "bower-asset/jquery": "~1.7" + }, + "type": "bower-asset-library", + "extra": { + "bower-asset-main": "dist/typeahead.bundle.js" + } + }, + { + "name": "codeception/base", + "version": "2.2.9", + "source": { + "type": "git", + "url": "https://github.com/Codeception/base.git", + "reference": "8d5f54ce583ceaa9627c2441e20bbd4873de50cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/base/zipball/8d5f54ce583ceaa9627c2441e20bbd4873de50cc", + "reference": "8d5f54ce583ceaa9627c2441e20bbd4873de50cc", + "shasum": "" + }, + "require": { + "behat/gherkin": "~4.4.0", + "ext-json": "*", + "ext-mbstring": "*", + "guzzlehttp/psr7": "~1.0", + "php": ">=5.4.0 <8.0", + "phpunit/php-code-coverage": ">=2.2.4 <5.0", + "phpunit/phpunit": ">4.8.20 <6.0", + "sebastian/comparator": "~1.1", + "sebastian/diff": "^1.4", + "symfony/browser-kit": ">=2.7 <4.0", + "symfony/console": ">=2.7 <4.0", + "symfony/css-selector": ">=2.7 <4.0", + "symfony/dom-crawler": ">=2.7.5 <4.0", + "symfony/event-dispatcher": ">=2.7 <4.0", + "symfony/finder": ">=2.7 <4.0", + "symfony/yaml": ">=2.7 <4.0" + }, + "require-dev": { + "codeception/specify": "~0.3", + "facebook/graph-sdk": "~5.3", + "flow/jsonpath": "~0.2", + "league/factory-muffin": "^3.0", + "league/factory-muffin-faker": "^1.0", + "mongodb/mongodb": "^1.0", + "monolog/monolog": "~1.8", + "pda/pheanstalk": "~3.0", + "php-amqplib/php-amqplib": "~2.4", + "predis/predis": "^1.0", + "squizlabs/php_codesniffer": "~2.0", + "vlucas/phpdotenv": "^2.4.0" + }, + "suggest": { + "codeception/specify": "BDD-style code blocks", + "codeception/verify": "BDD-style assertions", + "flow/jsonpath": "For using JSONPath in REST module", + "league/factory-muffin": "For DataFactory module", + "league/factory-muffin-faker": "For Faker support in DataFactory module", + "phpseclib/phpseclib": "for SFTP option in FTP Module", + "symfony/phpunit-bridge": "For phpunit-bridge support" + }, + "bin": [ + "codecept" + ], + "type": "library", + "extra": { + "branch-alias": [] + }, + "autoload": { + "psr-4": { + "Codeception\\": "src\\Codeception", + "Codeception\\Extension\\": "ext" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert@mail.ua", + "homepage": "http://codegyre.com" + } + ], + "description": "BDD-style testing framework", + "homepage": "http://codeception.com/", + "keywords": [ + "BDD", + "TDD", + "acceptance testing", + "functional testing", + "unit testing" + ], + "time": "2017-02-04 02:16:42" + }, + { + "name": "codeception/verify", + "version": "0.3.3", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Verify.git", + "reference": "5d649dda453cd814dadc4bb053060cd2c6bb4b4c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Verify/zipball/5d649dda453cd814dadc4bb053060cd2c6bb4b4c", + "reference": "5d649dda453cd814dadc4bb053060cd2c6bb4b4c", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/Codeception/function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert.php@mailican.com" + } + ], + "description": "BDD assertion library for PHPUnit", + "time": "2017-01-09 10:58:51" + }, + { + "name": "doctrine/instantiator", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14 21:17:01" + }, + { + "name": "fzaninotto/faker", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/fzaninotto/Faker.git", + "reference": "44f9a286a04b80c76a4e5fb7aad8bb539b920123" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/44f9a286a04b80c76a4e5fb7aad8bb539b920123", + "reference": "44f9a286a04b80c76a4e5fb7aad8bb539b920123", + "shasum": "" + }, + "require": { + "php": "^5.3.3|^7.0" + }, + "require-dev": { + "ext-intl": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5" + }, + "type": "library", + "extra": { + "branch-alias": [] + }, + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "time": "2016-04-29 12:21:54" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "0d6c7ca039329247e4f0f8f8f6506810e8248855" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/0d6c7ca039329247e4f0f8f8f6506810e8248855", + "reference": "0d6c7ca039329247e4f0f8f8f6506810e8248855", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2017-02-27 10:51:17" + }, + { + "name": "myclabs/deep-copy", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5a5a9fc8025a08d8919be87d6884d5a92520cefe", + "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "doctrine/collections": "1.*", + "phpunit/phpunit": "~4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "homepage": "https://github.com/myclabs/DeepCopy", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2017-01-26 22:05:40" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2015-12-27 11:43:31" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/type-resolver": "^0.2.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2016-09-30 07:12:33" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.2.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2016-11-25 06:54:22" + }, + { + "name": "phpspec/php-diff", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/php-diff.git", + "reference": "0464787bfa7cd13576c5a1e318709768798bec6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/php-diff/zipball/0464787bfa7cd13576c5a1e318709768798bec6a", + "reference": "0464787bfa7cd13576c5a1e318709768798bec6a", + "shasum": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Diff": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Chris Boulton", + "homepage": "http://github.com/chrisboulton" + } + ], + "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", + "time": "2016-04-07 12:29:16" + }, + { + "name": "phpspec/prophecy", + "version": "v1.7.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1|^2.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8 || ^5.6.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2017-03-02 20:05:34" + }, + { + "name": "phpunit/php-code-coverage", + "version": "4.0.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "09e2277d14ea467e5a984010f501343ef29ffc69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/09e2277d14ea467e5a984010f501343ef29ffc69", + "reference": "09e2277d14ea467e5a984010f501343ef29ffc69", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^5.6 || ^7.0", + "phpunit/php-file-iterator": "^1.3", + "phpunit/php-text-template": "^1.2", + "phpunit/php-token-stream": "^1.4.2 || ^2.0", + "sebastian/code-unit-reverse-lookup": "^1.0", + "sebastian/environment": "^1.3.2 || ^2.0", + "sebastian/version": "^1.0 || ^2.0" + }, + "require-dev": { + "ext-xdebug": "^2.1.4", + "phpunit/phpunit": "^5.7" + }, + "suggest": { + "ext-xdebug": "^2.5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2017-03-01 09:12:17" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2016-10-03 07:40:28" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21 13:50:34" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2017-02-26 11:10:40" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.4.11", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2017-02-27 10:12:30" + }, + { + "name": "phpunit/phpunit", + "version": "5.7.15", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "b99112aecc01f62acf3d81a3f59646700a1849e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b99112aecc01f62acf3d81a3f59646700a1849e5", + "reference": "b99112aecc01f62acf3d81a3f59646700a1849e5", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "~1.3", + "php": "^5.6 || ^7.0", + "phpspec/prophecy": "^1.6.2", + "phpunit/php-code-coverage": "^4.0.4", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "^3.2", + "sebastian/comparator": "^1.2.4", + "sebastian/diff": "~1.2", + "sebastian/environment": "^1.3.4 || ^2.0", + "sebastian/exporter": "~2.0", + "sebastian/global-state": "^1.1", + "sebastian/object-enumerator": "~2.0", + "sebastian/resource-operations": "~1.0", + "sebastian/version": "~1.0.3|~2.0", + "symfony/yaml": "~2.1|~3.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-xdebug": "*", + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.7.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2017-03-02 15:22:43" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "3.4.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.6 || ^7.0", + "phpunit/php-text-template": "^1.2", + "sebastian/exporter": "^1.2 || ^2.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2016-12-08 20:27:08" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06 14:39:51" + }, + { + "name": "psr/log", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-10-10 12:19:37" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2017-03-04 06:30:41" + }, + { + "name": "sebastian/comparator", + "version": "1.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2 || ~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2017-01-29 09:50:25" + }, + { + "name": "sebastian/diff", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-12-08 07:14:41" + }, + { + "name": "sebastian/environment", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2016-11-26 07:53:53" + }, + { + "name": "sebastian/exporter", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~2.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2016-11-19 08:54:04" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12 03:26:01" + }, + { + "name": "sebastian/object-enumerator", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "sebastian/recursion-context": "~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-02-18 15:18:39" + }, + { + "name": "sebastian/recursion-context", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2016-11-19 07:33:16" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28 20:34:47" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-10-03 07:35:21" + }, + { + "name": "symfony/browser-kit", + "version": "v3.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "394a2475a3a89089353fde5714a7f402fbb83880" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/394a2475a3a89089353fde5714a7f402fbb83880", + "reference": "394a2475a3a89089353fde5714a7f402fbb83880", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/dom-crawler": "~2.8|~3.0" + }, + "require-dev": { + "symfony/css-selector": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0" + }, + "suggest": { + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony BrowserKit Component", + "homepage": "https://symfony.com", + "time": "2017-01-31 21:49:23" + }, + { + "name": "symfony/console", + "version": "v3.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "0e5e6899f82230fcb1153bcaf0e106ffaa44b870" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/0e5e6899f82230fcb1153bcaf0e106ffaa44b870", + "reference": "0e5e6899f82230fcb1153bcaf0e106ffaa44b870", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/debug": "~2.8|~3.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.8|~3.0", + "symfony/filesystem": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/filesystem": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2017-02-16 14:07:22" + }, + { + "name": "symfony/css-selector", + "version": "v3.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "f0e628f04fc055c934b3211cfabdb1c59eefbfaa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/f0e628f04fc055c934b3211cfabdb1c59eefbfaa", + "reference": "f0e628f04fc055c934b3211cfabdb1c59eefbfaa", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony CssSelector Component", + "homepage": "https://symfony.com", + "time": "2017-01-02 20:32:22" + }, + { + "name": "symfony/debug", + "version": "v3.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "9b98854cb45bc59d100b7d4cc4cf9e05f21026b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/9b98854cb45bc59d100b7d4cc4cf9e05f21026b9", + "reference": "9b98854cb45bc59d100b7d4cc4cf9e05f21026b9", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/class-loader": "~2.8|~3.0", + "symfony/http-kernel": "~2.8|~3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2017-02-16 16:34:18" + }, + { + "name": "symfony/dom-crawler", + "version": "v3.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "b814b41373fc4e535aff8c765abe39545216f391" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b814b41373fc4e535aff8c765abe39545216f391", + "reference": "b814b41373fc4e535aff8c765abe39545216f391", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "~2.8|~3.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DomCrawler Component", + "homepage": "https://symfony.com", + "time": "2017-01-21 17:14:11" + }, + { + "name": "symfony/event-dispatcher", + "version": "v3.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "9137eb3a3328e413212826d63eeeb0217836e2b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9137eb3a3328e413212826d63eeeb0217836e2b6", + "reference": "9137eb3a3328e413212826d63eeeb0217836e2b6", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0", + "symfony/dependency-injection": "~2.8|~3.0", + "symfony/expression-language": "~2.8|~3.0", + "symfony/stopwatch": "~2.8|~3.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2017-01-02 20:32:22" + }, + { + "name": "symfony/finder", + "version": "v3.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "8c71141cae8e2957946b403cc71a67213c0380d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/8c71141cae8e2957946b403cc71a67213c0380d6", + "reference": "8c71141cae8e2957946b403cc71a67213c0380d6", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2017-01-02 20:32:22" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2016-11-14 01:06:16" + }, + { + "name": "symfony/yaml", + "version": "v3.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "9724c684646fcb5387d579b4bfaa63ee0b0c64c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/9724c684646fcb5387d579b4bfaa63ee0b0c64c8", + "reference": "9724c684646fcb5387d579b4bfaa63ee0b0c64c8", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "symfony/console": "~2.8|~3.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2017-02-16 22:46:52" + }, + { + "name": "webmozart/assert", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2016-11-23 20:04:58" + }, + { + "name": "yiisoft/yii2-debug", + "version": "2.0.9", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii2-debug.git", + "reference": "647be6c9d48dc2f3c2e2f33b9eba0a4ca78abde9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii2-debug/zipball/647be6c9d48dc2f3c2e2f33b9eba0a4ca78abde9", + "reference": "647be6c9d48dc2f3c2e2f33b9eba0a4ca78abde9", + "shasum": "" + }, + "require": { + "yiisoft/yii2": "~2.0.11", + "yiisoft/yii2-bootstrap": "~2.0.0" + }, + "type": "yii2-extension", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "yii\\debug\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Qiang Xue", + "email": "qiang.xue@gmail.com" + } + ], + "description": "The debugger extension for the Yii framework", + "keywords": [ + "debug", + "debugger", + "yii2" + ], + "time": "2017-02-21 10:30:50" + }, + { + "name": "yiisoft/yii2-faker", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii2-faker.git", + "reference": "b88ca69ee226a3610b2c26c026c3203d7ac50f6c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii2-faker/zipball/b88ca69ee226a3610b2c26c026c3203d7ac50f6c", + "reference": "b88ca69ee226a3610b2c26c026c3203d7ac50f6c", + "shasum": "" + }, + "require": { + "fzaninotto/faker": "*", + "yiisoft/yii2": "*" + }, + "type": "yii2-extension", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "yii\\faker\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Mark Jebri", + "email": "mark.github@yandex.ru" + } + ], + "description": "Fixture generator. The Faker integration for the Yii framework.", + "keywords": [ + "Fixture", + "faker", + "yii2" + ], + "time": "2015-03-01 06:22:44" + }, + { + "name": "yiisoft/yii2-gii", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii2-gii.git", + "reference": "1bd6df6804ca077ec022587905a0d43eb286f507" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii2-gii/zipball/1bd6df6804ca077ec022587905a0d43eb286f507", + "reference": "1bd6df6804ca077ec022587905a0d43eb286f507", + "shasum": "" + }, + "require": { + "bower-asset/typeahead.js": "0.10.* | ~0.11.0", + "phpspec/php-diff": ">=1.0.2", + "yiisoft/yii2": ">=2.0.4", + "yiisoft/yii2-bootstrap": "~2.0" + }, + "type": "yii2-extension", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + }, + "asset-installer-paths": { + "npm-asset-library": "vendor/npm", + "bower-asset-library": "vendor/bower" + } + }, + "autoload": { + "psr-4": { + "yii\\gii\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Qiang Xue", + "email": "qiang.xue@gmail.com" + } + ], + "description": "The Gii extension for the Yii framework", + "keywords": [ + "code generator", + "gii", + "yii2" + ], + "time": "2016-03-18 14:09:46" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.4.0" + }, + "platform-dev": [] +} diff --git a/console/config/.gitignore b/console/config/.gitignore new file mode 100755 index 0000000..20da318 --- /dev/null +++ b/console/config/.gitignore @@ -0,0 +1,2 @@ +main-local.php +params-local.php \ No newline at end of file diff --git a/console/config/bootstrap.php b/console/config/bootstrap.php new file mode 100755 index 0000000..b3d9bbc --- /dev/null +++ b/console/config/bootstrap.php @@ -0,0 +1 @@ + 'app-console', + 'basePath' => dirname(__DIR__), + 'bootstrap' => ['log'], + 'controllerNamespace' => 'console\controllers', + 'controllerMap' => [ + 'fixture' => [ + 'class' => 'yii\console\controllers\FixtureController', + 'namespace' => 'common\fixtures', + ], + ], + 'components' => [ + 'log' => [ + 'targets' => [ + [ + 'class' => 'yii\log\FileTarget', + 'levels' => ['error', 'warning'], + ], + ], + ], + ], + 'params' => $params, +]; diff --git a/console/config/params.php b/console/config/params.php new file mode 100755 index 0000000..7f754b9 --- /dev/null +++ b/console/config/params.php @@ -0,0 +1,4 @@ + 'admin@example.com', +]; diff --git a/console/controllers/.gitkeep b/console/controllers/.gitkeep new file mode 100755 index 0000000..e69de29 diff --git a/console/migrations/m130524_201442_init.php b/console/migrations/m130524_201442_init.php new file mode 100755 index 0000000..6b649f4 --- /dev/null +++ b/console/migrations/m130524_201442_init.php @@ -0,0 +1,33 @@ +db->driverName === 'mysql') { + // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci + $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; + } + + $this->createTable('{{%user}}', [ + 'id' => $this->primaryKey(), + 'username' => $this->string()->notNull()->unique(), + 'auth_key' => $this->string(32)->notNull(), + 'password_hash' => $this->string()->notNull(), + 'password_reset_token' => $this->string()->unique(), + 'email' => $this->string()->notNull()->unique(), + + 'status' => $this->smallInteger()->notNull()->defaultValue(10), + 'created_at' => $this->integer()->notNull(), + 'updated_at' => $this->integer()->notNull(), + ], $tableOptions); + } + + public function down() + { + $this->dropTable('{{%user}}'); + } +} diff --git a/console/migrations/m170225_203605_add_win_column_to_user_table.php b/console/migrations/m170225_203605_add_win_column_to_user_table.php new file mode 100755 index 0000000..0c44f98 --- /dev/null +++ b/console/migrations/m170225_203605_add_win_column_to_user_table.php @@ -0,0 +1,25 @@ +addColumn('user', 'win', $this->integer(5)->notNull()); + } + + /** + * @inheritdoc + */ + public function down() + { + $this->dropColumn('user', 'win'); + } +} diff --git a/console/migrations/m170225_203634_add_lose_column_to_user_table.php b/console/migrations/m170225_203634_add_lose_column_to_user_table.php new file mode 100755 index 0000000..1f36ec1 --- /dev/null +++ b/console/migrations/m170225_203634_add_lose_column_to_user_table.php @@ -0,0 +1,25 @@ +addColumn('user', 'lose', $this->integer(5)->notNull()); + } + + /** + * @inheritdoc + */ + public function down() + { + $this->dropColumn('user', 'lose'); + } +} diff --git a/console/migrations/m170225_203656_add_draw_column_to_user_table.php b/console/migrations/m170225_203656_add_draw_column_to_user_table.php new file mode 100755 index 0000000..61dbfbf --- /dev/null +++ b/console/migrations/m170225_203656_add_draw_column_to_user_table.php @@ -0,0 +1,25 @@ +addColumn('user', 'draw', $this->integer(5)->notNull()); + } + + /** + * @inheritdoc + */ + public function down() + { + $this->dropColumn('user', 'draw'); + } +} diff --git a/console/migrations/m170225_204626_add_credits_column_to_user_table.php b/console/migrations/m170225_204626_add_credits_column_to_user_table.php new file mode 100755 index 0000000..c863b08 --- /dev/null +++ b/console/migrations/m170225_204626_add_credits_column_to_user_table.php @@ -0,0 +1,25 @@ +addColumn('user', 'credits', $this->integer(5)->notNull()); + } + + /** + * @inheritdoc + */ + public function down() + { + $this->dropColumn('user', 'credits'); + } +} diff --git a/console/migrations/m170317_132201_create_ship_table.php b/console/migrations/m170317_132201_create_ship_table.php new file mode 100755 index 0000000..803aa52 --- /dev/null +++ b/console/migrations/m170317_132201_create_ship_table.php @@ -0,0 +1,34 @@ +createTable('ship', [ + 'id' => $this->primaryKey(), + 'name' => $this->string(255)->notNull(), + 'lvl' => $this->integer(5)->notNull(), + 'stock_gun' => $this->integer(1)->notNull(), + 'stock_tower' => $this->integer(1)->notNull(), + 'mod_gun' => $this->integer(1)->notNull(), + 'mod_tower' => $this->integer(1)->notNull(), + 'strength' => $this->integer(10)->notNull(), + ]); + } + + /** + * @inheritdoc + */ + public function down() + { + $this->dropTable('ship'); + } +} diff --git a/console/migrations/m170317_132341_create_port_table.php b/console/migrations/m170317_132341_create_port_table.php new file mode 100755 index 0000000..81f3cba --- /dev/null +++ b/console/migrations/m170317_132341_create_port_table.php @@ -0,0 +1,97 @@ +createTable('port', [ + 'id' => $this->primaryKey(), + 'user_id' => $this->integer(10)->notNull(), + 'ship_id' => $this->integer(5)->notNull(), + 'exp' => $this->integer(5)->notNull(), + 'stock_gun' => $this->integer(1)->notNull(), + 'stock_tower' => $this->integer(1)->notNull(), + 'mod_gun' => $this->integer(1)->notNull(), + 'mod_tower' => $this->integer(1)->notNull(), + 'strength' => $this->integer(10)->notNull(), + ]); + + // creates index for column `user_id` + $this->createIndex( + 'idx-port-user_id', + 'port', + 'user_id' + ); + + // add foreign key for table `user` + $this->addForeignKey( + 'fk-port-user_id', + 'port', + 'user_id', + 'user', + 'id', + 'CASCADE' + ); + + // creates index for column `ship_id` + $this->createIndex( + 'idx-port-ship_id', + 'port', + 'ship_id' + ); + + // add foreign key for table `ship` + $this->addForeignKey( + 'fk-port-ship_id', + 'port', + 'ship_id', + 'ship', + 'id', + 'CASCADE' + ); + } + + /** + * @inheritdoc + */ + public function down() + { + // drops foreign key for table `user` + $this->dropForeignKey( + 'fk-port-user_id', + 'port' + ); + + // drops index for column `user_id` + $this->dropIndex( + 'idx-port-user_id', + 'port' + ); + + // drops foreign key for table `ship` + $this->dropForeignKey( + 'fk-port-ship_id', + 'port' + ); + + // drops index for column `ship_id` + $this->dropIndex( + 'idx-port-ship_id', + 'port' + ); + + $this->dropTable('port'); + } +} diff --git a/console/migrations/m170317_141028_add_type_column_to_ship_table.php b/console/migrations/m170317_141028_add_type_column_to_ship_table.php new file mode 100755 index 0000000..1519191 --- /dev/null +++ b/console/migrations/m170317_141028_add_type_column_to_ship_table.php @@ -0,0 +1,25 @@ +addColumn('ship', 'type', $this->integer(2)->notNull()); + } + + /** + * @inheritdoc + */ + public function down() + { + $this->dropColumn('ship', 'type'); + } +} diff --git a/console/migrations/m170317_141121_add_type_column_to_port_table.php b/console/migrations/m170317_141121_add_type_column_to_port_table.php new file mode 100755 index 0000000..eb739e5 --- /dev/null +++ b/console/migrations/m170317_141121_add_type_column_to_port_table.php @@ -0,0 +1,25 @@ +addColumn('port', 'type', $this->integer(2)->notNull()); + } + + /** + * @inheritdoc + */ + public function down() + { + $this->dropColumn('port', 'type'); + } +} diff --git a/console/migrations/m170321_105310_create_mods_table.php b/console/migrations/m170321_105310_create_mods_table.php new file mode 100644 index 0000000..b4c76a9 --- /dev/null +++ b/console/migrations/m170321_105310_create_mods_table.php @@ -0,0 +1,62 @@ +createTable('mods', [ + 'id' => $this->primaryKey(), + 'ship_id' => $this->integer(5)->notNull(), + 'mod_gun' => $this->integer(1), + 'mod_tower' => $this->integer(1), + ]); + + // creates index for column `ship_id` + $this->createIndex( + 'idx-mods-ship_id', + 'mods', + 'ship_id' + ); + + // add foreign key for table `ship` + $this->addForeignKey( + 'fk-mods-ship_id', + 'mods', + 'ship_id', + 'ship', + 'id', + 'CASCADE' + ); + } + + /** + * @inheritdoc + */ + public function down() + { + // drops foreign key for table `ship` + $this->dropForeignKey( + 'fk-mods-ship_id', + 'mods' + ); + + // drops index for column `ship_id` + $this->dropIndex( + 'idx-mods-ship_id', + 'mods' + ); + + $this->dropTable('mods'); + } +} diff --git a/console/migrations/m170321_122136_add_exp_gun_column_to_port_table.php b/console/migrations/m170321_122136_add_exp_gun_column_to_port_table.php new file mode 100644 index 0000000..c180f3e --- /dev/null +++ b/console/migrations/m170321_122136_add_exp_gun_column_to_port_table.php @@ -0,0 +1,25 @@ +addColumn('port', 'exp_gun', $this->integer(1)->notNull()); + } + + /** + * @inheritdoc + */ + public function down() + { + $this->dropColumn('port', 'exp_gun'); + } +} diff --git a/console/migrations/m170321_122225_add_exp_tower_column_to_port_table.php b/console/migrations/m170321_122225_add_exp_tower_column_to_port_table.php new file mode 100644 index 0000000..f73ffd3 --- /dev/null +++ b/console/migrations/m170321_122225_add_exp_tower_column_to_port_table.php @@ -0,0 +1,25 @@ +addColumn('port', 'exp_tower', $this->integer(1)->notNull()); + } + + /** + * @inheritdoc + */ + public function down() + { + $this->dropColumn('port', 'exp_tower'); + } +} diff --git a/console/migrations/m170321_135228_create_mods_table.php b/console/migrations/m170321_135228_create_mods_table.php new file mode 100644 index 0000000..2a147f5 --- /dev/null +++ b/console/migrations/m170321_135228_create_mods_table.php @@ -0,0 +1,66 @@ +createTable('mods', [ + 'id' => $this->primaryKey(), + 'ship_id' => $this->integer(5)->notNull(), + 'mod_gun' => $this->integer(1)->notNull(), + 'mod_tower' => $this->integer(1)->notNull(), + 'exp_gun' => $this->integer(5)->notNull(), + 'exp_tower' => $this->integer(5)->notNull(), + 'cost_gun' => $this->integer(5)->notNull(), + 'cost_tower' => $this->integer(5)->notNull(), + ]); + + // creates index for column `ship_id` + $this->createIndex( + 'idx-mods-ship_id', + 'mods', + 'ship_id' + ); + + // add foreign key for table `ship` + $this->addForeignKey( + 'fk-mods-ship_id', + 'mods', + 'ship_id', + 'ship', + 'id', + 'CASCADE' + ); + } + + /** + * @inheritdoc + */ + public function down() + { + // drops foreign key for table `ship` + $this->dropForeignKey( + 'fk-mods-ship_id', + 'mods' + ); + + // drops index for column `ship_id` + $this->dropIndex( + 'idx-mods-ship_id', + 'mods' + ); + + $this->dropTable('mods'); + } +} diff --git a/console/migrations/m170329_081414_add_battle_id_column_to_user_table.php b/console/migrations/m170329_081414_add_battle_id_column_to_user_table.php new file mode 100644 index 0000000..c3dbb8f --- /dev/null +++ b/console/migrations/m170329_081414_add_battle_id_column_to_user_table.php @@ -0,0 +1,25 @@ +addColumn('user', 'battle_id', $this->integer(10)->notNull()); + } + + /** + * @inheritdoc + */ + public function down() + { + $this->dropColumn('user', 'battle_id'); + } +} diff --git a/console/migrations/m170408_110257_create_battles_table.php b/console/migrations/m170408_110257_create_battles_table.php new file mode 100644 index 0000000..2d3bb48 --- /dev/null +++ b/console/migrations/m170408_110257_create_battles_table.php @@ -0,0 +1,64 @@ +createTable('battles', [ + 'id' => $this->primaryKey(), + 'logs' => $this->text(), + 'bid' => $this->integer(10)->notNull(), + 'creator_id' => $this->integer(10)->notNull(), + 'date' => $this->dateTime(), + 'status' => $this->integer(1)->notNull(), + ]); + + // creates index for column `creator_id` + $this->createIndex( + 'idx-battles-creator_id', + 'battles', + 'creator_id' + ); + + // add foreign key for table `user` + $this->addForeignKey( + 'fk-battles-creator_id', + 'battles', + 'creator_id', + 'user', + 'id', + 'CASCADE' + ); + } + + /** + * @inheritdoc + */ + public function down() + { + // drops foreign key for table `user` + $this->dropForeignKey( + 'fk-battles-creator_id', + 'battles' + ); + + // drops index for column `creator_id` + $this->dropIndex( + 'idx-battles-creator_id', + 'battles' + ); + + $this->dropTable('battles'); + } +} diff --git a/console/models/.gitkeep b/console/models/.gitkeep new file mode 100755 index 0000000..72e8ffc --- /dev/null +++ b/console/models/.gitkeep @@ -0,0 +1 @@ +* diff --git a/console/runtime/.gitignore b/console/runtime/.gitignore new file mode 100755 index 0000000..c96a04f --- /dev/null +++ b/console/runtime/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/environments/dev/backend/config/main-local.php b/environments/dev/backend/config/main-local.php new file mode 100755 index 0000000..d9a8ceb --- /dev/null +++ b/environments/dev/backend/config/main-local.php @@ -0,0 +1,25 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => '', + ], + ], +]; + +if (!YII_ENV_TEST) { + // configuration adjustments for 'dev' environment + $config['bootstrap'][] = 'debug'; + $config['modules']['debug'] = [ + 'class' => 'yii\debug\Module', + ]; + + $config['bootstrap'][] = 'gii'; + $config['modules']['gii'] = [ + 'class' => 'yii\gii\Module', + ]; +} + +return $config; diff --git a/environments/dev/backend/config/params-local.php b/environments/dev/backend/config/params-local.php new file mode 100755 index 0000000..d0b9c34 --- /dev/null +++ b/environments/dev/backend/config/params-local.php @@ -0,0 +1,3 @@ +run(); diff --git a/environments/dev/backend/web/index.php b/environments/dev/backend/web/index.php new file mode 100755 index 0000000..1d75140 --- /dev/null +++ b/environments/dev/backend/web/index.php @@ -0,0 +1,17 @@ +run(); diff --git a/environments/dev/common/config/main-local.php b/environments/dev/common/config/main-local.php new file mode 100755 index 0000000..43db30e --- /dev/null +++ b/environments/dev/common/config/main-local.php @@ -0,0 +1,20 @@ + [ + 'db' => [ + 'class' => 'yii\db\Connection', + 'dsn' => 'mysql:host=localhost;dbname=yii2advanced', + 'username' => 'root', + 'password' => '', + 'charset' => 'utf8', + ], + 'mailer' => [ + 'class' => 'yii\swiftmailer\Mailer', + 'viewPath' => '@common/mail', + // send all mails to a file by default. You have to set + // 'useFileTransport' to false and configure a transport + // for the mailer to send real emails. + 'useFileTransport' => true, + ], + ], +]; diff --git a/environments/dev/common/config/params-local.php b/environments/dev/common/config/params-local.php new file mode 100755 index 0000000..d0b9c34 --- /dev/null +++ b/environments/dev/common/config/params-local.php @@ -0,0 +1,3 @@ + [ + 'db' => [ + 'dsn' => 'mysql:host=localhost;dbname=yii2advanced_test', + ] + ], + ] +); diff --git a/environments/dev/console/config/main-local.php b/environments/dev/console/config/main-local.php new file mode 100755 index 0000000..1d2118f --- /dev/null +++ b/environments/dev/console/config/main-local.php @@ -0,0 +1,7 @@ + ['gii'], + 'modules' => [ + 'gii' => 'yii\gii\Module', + ], +]; diff --git a/environments/dev/console/config/params-local.php b/environments/dev/console/config/params-local.php new file mode 100755 index 0000000..d0b9c34 --- /dev/null +++ b/environments/dev/console/config/params-local.php @@ -0,0 +1,3 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => '', + ], + ], +]; + +if (!YII_ENV_TEST) { + // configuration adjustments for 'dev' environment + $config['bootstrap'][] = 'debug'; + $config['modules']['debug'] = [ + 'class' => 'yii\debug\Module', + ]; + + $config['bootstrap'][] = 'gii'; + $config['modules']['gii'] = [ + 'class' => 'yii\gii\Module', + ]; +} + +return $config; diff --git a/environments/dev/frontend/config/params-local.php b/environments/dev/frontend/config/params-local.php new file mode 100755 index 0000000..d0b9c34 --- /dev/null +++ b/environments/dev/frontend/config/params-local.php @@ -0,0 +1,3 @@ +run(); diff --git a/environments/dev/frontend/web/index.php b/environments/dev/frontend/web/index.php new file mode 100755 index 0000000..1d75140 --- /dev/null +++ b/environments/dev/frontend/web/index.php @@ -0,0 +1,17 @@ +run(); diff --git a/environments/dev/yii b/environments/dev/yii new file mode 100755 index 0000000..6f0c6d2 --- /dev/null +++ b/environments/dev/yii @@ -0,0 +1,28 @@ +#!/usr/bin/env php +run(); +exit($exitCode); diff --git a/environments/dev/yii_test b/environments/dev/yii_test new file mode 100755 index 0000000..880050e --- /dev/null +++ b/environments/dev/yii_test @@ -0,0 +1,27 @@ +#!/usr/bin/env php +run(); +exit($exitCode); diff --git a/environments/dev/yii_test.bat b/environments/dev/yii_test.bat new file mode 100755 index 0000000..854e08b --- /dev/null +++ b/environments/dev/yii_test.bat @@ -0,0 +1,20 @@ +@echo off + +rem ------------------------------------------------------------- +rem Yii command line bootstrap script for Windows. +rem +rem @author Qiang Xue +rem @link http://www.yiiframework.com/ +rem @copyright Copyright (c) 2008 Yii Software LLC +rem @license http://www.yiiframework.com/license/ +rem ------------------------------------------------------------- + +@setlocal + +set YII_PATH=%~dp0 + +if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe + +"%PHP_COMMAND%" "%YII_PATH%yii_test" %* + +@endlocal diff --git a/environments/index.php b/environments/index.php new file mode 100755 index 0000000..5c3cca3 --- /dev/null +++ b/environments/index.php @@ -0,0 +1,65 @@ + [ + * 'path' => 'directory storing the local files', + * 'skipFiles' => [ + * // list of files that should only copied once and skipped if they already exist + * ], + * 'setWritable' => [ + * // list of directories that should be set writable + * ], + * 'setExecutable' => [ + * // list of files that should be set executable + * ], + * 'setCookieValidationKey' => [ + * // list of config files that need to be inserted with automatically generated cookie validation keys + * ], + * 'createSymlink' => [ + * // list of symlinks to be created. Keys are symlinks, and values are the targets. + * ], + * ], + * ]; + * ``` + */ +return [ + 'Development' => [ + 'path' => 'dev', + 'setWritable' => [ + 'backend/runtime', + 'backend/web/assets', + 'frontend/runtime', + 'frontend/web/assets', + ], + 'setExecutable' => [ + 'yii', + 'yii_test', + ], + 'setCookieValidationKey' => [ + 'backend/config/main-local.php', + 'frontend/config/main-local.php', + ], + ], + 'Production' => [ + 'path' => 'prod', + 'setWritable' => [ + 'backend/runtime', + 'backend/web/assets', + 'frontend/runtime', + 'frontend/web/assets', + ], + 'setExecutable' => [ + 'yii', + ], + 'setCookieValidationKey' => [ + 'backend/config/main-local.php', + 'frontend/config/main-local.php', + ], + ], +]; diff --git a/environments/prod/backend/config/main-local.php b/environments/prod/backend/config/main-local.php new file mode 100755 index 0000000..af46ba3 --- /dev/null +++ b/environments/prod/backend/config/main-local.php @@ -0,0 +1,9 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => '', + ], + ], +]; diff --git a/environments/prod/backend/config/params-local.php b/environments/prod/backend/config/params-local.php new file mode 100755 index 0000000..d0b9c34 --- /dev/null +++ b/environments/prod/backend/config/params-local.php @@ -0,0 +1,3 @@ +run(); diff --git a/environments/prod/common/config/main-local.php b/environments/prod/common/config/main-local.php new file mode 100755 index 0000000..84c4d9f --- /dev/null +++ b/environments/prod/common/config/main-local.php @@ -0,0 +1,16 @@ + [ + 'db' => [ + 'class' => 'yii\db\Connection', + 'dsn' => 'mysql:host=localhost;dbname=yii2advanced', + 'username' => 'root', + 'password' => '', + 'charset' => 'utf8', + ], + 'mailer' => [ + 'class' => 'yii\swiftmailer\Mailer', + 'viewPath' => '@common/mail', + ], + ], +]; diff --git a/environments/prod/common/config/params-local.php b/environments/prod/common/config/params-local.php new file mode 100755 index 0000000..d0b9c34 --- /dev/null +++ b/environments/prod/common/config/params-local.php @@ -0,0 +1,3 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => '', + ], + ], +]; diff --git a/environments/prod/frontend/config/params-local.php b/environments/prod/frontend/config/params-local.php new file mode 100755 index 0000000..d0b9c34 --- /dev/null +++ b/environments/prod/frontend/config/params-local.php @@ -0,0 +1,3 @@ +run(); diff --git a/environments/prod/yii b/environments/prod/yii new file mode 100755 index 0000000..1fe0342 --- /dev/null +++ b/environments/prod/yii @@ -0,0 +1,28 @@ +#!/usr/bin/env php +run(); +exit($exitCode); diff --git a/frontend/assets/AppAsset.php b/frontend/assets/AppAsset.php new file mode 100755 index 0000000..3a8bb96 --- /dev/null +++ b/frontend/assets/AppAsset.php @@ -0,0 +1,23 @@ + 'app-frontend', + 'basePath' => dirname(__DIR__), + 'bootstrap' => ['log'], + 'controllerNamespace' => 'frontend\controllers', + 'components' => [ + 'request' => [ + 'csrfParam' => '_csrf-frontend', + ], + 'user' => [ + 'identityClass' => 'common\models\User', + 'enableAutoLogin' => true, + 'identityCookie' => ['name' => '_identity-frontend', 'httpOnly' => true], + ], + 'session' => [ + // this is the name of the session cookie used for login on the frontend + 'name' => 'advanced-frontend', + ], + 'log' => [ + 'traceLevel' => YII_DEBUG ? 3 : 0, + 'targets' => [ + [ + 'class' => 'yii\log\FileTarget', + 'levels' => ['error', 'warning'], + ], + ], + ], + 'errorHandler' => [ + 'errorAction' => 'site/error', + ], + 'i18n' => [ + 'translations' => [ + 'app*' => [ + 'class' => 'yii\i18n\PhpMessageSource', + 'basePath' => '@app/messages', + // 'sourceLanguage' => 'en-US', + 'fileMap' => [ + 'app' => 'app.php', + 'app/error' => 'error.php', + ], + ], + ], + ], + + 'urlManager' => [ + 'class' => 'codemix\localeurls\UrlManager', + 'languages' => ['ru', 'en'], + 'enableDefaultLanguageUrlCode' => true, + 'enablePrettyUrl' => true, + 'showScriptName' => false, + 'enableStrictParsing' => false, + 'rules' => [ + ], + ], + + ], + 'params' => $params, +]; diff --git a/frontend/config/params.php b/frontend/config/params.php new file mode 100755 index 0000000..7f754b9 --- /dev/null +++ b/frontend/config/params.php @@ -0,0 +1,4 @@ + 'admin@example.com', +]; diff --git a/frontend/config/test.php b/frontend/config/test.php new file mode 100755 index 0000000..775aa98 --- /dev/null +++ b/frontend/config/test.php @@ -0,0 +1,9 @@ + 'app-frontend-tests', + 'components' => [ + 'assetManager' => [ + 'basePath' => __DIR__ . '/../web/assets', + ], + ], +]; diff --git a/frontend/controllers/CombatController.php b/frontend/controllers/CombatController.php new file mode 100755 index 0000000..b95f7b3 --- /dev/null +++ b/frontend/controllers/CombatController.php @@ -0,0 +1,81 @@ +user->isGuest) { + /** + * Run sessions. + */ + $session = Yii::$app->session; + $session->open(); + $user = User::findOne(['id' => Yii::$app->user->id]); + $usership = Port::findOne(['user_id' => Yii::$app->user->id]); + /** + * Checking user ship in port. + */ + if(isset($usership)) { + + $user_items = UserItems::findOne(['user_id' => $user->id]); + $shipname = Ship::findOne(['id' => $usership->ship_id]); + $battle_log = Battles::findOne(['bid' => $session['battle_id']]); + + if (!isset($session['usershiphp']) && !isset($session['bothp'])) { + $session['usershiphp'] = $usership->strength; + $session['bothp'] = $usership->strength; + } + if(Yii::$app->request->post('Attack')) { + if(Yii::$app->request->post('shot')) { + $shottype = Yii::$app->request->post('shot'); + Yii::$app->Combat->combat($shottype, $usership, $user, $session['battle_id'], $battle_log); + + } + } + + //Yii::$app->Combat->fight($user->id); + + return $this->render('index', [ + 'session' => $session, + 'usership' => $usership, + 'shipname' => $shipname, + 'user_items' => $user_items, + 'user' => $user, + 'battle_log' => $battle_log, + ]); + } else { + return $this->redirect('site/index'); + } + } else { + return $this->redirect('site/login'); + } + } + + /** + * Redirect to win page. + * @return string + */ + public function actionWin() + { + return $this->render('win'); + } + + /** + * Redirect to lose page. + * @return string + */ + public function actionLose() + { + return $this->render('lose'); + } +} diff --git a/frontend/controllers/DockController.php b/frontend/controllers/DockController.php new file mode 100644 index 0000000..080a849 --- /dev/null +++ b/frontend/controllers/DockController.php @@ -0,0 +1,26 @@ + Yii::$app->user->id]); + $userships = Port::find() + ->joinWith('user', 'ship') + ->andWhere(['user_id' => $player->id]) + ->all(); + + return $this->render('index', [ + 'userships' => $userships, + 'player' => $player, + ]); + } + +} diff --git a/frontend/controllers/ListController.php b/frontend/controllers/ListController.php new file mode 100644 index 0000000..10ede41 --- /dev/null +++ b/frontend/controllers/ListController.php @@ -0,0 +1,45 @@ +session; + $session->open(); + $session['battle_id'] = date('dmhs'); + $user = User::findOne(['id' => Yii::$app->user->id]); + + /** + * Checking the battle's params. + * Redirect to the combat page. + */ + if(Yii::$app->request->post('start')) { + $bid = new Battles(); + $bid->bid = $session['battle_id']; + $bid->creator_id = $user->id; + $bid->status = 0; + $bid->date = date('d.m.Y'); + $bid->save(); + + $user->updateAll(['battle_id' => $session['battle_id']], ['id' => $user->id]); + $this->redirect(Yii::$app->homeUrl.'/combat'); + } + return $this->render('index', [ + 'user' => $user, + ]); + } + +} diff --git a/frontend/controllers/LogsController.php b/frontend/controllers/LogsController.php new file mode 100644 index 0000000..4d4e49e --- /dev/null +++ b/frontend/controllers/LogsController.php @@ -0,0 +1,19 @@ + 1])->all(); + + return $this->render('index', [ + 'models' => $models, + ]); + } + +} diff --git a/frontend/controllers/ShopController.php b/frontend/controllers/ShopController.php new file mode 100644 index 0000000..6f2722b --- /dev/null +++ b/frontend/controllers/ShopController.php @@ -0,0 +1,27 @@ + [ + 'pageSize' => 20, + ], + 'query' => Ship::find() + ->orderBy('lvl DESC') + ->limit(20) + ]); + + return $this->render('index', [ + 'shopProvider' => $shopProvider, + ]); + } + +} diff --git a/frontend/controllers/SiteController.php b/frontend/controllers/SiteController.php new file mode 100755 index 0000000..1b64335 --- /dev/null +++ b/frontend/controllers/SiteController.php @@ -0,0 +1,300 @@ + [ + 'class' => AccessControl::className(), + 'only' => ['login', 'signup', 'error', 'logout', 'index', 'combat', 'contact', 'about' ], + 'rules' => [ + [ + 'actions' => ['login', 'signup', 'error'], + 'allow' => true, + 'roles' => ['?'], + ], + [ + 'actions' => ['logout', 'index', 'combat', 'error', 'contact', 'about'], + 'allow' => true, + 'roles' => ['@'], + ], + ], + ], + 'verbs' => [ + 'class' => VerbFilter::className(), + 'actions' => [ + 'logout' => ['post'], + ], + ], + ]; + } + /** + * @inheritdoc + */ + public function actions() + { + return [ + 'error' => [ + 'class' => 'yii\web\ErrorAction', + ], + 'captcha' => [ + 'class' => 'yii\captcha\CaptchaAction', + 'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null, + ], + ]; + } + + /** + * Displays homepage. + * + * @return mixed + */ + public function actionIndex() + { + if(!Yii::$app->user->isGuest) { + $user = User::findOne(Yii::$app->user->getId()); + + // + if(Yii::$app->request->post('shipfirst')) { + $newship = new Port(); + + $newship->user_id = Yii::$app->user->id; + $newship->ship_id = 2; + $newship->exp = 0; + $newship->stock_gun = 1; + $newship->stock_tower = 1; + $newship->mod_gun = 0; + $newship->mod_tower = 0; + $newship->strength = 1600; + $newship->type = 2; + + $newship->save(); + + return $this->goHome(); + } elseif(Yii::$app->request->post('shipsecond')) { + $newship = new Port(); + + $newship->user_id = Yii::$app->user->id; + $newship->ship_id = 4; + $newship->exp = 0; + $newship->stock_gun = 1; + $newship->stock_tower = 1; + $newship->mod_gun = 0; + $newship->mod_tower = 0; + $newship->strength = 1600; + $newship->type = 3; + + $newship->save(); + + return $this->goHome(); + } + + $model = Port::findOne(['user_id' => Yii::$app->user->id]); + if($model) { + $shipname = Ship::findOne(['id' => $model->ship_id]); + + $avaible_mods = Mods::findOne(['ship_id' => $model->ship_id]); + + + if(Yii::$app->request->post('expmodgun')) { + $model->updateCounters(['exp' => -($avaible_mods->exp_gun)]); + $model->updateCounters(['exp_gun' => 1]); + + $this->goHome(); + } + if(Yii::$app->request->post('expmodtower')) { + $model->updateCounters(['exp' => -($avaible_mods->exp_tower)]); + $model->updateCounters(['exp_tower' => 1]); + + $this->goHome(); + } + + if(Yii::$app->request->post('buymodgun')) { + if(($user->credits) >= ($avaible_mods->cost_gun)) { + $user->updateCounters(['credits' => -($avaible_mods->cost_gun)]); + $model->updateCounters(['mod_gun' => 1]); + $model->updateCounters(['stock_gun' => -1]); + + $this->goHome(); + } + } + if(Yii::$app->request->post('buymodtower')) { + if(($user->credits) >= ($avaible_mods->cost_tower)) { + $user->updateCounters(['credits' => -($avaible_mods->cost_tower)]); + $model->updateCounters(['mod_tower' => 1]); + $model->updateCounters(['stock_tower' => -1]); + $model->updateCounters(['strength' => +500]); + + $this->goHome(); + } + } + + + return $this->render('main', [ + 'model' => $model, + 'shipname' => $shipname, + 'user' => $user, + 'avaible_mods' => $avaible_mods, + ]); + } else { + return $this->render('main', [ + 'user' => $user, + ]); + } + } else { + return $this->redirect('site/login'); + } + } + + /** + * Logs in a user. + * + * @return mixed + */ + public function actionLogin() + { + if (!Yii::$app->user->isGuest) { + return $this->goHome(); + } + + $model = new LoginForm(); + if ($model->load(Yii::$app->request->post()) && $model->login()) { + return $this->goBack(); + } else { + return $this->render('login', [ + 'model' => $model, + ]); + } + } + + /** + * Logs out the current user. + * + * @return mixed + */ + public function actionLogout() + { + Yii::$app->user->logout(); + + return $this->goHome(); + } + + /** + * Displays contact page. + * + * @return mixed + */ + public function actionContact() + { + $model = new ContactForm(); + if ($model->load(Yii::$app->request->post()) && $model->validate()) { + if ($model->sendEmail(Yii::$app->params['adminEmail'])) { + Yii::$app->session->setFlash('success', 'Thank you for contacting us. We will respond to you as soon as possible.'); + } else { + Yii::$app->session->setFlash('error', 'There was an error sending your message.'); + } + + return $this->refresh(); + } else { + return $this->render('contact', [ + 'model' => $model, + ]); + } + } + + /** + * Signs user up. + * + * @return mixed + */ + public function actionSignup() + { + + $model = new SignupForm(); + if ($model->load(Yii::$app->request->post())) { + if ($user = $model->signup()) { + if (Yii::$app->getUser()->login($user)) { + return $this->goHome(); + } + } + } + + return $this->render('signup', [ + 'model' => $model, + ]); + } + + /** + * Requests password reset. + * + * @return mixed + */ + public function actionRequestPasswordReset() + { + $model = new PasswordResetRequestForm(); + if ($model->load(Yii::$app->request->post()) && $model->validate()) { + if ($model->sendEmail()) { + Yii::$app->session->setFlash('success', 'Check your email for further instructions.'); + + return $this->goHome(); + } else { + Yii::$app->session->setFlash('error', 'Sorry, we are unable to reset password for the provided email address.'); + } + } + + return $this->render('requestPasswordResetToken', [ + 'model' => $model, + ]); + } + + /** + * Resets password. + * + * @param string $token + * @return mixed + * @throws BadRequestHttpException + */ + public function actionResetPassword($token) + { + try { + $model = new ResetPasswordForm($token); + } catch (InvalidParamException $e) { + throw new BadRequestHttpException($e->getMessage()); + } + + if ($model->load(Yii::$app->request->post()) && $model->validate() && $model->resetPassword()) { + Yii::$app->session->setFlash('success', 'New password saved.'); + + return $this->goHome(); + } + + return $this->render('resetPassword', [ + 'model' => $model, + ]); + } +} diff --git a/frontend/controllers/ToprankController.php b/frontend/controllers/ToprankController.php new file mode 100644 index 0000000..20a0035 --- /dev/null +++ b/frontend/controllers/ToprankController.php @@ -0,0 +1,22 @@ +joinWith('user', 'ship') + ->orderBy('user.win') + ->all(); + + return $this->render('index', [ + 'userships' => $userships, + ]); + + } +} diff --git a/frontend/messages/ru/app.php b/frontend/messages/ru/app.php new file mode 100755 index 0000000..b997a26 --- /dev/null +++ b/frontend/messages/ru/app.php @@ -0,0 +1,190 @@ +Battle Ships' => 'Морской Бой', + 'Home' => 'Главная', + 'Combat' => 'В бой', + 'Logout' => 'Выйти', + 'Login' => 'Авторизация', + 'Signup' => 'Регистрация', + 'Toprank' => 'Топ-игроки', + 'Hello' => 'Здравствуй', + 'Battle of WarShips!' => 'Битва Кораблей!', + 'Here is your Port of Battle Ships!' => 'Это Ваш порт!', + 'Strength' => 'Прочность', + 'Experience' => 'Опыт', + 'Credits' => 'Кредиты', + 'Statistics' => 'Статистика', + 'WIN' => 'Побед', + 'LOSE' => 'Поражений', + 'DRAW' => 'Ничьих', + 'Stock Gun' => 'Стоковое Орудие', + 'Modificate Gun' => 'Улучшеное Орудие', + 'Stock Tower' => 'Стоковый корпус корабля', + 'Modificate Tower' => 'Улучшеный корпус корабля', + 'Please, chose your first Warship' => 'Пожалуйста, выберите Ваш новый корабль', + 'getShip' => 'Выбрать боевой корабль', + 'Available Mods' => 'Доступные моды', + 'Improved Hit Points(HP)' => 'Улучшеный корпус корабля', + 'Modified Main Battery' => 'Модифицирован Главный-Калибр', + 'Explore' => 'Исследовать', + 'Installed modules' => 'Установленные модули', + 'Buy' => 'Купить', + //Combat + 'Battle Ship Combat Begin' => 'Великая битва кораблей началась', + 'Top Rank users' => 'Лучшие игроки', + 'Battle Shop' => 'Магазин кораблей', + 'Shop' => 'Магазин', + // Battle + 'Start battle' => 'Начать бой', + 'Reg Battle' => 'Вступить в бой', + 'Go Battle' => 'Вступить в бой', + 'You attacked the bot warship on -' => 'Вы нанесли урон вражескому кораблю на -', + 'Our warship were attacked by bot warship on -' => 'Ваш корабль был атакован на -', + 'Congratulations, You are Win' => 'Поздравляем, победа за Вами', + 'Go Port' => 'Перейти в порт', + 'Unfortunately' => 'К сожалению, Вы проиграли', + // Auth + 'Auth' => 'Авторизация', + 'Login' => 'Войти', + 'username' => 'Имя пользователя', + 'password' => 'Пароль', + 'rememberMe' => 'Запомнить меня', + 'reset it' => 'сбросить', + 'Please fill out the following fields to login' => 'Пожалуйста, заполните следующие поля', + 'If you forgot your password you can' => 'Если Вы забилы свой пароль, нажмите здесь', + // Signup + 'Signup' => 'Зарегистрировать', + 'Please fill out the following fields to signup' => 'Пожалуйста заполните следующие поля для регистрации', + 'Reg' => 'Регистрация', + // Others + 'Powered by {yii}' => 'Работает на {yii}', + 'Unknown alias: -{name}' => 'Неизвестный псевдоним: -{name}', + 'Yii Framework' => 'Yii Framework', + '(not set)' => '(не задано)', + ' and ' => ' и ', + 'An internal server error occurred.' => 'Возникла внутренняя ошибка сервера.', + 'Are you sure you want to delete this item?' => 'Вы уверены, что хотите удалить этот элемент?', + 'Delete' => 'Удалить', + 'Error' => 'Ошибка', + 'File upload failed.' => 'Загрузка файла не удалась.', + 'Home' => 'Главная', + 'Invalid data received for parameter "{param}".' => 'Неправильное значение параметра "{param}".', + 'Login Required' => 'Требуется вход.', + 'Missing required arguments: {params}' => 'Отсутствуют обязательные аргументы: {params}', + 'Missing required parameters: {params}' => 'Отсутствуют обязательные параметры: {params}', + 'No' => 'Нет', + 'No results found.' => 'Ничего не найдено.', + 'Only files with these MIME types are allowed: {mimeTypes}.' => 'Разрешена загрузка файлов только со следующими MIME-типами: {mimeTypes}.', + 'Only files with these extensions are allowed: {extensions}.' => 'Разрешена загрузка файлов только со следующими расширениями: {extensions}.', + 'Page not found.' => 'Страница не найдена.', + 'Please fix the following errors:' => 'Исправьте следующие ошибки:', + 'Please upload a file.' => 'Загрузите файл.', + 'Showing {begin, number}-{end, number} of {totalCount, number} {totalCount, plural, one{item} other{items}}.' => 'Показаны записи {begin, number}-{end, number} из {totalCount, number}.', + 'The combination {values} of {attributes} has already been taken.' => 'Комбинация {values} параметров {attributes} уже существует.', + 'The file "{file}" is not an image.' => 'Файл «{file}» не является изображением.', + 'The file "{file}" is too big. Its size cannot exceed {formattedLimit}.' => 'Файл «{file}» слишком большой. Размер не должен превышать {formattedLimit}.', + 'The file "{file}" is too small. Its size cannot be smaller than {formattedLimit}.' => 'Файл «{file}» слишком маленький. Размер должен быть более {formattedLimit}.', + 'The format of {attribute} is invalid.' => 'Неверный формат значения «{attribute}».', + 'The image "{file}" is too large. The height cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Файл «{file}» слишком большой. Высота не должна превышать {limit, number} {limit, plural, one{пиксель} few{пикселя} many{пикселей} other{пикселя}}.', + 'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Файл «{file}» слишком большой. Ширина не должна превышать {limit, number} {limit, plural, one{пиксель} few{пикселя} many{пикселей} other{пикселя}}.', + 'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Файл «{file}» слишком маленький. Высота должна быть более {limit, number} {limit, plural, one{пиксель} few{пикселя} many{пикселей} other{пикселя}}.', + 'The image "{file}" is too small. The width cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Файл «{file}» слишком маленький. Ширина должна быть более {limit, number} {limit, plural, one{пиксель} few{пикселя} many{пикселей} other{пикселя}}.', + 'The requested view "{name}" was not found.' => 'Запрашиваемый файл представления "{name}" не найден.', + 'The verification code is incorrect.' => 'Неправильный проверочный код.', + 'Total {count, number} {count, plural, one{item} other{items}}.' => 'Всего {count, number} {count, plural, one{запись} few{записи} many{записей} other{записи}}.', + 'Unable to verify your data submission.' => 'Не удалось проверить переданные данные.', + 'Unknown option: --{name}' => 'Неизвестная опция: --{name}', + 'Update' => 'Редактировать', + 'View' => 'Просмотр', + 'Yes' => 'Да', + 'You are not allowed to perform this action.' => 'Вам не разрешено производить данное действие.', + 'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.' => 'Вы не можете загружать более {limit, number} {limit, plural, one{файла} few{файлов} many{файлов} other{файла}}.', + 'in {delta, plural, =1{a day} other{# days}}' => 'через {delta, plural, =1{день} one{# день} few{# дня} many{# дней} other{# дня}}', + 'in {delta, plural, =1{a minute} other{# minutes}}' => 'через {delta, plural, =1{минуту} one{# минуту} few{# минуты} many{# минут} other{# минуты}}', + 'in {delta, plural, =1{a month} other{# months}}' => 'через {delta, plural, =1{месяц} one{# месяц} few{# месяца} many{# месяцев} other{# месяца}}', + 'in {delta, plural, =1{a second} other{# seconds}}' => 'через {delta, plural, =1{секунду} one{# секунду} few{# секунды} many{# секунд} other{# секунды}}', + 'in {delta, plural, =1{a year} other{# years}}' => 'через {delta, plural, =1{год} one{# год} few{# года} many{# лет} other{# года}}', + 'in {delta, plural, =1{an hour} other{# hours}}' => 'через {delta, plural, =1{час} one{# час} few{# часа} many{# часов} other{# часа}}', + 'just now' => 'прямо сейчас', + 'the input value' => 'введённое значение', + '{attribute} "{value}" has already been taken.' => 'Значение «{value}» для «{attribute}» уже занято.', + '{attribute} cannot be blank.' => 'Необходимо заполнить «{attribute}».', + '{attribute} contains wrong subnet mask.' => 'Значение «{attribute}» содержит неверную маску подсети.', + '{attribute} is invalid.' => 'Значение «{attribute}» неверно.', + '{attribute} is not a valid URL.' => 'Значение «{attribute}» не является правильным URL.', + '{attribute} is not a valid email address.' => 'Значение «{attribute}» не является правильным email адресом.', + '{attribute} is not in the allowed range.' => 'Значение «{attribute}» не входит в список разрешенных диапазонов адресов.', + '{attribute} must be "{requiredValue}".' => 'Значение «{attribute}» должно быть равно «{requiredValue}».', + '{attribute} must be a number.' => 'Значение «{attribute}» должно быть числом.', + '{attribute} must be a string.' => 'Значение «{attribute}» должно быть строкой.', + '{attribute} must be a valid IP address.' => 'Значение «{attribute}» должно быть правильным IP адресом.', + '{attribute} must be an IP address with specified subnet.' => 'Значение «{attribute}» должно быть IP адресом с подсетью.', + '{attribute} must be an integer.' => 'Значение «{attribute}» должно быть целым числом.', + '{attribute} must be either "{true}" or "{false}".' => 'Значение «{attribute}» должно быть равно «{true}» или «{false}».', + '{attribute} must be equal to "{compareValueOrAttribute}".' => 'Значение «{attribute}» должно быть равно «{compareValueOrAttribute}».', + '{attribute} must be greater than "{compareValueOrAttribute}".' => 'Значение «{attribute}» должно быть больше значения «{compareValueOrAttribute}».', + '{attribute} must be greater than or equal to "{compareValueOrAttribute}".' => 'Значение «{attribute}» должно быть больше или равно значения «{compareValueOrAttribute}».', + '{attribute} must be less than "{compareValueOrAttribute}".' => 'Значение «{attribute}» должно быть меньше значения «{compareValueOrAttribute}».', + '{attribute} must be less than or equal to "{compareValueOrAttribute}".' => 'Значение «{attribute}» должно быть меньше или равно значения «{compareValueOrAttribute}».', + '{attribute} must be no greater than {max}.' => 'Значение «{attribute}» не должно превышать {max}.', + '{attribute} must be no less than {min}.' => 'Значение «{attribute}» должно быть не меньше {min}.', + '{attribute} must not be a subnet.' => 'Значение «{attribute}» не должно быть подсетью.', + '{attribute} must not be an IPv4 address.' => 'Значение «{attribute}» не должно быть IPv4 адресом.', + '{attribute} must not be an IPv6 address.' => 'Значение «{attribute}» не должно быть IPv6 адресом.', + '{attribute} must not be equal to "{compareValueOrAttribute}".' => 'Значение «{attribute}» не должно быть равно «{compareValueOrAttribute}».', + '{attribute} should contain at least {min, number} {min, plural, one{character} other{characters}}.' => 'Значение «{attribute}» должно содержать минимум {min, number} {min, plural, one{символ} few{символа} many{символов} other{символа}}.', + '{attribute} should contain at most {max, number} {max, plural, one{character} other{characters}}.' => 'Значение «{attribute}» должно содержать максимум {max, number} {max, plural, one{символ} few{символа} many{символов} other{символа}}.', + '{attribute} should contain {length, number} {length, plural, one{character} other{characters}}.' => 'Значение «{attribute}» должно содержать {length, number} {length, plural, one{символ} few{символа} many{символов} other{символа}}.', + '{delta, plural, =1{1 day} other{# days}}' => '{delta, plural, one{# день} few{# дня} many{# дней} other{# дня}}', + '{delta, plural, =1{1 hour} other{# hours}}' => '{delta, plural, one{# час} few{# часа} many{# часов} other{# часа}}', + '{delta, plural, =1{1 minute} other{# minutes}}' => '{delta, plural, one{# минута} few{# минуты} many{# минут} other{# минуты}}', + '{delta, plural, =1{1 month} other{# months}}' => '{delta, plural, one{# месяц} few{# месяца} many{# месяцев} other{# месяца}}', + '{delta, plural, =1{1 second} other{# seconds}}' => '{delta, plural, one{# секунда} few{# секунды} many{# секунд} other{# секунды}}', + '{delta, plural, =1{1 year} other{# years}}' => '{delta, plural, one{# год} few{# года} many{# лет} other{# года}}', + '{delta, plural, =1{a day} other{# days}} ago' => '{delta, plural, =1{день} one{# день} few{# дня} many{# дней} other{# дня}} назад', + '{delta, plural, =1{a minute} other{# minutes}} ago' => '{delta, plural, =1{минуту} one{# минуту} few{# минуты} many{# минут} other{# минуты}} назад', + '{delta, plural, =1{a month} other{# months}} ago' => '{delta, plural, =1{месяц} one{# месяц} few{# месяца} many{# месяцев} other{# месяца}} назад', + '{delta, plural, =1{a second} other{# seconds}} ago' => '{delta, plural, =1{секунду} one{# секунду} few{# секунды} many{# секунд} other{# секунды}} назад', + '{delta, plural, =1{a year} other{# years}} ago' => '{delta, plural, =1{год} one{# год} few{# года} many{# лет} other{# года}} назад', + '{delta, plural, =1{an hour} other{# hours}} ago' => '{delta, plural, =1{час} one{# час} few{# часа} many{# часов} other{# часа}} назад', + '{nFormatted} B' => '{nFormatted} Б', + '{nFormatted} GB' => '{nFormatted} ГБ', + '{nFormatted} GiB' => '{nFormatted} ГиБ', + '{nFormatted} KB' => '{nFormatted} КБ', + '{nFormatted} KiB' => '{nFormatted} КиБ', + '{nFormatted} MB' => '{nFormatted} МБ', + '{nFormatted} MiB' => '{nFormatted} МиБ', + '{nFormatted} PB' => '{nFormatted} ПБ', + '{nFormatted} PiB' => '{nFormatted} ПиБ', + '{nFormatted} TB' => '{nFormatted} ТБ', + '{nFormatted} TiB' => '{nFormatted} ТиБ', + '{nFormatted} {n, plural, =1{byte} other{bytes}}' => '{nFormatted} {n, plural, one{байт} few{байта} many{байтов} other{байта}}', + '{nFormatted} {n, plural, =1{gibibyte} other{gibibytes}}' => '{nFormatted} {n, plural, one{гибибайт} few{гибибайта} many{гибибайтов} other{гибибайта}}', + '{nFormatted} {n, plural, =1{gigabyte} other{gigabytes}}' => '{nFormatted} {n, plural, one{гигабайт} few{гигабайта} many{гигабайтов} other{гигабайта}}', + '{nFormatted} {n, plural, =1{kibibyte} other{kibibytes}}' => '{nFormatted} {n, plural, one{кибибайт} few{кибибайта} many{кибибайтов} other{кибибайта}}', + '{nFormatted} {n, plural, =1{kilobyte} other{kilobytes}}' => '{nFormatted} {n, plural, one{килобайт} few{килобайта} many{килобайтов} other{килобайта}}', + '{nFormatted} {n, plural, =1{mebibyte} other{mebibytes}}' => '{nFormatted} {n, plural, one{мебибайт} few{мебибайта} many{мебибайтов} other{мебибайта}}', + '{nFormatted} {n, plural, =1{megabyte} other{megabytes}}' => '{nFormatted} {n, plural, one{мегабайт} few{мегабайта} many{мегабайтов} other{мегабайта}}', + '{nFormatted} {n, plural, =1{pebibyte} other{pebibytes}}' => '{nFormatted} {n, plural, one{пебибайт} few{пебибайта} many{пебибайтов} other{пебибайта}}', + '{nFormatted} {n, plural, =1{petabyte} other{petabytes}}' => '{nFormatted} {n, plural, one{петабайт} few{петабайта} many{петабайтов} other{петабайта}}', + '{nFormatted} {n, plural, =1{tebibyte} other{tebibytes}}' => '{nFormatted} {n, plural, one{тебибайт} few{тебибайта} many{тебибайтов} other{тебибайта}}', + '{nFormatted} {n, plural, =1{terabyte} other{terabytes}}' => '{nFormatted} {n, plural, one{терабайт} few{терабайта} many{терабайтов} other{терабайта}}', +]; diff --git a/frontend/models/ContactForm.php b/frontend/models/ContactForm.php new file mode 100755 index 0000000..d0cc9cb --- /dev/null +++ b/frontend/models/ContactForm.php @@ -0,0 +1,60 @@ + 'Verification Code', + ]; + } + + /** + * Sends an email to the specified email address using the information collected by this model. + * + * @param string $email the target email address + * @return bool whether the email was sent + */ + public function sendEmail($email) + { + return Yii::$app->mailer->compose() + ->setTo($email) + ->setFrom([$this->email => $this->name]) + ->setSubject($this->subject) + ->setTextBody($this->body) + ->send(); + } +} diff --git a/frontend/models/PasswordResetRequestForm.php b/frontend/models/PasswordResetRequestForm.php new file mode 100755 index 0000000..c11aeec --- /dev/null +++ b/frontend/models/PasswordResetRequestForm.php @@ -0,0 +1,68 @@ + '\common\models\User', + 'filter' => ['status' => User::STATUS_ACTIVE], + 'message' => 'There is no user with this email address.' + ], + ]; + } + + /** + * Sends an email with a link, for resetting the password. + * + * @return bool whether the email was send + */ + public function sendEmail() + { + /* @var $user User */ + $user = User::findOne([ + 'status' => User::STATUS_ACTIVE, + 'email' => $this->email, + ]); + + if (!$user) { + return false; + } + + if (!User::isPasswordResetTokenValid($user->password_reset_token)) { + $user->generatePasswordResetToken(); + if (!$user->save()) { + return false; + } + } + + return Yii::$app + ->mailer + ->compose( + ['html' => 'passwordResetToken-html', 'text' => 'passwordResetToken-text'], + ['user' => $user] + ) + ->setFrom([Yii::$app->params['supportEmail'] => Yii::$app->name . ' robot']) + ->setTo($this->email) + ->setSubject('Password reset for ' . Yii::$app->name) + ->send(); + } +} diff --git a/frontend/models/ResetPasswordForm.php b/frontend/models/ResetPasswordForm.php new file mode 100755 index 0000000..fb36dd0 --- /dev/null +++ b/frontend/models/ResetPasswordForm.php @@ -0,0 +1,64 @@ +_user = User::findByPasswordResetToken($token); + if (!$this->_user) { + throw new InvalidParamException('Wrong password reset token.'); + } + parent::__construct($config); + } + + /** + * @inheritdoc + */ + public function rules() + { + return [ + ['password', 'required'], + ['password', 'string', 'min' => 6], + ]; + } + + /** + * Resets password. + * + * @return bool if password was reset. + */ + public function resetPassword() + { + $user = $this->_user; + $user->setPassword($this->password); + $user->removePasswordResetToken(); + + return $user->save(false); + } +} diff --git a/frontend/models/SignupForm.php b/frontend/models/SignupForm.php new file mode 100755 index 0000000..dac4d96 --- /dev/null +++ b/frontend/models/SignupForm.php @@ -0,0 +1,71 @@ + '\common\models\User', 'message' => 'This username has already been taken.'], + ['username', 'string', 'min' => 2, 'max' => 255], + + ['email', 'trim'], + ['email', 'required'], + ['email', 'email'], + ['email', 'string', 'max' => 255], + ['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'], + + ['password', 'required'], + ['password', 'string', 'min' => 6], + ]; + } + + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'username' => Yii::t('app', 'username'), + 'password' => Yii::t('app', 'password'), + ]; + } + + /** + * Signs user up. + * + * @return User|null the saved model or null if saving fails + */ + public function signup() + { + if (!$this->validate()) { + return null; + } + + $user = new User(); + $user->username = $this->username; + $user->email = $this->email; + $user->setPassword($this->password); + $user->generateAuthKey(); + + return $user->save() ? $user : null; + } +} diff --git a/frontend/runtime/.gitignore b/frontend/runtime/.gitignore new file mode 100755 index 0000000..c96a04f --- /dev/null +++ b/frontend/runtime/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/frontend/tests/1bootstrap.php b/frontend/tests/1bootstrap.php new file mode 100755 index 0000000..83a1f26 --- /dev/null +++ b/frontend/tests/1bootstrap.php @@ -0,0 +1,9 @@ + 'erau', + 'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI', + // password_0 + 'password_hash' => '$2y$13$nJ1WDlBaGcbCdbNC5.5l4.sgy.OMEKCqtDQOdQ2OWpgiKRWYyzzne', + 'password_reset_token' => 'RkD_Jw0_8HEedzLk7MM-ZKEFfYR7VbMr_1392559490', + 'created_at' => '1392559490', + 'updated_at' => '1392559490', + 'email' => 'sfriesen@jenkins.info', + ], +]; diff --git a/frontend/tests/_data/user.php b/frontend/tests/_data/user.php new file mode 100755 index 0000000..3670e09 --- /dev/null +++ b/frontend/tests/_data/user.php @@ -0,0 +1,23 @@ + 'okirlin', + 'auth_key' => 'iwTNae9t34OmnK6l4vT4IeaTk-YWI2Rv', + 'password_hash' => '$2y$13$CXT0Rkle1EMJ/c1l5bylL.EylfmQ39O5JlHJVFpNn618OUS1HwaIi', + 'password_reset_token' => 't5GU9NwpuGYSfb7FEZMAxqtuz2PkEvv_' . time(), + 'created_at' => '1391885313', + 'updated_at' => '1391885313', + 'email' => 'brady.renner@rutherford.com', + ], + [ + 'username' => 'troy.becker', + 'auth_key' => 'EdKfXrx88weFMV0vIxuTMWKgfK2tS3Lp', + 'password_hash' => '$2y$13$g5nv41Px7VBqhS3hVsVN2.MKfgT3jFdkXEsMC4rQJLfaMa7VaJqL2', + 'password_reset_token' => '4BSNyiZNAuxjs5Mty990c47sVrgllIi_' . time(), + 'created_at' => '1391885313', + 'updated_at' => '1391885313', + 'email' => 'nicolas.dianna@hotmail.com', + 'status' => '0', + ], +]; diff --git a/frontend/tests/_output/.gitignore b/frontend/tests/_output/.gitignore new file mode 100755 index 0000000..d6b7ef3 --- /dev/null +++ b/frontend/tests/_output/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/frontend/tests/_support/.gitignore b/frontend/tests/_support/.gitignore new file mode 100755 index 0000000..36e264c --- /dev/null +++ b/frontend/tests/_support/.gitignore @@ -0,0 +1 @@ +_generated diff --git a/frontend/tests/_support/AcceptanceTester.php b/frontend/tests/_support/AcceptanceTester.php new file mode 100755 index 0000000..3c79b4f --- /dev/null +++ b/frontend/tests/_support/AcceptanceTester.php @@ -0,0 +1,26 @@ +see($message, '.help-block'); + } + + public function dontSeeValidationError($message) + { + $this->dontSee($message, '.help-block'); + } +} diff --git a/frontend/tests/_support/UnitTester.php b/frontend/tests/_support/UnitTester.php new file mode 100755 index 0000000..8c708e7 --- /dev/null +++ b/frontend/tests/_support/UnitTester.php @@ -0,0 +1,25 @@ +amOnPage(Url::toRoute('/site/index')); + $I->see('My Company'); + + $I->seeLink('About'); + $I->click('About'); + $I->wait(2); // wait for page to be opened + + $I->see('This is the About page.'); + } +} diff --git a/frontend/tests/acceptance/_bootstrap.php b/frontend/tests/acceptance/_bootstrap.php new file mode 100755 index 0000000..47716f0 --- /dev/null +++ b/frontend/tests/acceptance/_bootstrap.php @@ -0,0 +1,16 @@ + 'davert']); + * ``` + * + * In Cept + * + * ```php + * \Codeception\Util\Fixtures::get('user1'); + * ``` + */ \ No newline at end of file diff --git a/frontend/tests/functional.suite.yml b/frontend/tests/functional.suite.yml new file mode 100755 index 0000000..3f851d1 --- /dev/null +++ b/frontend/tests/functional.suite.yml @@ -0,0 +1,5 @@ +class_name: FunctionalTester +modules: + enabled: + - Filesystem + - Yii2 diff --git a/frontend/tests/functional/AboutCest.php b/frontend/tests/functional/AboutCest.php new file mode 100755 index 0000000..6c3cb9e --- /dev/null +++ b/frontend/tests/functional/AboutCest.php @@ -0,0 +1,13 @@ +amOnRoute('site/about'); + $I->see('About', 'h1'); + } +} diff --git a/frontend/tests/functional/ContactCest.php b/frontend/tests/functional/ContactCest.php new file mode 100755 index 0000000..bdda991 --- /dev/null +++ b/frontend/tests/functional/ContactCest.php @@ -0,0 +1,59 @@ +amOnPage(['site/contact']); + } + + public function checkContact(FunctionalTester $I) + { + $I->see('Contact', 'h1'); + } + + public function checkContactSubmitNoData(FunctionalTester $I) + { + $I->submitForm('#contact-form', []); + $I->see('Contact', 'h1'); + $I->seeValidationError('Name cannot be blank'); + $I->seeValidationError('Email cannot be blank'); + $I->seeValidationError('Subject cannot be blank'); + $I->seeValidationError('Body cannot be blank'); + $I->seeValidationError('The verification code is incorrect'); + } + + public function checkContactSubmitNotCorrectEmail(FunctionalTester $I) + { + $I->submitForm('#contact-form', [ + 'ContactForm[name]' => 'tester', + 'ContactForm[email]' => 'tester.email', + 'ContactForm[subject]' => 'test subject', + 'ContactForm[body]' => 'test content', + 'ContactForm[verifyCode]' => 'testme', + ]); + $I->seeValidationError('Email is not a valid email address.'); + $I->dontSeeValidationError('Name cannot be blank'); + $I->dontSeeValidationError('Subject cannot be blank'); + $I->dontSeeValidationError('Body cannot be blank'); + $I->dontSeeValidationError('The verification code is incorrect'); + } + + public function checkContactSubmitCorrectData(FunctionalTester $I) + { + $I->submitForm('#contact-form', [ + 'ContactForm[name]' => 'tester', + 'ContactForm[email]' => 'tester@example.com', + 'ContactForm[subject]' => 'test subject', + 'ContactForm[body]' => 'test content', + 'ContactForm[verifyCode]' => 'testme', + ]); + $I->seeEmailIsSent(); + $I->see('Thank you for contacting us. We will respond to you as soon as possible.'); + } +} diff --git a/frontend/tests/functional/HomeCest.php b/frontend/tests/functional/HomeCest.php new file mode 100755 index 0000000..8f99b48 --- /dev/null +++ b/frontend/tests/functional/HomeCest.php @@ -0,0 +1,17 @@ +amOnPage(\Yii::$app->homeUrl); + $I->see('My Company'); + $I->seeLink('About'); + $I->click('About'); + $I->see('This is the About page.'); + } +} \ No newline at end of file diff --git a/frontend/tests/functional/LoginCest.php b/frontend/tests/functional/LoginCest.php new file mode 100755 index 0000000..696aeda --- /dev/null +++ b/frontend/tests/functional/LoginCest.php @@ -0,0 +1,49 @@ +haveFixtures([ + 'user' => [ + 'class' => UserFixture::className(), + 'dataFile' => codecept_data_dir() . 'login_data.php' + ] + ]); + $I->amOnRoute('site/login'); + } + + protected function formParams($login, $password) + { + return [ + 'LoginForm[username]' => $login, + 'LoginForm[password]' => $password, + ]; + } + + public function checkEmpty(FunctionalTester $I) + { + $I->submitForm('#login-form', $this->formParams('', '')); + $I->seeValidationError('Username cannot be blank.'); + $I->seeValidationError('Password cannot be blank.'); + } + + public function checkWrongPassword(FunctionalTester $I) + { + $I->submitForm('#login-form', $this->formParams('admin', 'wrong')); + $I->seeValidationError('Incorrect username or password.'); + } + + public function checkValidLogin(FunctionalTester $I) + { + $I->submitForm('#login-form', $this->formParams('erau', 'password_0')); + $I->see('Logout (erau)', 'form button[type=submit]'); + $I->dontSeeLink('Login'); + $I->dontSeeLink('Signup'); + } +} diff --git a/frontend/tests/functional/SignupCest.php b/frontend/tests/functional/SignupCest.php new file mode 100755 index 0000000..8cfde9a --- /dev/null +++ b/frontend/tests/functional/SignupCest.php @@ -0,0 +1,57 @@ +amOnRoute('site/signup'); + } + + public function signupWithEmptyFields(FunctionalTester $I) + { + $I->see('Signup', 'h1'); + $I->see('Please fill out the following fields to signup:'); + $I->submitForm($this->formId, []); + $I->seeValidationError('Username cannot be blank.'); + $I->seeValidationError('Email cannot be blank.'); + $I->seeValidationError('Password cannot be blank.'); + + } + + public function signupWithWrongEmail(FunctionalTester $I) + { + $I->submitForm( + $this->formId, [ + 'SignupForm[username]' => 'tester', + 'SignupForm[email]' => 'ttttt', + 'SignupForm[password]' => 'tester_password', + ] + ); + $I->dontSee('Username cannot be blank.', '.help-block'); + $I->dontSee('Password cannot be blank.', '.help-block'); + $I->see('Email is not a valid email address.', '.help-block'); + } + + public function signupSuccessfully(FunctionalTester $I) + { + $I->submitForm($this->formId, [ + 'SignupForm[username]' => 'tester', + 'SignupForm[email]' => 'tester.email@example.com', + 'SignupForm[password]' => 'tester_password', + ]); + + $I->seeRecord('common\models\User', [ + 'username' => 'tester', + 'email' => 'tester.email@example.com', + ]); + + $I->see('Logout (tester)', 'form button[type=submit]'); + } +} diff --git a/frontend/tests/functional/_bootstrap.php b/frontend/tests/functional/_bootstrap.php new file mode 100755 index 0000000..30ed54b --- /dev/null +++ b/frontend/tests/functional/_bootstrap.php @@ -0,0 +1,16 @@ + 'davert']); + * ``` + * + * In Cests + * + * ```php + * \Codeception\Util\Fixtures::get('user1'); + * ``` + */ \ No newline at end of file diff --git a/frontend/tests/unit.suite.yml b/frontend/tests/unit.suite.yml new file mode 100755 index 0000000..27f2907 --- /dev/null +++ b/frontend/tests/unit.suite.yml @@ -0,0 +1,6 @@ +class_name: UnitTester +modules: + enabled: + - Yii2: + part: [orm, email, fixtures] + - Asserts diff --git a/frontend/tests/unit/_bootstrap.php b/frontend/tests/unit/_bootstrap.php new file mode 100755 index 0000000..e432ce5 --- /dev/null +++ b/frontend/tests/unit/_bootstrap.php @@ -0,0 +1,16 @@ + 'davert']); + * ``` + * + * In Tests + * + * ```php + * \Codeception\Util\Fixtures::get('user1'); + * ``` + */ diff --git a/frontend/tests/unit/models/ContactFormTest.php b/frontend/tests/unit/models/ContactFormTest.php new file mode 100755 index 0000000..acdf9db --- /dev/null +++ b/frontend/tests/unit/models/ContactFormTest.php @@ -0,0 +1,32 @@ +attributes = [ + 'name' => 'Tester', + 'email' => 'tester@example.com', + 'subject' => 'very important letter subject', + 'body' => 'body of current message', + ]; + + expect_that($model->sendEmail('admin@example.com')); + + // using Yii2 module actions to check email was sent + $this->tester->seeEmailIsSent(); + + $emailMessage = $this->tester->grabLastSentEmail(); + expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface'); + expect($emailMessage->getTo())->hasKey('admin@example.com'); + expect($emailMessage->getFrom())->hasKey('tester@example.com'); + expect($emailMessage->getSubject())->equals('very important letter subject'); + expect($emailMessage->toString())->contains('body of current message'); + } +} diff --git a/frontend/tests/unit/models/PasswordResetRequestFormTest.php b/frontend/tests/unit/models/PasswordResetRequestFormTest.php new file mode 100755 index 0000000..eba7203 --- /dev/null +++ b/frontend/tests/unit/models/PasswordResetRequestFormTest.php @@ -0,0 +1,59 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::className(), + 'dataFile' => codecept_data_dir() . 'user.php' + ] + ]); + } + + public function testSendMessageWithWrongEmailAddress() + { + $model = new PasswordResetRequestForm(); + $model->email = 'not-existing-email@example.com'; + expect_not($model->sendEmail()); + } + + public function testNotSendEmailsToInactiveUser() + { + $user = $this->tester->grabFixture('user', 1); + $model = new PasswordResetRequestForm(); + $model->email = $user['email']; + expect_not($model->sendEmail()); + } + + public function testSendEmailSuccessfully() + { + $userFixture = $this->tester->grabFixture('user', 0); + + $model = new PasswordResetRequestForm(); + $model->email = $userFixture['email']; + $user = User::findOne(['password_reset_token' => $userFixture['password_reset_token']]); + + expect_that($model->sendEmail()); + expect_that($user->password_reset_token); + + $emailMessage = $this->tester->grabLastSentEmail(); + expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface'); + expect($emailMessage->getTo())->hasKey($model->email); + expect($emailMessage->getFrom())->hasKey(Yii::$app->params['supportEmail']); + } +} diff --git a/frontend/tests/unit/models/ResetPasswordFormTest.php b/frontend/tests/unit/models/ResetPasswordFormTest.php new file mode 100755 index 0000000..74929bf --- /dev/null +++ b/frontend/tests/unit/models/ResetPasswordFormTest.php @@ -0,0 +1,44 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::className(), + 'dataFile' => codecept_data_dir() . 'user.php' + ], + ]); + } + + public function testResetWrongToken() + { + $this->tester->expectException('yii\base\InvalidParamException', function() { + new ResetPasswordForm(''); + }); + + $this->tester->expectException('yii\base\InvalidParamException', function() { + new ResetPasswordForm('notexistingtoken_1391882543'); + }); + } + + public function testResetCorrectToken() + { + $user = $this->tester->grabFixture('user', 0); + $form = new ResetPasswordForm($user['password_reset_token']); + expect_that($form->resetPassword()); + } + +} diff --git a/frontend/tests/unit/models/SignupFormTest.php b/frontend/tests/unit/models/SignupFormTest.php new file mode 100755 index 0000000..23a3463 --- /dev/null +++ b/frontend/tests/unit/models/SignupFormTest.php @@ -0,0 +1,59 @@ +tester->haveFixtures([ + 'user' => [ + 'class' => UserFixture::className(), + 'dataFile' => codecept_data_dir() . 'user.php' + ] + ]); + } + + public function testCorrectSignup() + { + $model = new SignupForm([ + 'username' => 'some_username', + 'email' => 'some_email@example.com', + 'password' => 'some_password', + ]); + + $user = $model->signup(); + + expect($user)->isInstanceOf('common\models\User'); + + expect($user->username)->equals('some_username'); + expect($user->email)->equals('some_email@example.com'); + expect($user->validatePassword('some_password'))->true(); + } + + public function testNotCorrectSignup() + { + $model = new SignupForm([ + 'username' => 'troy.becker', + 'email' => 'nicolas.dianna@hotmail.com', + 'password' => 'some_password', + ]); + + expect_not($model->signup()); + expect_that($model->getErrors('username')); + expect_that($model->getErrors('email')); + + expect($model->getFirstError('username')) + ->equals('This username has already been taken.'); + expect($model->getFirstError('email')) + ->equals('This email address has already been taken.'); + } +} diff --git a/frontend/views/combat/index.php b/frontend/views/combat/index.php new file mode 100755 index 0000000..2e5a5a1 --- /dev/null +++ b/frontend/views/combat/index.php @@ -0,0 +1,97 @@ +title = Yii::t('app', 'Battle of WarShips!'); + +$curhpplayer = ceil(($session['usershiphp'] / $usership->strength)*100); +$curhpbot = ceil(($session['bothp'] / $usership->strength)*100); +?> + 'battle-form']); ?> +
    +

    !

    +
    +
    + + + + + + + + + + + + +
    +
    + user->identity->username; ?> [/strength ?>]
    +
    +
    + % HP +
    +
    +
    +
    + +
    +
    +

    Items:


    + hp.' +HP ['.$user_items->qnt.']
    '; + echo Html::submitButton(Yii::t('app', 'getHP'), ['class' => 'btn btn-primary', 'name' => 'gethp', 'value' => 'gethp']); + } + ?> +
    +
    +
    +
    + 'my-test']); ?> +
    '1', 'id' => 'radio1']); ?>
    +
    '2', 'id' => 'radio2']); ?>
    +
    '3', 'id' => 'radio3']); ?>
    +
    '4', 'id' => 'radio4']); ?>
    + +
    +
    +
    +
    + BotShip [/strength ?>]
    +
    +
    + % HP +
    +
    +
    +
    + +
    + +
    +

    + 'btn btn-primary', 'style' => 'width: 220px', 'name' => 'Attack', 'id' => 'battle-form', 'value' => 'Attack']) ?> +
    +
    +logs . '
    '; +} +?> +
    + \ No newline at end of file diff --git a/frontend/views/combat/lose.php b/frontend/views/combat/lose.php new file mode 100755 index 0000000..9b8812f --- /dev/null +++ b/frontend/views/combat/lose.php @@ -0,0 +1,14 @@ +title = 'Battle Win!'; +?> +
    +
    +

    !

    +
    +
    + ! :( +
    +
    diff --git a/frontend/views/combat/win.php b/frontend/views/combat/win.php new file mode 100755 index 0000000..c1bfc53 --- /dev/null +++ b/frontend/views/combat/win.php @@ -0,0 +1,14 @@ +title = 'Battle Win!'; +?> +
    +
    +

    !

    +
    +
    + ! :) +
    +
    diff --git a/frontend/views/dock/index.php b/frontend/views/dock/index.php new file mode 100644 index 0000000..fbc59ec --- /dev/null +++ b/frontend/views/dock/index.php @@ -0,0 +1,27 @@ + + +
    +

    User Dock

    +
    +

    Ships

    +
    +
    +

    + +

    + +
    +
    + ship->name; ?> | user->username; ?> +
    + +

    +
    \ No newline at end of file diff --git a/frontend/views/layouts/main.php b/frontend/views/layouts/main.php new file mode 100755 index 0000000..af8d676 --- /dev/null +++ b/frontend/views/layouts/main.php @@ -0,0 +1,87 @@ + +beginPage() ?> + + + + + + + <?= Html::encode(Yii::t('app', $this->title)) ?> + head() ?> + + +beginBody() ?> +
    + Yii::t('app', 'Battle Ships'), + 'brandUrl' => Yii::$app->homeUrl, + 'options' => [ + 'class' => 'navbar-inverse navbar-fixed-top', + ], + ]); + $menuItems = [ + ['label' => Yii::t('app', 'Home'), 'url' => ['/site']], + ['label' => Yii::t('app', 'Reg Battle'), 'url' => ['/list']], + ['label' => Yii::t('app', 'Toprank'), 'url' => ['/toprank']], + ['label' => Yii::t('app', 'Shop'), 'url' => ['/shop']], + ]; + if (Yii::$app->user->isGuest) { + $menuItems[] = ['label' => Yii::t('app', 'Signup'), 'url' => ['/site/signup']]; + $menuItems[] = ['label' => Yii::t('app', 'Login'), 'url' => ['/site/login']]; + } else { + $menuItems[] = '
  • ' + . Html::beginForm(['/site/logout'], 'post') + . Html::submitButton( + Yii::t('app', 'Logout') . '(' . Yii::$app->user->identity->username . ')', + ['class' => 'btn btn-link logout'] + ) + . Html::endForm() + . '
  • '; + } + echo Nav::widget([ + 'options' => ['class' => 'navbar-nav navbar-right'], + 'items' => $menuItems, + ]); + NavBar::end(); + ?> + + +
    +
    +
    +
    +
    + isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [], + ]) ?> + + +
    +
    + +
    +
    +

    © GeekHub 2016-

    + +

    render('main/select-language') ?> |

    +
    +
    + +endBody() ?> + + +endPage() ?> diff --git a/frontend/views/layouts/main/select-language.php b/frontend/views/layouts/main/select-language.php new file mode 100755 index 0000000..a9bb2e5 --- /dev/null +++ b/frontend/views/layouts/main/select-language.php @@ -0,0 +1,15 @@ +language == 'ru'): + echo Html::a('Go to English', array_merge( + \Yii::$app->request->get(), + [\Yii::$app->controller->route, 'language' => 'en'] + )); +else: + echo Html::a('Перейти на русский', array_merge( + \Yii::$app->request->get(), + [\Yii::$app->controller->route, 'language' => 'ru'] + )); +endif; \ No newline at end of file diff --git a/frontend/views/list/index.php b/frontend/views/list/index.php new file mode 100644 index 0000000..b1dbc71 --- /dev/null +++ b/frontend/views/list/index.php @@ -0,0 +1,13 @@ + +
    +

    !

    +
    +

    + 'battle-form']); ?> + 'btn btn-outlined btn-primary', 'name' => 'start', 'id' => 'start-battle', 'value' => 'Start']) ?> + +

    diff --git a/frontend/views/logs/index.php b/frontend/views/logs/index.php new file mode 100644 index 0000000..379ed21 --- /dev/null +++ b/frontend/views/logs/index.php @@ -0,0 +1,17 @@ +title = 'Battle logs'; +?> +

    logs

    + +

    + Viewing Full Battle Log


    '; + echo '
    '.$model->bid.' | '.$model->date.'
    '; + echo '
    '.$model->logs .''; + } + } + ?> +

    diff --git a/frontend/views/shop/_list.php b/frontend/views/shop/_list.php new file mode 100755 index 0000000..9a66c29 --- /dev/null +++ b/frontend/views/shop/_list.php @@ -0,0 +1,11 @@ +
    +
    + +

    +

    name ?>

    +

    +
    +
    +
    + Уровень: lvl ?> +
    \ No newline at end of file diff --git a/frontend/views/shop/index.php b/frontend/views/shop/index.php new file mode 100755 index 0000000..0cbdae6 --- /dev/null +++ b/frontend/views/shop/index.php @@ -0,0 +1,19 @@ +title = Yii::t('app', 'Battle Shop'); +$this->params['breadcrumbs'][] = $this->title; +?> +
    +


    +
    +

    +

    + $shopProvider, + 'layout' => '{items}', + 'options' => ['class' => 'projects-flow'], + 'itemOptions' => ['class' => 'item'], + 'itemView' => '_list' + ]) ?> +
    +

    diff --git a/frontend/views/site/about.php b/frontend/views/site/about.php new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/frontend/views/site/about.php @@ -0,0 +1 @@ + diff --git a/frontend/views/site/contact.php b/frontend/views/site/contact.php new file mode 100755 index 0000000..dc48410 --- /dev/null +++ b/frontend/views/site/contact.php @@ -0,0 +1,45 @@ +title = 'Contact'; +$this->params['breadcrumbs'][] = $this->title; +?> +
    +

    title) ?>

    + +

    + If you have business inquiries or other questions, please fill out the following form to contact us. Thank you. +

    + +
    +
    + 'contact-form']); ?> + + field($model, 'name')->textInput(['autofocus' => true]) ?> + + field($model, 'email') ?> + + field($model, 'subject') ?> + + field($model, 'body')->textarea(['rows' => 6]) ?> + + field($model, 'verifyCode')->widget(Captcha::className(), [ + 'template' => '
    {image}
    {input}
    ', + ]) ?> + +
    + 'btn btn-primary', 'name' => 'contact-button']) ?> +
    + + +
    +
    + +
    diff --git a/frontend/views/site/error.php b/frontend/views/site/error.php new file mode 100755 index 0000000..0ba2574 --- /dev/null +++ b/frontend/views/site/error.php @@ -0,0 +1,27 @@ +title = $name; +?> +
    + +

    title) ?>

    + +
    + +
    + +

    + The above error occurred while the Web server was processing your request. +

    +

    + Please contact us if you think this is a server error. Thank you. +

    + +
    diff --git a/frontend/views/site/index.php b/frontend/views/site/index.php new file mode 100755 index 0000000..5a6dfdd --- /dev/null +++ b/frontend/views/site/index.php @@ -0,0 +1,16 @@ +title = 'BattleShips GunS!'; +?> +
    + +
    +

    You are Welcome!

    +
    + +
    + +
    +
    diff --git a/frontend/views/site/login.php b/frontend/views/site/login.php new file mode 100755 index 0000000..d9808a5 --- /dev/null +++ b/frontend/views/site/login.php @@ -0,0 +1,39 @@ +title = Yii::t('app', 'Auth'); +$this->params['breadcrumbs'][] = $this->title; +?> + diff --git a/frontend/views/site/main.php b/frontend/views/site/main.php new file mode 100755 index 0000000..81852bb --- /dev/null +++ b/frontend/views/site/main.php @@ -0,0 +1,139 @@ +title = Yii::t('app', 'Battle of WarShips!'); +?> +
    +
    +

    , user->identity->username; ?>!

    +

    +
    +
    + + + + + + +
    +
    +[ ' . $shipname->name . ' ]'; + echo '
    100% HP
    '; + echo 'name . '.png>'; + echo '
    '; + echo Yii::t('app', 'Strength').': ' . $model->strength . ' | '.Yii::t('app', 'Experience').': ' . $model->exp . ' | '.Yii::t('app', 'Credits').': ' . $user->credits . '.
    '; +?> +
    +
    +

    :

    +
    + '.$user->win.'
    '; + echo Yii::t('app', 'LOSE').': '.$user->lose.'
    '; + echo Yii::t('app', 'DRAW').': '.$user->draw.'
    '; + ?> +
    +
    +
    + " . Yii::t('app', 'Available Mods') . "
    "; + if (($model->exp_gun) != 1) { + if (($model->exp) >= ($avaible_mods->exp_gun)) { + $form = ActiveForm::begin(['id' => 'exp_mod_gun']); + echo " - " . Yii::t('app', 'Modified Main Battery') . " " . Html::submitButton(Yii::t('app', 'Explore'), ['class' => 'btn btn-lg btn-success', 'style' => 'width: 140px; height: 25px; padding: 0px 3px 1px 3px', 'name' => 'expmodgun', 'id' => 'exp_mod_gun', 'value' => 'Explore']); + ActiveForm::end(); + } else { + echo " - " . Yii::t('app', 'Modified Main Battery') . ""; + } + } else { + if (($model->mod_gun) != 1) { + $form = ActiveForm::begin(['id' => 'buy_mod_gun']); + echo " - " . Yii::t('app', 'Modified Main Battery') . " - Already explored ".Html::submitButton(Yii::t('app', 'Buy'), ['class' => 'btn btn-primary', 'style' => 'width: 70px; height: 25px; padding: 0px 3px 1px 3px', 'name' => 'buymodgun', 'id' => 'buy_mod_gun', 'value' => 'Buy']); + ActiveForm::end(); + } else { + echo " - " . Yii::t('app', 'Modified Main Battery') . " - Installed "; + } + } + echo "
    "; + if (($model->exp_tower) != 1) { + if (($model->exp) >= ($avaible_mods->exp_tower)) { + $form = ActiveForm::begin(['id' => 'exp_mod_tower']); + echo " - " . Yii::t('app', 'Improved Hit Points(HP)') . " " . Html::submitButton(Yii::t('app', 'Explore'), ['class' => 'btn btn-lg btn-success', 'style' => 'width: 140px; height: 25px; padding: 0px 3px 1px 3px', 'name' => 'expmodtower', 'id' => 'exp_mod_tower', 'value' => 'Explore']); + ActiveForm::end(); + } else { + echo " - " . Yii::t('app', 'Improved Hit Points(HP)') . ""; + } + } else { + if(($model->mod_tower) != 1) { + $form = ActiveForm::begin(['id' => 'buy_mod_tower']); + echo " - " . Yii::t('app', 'Improved Hit Points(HP)') . " - Already explored ".Html::submitButton(Yii::t('app', 'Buy'), ['class' => 'btn btn-primary', 'style' => 'width: 70px; height: 25px; padding: 0px 3px 1px 3px', 'name' => 'buymodtower', 'id' => 'buy_mod_tower', 'value' => 'Buy']); + ActiveForm::end(); + } else { + echo " - " . Yii::t('app', 'Improved Hit Points(HP)') . " Installed"; + } + } + } + ?> +
    +



    +
    +

    +
    +
    + stock_gun == 1 && $model->mod_gun == 0) { + echo ''.Yii::t('app', 'Stock Gun').' - '; + } elseif($model->stock_gun == 0 && $model->mod_gun == 1) { + echo ''.Yii::t('app', 'Modificate Gun').' - '; + } + if($model->stock_tower == 1 && $model->mod_tower == 0) { + echo ''.Yii::t('app', 'Stock Tower').' - '; + } elseif($model->stock_tower == 0 && $model->mod_tower == 1) { + echo ''.Yii::t('app', 'Modificate Tower').' - '; + } + + } else { + echo "

    ".Yii::t('app', 'Please, chose your first Warship')."!

    "; +?> + + + + + +
    + 'shipone']); ?> +
    + +
    +

    +
    +
    +
    + 'btn btn-primary', 'style' => 'width: 320px', 'name' => 'shipfirst', 'id' => 'shipone', 'value' => '2', 'width' => 50]) ?> +
    + +
    + 'shiptwo']); ?> +
    + +
    +

    +
    +
    +
    + 'btn btn-primary', 'style' => 'width: 320px', 'name' => 'shipsecond', 'id' => 'shiptwo', 'value' => '4', 'width' => 150]) ?> +
    + +
    + +
    +
    +
    diff --git a/frontend/views/site/requestPasswordResetToken.php b/frontend/views/site/requestPasswordResetToken.php new file mode 100755 index 0000000..9f6822e --- /dev/null +++ b/frontend/views/site/requestPasswordResetToken.php @@ -0,0 +1,31 @@ +title = 'Request password reset'; +$this->params['breadcrumbs'][] = $this->title; +?> +
    +

    title) ?>

    + +

    Please fill out your email. A link to reset password will be sent there.

    + +
    +
    + 'request-password-reset-form']); ?> + + field($model, 'email')->textInput(['autofocus' => true]) ?> + +
    + 'btn btn-primary']) ?> +
    + + +
    +
    +
    diff --git a/frontend/views/site/resetPassword.php b/frontend/views/site/resetPassword.php new file mode 100755 index 0000000..36ef452 --- /dev/null +++ b/frontend/views/site/resetPassword.php @@ -0,0 +1,31 @@ +title = 'Reset password'; +$this->params['breadcrumbs'][] = $this->title; +?> +
    +

    title) ?>

    + +

    Please choose your new password:

    + +
    +
    + 'reset-password-form']); ?> + + field($model, 'password')->passwordInput(['autofocus' => true]) ?> + +
    + 'btn btn-primary']) ?> +
    + + +
    +
    +
    diff --git a/frontend/views/site/signup.php b/frontend/views/site/signup.php new file mode 100755 index 0000000..d57438a --- /dev/null +++ b/frontend/views/site/signup.php @@ -0,0 +1,44 @@ +title = Yii::t('app', 'Reg'); +$this->params['breadcrumbs'][] = $this->title; +?> + + + + +
    +

    title) ?>

    + +

    :

    + +
    +
    + 'form-signup']); ?> + + field($model, 'username')->textInput(['autofocus' => true]) ?> + + field($model, 'email') ?> + + field($model, 'password')->passwordInput() ?> + +
    + 'btn btn-primary', 'name' => 'signup-button']) ?> +
    + + +
    +
    + + +
    diff --git a/frontend/views/toprank/index.php b/frontend/views/toprank/index.php new file mode 100644 index 0000000..4555612 --- /dev/null +++ b/frontend/views/toprank/index.php @@ -0,0 +1,42 @@ + +

    !

    +
    +

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    #

    user->username ?>

    ship->name ?> [ship->lvl ?>]user->win ?>user->lose ?>user->draw ?>mod_gun !=1) { echo ""; } else { echo ""; } ?>mod_tower !=1) { echo ""; } else { echo ""; } ?>
    +
    +

    diff --git a/frontend/web/.gitignore b/frontend/web/.gitignore new file mode 100755 index 0000000..25c74e6 --- /dev/null +++ b/frontend/web/.gitignore @@ -0,0 +1,2 @@ +/index.php +/index-test.php diff --git a/frontend/web/.htaccess b/frontend/web/.htaccess new file mode 100755 index 0000000..1426180 --- /dev/null +++ b/frontend/web/.htaccess @@ -0,0 +1,10 @@ +Options +FollowSymLinks + +RewriteEngine on + +# if a directory or a file exists, use it directly +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d + +# otherwise forward it to index.php +RewriteRule . index.php diff --git a/frontend/web/assets/.gitignore b/frontend/web/assets/.gitignore new file mode 100755 index 0000000..d6b7ef3 --- /dev/null +++ b/frontend/web/assets/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/frontend/web/css/site.css b/frontend/web/css/site.css new file mode 100755 index 0000000..269da07 --- /dev/null +++ b/frontend/web/css/site.css @@ -0,0 +1,444 @@ +html, +body { + height: 100%; + background: url('../img/bg.jpg'); +} + +l-separator{ + width:100%; + padding:0; + z-index:-1; +} + +l-separator__header{ + position:absolute; + margin:0; + left:0; + bottom:-33px; +} + +.b-separator{ + background:url('../img/separator.png') no-repeat scroll 0 0; +} + +.b-separator-right{ + background:url('../img/separator_1.png') no-repeat scroll 100% 0 transparent; + height:81px; + width:349px; + float:right; + margin-right:-349px; + position:relative; +} + +.wrap { + min-height: 100%; + height: auto; + margin: 0 auto -60px; + padding: 0 0 60px; +} + +.wrap > .container { + padding: 70px 15px 20px; +} + +.toprank { + font-weight: bold; + padding: 3px 4px; + text-align: left; +} +.toprank td { + padding: 4px 10px; +} + +.toph { + border-bottom:3px solid lightblue; +} + +.footer { + height: 60px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + padding-top: 20px; +} + +.wrap { + min-height: 100%; + height: auto; + margin: 0 auto -60px; + padding: 0 0 60px; +} + +.wrap > .container { + padding: 70px 15px 20px; +} + +.footer { + height: 60px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + padding-top: 20px; +} + +.jumbotron { + text-align: center; + background-color: transparent; +} + +.jumbotron .btn { + font-size: 21px; + padding: 14px 24px; +} + +.not-set { + color: #c55; + font-style: italic; +} + +/* add sorting icons to gridview sort links */ +a.asc:after, a.desc:after { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + padding-left: 5px; +} + +a.asc:after { + content: /*"\e113"*/ "\e151"; +} + +a.desc:after { + content: /*"\e114"*/ "\e152"; +} + +.sort-numerical a.asc:after { + content: "\e153"; +} + +.sort-numerical a.desc:after { + content: "\e154"; +} + +.sort-ordinal a.asc:after { + content: "\e155"; +} + +.sort-ordinal a.desc:after { + content: "\e156"; +} + +.grid-view th { + white-space: nowrap; +} + +.hint-block { + display: block; + margin-top: 5px; + color: #999; +} + +.error-summary { + color: #a94442; + background: #fdf7f7; + border-left: 3px solid #eed3d7; + padding: 10px 20px; + margin: 0 0 15px 0; +} + +/* align the logout "link" (button in form) of the navbar */ +.nav li > form > button.logout { + padding: 15px; + border: none; +} + +@media(max-width:767px) { + .nav li > form > button.logout { + display:block; + text-align: left; + width: 100%; + padding: 10px 15px; + } +} + +.nav > li > form > button.logout:focus, +.nav > li > form > button.logout:hover { + text-decoration: none; +} + +.nav > li > form > button.logout:focus { + outline: none; +} + +.CodeMirror { + border: 1px solid #eee; +} + +.project-card { + padding: 2rem; + background: rgba(128, 128, 128, .1); + position: relative; + margin: 0 1rem 1rem 0; +} + +.featured { + color: #ffcc4b; +} + +.label.status-deleted { + background: rgba(200, 10, 10, .5); +} + +.label.status-draft { + background: rgba(10, 10, 200, .8); +} + +.project-card { + display: inline-block; +} + +.project-card img { + border: 2px solid transparent; +} + +.project-card.status-deleted img { + border: 2px solid rgba(200, 10, 10, .5); +} + +.project-card.status-draft img { + border: 2px solid rgba(10, 10, 200, .5); +} + +.project-card img { + background: rgba(128, 128, 128, .1); +} + +.project-card h1 { + font-size: large; +} + +.authors { + list-style: none; + padding: 0; +} + +.authors li { + display: inline-block; +} + +.author img { + border-radius: 32px; +} + +.tags { + list-style: none; + padding: 0; +} + +.tags li { + display: inline-block; + padding: .5rem; + background: #eedc43; + border-radius: .25em; +} + +.project-view .content { + margin: 4rem 0 1rem 0; + padding-bottom: 2rem; + border-bottom: 1px solid #eee; +} + +.project-view .images { + margin-top: 2rem; +} + +.project-view .image a { + display: inline-block; + padding: 2rem; + background: rgba(128, 128, 128, .1); +} + +.project-view .image { + position: relative; + display: inline-block; +} + +.project-view .image .delete { + position: absolute; + top: 0; + right: 0; + font-size: 150%; + background: #fff; + border-radius: 10rem; + cursor: pointer; +} + +.project-view .image .delete:hover { + color: #f00; +} + +.projects-flow { + display: flex; + flex-flow: row wrap; + justify-content: flex-start; + align-content: space-around; + align-items: flex-start; +} + +.projects-flow .item { + min-width: 25em; + margin: 1em; + flex: 1 0 0; +} + +.pagination { + width: 100%; +} + +.row_b { + padding: 6px; + border:1px solid #0d3349; +} + +.radio { + padding-left: 20px; +} +.radio label { + display: inline-block; + position: relative; + padding-left: 5px; +} +.radio label::before { + content: ""; + display: inline-block; + position: absolute; + width: 17px; + height: 17px; + left: 0; + margin-left: -20px; + border: 1px solid #cccccc; + border-radius: 50%; + background-color: #fff; + -webkit-transition: border 0.15s ease-in-out; + -o-transition: border 0.15s ease-in-out; + transition: border 0.15s ease-in-out; +} +.radio label::after { + display: inline-block; + position: absolute; + content: " "; + width: 11px; + height: 11px; + left: 3px; + top: 3px; + margin-left: -20px; + border-radius: 50%; + background-color: #555555; + -webkit-transform: scale(0, 0); + -ms-transform: scale(0, 0); + -o-transform: scale(0, 0); + transform: scale(0, 0); + -webkit-transition: -webkit-transform 0.1s cubic-bezier(0.8, -0.33, 0.2, 1.33); + -moz-transition: -moz-transform 0.1s cubic-bezier(0.8, -0.33, 0.2, 1.33); + -o-transition: -o-transform 0.1s cubic-bezier(0.8, -0.33, 0.2, 1.33); + transition: transform 0.1s cubic-bezier(0.8, -0.33, 0.2, 1.33); +} +.radio input[type="radio"] { + opacity: 0; +} +.radio input[type="radio"]:focus + label::before { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.radio input[type="radio"]:checked + label::after { + -webkit-transform: scale(1, 1); + -ms-transform: scale(1, 1); + -o-transform: scale(1, 1); + transform: scale(1, 1); +} +.radio input[type="radio"]:disabled + label { + opacity: 0.65; +} +.radio input[type="radio"]:disabled + label::before { + cursor: not-allowed; +} +.radio.radio-inline { + margin-top: 0; +} + +.radio-primary input[type="radio"] + label::after { + background-color: #428bca; +} +.radio-primary input[type="radio"]:checked + label::before { + border-color: #428bca; +} +.radio-primary input[type="radio"]:checked + label::after { + background-color: #428bca; +} + +.radio-danger input[type="radio"] + label::after { + background-color: #d9534f; +} +.radio-danger input[type="radio"]:checked + label::before { + border-color: #d9534f; +} +.radio-danger input[type="radio"]:checked + label::after { + background-color: #d9534f; +} + +.radio-info input[type="radio"] + label::after { + background-color: #5bc0de; +} +.radio-info input[type="radio"]:checked + label::before { + border-color: #5bc0de; +} +.radio-info input[type="radio"]:checked + label::after { + background-color: #5bc0de; +} + +.radio-warning input[type="radio"] + label::after { + background-color: #f0ad4e; +} +.radio-warning input[type="radio"]:checked + label::before { + border-color: #f0ad4e; +} +.radio-warning input[type="radio"]:checked + label::after { + background-color: #f0ad4e; +} + +.radio-success input[type="radio"] + label::after { + background-color: #5cb85c; +} +.radio-success input[type="radio"]:checked + label::before { + border-color: #5cb85c; +} +.radio-success input[type="radio"]:checked + label::after { + background-color: #5cb85c; +} + +.btn-outlined { + border-radius: 0; + -webkit-transition: all 0.3s; + -moz-transition: all 0.3s; + transition: all 0.3s; +} +.btn-outlined.btn-primary { + background: none; + border: 1px solid #428bca; + color: #428bca; +} +.btn-outlined.btn-primary:hover, +.btn-outlined.btn-primary:active { + color: #FFF; + background: #428bca; + border-color: #428bca; +} + +.dock { + height: 100%; + width: 100%; + background: url('../img/dock_bg.jpg') no-repeat; +} \ No newline at end of file diff --git a/frontend/web/favicon.ico b/frontend/web/favicon.ico new file mode 100755 index 0000000..580ed73 Binary files /dev/null and b/frontend/web/favicon.ico differ diff --git a/frontend/web/img/1.png b/frontend/web/img/1.png new file mode 100755 index 0000000..319c477 Binary files /dev/null and b/frontend/web/img/1.png differ diff --git a/frontend/web/img/2.png b/frontend/web/img/2.png new file mode 100755 index 0000000..a7e3527 Binary files /dev/null and b/frontend/web/img/2.png differ diff --git a/frontend/web/img/bg.jpg b/frontend/web/img/bg.jpg new file mode 100644 index 0000000..37dd76c Binary files /dev/null and b/frontend/web/img/bg.jpg differ diff --git a/frontend/web/img/dock_bg.jpg b/frontend/web/img/dock_bg.jpg new file mode 100644 index 0000000..e976e1d Binary files /dev/null and b/frontend/web/img/dock_bg.jpg differ diff --git a/frontend/web/img/mod_gun.png b/frontend/web/img/mod_gun.png new file mode 100755 index 0000000..d93d354 Binary files /dev/null and b/frontend/web/img/mod_gun.png differ diff --git a/frontend/web/img/mod_tower.png b/frontend/web/img/mod_tower.png new file mode 100755 index 0000000..a603922 Binary files /dev/null and b/frontend/web/img/mod_tower.png differ diff --git a/frontend/web/img/projectgame_bg.jpg b/frontend/web/img/projectgame_bg.jpg new file mode 100755 index 0000000..ed56a22 Binary files /dev/null and b/frontend/web/img/projectgame_bg.jpg differ diff --git a/frontend/web/img/projectgame_bg1 b/frontend/web/img/projectgame_bg1 new file mode 100755 index 0000000..2fd8d27 Binary files /dev/null and b/frontend/web/img/projectgame_bg1 differ diff --git a/frontend/web/img/projectgame_bg1.jpg b/frontend/web/img/projectgame_bg1.jpg new file mode 100755 index 0000000..2fd8d27 Binary files /dev/null and b/frontend/web/img/projectgame_bg1.jpg differ diff --git a/frontend/web/img/projectgame_bg_1.jpg b/frontend/web/img/projectgame_bg_1.jpg new file mode 100755 index 0000000..27e79bc Binary files /dev/null and b/frontend/web/img/projectgame_bg_1.jpg differ diff --git a/frontend/web/img/separator.png b/frontend/web/img/separator.png new file mode 100644 index 0000000..5d32d8d Binary files /dev/null and b/frontend/web/img/separator.png differ diff --git a/frontend/web/img/separator_1.png b/frontend/web/img/separator_1.png new file mode 100644 index 0000000..5d32d8d Binary files /dev/null and b/frontend/web/img/separator_1.png differ diff --git a/frontend/web/img/ships/Albany.png b/frontend/web/img/ships/Albany.png new file mode 100755 index 0000000..f98f54f Binary files /dev/null and b/frontend/web/img/ships/Albany.png differ diff --git a/frontend/web/img/ships/Arizona.png b/frontend/web/img/ships/Arizona.png new file mode 100755 index 0000000..703d673 Binary files /dev/null and b/frontend/web/img/ships/Arizona.png differ diff --git a/frontend/web/img/ships/Atago.png b/frontend/web/img/ships/Atago.png new file mode 100755 index 0000000..50222f8 Binary files /dev/null and b/frontend/web/img/ships/Atago.png differ diff --git a/frontend/web/img/ships/Atlanta.png b/frontend/web/img/ships/Atlanta.png new file mode 100755 index 0000000..39a7440 Binary files /dev/null and b/frontend/web/img/ships/Atlanta.png differ diff --git a/frontend/web/img/ships/Aurora.png b/frontend/web/img/ships/Aurora.png new file mode 100755 index 0000000..80a6003 Binary files /dev/null and b/frontend/web/img/ships/Aurora.png differ diff --git a/frontend/web/img/ships/Bliskavutsya.png b/frontend/web/img/ships/Bliskavutsya.png new file mode 100755 index 0000000..fb0de21 Binary files /dev/null and b/frontend/web/img/ships/Bliskavutsya.png differ diff --git a/frontend/web/img/ships/Campbeltown.png b/frontend/web/img/ships/Campbeltown.png new file mode 100755 index 0000000..79977f0 Binary files /dev/null and b/frontend/web/img/ships/Campbeltown.png differ diff --git a/frontend/web/img/ships/Diana.png b/frontend/web/img/ships/Diana.png new file mode 100755 index 0000000..225ef46 Binary files /dev/null and b/frontend/web/img/ships/Diana.png differ diff --git a/frontend/web/img/ships/Emden.png b/frontend/web/img/ships/Emden.png new file mode 100755 index 0000000..e0a25da Binary files /dev/null and b/frontend/web/img/ships/Emden.png differ diff --git a/frontend/web/img/ships/Ishiz.png b/frontend/web/img/ships/Ishiz.png new file mode 100755 index 0000000..feed962 Binary files /dev/null and b/frontend/web/img/ships/Ishiz.png differ diff --git a/frontend/web/img/ships/KoenigAlbert.png b/frontend/web/img/ships/KoenigAlbert.png new file mode 100755 index 0000000..112460f Binary files /dev/null and b/frontend/web/img/ships/KoenigAlbert.png differ diff --git a/frontend/web/img/ships/Leningrad.png b/frontend/web/img/ships/Leningrad.png new file mode 100644 index 0000000..66f9ee9 Binary files /dev/null and b/frontend/web/img/ships/Leningrad.png differ diff --git a/frontend/web/img/ships/Marblehead.png b/frontend/web/img/ships/Marblehead.png new file mode 100755 index 0000000..6238dc7 Binary files /dev/null and b/frontend/web/img/ships/Marblehead.png differ diff --git a/frontend/web/img/ships/MixailKytyzov.png b/frontend/web/img/ships/MixailKytyzov.png new file mode 100755 index 0000000..00a325a Binary files /dev/null and b/frontend/web/img/ships/MixailKytyzov.png differ diff --git a/frontend/web/img/ships/Molotov.png b/frontend/web/img/ships/Molotov.png new file mode 100755 index 0000000..7d72ea4 Binary files /dev/null and b/frontend/web/img/ships/Molotov.png differ diff --git a/frontend/web/img/ships/Murmansk.png b/frontend/web/img/ships/Murmansk.png new file mode 100755 index 0000000..bbcefa8 Binary files /dev/null and b/frontend/web/img/ships/Murmansk.png differ diff --git a/frontend/web/img/ships/RedCrimea.png b/frontend/web/img/ships/RedCrimea.png new file mode 100755 index 0000000..462945e Binary files /dev/null and b/frontend/web/img/ships/RedCrimea.png differ diff --git a/frontend/web/img/ships/Simple.png b/frontend/web/img/ships/Simple.png new file mode 100755 index 0000000..319c477 Binary files /dev/null and b/frontend/web/img/ships/Simple.png differ diff --git a/frontend/web/img/ships/Smith.png b/frontend/web/img/ships/Smith.png new file mode 100755 index 0000000..64b4d00 Binary files /dev/null and b/frontend/web/img/ships/Smith.png differ diff --git a/frontend/web/img/ships/Tachibana.png b/frontend/web/img/ships/Tachibana.png new file mode 100755 index 0000000..3342e49 Binary files /dev/null and b/frontend/web/img/ships/Tachibana.png differ diff --git a/frontend/web/img/ships/Texas.png b/frontend/web/img/ships/Texas.png new file mode 100755 index 0000000..7a1e939 Binary files /dev/null and b/frontend/web/img/ships/Texas.png differ diff --git a/frontend/web/img/ships/Tirpitz.png b/frontend/web/img/ships/Tirpitz.png new file mode 100755 index 0000000..26a08ac Binary files /dev/null and b/frontend/web/img/ships/Tirpitz.png differ diff --git a/frontend/web/img/ships/Warspite.png b/frontend/web/img/ships/Warspite.png new file mode 100644 index 0000000..cae2172 Binary files /dev/null and b/frontend/web/img/ships/Warspite.png differ diff --git a/frontend/web/img/ships/belfast.png b/frontend/web/img/ships/belfast.png new file mode 100755 index 0000000..100efdc Binary files /dev/null and b/frontend/web/img/ships/belfast.png differ diff --git a/frontend/web/img/stock_gun.png b/frontend/web/img/stock_gun.png new file mode 100755 index 0000000..7ea8921 Binary files /dev/null and b/frontend/web/img/stock_gun.png differ diff --git a/frontend/web/img/stock_tower.png b/frontend/web/img/stock_tower.png new file mode 100755 index 0000000..c333241 Binary files /dev/null and b/frontend/web/img/stock_tower.png differ diff --git a/frontend/web/robots.txt b/frontend/web/robots.txt new file mode 100755 index 0000000..6f27bb6 --- /dev/null +++ b/frontend/web/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: \ No newline at end of file diff --git a/init b/init new file mode 100755 index 0000000..7aaf086 --- /dev/null +++ b/init @@ -0,0 +1,299 @@ +#!/usr/bin/env php + + * + * @link http://www.yiiframework.com/ + * @copyright Copyright (c) 2008 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +if (!extension_loaded('openssl')) { + die('The OpenSSL PHP extension is required by Yii2.'); +} + +$params = getParams(); +$root = str_replace('\\', '/', __DIR__); +$envs = require("$root/environments/index.php"); +$envNames = array_keys($envs); + +echo "Yii Application Initialization Tool v1.0\n\n"; + +$envName = null; +if (empty($params['env']) || $params['env'] === '1') { + echo "Which environment do you want the application to be initialized in?\n\n"; + foreach ($envNames as $i => $name) { + echo " [$i] $name\n"; + } + echo "\n Your choice [0-" . (count($envs) - 1) . ', or "q" to quit] '; + $answer = trim(fgets(STDIN)); + + if (!ctype_digit($answer) || !in_array($answer, range(0, count($envs) - 1))) { + echo "\n Quit initialization.\n"; + exit(0); + } + + if (isset($envNames[$answer])) { + $envName = $envNames[$answer]; + } +} else { + $envName = $params['env']; +} + +if (!in_array($envName, $envNames)) { + $envsList = implode(', ', $envNames); + echo "\n $envName is not a valid environment. Try one of the following: $envsList. \n"; + exit(2); +} + +$env = $envs[$envName]; + +if (empty($params['env'])) { + echo "\n Initialize the application under '{$envNames[$answer]}' environment? [yes|no] "; + $answer = trim(fgets(STDIN)); + if (strncasecmp($answer, 'y', 1)) { + echo "\n Quit initialization.\n"; + exit(0); + } +} + +echo "\n Start initialization ...\n\n"; +$files = getFileList("$root/environments/{$env['path']}"); +if (isset($env['skipFiles'])) { + $skipFiles = $env['skipFiles']; + array_walk($skipFiles, function(&$value) use($env, $root) { $value = "$root/$value"; }); + $files = array_diff($files, array_intersect_key($env['skipFiles'], array_filter($skipFiles, 'file_exists'))); +} +$all = false; +foreach ($files as $file) { + if (!copyFile($root, "environments/{$env['path']}/$file", $file, $all, $params)) { + break; + } +} + +$callbacks = ['setCookieValidationKey', 'setWritable', 'setExecutable', 'createSymlink']; +foreach ($callbacks as $callback) { + if (!empty($env[$callback])) { + $callback($root, $env[$callback]); + } +} + +echo "\n ... initialization completed.\n\n"; + +function getFileList($root, $basePath = '') +{ + $files = []; + $handle = opendir($root); + while (($path = readdir($handle)) !== false) { + if ($path === '.git' || $path === '.svn' || $path === '.' || $path === '..') { + continue; + } + $fullPath = "$root/$path"; + $relativePath = $basePath === '' ? $path : "$basePath/$path"; + if (is_dir($fullPath)) { + $files = array_merge($files, getFileList($fullPath, $relativePath)); + } else { + $files[] = $relativePath; + } + } + closedir($handle); + return $files; +} + +function copyFile($root, $source, $target, &$all, $params) +{ + if (!is_file($root . '/' . $source)) { + echo " skip $target ($source not exist)\n"; + return true; + } + if (is_file($root . '/' . $target)) { + if (file_get_contents($root . '/' . $source) === file_get_contents($root . '/' . $target)) { + echo " unchanged $target\n"; + return true; + } + if ($all) { + echo " overwrite $target\n"; + } else { + echo " exist $target\n"; + echo " ...overwrite? [Yes|No|All|Quit] "; + + + $answer = !empty($params['overwrite']) ? $params['overwrite'] : trim(fgets(STDIN)); + if (!strncasecmp($answer, 'q', 1)) { + return false; + } else { + if (!strncasecmp($answer, 'y', 1)) { + echo " overwrite $target\n"; + } else { + if (!strncasecmp($answer, 'a', 1)) { + echo " overwrite $target\n"; + $all = true; + } else { + echo " skip $target\n"; + return true; + } + } + } + } + file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source)); + return true; + } + echo " generate $target\n"; + @mkdir(dirname($root . '/' . $target), 0777, true); + file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source)); + return true; +} + +function getParams() +{ + $rawParams = []; + if (isset($_SERVER['argv'])) { + $rawParams = $_SERVER['argv']; + array_shift($rawParams); + } + + $params = []; + foreach ($rawParams as $param) { + if (preg_match('/^--(\w+)(=(.*))?$/', $param, $matches)) { + $name = $matches[1]; + $params[$name] = isset($matches[3]) ? $matches[3] : true; + } else { + $params[] = $param; + } + } + return $params; +} + +function setWritable($root, $paths) +{ + foreach ($paths as $writable) { + if (is_dir("$root/$writable")) { + if (@chmod("$root/$writable", 0777)) { + echo " chmod 0777 $writable\n"; + } else { + printError("Operation chmod not permitted for directory $writable."); + } + } else { + printError("Directory $writable does not exist."); + } + } +} + +function setExecutable($root, $paths) +{ + foreach ($paths as $executable) { + if (file_exists("$root/$executable")) { + if (@chmod("$root/$executable", 0755)) { + echo " chmod 0755 $executable\n"; + } else { + printError("Operation chmod not permitted for $executable."); + } + } else { + printError("$executable does not exist."); + } + } +} + +function setCookieValidationKey($root, $paths) +{ + foreach ($paths as $file) { + echo " generate cookie validation key in $file\n"; + $file = $root . '/' . $file; + $length = 32; + $bytes = openssl_random_pseudo_bytes($length); + $key = strtr(substr(base64_encode($bytes), 0, $length), '+/=', '_-.'); + $content = preg_replace('/(("|\')cookieValidationKey("|\')\s*=>\s*)(""|\'\')/', "\\1'$key'", file_get_contents($file)); + file_put_contents($file, $content); + } +} + +function createSymlink($root, $links) +{ + foreach ($links as $link => $target) { + //first removing folders to avoid errors if the folder already exists + @rmdir($root . "/" . $link); + //next removing existing symlink in order to update the target + if (is_link($root . "/" . $link)) { + @unlink($root . "/" . $link); + } + if (@symlink($root . "/" . $target, $root . "/" . $link)) { + echo " symlink $root/$target $root/$link\n"; + } else { + printError("Cannot create symlink $root/$target $root/$link."); + } + } +} + +/** + * Prints error message. + * @param string $message message + */ +function printError($message) +{ + echo "\n " . formatMessage("Error. $message", ['fg-red']) . " \n"; +} + +/** + * Returns true if the stream supports colorization. ANSI colors are disabled if not supported by the stream. + * + * - windows without ansicon + * - not tty consoles + * + * @return boolean true if the stream supports ANSI colors, otherwise false. + */ +function ansiColorsSupported() +{ + return DIRECTORY_SEPARATOR === '\\' + ? getenv('ANSICON') !== false || getenv('ConEmuANSI') === 'ON' + : function_exists('posix_isatty') && @posix_isatty(STDOUT); +} + +/** + * Get ANSI code of style. + * @param string $name style name + * @return integer ANSI code of style. + */ +function getStyleCode($name) +{ + $styles = [ + 'bold' => 1, + 'fg-black' => 30, + 'fg-red' => 31, + 'fg-green' => 32, + 'fg-yellow' => 33, + 'fg-blue' => 34, + 'fg-magenta' => 35, + 'fg-cyan' => 36, + 'fg-white' => 37, + 'bg-black' => 40, + 'bg-red' => 41, + 'bg-green' => 42, + 'bg-yellow' => 43, + 'bg-blue' => 44, + 'bg-magenta' => 45, + 'bg-cyan' => 46, + 'bg-white' => 47, + ]; + return $styles[$name]; +} + +/** + * Formats message using styles if STDOUT supports it. + * @param string $message message + * @param string[] $styles styles + * @return string formatted message. + */ +function formatMessage($message, $styles) +{ + if (empty($styles) || !ansiColorsSupported()) { + return $message; + } + + return sprintf("\x1b[%sm", implode(';', array_map('getStyleCode', $styles))) . $message . "\x1b[0m"; +} diff --git a/init.bat b/init.bat new file mode 100755 index 0000000..e50c242 --- /dev/null +++ b/init.bat @@ -0,0 +1,20 @@ +@echo off + +rem ------------------------------------------------------------- +rem Yii command line init script for Windows. +rem +rem @author Qiang Xue +rem @link http://www.yiiframework.com/ +rem @copyright Copyright (c) 2008 Yii Software LLC +rem @license http://www.yiiframework.com/license/ +rem ------------------------------------------------------------- + +@setlocal + +set YII_PATH=%~dp0 + +if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe + +"%PHP_COMMAND%" "%YII_PATH%init" %* + +@endlocal diff --git a/requirements.php b/requirements.php new file mode 100755 index 0000000..62c731b --- /dev/null +++ b/requirements.php @@ -0,0 +1,132 @@ +Error'; + echo '

    The path to yii framework seems to be incorrect.

    '; + echo '

    You need to install Yii framework via composer or adjust the framework path in file ' . basename(__FILE__) . '.

    '; + echo '

    Please refer to the README on how to install Yii.

    '; +} + +require_once($frameworkPath . '/requirements/YiiRequirementChecker.php'); +$requirementsChecker = new YiiRequirementChecker(); + +$gdMemo = $imagickMemo = 'Either GD PHP extension with FreeType support or ImageMagick PHP extension with PNG support is required for image CAPTCHA.'; +$gdOK = $imagickOK = false; + +if (extension_loaded('imagick')) { + $imagick = new Imagick(); + $imagickFormats = $imagick->queryFormats('PNG'); + if (in_array('PNG', $imagickFormats)) { + $imagickOK = true; + } else { + $imagickMemo = 'Imagick extension should be installed with PNG support in order to be used for image CAPTCHA.'; + } +} + +if (extension_loaded('gd')) { + $gdInfo = gd_info(); + if (!empty($gdInfo['FreeType Support'])) { + $gdOK = true; + } else { + $gdMemo = 'GD extension should be installed with FreeType support in order to be used for image CAPTCHA.'; + } +} + +/** + * Adjust requirements according to your application specifics. + */ +$requirements = array( + // Database : + array( + 'name' => 'PDO extension', + 'mandatory' => true, + 'condition' => extension_loaded('pdo'), + 'by' => 'All DB-related classes', + ), + array( + 'name' => 'PDO SQLite extension', + 'mandatory' => false, + 'condition' => extension_loaded('pdo_sqlite'), + 'by' => 'All DB-related classes', + 'memo' => 'Required for SQLite database.', + ), + array( + 'name' => 'PDO MySQL extension', + 'mandatory' => false, + 'condition' => extension_loaded('pdo_mysql'), + 'by' => 'All DB-related classes', + 'memo' => 'Required for MySQL database.', + ), + array( + 'name' => 'PDO PostgreSQL extension', + 'mandatory' => false, + 'condition' => extension_loaded('pdo_pgsql'), + 'by' => 'All DB-related classes', + 'memo' => 'Required for PostgreSQL database.', + ), + // Cache : + array( + 'name' => 'Memcache extension', + 'mandatory' => false, + 'condition' => extension_loaded('memcache') || extension_loaded('memcached'), + 'by' => 'MemCache', + 'memo' => extension_loaded('memcached') ? 'To use memcached set MemCache::useMemcached to true.' : '' + ), + array( + 'name' => 'APC extension', + 'mandatory' => false, + 'condition' => extension_loaded('apc'), + 'by' => 'ApcCache', + ), + // CAPTCHA: + array( + 'name' => 'GD PHP extension with FreeType support', + 'mandatory' => false, + 'condition' => $gdOK, + 'by' => 'Captcha', + 'memo' => $gdMemo, + ), + array( + 'name' => 'ImageMagick PHP extension with PNG support', + 'mandatory' => false, + 'condition' => $imagickOK, + 'by' => 'Captcha', + 'memo' => $imagickMemo, + ), + // PHP ini : + 'phpExposePhp' => array( + 'name' => 'Expose PHP', + 'mandatory' => false, + 'condition' => $requirementsChecker->checkPhpIniOff("expose_php"), + 'by' => 'Security reasons', + 'memo' => '"expose_php" should be disabled at php.ini', + ), + 'phpAllowUrlInclude' => array( + 'name' => 'PHP allow url include', + 'mandatory' => false, + 'condition' => $requirementsChecker->checkPhpIniOff("allow_url_include"), + 'by' => 'Security reasons', + 'memo' => '"allow_url_include" should be disabled at php.ini', + ), + 'phpSmtp' => array( + 'name' => 'PHP mail SMTP', + 'mandatory' => false, + 'condition' => strlen(ini_get('SMTP')) > 0, + 'by' => 'Email sending', + 'memo' => 'PHP mail SMTP server required', + ), +); +$requirementsChecker->checkYii()->check($requirements)->render(); diff --git a/vagrant/config/.gitignore b/vagrant/config/.gitignore new file mode 100755 index 0000000..0685a56 --- /dev/null +++ b/vagrant/config/.gitignore @@ -0,0 +1,2 @@ +# local configuration +vagrant-local.yml \ No newline at end of file diff --git a/vagrant/config/vagrant-local.example.yml b/vagrant/config/vagrant-local.example.yml new file mode 100755 index 0000000..32dd3ab --- /dev/null +++ b/vagrant/config/vagrant-local.example.yml @@ -0,0 +1,22 @@ +# Your personal GitHub token +github_token: +# Read more: https://github.com/blog/1509-personal-api-tokens +# You can generate it here: https://github.com/settings/tokens + +# Guest OS timezone +timezone: Europe/London + +# Are we need check box updates for every 'vagrant up'? +box_check_update: false + +# Virtual machine name +machine_name: y2aa + +# Virtual machine IP +ip: 192.168.83.137 + +# Virtual machine CPU cores number +cpus: 1 + +# Virtual machine RAM +memory: 512 diff --git a/vagrant/nginx/app.conf b/vagrant/nginx/app.conf new file mode 100755 index 0000000..fc8fe40 --- /dev/null +++ b/vagrant/nginx/app.conf @@ -0,0 +1,77 @@ +server { + charset utf-8; + client_max_body_size 128M; + sendfile off; + + listen 80; ## listen for ipv4 + #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 + + server_name y2aa-frontend.dev; + root /app/frontend/web/; + index index.php; + + access_log /app/vagrant/nginx/log/frontend-access.log; + error_log /app/vagrant/nginx/log/frontend-error.log; + + location / { + # Redirect everything that isn't a real file to index.php + try_files $uri $uri/ /index.php$is_args$args; + } + + # uncomment to avoid processing of calls to non-existing static files by Yii + #location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ { + # try_files $uri =404; + #} + #error_page 404 /404.html; + + location ~ \.php$ { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + #fastcgi_pass 127.0.0.1:9000; + fastcgi_pass unix:/var/run/php5-fpm.sock; + try_files $uri =404; + } + + location ~ /\.(ht|svn|git) { + deny all; + } +} + +server { + charset utf-8; + client_max_body_size 128M; + sendfile off; + + listen 80; ## listen for ipv4 + #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 + + server_name y2aa-backend.dev; + root /app/backend/web/; + index index.php; + + access_log /app/vagrant/nginx/log/backend-access.log; + error_log /app/vagrant/nginx/log/backend-error.log; + + location / { + # Redirect everything that isn't a real file to index.php + try_files $uri $uri/ /index.php$is_args$args; + } + + # uncomment to avoid processing of calls to non-existing static files by Yii + #location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ { + # try_files $uri =404; + #} + #error_page 404 /404.html; + + location ~ \.php$ { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + #fastcgi_pass 127.0.0.1:9000; + fastcgi_pass unix:/var/run/php5-fpm.sock; + try_files $uri =404; + } + + location ~ /\.(ht|svn|git) { + deny all; + } +} diff --git a/vagrant/nginx/log/.gitignore b/vagrant/nginx/log/.gitignore new file mode 100755 index 0000000..c15cedd --- /dev/null +++ b/vagrant/nginx/log/.gitignore @@ -0,0 +1,5 @@ +# nginx logs +backend-access.log +backend-error.log +frontend-access.log +frontend-error.log \ No newline at end of file diff --git a/vagrant/provision/always-as-root.sh b/vagrant/provision/always-as-root.sh new file mode 100755 index 0000000..f2465e7 --- /dev/null +++ b/vagrant/provision/always-as-root.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +#== Bash helpers == + +function info { + echo " " + echo "--> $1" + echo " " +} + +#== Provision script == + +info "Provision-script user: `whoami`" + +info "Restart web-stack" +service php5-fpm restart +service nginx restart +service mysql restart \ No newline at end of file diff --git a/vagrant/provision/once-as-root.sh b/vagrant/provision/once-as-root.sh new file mode 100755 index 0000000..1dd108c --- /dev/null +++ b/vagrant/provision/once-as-root.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash + +#== Import script args == + +timezone=$(echo "$1") + +#== Bash helpers == + +function info { + echo " " + echo "--> $1" + echo " " +} + +#== Provision script == + +info "Provision-script user: `whoami`" + +info "Allocate swap for MySQL 5.6" +fallocate -l 2048M /swapfile +chmod 600 /swapfile +mkswap /swapfile +swapon /swapfile +echo '/swapfile none swap defaults 0 0' >> /etc/fstab + +info "Configure locales" +update-locale LC_ALL="C" +dpkg-reconfigure locales + +info "Configure timezone" +echo ${timezone} | tee /etc/timezone +dpkg-reconfigure --frontend noninteractive tzdata + +info "Prepare root password for MySQL" +debconf-set-selections <<< "mysql-server-5.6 mysql-server/root_password password \"''\"" +debconf-set-selections <<< "mysql-server-5.6 mysql-server/root_password_again password \"''\"" +echo "Done!" + +info "Update OS software" +apt-get update +apt-get upgrade -y + +info "Install additional software" +apt-get install -y git php5-curl php5-cli php5-intl php5-mysqlnd php5-gd php5-fpm nginx mysql-server-5.6 + +info "Configure MySQL" +sed -i "s/.*bind-address.*/bind-address = 0.0.0.0/" /etc/mysql/my.cnf +echo "Done!" + +info "Configure PHP-FPM" +sed -i 's/user = www-data/user = vagrant/g' /etc/php5/fpm/pool.d/www.conf +sed -i 's/group = www-data/group = vagrant/g' /etc/php5/fpm/pool.d/www.conf +sed -i 's/owner = www-data/owner = vagrant/g' /etc/php5/fpm/pool.d/www.conf +echo "Done!" + +info "Configure NGINX" +sed -i 's/user www-data/user vagrant/g' /etc/nginx/nginx.conf +echo "Done!" + +info "Enabling site configuration" +ln -s /app/vagrant/nginx/app.conf /etc/nginx/sites-enabled/app.conf +echo "Done!" + +info "Initailize databases for MySQL" +mysql -uroot <<< "CREATE DATABASE yii2advanced" +mysql -uroot <<< "CREATE DATABASE yii2advanced_test" +echo "Done!" + +info "Install composer" +curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \ No newline at end of file diff --git a/vagrant/provision/once-as-vagrant.sh b/vagrant/provision/once-as-vagrant.sh new file mode 100755 index 0000000..a9a5e33 --- /dev/null +++ b/vagrant/provision/once-as-vagrant.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +#== Import script args == + +github_token=$(echo "$1") + +#== Bash helpers == + +function info { + echo " " + echo "--> $1" + echo " " +} + +#== Provision script == + +info "Provision-script user: `whoami`" + +info "Configure composer" +composer config --global github-oauth.github.com ${github_token} +echo "Done!" + +info "Install plugins for composer" +composer global require "fxp/composer-asset-plugin:^1.2.0" --no-progress + +info "Install codeception" +composer global require "codeception/codeception=2.0.*" "codeception/specify=*" "codeception/verify=*" --no-progress +echo 'export PATH=/home/vagrant/.config/composer/vendor/bin:$PATH' | tee -a /home/vagrant/.profile + +info "Install project dependencies" +cd /app +composer --no-progress --prefer-dist install + +info "Init project" +./init --env=Development --overwrite=y + +info "Apply migrations" +./yii migrate <<< "yes" + +info "Create bash-alias 'app' for vagrant user" +echo 'alias app="cd /app"' | tee /home/vagrant/.bash_aliases + +info "Enabling colorized prompt for guest console" +sed -i "s/#force_color_prompt=yes/force_color_prompt=yes/" /home/vagrant/.bashrc diff --git a/yii.bat b/yii.bat new file mode 100755 index 0000000..d516b3a --- /dev/null +++ b/yii.bat @@ -0,0 +1,20 @@ +@echo off + +rem ------------------------------------------------------------- +rem Yii command line bootstrap script for Windows. +rem +rem @author Qiang Xue +rem @link http://www.yiiframework.com/ +rem @copyright Copyright (c) 2008 Yii Software LLC +rem @license http://www.yiiframework.com/license/ +rem ------------------------------------------------------------- + +@setlocal + +set YII_PATH=%~dp0 + +if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe + +"%PHP_COMMAND%" "%YII_PATH%yii" %* + +@endlocal