├── .dockerignore ├── .env.dist ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── main.yml ├── .gitignore ├── LICENSE.md ├── Procfile ├── README.md ├── api ├── Dockerfile ├── config │ ├── _cache.php │ ├── _urlManager.php │ ├── base.php │ ├── bootstrap.php │ ├── console.php │ └── web.php ├── controllers │ └── SiteController.php ├── modules │ └── v1 │ │ ├── Module.php │ │ ├── controllers │ │ ├── ArticleController.php │ │ └── UserController.php │ │ ├── models │ │ ├── ApiUserIdentity.php │ │ └── definitions │ │ │ └── Article.php │ │ └── resources │ │ ├── Article.php │ │ └── User.php ├── runtime │ └── .gitignore ├── web │ ├── .htaccess │ ├── assets │ │ └── .gitignore │ ├── index-test.php │ └── index.php ├── yii └── yii.bat ├── autocompletion.php ├── backend ├── Dockerfile ├── assets │ └── BackendAsset.php ├── config │ ├── _urlManager.php │ ├── base.php │ ├── bootstrap.php │ ├── console.php │ └── web.php ├── controllers │ ├── SignInController.php │ ├── SiteController.php │ ├── TimelineEventController.php │ └── UserController.php ├── mail │ └── layouts │ │ ├── html.php │ │ └── text.php ├── models │ ├── AccountForm.php │ ├── LoginForm.php │ ├── UserForm.php │ └── search │ │ ├── TimelineEventSearch.php │ │ └── UserSearch.php ├── modules │ ├── content │ │ ├── Module.php │ │ ├── controllers │ │ │ ├── ArticleController.php │ │ │ ├── CategoryController.php │ │ │ └── PageController.php │ │ ├── models │ │ │ └── search │ │ │ │ ├── ArticleCategorySearch.php │ │ │ │ ├── ArticleSearch.php │ │ │ │ └── PageSearch.php │ │ └── views │ │ │ ├── article │ │ │ ├── _form.php │ │ │ ├── create.php │ │ │ ├── index.php │ │ │ └── update.php │ │ │ ├── category │ │ │ ├── _form.php │ │ │ ├── index.php │ │ │ └── update.php │ │ │ └── page │ │ │ ├── _form.php │ │ │ ├── index.php │ │ │ └── update.php │ ├── file │ │ ├── Module.php │ │ ├── controllers │ │ │ ├── ManagerController.php │ │ │ └── StorageController.php │ │ ├── models │ │ │ └── search │ │ │ │ └── FileStorageItemSearch.php │ │ └── views │ │ │ ├── manager │ │ │ └── index.php │ │ │ └── storage │ │ │ ├── index.php │ │ │ └── view.php │ ├── rbac │ │ ├── Module.php │ │ ├── controllers │ │ │ ├── RbacAuthAssignmentController.php │ │ │ ├── RbacAuthItemChildController.php │ │ │ ├── RbacAuthItemController.php │ │ │ └── RbacAuthRuleController.php │ │ ├── models │ │ │ ├── RbacAuthAssignment.php │ │ │ ├── RbacAuthItem.php │ │ │ ├── RbacAuthItemChild.php │ │ │ └── RbacAuthRule.php │ │ └── views │ │ │ ├── rbac-auth-assignment │ │ │ ├── _form.php │ │ │ ├── create.php │ │ │ ├── index.php │ │ │ ├── update.php │ │ │ └── view.php │ │ │ ├── rbac-auth-item-child │ │ │ ├── _form.php │ │ │ ├── create.php │ │ │ ├── index.php │ │ │ ├── update.php │ │ │ └── view.php │ │ │ ├── rbac-auth-item │ │ │ ├── _form.php │ │ │ ├── create.php │ │ │ ├── index.php │ │ │ ├── update.php │ │ │ └── view.php │ │ │ └── rbac-auth-rule │ │ │ ├── _form.php │ │ │ ├── create.php │ │ │ ├── index.php │ │ │ ├── update.php │ │ │ └── view.php │ ├── system │ │ ├── Module.php │ │ ├── controllers │ │ │ ├── CacheController.php │ │ │ ├── InformationController.php │ │ │ ├── KeyStorageController.php │ │ │ ├── LogController.php │ │ │ └── SettingsController.php │ │ ├── models │ │ │ ├── SystemLog.php │ │ │ └── search │ │ │ │ ├── KeyStorageItemSearch.php │ │ │ │ └── SystemLogSearch.php │ │ └── views │ │ │ ├── cache │ │ │ └── index.php │ │ │ ├── information │ │ │ ├── fail.php │ │ │ └── index.php │ │ │ ├── key-storage │ │ │ ├── _form.php │ │ │ ├── index.php │ │ │ └── update.php │ │ │ ├── log │ │ │ ├── index.php │ │ │ └── view.php │ │ │ └── settings │ │ │ └── index.php │ ├── translation │ │ ├── Module.php │ │ ├── controllers │ │ │ └── DefaultController.php │ │ ├── models │ │ │ ├── Source.php │ │ │ ├── Translation.php │ │ │ └── search │ │ │ │ └── SourceSearch.php │ │ ├── traits │ │ │ └── ModuleTrait.php │ │ └── views │ │ │ └── default │ │ │ ├── _form.php │ │ │ ├── index.php │ │ │ └── update.php │ └── widget │ │ ├── Module.php │ │ ├── controllers │ │ ├── CarouselController.php │ │ ├── CarouselItemController.php │ │ ├── MenuController.php │ │ └── TextController.php │ │ ├── models │ │ └── search │ │ │ ├── CarouselItemSearch.php │ │ │ ├── CarouselSearch.php │ │ │ ├── MenuSearch.php │ │ │ └── TextSearch.php │ │ └── views │ │ ├── carousel │ │ ├── _form.php │ │ ├── index.php │ │ ├── item │ │ │ ├── _form.php │ │ │ ├── create.php │ │ │ └── update.php │ │ └── update.php │ │ ├── menu │ │ ├── _form.php │ │ ├── index.php │ │ └── update.php │ │ └── text │ │ ├── _form.php │ │ ├── index.php │ │ └── update.php ├── runtime │ └── .gitignore ├── views │ ├── _gii │ │ └── templates │ │ │ ├── controller.php │ │ │ ├── search.php │ │ │ └── views │ │ │ ├── _form.php │ │ │ ├── _search.php │ │ │ ├── create.php │ │ │ ├── index.php │ │ │ ├── update.php │ │ │ └── view.php │ ├── layouts │ │ ├── base.php │ │ ├── clear.php │ │ ├── common.php │ │ └── main.php │ ├── sign-in │ │ ├── account.php │ │ ├── login.php │ │ └── profile.php │ ├── site │ │ └── error.php │ ├── timeline-event │ │ ├── _item.php │ │ ├── _search.php │ │ ├── index.php │ │ └── user │ │ │ ├── delete.php │ │ │ └── signup.php │ └── user │ │ ├── _form.php │ │ ├── _search.php │ │ ├── create.php │ │ ├── index.php │ │ ├── update.php │ │ └── view.php ├── web │ ├── .htaccess │ ├── assets │ │ └── .gitignore │ ├── bundle │ │ └── .gitignore │ ├── css │ │ └── style.less │ ├── favicon.ico │ ├── img │ │ ├── anonymous.png │ │ └── yii2-starter-kit.gif │ ├── index-test.php │ ├── index.php │ ├── js │ │ ├── app.js │ │ └── system-information │ │ │ └── index.js │ └── robots.txt ├── widgets │ └── MainSidebarMenu.php ├── yii └── yii.bat ├── codeception.yml ├── common ├── actions │ └── SetLocaleAction.php ├── assets │ ├── AdminLte.php │ ├── Flot.php │ ├── Html5shiv.php │ └── JquerySlimScroll.php ├── base │ └── MultiModel.php ├── behaviors │ ├── CacheInvalidateBehavior.php │ ├── FileStorageLogBehavior.php │ ├── GlobalAccessBehavior.php │ ├── LocaleBehavior.php │ └── LoginTimestampBehavior.php ├── commands │ ├── AddToTimelineCommand.php │ └── SendEmailCommand.php ├── components │ ├── filesystem │ │ └── LocalFlysystemBuilder.php │ ├── keyStorage │ │ ├── FormModel.php │ │ ├── FormWidget.php │ │ └── KeyStorage.php │ ├── log │ │ └── NotFoundTarget.php │ └── maintenance │ │ ├── Maintenance.php │ │ ├── MaintenanceAsset.php │ │ ├── assets │ │ └── css │ │ │ ├── maintenance.css │ │ │ ├── maintenance.less │ │ │ └── maintenance.map │ │ ├── controllers │ │ └── MaintenanceController.php │ │ └── views │ │ ├── layouts │ │ └── main.php │ │ └── maintenance │ │ └── index.php ├── config │ ├── base.php │ ├── bootstrap.php │ ├── console.php │ ├── messages │ │ ├── _base.php │ │ ├── db.php │ │ ├── php.php │ │ └── po.php │ └── web.php ├── env.php ├── filters │ └── OwnModelAccessFilter.php ├── grid │ └── EnumColumn.php ├── helpers.php ├── messages │ ├── es │ │ ├── backend.php │ │ ├── common.php │ │ └── frontend.php │ ├── fr │ │ ├── backend.php │ │ ├── common.php │ │ └── frontend.php │ ├── hu │ │ ├── backend.php │ │ ├── common.php │ │ └── frontend.php │ ├── id │ │ ├── backend.php │ │ ├── common.php │ │ └── frontend.php │ ├── pl │ │ ├── backend.php │ │ ├── common.php │ │ └── frontend.php │ ├── pt-BR │ │ ├── backend.php │ │ ├── common.php │ │ └── frontend.php │ ├── ru │ │ ├── backend.php │ │ ├── common.php │ │ └── frontend.php │ ├── uk │ │ ├── backend.php │ │ ├── common.php │ │ └── frontend.php │ ├── vi │ │ ├── backend.php │ │ ├── common.php │ │ └── frontend.php │ └── zh │ │ ├── backend.php │ │ ├── common.php │ │ └── frontend.php ├── migrations │ ├── db │ │ ├── m140703_123000_user.php │ │ ├── m140703_123055_log.php │ │ ├── m140703_123104_page.php │ │ ├── m140703_123803_article.php │ │ ├── m140703_123813_rbac.php │ │ ├── m140709_173306_widget_menu.php │ │ ├── m140709_173333_widget_text.php │ │ ├── m140712_123329_widget_carousel.php │ │ ├── m140805_084745_key_storage_item.php │ │ ├── m141012_101932_i18n_tables.php │ │ ├── m150318_213934_file_storage_item.php │ │ ├── m150414_195800_timeline_event.php │ │ ├── m150725_192740_seed_data.php │ │ ├── m150929_074021_article_attachment_order.php │ │ ├── m160203_095604_user_token.php │ │ └── m190130_155645_add_article_slug_index.php │ └── rbac │ │ ├── m150625_214101_roles.php │ │ ├── m150625_215624_init_permissions.php │ │ └── m151223_074604_edit_own_model.php ├── models │ ├── Article.php │ ├── ArticleAttachment.php │ ├── ArticleCategory.php │ ├── FileStorageItem.php │ ├── KeyStorageItem.php │ ├── Page.php │ ├── TimelineEvent.php │ ├── User.php │ ├── UserProfile.php │ ├── UserToken.php │ ├── WidgetCarousel.php │ ├── WidgetCarouselItem.php │ ├── WidgetMenu.php │ ├── WidgetText.php │ └── query │ │ ├── ArticleCategoryQuery.php │ │ ├── ArticleQuery.php │ │ ├── PageQuery.php │ │ ├── TimelineEventQuery.php │ │ ├── UserQuery.php │ │ └── UserTokenQuery.php ├── rbac │ ├── Migration.php │ ├── rule │ │ └── OwnModelRule.php │ └── views │ │ └── migration.php ├── runtime │ └── .gitignore ├── sitemap │ └── UrlsIterator.php ├── traits │ └── FormAjaxValidationTrait.php ├── validators │ └── JsonValidator.php └── widgets │ ├── ActionColumn.php │ ├── DbCarousel.php │ ├── DbMenu.php │ └── DbText.php ├── composer.json ├── composer.lock ├── console ├── Dockerfile ├── config │ ├── bootstrap.php │ └── console.php ├── controllers │ ├── AppController.php │ ├── ExtendedMessageController.php │ └── RbacMigrateController.php ├── runtime │ └── .gitignore ├── yii └── yii.bat ├── deploy └── heroku │ ├── .env │ └── heroku-nginx.conf ├── docker-compose.yml ├── docker ├── mysql │ └── config.cnf ├── nginx │ ├── vhost.conf │ └── vhost_single_domain.conf └── php │ ├── Dockerfile │ ├── install-composer.sh │ ├── php.ini │ └── www.conf ├── frontend ├── Dockerfile ├── assets │ └── FrontendAsset.php ├── config │ ├── _cache.php │ ├── _urlManager.php │ ├── base.php │ ├── bootstrap.php │ ├── console.php │ └── web.php ├── controllers │ ├── ArticleController.php │ ├── PageController.php │ └── SiteController.php ├── mail │ ├── activation.php │ ├── layouts │ │ ├── html.php │ │ └── text.php │ ├── oauth_welcome.php │ └── passwordResetToken.php ├── models │ ├── ContactForm.php │ └── search │ │ └── ArticleSearch.php ├── modules │ └── user │ │ ├── Module.php │ │ ├── controllers │ │ ├── DefaultController.php │ │ └── SignInController.php │ │ ├── models │ │ ├── AccountForm.php │ │ ├── LoginForm.php │ │ ├── PasswordResetRequestForm.php │ │ ├── ResendEmailForm.php │ │ ├── ResetPasswordForm.php │ │ └── SignupForm.php │ │ └── views │ │ ├── default │ │ └── index.php │ │ └── sign-in │ │ ├── login.php │ │ ├── requestPasswordResetToken.php │ │ ├── resend-email.php │ │ ├── resetPassword.php │ │ └── signup.php ├── runtime │ └── .gitignore ├── views │ ├── article │ │ ├── _archive.php │ │ ├── _categories.php │ │ ├── _item.php │ │ ├── index.php │ │ └── view.php │ ├── layouts │ │ ├── _clear.php │ │ ├── base.php │ │ ├── full-width.php │ │ └── main.php │ ├── page │ │ └── view.php │ └── site │ │ ├── contact.php │ │ ├── error.php │ │ └── index.php ├── web │ ├── .htaccess │ ├── assets │ │ └── .gitignore │ ├── bundle │ │ └── .gitignore │ ├── css │ │ ├── _article.less │ │ └── style.less │ ├── favicon.ico │ ├── img │ │ ├── anonymous.png │ │ └── yii2-starter-kit.gif │ ├── index-test.php │ ├── index.php │ ├── js │ │ └── app.js │ └── robots.txt ├── yii └── yii.bat ├── package-lock.json ├── package.json ├── storage ├── Dockerfile ├── cache │ └── .gitignore ├── config │ ├── _urlManager.php │ └── base.php └── web │ ├── .htaccess │ ├── index.php │ └── source │ └── .gitignore ├── taskctl.yaml ├── tests ├── _output │ └── .gitignore ├── api │ ├── _bootstrap.php │ ├── _output │ │ └── .gitignore │ ├── _support │ │ ├── FunctionalTester.php │ │ └── _generated │ │ │ └── .gitignore │ ├── codeception.yml │ ├── functional.suite.yml │ ├── functional │ │ ├── ArticleCest.php │ │ ├── UserCest.php │ │ ├── _bootstrap.php │ │ └── base │ │ │ └── ApiCest.php │ └── unit │ │ └── _bootstrap.php ├── backend │ ├── _bootstrap.php │ ├── _output │ │ └── .gitignore │ ├── _pages │ │ └── LoginPage.php │ ├── _support │ │ ├── AcceptanceTester.php │ │ ├── FunctionalTester.php │ │ ├── UnitTester.php │ │ └── _generated │ │ │ └── .gitignore │ ├── acceptance.suite.yml │ ├── acceptance │ │ ├── LoginCept.php │ │ └── _bootstrap.php │ ├── codeception.yml │ ├── functional.suite.yml │ ├── functional │ │ ├── LoginCept.php │ │ └── _bootstrap.php │ ├── unit.suite.yml │ └── unit │ │ └── _bootstrap.php ├── bin │ └── yii ├── bootstrap.php ├── common │ ├── _bootstrap.php │ ├── _output │ │ └── .gitignore │ ├── _support │ │ ├── FixtureHelper.php │ │ ├── UnitTester.php │ │ └── _generated │ │ │ └── .gitignore │ ├── codeception.yml │ ├── fixtures │ │ ├── ArticleAttachmentFixture.php │ │ ├── ArticleCategoryFixture.php │ │ ├── ArticleFixture.php │ │ ├── KeyStorageItemFixture.php │ │ ├── PageFixture.php │ │ ├── RbacAuthAssignmentFixture.php │ │ ├── RbacAuthItemChildFixture.php │ │ ├── RbacAuthItemFixture.php │ │ ├── RbacAuthRuleFixture.php │ │ ├── UserFixture.php │ │ ├── UserProfileFixture.php │ │ ├── WidgetCarouselFixture.php │ │ ├── WidgetCarouselItemFixture.php │ │ ├── WidgetMenuFixture.php │ │ ├── WidgetTextFixture.php │ │ └── data │ │ │ ├── article.php │ │ │ ├── article_attachment.php │ │ │ ├── article_category.php │ │ │ ├── key_storage_item.php │ │ │ ├── page.php │ │ │ ├── rbac_auth_assignment.php │ │ │ ├── rbac_auth_item.php │ │ │ ├── rbac_auth_item_child.php │ │ │ ├── rbac_auth_rule.php │ │ │ ├── user.php │ │ │ ├── user_profile.php │ │ │ ├── widget_carousel.php │ │ │ ├── widget_carousel_item.php │ │ │ ├── widget_menu.php │ │ │ └── widget_text.php │ ├── templates │ │ └── fixtures │ │ │ └── user.php │ ├── unit.suite.yml │ └── unit │ │ ├── KeyStorageTest.php │ │ ├── UserTest.php │ │ └── _bootstrap.php ├── config │ ├── api │ │ └── functional.php │ ├── backend │ │ ├── acceptance.php │ │ ├── functional.php │ │ └── unit.php │ ├── base.php │ ├── common │ │ ├── acceptance.php │ │ ├── functional.php │ │ └── unit.php │ ├── console.php │ ├── console │ │ └── unit.php │ └── frontend │ │ ├── acceptance.php │ │ ├── functional.php │ │ └── unit.php ├── console │ ├── _bootstrap.php │ ├── _output │ │ └── .gitignore │ ├── _support │ │ ├── UnitTester.php │ │ └── _generated │ │ │ └── .gitignore │ ├── codeception.yml │ ├── unit.suite.yml │ └── unit │ │ └── _bootstrap.php └── frontend │ ├── _bootstrap.php │ ├── _output │ └── .gitignore │ ├── _pages │ ├── LoginPage.php │ └── SignupPage.php │ ├── _support │ ├── AcceptanceHelper.php │ ├── AcceptanceTester.php │ ├── FunctionalHelper.php │ ├── FunctionalTester.php │ ├── UnitHelper.php │ ├── UnitTester.php │ └── _generated │ │ └── .gitignore │ ├── acceptance.suite.yml │ ├── acceptance │ ├── HomeCept.php │ ├── LoginCept.php │ ├── SignupCest.php │ └── _bootstrap.php │ ├── codeception.yml │ ├── functional.suite.yml │ ├── functional │ ├── ArticleCest.php │ ├── HomeCept.php │ ├── LoginCept.php │ ├── SignupCest.php │ └── _bootstrap.php │ ├── unit.suite.yml │ └── unit │ └── _bootstrap.php └── webpack.config.js /.dockerignore: -------------------------------------------------------------------------------- 1 | # Git 2 | .git 3 | 4 | # Runtime 5 | backend/runtime 6 | common/runtime 7 | frontend/runtime 8 | console/runtime 9 | 10 | # Assets 11 | backend/web/assets 12 | frontend/web/assets 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | 40 | ** Software Versions ** 41 | 42 | | Q | A 43 | | ---------------- | --- 44 | | Yii version | 45 | | PHP version | 46 | | Operating system | 47 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Env 2 | /.env 3 | 4 | # Composer 5 | /vendor 6 | composer.phar 7 | 8 | # JS 9 | node_modules 10 | spa/npm-debug.log 11 | spa/yarn-error.log 12 | 13 | # IDE 14 | .idea 15 | nbproject 16 | .buildpath 17 | .project 18 | .settings 19 | 20 | # windows thumbnail cache 21 | Thumbs.db 22 | 23 | # Mac DS_Store Files 24 | .DS_Store 25 | 26 | # phpunit 27 | phpunit.phar 28 | /phpunit.xml 29 | 30 | # Vagrant 31 | /.vagrant 32 | 33 | # Tests 34 | tests/codeception/*/_support/_generated/* 35 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: vendor/bin/heroku-php-nginx -C deploy/heroku/heroku-nginx.conf 2 | -------------------------------------------------------------------------------- /api/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM yiisoftware/yii2-php:8.0-fpm -------------------------------------------------------------------------------- /api/config/_cache.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | 6 | $cache = [ 7 | 'class' => yii\caching\FileCache::class, 8 | 'cachePath' => '@api/runtime/cache' 9 | ]; 10 | 11 | if (YII_ENV_DEV) { 12 | $cache = [ 13 | 'class' => yii\caching\DummyCache::class 14 | ]; 15 | } 16 | 17 | return $cache; 18 | -------------------------------------------------------------------------------- /api/config/_urlManager.php: -------------------------------------------------------------------------------- 1 | 'yii\web\UrlManager', 4 | 'enablePrettyUrl' => true, 5 | 'showScriptName' => false, 6 | 'rules' => [ 7 | // Api 8 | ['class' => 'yii\rest\UrlRule', 'controller' => 'v1/article', 'only' => ['index', 'view', 'options']], 9 | ] 10 | ]; 11 | -------------------------------------------------------------------------------- /api/config/base.php: -------------------------------------------------------------------------------- 1 | 'frontend', 4 | 'basePath' => dirname(__DIR__), 5 | 'components' => [ 6 | 'urlManager' => require(__DIR__ . '/_urlManager.php'), 7 | 'cache' => require(__DIR__ . '/_cache.php'), 8 | ], 9 | ]; 10 | -------------------------------------------------------------------------------- /api/config/bootstrap.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | -------------------------------------------------------------------------------- /api/config/console.php: -------------------------------------------------------------------------------- 1 | Yii::getAlias('@apiUrl'), 4 | 'controllerNamespace' => 'api\controllers', 5 | 'defaultRoute' => 'site/index', 6 | 'bootstrap' => ['maintenance'], 7 | 'modules' => [ 8 | 'v1' => \api\modules\v1\Module::class 9 | ], 10 | 'components' => [ 11 | 'errorHandler' => [ 12 | 'errorAction' => 'site/error' 13 | ], 14 | 'maintenance' => [ 15 | 'class' => common\components\maintenance\Maintenance::class, 16 | 'enabled' => function ($app) { 17 | if (env('APP_MAINTENANCE') === '1') { 18 | return true; 19 | } 20 | return $app->keyStorage->get('frontend.maintenance') === 'enabled'; 21 | } 22 | ], 23 | 'request' => [ 24 | 'enableCookieValidation' => false, 25 | ], 26 | 'user' => [ 27 | 'class' => yii\web\User::class, 28 | 'identityClass' => common\models\User::class, 29 | 'loginUrl' => ['/user/sign-in/login'], 30 | 'enableAutoLogin' => true, 31 | 'as afterLogin' => common\behaviors\LoginTimestampBehavior::class 32 | ] 33 | ] 34 | ]; 35 | 36 | return $config; 37 | -------------------------------------------------------------------------------- /api/modules/v1/Module.php: -------------------------------------------------------------------------------- 1 | user->identityClass = 'api\modules\v1\models\ApiUserIdentity'; 22 | Yii::$app->user->enableSession = false; 23 | Yii::$app->user->loginUrl = null; 24 | } 25 | 26 | /** 27 | * @return array 28 | */ 29 | public function behaviors() 30 | { 31 | $behaviors = parent::behaviors(); 32 | 33 | $behaviors['contentNegotiator'] = [ 34 | 'class' => ContentNegotiator::class, 35 | 'formats' => [ 36 | 'application/json' => Response::FORMAT_JSON, 37 | 'application/xml' => Response::FORMAT_XML, 38 | ], 39 | ]; 40 | 41 | $behaviors['rateLimiter'] = [ 42 | 'class' => RateLimiter::class, 43 | ]; 44 | 45 | return $behaviors; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /api/modules/v1/models/definitions/Article.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class Article extends \common\models\Article implements Linkable 13 | { 14 | public function fields() 15 | { 16 | return ['id', 'slug', 'thumbnail_base_url', 'thumbnail_path', 'title', 'body', 'status', 17 | 'published_at', 'created_by', 'updated_by', 'created_at', 'updated_at', 'category', 'articleAttachments']; 18 | } 19 | 20 | public function extraFields() 21 | { 22 | return ['category', 'articleAttachments']; 23 | } 24 | 25 | /** 26 | * Returns a list of links. 27 | * 28 | * @return array the links 29 | */ 30 | public function getLinks() 31 | { 32 | return [ 33 | Link::REL_SELF => Url::to(['article/view', 'id' => $this->id], true) 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /api/modules/v1/resources/User.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | class User extends \common\models\User 9 | { 10 | public function fields() 11 | { 12 | return ['id', 'username', 'created_at']; 13 | } 14 | 15 | public function extraFields() 16 | { 17 | return ['userProfile']; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /api/runtime/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /api/web/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | RewriteCond %{REQUEST_FILENAME} !-f 3 | RewriteCond %{REQUEST_FILENAME} !-d 4 | RewriteRule . index.php -------------------------------------------------------------------------------- /api/web/assets/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /api/web/index-test.php: -------------------------------------------------------------------------------- 1 | run(); 30 | -------------------------------------------------------------------------------- /api/web/index.php: -------------------------------------------------------------------------------- 1 | run(); 23 | -------------------------------------------------------------------------------- /api/yii: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | run(); 28 | exit($exitCode); 29 | -------------------------------------------------------------------------------- /api/yii.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem ------------------------------------------------------------- 4 | rem Yii command line bootstrap script for Windows. 5 | rem 6 | rem @author Qiang Xue 7 | rem @link http://www.yiiframework.com/ 8 | rem @copyright Copyright © 2012 Yii Software LLC 9 | rem @license http://www.yiiframework.com/license/ 10 | rem ------------------------------------------------------------- 11 | 12 | @setlocal 13 | 14 | set YII_PATH=%~dp0 15 | 16 | if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe 17 | 18 | "%PHP_COMMAND%" "%YII_PATH%yii" %* 19 | 20 | @endlocal 21 | -------------------------------------------------------------------------------- /backend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM yiisoftware/yii2-php:8.0-fpm 2 | 3 | WORKDIR /app -------------------------------------------------------------------------------- /backend/assets/BackendAsset.php: -------------------------------------------------------------------------------- 1 | [ 39 | '*.css', 40 | '*.js', 41 | '../img/*' 42 | ], 43 | "forceCopy" => YII_ENV_DEV, 44 | ]; 45 | 46 | /** 47 | * @var array 48 | */ 49 | public $depends = [ 50 | YiiAsset::class, 51 | AdminLte::class, 52 | Html5shiv::class, 53 | ]; 54 | } 55 | -------------------------------------------------------------------------------- /backend/config/_urlManager.php: -------------------------------------------------------------------------------- 1 | yii\web\UrlManager::class, 4 | 'enablePrettyUrl' => true, 5 | 'showScriptName' => false, 6 | ]; 7 | -------------------------------------------------------------------------------- /backend/config/base.php: -------------------------------------------------------------------------------- 1 | 'backend', 4 | 'basePath' => dirname(__DIR__), 5 | 'components' => [ 6 | 'urlManager' => require __DIR__ . '/_urlManager.php', 7 | 'frontendCache' => require Yii::getAlias('@frontend/config/_cache.php') 8 | ], 9 | ]; 10 | -------------------------------------------------------------------------------- /backend/config/bootstrap.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | -------------------------------------------------------------------------------- /backend/config/console.php: -------------------------------------------------------------------------------- 1 | [ 19 | 'class' => 'yii\web\ErrorAction', 20 | ], 21 | ]; 22 | } 23 | 24 | public function beforeAction($action) 25 | { 26 | $this->layout = Yii::$app->user->isGuest || !Yii::$app->user->can('loginToBackend') ? 'base' : 'common'; 27 | 28 | return parent::beforeAction($action); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /backend/controllers/TimelineEventController.php: -------------------------------------------------------------------------------- 1 | search(Yii::$app->request->queryParams); 24 | $dataProvider->sort = [ 25 | 'defaultOrder' => ['created_at' => SORT_DESC] 26 | ]; 27 | 28 | return $this->render('index', [ 29 | 'searchModel' => $searchModel, 30 | 'dataProvider' => $dataProvider, 31 | ]); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /backend/mail/layouts/html.php: -------------------------------------------------------------------------------- 1 | 8 | beginPage() ?> 9 | 10 | 11 | 12 | 13 | <?php echo Html::encode($this->title) ?> 14 | head() ?> 15 | 16 | 17 | beginBody() ?> 18 | 19 | endBody() ?> 20 | 21 | 22 | endPage() ?> 23 | -------------------------------------------------------------------------------- /backend/mail/layouts/text.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Create {modelClass}', [ 10 | 'modelClass' => 'Article', 11 | ]); 12 | 13 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Articles'), 'url' => ['index']]; 14 | $this->params['breadcrumbs'][] = $this->title; 15 | 16 | ?> 17 | 18 | render('_form', [ 19 | 'model' => $model, 20 | 'categories' => $categories, 21 | ]) ?> 22 | -------------------------------------------------------------------------------- /backend/modules/content/views/article/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Update {modelClass}: ', [ 9 | 'modelClass' => 'Article', 10 | ]) . ' ' . $model->title; 11 | 12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Articles'), 'url' => ['index']]; 13 | $this->params['breadcrumbs'][] = Yii::t('backend', 'Update'); 14 | 15 | ?> 16 | 17 | render('_form', [ 18 | 'model' => $model, 19 | 'categories' => $categories, 20 | ]) ?> 21 | -------------------------------------------------------------------------------- /backend/modules/content/views/category/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Update {modelClass}: ', [ 10 | 'modelClass' => 'Article Category', 11 | ]) . ' ' . $model->title; 12 | 13 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Article Categories'), 'url' => ['index']]; 14 | $this->params['breadcrumbs'][] = Yii::t('backend', 'Update'); 15 | 16 | ?> 17 | 18 | render('_form', [ 19 | 'model' => $model, 20 | 'categories' => $categories, 21 | ]) ?> 22 | -------------------------------------------------------------------------------- /backend/modules/content/views/page/_form.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | false, 15 | 'enableAjaxValidation' => true, 16 | ]) ?> 17 | 18 | field($model, 'title')->textInput(['maxlength' => true]) ?> 19 | 20 | field($model, 'slug')->textInput(['maxlength' => true]) ?> 21 | 22 | field($model, 'body')->widget( 23 | \yii\imperavi\Widget::class, 24 | [ 25 | 'plugins' => ['fullscreen', 'fontcolor', 'video'], 26 | 'options' => [ 27 | 'minHeight' => 400, 28 | 'maxHeight' => 400, 29 | 'buttonSource' => true, 30 | 'imageUpload' => Yii::$app->urlManager->createUrl(['/file/storage/upload-imperavi']), 31 | ], 32 | ] 33 | ) ?> 34 | 35 | field($model, 'view')->textInput(['maxlength' => true]) ?> 36 | 37 | field($model, 'status')->checkbox() ?> 38 | 39 |
40 | isNewRecord ? Yii::t('backend', 'Create') : Yii::t('backend', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> 41 |
42 | 43 | 44 | -------------------------------------------------------------------------------- /backend/modules/content/views/page/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Update {modelClass}: ', [ 9 | 'modelClass' => 'Page', 10 | ]) . ' ' . $model->title; 11 | 12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Pages'), 'url' => ['index']]; 13 | $this->params['breadcrumbs'][] = Yii::t('backend', 'Update'); 14 | 15 | ?> 16 | 17 | render('_form', [ 18 | 'model' => $model, 19 | ]) ?> 20 | -------------------------------------------------------------------------------- /backend/modules/file/Module.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'File Manager'); 8 | 9 | $this->params['breadcrumbs'][] = $this->title; 10 | 11 | ?> 12 | 13 | ['connector'], 15 | 'settings' => [ 16 | 'height' => '500px', 17 | 'width' => '100%' 18 | ], 19 | 'buttonNoConflict' => true, 20 | ]) ?> -------------------------------------------------------------------------------- /backend/modules/file/views/storage/view.php: -------------------------------------------------------------------------------- 1 | title = $model->name; 12 | 13 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'File Storage Items'), 'url' => ['index']]; 14 | $this->params['breadcrumbs'][] = $this->title; 15 | 16 | ?> 17 | 18 | 19 |
20 |
21 | $model->id], [ 22 | 'class' => 'btn btn-danger', 23 | 'data' => [ 24 | 'confirm' => Yii::t('backend', 'Are you sure you want to delete this item?'), 25 | 'method' => 'post', 26 | ], 27 | ]) ?> 28 |
29 |
30 | 31 | $model, 33 | 'attributes' => [ 34 | 'id', 35 | 'component', 36 | 'base_url:url', 37 | 'path', 38 | 'type', 39 | 'size', 40 | 'name', 41 | 'upload_ip', 42 | 'created_at:datetime', 43 | ], 44 | ]) ?> 45 |
46 |
47 | -------------------------------------------------------------------------------- /backend/modules/rbac/Module.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Create {modelClass}', [ 10 | 'modelClass' => 'Assignment', 11 | ]); 12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Assignments'), 'url' => ['index']]; 13 | $this->params['breadcrumbs'][] = $this->title; 14 | ?> 15 |
16 | 17 | render('_form', [ 18 | 'model' => $model, 19 | ]) ?> 20 | 21 |
22 | -------------------------------------------------------------------------------- /backend/modules/rbac/views/rbac-auth-assignment/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Update {modelClass}: ', [ 9 | 'modelClass' => 'Assignment', 10 | ]) . ' ' . $model->item_name; 11 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Assignments'), 'url' => ['index']]; 12 | $this->params['breadcrumbs'][] = ['label' => $model->item_name, 'url' => ['view', 'item_name' => $model->item_name, 'user_id' => $model->user_id]]; 13 | $this->params['breadcrumbs'][] = Yii::t('backend', 'Update'); 14 | ?> 15 |
16 | 17 | render('_form', [ 18 | 'model' => $model, 19 | ]) ?> 20 | 21 |
22 | -------------------------------------------------------------------------------- /backend/modules/rbac/views/rbac-auth-item-child/_form.php: -------------------------------------------------------------------------------- 1 | 13 | 14 | false, 16 | 'enableAjaxValidation' => true, 17 | ]) ?> 18 |
19 |
20 | 21 | field($model, 'parent')->dropDownList(ArrayHelper::map(RbacAuthItem::find()->all(), 'name', 'name'), ['prompt' => Yii::t('backend', 'Please select a parent item...')]) ?> 22 | 23 | field($model, 'child')->dropDownList(ArrayHelper::map(RbacAuthItem::find()->all(), 'name', 'name'), ['prompt' => Yii::t('backend', 'Please select a child item...')]) ?> 24 | 25 |
26 | 32 |
33 | 34 | -------------------------------------------------------------------------------- /backend/modules/rbac/views/rbac-auth-item-child/create.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Create {modelClass}', [ 10 | 'modelClass' => 'Child Item', 11 | ]); 12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Child Items'), 'url' => ['index']]; 13 | $this->params['breadcrumbs'][] = $this->title; 14 | ?> 15 |
16 | 17 | render('_form', [ 18 | 'model' => $model, 19 | ]) ?> 20 | 21 |
22 | -------------------------------------------------------------------------------- /backend/modules/rbac/views/rbac-auth-item-child/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Update {modelClass}: ', [ 9 | 'modelClass' => 'Child Item', 10 | ]) . $model->parent; 11 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Child Items'), 'url' => ['index']]; 12 | $this->params['breadcrumbs'][] = ['label' => $model->parent, 'url' => ['view', 'parent' => $model->parent, 'child' => $model->child]]; 13 | $this->params['breadcrumbs'][] = Yii::t('backend', 'Update'); 14 | ?> 15 |
16 | 17 | render('_form', [ 18 | 'model' => $model, 19 | ]) ?> 20 | 21 |
22 | -------------------------------------------------------------------------------- /backend/modules/rbac/views/rbac-auth-item/create.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Create {modelClass}', [ 10 | 'modelClass' => 'Item', 11 | ]); 12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Items'), 'url' => ['index']]; 13 | $this->params['breadcrumbs'][] = $this->title; 14 | ?> 15 |
16 | 17 | render('_form', [ 18 | 'model' => $model, 19 | ]) ?> 20 | 21 |
22 | -------------------------------------------------------------------------------- /backend/modules/rbac/views/rbac-auth-item/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Update {modelClass}: ', [ 9 | 'modelClass' => 'Item', 10 | ]) . $model->name; 11 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Items'), 'url' => ['index']]; 12 | $this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->name]]; 13 | $this->params['breadcrumbs'][] = Yii::t('backend', 'Update'); 14 | ?> 15 |
16 | 17 | render('_form', [ 18 | 'model' => $model, 19 | ]) ?> 20 | 21 |
22 | -------------------------------------------------------------------------------- /backend/modules/rbac/views/rbac-auth-rule/_form.php: -------------------------------------------------------------------------------- 1 | 11 | 12 | false, 14 | 'enableAjaxValidation' => true, 15 | ]) ?> 16 |
17 |
18 | 19 | field($model, 'name')->textInput(['maxlength' => true]) ?> 20 | 21 | field($model, 'data')->textInput() ?> 22 | 23 |
24 | 30 |
31 | 32 | -------------------------------------------------------------------------------- /backend/modules/rbac/views/rbac-auth-rule/create.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('frontend', 'Create Rule'); 10 | $this->params['breadcrumbs'][] = ['label' => Yii::t('frontend', 'Rules'), 'url' => ['index']]; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 |
14 | 15 | render('_form', [ 16 | 'model' => $model, 17 | ]) ?> 18 | 19 |
20 | -------------------------------------------------------------------------------- /backend/modules/rbac/views/rbac-auth-rule/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Update {modelClass}: ', [ 9 | 'modelClass' => 'Rule', 10 | ]) . $model->name; 11 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Rules'), 'url' => ['index']]; 12 | $this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->name]]; 13 | $this->params['breadcrumbs'][] = Yii::t('backend', 'Update'); 14 | ?> 15 |
16 | 17 | render('_form', [ 18 | 'model' => $model, 19 | ]) ?> 20 | 21 |
22 | -------------------------------------------------------------------------------- /backend/modules/rbac/views/rbac-auth-rule/view.php: -------------------------------------------------------------------------------- 1 | title = $model->name; 10 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Rules'), 'url' => ['index']]; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 |
14 |
15 |
16 | $model->name], ['class' => 'btn btn-primary']) ?> 17 | $model->name], [ 18 | 'class' => 'btn btn-danger', 19 | 'data' => [ 20 | 'confirm' => Yii::t('backend', 'Are you sure you want to delete this item?'), 21 | 'method' => 'post', 22 | ], 23 | ]) ?> 24 |
25 |
26 | $model, 28 | 'attributes' => [ 29 | 'name', 30 | 'data', 31 | 'created_at:datetime', 32 | 'updated_at:datetime', 33 | ], 34 | ]) ?> 35 |
36 |
37 |
38 | -------------------------------------------------------------------------------- /backend/modules/system/Module.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | 6 | namespace backend\modules\system\controllers; 7 | 8 | use Probe\ProviderFactory; 9 | use Yii; 10 | use yii\web\Controller; 11 | use yii\web\Response; 12 | 13 | class InformationController extends Controller 14 | { 15 | 16 | public $layout = '@backend/views/layouts/common'; 17 | 18 | public function actionIndex() 19 | { 20 | $provider = ProviderFactory::create(); 21 | if ($provider) { 22 | if (Yii::$app->request->isAjax) { 23 | Yii::$app->response->format = Response::FORMAT_JSON; 24 | if ($key = Yii::$app->request->get('data')) { 25 | switch ($key) { 26 | case 'cpu_usage': 27 | return $provider->getCpuUsage(); 28 | break; 29 | case 'memory_usage': 30 | return ($provider->getTotalMem() - $provider->getFreeMem()) / $provider->getTotalMem(); 31 | break; 32 | } 33 | } 34 | } else { 35 | return $this->render('index', ['provider' => $provider]); 36 | } 37 | } 38 | 39 | return $this->render('fail'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /backend/modules/system/views/information/fail.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | use yii\helpers\Html; 6 | 7 | $this->title = Yii::t('backend', 'System Information'); 8 | ?> 9 | Html::a('trntv/probe', 'https://github.com/trntv/probe#user-content-supported-os')] 13 | ); 14 | -------------------------------------------------------------------------------- /backend/modules/system/views/key-storage/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Update {modelClass}: ', [ 9 | 'modelClass' => 'Key Storage Item', 10 | ]) . ' ' . $model->key; 11 | 12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Key Storage Items'), 'url' => ['index']]; 13 | $this->params['breadcrumbs'][] = Yii::t('backend', 'Update'); 14 | 15 | ?> 16 | 17 | render('_form', [ 18 | 'model' => $model, 19 | ]) ?> 20 | -------------------------------------------------------------------------------- /backend/modules/system/views/log/view.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Error #{id}', ['id' => $model->id]); 12 | 13 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'System Logs'), 'url' => ['index']]; 14 | $this->params['breadcrumbs'][] = $this->title; 15 | 16 | ?> 17 | 18 |

