From bbdb0ba954aea4bbaf80f0b051eecc9540d36b8f Mon Sep 17 00:00:00 2001 From: Egorka Date: Thu, 19 Jul 2018 22:01:07 +0300 Subject: [PATCH] Menu Management Pages module --- backend/components/menu/widgets/views/_item.php | 90 +++++++++- backend/components/menu/widgets/views/menu.php | 52 ++++++ backend/controllers/MenuController.php | 80 ++++++++- backend/controllers/PageController.php | 171 ------------------ backend/forms/PageSearch.php | 57 ------ backend/messages/ru/main.php | 2 + backend/messages/ru/menu.php | 12 ++ backend/messages/ru/page.php | 13 -- backend/views/layouts/left.php | 4 +- backend/views/menu/menu.php | 6 +- backend/views/page/_form.php | 42 ----- backend/views/page/create.php | 16 -- backend/views/page/index.php | 55 ------ backend/views/page/update.php | 18 -- backend/views/page/view.php | 76 -------- common/modules/blog/BlogModule.php | 3 +- .../blog/widgets/views/menu-item/creator.php | 21 ++- common/modules/links/LinksModule.php | 57 ++++++ common/modules/links/messages/ru/link.php | 4 + .../links/widgets/MenuItemCreatorWidget.php | 26 +++ .../links/widgets/views/menu-item/creator.php | 40 +++++ common/modules/pages/PagesModule.php | 78 +++++++++ .../modules/pages/controllers/PageController.php | 59 +++++++ .../pages/controllers/manage/PageController.php | 191 +++++++++++++++++++++ common/modules/pages/entities/Page.php | 84 +++++++++ common/modules/pages/forms/PageForm.php | 72 ++++++++ common/modules/pages/forms/PageSearch.php | 57 ++++++ common/modules/pages/messages/ru/page.php | 14 ++ .../modules/pages/repositories/PageRepository.php | 31 ++++ .../pages/repositories/read/PageReadRepository.php | 23 +++ .../modules/pages/services/PageManageService.php | 91 ++++++++++ common/modules/pages/urls/PageMainUrlRule.php | 89 ++++++++++ common/modules/pages/views/manage/page/_form.php | 42 +++++ common/modules/pages/views/manage/page/create.php | 16 ++ common/modules/pages/views/manage/page/index.php | 55 ++++++ common/modules/pages/views/manage/page/update.php | 18 ++ common/modules/pages/views/manage/page/view.php | 76 ++++++++ common/modules/pages/views/page/view.php | 32 ++++ .../pages/widgets/MenuItemCreatorWidget.php | 29 ++++ .../pages/widgets/views/menu-item/creator.php | 95 ++++++++++ core/entities/Page.php | 84 --------- core/entities/menu/MenuItem.php | 26 ++- core/forms/PageForm.php | 70 -------- core/repositories/page/PageRepository.php | 31 ---- core/repositories/page/read/PageReadRepository.php | 23 --- core/services/PageManageService.php | 91 ---------- core/widgets/menu/MenuWidget.php | 22 +++ core/widgets/menu/views/menu.php | 30 ++++ frontend/controllers/PageController.php | 57 ------ frontend/views/page/view.php | 32 ---- frontend/web/themes/start/layouts/main.php | 14 +- .../start/modules/pages/views/layouts/page.php | 28 +++ .../themes/start/modules/pages/views/page/view.php | 32 ++++ 53 files changed, 1683 insertions(+), 854 deletions(-) delete mode 100644 backend/controllers/PageController.php delete mode 100644 backend/forms/PageSearch.php delete mode 100644 backend/messages/ru/page.php delete mode 100644 backend/views/page/_form.php delete mode 100644 backend/views/page/create.php delete mode 100644 backend/views/page/index.php delete mode 100644 backend/views/page/update.php delete mode 100644 backend/views/page/view.php create mode 100644 common/modules/links/LinksModule.php create mode 100644 common/modules/links/messages/ru/link.php create mode 100644 common/modules/links/widgets/MenuItemCreatorWidget.php create mode 100644 common/modules/links/widgets/views/menu-item/creator.php create mode 100644 common/modules/pages/PagesModule.php create mode 100644 common/modules/pages/controllers/PageController.php create mode 100644 common/modules/pages/controllers/manage/PageController.php create mode 100644 common/modules/pages/entities/Page.php create mode 100644 common/modules/pages/forms/PageForm.php create mode 100644 common/modules/pages/forms/PageSearch.php create mode 100644 common/modules/pages/messages/ru/page.php create mode 100644 common/modules/pages/repositories/PageRepository.php create mode 100644 common/modules/pages/repositories/read/PageReadRepository.php create mode 100644 common/modules/pages/services/PageManageService.php create mode 100644 common/modules/pages/urls/PageMainUrlRule.php create mode 100644 common/modules/pages/views/manage/page/_form.php create mode 100644 common/modules/pages/views/manage/page/create.php create mode 100644 common/modules/pages/views/manage/page/index.php create mode 100644 common/modules/pages/views/manage/page/update.php create mode 100644 common/modules/pages/views/manage/page/view.php create mode 100644 common/modules/pages/views/page/view.php create mode 100644 common/modules/pages/widgets/MenuItemCreatorWidget.php create mode 100644 common/modules/pages/widgets/views/menu-item/creator.php delete mode 100644 core/entities/Page.php delete mode 100644 core/forms/PageForm.php delete mode 100644 core/repositories/page/PageRepository.php delete mode 100644 core/repositories/page/read/PageReadRepository.php delete mode 100644 core/services/PageManageService.php create mode 100644 core/widgets/menu/MenuWidget.php create mode 100644 core/widgets/menu/views/menu.php delete mode 100644 frontend/controllers/PageController.php delete mode 100644 frontend/views/page/view.php create mode 100644 frontend/web/themes/start/modules/pages/views/layouts/page.php create mode 100644 frontend/web/themes/start/modules/pages/views/page/view.php diff --git a/backend/components/menu/widgets/views/_item.php b/backend/components/menu/widgets/views/_item.php index 7811f8b..d4a3f0f 100644 --- a/backend/components/menu/widgets/views/_item.php +++ b/backend/components/menu/widgets/views/_item.php @@ -4,6 +4,8 @@ * Date: 11.07.2018 */ +use yii\helpers\Html; + /** * @var $this \yii\web\View * @var $item array @@ -22,12 +24,96 @@ $menu_item = $item['item'];

name ?> - + module ?>

- Content Panel + +
+
+ 'color: #555555', + ]) ?> + name, [ + 'id' => 'item-name-' . $menu_item->id, + 'class' => 'form-control', + ]) ?> +
+
+ 'color: #555555', + ]) ?> + title_attr, [ + 'id' => 'item-title-attr-' . $menu_item->id, + 'class' => 'form-control', + ]) ?> +
+
+ +
+
+ 'color: #555555', + ]) ?> + style, [ + 'id' => 'item-style-' . $menu_item->id, + 'class' => 'form-control', + ]) ?> +
+
+ 'color: #555555', + ]) ?> + css, [ + 'id' => 'item-css-' . $menu_item->id, + 'class' => 'form-control', + ]) ?> +
+
+ +
+ url_params): ?> +
+ 'color: #555555', + ]) ?> + url, [ + 'id' => 'item-url-' . $menu_item->id, + 'class' => 'form-control', + ]) ?> +
+ + url, [ + 'id' => 'item-url-' . $menu_item->id, + ]) ?> + +
+ 'color: #555555', + ]) ?> + target, [ + '' => Yii::t('menu', 'Self Window'), + '_blank' => Yii::t('menu', 'Blank Window'), + ], [ + 'id' => 'item-target-' . $menu_item->id, + 'class' => 'form-control', + ]) ?> +
+
+ +
+
+ 'item-delete-button btn btn-sm btn-danger', + 'data-id' => $menu_item->id, + ]) ?> + 'item-save-button btn btn-sm btn-success', + 'data-id' => $menu_item->id, + ]) ?> +
+
diff --git a/backend/components/menu/widgets/views/menu.php b/backend/components/menu/widgets/views/menu.php index 1a71f76..31464b2 100644 --- a/backend/components/menu/widgets/views/menu.php +++ b/backend/components/menu/widgets/views/menu.php @@ -27,6 +27,58 @@ function menu_generate($items) { return $html . ''; } +$name_empty_error = Yii::t('menu', 'Name must be specified'); +$item_save_url = Url::to(['menu/save-menu-item-data']); +$item_delete_url = Url::to(['menu/delete-menu-item']); +$confirm_delete_message = Yii::t('buttons', 'Are you sure you want to delete this item?'); +$current_url = Url::to(['menu/index', 'id' => $menu->id]); +$js = <<registerJs($js, $this::POS_READY); + $url = Url::to(['/menu/save-menu-items']); $redirect = Url::to(['menu/index', 'id' => $menu->id]); ?> diff --git a/backend/controllers/MenuController.php b/backend/controllers/MenuController.php index a0f2065..da05d96 100644 --- a/backend/controllers/MenuController.php +++ b/backend/controllers/MenuController.php @@ -6,8 +6,6 @@ namespace backend\controllers; - -use common\modules\blog\BlogModule; use core\entities\menu\Menu; use core\entities\menu\MenuItem; use core\entities\ModuleRecord; @@ -42,7 +40,7 @@ class MenuController extends Controller 'class' => AccessControl::class, 'rules' => [ [ - 'actions' => ['create', 'update', 'delete', 'index', 'save-menu-items'], + 'actions' => ['create', 'update', 'delete', 'index', 'save-menu-items', 'save-menu-item-data', 'delete-menu-item'], 'allow' => true, 'roles' => ['MenuManagement'], ], @@ -56,6 +54,7 @@ class MenuController extends Controller 'class' => VerbFilter::class, 'actions' => [ 'delete' => ['POST'], + 'delete-menu-item' => ['POST'], ], ], ]; @@ -139,6 +138,72 @@ class MenuController extends Controller return $this->redirect(['index']); } + public function actionDeleteMenuItem() + { + Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; + if (Yii::$app->request->isAjax) { + try { + $id = Yii::$app->request->post('id'); + $item = $this->findItemModel($id); + + //$this->deleteItem($item); + $item->delete(); + + Yii::$app->session->setFlash('success', Yii::t('menu', 'Menu Item Deleted')); + + return [ 'result' => 'success' ]; + } + catch (\RuntimeException $e) { + return [ 'result' => 'error', 'message' => $e->getMessage() ]; + } + } + return ['result' => 'error', 'message' => 'Request error']; + } + + //private function deleteItem(MenuItem $item): void + //{ + /*if ($item->hasChildren()) { + $children = $item->children; + foreach ($children as $child) { + $this->deleteItem($child); + } + }*/ + //$item->delete(); + //} + + public function actionSaveMenuItemData() + { + Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; + if (Yii::$app->request->isAjax) { + try { + $id = Yii::$app->request->post('id'); + $name = Yii::$app->request->post('name'); + $title = Yii::$app->request->post('title'); + $style = Yii::$app->request->post('style'); + $css = Yii::$app->request->post('css'); + $url = Yii::$app->request->post('url'); + $target = Yii::$app->request->post('target'); + + $item = $this->findItemModel($id); + $item->name = $name; + $item->title_attr = $title; + $item->style = $style; + $item->css = $css; + $item->url = $url; + $item->target = $target; + $item->save(); + + Yii::$app->session->setFlash('success', Yii::t('menu', 'Menu Item Saved')); + + return [ 'result' => 'success' ]; + } + catch (\RuntimeException $e) { + return [ 'result' => 'error', 'message' => $e->getMessage() ]; + } + } + return ['result' => 'error', 'message' => 'Request error']; + } + public function actionSaveMenuItems() { $json = Yii::$app->request->post('json'); @@ -151,6 +216,7 @@ class MenuController extends Controller $order[$item[1]] = isset($order[$item[1]]) ? $order[$item[1]]+1 : 0; $this->menu_item_service->setPosition($item, $order[$item[1]]); } + Yii::$app->session->setFlash('success', Yii::t('menu', 'Menu Saved')); return [ 'result' => 'success' ]; } catch (\RuntimeException $e) { @@ -192,4 +258,12 @@ class MenuController extends Controller } throw new NotFoundHttpException('The requested menu does not exist.'); } + + protected function findItemModel($id): MenuItem + { + if (($model = MenuItem::findOne($id)) !== null) { + return $model; + } + throw new NotFoundHttpException('The requested menu item does not exist.'); + } } \ No newline at end of file diff --git a/backend/controllers/PageController.php b/backend/controllers/PageController.php deleted file mode 100644 index 22306f9..0000000 --- a/backend/controllers/PageController.php +++ /dev/null @@ -1,171 +0,0 @@ -service = $service; - } - - public function behaviors(): array - { - return [ - 'access' => [ - 'class' => AccessControl::class, - 'rules' => [ - [ - 'actions' => ['create', 'view', 'index', 'update', 'delete', 'move-up', 'move-down'], - 'allow' => true, - 'roles' => ['PagesManagement'], - ], - [ // all the action are accessible to admin - 'allow' => true, - 'roles' => ['admin'], - ], - ], - ], - 'verbs' => [ - 'class' => VerbFilter::class, - 'actions' => [ - 'delete' => ['POST'], - ], - ], - ]; - } - - /** - * @return mixed - */ - public function actionIndex() - { - $searchModel = new PageSearch(); - $dataProvider = $searchModel->search(Yii::$app->request->queryParams); - - return $this->render('index', [ - 'searchModel' => $searchModel, - 'dataProvider' => $dataProvider, - ]); - } - - /** - * @param $id - * - * @return string - * @throws NotFoundHttpException - */ - public function actionView($id) - { - return $this->render('view', [ - 'page' => $this->findModel($id), - ]); - } - - /** - * @return mixed - */ - public function actionCreate() - { - $form = new PageForm(); - if ($form->load(Yii::$app->request->post()) && $form->validate()) { - try { - $page = $this->service->create($form); - return $this->redirect(['view', 'id' => $page->id]); - } catch (\DomainException $e) { - Yii::$app->errorHandler->logException($e); - Yii::$app->session->setFlash('error', $e->getMessage()); - } - } - return $this->render('create', [ - 'model' => $form, - ]); - } - - /** - * @param $id - * - * @return string|\yii\web\Response - * @throws NotFoundHttpException - */ - public function actionUpdate($id) - { - $page = $this->findModel($id); - - $form = new PageForm($page); - if ($form->load(Yii::$app->request->post()) && $form->validate()) { - try { - $this->service->edit($page->id, $form); - return $this->redirect(['view', 'id' => $page->id]); - } catch (\DomainException $e) { - Yii::$app->errorHandler->logException($e); - Yii::$app->session->setFlash('error', $e->getMessage()); - } - } - return $this->render('update', [ - 'model' => $form, - 'page' => $page, - ]); - } - - /** - * @param integer $id - * @return mixed - */ - public function actionDelete($id) - { - try { - $this->service->remove($id); - } catch (\DomainException $e) { - Yii::$app->errorHandler->logException($e); - Yii::$app->session->setFlash('error', $e->getMessage()); - } - return $this->redirect(['index']); - } - - /** - * @param integer $id - * @return mixed - */ - public function actionMoveUp($id) - { - $this->service->moveUp($id); - return $this->redirect(['index']); - } - - /** - * @param integer $id - * @return mixed - */ - public function actionMoveDown($id) - { - $this->service->moveDown($id); - return $this->redirect(['index']); - } - - /** - * @param integer $id - * @return Page the loaded model - * @throws NotFoundHttpException if the model cannot be found - */ - protected function findModel($id): Page - { - if (($model = Page::findOne($id)) !== null) { - return $model; - } - throw new NotFoundHttpException('The requested page does not exist.'); - } -} diff --git a/backend/forms/PageSearch.php b/backend/forms/PageSearch.php deleted file mode 100644 index 05aa7ff..0000000 --- a/backend/forms/PageSearch.php +++ /dev/null @@ -1,57 +0,0 @@ -andWhere(['>', 'depth', 0]); - - $dataProvider = new ActiveDataProvider([ - 'query' => $query, - 'sort' => [ - 'defaultOrder' => ['lft' => SORT_ASC] - ] - ]); - - $this->load($params); - - if (!$this->validate()) { - $query->where('0=1'); - return $dataProvider; - } - - $query->andFilterWhere([ - 'id' => $this->id, - ]); - - $query - ->andFilterWhere(['like', 'name', $this->name]) - ->andFilterWhere(['like', 'slug', $this->slug]) - ->andFilterWhere(['like', 'title', $this->title]); - - return $dataProvider; - } -} diff --git a/backend/messages/ru/main.php b/backend/messages/ru/main.php index 7f2a71f..e2acfdd 100644 --- a/backend/messages/ru/main.php +++ b/backend/messages/ru/main.php @@ -28,4 +28,6 @@ return [ 'Search results' => 'Поиск', 'Search...' => 'Поиск...', 'Name' => 'Название', + 'Title attribute' => 'Атрибут тега Title', + 'Url' => 'Ссылка', ]; \ No newline at end of file diff --git a/backend/messages/ru/menu.php b/backend/messages/ru/menu.php index 2e7fd4d..18c3309 100644 --- a/backend/messages/ru/menu.php +++ b/backend/messages/ru/menu.php @@ -9,4 +9,16 @@ return [ 'Current Menu' => 'Текущее меню', 'Available Blocks' => 'Доступные блоки', 'Menu Items' => 'Элементы меню', + 'Item Name' => 'Название', + 'Item Title Attribute' => 'Атрибут Title', + 'Style Attribute' => 'Атрибут Style', + 'CSS' => 'Класс CSS', + 'Self Window' => 'Текущее окно', + 'Blank Window' => 'Новое окно', + 'Target' => 'Цель', + 'URL' => 'Ссылка', + 'Name must be specified' => 'Укажите название пункта меню', + 'Menu Item Saved' => 'Пункт меню сохранен', + 'Menu Item Deleted' => 'Пункт меню удален', + 'Menu Saved' => 'Меню сохранено', ]; \ No newline at end of file diff --git a/backend/messages/ru/page.php b/backend/messages/ru/page.php deleted file mode 100644 index 5b1bb29..0000000 --- a/backend/messages/ru/page.php +++ /dev/null @@ -1,13 +0,0 @@ - 'Новая страница', - 'Pages' => 'Страницы', - 'Common' => 'Основное', - 'Content' => 'Содержание', - 'SEO' => 'META теги', - 'Title' => 'Заголовок', - 'Slug' => 'ЧПУ ссылка', - 'ID' => '№', - 'Parent Page' => 'Родительская страница', - 'Update Page: {name}' => 'Редактирование страницы: {name}', -]; \ No newline at end of file diff --git a/backend/views/layouts/left.php b/backend/views/layouts/left.php index 5f05099..bf890e7 100644 --- a/backend/views/layouts/left.php +++ b/backend/views/layouts/left.php @@ -83,12 +83,12 @@ $model = new SearchForm(); 'visible' => \Yii::$app->user->can('admin') || \Yii::$app->user->can('MenuManagement'), ], - [ + /*[ 'label' => Yii::t('page', 'Pages'), 'icon' => 'file-o', 'url' => ['/page/index'], 'active' => $this->context->id == 'page', 'visible' => \Yii::$app->user->can('admin') || \Yii::$app->user->can('PagesManagement'), - ], + ],*/ ['label' => Yii::t('post', 'Posts'), 'icon' => 'newspaper-o', 'items' => array_merge( array_map(function(\core\entities\post\PostType $type) { diff --git a/backend/views/menu/menu.php b/backend/views/menu/menu.php index 6276113..9c5d33b 100644 --- a/backend/views/menu/menu.php +++ b/backend/views/menu/menu.php @@ -75,13 +75,13 @@ $this->params['breadcrumbs'][] = $this->title;
-
+ -
+
diff --git a/backend/views/page/_form.php b/backend/views/page/_form.php deleted file mode 100644 index a110c21..0000000 --- a/backend/views/page/_form.php +++ /dev/null @@ -1,42 +0,0 @@ - - -
- - - -
-
-
- field($model, 'parentId')->dropDownList($model->parentsList()) ?> - field($model, 'title')->textInput(['maxlength' => true]) ?> - field($model, 'slug')->textInput(['maxlength' => true]) ?> - field($model, 'content')->widget(CKEditor::className()) ?> - -
-
- -
-
-
- field($model->meta, 'title')->textInput() ?> - field($model->meta, 'description')->textarea(['rows' => 2]) ?> - field($model->meta, 'keywords')->textInput() ?> -
-
- -
- 'btn btn-success']) ?> -
- - - -
diff --git a/backend/views/page/create.php b/backend/views/page/create.php deleted file mode 100644 index 5be1319..0000000 --- a/backend/views/page/create.php +++ /dev/null @@ -1,16 +0,0 @@ -title = Yii::t('page', 'Create Page'); -$this->params['breadcrumbs'][] = ['label' => Yii::t('page', 'Pages'), 'url' => ['index']]; -$this->params['breadcrumbs'][] = $this->title; -?> -
- - render('_form', [ - 'model' => $model, - ]) ?> - -
diff --git a/backend/views/page/index.php b/backend/views/page/index.php deleted file mode 100644 index a1a873f..0000000 --- a/backend/views/page/index.php +++ /dev/null @@ -1,55 +0,0 @@ -title = Yii::t('page', 'Pages'); -$this->params['breadcrumbs'][] = $this->title; -?> -
- -

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

