This package will help you for manage tickets and support your clients.
- Features include:
- Department Management
- Ticket Management
- Ticket Messages Management
- Ticket Attachments Management
- Latest versions of PHP and PHPUnit and PHPCsFixer
- Best practices applied:
README.md
(badges included)LICENSE
composer.json
phpunit.xml
.gitignore
.php-cs-fixer.php
Require this package with composer.
composer require dnj/laravel-ticketing
Laravel uses Package Auto-Discovery, so doesn't require you to manually add the ServiceProvider.
php artisan vendor:publish --provider="dnj\Ticket\TicketServiceProvider"
use dnj\Filesystem\Local\Directory;
return [
// If set True we will migrate and validate title field for ticket.
'title' => true,
// Define your user model class for connect tickets to users. | example: App\User:class
'user_model' => null,
/**
* By default, the dnj/local-filesystem package is used to store files.
* According to the Directory class, you can specify the main path for storing file
*/
'attachment_root' => new Directory(public_path('ticket')),
/**
* Specifies the number of folders to create for storage based on the file hash
* If the hash of your file is 8c7dd922ad47494fc02c388e12c00eac and dir_layer_number is 2,
* the file is saved with this structure : [path]/8c/7d/8c7dd922ad47494fc02c388e12c00eac.jpg
*/
'dir_layer_number' => 2,
/**
* You can set the validations you want to store files from here.
*/
'attachment_rules' => [
'mimes:jpg,png,txt', 'mimetypes:text/plain,image/jpeg,image/png', 'max:1024',
]
];
ℹ️ Note
User activity logs are disabled by default, if you want to save them set
$userActivityLog
to true.
Example :
use dnj\Ticket\Contracts\IDepartmentManager;
$departmentManager = app(IDepartmentManager::class);
$department = $departmentManager->store(
title:'Sell Department',
userActivityLog: true
); // returns an Department model which implementes IDepartment
Search departments:
use dnj\Ticket\Contracts\IDepartmentManager;
use dnj\Ticket\Contracts\IDepartment;
$departmentManager = app(IDepartmentManager::class);
/**
* @param array{title?:string,created_start_date?:string,created_end_date?:string,updated_start_date?:string,updated_end_date?:string}|null $filters
* @var iterable<IDepartment> $departments
*/
$departments = $departmentManager->search(
filters:['title' => 'sales']
);
Create new department:
use dnj\Ticket\Contracts\IDepartmentManager;
$departmentManager = app(IDepartmentManager::class);
/**
* @param string $title
* @param bool $userActivityLog = false
* @return IDepartment
*/
$department = $departmentManager->store(title:'Sell Department');
Show department:
use dnj\Ticket\Contracts\IDepartmentManager;
$departmentManager = app(IDepartmentManager::class);
/**
* @param int $id
* @return IDepartment
*/
$department = $departmentManager->find(id:1);
Update department:
use dnj\Ticket\Contracts\IDepartmentManager;
$departmentManager = app(IDepartmentManager::class);
/**
* @param int $id
* @param array{title?:string} $changes
* @param bool $userActivityLog = false
* @return IDepartment
*/
$department = $departmentManager->update(
id:1,
changes: ['title' => 'Support']
);
Delete department:
use dnj\Ticket\Contracts\IDepartmentManager;
$departmentManager = app(IDepartmentManager::class);
/**
* @param int $id
* @param bool $userActivityLog = false
* @return void
*/
$departmentManager->destroy(
id:1,
userActivityLog: false, // Prevent saving a log for authenticated user
);
Search tickets:
use dnj\Ticket\Contracts\ITicketManager;
use dnj\Ticket\Contracts\ITicket;
use dnj\Ticket\Enums\TicketStatus;
$ticketManager = app(ITicketManager::class);
/**
* @param array{title?:string,client_id?:int,department_id?:int,status?:TicketStatus[],created_start_date?:DateTimeInterface,created_end_date?:DateTimeInterface,updated_start_date?:DateTimeInterface,updated_end_date?:DateTimeInterface}|null $filters
* @param bool $userActivityLog = false
* @return iterable<ITicket>
*/
$tickets = $ticketManager->search(
filters: [
'client_id' => 1,
'status' => [TicketStatus::UNREAD, TicketStatus::IN_PROGRESS],
]
);
Create new ticket:
use dnj\Ticket\Managers\TicketManager;
$ticketManager = app(ITicketManager::class);
/**
* @param int $clientId
* @param int $departmentId
* @param string $message
* @param array<int|UploadedFile> $files
* @param string|null $title = null
* @param int|null $userId = null
* @param dnj\Ticket\Enums\TicketStatus|null $status = null
* @param bool $userActivityLog = false
* @throws ITicketTitleHasBeenDisabledException if $title is set but title is disabled
* @return IMessage
*/
$message = $ticketManager->store(
clientId: 1,
departmentId: 1,
message:'First message for ticket',
files:[],
title:'Ticket subject',
userId: auth()->user()->id,
status: null
);
Show ticket:
use dnj\Ticket\Managers\TicketManager;
$ticketManager = app(ITicketManager::class);
/**
* @param int id
* @return ITicket
*/
$ticket = $ticket->find(id:1);
Update ticket :
use dnj\Ticket\Managers\TicketManager;
$ticketManager = app(ITicketManager::class);
/**
* @param int $id
* @param array{title?:string,client_id?:int,department_id?:int,status?:TicketStatus} $changes
* @param bool $userActivityLog = false
* @return ITicket
*/
$ticket = $ticket->update(
id: 1,
changes: ['client_id' => 3],
userActivityLog: true
);
Delete ticket :
use dnj\Ticket\Managers\TicketManager;
$ticketManager = app(ITicketManager::class);
/**
* @param int $id
* @param bool $userActivityLog = false
* @return void
*/
$ticket->destroy(id:1);
Search ticket messages :
use dnj\Ticket\Contracts\IMessageManager;
use dnj\Ticket\Contracts\IMessage;
$messageManager = app(IMessageManager::class);
/**
* @param int $ticketId
* @param array{user_id?:int,sort?:string,created_start_date?:DateTimeInterface,created_end_date?:DateTimeInterface,updated_start_date?:DateTimeInterface,updated_end_date?:DateTimeInterface}|null $filters
* @return iterable<IMessage>
*/
$ticketMessages = $messageManager->search(
ticketId:5,
filters:[
'user_id' => 1,
]
);
Create new ticket message :
use dnj\Ticket\Contracts\IMessageManager;
use dnj\Ticket\Contracts\IMessage;
use dnj\Ticket\Enums\TicketStatus;
$messageManager = app(IMessageManager::class);
/**
* @param int $ticketId
* @param string $message
* @param array<int|UploadedFile> $files
* @param int|null $userId = null
* @param bool $userActivityLog = false
* @return IMessage
*/
$ticketMessage = $messageManager->store(
ticketId: 1,
message: 'Second message for ticket',
files: [113],
userId: auth()->user()->id
);
Show ticket message:
use dnj\Ticket\Contracts\IMessageManager;
use dnj\Ticket\Contracts\IMessage;
$messageManager = app(IMessageManager::class);
/**
* @param int id
* @return IMessage
*/
$ticketMessage = $messageManager->find(id:4);
Update ticket message:
use dnj\Ticket\Contracts\IMessageManager;
use dnj\Ticket\Contracts\IMessage;
$messageManager = app(IMessageManager::class);
/**
* @param int $id
* @param array{message?:string,userId?:int} $changes
* @param bool $userActivityLog = false
* @return IMessage
*/
$ticketMessage = $messageManager->update(
id:1,
changes: ['message'=>'Ticket message has updated']
);
Delete ticket message:
use dnj\Ticket\Contracts\IMessageManager;
$messageManager = app(IMessageManager::class);
/**
* @param int $id
* @param bool $userActivityLog = false
* @return void
*/
$messageManager->destroy(id:1);
Search ticket attachment :
use dnj\Ticket\Contracts\IAttachmentManager;
use dnj\Ticket\Contracts\IAttachment;
$attachmentManager = app(IAttachmentManager::class);
/**
* @param int $messageId
* @return iterable<IAttachment>
*/
$ticketAttachment = $attachmentManager->search(messageId:5);
Create new ticket attachment:
use dnj\Ticket\Contracts\IAttachmentManager;
use dnj\Ticket\Contracts\IAttachment;
use Illuminate\Http\UploadedFile;
$attachmentManager = app(IAttachmentManager::class);
/**
* @param UploadedFile $file
* @param int $messageId
* @param bool $userActivityLog = false
* @return IAttachment
*/
$attachment = $attachmentManager->storeByUpload(
file: UploadedFile::fake()->image('avatar.jpg'),
messageId: 2,
);
Show the attachment model using it's ID:
use dnj\Ticket\Contracts\IAttachmentManager;
use dnj\Ticket\Contracts\IAttachment;
$attachmentManager = app(IAttachmentManager::class);
/**
* @param int $id
* @return IAttachment
*/
$attachment = $attachmentManager->find(id:4);
Find orphan attachments:
This method helps you find stray files that are not attached to a message
use dnj\Ticket\Contracts\IAttachmentManager;
use dnj\Ticket\Contracts\IAttachment;
$attachmentManager = app(IAttachmentManager::class);
/**
* @param int id
* @return iterable<IAttachment>
*/
$orphans = $attachmentManager->findOrphans();
Update attachment:
use dnj\Ticket\Contracts\IAttachment;
use dnj\Ticket\Contracts\IAttachmentManager;
$attachmentManager = app(IAttachmentManager::class);
/**
* @param int $id
* @param array{message_id?:int} $changes
* @param bool $userActivityLog = false
* @throws dnj\Ticket\Contracts\Exceptions\IAttachmentAlreadyAsignedException if you double assign a attachment
* @return IAttachment
*/
$attachment = $attachmentManager->update(
id:1,
changes: [message_id => 5]
);
Delete ticket attachment:
use dnj\Ticket\Contracts\IAttachmentManager;
$attachmentManager = app(IAttachmentManager::class);
/**
* @param int $id
* @param bool $userActivityLog = false
* @return void
*/
$attachmentManager->destroy(id:1);
A document in YAML format has been prepared for better familiarization and use of package web services. which is placed in the docs
folder.
To use this file, you can import it on the stoplight.io site and see all available web services.
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
If you discover any security-related issues, please email security@dnj.co.ir instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.