19 | $model->id], ['class' => 'btn btn-danger', 'data' => ['method' => 'post']]) ?> 20 |

21 | 22 | $model, 24 | 'attributes' => [ 25 | 'id', 26 | 'level', 27 | 'category', 28 | [ 29 | 'attribute' => 'log_time', 30 | 'format' => 'datetime', 31 | 'value' => (int)$model->log_time, 32 | ], 33 | 'prefix:ntext', 34 | [ 35 | 'attribute' => 'message', 36 | 'format' => 'raw', 37 | 'value' => Html::tag('pre', $model->message, ['style' => 'white-space: pre-wrap']), 38 | ], 39 | ], 40 | ]) ?> 41 | -------------------------------------------------------------------------------- /backend/modules/system/views/settings/index.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | 6 | use common\components\keyStorage\FormWidget; 7 | use rmrevin\yii\fontawesome\FAS; 8 | 9 | /** 10 | * @var $model \common\components\keyStorage\FormModel 11 | */ 12 | 13 | $this->title = Yii::t('backend', 'Application settings'); 14 | 15 | ?> 16 | 17 | $model, 19 | 'formClass' => \yii\bootstrap4\ActiveForm::class, 20 | 'submitText' => FAS::icon('save').' '.Yii::t('backend', 'Save'), 21 | 'submitOptions' => ['class' => 'btn btn-primary'], 22 | ]) ?> 23 | -------------------------------------------------------------------------------- /backend/modules/translation/Module.php: -------------------------------------------------------------------------------- 1 | params['availableLocales'] as $locale => $name) { 18 | if ($locale !== Yii::$app->sourceLanguage) 19 | $languages[substr($locale, 0, 2)] = $name; 20 | } 21 | 22 | return $languages; 23 | } 24 | 25 | /** 26 | * @return array 27 | */ 28 | public function getPrefixedLanguages() 29 | { 30 | $languages = []; 31 | foreach ($this->getLanguages() as $lang => $name) { 32 | $languages['lang_'.$lang] = $name; 33 | } 34 | 35 | return $languages; 36 | } 37 | 38 | /** 39 | * @return string 40 | */ 41 | public function stripLanguagePrefix($name) 42 | { 43 | return substr($name, 5); 44 | } 45 | } -------------------------------------------------------------------------------- /backend/modules/translation/views/default/_form.php: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | field($model->getModel('source'), 'category')->textInput(['maxlength' => 32]) ?> 17 | 18 | field($model->getModel('source'), 'message')->textInput() ?> 19 | 20 | getModel('source')->isNewRecord) { ?> 21 |
22 |
23 |

24 |
25 |
26 | $name) { 27 | echo $form->field($model->getModel($language), 'translation')->textInput([ 28 | 'id' => $language . '-translation', 29 | 'name' => $language . '[translation]', 30 | ])->label($name); 31 | } ?> 32 |
33 |
34 | 35 | 36 |
37 | 'btn btn-primary']) ?> 38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /backend/modules/translation/views/default/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Update {modelClass}: ', [ 10 | 'modelClass' => 'I18n Source Message', 11 | ]) . ' ' . $model->getModel('source')->message; 12 | 13 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'I18n Source Messages'), 'url' => ['index']]; 14 | $this->params['breadcrumbs'][] = ['label' => $model->getModel('source')->message, 'url' => ['update', 'id' => $model->getModel('source')->id]]; 15 | $this->params['breadcrumbs'][] = Yii::t('backend', 'Update'); 16 | 17 | ?> 18 | 19 | render('_form', [ 20 | 'model' => $model, 21 | 'languages' => $languages, 22 | ]) ?> 23 | 24 | 25 | -------------------------------------------------------------------------------- /backend/modules/widget/Module.php: -------------------------------------------------------------------------------- 1 | 13 | 14 | false, 16 | 'enableAjaxValidation' => true, 17 | ]) ?> 18 |
19 | isNewRecord) : ?> 20 |
21 |

