Skip to content

Commit

Permalink
Implemented ticket reference
Browse files Browse the repository at this point in the history
  • Loading branch information
rexlManu committed Nov 18, 2020
1 parent 936afce commit 0055762
Show file tree
Hide file tree
Showing 10 changed files with 235 additions and 2 deletions.
14 changes: 12 additions & 2 deletions config/config.php
Expand Up @@ -50,7 +50,8 @@
'tickets-table' => 'tickets',
'ticket-messages-table' => 'ticket_messages',
'ticket-uploads-table' => 'ticket_uploads',
'ticket-categories-table' => 'ticket_categories'
'ticket-categories-table' => 'ticket_categories',
'ticket-references-table' => 'ticket_references'
],

/*
Expand Down Expand Up @@ -117,5 +118,14 @@
/*
* Enable categories for tickets
*/
'category' => true
'category' => true,
/*
* Enable references for tickets
*/
'references' => true,
'references-nullable' => true,
/*
* Ether you define your models for references or customize the view.
*/
'reference-models' => []
];
@@ -0,0 +1,38 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTicketReferencesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(config('laravel-tickets.database.ticket-references-table'), function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('ticket_id');
$table->morphs('referenceable');
$table->timestamps();

if (! config('laravel-tickets.models.uuid')) {
$table->foreign('ticket_id')
->on(config('laravel-tickets.database.tickets-table'))->references('id');
}
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists(config('laravel-tickets.database.ticket-references-table'));
}
}
27 changes: 27 additions & 0 deletions resources/views/tickets/create.blade.php
Expand Up @@ -33,6 +33,33 @@
</div>
</div>
@endif
@if (config('laravel-tickets.references'))
<div class="col-12">
<div class="form-group">
<label>@lang('Reference')</label>
<select class="form-control @error('reference') is-invalid @enderror"
name="reference">
@if (config('laravel-tickets.references-nullable'))
<option value="">@lang('No reference')</option>
@endif
@foreach (config('laravel-tickets.reference-models') as $modelClass)
@foreach (resolve($modelClass)->all() as $model)
@if (!$model->hasReferenceAccess())
@continue
@endif
<option value="{{ $model->toReference() }}"
@if (old('reference') === $model->toReference())
selected
@endif>@lang(basename(get_class($model))) #{{$model->id}}</option>
@endforeach
@endforeach
</select>
@error('reference')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
@endif
<div class="col-4">
<div class="form-group">
<label>@lang('Priority')</label>
Expand Down
8 changes: 8 additions & 0 deletions resources/views/tickets/show.blade.php
Expand Up @@ -91,6 +91,14 @@ class="custom-file-input @error('files') is-invalid @enderror" id="files">
value="{{ $ticket->category()->first()->translation }}" disabled>
</div>
@endif
@if (config('laravel-tickets.references') && $ticket->reference()->exists())
<div class="form-group">
<label>@lang('Reference'):</label>
@php($referenceable = $ticket->reference->referenceable)
<input class="form-control" type="text"
value="@lang(basename(get_class($referenceable))) #{{$referenceable->id}}" disabled>
</div>
@endif
<div class="form-group">
<label>@lang('Subject'):</label>
<input class="form-control" type="text" value="{{ $ticket->subject }}" disabled>
Expand Down
20 changes: 20 additions & 0 deletions src/Controllers/TicketController.php
Expand Up @@ -4,6 +4,7 @@
namespace RexlManu\LaravelTickets\Controllers;


use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
Expand All @@ -15,7 +16,9 @@
use RexlManu\LaravelTickets\Events\TicketOpenEvent;
use RexlManu\LaravelTickets\Models\Ticket;
use RexlManu\LaravelTickets\Models\TicketMessage;
use RexlManu\LaravelTickets\Models\TicketReference;
use RexlManu\LaravelTickets\Models\TicketUpload;
use RexlManu\LaravelTickets\Rule\TicketReferenceRule;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