- -
-
- $dataProvider, - 'filterModel' => $searchModel, - 'columns' => [ - [ - 'attribute' => 'title', - 'value' => function (Page $model) { - $indent = ($model->depth > 1 ? str_repeat('  ', $model->depth - 1) . ' ' : ''); - return $indent . Html::a(Html::encode($model->title), ['view', 'id' => $model->id]); - }, - 'format' => 'raw', - ], - [ - 'value' => function (Page $model) { - return - Html::a('', ['move-up', 'id' => $model->id]) . - Html::a('', ['move-down', 'id' => $model->id]); - }, - 'format' => 'raw', - 'options' => ['style' => 'width: 100px;'], - 'contentOptions' => ['style' => 'text-align: center'], - ], - 'slug', - [ - 'class' => ActionColumn::class, - 'options' => ['style' => 'width: 100px;'], - 'contentOptions' => ['class' => 'text-center'], - ], - ], - ]); ?> -
-
-
diff --git a/backend/views/page/update.php b/backend/views/page/update.php deleted file mode 100644 index ea93140..0000000 --- a/backend/views/page/update.php +++ /dev/null @@ -1,18 +0,0 @@ -title = Yii::t('page', 'Update Page: {name}', ['name' => $page->title]); -$this->params['breadcrumbs'][] = ['label' => Yii::t('page', 'Pages'), 'url' => ['index']]; -$this->params['breadcrumbs'][] = ['label' => $page->title, 'url' => ['view', 'id' => $page->id]]; -$this->params['breadcrumbs'][] = Yii::t('buttons', 'Editing'); -?> -
- - render('_form', [ - 'model' => $model, - ]) ?> - -
diff --git a/backend/views/page/view.php b/backend/views/page/view.php deleted file mode 100644 index 0532100..0000000 --- a/backend/views/page/view.php +++ /dev/null @@ -1,76 +0,0 @@ -title = $page->title; -$this->params['breadcrumbs'][] = ['label' => Yii::t('page', 'Pages'), 'url' => ['index']]; -$this->params['breadcrumbs'][] = $this->title; -?> -
- -