22 | 23 |

24 |
25 | 26 |
27 | field($model, 'key')->textInput(['maxlength' => 1024]) ?> 28 | 29 | field($model, 'status')->checkbox() ?> 30 |
31 | 37 |
38 | 39 | -------------------------------------------------------------------------------- /backend/modules/widget/views/carousel/item/create.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Create {modelClass}', [ 9 | 'modelClass' => 'Widget Carousel Item', 10 | ]); 11 | 12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Widget Carousel Items'), 'url' => ['/widget/carousel/index']]; 13 | $this->params['breadcrumbs'][] = ['label' => $carousel->key, 'url' => ['/widget/carousel/update', 'id' => $carousel->id]]; 14 | $this->params['breadcrumbs'][] = Yii::t('backend', 'Create'); 15 | 16 | ?> 17 | 18 | render('_form', [ 19 | 'model' => $model, 20 | ]) ?> 21 | -------------------------------------------------------------------------------- /backend/modules/widget/views/carousel/item/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Update {modelClass}: ', [ 9 | 'modelClass' => 'Widget Carousel Item', 10 | ]) . ' ' . $model->id; 11 | 12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Widget Carousel Items'), 'url' => ['/widget/carousel/index']]; 13 | $this->params['breadcrumbs'][] = ['label' => $model->carousel->key, 'url' => ['/widget/carousel/update', 'id' => $model->carousel->id]]; 14 | $this->params['breadcrumbs'][] = Yii::t('backend', 'Update'); 15 | 16 | ?> 17 | 18 | render('_form', [ 19 | 'model' => $model, 20 | ]) ?> 21 | -------------------------------------------------------------------------------- /backend/modules/widget/views/menu/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Update {modelClass}: ', [ 9 | 'modelClass' => 'Widget Menu', 10 | ]) . ' ' . $model->title; 11 | 12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Widget Menus'), 'url' => ['index']]; 13 | $this->params['breadcrumbs'][] = Yii::t('backend', 'Update'); 14 | 15 | ?> 16 | 17 | render('_form', [ 18 | 'model' => $model, 19 | ]) ?> 20 | -------------------------------------------------------------------------------- /backend/modules/widget/views/text/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Update {modelClass}: ', [ 9 | 'modelClass' => 'Text Block', 10 | ]) . ' ' . $model->title; 11 | 12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Text Blocks'), 'url' => ['index']]; 13 | $this->params['breadcrumbs'][] = Yii::t('backend', 'Update'); 14 | 15 | ?> 16 | 17 | render('_form', [ 18 | 'model' => $model, 19 | ]) ?> 20 | -------------------------------------------------------------------------------- /backend/runtime/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /backend/views/_gii/templates/views/create.php: -------------------------------------------------------------------------------- 1 | 13 | 14 | /** 15 | * @var yii\web\View $this 16 | * @var modelClass, '\\') ?> $model 17 | */ 18 | 19 | $this->title = generateString('Create {modelClass}', ['modelClass' => Inflector::camel2words(StringHelper::basename($generator->modelClass))]) ?>; 20 | $this->params['breadcrumbs'][] = ['label' => generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']]; 21 | $this->params['breadcrumbs'][] = $this->title; 22 | ?> 23 |
24 | 25 | $this->render('_form', [ 26 | 'model' => $model, 27 | ]) ?> 28 | 29 |
30 | -------------------------------------------------------------------------------- /backend/views/_gii/templates/views/update.php: -------------------------------------------------------------------------------- 1 | generateUrlParams(); 12 | 13 | echo " 15 | 16 | /** 17 | * @var yii\web\View $this 18 | * @var modelClass, '\\') ?> $model 19 | */ 20 | 21 | $this->title = generateString('Update {modelClass}: ', ['modelClass' => Inflector::camel2words(StringHelper::basename($generator->modelClass))]) ?> . ' ' . $model->getNameAttribute() ?>; 22 | $this->params['breadcrumbs'][] = ['label' => generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']]; 23 | $this->params['breadcrumbs'][] = ['label' => $model->getNameAttribute() ?>, 'url' => ['view', ]]; 24 | $this->params['breadcrumbs'][] = generateString('Update') ?>; 25 | ?> 26 |
27 | 28 | $this->render('_form', [ 29 | 'model' => $model, 30 | ]) ?> 31 | 32 |
33 | -------------------------------------------------------------------------------- /backend/views/layouts/clear.php: -------------------------------------------------------------------------------- 1 | 7 | beginContent('@backend/views/layouts/common.php'); ?> 8 | 9 | endContent(); ?> 10 | -------------------------------------------------------------------------------- /backend/views/layouts/main.php: -------------------------------------------------------------------------------- 1 | 4 | * @author Victor Gonzalez 5 | * @var yii\web\View $this 6 | * @var string $content 7 | */ 8 | ?> 9 | beginContent('@backend/views/layouts/common.php'); ?> 10 |
11 |
12 | 13 |
14 |
15 | endContent(); ?> 16 | -------------------------------------------------------------------------------- /backend/views/sign-in/account.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Edit account') 14 | ?> 15 | 16 | 17 | 28 | -------------------------------------------------------------------------------- /backend/views/timeline-event/_item.php: -------------------------------------------------------------------------------- 1 | 4 | * @var $model common\models\TimelineEvent 5 | */ 6 | ?> 7 |
8 | 9 | 10 | formatter->asRelativeTime($model->created_at) ?> 11 | 12 |

13 | 14 |

15 | 16 |
17 |
18 |
:
19 |
application ?>
20 | 21 |
:
22 |
category ?>
23 | 24 |
:
25 |
event ?>
26 | 27 |
:
28 |
formatter->asDatetime($model->created_at) ?>
29 |
30 |
31 |
-------------------------------------------------------------------------------- /backend/views/timeline-event/_search.php: -------------------------------------------------------------------------------- 1 | 10 | 11 | 32 | -------------------------------------------------------------------------------- /backend/views/timeline-event/user/delete.php: -------------------------------------------------------------------------------- 1 | 4 | * @author Victor Gonzalez 5 | * @var common\models\TimelineEvent $model 6 | */ 7 | 8 | use rmrevin\yii\fontawesome\FAS; 9 | use yii\helpers\Html; 10 | ?> 11 | 12 | 'bg-red']) ?> 13 |
14 | 15 | formatter->asRelativeTime($model->created_at) ?> 16 | 17 | 18 |

