DataModel.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. /**
  3. * This file is part of the ForkBB <https://github.com/forkbb>.
  4. *
  5. * @copyright (c) Visman <mio.visman@yandex.ru, https://github.com/MioVisman>
  6. * @license The MIT License (MIT)
  7. */
  8. declare(strict_types=1);
  9. namespace ForkBB\Models;
  10. use ForkBB\Models\Model;
  11. class DataModel extends Model
  12. {
  13. /**
  14. * Массив флагов измененных свойств модели
  15. * @var array
  16. */
  17. protected $zModFlags = [];
  18. /**
  19. * Массив состояний отслеживания изменений в свойствах модели
  20. * @var array
  21. */
  22. protected $zTrackFlags = [];
  23. /**
  24. * Устанавливает значения для свойств
  25. * Сбрасывает вычисленные свойства
  26. * Флаги модификации свойст сброшены
  27. */
  28. public function setAttrs(array $attrs): Model
  29. {
  30. $this->zModFlags = [];
  31. $this->zTrackFlags = [];
  32. return parent::setAttrs($attrs);
  33. }
  34. /**
  35. * Перезаписывает свойства модели
  36. * Флаги модификации свойств сбрасываются/устанавливаются в зависимости от второго параметра
  37. */
  38. public function replAttrs(array $attrs, bool $setFlags = false): DataModel
  39. {
  40. foreach ($attrs as $name => $value) {
  41. $this->__set($name, $value);
  42. if (! $setFlags) {
  43. unset($this->zModFlags[$name]);
  44. }
  45. }
  46. return $this;
  47. }
  48. /**
  49. * Возвращает значения свойств в массиве
  50. */
  51. public function getAttrs(): array
  52. {
  53. return $this->zAttrs; //????
  54. }
  55. /**
  56. * Возвращает массив имен измененных свойств модели
  57. */
  58. public function getModified(): array
  59. {
  60. return \array_keys($this->zModFlags);
  61. }
  62. /**
  63. * Возвращает модифицировано ли свойство модели
  64. */
  65. public function isModified(string $name): bool
  66. {
  67. return isset($this->zModFlags[$name]);
  68. }
  69. /**
  70. * Обнуляет массив флагов измененных свойств модели
  71. */
  72. public function resModified(): void
  73. {
  74. $this->zModFlags = [];
  75. $this->zTrackFlags = [];
  76. }
  77. /**
  78. * Устанавливает значение для свойства
  79. */
  80. public function __set(string $name, /* mixed */ $value): void
  81. {
  82. // без отслеживания
  83. if (0 === \strpos($name, '__')) {
  84. $track = null;
  85. $name = \substr($name, 2);
  86. // с отслеживанием
  87. } else {
  88. $track = false;
  89. if (\array_key_exists($name, $this->zAttrs)) {
  90. $track = true;
  91. $old = $this->zAttrs[$name];
  92. // fix
  93. if (
  94. \is_int($value)
  95. && \is_numeric($old)
  96. && \is_int(0 + $old)
  97. ) {
  98. $old = (int) $old;
  99. }
  100. }
  101. }
  102. $this->zTrackFlags[$name] = $track;
  103. parent::__set($name, $value);
  104. unset($this->zTrackFlags[$name]);
  105. if (null === $track) {
  106. return;
  107. }
  108. if (
  109. (
  110. ! $track
  111. && \array_key_exists($name, $this->zAttrs)
  112. )
  113. || (
  114. $track
  115. && $old !== $this->zAttrs[$name]
  116. )
  117. ) {
  118. $this->zModFlags[$name] = true;
  119. if (isset($this->zDepend[$name])) {
  120. foreach ($this->zDepend[$name] as $dependent) {
  121. $this->zModFlags[$dependent] = true; //???? может только физические свойства менять?
  122. }
  123. }
  124. }
  125. }
  126. /**
  127. * Возвращает значение свойства
  128. */
  129. public function __get(string $name) /* : mixed */
  130. {
  131. // без вычисления
  132. if (0 === \strpos($name, '__')) {
  133. return $this->getAttr(\substr($name, 2));
  134. // с вычислениями
  135. } else {
  136. return parent::__get($name);
  137. }
  138. }
  139. /**
  140. * Удаляет свойство ????
  141. */
  142. public function __unset(/* mixed */ $name): void
  143. {
  144. $this->zModFlags[$name] = false;
  145. parent::__unset($name);
  146. }
  147. }