Личный кабинет пользователя. Поиск компонента

Всем добрый день.
Столкнулся с необходимостью соединить пользователей в системе с их страничками на сайте.
Т.е. есть 10 пользователей, а на сайте в открытом доступе есть 10 страниц с информацией об этих пользователях: в конкретной задаче это 10 профилей психологов.
Мне нужно сделать так, чтобы каждый из психологов имел доступ к своей страничке и мог управлять на ней разрешенными для изменения полями.

Как сделать это с нуля я представляю, но может быть есть какой-то готовый компонент? Который уже способен новому пользователя присвоить конкретную страницу в его управление? Через права пользователей в админке не вариант, так как психологов около 300 человек — под каждого создавать группу прав такое себе решение.
Валерий
21 марта 2024, 12:52
modx.pro
1 501
0

Комментарии: 4

Артур Шевченко
21 марта 2024, 20:14
+1
Если ты будешь создавать ресурс при регистрации, то ставь ему в createdby id нового пользователя. А потом в ЛК выводи форму с данными ресурса, который найдёшь по createdby. В общем, если использовать SendIt дело одной формы (изменения данных ресурса), и одного плагина (создания ресурса после регистрации) и одного сниппета (сохранения данных ресурса). 2-3 часа работы.
    Валерий
    21 марта 2024, 21:18
    0
    В целом да, план примерно такой, когда какой-то элемент у созданного пользователя, будет соотноситься с имеющимся ресурсом (просто сначала сделали ресурсы, а потом спустя пару лет решили делать кабинеты). Спасибо за наводку на компонент, изучу.
      Валерий
      28 марта 2024, 22:31
      0
      В итоге сделал, все работает корректно. Но пошел по пути написания сниппета и небольшого «одноразового» сниппета для регистрации пользователей. Оставлю тут, может кому пригодится.
      Конечно, код далек от идеального, я так и не добрался до 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();
                  }
              }
          }
      }
      Таким образом были созданы все пользователи с именем пользователя и почтой = почты в карточках специалистов, и полным именем из карточек специалистов.
        Валерий
        28 марта 2024, 22:34
        0
        5. Настроил компонент Login.
        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 полей уже для редактирования можно было бы как-то лучше разобраться, но пока такой формат работает и нагрузки лишней нет. Есть проблемы с мультиполями, с ними еще работаю.
      Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
      4