19 | Html::tag('b', $model->data['public_identity']), 21 | 'deleted_at' => Yii::$app->formatter->asDatetime($model->data['deleted_at']) 22 | ]) ?> 23 |

24 |
-------------------------------------------------------------------------------- /backend/views/timeline-event/user/signup.php: -------------------------------------------------------------------------------- 1 | 4 | * @author Victor Gonzalez 5 | * @var common\models\TimelineEvent $model 6 | */ 7 | 8 | use rmrevin\yii\fontawesome\FAS; 9 | use yii\helpers\Html; 10 | ?> 11 | 12 | 'bg-green']) ?> 13 |
14 | 15 | formatter->asRelativeTime($model->created_at) ?> 16 | 17 | 18 |

19 | Html::a($model->data['public_identity'], ['user/view', 'id' => $model->data['user_id']]), 21 | 'created_at' => Yii::$app->formatter->asDatetime($model->data['created_at']) 22 | ]) ?> 23 |

24 |
-------------------------------------------------------------------------------- /backend/views/user/_form.php: -------------------------------------------------------------------------------- 1 | 13 | 14 |
15 | 16 |
17 |
18 | field($model, 'username') ?> 19 | field($model, 'email') ?> 20 | field($model, 'password')->passwordInput() ?> 21 | field($model, 'status')->dropDownList(User::statuses()) ?> 22 | field($model, 'roles')->checkboxList($roles) ?> 23 |
24 | 27 |
28 | 29 |
30 | -------------------------------------------------------------------------------- /backend/views/user/_search.php: -------------------------------------------------------------------------------- 1 | 10 | 11 | 42 | -------------------------------------------------------------------------------- /backend/views/user/create.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Create {modelClass}', [ 6 | 'modelClass' => 'User', 7 | ]); 8 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Users'), 'url' => ['index']]; 9 | $this->params['breadcrumbs'][] = $this->title; 10 | ?> 11 |
12 | 13 | render('_form', [ 14 | 'model' => $model, 15 | 'roles' => $roles 16 | ]) ?> 17 | 18 |
19 | -------------------------------------------------------------------------------- /backend/views/user/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('backend', 'Update {modelClass}: ', ['modelClass' => 'User']) . ' ' . $model->username; 10 | $this->params['breadcrumbs'][] = ['label' => Yii::t('backend', 'Users'), 'url' => ['index']]; 11 | $this->params['breadcrumbs'][] = ['label' => $model->email, 'url' => ['view', 'id' => $model->email]]; 12 | $this->params['breadcrumbs'][] = ['label'=>Yii::t('backend', 'Update')]; 13 | ?> 14 |
15 | 16 | render('_form', [ 17 | 'model' => $model, 18 | 'roles' => $roles 19 | ]) ?> 20 | 21 |
22 | -------------------------------------------------------------------------------- /backend/web/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | RewriteCond %{REQUEST_FILENAME} !-f 3 | RewriteCond %{REQUEST_FILENAME} !-d 4 | RewriteRule . index.php -------------------------------------------------------------------------------- /backend/web/assets/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /backend/web/bundle/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /backend/web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yii-starter-kit/yii2-starter-kit/4f019ad2bba87b6abebcb340ece6fa1475fb2f71/backend/web/favicon.ico -------------------------------------------------------------------------------- /backend/web/img/anonymous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yii-starter-kit/yii2-starter-kit/4f019ad2bba87b6abebcb340ece6fa1475fb2f71/backend/web/img/anonymous.png -------------------------------------------------------------------------------- /backend/web/img/yii2-starter-kit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yii-starter-kit/yii2-starter-kit/4f019ad2bba87b6abebcb340ece6fa1475fb2f71/backend/web/img/yii2-starter-kit.gif -------------------------------------------------------------------------------- /backend/web/index-test.php: -------------------------------------------------------------------------------- 1 | run(); 31 | -------------------------------------------------------------------------------- /backend/web/index.php: -------------------------------------------------------------------------------- 1 | run(); 24 | -------------------------------------------------------------------------------- /backend/web/js/app.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | }); -------------------------------------------------------------------------------- /backend/web/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / -------------------------------------------------------------------------------- /backend/yii: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | run(); 28 | exit($exitCode); 29 | -------------------------------------------------------------------------------- /backend/yii.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem ------------------------------------------------------------- 4 | rem Yii command line bootstrap script for Windows. 5 | rem 6 | rem @author Qiang Xue 7 | rem @link http://www.yiiframework.com/ 8 | rem @copyright Copyright © 2012 Yii Software LLC 9 | rem @license http://www.yiiframework.com/license/ 10 | rem ------------------------------------------------------------- 11 | 12 | @setlocal 13 | 14 | set YII_PATH=%~dp0 15 | 16 | if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe 17 | 18 | "%PHP_COMMAND%" "%YII_PATH%yii" %* 19 | 20 | @endlocal 21 | -------------------------------------------------------------------------------- /codeception.yml: -------------------------------------------------------------------------------- 1 | include: 2 | - tests/common 3 | - tests/console 4 | - tests/backend 5 | - tests/frontend 6 | - tests/api 7 | 8 | paths: 9 | output: tests/_output 10 | 11 | settings: 12 | colors: true 13 | 14 | db: 15 | dsn: 16 | username: 17 | password: 18 | -------------------------------------------------------------------------------- /common/assets/AdminLte.php: -------------------------------------------------------------------------------- 1 | 'lt IE 9' 22 | ]; 23 | } 24 | -------------------------------------------------------------------------------- /common/assets/JquerySlimScroll.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class JquerySlimScroll extends AssetBundle 14 | { 15 | /** 16 | * @var string 17 | */ 18 | public $sourcePath = '@npm/jquery-slimscroll'; 19 | /** 20 | * @var array 21 | */ 22 | public $js = [ 23 | 'jquery.slimscroll.min.js' 24 | ]; 25 | /** 26 | * @var array 27 | */ 28 | public $depends = [ 29 | JqueryAsset::class 30 | ]; 31 | } 32 | -------------------------------------------------------------------------------- /common/behaviors/LoginTimestampBehavior.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class LoginTimestampBehavior extends Behavior 12 | { 13 | /** 14 | * @var string 15 | */ 16 | public $attribute = 'logged_at'; 17 | 18 | 19 | /** 20 | * @inheritdoc 21 | */ 22 | public function events() 23 | { 24 | return [ 25 | User::EVENT_AFTER_LOGIN => 'afterLogin' 26 | ]; 27 | } 28 | 29 | /** 30 | * @param $event \yii\web\UserEvent 31 | */ 32 | public function afterLogin($event) 33 | { 34 | $user = $event->identity; 35 | $user->touch($this->attribute); 36 | $user->save(false); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /common/commands/AddToTimelineCommand.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class AddToTimelineCommand extends BaseObject implements SelfHandlingCommand 14 | { 15 | /** 16 | * @var string 17 | */ 18 | public $category; 19 | /** 20 | * @var string 21 | */ 22 | public $event; 23 | /** 24 | * @var mixed 25 | */ 26 | public $data; 27 | 28 | /** 29 | * @param AddToTimelineCommand $command 30 | * @return bool 31 | */ 32 | public function handle($command) 33 | { 34 | $model = new TimelineEvent(); 35 | $model->application = Yii::$app->id; 36 | $model->category = $command->category; 37 | $model->event = $command->event; 38 | $model->data = json_encode($command->data, JSON_UNESCAPED_UNICODE); 39 | return $model->save(false); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /common/components/filesystem/LocalFlysystemBuilder.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class LocalFlysystemBuilder implements FilesystemBuilderInterface 14 | { 15 | public $path; 16 | 17 | public function build() 18 | { 19 | $adapter = new Local(\Yii::getAlias($this->path)); 20 | return new Filesystem($adapter); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /common/components/log/NotFoundTarget.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class MaintenanceAsset extends AssetBundle 13 | { 14 | public $sourcePath = '@common/components/maintenance/assets'; 15 | 16 | public $css = [ 17 | 'css/maintenance.css' 18 | ]; 19 | 20 | public $depends = [ 21 | 'yii\web\YiiAsset', 22 | 'yii\bootstrap4\BootstrapAsset' 23 | ]; 24 | } 25 | -------------------------------------------------------------------------------- /common/components/maintenance/assets/css/maintenance.css: -------------------------------------------------------------------------------- 1 | body.maintenance-body { 2 | background: #555555; 3 | } 4 | /*# sourceMappingURL=maintenance.map */ -------------------------------------------------------------------------------- /common/components/maintenance/assets/css/maintenance.less: -------------------------------------------------------------------------------- 1 | body.maintenance-body{ 2 | background: #555555; 3 | } -------------------------------------------------------------------------------- /common/components/maintenance/assets/css/maintenance.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["maintenance.less"],"names":[],"mappings":"AAAA,IAAI;EACF,mBAAA","file":"undefined"} -------------------------------------------------------------------------------- /common/components/maintenance/controllers/MaintenanceController.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class MaintenanceController extends Controller 13 | { 14 | /** 15 | * @var int 16 | */ 17 | public $statusCode = 503; 18 | /** 19 | * @var int 20 | */ 21 | public $retryAfter; 22 | /** 23 | * @var string|null 24 | */ 25 | public $maintenanceLayout; 26 | /** 27 | * @var string|null 28 | */ 29 | public $maintenanceView; 30 | /** 31 | * @var string|null 32 | */ 33 | public $maintenanceText; 34 | 35 | /** 36 | * @return string 37 | */ 38 | public function actionIndex() 39 | { 40 | $this->layout = $this->maintenanceLayout; 41 | 42 | Yii::$app->response->statusCode = $this->statusCode; 43 | Yii::$app->response->headers->set('Retry-After', $this->retryAfter); 44 | 45 | return $this->render($this->maintenanceView, [ 46 | 'maintenanceText' => $this->maintenanceText, 47 | 'retryAfter' => $this->retryAfter 48 | ]); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /common/components/maintenance/views/layouts/main.php: -------------------------------------------------------------------------------- 1 | 4 | * @var $this \yii\web\View 5 | * @var $content string 6 | */ 7 | 8 | use yii\helpers\Html; 9 | 10 | \yii\bootstrap4\BootstrapAsset::register($this) 11 | ?> 12 | beginPage() ?> 13 | 14 | 15 | 16 | 17 | <?php echo Html::encode(Yii::$app->name); ?> 18 | head(); ?> 19 | 20 | 21 | beginBody() ?> 22 |
23 | 24 |
25 | endBody() ?> 26 | 27 | 28 | endPage() ?> 29 | -------------------------------------------------------------------------------- /common/components/maintenance/views/maintenance/index.php: -------------------------------------------------------------------------------- 1 | 4 | * @var string $maintenanceText 5 | * @var int|string $retryAfter 6 | */ 7 | ?> 8 |
9 |

10 | $retryAfter, 12 | 'adminEmail' => Yii::$app->params['adminEmail'] 13 | ]) ?> 14 |

