vendor/pimcore/pimcore/lib/Model/AbstractModel.php line 246

Open in your IDE?
  1. <?php
  2. /**
  3. * Pimcore
  4. *
  5. * This source file is available under two different licenses:
  6. * - GNU General Public License version 3 (GPLv3)
  7. * - Pimcore Commercial License (PCL)
  8. * Full copyright and license information is available in
  9. * LICENSE.md which is distributed with this source code.
  10. *
  11. * @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12. * @license http://www.pimcore.org/license GPLv3 and PCL
  13. */
  14. namespace Pimcore\Model;
  15. use Pimcore\Logger;
  16. use Pimcore\Model\DataObject\Traits\ObjectVarTrait;
  17. /**
  18. * @method void beginTransaction()
  19. * @method void commit()
  20. * @method void rollBack()
  21. * @method void configure()
  22. * @method array getValidTableColumns(string $table, bool $cache)
  23. * @method void resetValidTableColumnsCache(string $table)
  24. */
  25. abstract class AbstractModel implements ModelInterface
  26. {
  27. use ObjectVarTrait;
  28. /**
  29. * @var \Pimcore\Model\Dao\AbstractDao|null
  30. */
  31. protected $dao;
  32. /**
  33. * @var array
  34. */
  35. private static $daoClassCache = [];
  36. /**
  37. * @var array|null
  38. */
  39. private static $daoClassMap = null;
  40. /**
  41. * @return \Pimcore\Model\Dao\AbstractDao
  42. */
  43. public function getDao()
  44. {
  45. if (!$this->dao) {
  46. $this->initDao();
  47. }
  48. return $this->dao;
  49. }
  50. /**
  51. * @param \Pimcore\Model\Dao\AbstractDao $dao
  52. *
  53. * @return self
  54. */
  55. public function setDao($dao)
  56. {
  57. $this->dao = $dao;
  58. return $this;
  59. }
  60. /**
  61. * @param string|null $key
  62. * @param bool $forceDetection
  63. *
  64. * @throws \Exception
  65. */
  66. public function initDao($key = null, $forceDetection = false)
  67. {
  68. $myClass = get_class($this);
  69. $cacheKey = $myClass . ($key ? ('-' . $key) : '');
  70. $dao = null;
  71. $myClass = $key ? $key : $myClass;
  72. if (null === self::$daoClassMap) {
  73. // static classmap is generated by command: ./bin/console internal:model-dao-mapping-generator
  74. self::$daoClassMap = include(__DIR__ . '/../../config/dao-classmap.php');
  75. }
  76. if (!$forceDetection && array_key_exists($cacheKey, self::$daoClassCache)) {
  77. $dao = self::$daoClassCache[$cacheKey];
  78. } elseif (!$key || $forceDetection) {
  79. if (isset(self::$daoClassMap[$myClass])) {
  80. $dao = self::$daoClassMap[$myClass];
  81. } else {
  82. $dao = self::locateDaoClass($myClass);
  83. }
  84. } else {
  85. $delimiter = '_'; // old prefixed class style
  86. if (str_contains($key, '\\') !== false) {
  87. $delimiter = '\\'; // that's the new with namespaces
  88. }
  89. $dao = $key . $delimiter . 'Dao';
  90. }
  91. if (!$dao) {
  92. Logger::critical('No dao implementation found for: ' . $myClass);
  93. throw new \Exception('No dao implementation found for: ' . $myClass);
  94. }
  95. self::$daoClassCache[$cacheKey] = $dao;
  96. $dao = '\\' . ltrim($dao, '\\');
  97. $this->dao = new $dao();
  98. $this->dao->setModel($this);
  99. $this->dao->configure();
  100. if (method_exists($this->dao, 'init')) {
  101. $this->dao->init();
  102. }
  103. }
  104. /**
  105. * @param string $modelClass
  106. *
  107. * @return string|null
  108. */
  109. public static function locateDaoClass($modelClass)
  110. {
  111. $forbiddenClassNames = ['Pimcore\\Resource'];
  112. $classes = class_parents($modelClass);
  113. array_unshift($classes, $modelClass);
  114. foreach ($classes as $class) {
  115. $delimiter = '_'; // old prefixed class style
  116. if (strpos($class, '\\')) {
  117. $delimiter = '\\'; // that's the new with namespaces
  118. }
  119. $classParts = explode($delimiter, $class);
  120. $length = count($classParts);
  121. $daoClass = null;
  122. for ($i = 0; $i < $length; $i++) {
  123. $classNames = [
  124. implode($delimiter, $classParts) . $delimiter . 'Dao',
  125. implode($delimiter, $classParts) . $delimiter . 'Resource',
  126. ];
  127. foreach ($classNames as $tmpClassName) {
  128. if (class_exists($tmpClassName) && !in_array($tmpClassName, $forbiddenClassNames)) {
  129. $daoClass = $tmpClassName;
  130. break;
  131. }
  132. }
  133. if ($daoClass) {
  134. break;
  135. }
  136. array_pop($classParts);
  137. }
  138. if ($daoClass) {
  139. return $daoClass;
  140. }
  141. }
  142. return null;
  143. }
  144. /**
  145. * @param array $data
  146. *
  147. * @return $this
  148. */
  149. public function setValues($data = [])
  150. {
  151. if (is_array($data) && count($data) > 0) {
  152. foreach ($data as $key => $value) {
  153. $this->setValue($key, $value);
  154. }
  155. }
  156. return $this;
  157. }
  158. /**
  159. * @param string $key
  160. * @param mixed $value
  161. *
  162. * @return $this
  163. */
  164. public function setValue($key, $value)
  165. {
  166. $method = 'set' . $key;
  167. if (strcasecmp($method, __FUNCTION__) !== 0) {
  168. if (method_exists($this, $method)) {
  169. $this->$method($value);
  170. } elseif (method_exists($this, 'set' . preg_replace('/^o_/', '', $key))) {
  171. // compatibility mode for objects (they do not have any set_oXyz() methods anymore)
  172. $this->$method($value);
  173. }
  174. }
  175. return $this;
  176. }
  177. /**
  178. * @return array
  179. */
  180. public function __sleep()
  181. {
  182. $blockedVars = ['dao', 'o_dirtyFields'];
  183. $vars = get_object_vars($this);
  184. return array_diff(array_keys($vars), $blockedVars);
  185. }
  186. /**
  187. * @param string $method
  188. * @param array $args
  189. *
  190. * @return mixed
  191. *
  192. * @throws \Exception
  193. */
  194. public function __call($method, $args)
  195. {
  196. // protected / private methods shouldn't be delegated to the dao -> this can have dangerous effects
  197. if (!is_callable([$this, $method])) {
  198. throw new \Exception("Unable to call private/protected method '" . $method . "' on object " . get_class($this));
  199. }
  200. // check if the method is defined in ´dao
  201. if (method_exists($this->getDao(), $method)) {
  202. try {
  203. $r = call_user_func_array([$this->getDao(), $method], $args);
  204. return $r;
  205. } catch (\Exception $e) {
  206. Logger::emergency($e);
  207. throw $e;
  208. }
  209. } else {
  210. Logger::error('Class: ' . get_class($this) . ' => call to undefined method ' . $method);
  211. throw new \Exception('Call to undefined method ' . $method . ' in class ' . get_class($this));
  212. }
  213. }
  214. public function __clone()
  215. {
  216. $this->dao = null;
  217. }
  218. /**
  219. * @return array
  220. */
  221. public function __debugInfo()
  222. {
  223. $result = get_object_vars($this);
  224. unset($result['dao']);
  225. return $result;
  226. }
  227. /**
  228. * @return Factory
  229. */
  230. protected static function getModelFactory()
  231. {
  232. return \Pimcore::getContainer()->get('pimcore.model.factory');
  233. }
  234. /**
  235. * @internal
  236. *
  237. * @param array $data
  238. *
  239. * @throws \Exception
  240. */
  241. protected static function checkCreateData(array $data)
  242. {
  243. if (isset($data['id'])) {
  244. throw new \Exception(sprintf('Calling %s including `id` key in the data-array is not supported, use setId() instead.', __METHOD__));
  245. }
  246. }
  247. }