app/ # Основная директория приложения
│── Console/ # Консольные команды
│ └── Mattermost/ # Команды для работы с Mattermost
│ ├── SyncChannelsCommand.php # Команда для синхронизации каналов (чатов)
│ ├── SyncCommandCommand.php # Команда для синхронизации команды
│ ├── SyncCommandsCommand.php # Команда для синхронизации команд
│ ├── SyncTeamsCommand.php # Команда для синхронизации пространств
│ ├── SyncUsersCommand.php # Команда для синхронизации пользователей Mattermost
│── Contracts/ # Контракты (интерфейсы)
│ └── Mattermost/ # Контракты для работы с Mattermost
│ ├── ActionContract.php # Контракт для работы с Mattermost Action Hook
│ ├── DialogServiceContract.php # Контракт для работы с Mattermost Dialog Hook
│ ├── CommandContract.php # Контракт для работы с вызовами команд Mattermost
│ ├── CommandServiceContract.php # Контракт для работы с командами (CRUD) Mattermost
│ ├── PostServiceContract.php # Контракт для работы с постами (сообщениями) Mattermost
│ ├── TeamServiceContract.php # Контракт для работы с пространствами Mattermost
│ ├── UserServiceContract.php # Контракт для работы с пользователями Mattermost
│── DTO/ # Data Transfer Objects (объекты передачи данных)
│ └── Jenkins/ # DTO для работы с запросами Jenkins Webhook
│── Enums/ # Классы-перечисления
│ └── Jenkins/ # Перечисления для работы с Jenkins Webhook
│── Exceptions/ # Исключения
│ └── Mattermost/ # Исключения для работы с Mattermost
│ ├── ServiceException.php # Базовое исключение для работы с Mattermost
│── Filament/ # Ресурсы админки Filament
│── Handlers/ # Обработчики событий
│ ├── Jenkins/ # Обработчики для работы с Jenkins Webhook
│ └── Mattermost/ # Обработчики для работы с Mattermost
│ ├── SyncChannelsHandler.php # Обработчик для синхронизации каналов (чатов)
│ ├── SyncCommandHandler.php # Обработчик для синхронизации команды
│ ├── SyncCommandsHandler.php # Обработчик для синхронизации команд
│ ├── SyncDataHandler.php # Обработчик для синхронизации всех сущностей Mattermost
│ ├── SyncTeamsHandler.php # Обработчик для синхронизации пространств Mattermost
│ ├── SyncUsersHandler.php # Обработчик для синхронизации пользователей Mattermost
│── Http/ # HTTP-слой приложения
│ ├── Controllers/ # Контроллеры
│ │ ├── Commands/ # Контроллеры для работы с командами
│ │ │ └── Mattermost/ # Контроллеры для Mattermost
│ │ │ ├── CommandController.php # Контроллер для работы с командами Mattermost
│ │ ├── Webhook/ # Контроллеры для работы с Webhook
│ │ │ ├── Jenkins/ # Контроллеры для работы с Jenkins Webhook
│ │ │ └── Mattermost/ # Контроллеры для работы с Mattermost Webhook
│ │ │ ├── ActionController.php # Контроллер для работы с Mattermost Action Hook
│── Livewire/ # Компоненты Livewire
│── Models/ # Модели Eloquent
│ └── Mattermost/ # Модели для работы с Mattermost
│ ├── Channel.php # Модель для работы с каналами (чатами)
│ ├── ChannelProject.php # Модель для связи каналов с проектами
│ ├── Command.php # Модель для работы с командами
│ ├── ProjectUser.php # Модель для связи пользователей с проектами
│ ├── Team.php # Модель для работы с пространствами
│ ├── User.php # Модель для работы с пользователями
│── Policies/ # Политики (доступ) для админки Filament
│── Providers/ # Сервис-провайдеры
│ └── Mattermost/ # Провайдеры для Mattermost
│ ├── ServiceProvider.php # Провайдер для работы с сервисами Mattermost
│── Services/ # Сервисный слой
│ └── Mattermost/ # Сервисы для работы с Mattermost
│ ├── ChannelService.php # Сервис для работы с каналами (чатами) Mattermost
│ ├── CommandService.php # Сервис для работы с командами Mattermost
│ ├── DialogService.php # Сервис для работы с диалогами (модальными окнами) Mattermost
│ ├── PostService.php # Сервис для работы с постами (сообщениями) Mattermost
│ ├── TeamService.php # Сервис для работы с пространствами Mattermost
│ ├── UserService.php # Сервис для работы с пользователями Mattermost
│── Traits/ # Трейты (модули переиспользуемого кода)
│ ├── Mattermost/ # Трейты для работы с Mattermost
│ │ ├── CallEndpointMethod.php # Трейт для вызова методов эндпоинтов Mattermost
│ ├── ConfigTrait.php # Трейт для работы с конфигурацией
│ ├── LocalizationTrait.php # Трейт для работы с локализацией
│ ├── ResponseTrait.php # Трейт для работы с HTTP-ответами
- Mattermost/Channel.php - таблица:
mattermost_channels, Модель для работы с каналами (чатами) - Mattermost/ChannelProject.php - таблица:
mattermost_channels_projects, Модель для связи каналов с проектами - Mattermost/Command.php - таблица:
mattermost_commands, Модель для работы с командами - Mattermost/ProjectUser.php - таблица:
mattermost_projects_users, Модель для связи пользователей с проектами - Mattermost/Team.php - таблица:
mattermost_teams, Модель для работы с пространствами - Mattermost/User.php - таблица:
mattermost_users, Модель для работы с пользователями
- Настройки: Лог действий, Пользователи, Роли
- Mattermost: Чаты (Channel), Команды (Command), Проекты (ChannelProject), Пространства (Team), Пользователи (User)
Конфигурация в файле config/mattermost.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Mattermost Server Name
|--------------------------------------------------------------------------
|
| Here you cam specify which server you wish to use as your
| default Mattermost server.
|
*/
'default' => env('MATTERMOST_SERVER', 'login'),
/*
|--------------------------------------------------------------------------
| Mattermost Servers
|--------------------------------------------------------------------------
|
| Here you can configure a list of different Mattermost servers
| to use within your application.
|
| You can authenticate in two ways: passing a Bearer Token or
| passing Username and Password. The allowed values for the "auth"
| option are: "default", "bearer".
|
*/
'servers' => [
// Подключение к Mattermost, используя следующие параметры
'login' => [
'auth' => env('MATTERMOST_AUTH', 'login'),
'host' => env('MATTERMOST_HOST', 'localhost'),
'login' => env('MATTERMOST_LOGIN', 'login'),
'password' => env('MATTERMOST_PASSWORD', 'password'),
'api' => env('MATTERMOST_API', '/api/v4'),
'timeout' => env('MATTERMOST_TIMEOUT', 5),
],
],
];Для работы с Mattermost используется драйвер MattermostDriver
composer require rocketfirm/mattermost-driverphp artisan vendor:publishВ контрактах заложены методы, которые используются для работы с Mattermost. Реализация контрактов находится в Services/Mattermost. Инициализация контрактов происходит в Providers/Mattermost/ServiceProvider.php
Кнопки в постах (ActionContract.php)
Выполнение действия кнопки в постах происходит через вебхук ActionController.php, который использует контракт ActionContract.php
/** @var \App\Http\Requests\Mattermost\ActionHookRequest $request */
$request = app()->make(\App\Http\Requests\Mattermost\ActionHookRequest::class);
/** @var \App\Contracts\Mattermost\ActionContract $contract */
$contract = app()->make(\App\Contracts\Mattermost\ActionContract::class);
$contract->do($request->getDto());Открытие личного чата с пользователями в Mattermost (ChannelServiceContract.php)
Метод direct возвращает новый/текущий чат с пользователями (senderId - отправитель, receiverId - получатель)
$senderId = 'senderId'; // ID пользователя в Mattermost
$receiverId = 'receiverId'; // ID пользователя в Mattermost
/** @var \App\Contracts\Mattermost\ChannelServiceContract $service */
$service = app()->make(\App\Contracts\Mattermost\ChannelServiceContract::class);
$channel = $service->direct($senderId, $receiverId);
$channel->id; // ID чатаВыполнение команды (CommandServiceContract.php)
Выполнение команды в чате происходит через вебхук CommandController.php, который использует контракт CommandContract.php
/** @var \App\Http\Requests\Mattermost\CommandRequest $request */
$request = app()->make(\App\Http\Requests\Mattermost\CommandRequest::class);
/** @var \App\Contracts\Mattermost\CommandContract $contract */
$contract = app()->make(\App\Contracts\Mattermost\CommandContract::class);
$contract->call($request->getDto());Управление командами (CommandServiceContract.php)
use Rocketfirm\MattermostDriver\Requests\Command\CreateRequest;
use Rocketfirm\MattermostDriver\Enums\Command\Method;
use Rocketfirm\MattermostDriver\Requests\Command\IndexRequest;
use Rocketfirm\MattermostDriver\Requests\Command\UpdateRequest;
/** @var \App\Contracts\Mattermost\CommandServiceContract $service */
$service = app()->make(\App\Contracts\Mattermost\CommandServiceContract::class);
// Создание команды
$command = $service->createCommand(new CreateRequest(
teamId: 'teamId', // ID пространства в Mattermost
method: Method::POST, // HTTP метод вызова команды через вебхук
trigger: 'command', // Триггер команды
url: 'http://localhost', // URL вебхука для вызова команды
));
// Редактирование команды
$service->updateCommand(new UpdateRequest(
id: $command->id, // ID команды в Mattermost
token: $command->token, // Токен команды
createAt: $command->createAt, // Дата создания команды
updateAt: $command->updateAt, // Дата обновления команды
deleteAt: $command->deleteAt, // Дата удаления команды
creatorId: $command->creatorId, // ID создателя команды
teamId: $command->teamId, // ID пространства в Mattermost
trigger: $command->trigger, // Триггер команды
method: $command->method, // HTTP метод вызова команды через вебхук
username: $command->username, // Имя пользователя в Mattermost
iconUrl: $command->iconUrl, // URL иконки пользователя в Mattermost
autoComplete: $command->autoComplete, // Автозаполнение команды
autoCompleteDesc: $command->autoCompleteDesc, // Описание автозаполнения команды
autoCompleteHint: $command->autoCompleteHint, // Подсказка автозаполнения команды
displayName: $command->displayName, // Отображаемое имя команды
description: $command->description, // Описание команды
url: $command->url, // URL вебхука для вызова команды
));
// Получение команд пространства
$commands = $service->getCommands(new IndexRequest(
teamId: 'teamId', // ID пространства в Mattermost
customOnly: false, // Получить только пользовательские команды
));
// Получение команды
$command = $service->showCommand($command->id);
// Удаление команды
$service->deleteCommand($command->id);Вызов диалога (модалки) (DialogServiceContract.php)
Вызов диалога происходит через вебхук и использует контракт DialogServiceContract.php
/** @var \App\Http\Requests\Mattermost\DialogRequest $request */
$request = app()->make(\App\Http\Requests\Mattermost\DialogRequest::class);
/** @var \App\Contracts\Mattermost\DialogServiceContract $contract */
$contract = app()->make(\App\Contracts\Mattermost\DialogServiceContract::class);
$contract->open($request->getDto());Управление постами (сообщениями) (PostServiceContract.php)
use Rocketfirm\MattermostDriver\Collections\AttachmentCollection;
use Rocketfirm\MattermostDriver\Entities\Props;
use Rocketfirm\MattermostDriver\Requests\Post\CreateRequest;
use Rocketfirm\MattermostDriver\Requests\Post\UpdateRequest;
/** @var \App\Contracts\Mattermost\PostServiceContract $contract */
$contract = app()->make(\App\Contracts\Mattermost\PostServiceContract::class);
// Создание поста
$post = $contract->createPost(new CreateRequest(
setOnline: true, // Изменить статус пользователя на онлайн
channelId: 'channelId', // ID канала
message: 'Text message', // Текст сообщения
rootId: 'rootId', // ID родительского сообщения
fileIds: ['fileId1', 'fileId2'], // ID файлов
props: new Props(
props: [ // Дополнительные свойства
'key1' => 'value1',
'key2' => 'value2',
],
attachmentCollection: AttachmentCollection::make(), // Коллекция вложений (кнопок, файлов, картинок)
)
));
// Редактирование поста
$contract->updatePost(new UpdateRequest(
id: $post->id, // ID поста в Mattermost
isPinned: true, // Закрепить пост
message: 'Updated message', // Текст сообщения
hasReactions: false, // Удалить реакции
props: new Props(
props: [ // Дополнительные свойства
'key1' => 'value1',
'key2' => 'value2',
],
attachmentCollection: AttachmentCollection::make(), // Коллекция вложений (кнопок, файлов, картинок)
)
));Управление пространствами (TeamServiceContract.php)
use Rocketfirm\MattermostDriver\Requests\Team\ChannelsRequest;
use Rocketfirm\MattermostDriver\Requests\Team\IndexRequest;
/** @var \App\Contracts\Mattermost\TeamServiceContract $service */
$service = app()->make(\App\Contracts\Mattermost\TeamServiceContract::class);
// Получение пространств
$teams = $service->getTeams(new IndexRequest(
page: 0, // Номер страницы
perPage: 60, // Количество элементов на странице
includeTotalCount: true, // Включить подсчет общего количества элементов
excludePolicyConstrained: true, // Исключить пространства, ограниченные политикой
));
// Получение публичных каналов (чатов)
$publicChannels = $service->getPublicChannels(new ChannelsRequest(
teamId: 'teamId', // ID пространства
page: 0, // Номер страницы
perPage: 60, // Количество элементов на странице
));
// Получение приватных каналов (чатов)
$privateChannels = $service->getPrivateChannels(new ChannelsRequest(
teamId: 'teamId', // ID пространства
page: 0, // Номер страницы
perPage: 60, // Количество элементов на странице
));Управление пользователями (UserServiceContract.php)
use Rocketfirm\MattermostDriver\Requests\User\IndexRequest;
use Rocketfirm\MattermostDriver\Enums\Post\Sort;
/** @var \App\Contracts\Mattermost\UserServiceContract $service */
$service = app()->make(\App\Contracts\Mattermost\UserServiceContract::class);
// Получение пользователей
$users = $service->index(new IndexRequest(
page: 0, // Номер страницы
perPage: 60, // Количество элементов на странице
inTeam: 'teamId', // ID пространства
notInTeam: 'teamId', // ID пространства
inChannel: 'channelId', // ID канала
notInChannel: 'channelId', // ID канала
inGroup: 'groupId', // ID группы
groupConstrained: true, // Исключить пользователей, ограниченных группой
withoutTeam: false, // Исключить пользователей без пространства
active: true, // Активные пользователи
inactive: true, // Неактивные пользователи
role: 'role', // Роль
sort: Sort::CREATE_AT, // Сортировка
roles: ['role1', 'role2'], // Роли
channelRoles: ['channelRole1', 'channelRole2'], // Роли канала
teamRoles: ['teamRole1', 'teamRole2'], // Роли пространства
));
// Получение всех пользователей в пространстве
$allUsers = $service->all(
inTeamId: 'teamId', // ID пространства
notInTeamId: 'teamId', // ID пространства
);- PHP 8.2
- Laravel 11.9
- PostgreSQL Latest
- Nginx Latest Alpine
Используется библиотека Laravel Pint Конфигурация в pint.json
- Для проверки кода запускается команда:
vendor/bin/pint --test --dirty --config pint.json- Для форматирования кода:
vendor/bin/pint --config pint.jsonИспользуется библиотека PHPStan Конфигурация в phpstan.neon
- Для запуска анализатора используется команда:
vendor/bin/phpstan analyse -c phpstan.neonИспользуется библиотека L5-Swagger
Конфиги в файле l5-swagger.php
Базовый класс контроллера в Controller
UI документации доступен по пути http://blog.localhost/api/documentation
JSON файл доступен по пути http://blog.localhost/docs/api-docs.json
Сама документация генерируется в директории storage/api-docs/api-docs.json
Для генерации документации используется команда:
php artisan l5-swagger:generateИспользуется стандартная библиотека PHPUnit
Конфигурация в файле phpunit.xml
Unit тесты в директории Unit Feature тесты в директории Feature
Так же применяются проверки и подготовка тестов к запуску (логика описана в трейте CreatesApplication).
Базовый класс тестов в TestCase
Для запуска тестов используется следующая команда:
vendor/bin/phpunit