15 |
-------------------------------------------------------------------------------- /common/config/bootstrap.php: -------------------------------------------------------------------------------- 1 | 'db', 8 | // Connection component to use. Optional. 9 | 'db' => 'db', 10 | // Custom source message table. Optional. 11 | 'sourceMessageTable' => '{{%i18n_source_message}}', 12 | // Custom name for translation message table. Optional. 13 | 'messageTable' => '{{%i18n_message}}', 14 | ] 15 | ); 16 | -------------------------------------------------------------------------------- /common/config/messages/php.php: -------------------------------------------------------------------------------- 1 | 'php', 8 | // Root directory containing message translations. 9 | 'messagePath' => Yii::getAlias('@common/messages'), 10 | // boolean, whether the message file should be overwritten with the merged messages 11 | 'overwrite' => true, 12 | ] 13 | ); 14 | -------------------------------------------------------------------------------- /common/config/messages/po.php: -------------------------------------------------------------------------------- 1 | 'po', 8 | // Root directory containing message translations. 9 | 'messagePath' => Yii::getAlias('@common/messages'), 10 | // Name of the file that will be used for translations. 11 | 'catalog' => 'messages', 12 | // boolean, whether the message file should be overwritten with the merged messages 13 | 'overwrite' => true, 14 | ] 15 | ); 16 | -------------------------------------------------------------------------------- /common/config/web.php: -------------------------------------------------------------------------------- 1 | [ 4 | 'assetManager' => [ 5 | 'class' => yii\web\AssetManager::class, 6 | 'linkAssets' => env('LINK_ASSETS'), 7 | 'appendTimestamp' => YII_ENV_DEV 8 | ] 9 | ], 10 | 'as locale' => [ 11 | 'class' => common\behaviors\LocaleBehavior::class, 12 | 'enablePreferredLanguage' => true 13 | ], 14 | 'container' => [ 15 | 'definitions' => [ 16 | \yii\widgets\LinkPager::class => \yii\bootstrap4\LinkPager::class, 17 | ], 18 | ], 19 | ]; 20 | 21 | if (YII_DEBUG) { 22 | $config['bootstrap'][] = 'debug'; 23 | $config['modules']['debug'] = [ 24 | 'class' => yii\debug\Module::class, 25 | 'allowedIPs' => ['*'], 26 | ]; 27 | } 28 | 29 | if (YII_ENV_DEV) { 30 | $config['modules']['gii'] = [ 31 | 'allowedIPs' => ['*'], 32 | ]; 33 | } 34 | 35 | 36 | return $config; 37 | -------------------------------------------------------------------------------- /common/env.php: -------------------------------------------------------------------------------- 1 | load(); 12 | 13 | /** 14 | * Init application constants 15 | */ 16 | defined('YII_DEBUG') or define('YII_DEBUG', env('YII_DEBUG')); 17 | defined('YII_ENV') or define('YII_ENV', env('YII_ENV', 'prod')); 18 | -------------------------------------------------------------------------------- /common/grid/EnumColumn.php: -------------------------------------------------------------------------------- 1 | 'common\grid\EnumColumn', 12 | * 'attribute' => 'role', 13 | * 'enum' => User::getRoles() 14 | * ] 15 | * @package common\components\grid 16 | */ 17 | class EnumColumn extends DataColumn 18 | { 19 | /** 20 | * @var array List of value => name pairs 21 | */ 22 | public $enum = []; 23 | /** 24 | * @var bool 25 | */ 26 | public $loadFilterDefaultValues = true; 27 | 28 | /** 29 | * @inheritdoc 30 | */ 31 | public function init() 32 | { 33 | if ($this->loadFilterDefaultValues && $this->filter === null) { 34 | $this->filter = $this->enum; 35 | } 36 | } 37 | 38 | /** 39 | * @param mixed $model 40 | * @param mixed $key 41 | * @param int $index 42 | * @return mixed 43 | */ 44 | public function getDataCellValue($model, $key, $index) 45 | { 46 | $value = parent::getDataCellValue($model, $key, $index); 47 | return ArrayHelper::getValue($this->enum, $value, $value); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /common/migrations/db/m140703_123055_log.php: -------------------------------------------------------------------------------- 1 | createTable('{{%page}}', [ 13 | 'id' => $this->primaryKey(), 14 | 'slug' => $this->string(2048)->notNull(), 15 | 'title' => $this->string(512)->notNull(), 16 | 'body' => $this->text()->notNull(), 17 | 'view' => $this->string(), 18 | 'status' => $this->smallInteger()->notNull(), 19 | 'created_at' => $this->integer(), 20 | 'updated_at' => $this->integer(), 21 | ]); 22 | } 23 | 24 | /** 25 | * @return bool|void 26 | */ 27 | public function down() 28 | { 29 | $this->dropTable('{{%page}}'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /common/migrations/db/m140703_123813_rbac.php: -------------------------------------------------------------------------------- 1 | createTable('{{%widget_menu}}', [ 13 | 'id' => $this->primaryKey(), 14 | 'key' => $this->string(32)->notNull(), 15 | 'title' => $this->string()->notNull(), 16 | 'items' => $this->text()->notNull(), 17 | 'status' => $this->smallInteger()->notNull()->defaultValue(0) 18 | ]); 19 | } 20 | 21 | /** 22 | * @return bool|void 23 | */ 24 | public function down() 25 | { 26 | $this->dropTable('{{%widget_menu}}'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /common/migrations/db/m140709_173333_widget_text.php: -------------------------------------------------------------------------------- 1 | createTable('{{%widget_text}}', [ 13 | 'id' => $this->primaryKey(), 14 | 'key' => $this->string()->notNull(), 15 | 'title' => $this->string()->notNull(), 16 | 'body' => $this->text()->notNull(), 17 | 'status' => $this->smallInteger(), 18 | 'created_at' => $this->integer(), 19 | 'updated_at' => $this->integer(), 20 | ]); 21 | 22 | $this->createIndex('idx_widget_text_key', '{{%widget_text}}', 'key'); 23 | } 24 | 25 | /** 26 | * @return bool|void 27 | */ 28 | public function down() 29 | { 30 | $this->dropTable('{{%widget_text}}'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/migrations/db/m140805_084745_key_storage_item.php: -------------------------------------------------------------------------------- 1 | createTable('{{%key_storage_item}}', [ 13 | 'key' => $this->string(128)->notNull(), 14 | 'value' => $this->text()->notNull(), 15 | 'comment' => $this->text(), 16 | 'updated_at' => $this->integer(), 17 | 'created_at' => $this->integer() 18 | ]); 19 | 20 | $this->addPrimaryKey('pk_key_storage_item_key', '{{%key_storage_item}}', 'key'); 21 | $this->createIndex('idx_key_storage_item_key', '{{%key_storage_item}}', 'key', true); 22 | } 23 | 24 | /** 25 | * @return bool|void 26 | */ 27 | public function down() 28 | { 29 | $this->dropTable('{{%key_storage_item}}'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /common/migrations/db/m141012_101932_i18n_tables.php: -------------------------------------------------------------------------------- 1 | createTable('{{%i18n_source_message}}', [ 13 | 'id' => $this->primaryKey(), 14 | 'category' => $this->string(32), 15 | 'message' => $this->text() 16 | ]); 17 | 18 | $this->createTable('{{%i18n_message}}', [ 19 | 'id' => $this->integer(), 20 | 'language' => $this->string(16), 21 | 'translation' => $this->text() 22 | ]); 23 | 24 | $this->addPrimaryKey('i18n_message_pk', '{{%i18n_message}}', ['id', 'language']); 25 | $this->addForeignKey('fk_i18n_message_source_message', '{{%i18n_message}}', 'id', '{{%i18n_source_message}}', 'id', 'cascade', 'restrict'); 26 | } 27 | 28 | /** 29 | * @return bool|void 30 | */ 31 | public function safeDown() 32 | { 33 | $this->dropForeignKey('fk_i18n_message_source_message', '{{%i18n_message}}'); 34 | $this->dropTable('{{%i18n_message}}'); 35 | $this->dropTable('{{%i18n_source_message}}'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /common/migrations/db/m150318_213934_file_storage_item.php: -------------------------------------------------------------------------------- 1 | createTable('{{%file_storage_item}}', [ 13 | 'id' => $this->primaryKey(), 14 | 'component' => $this->string()->notNull(), 15 | 'base_url' => $this->string(1024)->notNull(), 16 | 'path' => $this->string(1024)->notNull(), 17 | 'type' => $this->string(), 18 | 'size' => $this->integer(), 19 | 'name' => $this->string(), 20 | 'upload_ip' => $this->string(45), 21 | 'created_at' => $this->integer()->notNull() 22 | ]); 23 | } 24 | 25 | /** 26 | * @return bool|void 27 | */ 28 | public function down() 29 | { 30 | $this->dropTable('{{%file_storage_item}}'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/migrations/db/m150929_074021_article_attachment_order.php: -------------------------------------------------------------------------------- 1 | addColumn('{{%article_attachment}}', 'order', $this->integer()); 13 | } 14 | 15 | /** 16 | * @return bool|void 17 | */ 18 | public function down() 19 | { 20 | $this->dropColumn('{{%article_attachment}}', 'order'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /common/migrations/db/m160203_095604_user_token.php: -------------------------------------------------------------------------------- 1 | createTable('{{%user_token}}', [ 13 | 'id' => $this->primaryKey(), 14 | 'user_id' => $this->integer()->notNull(), 15 | 'type' => $this->string()->notNull(), 16 | 'token' => $this->string(40)->notNull(), 17 | 'expire_at' => $this->integer(), 18 | 'created_at' => $this->integer(), 19 | 'updated_at' => $this->integer() 20 | ]); 21 | } 22 | 23 | /** 24 | * @return bool|void 25 | */ 26 | public function down() 27 | { 28 | $this->dropTable('{{%user_token}}'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /common/migrations/db/m190130_155645_add_article_slug_index.php: -------------------------------------------------------------------------------- 1 | alterColumn('{{%article}}', 'slug', $this->string(255)->notNull()); 16 | $this->alterColumn('{{%article_category}}', 'slug', $this->string(255)->notNull()); 17 | $this->createIndex('idx_article_slug', '{{%article}}', 'slug', true); 18 | $this->createIndex('idx_article_category_slug', '{{%article_category}}', 'slug', true); 19 | } 20 | 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function safeDown() 25 | { 26 | $this->dropIndex('idx_article_slug', '{{%article}}'); 27 | $this->dropIndex('idx_article_category_slug', '{{%article_category}}'); 28 | $this->alterColumn('{{%article}}', 'slug', $this->string(1024)->notNull()); 29 | $this->alterColumn('{{%article_category}}', 'slug', $this->string(1024)->notNull()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /common/migrations/rbac/m150625_214101_roles.php: -------------------------------------------------------------------------------- 1 | auth->removeAll(); 15 | 16 | $user = $this->auth->createRole(User::ROLE_USER); 17 | $this->auth->add($user); 18 | 19 | $manager = $this->auth->createRole(User::ROLE_MANAGER); 20 | $this->auth->add($manager); 21 | $this->auth->addChild($manager, $user); 22 | 23 | $admin = $this->auth->createRole(User::ROLE_ADMINISTRATOR); 24 | $this->auth->add($admin); 25 | $this->auth->addChild($admin, $manager); 26 | $this->auth->addChild($admin, $user); 27 | 28 | $this->auth->assign($admin, 1); 29 | $this->auth->assign($manager, 2); 30 | $this->auth->assign($user, 3); 31 | } 32 | 33 | /** 34 | * @return bool|void 35 | */ 36 | public function down() 37 | { 38 | $this->auth->remove($this->auth->getRole(User::ROLE_ADMINISTRATOR)); 39 | $this->auth->remove($this->auth->getRole(User::ROLE_MANAGER)); 40 | $this->auth->remove($this->auth->getRole(User::ROLE_USER)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /common/migrations/rbac/m150625_215624_init_permissions.php: -------------------------------------------------------------------------------- 1 | auth->getRole(User::ROLE_MANAGER); 11 | $administratorRole = $this->auth->getRole(User::ROLE_ADMINISTRATOR); 12 | 13 | $loginToBackend = $this->auth->createPermission('loginToBackend'); 14 | $this->auth->add($loginToBackend); 15 | 16 | $this->auth->addChild($managerRole, $loginToBackend); 17 | $this->auth->addChild($administratorRole, $loginToBackend); 18 | } 19 | 20 | public function down() 21 | { 22 | $this->auth->remove($this->auth->getPermission('loginToBackend')); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /common/migrations/rbac/m151223_074604_edit_own_model.php: -------------------------------------------------------------------------------- 1 | auth->add($rule); 13 | 14 | $role = $this->auth->getRole(User::ROLE_USER); 15 | 16 | $editOwnModelPermission = $this->auth->createPermission('editOwnModel'); 17 | $editOwnModelPermission->ruleName = $rule->name; 18 | 19 | $this->auth->add($editOwnModelPermission); 20 | $this->auth->addChild($role, $editOwnModelPermission); 21 | } 22 | 23 | public function down() 24 | { 25 | $permission = $this->auth->getPermission('editOwnModel'); 26 | $rule = $this->auth->getRule('ownModelRule'); 27 | 28 | $this->auth->remove($permission); 29 | $this->auth->remove($rule); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /common/models/KeyStorageItem.php: -------------------------------------------------------------------------------- 1 | TimestampBehavior::class, 30 | ], 31 | ]; 32 | } 33 | 34 | /** 35 | * @inheritdoc 36 | */ 37 | public function rules() 38 | { 39 | return [ 40 | [['key', 'value'], 'required'], 41 | [['key'], 'string', 'max' => 128], 42 | [['value', 'comment'], 'safe'], 43 | [['key'], 'unique'] 44 | ]; 45 | } 46 | 47 | /** 48 | * @inheritdoc 49 | */ 50 | public function attributeLabels() 51 | { 52 | return [ 53 | 'key' => Yii::t('common', 'Key'), 54 | 'value' => Yii::t('common', 'Value'), 55 | 'comment' => Yii::t('common', 'Comment'), 56 | ]; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /common/models/query/ArticleQuery.php: -------------------------------------------------------------------------------- 1 | andWhere(['{{%article}}.[[status]]' => Article::STATUS_PUBLISHED]); 23 | $this->andWhere(['<', '{{%article}}.[[published_at]]', time()]); 24 | return $this; 25 | } 26 | 27 | public function getFullArchive() 28 | { 29 | $this->innerJoin('{{%article_category}}', '{{%article_category}}.[[id]] = {{%article}}.[[category_id]]'); 30 | $this->select([ 31 | 'YEAR(FROM_UNIXTIME({{%article}}.[[published_at]])) AS [[year]]', 32 | 'MONTH(FROM_UNIXTIME({{%article}}.[[published_at]])) AS [[month]]', 33 | 'COUNT(*) AS [[count]]' 34 | ]); 35 | $this->published(); 36 | $this->andWhere(['{{%article_category}}.[[status]]' => ArticleCategory::STATUS_ACTIVE]); 37 | $this->groupBy('[[year]], [[month]]'); 38 | $this->orderBy('[[year]] DESC, [[month]] DESC'); 39 | return $this; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /common/models/query/PageQuery.php: -------------------------------------------------------------------------------- 1 | andWhere(['status' => Page::STATUS_PUBLISHED]); 17 | return $this; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /common/models/query/TimelineEventQuery.php: -------------------------------------------------------------------------------- 1 | andWhere(['>=', 'created_at', strtotime('today midnight')]); 21 | return $this; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /common/models/query/UserQuery.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class UserQuery extends ActiveQuery 14 | { 15 | /** 16 | * @return $this 17 | */ 18 | public function notDeleted() 19 | { 20 | $this->andWhere(['!=', 'status', User::STATUS_DELETED]); 21 | return $this; 22 | } 23 | 24 | /** 25 | * @return $this 26 | */ 27 | public function active() 28 | { 29 | $this->andWhere(['status' => User::STATUS_ACTIVE]); 30 | return $this; 31 | } 32 | } -------------------------------------------------------------------------------- /common/models/query/UserTokenQuery.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class UserTokenQuery extends ActiveQuery 13 | { 14 | /** 15 | * @return $this 16 | */ 17 | public function notExpired() 18 | { 19 | $this->andWhere(['>', 'expire_at', time()]); 20 | return $this; 21 | } 22 | 23 | /** 24 | * @param $type 25 | * @return $this 26 | */ 27 | public function byType($type) 28 | { 29 | $this->andWhere(['type' => $type]); 30 | return $this; 31 | } 32 | 33 | /** 34 | * @param $token 35 | * @return $this 36 | */ 37 | public function byToken($token) 38 | { 39 | $this->andWhere(['token' => $token]); 40 | return $this; 41 | } 42 | } -------------------------------------------------------------------------------- /common/rbac/rule/OwnModelRule.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | 6 | namespace common\rbac\rule; 7 | 8 | use yii\rbac\Item; 9 | use yii\rbac\Rule; 10 | 11 | class OwnModelRule extends Rule 12 | { 13 | /** @var string */ 14 | public $name = 'ownModelRule'; 15 | 16 | /** 17 | * @param int $user 18 | * @param Item $item 19 | * @param array $params 20 | * - model: model to check owner 21 | * - attribute: attribute that will be compared to user ID 22 | * @return bool 23 | */ 24 | public function execute($user, $item, $params) 25 | { 26 | $attribute = isset($params['attribute']) ? $params['attribute'] : 'created_by'; 27 | return $user && isset($params['model']) && $user === $params['model']->getAttribute($attribute); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /common/rbac/views/migration.php: -------------------------------------------------------------------------------- 1 | 10 | 11 | use yii\db\Schema; 12 | use common\rbac\Migration; 13 | 14 | class extends Migration 15 | { 16 | public function up() 17 | { 18 | 19 | } 20 | 21 | public function down() 22 | { 23 | echo " cannot be reverted.\n"; 24 | 25 | return false; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /common/runtime/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /common/traits/FormAjaxValidationTrait.php: -------------------------------------------------------------------------------- 1 | request->isAjax && !Yii::$app->request->isPjax) { 22 | if ($model->load(Yii::$app->request->post())) { 23 | Yii::$app->response->format = Response::FORMAT_JSON; 24 | Yii::$app->response->data = ActiveForm::validate($model); 25 | Yii::$app->end(); 26 | } 27 | } 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /common/validators/JsonValidator.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class JsonValidator extends Validator 12 | { 13 | /** 14 | * @inheritdoc 15 | */ 16 | public function init() 17 | { 18 | parent::init(); 19 | if ($this->message === null) { 20 | $this->message = Yii::t('common', '"{attribute}" must be a valid JSON'); 21 | } 22 | } 23 | 24 | /** 25 | * @inheritdoc 26 | */ 27 | public function validateValue($value) 28 | { 29 | if (!@json_decode($value)) { 30 | return [$this->message, []]; 31 | } 32 | } 33 | 34 | /** 35 | * @inheritdoc 36 | */ 37 | public function clientValidateAttribute($model, $attribute, $view) 38 | { 39 | $message = Yii::$app->getI18n()->format($this->message, [ 40 | 'attribute' => $model->getAttributeLabel($attribute) 41 | ], Yii::$app->language); 42 | return <<<"JS" 43 | try { 44 | JSON.parse(value); 45 | } catch (e) { 46 | messages.push('{$message}') 47 | } 48 | JS; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /common/widgets/DbMenu.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | 6 | namespace common\widgets; 7 | 8 | use common\models\WidgetMenu; 9 | use Yii; 10 | use yii\base\InvalidConfigException; 11 | use yii\widgets\Menu; 12 | 13 | /** 14 | * Class DbMenu 15 | * Usage: 16 | * echo common\widgets\DbMenu::widget([ 17 | * 'key'=>'stored-menu-key', 18 | * ... other options from \yii\widgets\Menu 19 | * ]) 20 | * @package common\widgets 21 | */ 22 | class DbMenu extends Menu 23 | { 24 | 25 | /** 26 | * @var string Key to find menu model 27 | */ 28 | public $key; 29 | 30 | public function init() 31 | { 32 | $cacheKey = [ 33 | WidgetMenu::class, 34 | $this->key 35 | ]; 36 | $this->items = Yii::$app->cache->get($cacheKey); 37 | if ($this->items === false) { 38 | if (!($model = WidgetMenu::findOne(['key' => $this->key, 'status' => WidgetMenu::STATUS_ACTIVE]))) { 39 | throw new InvalidConfigException; 40 | } 41 | $this->items = json_decode($model->items, true); 42 | Yii::$app->cache->set($cacheKey, $this->items, 60 * 60 * 24); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /common/widgets/DbText.php: -------------------------------------------------------------------------------- 1 | key 29 | ]; 30 | $content = Yii::$app->cache->get($cacheKey); 31 | if (!$content) { 32 | $model = WidgetText::findOne(['key' => $this->key, 'status' => WidgetText::STATUS_ACTIVE]); 33 | if ($model) { 34 | $content = $model->body; 35 | Yii::$app->cache->set($cacheKey, $content, 60 * 60 * 24); 36 | } 37 | } 38 | return $content; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /console/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM yiisoftware/yii2-php:8.0-fpm 2 | 3 | WORKDIR /app -------------------------------------------------------------------------------- /console/config/bootstrap.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | -------------------------------------------------------------------------------- /console/config/console.php: -------------------------------------------------------------------------------- 1 | 'console', 4 | 'basePath' => dirname(__DIR__), 5 | 'controllerNamespace' => 'console\controllers', 6 | 'controllerMap' => [ 7 | 'command-bus' => [ 8 | 'class' => trntv\bus\console\BackgroundBusController::class, 9 | ], 10 | 'message' => [ 11 | 'class' => console\controllers\ExtendedMessageController::class 12 | ], 13 | 'migrate' => [ 14 | 'class' => yii\console\controllers\MigrateController::class, 15 | 'migrationPath' => '@common/migrations/db', 16 | 'migrationTable' => '{{%system_db_migration}}' 17 | ], 18 | 'rbac-migrate' => [ 19 | 'class' => console\controllers\RbacMigrateController::class, 20 | 'migrationPath' => '@common/migrations/rbac/', 21 | 'migrationTable' => '{{%system_rbac_migration}}', 22 | 'templateFile' => '@common/rbac/views/migration.php' 23 | ], 24 | ], 25 | ]; 26 | -------------------------------------------------------------------------------- /console/controllers/RbacMigrateController.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class RbacMigrateController extends MigrateController 11 | { 12 | /** 13 | * Creates a new migration instance. 14 | * @param string $class the migration class name 15 | * @return \common\rbac\Migration the migration instance 16 | */ 17 | protected function createMigration($class) 18 | { 19 | $file = $this->migrationPath . DIRECTORY_SEPARATOR . $class . '.php'; 20 | require_once($file); 21 | 22 | return new $class(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /console/runtime/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /console/yii: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | run(); 27 | exit($exitCode); 28 | -------------------------------------------------------------------------------- /console/yii.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem ------------------------------------------------------------- 4 | rem Yii command line bootstrap script for Windows. 5 | rem 6 | rem @author Qiang Xue 7 | rem @link http://www.yiiframework.com/ 8 | rem @copyright Copyright © 2012 Yii Software LLC 9 | rem @license http://www.yiiframework.com/license/ 10 | rem ------------------------------------------------------------- 11 | 12 | @setlocal 13 | 14 | set YII_PATH=%~dp0 15 | 16 | if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe 17 | 18 | "%PHP_COMMAND%" "%YII_PATH%yii" %* 19 | 20 | @endlocal 21 | -------------------------------------------------------------------------------- /deploy/heroku/.env: -------------------------------------------------------------------------------- 1 | # Framework 2 | # --------- 3 | YII_DEBUG=false 4 | YII_ENV=prod 5 | APP_MAINTENANCE=0 6 | 7 | # Application 8 | # ----------- 9 | LINK_ASSETS=true 10 | 11 | # Urls 12 | # ---- 13 | FRONTEND_HOST_INFO=https://yii2-starter-kit.herokuapp.com 14 | FRONTEND_BASE_URL=/ 15 | BACKEND_HOST_INFO=https://yii2-starter-kit.herokuapp.com 16 | BACKEND_BASE_URL=/backend/web 17 | STORAGE_HOST_INFO=https://yii2-starter-kit.herokuapp.com 18 | STORAGE_BASE_URL=/storage/web 19 | 20 | # Other 21 | # ----- 22 | SMTP_HOST=mailcatcher 23 | SMTP_PORT=1025 24 | 25 | FRONTEND_COOKIE_VALIDATION_KEY= 26 | BACKEND_COOKIE_VALIDATION_KEY= 27 | 28 | ADMIN_EMAIL=admin@yii2-starter-kit.localhost 29 | ROBOT_EMAIL=robot@yii2-starter-kit.localhost 30 | 31 | GITHUB_CLIENT_ID=your-client-id 32 | GITHUB_CLIENT_SECRET=your-client-secret 33 | 34 | GLIDE_SIGN_KEY= 35 | GLIDE_MAX_IMAGE_SIZE=4000000 36 | -------------------------------------------------------------------------------- /deploy/heroku/heroku-nginx.conf: -------------------------------------------------------------------------------- 1 | charset utf-8; 2 | client_max_body_size 32m; 3 | 4 | location /backend { 5 | try_files $uri /backend/web/index.php?$args; 6 | } 7 | 8 | location /storage { 9 | try_files $uri /storage/web/index.php?$args; 10 | } 11 | 12 | location /frontend { 13 | try_files $uri /frontend/web/index.php?$args; 14 | } 15 | 16 | location / { 17 | try_files /frontend/web/$uri /frontend/web/index.php?$args; 18 | } 19 | 20 | location ~ \.php$ { 21 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 22 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 23 | fastcgi_pass heroku-fcgi; 24 | fastcgi_index index.php; 25 | include fastcgi_params; 26 | } 27 | -------------------------------------------------------------------------------- /docker/mysql/config.cnf: -------------------------------------------------------------------------------- 1 | [client] 2 | default-character-set = utf8mb4 3 | 4 | [mysql] 5 | default-character-set = utf8mb4 6 | 7 | [mysqld] 8 | init-connect='SET NAMES utf8mb4' 9 | collation_server=utf8mb4_unicode_ci 10 | character_set_server=utf8mb4 11 | skip-character-set-client-handshake 12 | default_authentication_plugin= mysql_native_password 13 | -------------------------------------------------------------------------------- /docker/php/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM yiisoftware/yii2-php:8.0-fpm 2 | 3 | # Install modules 4 | RUN apt-get update && apt-get install -y \ 5 | libfreetype6-dev \ 6 | libjpeg62-turbo-dev \ 7 | libicu-dev \ 8 | libzip-dev \ 9 | libonig-dev \ 10 | wget \ 11 | git \ 12 | --no-install-recommends 13 | 14 | RUN docker-php-ext-install zip intl mbstring pdo_mysql exif gd 15 | 16 | RUN pecl install -o -f xdebug-2.9.8 \ 17 | && rm -rf /tmp/pear 18 | 19 | COPY ./install-composer.sh / 20 | COPY ./php.ini /usr/local/etc/php/ 21 | COPY ./www.conf /usr/local/etc/php/ 22 | 23 | RUN apt-get purge -y g++ \ 24 | && apt-get autoremove -y \ 25 | && rm -r /var/lib/apt/lists/* \ 26 | && rm -rf /tmp/* \ 27 | && sh /install-composer.sh \ 28 | && rm /install-composer.sh 29 | 30 | RUN usermod -u 1000 www-data 31 | 32 | VOLUME /root/.composer 33 | WORKDIR /app 34 | 35 | EXPOSE 9000 36 | CMD ["php-fpm"] 37 | -------------------------------------------------------------------------------- /docker/php/install-composer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | EXPECTED_SIGNATURE=$(wget -q -O - https://composer.github.io/installer.sig) 4 | php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" 5 | ACTUAL_SIGNATURE=$(php -r "echo hash_file('SHA384', 'composer-setup.php');") 6 | 7 | if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ] 8 | then 9 | >&2 echo 'ERROR: Invalid installer signature' 10 | rm composer-setup.php 11 | exit 1 12 | fi 13 | 14 | php composer-setup.php --quiet --install-dir=/usr/local/bin --filename=composer 15 | RESULT=$? 16 | rm composer-setup.php 17 | exit $RESULT 18 | -------------------------------------------------------------------------------- /docker/php/php.ini: -------------------------------------------------------------------------------- 1 | ; General settings 2 | date.timezone = UTC 3 | memory_limit=-1 4 | max_execution_time=30 5 | sys_temp_dir=/tmp 6 | upload_max_filesize=512M 7 | upload_tmp_dir=/tmp 8 | post_max_size=512M 9 | 10 | ; Security, Debug & Logs 11 | expose_php=off 12 | cgi.fix_pathinfo=0 13 | log_errors=on 14 | error_reporting=E_ALL 15 | html_errors=on 16 | xdebug.default_enable=off 17 | 18 | ; Opcache 19 | opcache.memory_consumption=128 20 | opcache.interned_strings_buffer=8 21 | opcache.max_accelerated_files=4000 22 | ;opcache.validate_timestamps=off 23 | opcache.fast_shutdown=0 24 | opcache.enable_cli=1 25 | 26 | ; PHP language options 27 | short_open_tag=0 28 | 29 | ; xdebug 30 | zend_extension = xdebug.so 31 | xdebug.idekey = PHPSTORM 32 | xdebug.mode = debug 33 | xdebug.discover_client_host = 1 -------------------------------------------------------------------------------- /docker/php/www.conf: -------------------------------------------------------------------------------- 1 | [wwww] 2 | 3 | listen = 0.0.0.0:9000 4 | 5 | listen.owner = www-data 6 | listen.group = www-data 7 | 8 | listen.mode = 0666 9 | 10 | pm = ondemand 11 | pm.max_children = 25 12 | pm.process_idle_timeout = 10s 13 | pm.max_requests = 200 14 | 15 | chdir = / 16 | 17 | user = www-data 18 | group = www-data -------------------------------------------------------------------------------- /frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM yiisoftware/yii2-php:8.0-fpm 2 | 3 | WORKDIR /app -------------------------------------------------------------------------------- /frontend/assets/FrontendAsset.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | 6 | $cache = [ 7 | 'class' => 'yii\caching\FileCache', 8 | 'cachePath' => '@frontend/runtime/cache' 9 | ]; 10 | 11 | if (YII_ENV_DEV) { 12 | $cache = [ 13 | 'class' => 'yii\caching\DummyCache' 14 | ]; 15 | } 16 | 17 | return $cache; 18 | -------------------------------------------------------------------------------- /frontend/config/_urlManager.php: -------------------------------------------------------------------------------- 1 | 'yii\web\UrlManager', 7 | 'enablePrettyUrl' => true, 8 | 'showScriptName' => false, 9 | 'rules' => [ 10 | // Pages 11 | ['pattern' => 'page/', 'route' => 'page/view'], 12 | 13 | // Articles 14 | ['pattern' => 'article/index', 'route' => 'article/index'], 15 | ['pattern' => 'article/attachment-download', 'route' => 'article/attachment-download'], 16 | ['pattern' => 'article/', 'route' => 'article/view'], 17 | 18 | // Sitemap 19 | ['pattern' => 'sitemap.xml', 'route' => 'site/sitemap', 'defaults' => ['format' => Sitemap::FORMAT_XML]], 20 | ['pattern' => 'sitemap.txt', 'route' => 'site/sitemap', 'defaults' => ['format' => Sitemap::FORMAT_TXT]], 21 | ['pattern' => 'sitemap.xml.gz', 'route' => 'site/sitemap', 'defaults' => ['format' => Sitemap::FORMAT_XML, 'gzip' => true]], 22 | ] 23 | ]; 24 | -------------------------------------------------------------------------------- /frontend/config/base.php: -------------------------------------------------------------------------------- 1 | 'frontend', 4 | 'basePath' => dirname(__DIR__), 5 | 'components' => [ 6 | 'urlManager' => require(__DIR__ . '/_urlManager.php'), 7 | 'cache' => require(__DIR__ . '/_cache.php'), 8 | ], 9 | ]; 10 | -------------------------------------------------------------------------------- /frontend/config/bootstrap.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | -------------------------------------------------------------------------------- /frontend/config/console.php: -------------------------------------------------------------------------------- 1 | where(['slug' => $slug, 'status' => Page::STATUS_PUBLISHED])->one(); 21 | if (!$model) { 22 | throw new NotFoundHttpException(Yii::t('frontend', 'Page not found')); 23 | } 24 | 25 | $viewFile = $model->view ?: 'view'; 26 | return $this->render($viewFile, ['model' => $model]); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /frontend/mail/activation.php: -------------------------------------------------------------------------------- 1 | 7 | Yii::$app->formatter->asUrl($url)]) ?> 8 | -------------------------------------------------------------------------------- /frontend/mail/layouts/html.php: -------------------------------------------------------------------------------- 1 | 9 | beginPage() ?> 10 | 11 | 12 | 13 | 14 | <?php echo Html::encode($this->title) ?> 15 | head() ?> 16 | 17 | 18 | beginBody() ?> 19 | 20 | endBody() ?> 21 | 22 | 23 | endPage() ?> 24 | -------------------------------------------------------------------------------- /frontend/mail/layouts/text.php: -------------------------------------------------------------------------------- 1 | : username ?>
2 | : 3 | -------------------------------------------------------------------------------- /frontend/mail/passwordResetToken.php: -------------------------------------------------------------------------------- 1 | urlManager->createAbsoluteUrl(['/user/sign-in/reset-password', 'token' => $token]); 10 | ?> 11 | 12 | Hello username) ?>, 13 | 14 | Follow the link below to reset your password: 15 | 16 | 17 | -------------------------------------------------------------------------------- /frontend/modules/user/Module.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('frontend', 'Request password reset'); 12 | ?> 13 | 14 | 'password-reset']); ?> 15 |
16 |
17 |
18 |
19 |
20 |