- 'btn btn-default']) ?> - $page->id], ['class' => 'btn btn-primary']) ?> - $page->id], [ - 'class' => 'btn btn-danger', - 'data' => [ - 'confirm' => Yii::t('buttons', 'Are you sure you want to delete this item?'), - 'method' => 'post', - ], - ]) ?> -

- -
-
-
- $page, - 'attributes' => [ - 'id', - 'title', - 'slug', - ], - ]) ?> -
-
- -
-
-
- formatter->asHtml($page->content, [ - 'Attr.AllowedRel' => array('nofollow'), - 'HTML.SafeObject' => true, - 'Output.FlashCompat' => true, - 'HTML.SafeIframe' => true, - 'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%', - ]) ?> -
-
- -
-
-
- $page, - 'attributes' => [ - [ - 'attribute' => 'meta.title', - 'label' => Yii::t('main', 'Title'), - ], - [ - 'attribute' => 'meta.description', - 'label' => Yii::t('main', 'Description'), - ], - [ - 'attribute' => 'meta.keywords', - 'label' => Yii::t('main', 'Keywords'), - ], - ], - ]) ?> -
-
-
diff --git a/common/modules/blog/BlogModule.php b/common/modules/blog/BlogModule.php index 8a75e0f..bd76084 100644 --- a/common/modules/blog/BlogModule.php +++ b/common/modules/blog/BlogModule.php @@ -1,11 +1,11 @@ 'blog', 'title' => \Yii::t('blog', 'Blog'), 'content' => MenuItemCreatorWidget::widget([ 'menu_id' => $menu_id, diff --git a/common/modules/blog/widgets/views/menu-item/creator.php b/common/modules/blog/widgets/views/menu-item/creator.php index 9b338a4..6e93ca0 100644 --- a/common/modules/blog/widgets/views/menu-item/creator.php +++ b/common/modules/blog/widgets/views/menu-item/creator.php @@ -14,26 +14,35 @@ use yii\helpers\Html; use yii\web\JsExpression; use yii\helpers\Url; +$block_name = Yii::t('blog', 'Blog'); +$block_title_attr = Yii::t('blog', 'Blog'); + $js = << [ 'placeholder' => Yii::t('blog', 'Select post...'), 'id' => 'post_select', - 'onchange' => new JsExpression("updateUrl('post')"), + 'onchange' => new JsExpression("updateBlogUrl('post')"), ], 'pluginOptions' => [ 'disabled' => true, @@ -86,9 +95,11 @@ $fetchUrl = Url::to( [ '/blog/manage/post/post-search' ] ); field($model, 'name')->hiddenInput([ + 'id' => 'blog_menu_item_name', ])->label(false) ?> field($model, 'title_attr')->hiddenInput([ + 'id' => 'blog_menu_item_title_attr', ])->label(false) ?> field($model, 'module')->hiddenInput([ diff --git a/common/modules/links/LinksModule.php b/common/modules/links/LinksModule.php new file mode 100644 index 0000000..ec7e313 --- /dev/null +++ b/common/modules/links/LinksModule.php @@ -0,0 +1,57 @@ +getI18n()->translations = ArrayHelper::merge($app->getI18n()->translations, [ + 'link' => [ + 'class' => 'yii\i18n\PhpMessageSource', + 'basePath' => '@common/modules/links/messages', + ], + 'link_public' => [ + 'class' => 'yii\i18n\PhpMessageSource', + 'basePath' => '@common/modules/links/messages', + ], + ]); + } + + public static function getMenuItemCreator($menu_id): array + { + $widgets = []; + $widgets[] = [ + 'id' => 'links', + 'title' => \Yii::t('link', 'Links'), + 'content' => MenuItemCreatorWidget::widget([ + 'menu_id' => $menu_id, + ]), + ]; + return $widgets; + } +} diff --git a/common/modules/links/messages/ru/link.php b/common/modules/links/messages/ru/link.php new file mode 100644 index 0000000..72d235e --- /dev/null +++ b/common/modules/links/messages/ru/link.php @@ -0,0 +1,4 @@ + 'Ссылки', +]; \ No newline at end of file diff --git a/common/modules/links/widgets/MenuItemCreatorWidget.php b/common/modules/links/widgets/MenuItemCreatorWidget.php new file mode 100644 index 0000000..cd11575 --- /dev/null +++ b/common/modules/links/widgets/MenuItemCreatorWidget.php @@ -0,0 +1,26 @@ +module = \Yii::t('link', 'Links'); + $form->menu_id = $this->menu_id; + + return $this->render('menu-item/creator', [ + 'model' => $form, + ]); + } +} \ No newline at end of file diff --git a/common/modules/links/widgets/views/menu-item/creator.php b/common/modules/links/widgets/views/menu-item/creator.php new file mode 100644 index 0000000..6b5ecc8 --- /dev/null +++ b/common/modules/links/widgets/views/menu-item/creator.php @@ -0,0 +1,40 @@ + + + \ No newline at end of file diff --git a/common/modules/pages/PagesModule.php b/common/modules/pages/PagesModule.php new file mode 100644 index 0000000..1dadde0 --- /dev/null +++ b/common/modules/pages/PagesModule.php @@ -0,0 +1,78 @@ +params['search_rules'][] = "SELECT title, content, CONCAT('/pages/manage/page/view/', id) AS url FROM {{pages}}"; + + $app->getUrlManager()->addRules([ + ['class' => 'common\modules\pages\urls\PageMainUrlRule'], + ]); + + $app->getUrlManager()->addRules([ + 'pages/manage/page/view/' => 'pages/manage/page/view', + ]); + + // add languages + $app->getI18n()->translations = ArrayHelper::merge($app->getI18n()->translations, [ + 'page' => [ + 'class' => 'yii\i18n\PhpMessageSource', + 'basePath' => '@common/modules/pages/messages', + ], + 'page_public' => [ + 'class' => 'yii\i18n\PhpMessageSource', + 'basePath' => '@common/modules/pages/messages', + ], + ]); + + // add menu items + if (basename($app->getBasePath()) === 'backend') { + $app->params['adminMenu'][] = [ + 'label' => \Yii::t( 'page', 'Pages' ), + 'icon' => 'file-o', + 'url' => [ '/pages/manage/page/index' ], + 'visible' => \Yii::$app->user->can( 'admin' ) || \Yii::$app->user->can( 'PagesManagement' ) + ]; + } + } + + public static function getMenuItemCreator($menu_id): array + { + $widgets = []; + $widgets[] = [ + 'id' => 'pages', + 'title' => \Yii::t('page', 'Pages'), + 'content' => MenuItemCreatorWidget::widget([ + 'menu_id' => $menu_id, + ]), + ]; + return $widgets; + } +} diff --git a/common/modules/pages/controllers/PageController.php b/common/modules/pages/controllers/PageController.php new file mode 100644 index 0000000..94fb026 --- /dev/null +++ b/common/modules/pages/controllers/PageController.php @@ -0,0 +1,59 @@ +pages = $pages; + } + + public function behaviors(): array + { + return [ + 'access' => [ + 'class' => AccessControl::class, + 'rules' => [ + [ + 'actions' => ['view'], + 'allow' => true, + 'roles' => ['Pages'], + ], + [ // all the action are accessible to admin + 'allow' => true, + 'roles' => ['admin'], + ], + ], + ], + ]; + } + + /** + * @param $id + * @return mixed + * @throws NotFoundHttpException + * @internal param string $slug + */ + public function actionView($id) + { + if (!$page = $this->pages->find($id)) { + throw new NotFoundHttpException('The requested page does not exist.'); + } + + return $this->render('view', [ + 'page' => $page, + ]); + } +} diff --git a/common/modules/pages/controllers/manage/PageController.php b/common/modules/pages/controllers/manage/PageController.php new file mode 100644 index 0000000..22f79e0 --- /dev/null +++ b/common/modules/pages/controllers/manage/PageController.php @@ -0,0 +1,191 @@ +service = $service; + } + + public function behaviors(): array + { + return [ + 'access' => [ + 'class' => AccessControl::class, + 'rules' => [ + [ + 'actions' => ['create', 'view', 'index', 'update', 'delete', 'move-up', 'move-down'], + 'allow' => true, + 'roles' => ['PagesManagement'], + ], + [ // all the action are accessible to admin + 'allow' => true, + 'roles' => ['admin'], + ], + ], + ], + 'verbs' => [ + 'class' => VerbFilter::class, + 'actions' => [ + 'delete' => ['POST'], + ], + ], + ]; + } + + /** + * @return mixed + */ + public function actionIndex() + { + $searchModel = new PageSearch(); + $dataProvider = $searchModel->search(Yii::$app->request->queryParams); + + return $this->render('index', [ + 'searchModel' => $searchModel, + 'dataProvider' => $dataProvider, + ]); + } + + /** + * @param $id + * + * @return string + * @throws NotFoundHttpException + */ + public function actionView($id) + { + return $this->render('view', [ + 'page' => $this->findModel($id), + ]); + } + + /** + * @return mixed + */ + public function actionCreate() + { + $form = new PageForm(); + if ($form->load(Yii::$app->request->post()) && $form->validate()) { + try { + $page = $this->service->create($form); + return $this->redirect(['view', 'id' => $page->id]); + } catch (\DomainException $e) { + Yii::$app->errorHandler->logException($e); + Yii::$app->session->setFlash('error', $e->getMessage()); + } + } + return $this->render('create', [ + 'model' => $form, + ]); + } + + /** + * @param $id + * + * @return string|\yii\web\Response + * @throws NotFoundHttpException + */ + public function actionUpdate($id) + { + $page = $this->findModel($id); + + $form = new PageForm($page); + if ($form->load(Yii::$app->request->post()) && $form->validate()) { + try { + $this->service->edit($page->id, $form); + return $this->redirect(['view', 'id' => $page->id]); + } catch (\DomainException $e) { + Yii::$app->errorHandler->logException($e); + Yii::$app->session->setFlash('error', $e->getMessage()); + } + } + return $this->render('update', [ + 'model' => $form, + 'page' => $page, + ]); + } + + /** + * @param integer $id + * @return mixed + */ + public function actionDelete($id) + { + try { + $this->service->remove($id); + } catch (\DomainException $e) { + Yii::$app->errorHandler->logException($e); + Yii::$app->session->setFlash('error', $e->getMessage()); + } + return $this->redirect(['index']); + } + + /** + * @param integer $id + * @return mixed + */ + public function actionMoveUp($id) + { + $this->service->moveUp($id); + return $this->redirect(['index']); + } + + /** + * @param integer $id + * @return mixed + */ + public function actionMoveDown($id) + { + $this->service->moveDown($id); + return $this->redirect(['index']); + } + + public function actionPageSearch($q = null, $id = null) + { + \Yii::$app->response->format = Response::FORMAT_JSON; + $out = ['results' => ['id' => '', 'text' => '']]; + if (!is_null($q)) { + $data = Page::find()->select('id, title as text')->andWhere(['like', 'title', $q])->limit(20)->asArray()->all(); + $out['results'] = array_values($data); + } + elseif ($id > 0) { + $tag_name = Page::findOne($id)->title; + $out['results'] = ['id' => $tag_name, 'text' => $tag_name]; + } + else { + $data = Page::find()->select('id, title as text')->orderBy(['id' => SORT_DESC])->limit(20)->asArray()->all(); + $out['results'] = array_values($data); + } + return $out; + } + + /** + * @param integer $id + * @return Page the loaded model + * @throws NotFoundHttpException if the model cannot be found + */ + protected function findModel($id): Page + { + if (($model = Page::findOne($id)) !== null) { + return $model; + } + throw new NotFoundHttpException('The requested page does not exist.'); + } +} diff --git a/common/modules/pages/entities/Page.php b/common/modules/pages/entities/Page.php new file mode 100644 index 0000000..9d69749 --- /dev/null +++ b/common/modules/pages/entities/Page.php @@ -0,0 +1,84 @@ +title = $title; + $page->slug = $slug; + $page->content = $content; + $page->meta = $meta; + return $page; + } + + public function edit($title, $slug, $content, Meta $meta): void + { + $this->title = $title; + $this->slug = $slug; + $this->content = $content; + $this->meta = $meta; + } + + public function getSeoTitle(): string + { + return $this->meta->title ?: $this->title; + } + + public static function tableName(): string + { + return '{{%pages}}'; + } + + public function behaviors(): array + { + return [ + MetaBehavior::class, + NestedSetsBehavior::class, + ]; + } + + public function transactions(): array + { + return [ + self::SCENARIO_DEFAULT => self::OP_ALL, + ]; + } + + public function attributeLabels() { + return [ + 'title' => Yii::t('page', 'Title'), + 'slug' => Yii::t('page', 'Slug'), + 'id' => Yii::t('page', 'ID'), + 'content' => Yii::t('page', 'Content'), + ]; + } +} \ No newline at end of file diff --git a/common/modules/pages/forms/PageForm.php b/common/modules/pages/forms/PageForm.php new file mode 100644 index 0000000..60f7e36 --- /dev/null +++ b/common/modules/pages/forms/PageForm.php @@ -0,0 +1,72 @@ +title = $page->title; + $this->slug = $page->slug; + $this->content = $page->content; + $this->parentId = $page->parent ? $page->parent->id : null; + $this->meta = new MetaForm($page->meta); + $this->_page = $page; + } else { + $this->meta = new MetaForm(); + } + parent::__construct($config); + } + + public function rules(): array + { + return [ + [['title', 'slug'], 'required'], + [['parentId'], 'integer'], + [['title', 'slug'], 'string', 'max' => 255], + [['content'], 'string'], + ['slug', SlugValidator::class], + [['slug'], 'unique', 'targetClass' => Page::class, 'filter' => $this->_page ? ['<>', 'id', $this->_page->id] : null] + ]; + } + + public function attributeLabels() { + return [ + 'title' => Yii::t('page', 'Title'), + 'slug' => Yii::t('page', 'Slug'), + 'id' => Yii::t('page', 'ID'), + 'content' => Yii::t('page', 'Content'), + 'parentId' => Yii::t('page', 'Parent Page'), + ]; + } + + public function parentsList(): array + { + return ArrayHelper::map(Page::find()->orderBy('lft')->asArray()->all(), 'id', function (array $page) { + return ($page['depth'] > 1 ? str_repeat('-- ', $page['depth'] - 1) . ' ' : '') . $page['title']; + }); + } + + public function internalForms(): array + { + return ['meta']; + } +} \ No newline at end of file diff --git a/common/modules/pages/forms/PageSearch.php b/common/modules/pages/forms/PageSearch.php new file mode 100644 index 0000000..db1578b --- /dev/null +++ b/common/modules/pages/forms/PageSearch.php @@ -0,0 +1,57 @@ +andWhere(['>', 'depth', 0]); + + $dataProvider = new ActiveDataProvider([ + 'query' => $query, + 'sort' => [ + 'defaultOrder' => ['lft' => SORT_ASC] + ] + ]); + + $this->load($params); + + if (!$this->validate()) { + $query->where('0=1'); + return $dataProvider; + } + + $query->andFilterWhere([ + 'id' => $this->id, + ]); + + $query + ->andFilterWhere(['like', 'name', $this->name]) + ->andFilterWhere(['like', 'slug', $this->slug]) + ->andFilterWhere(['like', 'title', $this->title]); + + return $dataProvider; + } +} diff --git a/common/modules/pages/messages/ru/page.php b/common/modules/pages/messages/ru/page.php new file mode 100644 index 0000000..091c640 --- /dev/null +++ b/common/modules/pages/messages/ru/page.php @@ -0,0 +1,14 @@ + 'Новая страница', + 'Pages' => 'Страницы', + 'Common' => 'Основное', + 'Content' => 'Содержание', + 'SEO' => 'META теги', + 'Title' => 'Заголовок', + 'Slug' => 'ЧПУ ссылка', + 'ID' => '№', + 'Parent Page' => 'Родительская страница', + 'Update Page: {name}' => 'Редактирование страницы: {name}', + 'Select page...' => 'Укажите страницу', +]; \ No newline at end of file diff --git a/common/modules/pages/repositories/PageRepository.php b/common/modules/pages/repositories/PageRepository.php new file mode 100644 index 0000000..05de05c --- /dev/null +++ b/common/modules/pages/repositories/PageRepository.php @@ -0,0 +1,31 @@ +save()) { + throw new \RuntimeException('Saving error.'); + } + } + + public function remove(Page $page): void + { + if (!$page->delete()) { + throw new \RuntimeException('Removing error.'); + } + } +} \ No newline at end of file diff --git a/common/modules/pages/repositories/read/PageReadRepository.php b/common/modules/pages/repositories/read/PageReadRepository.php new file mode 100644 index 0000000..b084c47 --- /dev/null +++ b/common/modules/pages/repositories/read/PageReadRepository.php @@ -0,0 +1,23 @@ +andWhere(['>', 'depth', 0])->all(); + } + + public function find($id): ?Page + { + return Page::findOne($id); + } + + public function findBySlug($slug): ?Page + { + return Page::find()->andWhere(['slug' => $slug])->andWhere(['>', 'depth', 0])->one(); + } +} \ No newline at end of file diff --git a/common/modules/pages/services/PageManageService.php b/common/modules/pages/services/PageManageService.php new file mode 100644 index 0000000..de2d663 --- /dev/null +++ b/common/modules/pages/services/PageManageService.php @@ -0,0 +1,91 @@ +pages = $pages; + } + + public function create(PageForm $form): Page + { + $parent = $this->pages->get($form->parentId); + $page = Page::create( + $form->title, + $form->slug, + $form->content, + new Meta( + $form->meta->title, + $form->meta->description, + $form->meta->keywords + ) + ); + $page->appendTo($parent); + $this->pages->save($page); + return $page; + } + + public function edit($id, PageForm $form): void + { + $page = $this->pages->get($id); + $this->assertIsNotRoot($page); + $page->edit( + $form->title, + $form->slug, + $form->content, + new Meta( + $form->meta->title, + $form->meta->description, + $form->meta->keywords + ) + ); + if ($form->parentId !== $page->parent->id) { + $parent = $this->pages->get($form->parentId); + $page->appendTo($parent); + } + $this->pages->save($page); + } + + public function moveUp($id): void + { + $page = $this->pages->get($id); + $this->assertIsNotRoot($page); + if ($prev = $page->prev) { + $page->insertBefore($prev); + } + $this->pages->save($page); + } + + public function moveDown($id): void + { + $page = $this->pages->get($id); + $this->assertIsNotRoot($page); + if ($next = $page->next) { + $page->insertAfter($next); + } + $this->pages->save($page); + } + + public function remove($id): void + { + $page = $this->pages->get($id); + $this->assertIsNotRoot($page); + $this->pages->remove($page); + } + + private function assertIsNotRoot(Page $page): void + { + if ($page->isRoot()) { + throw new \DomainException('Unable to manage the root page.'); + } + } +} \ No newline at end of file diff --git a/common/modules/pages/urls/PageMainUrlRule.php b/common/modules/pages/urls/PageMainUrlRule.php new file mode 100644 index 0000000..3c29563 --- /dev/null +++ b/common/modules/pages/urls/PageMainUrlRule.php @@ -0,0 +1,89 @@ +repository = $repository; + $this->cache = $cache; + } + + public function parseRequest($manager, $request) + { + if (preg_match('#^' . $this->prefix . '(.*[a-z])$#is', $request->pathInfo, $matches)) { + $path = $matches['1']; + + $result = $this->cache->getOrSet( [ 'page_main_route', 'path' => $path ], function () use ( $path ) { + if ( ! $post = $this->repository->findBySlug($this->getPathSlug( $path ) ) ) { + return [ 'id' => null, 'path' => null ]; + } + return [ 'id' => $post->id, 'path' => $post->slug ]; + }, null, new TagDependency(['tags' => ['pages']]) ); + + if ( empty( $result['id'] ) ) { + return false; + } + + if ( $path != $result['path'] ) { + throw new UrlNormalizerRedirectException( [ 'pages/page/view', 'id' => $result['id'] ], 301 ); + } + + return ['pages/page/view', ['id' => $result['id']]]; + } + return false; + } + + public function createUrl($manager, $route, $params) + { + if ($route == 'pages/page/view') { + if (empty($params['id'])) { + throw new InvalidArgumentException('Empty id.'); + } + $id = $params['id']; + + $url = $this->cache->getOrSet(['page_main_route', 'id' => $id], function () use ($id) { + if (!$page = $this->repository->find($id)) { + return null; + } + return $page->slug; + }, null, new TagDependency(['tags' => ['pages']])); + + if (!$url) { + return '#'; + //throw new InvalidArgumentException('Undefined id.'); + } + + $url = $this->prefix . '/' . $url; + unset($params['id']); + if (!empty($params) && ($query = http_build_query($params)) !== '') { + $url .= '?' . $query; + } + + return $url; + } + return false; + } + + private function getPathSlug($path): string + { + $chunks = explode('/', $path); + return end($chunks); + } +} \ No newline at end of file diff --git a/common/modules/pages/views/manage/page/_form.php b/common/modules/pages/views/manage/page/_form.php new file mode 100644 index 0000000..a9d217f --- /dev/null +++ b/common/modules/pages/views/manage/page/_form.php @@ -0,0 +1,42 @@ + + +
+ + + +
+
+
+ field($model, 'parentId')->dropDownList($model->parentsList()) ?> + field($model, 'title')->textInput(['maxlength' => true]) ?> + field($model, 'slug')->textInput(['maxlength' => true]) ?> + field($model, 'content')->widget(CKEditor::class) ?> + +
+
+ +
+
+
+ field($model->meta, 'title')->textInput() ?> + field($model->meta, 'description')->textarea(['rows' => 2]) ?> + field($model->meta, 'keywords')->textInput() ?> +
+
+ +
+ 'btn btn-success']) ?> +
+ + + +
diff --git a/common/modules/pages/views/manage/page/create.php b/common/modules/pages/views/manage/page/create.php new file mode 100644 index 0000000..4271875 --- /dev/null +++ b/common/modules/pages/views/manage/page/create.php @@ -0,0 +1,16 @@ +title = Yii::t('page', 'Create Page'); +$this->params['breadcrumbs'][] = ['label' => Yii::t('page', 'Pages'), 'url' => ['index']]; +$this->params['breadcrumbs'][] = $this->title; +?> +
+ + render('_form', [ + 'model' => $model, + ]) ?> + +
diff --git a/common/modules/pages/views/manage/page/index.php b/common/modules/pages/views/manage/page/index.php new file mode 100644 index 0000000..2368545 --- /dev/null +++ b/common/modules/pages/views/manage/page/index.php @@ -0,0 +1,55 @@ +title = Yii::t('page', 'Pages'); +$this->params['breadcrumbs'][] = $this->title; +?> +
+ +

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

