|
|
<?php
namespace App\Utilities\Models;
use Anik\Amqp\Exchange; use Anik\Amqp\Facades\Amqp; 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));
$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; } }
|