Сейчас мы с вами реализуем личный кабинет покупателя. Согласитесь, что это очень полезная фишка для реализации систем лояльности. В данном курсе мы, правда, ограничимся только профилем пользователя и историей его заказов.
В данном уроке нам понадобится пара платных компонентов из репозитория modstore.pro:
Создадим с вами группу пользователей Users, для этого перейдем в Контроль доступа->Новая группа ресурсов:

Кроме того, я поставил галочку на опции “Создать параллельную группу ресурсов”, с помощью которой мы с вами будем скрывать от анонимных пользователей страницы личного кабинета. Теперь, чтобы настроить нашу группу пользователей, нам необходимо кликнуть по ней правой кнопкой мыши и нажать на “Редактирование”. Нас интересует вкладка “Права доступа”. На вкладке “Доступ к контекстам” у контекста web необходимо выставить политику доступа “Load, List and View”:

Аналогично действуем с группой ресурсов “Users” на вкладке “Доступ к группам ресурсов” и после не забываем нажать “Сохранить”:

Так как MODx по умолчанию выставляет некорректные права доступа для групп пользователей, нам необходимо отредактировать группу пользователей “аноним”. Нас интересует вкладка “Доступ к группам ресурсов”, где нужно выставить группе ресурсов “users” политику доступа “Load Only”. Не забудьте нажать кнопку “Сохранить”.

Мы с вами настроили наши права, теперь нам необходимо создать страницы авторизации и личного кабинета. Я создал шаблон для страницы авторизации и выглядит он следующим образом:
{extends 'file:templates/index.tpl'}
{block 'content'}
{include 'file:chunks/breadcrumbs.tpl'}
<!-- CONTENT -->
<section class="def-section content">
<div class="container">
<h1>{$_modx->resource.longtitle ?: $_modx->resource.pagetitle}</h1>
{$_modx->resource.content}
{$_modx->runSnippet(“!officeAuth”,[
'groups' => 'Users',
'loginResourceId' => '23',
'HybridAuth' => '0'
])}
</div>
</section>
<!-- / CONTENT -->
{/block}
Так как я адаптировал под себя стандартный чанк Office, то я не буду указывать в парметрах чанки. Параметр loginResourceId отвечает за переадресацию после успешной авторизации. У меня это страница со списком заказов:

Если все настроили корректно, то у вас выведется форма авторизации и регистрации, которые вы можете проверить. А мы тем временем перейдем с вами к нашему личному кабинету. У всех страниц я оставил шаблон текстовой страницы. Предлагаю вам реализовать страницу редактирования профиля:

Я снял галочки с опций “Доступен для поиска” и “Использовать HTML-редактор” (это же необходимо сделать со страницей истории заказов) и разместил поле “Содержимое ресурса” вызов сниппета officeProfile:
{$_modx->runSnippet("!officeProfile", [
"tplProfile" => "@FILE chunks/office_profile.tpl"
])}
Чанк office_profile.tpl (его вид может быть лучше, можете сами настроить его с помощью Bootstrap 4):
<form action="" method="post" class="form-horizontal well" id="office-profile-form" enctype="multipart/form-data">
<div class="header">
<small>{'office_profile_header' | lexicon}</small>
</div>
<div class="form-group avatar">
{$_modx->runSnippet("!uaAvatar")}
</div>
<div class="form-group">
<label class="col-sm-2 control-label">{'office_profile_username' | lexicon}<sup class="red">*</sup></label>
<div class="col-sm-10">
<input type="text" name="username" value="{$username}" placeholder="{'office_profile_username' | lexicon}"
class="form-control"/>
<p class="help-block message">{$error_username}</p>
<p class="help-block desc">{'office_profile_username_desc' | lexicon}</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">{'office_profile_fullname' | lexicon}<sup class="red">*</sup></label>
<div class="col-sm-10">
<input type="text" name="fullname" value="{$fullname}" placeholder="{'office_profile_fullname' | lexicon}"
class="form-control"/>
<p class="help-block message">{$error_fullname}</p>
<p class="help-block desc">{'office_profile_fullname_desc' | lexicon}</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">{'office_profile_email' | lexicon}<sup class="red">*</sup></label>
<div class="col-sm-10">
<input type="text" name="email" value="{$email}" placeholder="{'office_profile_email' | lexicon}"
class="form-control"/>
<p class="help-block message">{$error_email}</p>
<p class="help-block desc">{'office_profile_email_desc' | lexicon}</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">
{'office_profile_phone' | lexicon}{if $_modx->config.office_auth_mode == 'phone'} <span class="red">*</span>{/if}
</label>
<div class="col-md-10">
<input type="text" name="mobilephone" placeholder="" value="{$mobilephone}" class="form-control"/>
<p class="help-block message">{$error_mobilephone}</p>
<p class="help-block desc">{'office_profile_phone_desc' | lexicon}</p>
</div>
</div>
<div class="form-group hidden">
<label class="col-sm-2 control-label">{'office_auth_register_phone_code' | lexicon}</label>
<div class="col-md-10">
<input type="text" name="phone_code" value="" class="form-control"/>
<p class="help-block message">{$error_phone_code}</p>
<p class="help-block desc">{'office_profile_phone_code_desc' | lexicon}</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">{'office_profile_password' | lexicon}</label>
<div class="col-sm-10">
<input type="password" name="specifiedpassword" value="" placeholder="********" class="form-control"/>
<p class="help-block message">{$error_specifiedpassword}</p>
<p class="help-block desc">{'office_profile_specifiedpassword_desc' | lexicon}</p>
<input type="password" name="confirmpassword" value="" placeholder="********" class="form-control"/>
<p class="help-block message">{$error_confirmpassword}</p>
<p class="help-block desc">{'office_profile_confirmpassword_desc' | lexicon}</p>
</div>
</div>
{if $providers?}
<div class="form-group">
<label class="col-sm-2 control-label">{'ha.providers_available' | lexicon}</label>
<div class="col-sm-10">
{$providers}
</div>
</div>
{/if}
<hr/>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">{'office_profile_save' | lexicon}</button>
<a class="btn btn-danger" href="{$_modx->resource.id | url : [] : ['action' => 'auth/logout']}">{'office_profile_logout' | lexicon}</a>
</div>
</div>
</form>
Со страницей истории заказов нам достаточно разместить следующий вызов сниппета Office в поле “Содержимое ресурса”:
{$_modx->runSnippet("!Office", [
"action" => "miniShop2"
])}
Сейчас перейдем в “Содержимое”->”Группы ресурсов” и перетащим созданные нами страницы в группу ресурсов “Users”:

Для того, чтобюы нам настроить 403 страницу, необходимо зайти в системные настройки и для настройки “unauthorized_page” указать ID страницы с формой авторизации:

Отлично! Теперь выведем меню для авторизованных пользователей в чанке header:
{if $_modx->user.id > 0}
<div class="dropdown">
<a href="{44 | url}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{if $_modx->user.id | user : 'photo'}
<img src="{$_modx->getPlaceholder('+nophoto') | phpthumbon : 'w=20&h=20&zc=1&q=99'}" alt="{$_modx->user.id | user : 'username' | htmlent}" />
{else}
<img src="{$_modx->user.id | user : 'photo' | phpthumbon : 'w=20&h=20&zc=1&q=99'}" alt="{$_modx->user.id | user : 'username' | htmlent}">
{/if}
{$_modx->user.id | user : 'username'}
<i class="fa fa-angle-down"></i>
</a>
{$_modx->runSnippet('pdoMenu', [
'parents' => '21',
'limit' => 0,
'outerClass' => 'dropdown-menu',
'tplOuter' => '@INLINE <ul[[+classes]]>[[+wrapper]]<li><a href="{24 | url : [\'scheme\' => \'full\'] : [\'action\' => \'auth/logout\']}">Выйти</a></li></ul>'
])}
</div>
{else}
<a href="{24 | url}">
Вход/Регистрация
</a>
{/if}
Вот и реализован наш личный кабинет покупателя, который в дальнейшем мы сможем расширить.
{44 | url}подскажите пожалуйста что за ссылка?