+ +
+
+ $dataProvider, + 'filterModel' => $searchModel, + 'columns' => [ + [ + 'attribute' => 'title', + 'value' => function (Page $model) { + $indent = ($model->depth > 1 ? str_repeat('  ', $model->depth - 1) . ' ' : ''); + return $indent . Html::a(Html::encode($model->title), ['view', 'id' => $model->id]); + }, + 'format' => 'raw', + ], + [ + 'value' => function (Page $model) { + return + Html::a('', ['move-up', 'id' => $model->id]) . + Html::a('', ['move-down', 'id' => $model->id]); + }, + 'format' => 'raw', + 'options' => ['style' => 'width: 100px;'], + 'contentOptions' => ['style' => 'text-align: center'], + ], + 'slug', + [ + 'class' => ActionColumn::class, + 'options' => ['style' => 'width: 100px;'], + 'contentOptions' => ['class' => 'text-center'], + ], + ], + ]); ?> +
+
+
diff --git a/common/modules/pages/views/manage/page/update.php b/common/modules/pages/views/manage/page/update.php new file mode 100644 index 0000000..3d9a13d --- /dev/null +++ b/common/modules/pages/views/manage/page/update.php @@ -0,0 +1,18 @@ +title = Yii::t('page', 'Update Page: {name}', ['name' => $page->title]); +$this->params['breadcrumbs'][] = ['label' => Yii::t('page', 'Pages'), 'url' => ['index']]; +$this->params['breadcrumbs'][] = ['label' => $page->title, 'url' => ['view', 'id' => $page->id]]; +$this->params['breadcrumbs'][] = Yii::t('buttons', 'Editing'); +?> +
+ + render('_form', [ + 'model' => $model, + ]) ?> + +
diff --git a/common/modules/pages/views/manage/page/view.php b/common/modules/pages/views/manage/page/view.php new file mode 100644 index 0000000..5b5a9ed --- /dev/null +++ b/common/modules/pages/views/manage/page/view.php @@ -0,0 +1,76 @@ +title = $page->title; +$this->params['breadcrumbs'][] = ['label' => Yii::t('page', 'Pages'), 'url' => ['index']]; +$this->params['breadcrumbs'][] = $this->title; +?> +
+ +