title) ?>

21 | field($model, 'email')->input('email') ?> 22 |
23 | 'btn btn-primary btn-lg btn-block', 'name' => 'login-button']) ?> 24 |
25 |
26 |
27 |
28 |
29 |
30 | -------------------------------------------------------------------------------- /frontend/modules/user/views/sign-in/resend-email.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('frontend', 'Resend activation email'); 12 | ?> 13 | 14 | 'resend-email']); ?> 15 |
16 |
17 |
18 |
19 |
20 |

title) ?>

21 | field($model, 'email')->input('email') ?> 22 |
23 | 'btn btn-primary btn-lg btn-block', 'name' => 'login-button']) ?> 24 |
25 |
26 |
27 |
28 |
29 |
30 | -------------------------------------------------------------------------------- /frontend/modules/user/views/sign-in/resetPassword.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('frontend', 'Reset password'); 12 | ?> 13 | 14 | 'password-reset']); ?> 15 |
16 |
17 |
18 |
19 |
20 |

title) ?>

21 | field($model, 'password')->passwordInput() ?> 22 |
23 | 'btn btn-primary btn-lg btn-block', 'name' => 'login-button']) ?> 24 |
25 |
26 |
27 |
28 |
29 |
30 | 31 | -------------------------------------------------------------------------------- /frontend/runtime/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /frontend/views/article/_categories.php: -------------------------------------------------------------------------------- 1 | 9 | 10 |

11 |
    12 | 'list-group-item d-flex flex-column justify-content-between lh-condensed'] 16 | ); 17 | $blockEnd = Html::endTag('li'); 18 | echo $blockBegin; 19 | if (count($categories)) { 20 | foreach ($categories as $category) { 21 | $label = $category['title']; 22 | $slug = $category['slug']; 23 | $count = $category['articlesCount']; 24 | 25 | echo Html::beginTag('div', ['class' => 'd-flex justify-content-between align-items-center']); 26 | echo Html::a( 27 | Html::encode($label), 28 | ['article/index', 'ArticleSearch[category_id]' => $category['id']], 29 | ['class' => 'text-muted overflow-hidden'] 30 | ), ' ', Html::tag('span', $count, ['class' => 'badge badge-secondary badge-pill']); 31 | echo Html::endTag('div'); 32 | } 33 | } else { 34 | echo Yii::t('frontend', 'Categories not found'); 35 | } 36 | echo $blockEnd; 37 | ?> 38 |
-------------------------------------------------------------------------------- /frontend/views/article/index.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('frontend', 'Articles') 12 | ?> 13 | 14 |

15 | 16 |