/**
Expand Down Expand Up @@ -103,6 +106,12 @@ public function store(Request $request)
Rule::exists(config('laravel-tickets.database.ticket-categories-table'), 'id'),
];
}
if (config('laravel-tickets.references')) {
$rules[ 'reference' ] = [
config('laravel-tickets.references-nullable') ? 'nullable' : 'required',
new TicketReferenceRule(),
];
}
$data = $request->validate($rules);
if ($request->user()->tickets()->where('state', '!=', 'CLOSED')->count() >= config('laravel-tickets.maximal-open-tickets')) {
$message = trans('You have reached the limit of open tickets');
Expand All @@ -116,6 +125,17 @@ public function store(Request $request)
$ticket = $request->user()->tickets()->create(
$data
);

if (array_key_exists('reference', $data)) {
$reference = explode(',', $data[ 'reference' ]);
$ticketReference = new TicketReference();
$ticketReference->ticket()->associate($ticket);
$ticketReference->referenceable()->associate(
resolve($reference[ 0 ])->find($reference[ 1 ])
);
$ticketReference->save();
}

$ticketMessage = new TicketMessage($data);
$ticketMessage->user()->associate($request->user());
$ticketMessage->ticket()->associate($ticket);
Expand Down
24 changes: 24 additions & 0 deletions src/Interfaces/TicketReference.php
@@ -0,0 +1,24 @@
<?php


namespace RexlManu\LaravelTickets\Interfaces;


interface TicketReference
{

/**
* Check if a user has access to this reference
*
* @return boolean
*/
function hasReferenceAccess() : bool;

/**
* Combine type and id to a string for forms
*
* @return string
*/
function toReference() : string;

}
5 changes: 5 additions & 0 deletions src/Models/Ticket.php
Expand Up @@ -38,6 +38,11 @@ public function category()
return $this->belongsTo(TicketCategory::class);
}

public function reference()
{
return $this->hasOne(TicketReference::class);
}

public function scopeState($query, $state)
{
return $query->where('state', $state);
Expand Down
30 changes: 30 additions & 0 deletions src/Models/TicketReference.php
@@ -0,0 +1,30 @@
<?php


namespace RexlManu\LaravelTickets\Models;


use Illuminate\Database\Eloquent\Model;
use RexlManu\LaravelTickets\Traits\HasConfigModel;

class TicketReference extends Model
{

use HasConfigModel;

public function getTable()
{
return config('laravel-tickets.database.ticket-references-table');
}

public function ticket()
{
return $this->belongsTo(Ticket::class);
}

public function referenceable()
{
return $this->morphTo();
}

}
55 changes: 55 additions & 0 deletions src/Rule/TicketReferenceRule.php
@@ -0,0 +1,55 @@
<?php


namespace RexlManu\LaravelTickets\Rule;


use Illuminate\Contracts\Validation\Rule;
use Illuminate\Database\Eloquent\Relations\Relation;
use RexlManu\LaravelTickets\Interfaces\TicketReference;

class TicketReferenceRule implements Rule
{

/**
* Determine if the ticket reference is valid
* Checks
* if value contains type and id
* if the model exists
* if the model is a instance of @param string $attribute
*
* @param mixed $value
*
* @return bool if the value is valid
* @link TicketReference
* if the user has rights to the model
*
*/
public function passes($attribute, $value)
{
if (! str_contains($value, ',')) return false;

$values = explode(',', $value);
if (count($values) !== 2) return false;

$type = $values[ 0 ];
if (! class_exists($type)) return false;
$model = resolve($type)->find($values[ 1 ]);
if (empty($model)
|| ! $model instanceof TicketReference
|| ! $model->hasReferenceAccess()) {
return false;
}
return true;
}

/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return trans('The reference is not valid');
}
}
16 changes: 16 additions & 0 deletions src/Traits/HasTicketReference.php
@@ -0,0 +1,16 @@
<?php


namespace RexlManu\LaravelTickets\Traits;


trait HasTicketReference
{

public function toReference() : string
{
$type = get_class($this);
return "$type,$this->id";
}

}

0 comments on commit 0055762

Please sign in to comment.