+ 'btn btn-default']) ?> + $page->id], ['class' => 'btn btn-primary']) ?> + $page->id], [ + 'class' => 'btn btn-danger', + 'data' => [ + 'confirm' => Yii::t('buttons', 'Are you sure you want to delete this item?'), + 'method' => 'post', + ], + ]) ?> +

+ +
+
+
+ $page, + 'attributes' => [ + 'id', + 'title', + 'slug', + ], + ]) ?> +
+
+ +
+
+
+ formatter->asHtml($page->content, [ + 'Attr.AllowedRel' => array('nofollow'), + 'HTML.SafeObject' => true, + 'Output.FlashCompat' => true, + 'HTML.SafeIframe' => true, + 'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%', + ]) ?> +
+
+ +
+
+
+ $page, + 'attributes' => [ + [ + 'attribute' => 'meta.title', + 'label' => Yii::t('main', 'Title'), + ], + [ + 'attribute' => 'meta.description', + 'label' => Yii::t('main', 'Description'), + ], + [ + 'attribute' => 'meta.keywords', + 'label' => Yii::t('main', 'Keywords'), + ], + ], + ]) ?> +
+
+
diff --git a/common/modules/pages/views/page/view.php b/common/modules/pages/views/page/view.php new file mode 100644 index 0000000..d46e86e --- /dev/null +++ b/common/modules/pages/views/page/view.php @@ -0,0 +1,32 @@ +title = $page->getSeoTitle(); + +$this->registerMetaTag(['name' => 'description', 'content' => $page->meta->description]); +$this->registerMetaTag(['name' => 'keywords', 'content' => $page->meta->keywords]); + +foreach ($page->parents as $parent) { + if (!$parent->isRoot()) { + $this->params['breadcrumbs'][] = ['label' => $parent->title, 'url' => ['view', 'id' => $parent->id]]; + } +} +$this->params['breadcrumbs'][] = $page->title; +?> +
+ +