17 | 18 |
19 |
20 | $dataProvider, 22 | 'pager' => [ 23 | 'hideOnSinglePage' => true, 24 | ], 25 | 'itemView' => '_item', 26 | 'summaryOptions' => ['class' => ['text-muted mb-3']], 27 | ])?> 28 |
29 | 30 |
31 | render('_categories', ['categories' => $categories]) ?> 32 | render('_archive', ['archive' => $archive]) ?> 33 |
34 |
35 | -------------------------------------------------------------------------------- /frontend/views/layouts/_clear.php: -------------------------------------------------------------------------------- 1 | 11 | beginPage() ?> 12 | 13 | 14 | 15 | 16 | 17 | <?php echo Html::encode($this->title) ?> 18 | head() ?> 19 | 20 | 21 | 22 | beginBody() ?> 23 | 24 | endBody() ?> 25 | 26 | 27 | endPage() ?> 28 | -------------------------------------------------------------------------------- /frontend/views/layouts/full-width.php: -------------------------------------------------------------------------------- 1 | beginContent('@frontend/views/layouts/base.php') 11 | ?> 12 | 13 |
14 | isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [], 16 | ]) ?> 17 | 18 | session->hasFlash('alert')):?> 19 | ArrayHelper::getValue(Yii::$app->session->getFlash('alert'), 'body'), 21 | 'options'=>ArrayHelper::getValue(Yii::$app->session->getFlash('alert'), 'options'), 22 | ])?> 23 | 24 | 25 | 26 | 'ads-example' 28 | ]) ?> 29 |
30 | 31 | 32 | endContent() ?> -------------------------------------------------------------------------------- /frontend/views/layouts/main.php: -------------------------------------------------------------------------------- 1 | beginContent('@frontend/views/layouts/base.php') 11 | ?> 12 |
13 | 14 | isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [], 16 | ]) ?> 17 | 18 | session->hasFlash('alert')):?> 19 | ArrayHelper::getValue(Yii::$app->session->getFlash('alert'), 'body'), 21 | 'options'=>ArrayHelper::getValue(Yii::$app->session->getFlash('alert'), 'options'), 22 | ])?> 23 | 24 | 25 | 26 | 'ads-example' 28 | ]) ?> 29 | 30 | 31 |
32 | endContent() ?> -------------------------------------------------------------------------------- /frontend/views/page/view.php: -------------------------------------------------------------------------------- 1 | title = $model->title; 11 | ?> 12 | 13 |

title) ?>

14 | body) ?> -------------------------------------------------------------------------------- /frontend/views/site/contact.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('frontend', 'Contact us'); 13 | ?> 14 |
15 |
16 |
17 |

title) ?>

18 | 'contact-form']); ?> 19 | field($model, 'name') ?> 20 | field($model, 'email')->input('email') ?> 21 | field($model, 'subject') ?> 22 | field($model, 'body')->textArea(['rows' => 6]) ?> 23 | field($model, 'verifyCode')->widget(Captcha::class, [ 24 | 'template' => '
{image}
{input}
', 25 | ]) ?> 26 |
27 | 'btn btn-primary', 'name' => 'contact-button']) ?> 28 |
29 | 30 |
31 |
32 | 33 |
34 | -------------------------------------------------------------------------------- /frontend/views/site/error.php: -------------------------------------------------------------------------------- 1 | title = $name; 13 | ?> 14 |
15 | 16 |

17 |

title) ?>

18 | 19 |
20 | 21 |
22 | 23 |
    24 |
  • 25 | '.Yii::t('frontend', 'Go to Home'), ['/'], ['class' => ['btn', 'btn-primary', 'btn-lg']]) ?> 26 |
  • 27 |
  • 28 | '.Yii::t('frontend', 'Contact Support'), 30 | ['site/contact'], 31 | ['class' => ['btn', 'btn-outline-secondary', 'btn-lg']] 32 | ) ?> 33 |
  • 34 |
35 | 36 |
37 | -------------------------------------------------------------------------------- /frontend/web/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | RewriteCond %{REQUEST_FILENAME} !-f 3 | RewriteCond %{REQUEST_FILENAME} !-d 4 | RewriteRule . index.php -------------------------------------------------------------------------------- /frontend/web/assets/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /frontend/web/bundle/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /frontend/web/css/_article.less: -------------------------------------------------------------------------------- 1 | #article-index { 2 | h1 { 3 | display: inline-block; 4 | } 5 | .search-button { 6 | cursor: pointer; 7 | } 8 | } 9 | 10 | .article-item { 11 | margin-bottom: 15px; 12 | .article-title, 13 | .article-title a 14 | { 15 | color: inherit; 16 | margin: 0; 17 | } 18 | .article-meta, 19 | .article-meta a 20 | { 21 | color: #999; 22 | font-size: .85em; 23 | } 24 | .article-meta a{ 25 | text-decoration: underline; 26 | } 27 | .article-thumb { 28 | margin-right: 10px; 29 | margin-bottom: 10px; 30 | } 31 | .article-text { 32 | margin-top: 7px; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /frontend/web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yii-starter-kit/yii2-starter-kit/4f019ad2bba87b6abebcb340ece6fa1475fb2f71/frontend/web/favicon.ico -------------------------------------------------------------------------------- /frontend/web/img/anonymous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yii-starter-kit/yii2-starter-kit/4f019ad2bba87b6abebcb340ece6fa1475fb2f71/frontend/web/img/anonymous.png -------------------------------------------------------------------------------- /frontend/web/img/yii2-starter-kit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yii-starter-kit/yii2-starter-kit/4f019ad2bba87b6abebcb340ece6fa1475fb2f71/frontend/web/img/yii2-starter-kit.gif -------------------------------------------------------------------------------- /frontend/web/index-test.php: -------------------------------------------------------------------------------- 1 | run(); 35 | -------------------------------------------------------------------------------- /frontend/web/index.php: -------------------------------------------------------------------------------- 1 | run(); 23 | -------------------------------------------------------------------------------- /frontend/web/js/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Eugene Terentev 3 | */ 4 | -------------------------------------------------------------------------------- /frontend/web/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: -------------------------------------------------------------------------------- /frontend/yii: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | run(); 28 | exit($exitCode); 29 | -------------------------------------------------------------------------------- /frontend/yii.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem ------------------------------------------------------------- 4 | rem Yii command line bootstrap script for Windows. 5 | rem 6 | rem @author Qiang Xue 7 | rem @link http://www.yiiframework.com/ 8 | rem @copyright Copyright © 2012 Yii Software LLC 9 | rem @license http://www.yiiframework.com/license/ 10 | rem ------------------------------------------------------------- 11 | 12 | @setlocal 13 | 14 | set YII_PATH=%~dp0 15 | 16 | if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe 17 | 18 | "%PHP_COMMAND%" "%YII_PATH%yii" %* 19 | 20 | @endlocal 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "webpack --progress", 5 | "watch": "webpack --progress --watch" 6 | }, 7 | "devDependencies": { 8 | "babel-core": "^6.26.3", 9 | "babel-loader": "^7.1.5", 10 | "babel-preset-latest": "^6.24.0", 11 | "css-loader": "^3.6.0", 12 | "file-loader": "^6.2.0", 13 | "less-loader": "^3.0.0", 14 | "mini-css-extract-plugin": "^0.4.5", 15 | "optimize-css-assets-webpack-plugin": "^5.0.3", 16 | "serialize-javascript": "^5.0.1", 17 | "uglifyjs-webpack-plugin": "^1.2.7", 18 | "url-loader": "^4.1.0", 19 | "webpack": "^4.41.0", 20 | "webpack-cli": "^3.1.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /storage/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM yiisoftware/yii2-php:8.0-fpm 2 | 3 | WORKDIR /app -------------------------------------------------------------------------------- /storage/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /storage/config/_urlManager.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | return [ 6 | 'class'=>'yii\web\UrlManager', 7 | 'enablePrettyUrl'=>true, 8 | 'showScriptName'=>false, 9 | 'rules'=> [ 10 | ['pattern'=>'cache/', 'route'=>'glide/index', 'encodeParams' => false] 11 | ] 12 | ]; 13 | -------------------------------------------------------------------------------- /storage/config/base.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | return [ 6 | 'id' => 'storage', 7 | 'basePath' => dirname(__DIR__), 8 | 'defaultRoute' => 'glide/index', 9 | 'controllerMap' => [ 10 | 'glide' => '\trntv\glide\controllers\GlideController' 11 | ], 12 | 'components' => [ 13 | 'urlManager'=>require(__DIR__.'/_urlManager.php'), 14 | 'glide' => [ 15 | 'class' => 'trntv\glide\components\Glide', 16 | 'sourcePath' => '@storage/web/source', 17 | 'cachePath' => '@storage/cache', 18 | 'maxImageSize' => env('GLIDE_MAX_IMAGE_SIZE'), 19 | 'signKey' => env('GLIDE_SIGN_KEY') 20 | ] 21 | ] 22 | ]; 23 | -------------------------------------------------------------------------------- /storage/web/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine on 2 | 3 | RedirectMatch 403 /\..*$ 4 | RewriteCond %{REQUEST_FILENAME} !-f 5 | RewriteCond %{REQUEST_FILENAME} !-d 6 | RewriteRule . index.php -------------------------------------------------------------------------------- /storage/web/index.php: -------------------------------------------------------------------------------- 1 | run(); 18 | -------------------------------------------------------------------------------- /storage/web/source/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /tests/_output/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tests/api/_bootstrap.php: -------------------------------------------------------------------------------- 1 | amOnPage('/v1/articles'); 14 | $I->see('Lorem ipsum'); 15 | } 16 | 17 | public function testArticleView(FunctionalTester $I) 18 | { 19 | $I->amOnPage(['/v1/articles', 'slug' => 'test-article-1']); 20 | $I->see('Lorem ipsum'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/api/functional/UserCest.php: -------------------------------------------------------------------------------- 1 | amOnPage('/v1/user'); 14 | $I->see('user'); 15 | } 16 | 17 | public function testUserAccess(FunctionalTester $I) 18 | { 19 | $I->deleteHeader('X-Api-Key'); 20 | $I->amOnPage('/v1/user'); 21 | $I->seeResponseCodeIs(401); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/api/functional/_bootstrap.php: -------------------------------------------------------------------------------- 1 | haveHttpHeader('X-Api-Key', 'Q1M6dPrGpzBWOnGf2NbkEMLntSCDhchuVKDGOUWC'); 14 | } 15 | } -------------------------------------------------------------------------------- /tests/api/unit/_bootstrap.php: -------------------------------------------------------------------------------- 1 | actor = $actor; 25 | $this->actor->amOnPage(Url::to($this->route)); 26 | } 27 | 28 | /** 29 | * @param $actor 30 | * @return LoginPage 31 | */ 32 | public static function openBy($actor) 33 | { 34 | return new self($actor); 35 | } 36 | 37 | 38 | /** 39 | * @param string $username 40 | * @param string $password 41 | */ 42 | public function login($username, $password) 43 | { 44 | $this->actor->fillField('input[name="LoginForm[username]"]', $username); 45 | $this->actor->fillField('input[name="LoginForm[password]"]', $password); 46 | $this->actor->click('login-button'); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/backend/_support/AcceptanceTester.php: -------------------------------------------------------------------------------- 1 | wantTo('ensure login page works'); 10 | 11 | $loginPage = LoginPage::openBy($I); 12 | 13 | $I->amGoingTo('submit login form with no data'); 14 | $loginPage->login('', ''); 15 | $I->expectTo('see validations errors'); 16 | $I->see('Username cannot be blank.', '.alert.alert-danger'); 17 | $I->see('Password cannot be blank.', '.alert.alert-danger'); 18 | 19 | $I->amGoingTo('try to login with wrong credentials'); 20 | $I->expectTo('see validations errors'); 21 | $loginPage->login('admin', 'wrong'); 22 | $I->expectTo('see validations errors'); 23 | $I->see('Incorrect username or password.', '.alert.alert-danger'); 24 | 25 | $I->amGoingTo('try to login with "user" account'); 26 | $loginPage->login('user', 'user'); 27 | $I->expectTo('see that user is logged, and gets an unauthorized error'); 28 | $I->canSeeResponseCodeIs(403); 29 | 30 | $loginPage = LoginPage::openBy($I); 31 | 32 | $I->amGoingTo('try to login with correct credentials'); 33 | $loginPage->login('webmaster', 'webmaster'); 34 | $I->expectTo('see that user is logged'); 35 | $I->seeLink('Logout'); 36 | -------------------------------------------------------------------------------- /tests/backend/functional/_bootstrap.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | 6 | require __DIR__ . '/../vendor/autoload.php'; 7 | 8 | // Environment 9 | $dotenv = \Dotenv\Dotenv::createImmutable(dirname(__DIR__)); 10 | $dotenv->load(); 11 | $dotenv->required('TEST_DB_DSN'); 12 | $dotenv->required('TEST_DB_USERNAME'); 13 | $dotenv->required('TEST_DB_PASSWORD'); 14 | 15 | // Set environment 16 | defined('YII_DEBUG') or define('YII_DEBUG', true); 17 | defined('YII_ENV') or define('YII_ENV', 'test'); 18 | defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', dirname(__DIR__)); -------------------------------------------------------------------------------- /tests/common/_bootstrap.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class ArticleAttachmentFixture extends ActiveFixture 11 | { 12 | public $modelClass = 'common\models\ArticleAttachment'; 13 | public $depends = [ 14 | ArticleFixture::class 15 | ]; 16 | } 17 | -------------------------------------------------------------------------------- /tests/common/fixtures/ArticleCategoryFixture.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class ArticleCategoryFixture extends ActiveFixture 12 | { 13 | public $modelClass = ArticleCategory::class; 14 | } 15 | -------------------------------------------------------------------------------- /tests/common/fixtures/ArticleFixture.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class ArticleFixture extends ActiveFixture 11 | { 12 | public $modelClass = 'common\models\Article'; 13 | public $depends = [ 14 | ArticleCategoryFixture::class, 15 | UserFixture::class, 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /tests/common/fixtures/KeyStorageItemFixture.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | return [ 6 | [ 7 | 'id' => 1, 8 | 'slug' => 'test-article-1', 9 | 'title' => 'Test Article 1', 10 | 'body' => 'Lorem ipsum', 11 | 'category_id' => 1, 12 | 'status' => 1, 13 | 'created_by' => 1, 14 | 'updated_by' => 1, 15 | 'published_at' => time() - 10, 16 | 'created_at' => time() - 10, 17 | 'updated_at' => time() - 10 18 | ], 19 | [ 20 | 'id' => 2, 21 | 'slug' => 'test-article-2', 22 | 'title' => 'Test Article 2', 23 | 'body' => 'Lorem ipsum', 24 | 'category_id' => 1, 25 | 'created_by' => 1, 26 | 'updated_by' => 1, 27 | 'status' => 1, 28 | 'published_at' => time() + \cheatsheet\Time::SECONDS_IN_A_YEAR, 29 | 'created_at' => time() + \cheatsheet\Time::SECONDS_IN_A_YEAR, 30 | 'updated_at' => time() + \cheatsheet\Time::SECONDS_IN_A_YEAR 31 | ] 32 | ]; 33 | -------------------------------------------------------------------------------- /tests/common/fixtures/data/article_attachment.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | return [ 6 | [ 7 | 'id' => 1, 8 | 'article_id' => 1, 9 | 'path' => 'test-file.png', 10 | 'name' => 'Test File', 11 | 'base_url' => 'http://example.org', 12 | 'size' => 1024 13 | ] 14 | ]; -------------------------------------------------------------------------------- /tests/common/fixtures/data/article_category.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | return [ 6 | [ 7 | 'id' => 1, 8 | 'title' => 'Test Category', 9 | 'slug' => 'test-category', 10 | 'status' => 1 11 | ] 12 | ]; -------------------------------------------------------------------------------- /tests/common/fixtures/data/key_storage_item.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | return [ 6 | [ 7 | 'key' => 'frontend.maintenance', 8 | 'value' => 'disabled' 9 | ] 10 | ]; -------------------------------------------------------------------------------- /tests/common/fixtures/data/page.php: -------------------------------------------------------------------------------- 1 | "1", 13 | "slug" => "about", 14 | "title" => "About", 15 | "body" => "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", 16 | "view" => "", 17 | "status" => "1", 18 | "created_at" => "1508525930", 19 | "updated_at" => "1508525930" 20 | ] 21 | ]; -------------------------------------------------------------------------------- /tests/common/fixtures/data/rbac_auth_assignment.php: -------------------------------------------------------------------------------- 1 | 'administrator', 6 | 'user_id' => '1', 7 | 'created_at' => '1440552894', 8 | ], 9 | [ 10 | 'item_name' => 'manager', 11 | 'user_id' => '2', 12 | 'created_at' => '1440552894', 13 | ], 14 | [ 15 | 'item_name' => 'user', 16 | 'user_id' => '3', 17 | 'created_at' => '1440552894', 18 | ], 19 | ]; 20 | -------------------------------------------------------------------------------- /tests/common/fixtures/data/rbac_auth_item.php: -------------------------------------------------------------------------------- 1 | 'administrator', 6 | 'type' => '1', 7 | 'description' => '', 8 | 'rule_name' => null, 9 | 'data' => '', 10 | 'created_at' => '1508507788', 11 | 'updated_at' => '1508507788', 12 | ], 13 | [ 14 | 'name' => 'editOwnModel', 15 | 'type' => '2', 16 | 'description' => '', 17 | 'rule_name' => 'ownModelRule', 18 | 'data' => '', 19 | 'created_at' => '1508507788', 20 | 'updated_at' => '1508507788', 21 | ], 22 | [ 23 | 'name' => 'loginToBackend', 24 | 'type' => '2', 25 | 'description' => '', 26 | 'rule_name' => null, 27 | 'data' => '', 28 | 'created_at' => '1508507788', 29 | 'updated_at' => '1508507788', 30 | ], 31 | [ 32 | 'name' => 'manager', 33 | 'type' => '1', 34 | 'description' => '', 35 | 'rule_name' => null, 36 | 'data' => '', 37 | 'created_at' => '1508507787', 38 | 'updated_at' => '1508507787', 39 | ], 40 | [ 41 | 'name' => 'user', 42 | 'type' => '1', 43 | 'description' => '', 44 | 'rule_name' => null, 45 | 'data' => '', 46 | 'created_at' => '1508507787', 47 | 'updated_at' => '1508507787', 48 | ], 49 | ]; 50 | -------------------------------------------------------------------------------- /tests/common/fixtures/data/rbac_auth_item_child.php: -------------------------------------------------------------------------------- 1 | 'user', 6 | 'child' => 'editOwnModel', 7 | ], 8 | [ 9 | 'parent' => 'manager', 10 | 'child' => 'loginToBackend', 11 | ], 12 | [ 13 | 'parent' => 'administrator', 14 | 'child' => 'manager', 15 | ], 16 | [ 17 | 'parent' => 'manager', 18 | 'child' => 'user', 19 | ], 20 | ]; 21 | -------------------------------------------------------------------------------- /tests/common/fixtures/data/rbac_auth_rule.php: -------------------------------------------------------------------------------- 1 | 'ownModelRule', 6 | 'data' => 'O:29:"common\rbac\rule\OwnModelRule":3:{s:4:"name";s:12:"ownModelRule";s:9:"createdAt";i:1508507788;s:9:"updatedAt";i:1508507788;}', 7 | 'created_at' => '1508507788', 8 | 'updated_at' => '1508507788' 9 | ] 10 | ]; 11 | -------------------------------------------------------------------------------- /tests/common/fixtures/data/user.php: -------------------------------------------------------------------------------- 1 | 1, 6 | 'username' => 'webmaster', 7 | 'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI', 8 | 'password_hash' => '$2y$13$VnLT62YdhKy.RHHDLN0MEezggGKZZKQFmPVu5d.5ODTwBGSx7WcW6', 9 | 'access_token' => 'yNxS5kDGC8GAXXbkewJ8Rf2qY5rEdy01Odtgt8vO', 10 | 'created_at' => '1392559490', 11 | 'updated_at' => '1392559490', 12 | 'email' => 'webmaster@example.org', 13 | ], 14 | [ 15 | 'id' => 2, 16 | 'username' => 'manager', 17 | 'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI', 18 | 'password_hash' => '$2y$13$N785qekuqJzo2CsP7K0g/.KtWZ8SwZtqITdTPrHBFITYjX9WYnl5i', 19 | 'access_token' => 'JJcEWMSq4IFxhEMUpYoJXx5ZNDW33t4OFS5tXSlP', 20 | 'created_at' => '1392559490', 21 | 'updated_at' => '1392559490', 22 | 'email' => 'user@example.org' 23 | ], 24 | [ 25 | 'id' => 3, 26 | 'username' => 'user', 27 | 'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI', 28 | 'password_hash' => '$2y$13$tJKZTKUQ5DBFWNkkjd0goup.p8Tx5d9Mj/wWL6Vv8/Q038zk7g5.6', 29 | 'access_token' => 'Q1M6dPrGpzBWOnGf2NbkEMLntSCDhchuVKDGOUWC', 30 | 'created_at' => '1392559490', 31 | 'updated_at' => '1392559490', 32 | 'email' => 'user@example.org' 33 | ], 34 | ]; 35 | -------------------------------------------------------------------------------- /tests/common/fixtures/data/user_profile.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | return [ 6 | [ 7 | 'user_id' => 1, 8 | 'locale' => 'en_US' 9 | ], 10 | [ 11 | 'user_id' => 2, 12 | 'locale' => 'en_US' 13 | ], 14 | [ 15 | 'user_id' => 3, 16 | 'locale' => 'en_US' 17 | ], 18 | ]; -------------------------------------------------------------------------------- /tests/common/fixtures/data/widget_carousel.php: -------------------------------------------------------------------------------- 1 | "1", 6 | "key" => "index", 7 | "status" => "1" 8 | ] 9 | ]; -------------------------------------------------------------------------------- /tests/common/fixtures/data/widget_carousel_item.php: -------------------------------------------------------------------------------- 1 | "1", 6 | "carousel_id" => "1", 7 | "base_url" => "./", 8 | "path" => "img/yii2-starter-kit.gif", 9 | "type" => "image/gif", 10 | "url" => "/", 11 | "caption" => "", 12 | "status" => "1", 13 | "order" => "0", 14 | "created_at" => "", 15 | "updated_at" => "" 16 | ] 17 | ]; 18 | -------------------------------------------------------------------------------- /tests/common/fixtures/data/widget_menu.php: -------------------------------------------------------------------------------- 1 | "1", 6 | "key" => "frontend-index", 7 | "title" => "Frontend index menu", 8 | "items" => "[\n {\n \"label\": \"Get started with Yii2\",\n \"url\": \"http://www.yiiframework.com\",\n \"options\": {\n \"tag\": \"span\"\n },\n \"template\": \"{label}\"\n },\n {\n \"label\": \"Yii2 Starter Kit on GitHub\",\n \"url\": \"https://github.com/yii2-starter-kit/yii2-starter-kit\",\n \"options\": {\n \"tag\": \"span\"\n },\n \"template\": \"{label}\"\n },\n {\n \"label\": \"Find a bug?\",\n \"url\": \"https://github.com/yii2-starter-kit/yii2-starter-kit/issues\",\n \"options\": {\n \"tag\": \"span\"\n },\n \"template\": \"{label}\"\n }\n]", 9 | "status" => "1" 10 | ] 11 | ]; -------------------------------------------------------------------------------- /tests/common/fixtures/data/widget_text.php: -------------------------------------------------------------------------------- 1 | "1", 12 | "key" => "backend_welcome", 13 | "title" => "Welcome to backend", 14 | "body" => "

