Веб-разработка. Доработка существующего продукта. Сделать учебный проект по т.з. указанному ниже. Срок 1.5 недели. Техническое задание Общая концепция Сервис предоставляет пользователям возможность публиковать сообщения в своём блоге. Главная особенность сервиса — это формат постов. При публикации пользователь выбирает один из пяти доступных форматов записи. Такой формат публикации является чем-то средним между микроблогингом и полноценными, большими блог-постами. В зависимости от выбранного формата, запись пользователя оформляется особенным образом. Основные сценарии использования сайта: Публикация и репост записей в своём блоге; Комментирование чужих записей; Подписка на пользователей; Просмотр своей ленты; Поиск записей по тегам, тексту либо просмотр популярных постов; Переписка с другими пользователями. Техническое описание Для разработки сайта предлагается уже готовая вёрстка, от программиста требуется лишь написать бэкенд сайта, т. е. сделать сайт динамическим, реализовать возможности по добавлению, просмотру постов. Разработка бэкенда должна вестись на языке программирования PHP 8 и выше, база данных — MySQL 8 и выше. Не предполагается использование языка JavaScript для клиентского программирования. При разработке схемы базы данных необходимо принимать во внимание какие сущности необходимо хранить, их поля и возможные связи друг с другом. Технические требования для работы с БД необходимо использовать исключительно ORM-подход (Eloquent) для валидации формы применяются возможности Form Request Validation встроенные в фреймворк аутентификация пользователя выполняется средствами пакета Laravel Sanctum для взаимодействия со сторонними API используйте пакет HTTP Client Процессы Регистрация нового аккаунта Выполняется после заполнения формы на странице «Регистрация аккаунта». Последовательность действий: Проверить, что отправлена форма. Убедиться, что заполнены все обязательные поля. Проверить, что указанный email уже не используется другим пользователем. Проверить совпадение пароля и его повтора. Если есть ошибки заполнения формы, то сохранить их в отдельном массиве. Если ошибок нет, то сохранить данные формы в таблице пользователей. Выбранный файл аватара сохранить в отдельной, публичной папке и добавить ссылку на аватар в таблицу пользователей. Если были допущены ошибки (не заполнены все поля, email занят и т. д.), то не сохранять данные, а показать ошибки в форме под соответствующими полями. Также ошибки валидации показываются списком в специальном блоке справа от формы. Для валидации формы используются возможности Form Request Validation. Если данные были сохранены успешно, то переадресовать пользователя на страницу входа. Примечания Необходимо проверять, что значение из поля «email» действительно является валидным email-адресом. Для этих целей следует использовать встроенное правило email Для хранения пароля в БД, его предварительно нужно захэшировать средствами фреймворка Также нужно проверять формат загруженного файла в поле «Аватар», это обязательно должно быть изображение. Используйте правило image для такой проверки Публикация поста Выполняется после заполнения формы на странице «Публикация поста». Все поля формы обязательны к заполнению. Последовательность действий: Проверить, что отправлена форма. Убедиться, что заполнены все поля. Выполнить все проверки. Если есть ошибки заполнения формы, то сохранить их в отдельном массиве. Если ошибок нет, то сохранить новый пост в таблице постов. Отправить уведомления подписчикам пользователя о новом посте (процесс «Отправка уведомлений»). При успешном сохранении формы переадресовывать пользователя на страницу просмотра поста. В зависимости от выбранного типа поста для формы будут применяться различные правила валидации. Также некоторые типы требуют дополнительных действий, помимо сохранения данных в БД. Ниже даны все необходимые пояснения. Список проверок Валидация поля «Теги» В этом поле пользователь вводит теги, к которым относится публикация. Теги разделяются пробелом. Выполняя валидацию, нужно убедиться, что в поле одно или больше слов, а сами слова разделены пробелом. Каждый тег состоит только из одного слова. Привязка тегов к публикации Информацию из поля «Теги» надо разделить на отдельные теги-слова. Эти теги сохраняются в отдельной таблице и ссылаются на запись из таблицы постов (подробности смотри в разделе «Сущности»). Валидация записи типа «Картинка» При заполнении формы пользователю обязательно надо выбрать файл изображения со своего компьютера, либо указать прямую ссылку на изображение, размещенное в интернете. Следовательно, надо написать правило валидации, которое проверяет, что минимум одно из полей заполнено. Если заполнены оба поля, то игнорировать содержимое поля «Ссылка из интернета». Валидация поля «Выбор файла» Обязательно проверять тип загруженного файла. Формат загруженного файла должен быть изображением одного из следующих типов: png, jpeg, gif. Выбранный файл сохранить в отдельной, публичной папке и добавить ссылку на изображение в таблицу постов вместе с остальной информацией. Валидация поля «Ссылка из интернета» Сперва следует проверить правильность формата. Значение поля должно быть корректным URL-адресом. Используйте встроенное правило валидации URL. Затем по указанной ссылке необходимо скачать файл изображения, сохранить его в публичной папке и добавить ссылку на изображение в таблицу постов вместе с остальной информацией. Получить содержимое удалённого файла можно, например, встроенной функцией file_get_contents. Если функция вернула false или пустую строку, значит файл загрузить не получилось. Такая ситуация должна являться ошибкой валидации поля. Валидация записи типа «Видео»: При заполнении формы пользователь обязательно указывает ссылку на видео, размещённое на сайте YouTube. Сперва следует проверить правильность формата. Значение поля должно быть корректным URL-адресом. Используйте встроенное правило url Валидация записи типа «Ссылка» Значение поля должно быть корректным URL-адресом. Используйте встроенное правило url Для указанной ссылки необходимо сохранить её превью, используя компонент HTTP Client и сервис thumbnail.ws Вход на сайт Выполняется после заполнения формы на странице «Главная для анонимных пользователей». Последовательность действий: Проверить, что отправлена форма. Убедиться, что заполнены все поля. Если есть ошибки заполнения формы, то сохранить их в отдельном массиве. Найти в БД пользователя с переданным email. Проверить, что переданный в форме пароль совпадает с сохраненным. Если пользователь найден и пароли совпадают, то открыть новую сессию, в которую записать идентификатор пользователя. После успешного входа пользователь попадает на главную страницу. Репост Функция репоста позволяет скопировать и опубликовать пост другого пользователя. Процесс вызывается после клика на иконку «Репост», которая находится под содержимым поста на странице пользователя. Необходимо из параметра запроса получить ID оригинальной записи. Выполнить проверку по таблице постов, что существует запись с таким ID. Если запись существует, то скопировать все значения из этой записи в новую, внеся следующие изменения: Поменять ID автора на текущего пользователя; Поменять дату/время публикации на текущую; Установить признак «Репост» в «истина»; Заполнить поле «Автор оригинальной записи» в ID пользователя оригинала. Выполнить переадресацию на страницу профиля текущего пользователя. Подписка на пользователя Выполняется со страницы профиля пользователя. Последовательность действий: Из параметра запроса нужно извлечь ID пользователя, на которого выполняется подписка. По полученному ID убедиться, что в таблице пользователей существует такая запись. Добавить в таблицу подписок пользователей соответствующую связь (смотрите раздел «Сущности»). Отправить этому пользователю уведомление о новом подписчике (смотрите описание процесса «Отправка уведомлений»). Выполнить переадресацию обратно на профиль пользователя. Отписка от пользователя Выполняется со страницы профиля пользователя. Последовательность действий: Из параметра запроса надо извлечь ID пользователя, по которому выполняется отписка. По полученному ID убедиться, что в таблице подписок пользователей есть соответствующая связь (смотри раздел «Сущности»). Удалить запись с этой связью. Выполнить переадресацию обратно на профиль пользователя. Лайк публикации Выполняется с любой страницы, где есть блоки для показа публикаций. Последовательность действий: Из параметра запроса нужно извлечь ID поста; По этому ID убедиться, что в таблице с постами есть такой пост; Если такой пост существует, то добавить новую связь «Пользователь-лайки» через соответствующую таблицу (смотри раздел «Сущности»); Выполнить переадресацию обратно на предыдущую страницу (использовать заголовок запроса Referer для получения адреса этой страницы). Отправка уведомлений Пользователи сайта получают email-уведомления при наступлении двух событий: новый подписчик и публикация нового поста от одного из авторов, на которых подписан пользователь. Уведомление о новом подписчике После выполнения процесса «Подписка на пользователя» юзер, на которого подписались, получает об этом уведомление. Уведомление — это сообщение электронной почты, составленное по следующим требованиям: Тема письма: «У вас новый подписчик»; Содержимое письма: «Здравствуйте, %логин адресата%. На вас подписался новый пользователь %логин пользователя, оформившего подписку%. Вот ссылка на его профиль: %ссылка на профиль этого пользователя%». Уведомление о публикации нового поста После выполнения процесса «Публикация поста» все пользователи, подписанные на автора публикации получают об этом уведомление. Уведомление — это сообщение электронной почты, составленное по следующим требованиям: Тема письма: «Новая публикация от пользователя %логин автора поста%»; Содержимое письма: «Здравствуйте, %имя адресата%. Пользователь %логин автора поста% только что опубликовал новую запись „%заголовок поста%“. Посмотрите её на странице пользователя: %ссылка на профиль автора%». Необходимо вначале сформировать список адресатов-получателей этого уведомления. Для этого нужно найти пользователей, подписанных на автора новой публикации. Затем для каждого найденного пользователя следует отдельно сформировать и отправить уведомление. Для отправки email используется встроенный компонент Mail Следует использовать отложенную отправку сообщений. Для этого используйте технику Delayed Dispatching Поиск Выполняется после отправки формы поиска с любой страницы. Последовательность действий: Проверить, что в URL сценария есть параметр запроса, зарезервивованный под содержимое поискового запроса; Получить текст из этого параметра и убрать пробелы функцией trim; Проверить, что получившаяся строка не пустая; Выполнить полнотекстовый поиск (операторы «MATCH... AGAINST») в таблице постов по полям «заголовок» и «содержимое»; Показать результаты поиска на соответствующей странице. Поиск по тегам Отдельно надо рассмотреть процесс поиска по тегам. Он выполняется при клике по ссылке-тегу, расположенным в карточке любого поста. Чтобы отличить поиск по тегу от поиска по прозвольному тексту, надо получить первый символ поискового запроса (используйте встроенную функцию substr). Если первый символ является решёткой — «#», то это означает поиск по тегу. Той же функцией substr извлечь имя тега без решётки. Затем задействуйте поиск по связи «Посты-теги», чтобы получить из таблицы постов записи, имеющие связь с этим тегом и покажите их на странице. Отправка личного сообщения Выполняется после отправки формы со страницы «Сообщения». Последовательность действий: Проверить, что отправлена форма; Убедиться, что заполнены все её поля; Выполнить все проверки; Если есть ошибки заполнения формы, то сохранить их в отдельном массиве; Если ошибок нет, то сохранить новое сообщение в таблице сообщений. При успешном сохранении формы переадресовывать пользователя на страницу «Сообщения». Список проверок Проверка адресата ID пользователя, которому адресуется сообщение, находится в специальном скрытом поле формы. Следует проверить, что пользователь с этим ID существует в таблице пользователей, а также не равен отправителю сообщения. Проверка текста сообщения Поле должно быть заполнено. Очистить содержимое от начальных и конечных пробелов встроенной функцией trim. Итоговое содержимое не должно быть пустой строкой. Добавление комментария Выполняется после заполнения формы комментария на странице просмотра поста. Последовательность действий: Проверить, что отправлена форма; Убедиться, что заполнены все её поля; Выполнить все проверки; Если нет ошибок валидации, то сохранить новое сообщение в таблице комментариев; Показать ошибку валидации формы, если таковая была. При успешном сохранении формы переадресовывать пользователя на страницу профиля пользователя — автора публикации, к которой добавлялся комментарий. Список проверок Проверка существования поста ID поста, к которому добавляется комментарий, находится в специальном скрытом поле формы. Следует проверить, что пост с этим ID существует в таблице постов. Проверка текста сообщения Поле должно быть заполнено. Очистить содержимое от начальных и конечных пробелов встроенной функцией trim. Длина итогового комментария не должна быть меньше четырех символов. Основные сущности Список всех сущностей Пользователь; Пост; Комментарий; Лайк; Подписка; Сообщение; Хештег; Тип контента. Пользователь Представляет зарегистрированного пользователя. Поля: дата регистрации: дата и время, когда этот пользователь завёл аккаунт; email; логин; пароль: хэшированный пароль пользователя; аватар: ссылка на загруженный аватар пользователя; Пост Состоит из заголовка и содержимого. Набор полей, которые будут заполнены, зависит от выбранного типа. Поля: дата создания: дата и время, когда этот пост был создан пользователем; заголовок: задаётся пользователем; текстовое содержимое: задаётся пользователем; автор цитаты: задаётся пользователем; изображение: ссылка на сохранённый файл изображения; видео: ссылка на видео с youtube; ссылка: ссылка на сайт, задаётся пользователем; число просмотров. Связи: автор: пользователь, создавший пост; тип контента: тип контента, к которому относится пост; хештеги: связь вида «многие-ко-многим» с сущностью «хештег». Комментарий Текстовый комментарий, оставленный к одному из постов. Поля: дата создания: дата и время создания комментария; содержимое: задается пользователем. Связи: автор: пользователь, создавший пост; пост: пост, к которому добавлен комментарий. Лайк Эта сущность состоит только из связей и не имеет собственных полей. Связи: пользователь: кто оставил этот лайк; пост: какой пост лайкнули. Подписка Эта сущность состоит только из связей и не имеет собственных полей. Сущность создается, когда пользователь подписывается на другого пользователя. Связи: автор: пользователь, который подписался; подписка: пользователь, на которого подписались. Сообщение Одно сообщение из внутренней переписки пользователей на сайте Поля: дата создания: дата и время, когда это сообщение написали; содержимое: задаётся пользователем. Связи: отправитель: пользователь, отправивший сообщение; получатель: пользователь, которому отправили сообщение. Хештег Один из используемых хештегов на сайте. Сущность состоит только из названия хештега. Тип контента Один из пяти предопределенных типов контента. Поля: название (Текст, Цитата, Картинка, Видео, Ссылка); имя класса для иконки (photo, video, text, quote, link); Роли пользователей Сайт могут использовать только зарегистрированные пользователи. Анонимный пользователь всегда видит только приветственную страницу, где предлагается завести аккаунт или войти на сайт.