title) ?>

+ + formatter->asHtml($page->content, [ + 'Attr.AllowedRel' => array('nofollow'), + 'HTML.SafeObject' => true, + 'Output.FlashCompat' => true, + 'HTML.SafeIframe' => true, + 'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%', + ]) ?> + +
diff --git a/common/modules/pages/widgets/MenuItemCreatorWidget.php b/common/modules/pages/widgets/MenuItemCreatorWidget.php new file mode 100644 index 0000000..ebc1c32 --- /dev/null +++ b/common/modules/pages/widgets/MenuItemCreatorWidget.php @@ -0,0 +1,29 @@ +module = \Yii::t('page', 'Pages'); + $form->name = \Yii::t('page', 'Pages'); + $form->title_attr = \Yii::t('page', 'Pages'); + $form->menu_id = $this->menu_id; + $form->url = '/pages/page/index'; + + return $this->render('menu-item/creator', [ + 'model' => $form, + ]); + } +} \ No newline at end of file diff --git a/common/modules/pages/widgets/views/menu-item/creator.php b/common/modules/pages/widgets/views/menu-item/creator.php new file mode 100644 index 0000000..54c87b0 --- /dev/null +++ b/common/modules/pages/widgets/views/menu-item/creator.php @@ -0,0 +1,95 @@ +registerJs($js, $this::POS_HEAD); + +$fetchUrl = Url::to( [ '/pages/manage/page/page-search' ] ); +?> + + \ No newline at end of file diff --git a/core/entities/Page.php b/core/entities/Page.php deleted file mode 100644 index 9e907aa..0000000 --- a/core/entities/Page.php +++ /dev/null @@ -1,84 +0,0 @@ -title = $title; - $page->slug = $slug; - $page->content = $content; - $page->meta = $meta; - return $page; - } - - public function edit($title, $slug, $content, Meta $meta): void - { - $this->title = $title; - $this->slug = $slug; - $this->content = $content; - $this->meta = $meta; - } - - public function getSeoTitle(): string - { - return $this->meta->title ?: $this->title; - } - - public static function tableName(): string - { - return '{{%pages}}'; - } - - public function behaviors(): array - { - return [ - MetaBehavior::class, - NestedSetsBehavior::class, - ]; - } - - public function transactions(): array - { - return [ - self::SCENARIO_DEFAULT => self::OP_ALL, - ]; - } - - public function attributeLabels() { - return [ - 'title' => Yii::t('page', 'Title'), - 'slug' => Yii::t('page', 'Slug'), - 'id' => Yii::t('page', 'ID'), - 'content' => Yii::t('page', 'Content'), - ]; - } -} \ No newline at end of file diff --git a/core/entities/menu/MenuItem.php b/core/entities/menu/MenuItem.php index 3897219..f9cc849 100644 --- a/core/entities/menu/MenuItem.php +++ b/core/entities/menu/MenuItem.php @@ -6,8 +6,9 @@ namespace core\entities\menu; -use paulzi\sortable\SortableBehavior; use yii\db\ActiveRecord; +use yii\helpers\Json; +use yii\helpers\Url; /** * Class MenuItem @@ -91,11 +92,34 @@ class MenuItem extends ActiveRecord return false; } + public function beforeDelete(){ + foreach($this->children as $child) { + $child->delete(); + } + return parent::beforeDelete(); + } + + public function getUrl(): string + { + $params = $this->url_params ? Json::decode($this->url_params, true) : []; + return Url::to(array_merge([$this->url], $params)); + } + + public function isActive(): bool + { + return \Yii::$app->request->getUrl() == $this->getUrl(); + } + public function getChildren() { return $this->hasMany(MenuItem::class, ['parent_id' => 'id'])->orderBy(['sort' => SORT_ASC]); } + public function hasChildren(): bool + { + return $this->hasMany(MenuItem::class, ['parent_id' => 'id'])->orderBy(['sort' => SORT_ASC])->count() > 0 ? true : false; + } + public function getParent() { return $this->hasOne(MenuItem::class, ['id' => 'parent_id']); diff --git a/core/forms/PageForm.php b/core/forms/PageForm.php deleted file mode 100644 index 63fda31..0000000 --- a/core/forms/PageForm.php +++ /dev/null @@ -1,70 +0,0 @@ -title = $page->title; - $this->slug = $page->slug; - $this->content = $page->content; - $this->parentId = $page->parent ? $page->parent->id : null; - $this->meta = new MetaForm($page->meta); - $this->_page = $page; - } else { - $this->meta = new MetaForm(); - } - parent::__construct($config); - } - - public function rules(): array - { - return [ - [['title', 'slug'], 'required'], - [['parentId'], 'integer'], - [['title', 'slug'], 'string', 'max' => 255], - [['content'], 'string'], - ['slug', SlugValidator::class], - [['slug'], 'unique', 'targetClass' => Page::class, 'filter' => $this->_page ? ['<>', 'id', $this->_page->id] : null] - ]; - } - - public function attributeLabels() { - return [ - 'title' => Yii::t('page', 'Title'), - 'slug' => Yii::t('page', 'Slug'), - 'id' => Yii::t('page', 'ID'), - 'content' => Yii::t('page', 'Content'), - 'parentId' => Yii::t('page', 'Parent Page'), - ]; - } - - public function parentsList(): array - { - return ArrayHelper::map(Page::find()->orderBy('lft')->asArray()->all(), 'id', function (array $page) { - return ($page['depth'] > 1 ? str_repeat('-- ', $page['depth'] - 1) . ' ' : '') . $page['title']; - }); - } - - public function internalForms(): array - { - return ['meta']; - } -} \ No newline at end of file diff --git a/core/repositories/page/PageRepository.php b/core/repositories/page/PageRepository.php deleted file mode 100644 index a0bd631..0000000 --- a/core/repositories/page/PageRepository.php +++ /dev/null @@ -1,31 +0,0 @@ -save()) { - throw new \RuntimeException('Saving error.'); - } - } - - public function remove(Page $page): void - { - if (!$page->delete()) { - throw new \RuntimeException('Removing error.'); - } - } -} \ No newline at end of file diff --git a/core/repositories/page/read/PageReadRepository.php b/core/repositories/page/read/PageReadRepository.php deleted file mode 100644 index c6f25e7..0000000 --- a/core/repositories/page/read/PageReadRepository.php +++ /dev/null @@ -1,23 +0,0 @@ -andWhere(['>', 'depth', 0])->all(); - } - - public function find($id): ?Page - { - return Page::findOne($id); - } - - public function findBySlug($slug): ?Page - { - return Page::find()->andWhere(['slug' => $slug])->andWhere(['>', 'depth', 0])->one(); - } -} \ No newline at end of file diff --git a/core/services/PageManageService.php b/core/services/PageManageService.php deleted file mode 100644 index 2a9bdff..0000000 --- a/core/services/PageManageService.php +++ /dev/null @@ -1,91 +0,0 @@ -pages = $pages; - } - - public function create(PageForm $form): Page - { - $parent = $this->pages->get($form->parentId); - $page = Page::create( - $form->title, - $form->slug, - $form->content, - new Meta( - $form->meta->title, - $form->meta->description, - $form->meta->keywords - ) - ); - $page->appendTo($parent); - $this->pages->save($page); - return $page; - } - - public function edit($id, PageForm $form): void - { - $page = $this->pages->get($id); - $this->assertIsNotRoot($page); - $page->edit( - $form->title, - $form->slug, - $form->content, - new Meta( - $form->meta->title, - $form->meta->description, - $form->meta->keywords - ) - ); - if ($form->parentId !== $page->parent->id) { - $parent = $this->pages->get($form->parentId); - $page->appendTo($parent); - } - $this->pages->save($page); - } - - public function moveUp($id): void - { - $page = $this->pages->get($id); - $this->assertIsNotRoot($page); - if ($prev = $page->prev) { - $page->insertBefore($prev); - } - $this->pages->save($page); - } - - public function moveDown($id): void - { - $page = $this->pages->get($id); - $this->assertIsNotRoot($page); - if ($next = $page->next) { - $page->insertAfter($next); - } - $this->pages->save($page); - } - - public function remove($id): void - { - $page = $this->pages->get($id); - $this->assertIsNotRoot($page); - $this->pages->remove($page); - } - - private function assertIsNotRoot(Page $page): void - { - if ($page->isRoot()) { - throw new \DomainException('Unable to manage the root page.'); - } - } -} \ No newline at end of file diff --git a/core/widgets/menu/MenuWidget.php b/core/widgets/menu/MenuWidget.php new file mode 100644 index 0000000..7a56d05 --- /dev/null +++ b/core/widgets/menu/MenuWidget.php @@ -0,0 +1,22 @@ +menu_id); + return $this->render('menu', [ + 'menu' => $menu, + ]); + } +} \ No newline at end of file diff --git a/core/widgets/menu/views/menu.php b/core/widgets/menu/views/menu.php new file mode 100644 index 0000000..f4824cd --- /dev/null +++ b/core/widgets/menu/views/menu.php @@ -0,0 +1,30 @@ + + + \ No newline at end of file diff --git a/frontend/controllers/PageController.php b/frontend/controllers/PageController.php deleted file mode 100644 index 59e8d23..0000000 --- a/frontend/controllers/PageController.php +++ /dev/null @@ -1,57 +0,0 @@ -pages = $pages; - } - - public function behaviors(): array - { - return [ - 'access' => [ - 'class' => AccessControl::className(), - 'rules' => [ - [ - 'actions' => ['view'], - 'allow' => true, - 'roles' => ['Pages'], - ], - [ // all the action are accessible to admin - 'allow' => true, - 'roles' => ['admin'], - ], - ], - ], - ]; - } - - /** - * @param $id - * @return mixed - * @throws NotFoundHttpException - * @internal param string $slug - */ - public function actionView($id) - { - if (!$page = $this->pages->find($id)) { - throw new NotFoundHttpException('The requested page does not exist.'); - } - - return $this->render('view', [ - 'page' => $page, - ]); - } -} diff --git a/frontend/views/page/view.php b/frontend/views/page/view.php deleted file mode 100644 index bf1aa14..0000000 --- a/frontend/views/page/view.php +++ /dev/null @@ -1,32 +0,0 @@ -title = $page->getSeoTitle(); - -$this->registerMetaTag(['name' => 'description', 'content' => $page->meta->description]); -$this->registerMetaTag(['name' => 'keywords', 'content' => $page->meta->keywords]); - -foreach ($page->parents as $parent) { - if (!$parent->isRoot()) { - $this->params['breadcrumbs'][] = ['label' => $parent->title, 'url' => ['view', 'id' => $parent->id]]; - } -} -$this->params['breadcrumbs'][] = $page->title; -?> -
- -