Welcome to Yii2 Starter Kit Dashboard

", 15 | "status" => "1", 16 | "created_at" => "1508593313", 17 | "updated_at" => "1508593313" 18 | ], 19 | [ 20 | "id" => "2", 21 | "key" => "ads-example", 22 | "title" => "Google Ads Example Block", 23 | "body" => "
\r\n \r\n \r\n \r\n
", 24 | "status" => "0", 25 | "created_at" => "1508593313", 26 | "updated_at" => "1508593313" 27 | ] 28 | ]; -------------------------------------------------------------------------------- /tests/common/templates/fixtures/user.php: -------------------------------------------------------------------------------- 1 | getSecurity(); 8 | 9 | return [ 10 | 'username' => $faker->userName, 11 | 'email' => $faker->email, 12 | 'auth_key' => $security->generateRandomString(), 13 | 'password_hash' => $security->generatePasswordHash('password_' . $index), 14 | 'created_at' => time(), 15 | 'updated_at' => time(), 16 | ]; 17 | -------------------------------------------------------------------------------- /tests/common/unit.suite.yml: -------------------------------------------------------------------------------- 1 | class_name: UnitTester 2 | bootstrap: false 3 | modules: 4 | enabled: 5 | - Asserts 6 | - Yii2: 7 | part: [fixtures] 8 | -------------------------------------------------------------------------------- /tests/common/unit/KeyStorageTest.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class KeyStorageTest extends Unit 12 | { 13 | 14 | public function testKeyStorageSet() 15 | { 16 | Yii::$app->keyStorage->set('test.key', 'testValue'); 17 | $this->assertEquals('testValue', Yii::$app->keyStorage->get('test.key', null, false)); 18 | Yii::$app->keyStorage->set('test.key', 'anotherTestValue'); 19 | $this->assertEquals('anotherTestValue', Yii::$app->keyStorage->get('test.key', null, false)); 20 | } 21 | 22 | /** 23 | * @depends testKeyStorageSet 24 | */ 25 | public function testKeyStorageHas() 26 | { 27 | $this->assertTrue(Yii::$app->keyStorage->has('test.key')); 28 | $this->assertFalse(Yii::$app->keyStorage->has('falseKey')); 29 | } 30 | 31 | /** 32 | * @depends testKeyStorageHas 33 | */ 34 | public function testKeyStorageRemove() 35 | { 36 | Yii::$app->keyStorage->remove('test.key'); 37 | $this->assertNull(Yii::$app->keyStorage->get('test.key', null, false)); 38 | $this->assertFalse(Yii::$app->keyStorage->has('test.key', false)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/common/unit/UserTest.php: -------------------------------------------------------------------------------- 1 | email = "12345677713@test.com"; 24 | $user->password_hash = "1234"; 25 | $user->username = "

xss;

"; 26 | $this->assertTrue($user->save()); 27 | $this->assertTrue($user->username === '<p>xss;</p>'); 28 | $this->assertTrue((boolean)$user->delete()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/common/unit/_bootstrap.php: -------------------------------------------------------------------------------- 1 | [ 14 | 'assetManager' => [ 15 | 'basePath' => YII_APP_BASE_PATH . '/frontend/web/assets' 16 | ], 17 | ] 18 | ] 19 | ); 20 | -------------------------------------------------------------------------------- /tests/config/backend/unit.php: -------------------------------------------------------------------------------- 1 | 'app-common', 11 | 'basePath' => dirname(__DIR__), 12 | ] 13 | ); 14 | -------------------------------------------------------------------------------- /tests/config/base.php: -------------------------------------------------------------------------------- 1 | [ 7 | 'db' => [ 8 | 'dsn' => env('TEST_DB_DSN'), 9 | 'username' => env('TEST_DB_USERNAME'), 10 | 'password' => env('TEST_DB_PASSWORD') 11 | ], 12 | 'mailer' => [ 13 | 'useFileTransport' => true, 14 | ], 15 | 'urlManager' => [ 16 | 'showScriptName' => true, 17 | ], 18 | ], 19 | ]; 20 | -------------------------------------------------------------------------------- /tests/config/common/acceptance.php: -------------------------------------------------------------------------------- 1 | null, 7 | ]; 8 | -------------------------------------------------------------------------------- /tests/config/common/functional.php: -------------------------------------------------------------------------------- 1 | '/', 4 | 'components' => [ 5 | 'request' => [ 6 | 'enableCsrfValidation' => false, 7 | ], 8 | ], 9 | ]; 10 | -------------------------------------------------------------------------------- /tests/config/common/unit.php: -------------------------------------------------------------------------------- 1 | 'app-common', 10 | 'basePath' => YII_APP_BASE_PATH 11 | ] 12 | ); 13 | -------------------------------------------------------------------------------- /tests/config/console.php: -------------------------------------------------------------------------------- 1 | [ 4 | 'fixture' => [ 5 | 'class' => yii\faker\FixtureController::class, 6 | 'fixtureDataPath' => '@tests/common/fixtures/data', 7 | 'templatePath' => '@tests/common/templates/fixtures', 8 | 'namespace' => 'tests\common\fixtures', 9 | ], 10 | ], 11 | ]; 12 | -------------------------------------------------------------------------------- /tests/config/console/unit.php: -------------------------------------------------------------------------------- 1 | [ 14 | 'assetManager' => [ 15 | 'basePath' => YII_APP_BASE_PATH . '/frontend/web/assets' 16 | ], 17 | ] 18 | ] 19 | ); 20 | -------------------------------------------------------------------------------- /tests/config/frontend/unit.php: -------------------------------------------------------------------------------- 1 | actor = $actor; 25 | $this->actor->amOnPage(Url::toRoute($this->route)); 26 | } 27 | 28 | /** 29 | * @param $actor 30 | * @return LoginPage 31 | */ 32 | public static function openBy($actor) 33 | { 34 | return new self($actor); 35 | } 36 | 37 | 38 | /** 39 | * @param string $username 40 | * @param string $password 41 | */ 42 | public function login($username, $password) 43 | { 44 | $this->actor->fillField('input[name="LoginForm[identity]"]', $username); 45 | $this->actor->fillField('input[name="LoginForm[password]"]', $password); 46 | $this->actor->click('login-button'); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/frontend/_pages/SignupPage.php: -------------------------------------------------------------------------------- 1 | actor = $actor; 25 | $this->actor->amOnPage(Url::to($this->route)); 26 | } 27 | 28 | /** 29 | * @param $actor 30 | * @return SignupPage 31 | */ 32 | public static function openBy($actor) 33 | { 34 | return new self($actor); 35 | } 36 | 37 | /** 38 | * @param array $signupData 39 | */ 40 | public function submit(array $signupData) 41 | { 42 | foreach ($signupData as $field => $value) { 43 | $inputType = $field === 'body' ? 'textarea' : 'input'; 44 | $this->actor->fillField($inputType . '[name="SignupForm[' . $field . ']"]', $value); 45 | } 46 | $this->actor->click('signup-button'); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/frontend/_support/AcceptanceHelper.php: -------------------------------------------------------------------------------- 1 | wantTo('ensure that home page works'); 9 | $I->amOnPage(Yii::$app->homeUrl); 10 | $I->see('Yii2 Starter Kit'); 11 | $I->seeLink('About'); 12 | $I->click('About'); 13 | $I->seeInCurrentUrl('/page/about'); 14 | -------------------------------------------------------------------------------- /tests/frontend/acceptance/LoginCept.php: -------------------------------------------------------------------------------- 1 | wantTo('ensure login page works'); 10 | 11 | $loginPage = LoginPage::openBy($I); 12 | 13 | $I->amGoingTo('submit login form with no data'); 14 | $loginPage->login('', ''); 15 | $I->expectTo('see validations errors'); 16 | $I->see('Username or email cannot be blank.', '.alert.alert-danger'); 17 | $I->see('Password cannot be blank.', '.alert.alert-danger'); 18 | 19 | $I->amGoingTo('try to login with wrong credentials'); 20 | $I->expectTo('see validations errors'); 21 | $loginPage->login('admin', 'wrong'); 22 | $I->expectTo('see validations errors'); 23 | $I->see('Incorrect username or password.', '.alert.alert-danger'); 24 | 25 | $I->amGoingTo('try to login with correct credentials'); 26 | $loginPage->login('webmaster', 'webmaster'); 27 | $I->expectTo('see that user is logged'); 28 | $I->seeLink('Logout'); 29 | $I->dontSeeLink('Login'); 30 | $I->dontSeeLink('Signup'); 31 | /** Uncomment if using WebDriver 32 | * $I->click('Logout (erau)'); 33 | * $I->dontSeeLink('Logout (erau)'); 34 | * $I->seeLink('Login'); 35 | */ 36 | -------------------------------------------------------------------------------- /tests/frontend/acceptance/_bootstrap.php: -------------------------------------------------------------------------------- 1 | amOnPage(['article/index']); 11 | $I->canSee('Articles', 'h1'); 12 | $I->canSee('Test Article 1', '.h3.card-title'); 13 | $I->dontSee('Test Article 2', '.h3.card-title'); 14 | } 15 | 16 | public function testArticleView(FunctionalTester $I) 17 | { 18 | $I->amOnPage(['article/view', 'slug' => 'test-article-1']); 19 | $I->canSee('Test Article 1', 'h1'); 20 | $I->canSee('Lorem ipsum'); 21 | $I->canSeeElement("//a[contains(@href,'attachment-download')]"); 22 | $I->amOnPage(['article/view', 'slug' => 'unknown-article']); 23 | $I->canSee('404'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/frontend/functional/HomeCept.php: -------------------------------------------------------------------------------- 1 | wantTo('ensure that home page works'); 9 | $I->amOnPage(Yii::$app->homeUrl); 10 | $I->see('Yii2 Starter Kit'); 11 | $I->seeLink('About'); 12 | $I->click('About'); 13 | $I->see('Lorem ipsum'); 14 | -------------------------------------------------------------------------------- /tests/frontend/functional/LoginCept.php: -------------------------------------------------------------------------------- 1 | wantTo('ensure login page works'); 10 | 11 | $loginPage = LoginPage::openBy($I); 12 | 13 | $I->amGoingTo('submit login form with no data'); 14 | $loginPage->login('', ''); 15 | $I->expectTo('see validations errors'); 16 | $I->see('Username or email cannot be blank.', '.alert.alert-danger'); 17 | $I->see('Password cannot be blank.', '.alert.alert-danger'); 18 | 19 | $I->amGoingTo('try to login with wrong credentials'); 20 | $I->expectTo('see validations errors'); 21 | $loginPage->login('admin', 'wrong'); 22 | $I->expectTo('see validations errors'); 23 | $I->see('Incorrect username or password.', '.alert.alert-danger'); 24 | 25 | $I->amGoingTo('try to login with correct credentials'); 26 | $loginPage->login('webmaster', 'webmaster'); 27 | $I->expectTo('see that user is logged'); 28 | $I->seeLink('Logout'); 29 | $I->dontSeeLink('Login'); 30 | $I->dontSeeLink('Signup'); 31 | -------------------------------------------------------------------------------- /tests/frontend/functional/_bootstrap.php: -------------------------------------------------------------------------------- 1 |