You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

257 lines
7.1 KiB

<?php
namespace App\Models;
use Anik\Amqp\Exchange;
use Anik\Amqp\Facades\Amqp;
use App\Events\ModelSaved;
use PhpAmqpLib\Wire\AMQPTable;
use Anik\Amqp\PublishableMessage;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Validator;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Database\Eloquent\Model as EloquentModel;
class Model extends EloquentModel
{
/**
* Introducing model relationships
*
* @var array
*/
protected $fillable_relations = [];
/**
* Models that are ready to change.
*
* @var array
*/
protected $filled_relations = [];
/**
* Models that are ready to change.
*
* @var array
*/
protected $reportable = [];
protected $dirties = [];
protected $action = null;
public const CREATED = 10;
public const UPDATED = 20;
public const DELETED = 30;
public const RESTORED = 40;
protected static function booted()
{
static::created(function ($model) {
$model->action = static::CREATED;
});
static::updated(function ($model) {
$model->action = static::UPDATED;
});
static::deleted(function ($model) {
$model->action = static::DELETED;
});
}
/**
* @return void
* @throw \Exception
*/
public function rules()
{
return [];
}
/**
*
*
* @param array $attributes
* @return void
*/
public function validate(array $attributes = null)
{
$attributes = $attributes ?? $this->getAttributes();
/** @var Validator $validator */
$validator = app('validator')->make($attributes, $this->rules());
if ($validator->fails()) {
throw new ValidationException(
$validator,
new JsonResponse($validator->errors()->getMessages(), Response::HTTP_UNPROCESSABLE_ENTITY)
);
}
}
/**
* @return void
*/
public function updateRelations()
{
}
/**
* @param string|null $key
* @return void
*/
public function getValueOf(?string $key)
{
$values = [];
if ($key && isset($values, $key)) {
return $values[$key];
}
return $values;
}
protected function makeChanges()
{
if (empty($this->reportable)) {
return;
}
$changes = new Collection($this->getDirty());
// fillable * or field
$changes = $changes->filter(function ($value, $key) {
foreach ($this->reportable as $i => $name) {
if ($key === $name) {
return true;
}
}
return false;
});
if (($changes->isEmpty() && $this->action == static::UPDATED)) {
return;
}
return [
'original' => $this->getOriginal() + $this->getAttributes(),
'diff' => $changes->toArray(),
];
// return [
// 'auth' => Auth::id(),
// 'timestamp' => $this->freshTimestamp(),
// 'business' => $this->getValueOf('business_id'),
// 'info' => \request('_business_info')['info'] ?? null,
// 'project' => $this->getValueOf('project_id'),
// 'data' => [
// 'sprint_id' => $this->getValueOf('sprint_id'),
// 'system_id' => $this->getValueOf('system_id'),
// 'workflow_id' => $this->getValueOf('workflow_id'),
// 'status_id' => $this->getValueOf('status_id'),
// 'user_id' => $this->getValueOf('user_id'),
// 'table_name' => $this->getTable(),
// 'crud_id' => $this->action,
// 'original' => $this->getOriginal() + $this->getAttributes(),
// 'diff' => $changes->toArray(),
// ],
// 'from' => env('CONTAINER_NAME'),
// ];
}
protected function report($changes): void
{
if ($this->action == null){
return;
}
$payload = [
'auth' => Auth::id(),
'timestamp' => $this->freshTimestamp(),
'business' => $this->getValueOf('business_id'),
'info' => \request('_business_info') ?? null,
'project' => $this->getValueOf('project_id'),
'data' => [
'sprint_id' => $this->getValueOf('sprint_id'),
'system_id' => $this->getValueOf('system_id'),
'workflow_id' => $this->getValueOf('workflow_id'),
'status_id' => $this->getValueOf('status_id'),
'task_id' => $this->getValueOf('task_id'),
'subject_id' => $this->getValueOf('subject_id'),
'user_id' => $this->getValueOf('user_id'),
'table_name' => $this->getTable(),
'crud_id' => $this->action,
'original' => $changes['original'] + $this->getOriginal(),
'diff' => $changes['diff'],
],
'from' => env('CONTAINER_NAME'),
];
$message = new PublishableMessage(json_encode($payload));
ModelSaved::dispatch(json_encode($payload));
// $routers = [
// "activity_exchange" => ["name" => "activity",],
// "notif_exchange" => ["name" => "notif",],
// "socket_exchange" => ["name" => "socket",],
// ];
//
// foreach ($routers as $exchange => $properties) {
// $message->setProperties(["application_headers" => new AMQPTable($properties)]);
//
// $message->setExchange(new Exchange($exchange));
//
// Amqp::publish($message, "");
// }
}
/**
* @param array $options
* @return void
*/
public function save(array $options = [])
{
// The validation function is called first
$this->validate();
// Then, because the relationships are set as attributes in this model
// we pre-enter their names in filled_relation attribute and store
// them in a temporary variable with a loop.
foreach ($this->fillable_relations as $relation) {
$this->filled_relations[$relation] = $this[$relation];
unset($this[$relation]);
}
// all of its action inside one transaction
// so if any of them failed the whole
// process rollbacked
DB::transaction(function () use ($options) {
// report to the activity aggregator
$changes = $this->makeChanges();
// save the model with it's attributes
parent::save($options);
// save the model with it's relationships
$this->updateRelations();
is_array($changes) ? $this->report($changes) : true;
}, 3);
}
public function delete()
{
$changes = $this->makeChanges();
parent::delete();
is_array($changes) ? $this->report($changes) : true;
}
}