title) ?>

- - formatter->asHtml($page->content, [ - 'Attr.AllowedRel' => array('nofollow'), - 'HTML.SafeObject' => true, - 'Output.FlashCompat' => true, - 'HTML.SafeIframe' => true, - 'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%', - ]) ?> - -
diff --git a/frontend/web/themes/start/layouts/main.php b/frontend/web/themes/start/layouts/main.php index f55d798..5bbf7de 100644 --- a/frontend/web/themes/start/layouts/main.php +++ b/frontend/web/themes/start/layouts/main.php @@ -32,11 +32,20 @@ rmrevin\yii\fontawesome\cdn\AssetBundle::register($this); + + + + +
diff --git a/frontend/web/themes/start/modules/pages/views/layouts/page.php b/frontend/web/themes/start/modules/pages/views/layouts/page.php new file mode 100644 index 0000000..0b4d900 --- /dev/null +++ b/frontend/web/themes/start/modules/pages/views/layouts/page.php @@ -0,0 +1,28 @@ +beginContent('@frontend/web/themes/start/layouts/main.php') ?> + + +
+ + 'ul', + 'itemTemplate' => '' . "\n", + 'activeItemTemplate' => '' . "\n", + 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [], + ]) ?> + +
+ + +
+ + + +
+ +
+ + +
+ +endContent() ?> + diff --git a/frontend/web/themes/start/modules/pages/views/page/view.php b/frontend/web/themes/start/modules/pages/views/page/view.php new file mode 100644 index 0000000..d46e86e --- /dev/null +++ b/frontend/web/themes/start/modules/pages/views/page/view.php @@ -0,0 +1,32 @@ +title = $page->getSeoTitle(); + +$this->registerMetaTag(['name' => 'description', 'content' => $page->meta->description]); +$this->registerMetaTag(['name' => 'keywords', 'content' => $page->meta->keywords]); + +foreach ($page->parents as $parent) { + if (!$parent->isRoot()) { + $this->params['breadcrumbs'][] = ['label' => $parent->title, 'url' => ['view', 'id' => $parent->id]]; + } +} +$this->params['breadcrumbs'][] = $page->title; +?> +
+ +

title) ?>

+ + formatter->asHtml($page->content, [ + 'Attr.AllowedRel' => array('nofollow'), + 'HTML.SafeObject' => true, + 'Output.FlashCompat' => true, + 'HTML.SafeIframe' => true, + 'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%', + ]) ?> + +