Model.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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\Core\Container;
  11. class Model
  12. {
  13. /**
  14. * Контейнер
  15. * @var Container
  16. */
  17. protected $c;
  18. /**
  19. * Ключ модели для контейнера
  20. * @var string
  21. */
  22. protected $cKey = 'unknown';
  23. /**
  24. * Данные модели
  25. * @var array
  26. */
  27. protected $zAttrs = [];
  28. /**
  29. * Вычисленные данные модели
  30. * @var array
  31. */
  32. protected $zAttrsCalc = [];
  33. /**
  34. * Зависимости свойств
  35. * @var array
  36. */
  37. protected $zDepend = [];
  38. public function __construct(Container $container)
  39. {
  40. $this->c = $container;
  41. }
  42. /**
  43. * Проверяет наличие свойства
  44. */
  45. public function __isset(/* mixed */ $name): bool
  46. {
  47. return \array_key_exists($name, $this->zAttrs)
  48. || \array_key_exists($name, $this->zAttrsCalc)
  49. || \method_exists($this, 'get' . $name);
  50. }
  51. /**
  52. * Удаляет свойство
  53. */
  54. public function __unset(/* mixed */ $name): void
  55. {
  56. unset($this->zAttrs[$name]);
  57. $this->unsetCalc($name);
  58. }
  59. /**
  60. * Удаляет вычисленные зависимые свойства
  61. */
  62. protected function unsetCalc(/* mixed */ $name): void
  63. {
  64. unset($this->zAttrsCalc[$name]);
  65. unset($this->zAttrsCalc['censor' . \ucfirst($name)]);
  66. if (isset($this->zDepend[$name])) {
  67. $this->zAttrsCalc = \array_diff_key($this->zAttrsCalc, \array_flip($this->zDepend[$name]));
  68. }
  69. }
  70. /**
  71. * Устанавливает значение для свойства
  72. */
  73. public function __set(string $name, /* mixed */ $value): void
  74. {
  75. $this->unsetCalc($name);
  76. if (\method_exists($this, $method = 'set' . $name)) {
  77. $this->$method($value);
  78. } else {
  79. $this->zAttrs[$name] = $value;
  80. }
  81. }
  82. /**
  83. * Устанавливает значение для свойства
  84. * Без вычислений, но со сбросом зависимых свойст и вычисленного значения
  85. */
  86. public function setAttr(string $name, /* mixed */ $value): Model
  87. {
  88. $this->unsetCalc($name);
  89. $this->zAttrs[$name] = $value;
  90. return $this;
  91. }
  92. /**
  93. * Устанавливает значения для свойств
  94. * Сбрасывает вычисленные свойства
  95. */
  96. public function setAttrs(array $attrs): Model
  97. {
  98. $this->zAttrs = $attrs; //????
  99. $this->zAttrsCalc = [];
  100. return $this;
  101. }
  102. /**
  103. * Возвращает значение свойства
  104. * Или возвращает внешний метод Models\Method
  105. */
  106. public function __get(string $name) /* : mixed */
  107. {
  108. if (\array_key_exists($name, $this->zAttrsCalc)) {
  109. return $this->zAttrsCalc[$name];
  110. } elseif (\method_exists($this, $method = 'get' . $name)) {
  111. return $this->zAttrsCalc[$name] = $this->$method();
  112. } elseif (\array_key_exists($name, $this->zAttrs)) {
  113. return $this->zAttrs[$name];
  114. } elseif (
  115. 0 === \strpos($name, 'censor')
  116. && isset($this->zAttrs[$root = \lcfirst(\substr($name, 6))])
  117. ) {
  118. return $this->zAttrsCalc[$name] = $this->c->censorship->censor($this->zAttrs[$root]);
  119. }
  120. $x = \ord($name);
  121. if ($x > 90 || $x < 65) {
  122. return null;
  123. } else {
  124. $key = $this->cKey . '/' . \lcfirst($name);
  125. return $this->c->$key->setModel($this);
  126. }
  127. }
  128. /**
  129. * Возвращает значение свойства
  130. * Без вычислений
  131. */
  132. public function getAttr(string $name, /* mixed */ $default = null) /* : mixed */
  133. {
  134. return \array_key_exists($name, $this->zAttrs) ? $this->zAttrs[$name] : $default;
  135. }
  136. /**
  137. * Выполняет подгружаемый метод при его наличии
  138. */
  139. public function __call(string $name, array $args) /* : mixed */
  140. {
  141. $key = $this->cKey . '/' . $name;
  142. return $this->c->$key->setModel($this)->$name(...$args);
  143. }
  144. }