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.

237 lines
6.4 KiB

  1. <?php
  2. namespace App\Models;
  3. use App\Events\ModelSaved;
  4. use Illuminate\Http\JsonResponse;
  5. use Illuminate\Support\Facades\DB;
  6. use Illuminate\Support\Facades\Auth;
  7. use Illuminate\Validation\Validator;
  8. use Illuminate\Database\Eloquent\Collection;
  9. use Illuminate\Validation\ValidationException;
  10. use Symfony\Component\HttpFoundation\Response;
  11. use Illuminate\Database\Eloquent\Model as EloquentModel;
  12. class Model extends EloquentModel
  13. {
  14. /**
  15. * Introducing model relationships
  16. *
  17. * @var array
  18. */
  19. protected $fillable_relations = [];
  20. /**
  21. * Models that are ready to change.
  22. *
  23. * @var array
  24. */
  25. protected $filled_relations = [];
  26. /**
  27. * Models that are ready to change.
  28. *
  29. * @var array
  30. */
  31. protected $reportable = [];
  32. protected $dirties = [];
  33. protected $action = null;
  34. public const CREATED = 10;
  35. public const UPDATED = 20;
  36. public const DELETED = 30;
  37. public const RESTORED = 40;
  38. protected static function booted()
  39. {
  40. static::created(function ($model) {
  41. $model->action = static::CREATED;
  42. });
  43. static::updated(function ($model) {
  44. $model->action = static::UPDATED;
  45. });
  46. static::deleted(function ($model) {
  47. $model->action = static::DELETED;
  48. });
  49. }
  50. /**
  51. * @return void
  52. * @throw \Exception
  53. */
  54. public function rules()
  55. {
  56. return [];
  57. }
  58. /**
  59. *
  60. *
  61. * @param array $attributes
  62. * @return void
  63. */
  64. public function validate(array $attributes = null)
  65. {
  66. $attributes = $attributes ?? $this->getAttributes();
  67. /** @var Validator $validator */
  68. $validator = app('validator')->make($attributes, $this->rules());
  69. if ($validator->fails()) {
  70. throw new ValidationException(
  71. $validator,
  72. new JsonResponse($validator->errors()->getMessages(), Response::HTTP_UNPROCESSABLE_ENTITY)
  73. );
  74. }
  75. }
  76. /**
  77. * @return void
  78. */
  79. public function updateRelations()
  80. {
  81. }
  82. /**
  83. * @param string|null $key
  84. * @return void
  85. */
  86. public function getValueOf(?string $key)
  87. {
  88. $values = [];
  89. if ($key && isset($values, $key)) {
  90. return $values[$key];
  91. }
  92. return $values;
  93. }
  94. protected function makeChanges()
  95. {
  96. if (empty($this->reportable)) {
  97. return;
  98. }
  99. $changes = new Collection($this->getDirty());
  100. // fillable * or field
  101. $changes = $changes->filter(function ($value, $key) {
  102. foreach ($this->reportable as $i => $name) {
  103. if ($key === $name) {
  104. return true;
  105. }
  106. }
  107. return false;
  108. });
  109. if (($changes->isEmpty() && $this->action == static::UPDATED)) {
  110. return;
  111. }
  112. return [
  113. 'original' => $this->getOriginal() + $this->getAttributes(),
  114. 'diff' => $changes->toArray(),
  115. ];
  116. // return [
  117. // 'auth' => Auth::id(),
  118. // 'timestamp' => $this->freshTimestamp(),
  119. // 'business' => $this->getValueOf('business_id'),
  120. // 'info' => \request('_business_info')['info'] ?? null,
  121. // 'project' => $this->getValueOf('project_id'),
  122. // 'data' => [
  123. // 'sprint_id' => $this->getValueOf('sprint_id'),
  124. // 'system_id' => $this->getValueOf('system_id'),
  125. // 'workflow_id' => $this->getValueOf('workflow_id'),
  126. // 'status_id' => $this->getValueOf('status_id'),
  127. // 'user_id' => $this->getValueOf('user_id'),
  128. // 'table_name' => $this->getTable(),
  129. // 'crud_id' => $this->action,
  130. // 'original' => $this->getOriginal() + $this->getAttributes(),
  131. // 'diff' => $changes->toArray(),
  132. // ],
  133. // 'from' => env('CONTAINER_NAME'),
  134. // ];
  135. }
  136. protected function report($changes): void
  137. {
  138. if ($this->action == null){
  139. return;
  140. }
  141. $payload = [
  142. 'auth' => Auth::id(),
  143. 'timestamp' => $this->freshTimestamp(),
  144. 'business' => $this->getValueOf('business_id'),
  145. 'info' => \request('_business_info') ?? null,
  146. 'project' => $this->getValueOf('project_id'),
  147. 'data' => [
  148. 'sprint_id' => $this->getValueOf('sprint_id'),
  149. 'system_id' => $this->getValueOf('system_id'),
  150. 'workflow_id' => $this->getValueOf('workflow_id'),
  151. 'status_id' => $this->getValueOf('status_id'),
  152. 'task_id' => $this->getValueOf('task_id'),
  153. 'subject_id' => $this->getValueOf('subject_id'),
  154. 'user_id' => $this->getValueOf('user_id'),
  155. 'table_name' => $this->getTable(),
  156. 'crud_id' => $this->action,
  157. 'original' => $changes['original'] + $this->getOriginal(),
  158. 'diff' => $changes['diff'],
  159. ],
  160. 'from' => env('CONTAINER_NAME'),
  161. ];
  162. ModelSaved::dispatch(json_encode($payload));
  163. }
  164. /**
  165. * @param array $options
  166. * @return void
  167. */
  168. public function save(array $options = [])
  169. {
  170. // The validation function is called first
  171. $this->validate();
  172. // Then, because the relationships are set as attributes in this model
  173. // we pre-enter their names in filled_relation attribute and store
  174. // them in a temporary variable with a loop.
  175. foreach ($this->fillable_relations as $relation) {
  176. $this->filled_relations[$relation] = $this[$relation];
  177. unset($this[$relation]);
  178. }
  179. // all of its action inside one transaction
  180. // so if any of them failed the whole
  181. // process rollbacked
  182. DB::transaction(function () use ($options) {
  183. // report to the activity aggregator
  184. $changes = $this->makeChanges();
  185. // save the model with it's attributes
  186. parent::save($options);
  187. // save the model with it's relationships
  188. $this->updateRelations();
  189. is_array($changes) ? $this->report($changes) : true;
  190. }, 3);
  191. }
  192. public function delete()
  193. {
  194. $changes = $this->makeChanges();
  195. parent::delete();
  196. is_array($changes) ? $this->report($changes) : true;
  197. }
  198. }