Личный кабинет пользователя. Поиск компонента
Всем добрый день.
Столкнулся с необходимостью соединить пользователей в системе с их страничками на сайте.
Т.е. есть 10 пользователей, а на сайте в открытом доступе есть 10 страниц с информацией об этих пользователях: в конкретной задаче это 10 профилей психологов.
Мне нужно сделать так, чтобы каждый из психологов имел доступ к своей страничке и мог управлять на ней разрешенными для изменения полями.
Как сделать это с нуля я представляю, но может быть есть какой-то готовый компонент? Который уже способен новому пользователя присвоить конкретную страницу в его управление? Через права пользователей в админке не вариант, так как психологов около 300 человек — под каждого создавать группу прав такое себе решение.
Столкнулся с необходимостью соединить пользователей в системе с их страничками на сайте.
Т.е. есть 10 пользователей, а на сайте в открытом доступе есть 10 страниц с информацией об этих пользователях: в конкретной задаче это 10 профилей психологов.
Мне нужно сделать так, чтобы каждый из психологов имел доступ к своей страничке и мог управлять на ней разрешенными для изменения полями.
Как сделать это с нуля я представляю, но может быть есть какой-то готовый компонент? Который уже способен новому пользователя присвоить конкретную страницу в его управление? Через права пользователей в админке не вариант, так как психологов около 300 человек — под каждого создавать группу прав такое себе решение.
Комментарии: 4
Если ты будешь создавать ресурс при регистрации, то ставь ему в createdby id нового пользователя. А потом в ЛК выводи форму с данными ресурса, который найдёшь по createdby. В общем, если использовать SendIt дело одной формы (изменения данных ресурса), и одного плагина (создания ресурса после регистрации) и одного сниппета (сохранения данных ресурса). 2-3 часа работы.
В целом да, план примерно такой, когда какой-то элемент у созданного пользователя, будет соотноситься с имеющимся ресурсом (просто сначала сделали ресурсы, а потом спустя пару лет решили делать кабинеты). Спасибо за наводку на компонент, изучу.
В итоге сделал, все работает корректно. Но пошел по пути написания сниппета и небольшого «одноразового» сниппета для регистрации пользователей. Оставлю тут, может кому пригодится.
Конечно, код далек от идеального, я так и не добрался до php в чистом виде, только наверстываю. Может кто-то укажет на явные косяки и чрезмерность (стартовый каркас писал с помощью ChatGPT, потом уже все в рабочий вид превращал).
1. Вначале отсортировал в JSON файл всех сотрудников, у которых есть почты (было решено опираться на соответствие почты в карточках и у пользователя).
2. Вывел JSON с параметрами email и name (на самом деле больше параметров, но нужны для конкретной цели только эти два).
3. Создал группу для пользователей с нужными мне настройками доступа (работа ВНЕ админки).
4. Написал сниппет:
Конечно, код далек от идеального, я так и не добрался до php в чистом виде, только наверстываю. Может кто-то укажет на явные косяки и чрезмерность (стартовый каркас писал с помощью ChatGPT, потом уже все в рабочий вид превращал).
1. Вначале отсортировал в JSON файл всех сотрудников, у которых есть почты (было решено опираться на соответствие почты в карточках и у пользователя).
2. Вывел JSON с параметрами email и name (на самом деле больше параметров, но нужны для конкретной цели только эти два).
3. Создал группу для пользователей с нужными мне настройками доступа (работа ВНЕ админки).
4. Написал сниппет:
<?php
$usersJsonPath = 'https://migip-reg.ru/tehnicheskie-stranicy/fullstuff-list.json'; // Укажите путь к вашему JSON файлу
// Функция для создания случайного пароля
function generateRandomPassword($length = 8) {
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$password = '';
for ($i = 0; $i < $length; $i++) {
$password .= $characters[rand(0, strlen($characters) - 1)];
}
return $password;
}
// Получение данных из JSON файла
$jsonData = file_get_contents($usersJsonPath);
if ($jsonData === false) {
// Выводим сообщение об ошибке, если не удалось получить данные из JSON
echo 'Не удалось получить данные из JSON файла';
} else {
// Данные из JSON получены успешно, декодируем их
$usersData = json_decode($jsonData, true);
// Проверяем, произошла ли ошибка при декодировании JSON
if (json_last_error() !== JSON_ERROR_NONE) {
echo 'Ошибка при декодировании JSON: ' . json_last_error_msg();
} else {
// Данные из JSON успешно декодированы, выводим их для отладки
echo '<pre>';
print_r($usersData);
echo '</pre>';
// Проходим по каждому пользователю и создаем его в MODX
foreach ($usersData as $userData) {
$email = strtolower($userData['email']);
$fullName = $userData['name'];
// Проверка на существование пользователя с таким email
if (!$modx->getObject('modUser', array('email' => $email))) {
// Пользователя с таким email не существует, создаем нового
$user = $modx->newObject('modUser');
$user->set('username', $email); // Используем email в качестве имени пользователя
$user->set('email', $email);
$user->set('password', generateRandomPassword()); // Генерируем случайный пароль
$user->set('active', 1); // Устанавливаем пользователя активным
// Создаем профиль пользователя
$profile = $modx->newObject('modUserProfile');
$profile->set('internalKey', $user->get('id')); // Устанавливаем внутренний ключ профиля равным ID пользователя
$profile->set('fullname', $fullName); // Устанавливаем полное имя
$profile->set('email', $email); // Устанавливаем адрес электронной почты
// Присоединяем профиль к пользователю
$user->addOne($profile);
// Сохраняем пользователя
$user->save();
// Добавляем пользователя в группу "Stuff"
$user->joinGroup('Stuff');
$user->save();
}
}
}
}
Таким образом были созданы все пользователи с именем пользователя и почтой = почты в карточках специалистов, и полным именем из карточек специалистов.
5. Настроил компонент Login.
6. И в раздел «Редактирование данных» у уже авторизованного пользователя вывел следующий сниппет:
6. И в раздел «Редактирование данных» у уже авторизованного пользователя вывел следующий сниппет:
<?php
$modx->initialize('web');
// Проверяем, авторизован ли пользователь
if ($modx->user->isAuthenticated('web')) {
// Получаем имя пользователя (username) из текущей сессии
$FUusername = $modx->user->get('username');
// ID категории, где находятся ресурсы
$FUcategoryId = 162;
// Получаем все ресурсы из категории с ID 162
$resources = $modx->getCollection('modResource', array('parent' => $FUcategoryId));
// Переменная для хранения найденного ресурса
$foundResourceId = null;
// Проходим по каждому ресурсу
foreach ($resources as $resource) {
// Получаем значение TV-поля "mentor_email" для текущего ресурса
$mentorEmail = strtolower($resource->getTVValue('mentor_email'));
// Сравниваем значение TV-поля "mentor_email" с именем пользователя
if ($mentorEmail == $FUusername) {
// Если значение TV-поля "mentor_email" совпадает с именем пользователя, сохраняем ID этого ресурса
$foundResourceId = $resource->get('id');
break; // Прекращаем цикл, так как уже нашли нужный ресурс
}
}
// Проверяем, был ли найден ресурс с TV-полем "mentor_email" равным имени пользователя
if ($foundResourceId) {
$_SESSION['current_resource_id'] = $foundResourceId;
// Если форма была отправлена
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Получаем значение TV-поля "mentor_test" из отправленной формы
$mentorTestValue = $_POST['mentor_test'] ?? '';
$workingBusyValue = $_POST['workingBusy'] ?? '';
$workingPersonFormatValue = $_POST['workingPersonFormat'] ?? '';
// Получаем объект ресурса
$resource = $modx->getObject('modResource', $foundResourceId);
// Проверяем, был ли найден ресурс
if ($resource) {
// Сохраняем значение TV-поля "mentor_test"
$resource->setTVValue('mentor_test', $mentorTestValue);
$resource->setTVValue('workingBusy', $workingBusyValue);
$resource->setTVValue('workingPersonFormat', $workingPersonFormatValue);
$resource->save();
// Перенаправляем пользователя на текущую страницу для предотвращения повторной отправки формы
header('Location: ' . $_SERVER['REQUEST_URI']);
exit();
}
}
// Получаем данные ресурса
$resource = $modx->getObject('modResource', $foundResourceId);
// Проверяем, был ли найден ресурс
if ($resource) {
// Получаем значение TV-поля "mentor_test"
$mentorTest = $resource->getTVValue('mentor_test');
$workingBusy = $resource->getTVValue('workingBusy');
$workingPersonFormat = $resource->getTVValue('workingPersonFormat');
// Выводим значения переменных для отладки
echo '<pre>';
echo 'mentor_test: ' . $mentorTest . PHP_EOL;
echo 'workingBusy: ' . $workingBusy . PHP_EOL;
echo 'workingPersonFormat: ' . $workingPersonFormat . PHP_EOL;
echo '</pre>';
// Передаем данные в чанк "edit_profile_chunk" для заполнения формы
$output = $modx->getChunk('edit_profile_chunk', array(
'mentor_test' => $mentorTest,
'workingBusy' => $workingBusy,
'workingPersonFormat' => $workingPersonFormat,
// Другие данные для заполнения формы
));
} else {
// Если ресурс не найден, выводим сообщение об ошибке
$output = 'Ресурс не найден';
}
} else {
// Если не найден ресурс с TV-полем "mentor_email" равным имени пользователя
$output = 'Не найдено ресурсов с TV-полем ' . $FUusername .', равным имени пользователя';
}
} else {
// Если пользователь не авторизован, возвращаем сообщение об ошибке или что-то другое
$output = 'Пользователь не авторизован';
}
return $output;
7. Ну и чанк, в который передаются данные и из которого формируется сама страница:<form action="[[~[[*id]]]]" method="post" class="form-edit" id="editProfileForm">
<div class="form-edit__input">
<label for="mentorTest">Тестовое поле:</label>
<span class="form-edit__note">Немного слов.</span>
<input type="text" id="mentorTest" name="mentor_test" value="[[+mentor_test]]">
</div>
<div class="form-edit__select">
<label for="workingBus">Есть свободные слоты:</label>
<span class="form-edit__note">Поставить значение «нет» в том случае, когда у вас нет свободных мест для работы с студентами.</span>
<select id="workingBusy" name="workingBusy">
<option value="0" [[!If? &subject=`[[+workingBusy]]` &operator=`=` &operand=`0` &then=`selected`]]>Да</option>
<option value="1" [[!If? &subject=`[[+workingBusy]]` &operator=`=` &operand=`1` &then=`selected`]]>Нет</option>
</select>
</div>
<div class="form-edit__select">
<label for="workingBus">Доступный формат приема:</label>
<span class="form-edit__note">Внимание! Указывать формат, который вам разрешен для проведения сертификационных сессий.</span>
<select id="workingPersonFormat" name="workingPersonFormat">
<option value="0" [[!If? &subject=`[[+workingPersonFormat]]` &operator=`=` &operand=`0` &then=`selected`]]>Очно</option>
<option value="1" [[!If? &subject=`[[+workingPersonFormat]]` &operator=`=` &operand=`1` &then=`selected`]]>Онлайн</option>
<option value="2" [[!If? &subject=`[[+workingPersonFormat]]` &operator=`=` &operand=`2` &then=`selected`]]>Оба варианта</option>
</select>
</div>
<!-- Другие поля для редактирования -->
<!-- Кнопка для отправки формы -->
<button type="submit" class="btn btn_green btn_forSave">Сохранить</button>
</form>
<script>
// JavaScript для предотвращения множественных отправок формы
document.getElementById('editProfileForm').addEventListener('submit', function(event) {
// Проверяем, была ли форма отправлена ранее
if (this.getAttribute('data-submitted') === 'true') {
// Если форма уже была отправлена, предотвращаем повторную отправку
event.preventDefault();
return;
}
// Отмечаем форму как отправленную
this.setAttribute('data-submitted', 'true');
// Отключаем кнопку "Сохранить"
document.getElementById('saveButton').disabled = true;
// Отправляем форму асинхронным запросом
var formData = new FormData(this);
var xhr = new XMLHttpRequest();
xhr.open('POST', this.action);
xhr.onload = function() {
if (xhr.status === 200) {
// Если запрос выполнен успешно, перезагружаем страницу
location.reload();
} else {
// Если произошла ошибка, разрешаем повторную отправку формы
document.getElementById('editProfileForm').removeAttribute('data-submitted');
document.getElementById('saveButton').disabled = false;
}
};
xhr.send(formData);
});
</script>
Собственно все. Подозреваю, что с выводом TV полей уже для редактирования можно было бы как-то лучше разобраться, но пока такой формат работает и нагрузки лишней нет. Есть проблемы с мультиполями, с ними еще работаю.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.