/bitrix/modules/highloadblock/lib/datamanager.php

https://gitlab.com/Rad1calDreamer/honey · PHP · 460 lines · 310 code · 82 blank · 68 comment · 28 complexity · 4db5844c917984c95b7ade3ed72309ec MD5 · raw file

  1. <?php
  2. /**
  3. * Bitrix Framework
  4. * @package bitrix
  5. * @subpackage highloadblock
  6. * @copyright 2001-2014 Bitrix
  7. */
  8. namespace Bitrix\Highloadblock;
  9. use Bitrix\Main;
  10. use Bitrix\Main\Entity;
  11. use Bitrix\Main\Type;
  12. abstract class DataManager extends Entity\DataManager
  13. {
  14. /**
  15. * Being redefined in HL classes
  16. * @return null
  17. */
  18. public static function getHighloadBlock()
  19. {
  20. return null;
  21. }
  22. public static function checkFields(Entity\Result $result, $primary, array $data)
  23. {
  24. // check for unknown fields
  25. foreach ($data as $k => $v)
  26. {
  27. if (!(static::getEntity()->hasField($k) && static::getEntity()->getField($k) instanceof Entity\ScalarField))
  28. {
  29. throw new Main\SystemException(sprintf(
  30. 'Field `%s` not found in entity when trying to query %s row.',
  31. $k, static::getEntity()->getName()
  32. ));
  33. }
  34. }
  35. }
  36. /**
  37. * @param array $data
  38. *
  39. * @return Entity\AddResult
  40. */
  41. public static function add(array $data)
  42. {
  43. global $USER_FIELD_MANAGER, $APPLICATION;
  44. $result = new Entity\AddResult;
  45. $hlblock = static::getHighloadBlock();
  46. $entity = static::getEntity();
  47. //event before adding
  48. $event = new Entity\Event($entity, self::EVENT_ON_BEFORE_ADD, array("fields"=>$data));
  49. $event->send();
  50. $event->getErrors($result);
  51. $data = $event->mergeFields($data);
  52. //event before adding (modern with namespace)
  53. $event = new Entity\Event($entity, self::EVENT_ON_BEFORE_ADD, array("fields"=>$data), true);
  54. $event->send();
  55. $event->getErrors($result);
  56. $data = $event->mergeFields($data);
  57. // check data by uf manager
  58. if (!$USER_FIELD_MANAGER->checkFields('HLBLOCK_'.$hlblock['ID'], null, $data))
  59. {
  60. if(is_object($APPLICATION) && $APPLICATION->getException())
  61. {
  62. $e = $APPLICATION->getException();
  63. $result->addError(new Entity\EntityError($e->getString()));
  64. $APPLICATION->resetException();
  65. }
  66. else
  67. {
  68. $result->addError(new Entity\EntityError("Unknown error while checking userfields"));
  69. }
  70. }
  71. // return if any error
  72. if (!$result->isSuccess(true))
  73. {
  74. return $result;
  75. }
  76. //event on adding
  77. $event = new Entity\Event($entity, self::EVENT_ON_ADD, array("fields"=>$data));
  78. $event->send();
  79. //event on adding (modern with namespace)
  80. $event = new Entity\Event($entity, self::EVENT_ON_ADD, array("fields"=>$data), true);
  81. $event->send();
  82. // format data before save
  83. $fields = $USER_FIELD_MANAGER->getUserFields('HLBLOCK_'.$hlblock['ID']);
  84. list($data, $multiValues) = static::convertValuesBeforeSave($data, $fields);
  85. // use save modifiers
  86. foreach ($data as $fieldName => $value)
  87. {
  88. $field = static::getEntity()->getField($fieldName);
  89. $data[$fieldName] = $field->modifyValueBeforeSave($value, $data);
  90. }
  91. // save data
  92. $connection = Main\Application::getConnection();
  93. $tableName = $entity->getDBTableName();
  94. $identity = $entity->getAutoIncrement();
  95. $id = $connection->add($tableName, $data, $identity);
  96. $result->setId($id);
  97. $result->setData($data);
  98. // save multi values
  99. if (!empty($multiValues))
  100. {
  101. foreach ($multiValues as $userfieldName => $values)
  102. {
  103. $utmTableName = HighloadBlockTable::getMultipleValueTableName($hlblock, $fields[$userfieldName]);
  104. foreach ($values as $value)
  105. {
  106. $connection->add($utmTableName, array('ID' => $id, 'VALUE' => $value));
  107. }
  108. }
  109. }
  110. // build stamdard primary
  111. $primary = null;
  112. if (!empty($id))
  113. {
  114. $primary = $id;
  115. static::normalizePrimary($primary);
  116. }
  117. else
  118. {
  119. static::normalizePrimary($primary, $data);
  120. }
  121. //event after adding
  122. $event = new Entity\Event($entity, self::EVENT_ON_AFTER_ADD, array("id"=>$id, "fields"=>$data));
  123. $event->send();
  124. //event after adding (modern with namespace)
  125. $event = new Entity\Event($entity, self::EVENT_ON_AFTER_ADD, array("id"=>$id, "primary"=>$primary, "fields"=>$data), true);
  126. $event->send();
  127. return $result;
  128. }
  129. /**
  130. * @param mixed $primary
  131. * @param array $data
  132. *
  133. * @return Entity\UpdateResult
  134. */
  135. public static function update($primary, array $data)
  136. {
  137. global $USER_FIELD_MANAGER, $APPLICATION;
  138. $result = new Entity\UpdateResult();
  139. static::normalizePrimary($primary, $data);
  140. static::validatePrimary($primary);
  141. $oldData = static::getByPrimary($primary)->fetch();
  142. $hlblock = static::getHighloadBlock();
  143. $entity = static::getEntity();
  144. //event before update
  145. $event = new Entity\Event($entity, self::EVENT_ON_BEFORE_UPDATE, array("id"=>$primary, "fields"=>$data));
  146. $event->send();
  147. $event->getErrors($result);
  148. $data = $event->mergeFields($data);
  149. //event before update (modern with namespace)
  150. $event = new Entity\Event($entity, self::EVENT_ON_BEFORE_UPDATE, array(
  151. "id"=>$primary, "primary"=>$primary, "fields"=>$data, "oldFields" => $oldData
  152. ), true);
  153. $event->send();
  154. $event->getErrors($result);
  155. $data = $event->mergeFields($data);
  156. // check data by uf manager CheckFieldsWithOldData
  157. if (!$USER_FIELD_MANAGER->checkFieldsWithOldData('HLBLOCK_'.$hlblock['ID'], $oldData, $data))
  158. {
  159. if(is_object($APPLICATION) && $APPLICATION->getException())
  160. {
  161. $e = $APPLICATION->getException();
  162. $result->addError(new Entity\EntityError($e->getString()));
  163. $APPLICATION->resetException();
  164. }
  165. else
  166. {
  167. $result->addError(new Entity\EntityError("Unknown error while checking userfields"));
  168. }
  169. }
  170. // return if any error
  171. if (!$result->isSuccess(true))
  172. {
  173. return $result;
  174. }
  175. //event on update
  176. $event = new Entity\Event($entity, self::EVENT_ON_UPDATE, array("id"=>$primary, "fields"=>$data));
  177. $event->send();
  178. //event on update (modern with namespace)
  179. $event = new Entity\Event($entity, self::EVENT_ON_UPDATE, array(
  180. "id"=>$primary, "primary"=>$primary, "fields"=>$data, "oldFields" => $oldData
  181. ), true);
  182. $event->send();
  183. // format data before save
  184. $fields = $USER_FIELD_MANAGER->getUserFieldsWithReadyData('HLBLOCK_'.$hlblock['ID'], $oldData, LANGUAGE_ID, false, 'ID');
  185. list($data, $multiValues) = static::convertValuesBeforeSave($data, $fields);
  186. // use save modifiers
  187. foreach ($data as $fieldName => $value)
  188. {
  189. $field = static::getEntity()->getField($fieldName);
  190. $data[$fieldName] = $field->modifyValueBeforeSave($value, $data);
  191. }
  192. // save data
  193. $connection = Main\Application::getConnection();
  194. $helper = $connection->getSqlHelper();
  195. $tableName = $entity->getDBTableName();
  196. $update = $helper->prepareUpdate($tableName, $data);
  197. $id = array();
  198. foreach ($primary as $k => $v)
  199. {
  200. $id[] = $helper->prepareAssignment($tableName, $k, $v);
  201. }
  202. $where = implode(' AND ', $id);
  203. $sql = "UPDATE ".$tableName." SET ".$update[0]." WHERE ".$where;
  204. $connection->queryExecute($sql, $update[1]);
  205. $result->setAffectedRowsCount($connection);
  206. $result->setData($data);
  207. $result->setPrimary($primary);
  208. // save multi values
  209. if (!empty($multiValues))
  210. {
  211. foreach ($multiValues as $userfieldName => $values)
  212. {
  213. $utmTableName = HighloadBlockTable::getMultipleValueTableName($hlblock, $fields[$userfieldName]);
  214. // first, delete old values
  215. $connection->query(sprintf(
  216. 'DELETE FROM %s WHERE %s = %d',
  217. $helper->quote($utmTableName), $helper->quote('ID'), $primary['ID']
  218. ));
  219. // insert new values
  220. foreach ($values as $value)
  221. {
  222. $connection->add($utmTableName, array('ID' => $primary['ID'], 'VALUE' => $value));
  223. }
  224. }
  225. }
  226. //event after update
  227. $event = new Entity\Event($entity, self::EVENT_ON_AFTER_UPDATE, array("id"=>$primary, "fields"=>$data));
  228. $event->send();
  229. //event after update (modern with namespace)
  230. $event = new Entity\Event($entity, self::EVENT_ON_AFTER_UPDATE, array(
  231. "id"=>$primary, "primary"=>$primary, "fields"=>$data, "oldFields" => $oldData
  232. ), true);
  233. $event->send();
  234. return $result;
  235. }
  236. /**
  237. * @param mixed $primary
  238. *
  239. * @return Entity\DeleteResult
  240. */
  241. public static function delete($primary)
  242. {
  243. global $USER_FIELD_MANAGER;
  244. // check primary
  245. static::normalizePrimary($primary);
  246. static::validatePrimary($primary);
  247. // get old data
  248. $oldData = static::getByPrimary($primary)->fetch();
  249. $hlblock = static::getHighloadBlock();
  250. $entity = static::getEntity();
  251. $result = new Entity\DeleteResult();
  252. //event before delete
  253. $event = new Entity\Event($entity, self::EVENT_ON_BEFORE_DELETE, array("id"=>$primary));
  254. $event->send();
  255. $event->getErrors($result);
  256. //event before delete (modern with namespace)
  257. $event = new Entity\Event($entity, self::EVENT_ON_BEFORE_DELETE, array(
  258. "id"=>$primary, "primary"=>$primary, "oldFields" => $oldData
  259. ), true);
  260. $event->send();
  261. $event->getErrors($result);
  262. // return if any error
  263. if (!$result->isSuccess(true))
  264. {
  265. return $result;
  266. }
  267. //event on delete
  268. $event = new Entity\Event($entity, self::EVENT_ON_DELETE, array("id"=>$primary));
  269. $event->send();
  270. //event on delete (modern with namespace)
  271. $event = new Entity\Event($entity, self::EVENT_ON_DELETE, array(
  272. "id"=>$primary, "primary"=>$primary, "oldFields" => $oldData
  273. ), true);
  274. $event->send();
  275. // remove row
  276. $connection = Main\Application::getConnection();
  277. $helper = $connection->getSqlHelper();
  278. $tableName = $entity->getDBTableName();
  279. $id = array();
  280. foreach ($primary as $k => $v)
  281. {
  282. $id[] = $k." = '".$helper->forSql($v)."'";
  283. }
  284. $where = implode(' AND ', $id);
  285. $sql = "DELETE FROM ".$tableName." WHERE ".$where;
  286. $connection->queryExecute($sql);
  287. $fields = $USER_FIELD_MANAGER->getUserFields('HLBLOCK_'.$hlblock['ID']);
  288. foreach ($oldData as $k => $v)
  289. {
  290. $userfield = $fields[$k];
  291. // remove multi values
  292. if ($userfield['MULTIPLE'] == 'Y')
  293. {
  294. $utmTableName = HighloadBlockTable::getMultipleValueTableName($hlblock, $userfield);
  295. $connection->query(sprintf(
  296. 'DELETE FROM %s WHERE %s = %d',
  297. $helper->quote($utmTableName), $helper->quote('ID'), $primary['ID']
  298. ));
  299. }
  300. // remove files
  301. if ($userfield["USER_TYPE"]["BASE_TYPE"]=="file")
  302. {
  303. if(is_array($oldData[$k]))
  304. {
  305. foreach($oldData[$k] as $value)
  306. {
  307. \CFile::delete($value);
  308. }
  309. }
  310. else
  311. {
  312. \CFile::delete($oldData[$k]);
  313. }
  314. }
  315. }
  316. //event after delete
  317. $event = new Entity\Event($entity, self::EVENT_ON_AFTER_DELETE, array("id"=>$primary));
  318. $event->send();
  319. //event after delete (modern with namespace)
  320. $event = new Entity\Event($entity, self::EVENT_ON_AFTER_DELETE, array(
  321. "id"=>$primary, "primary" => $primary, "oldFields" => $oldData
  322. ), true);
  323. $event->send();
  324. return $result;
  325. }
  326. protected function convertValuesBeforeSave($data, $userfields)
  327. {
  328. $multiValues = array();
  329. foreach ($data as $k => $v)
  330. {
  331. if ($k == 'ID')
  332. {
  333. continue;
  334. }
  335. $userfield = $userfields[$k];
  336. if ($userfield['MULTIPLE'] == 'N')
  337. {
  338. $inputValue = array($v);
  339. }
  340. else
  341. {
  342. $inputValue = $v;
  343. }
  344. $tmpValue = array();
  345. foreach ($inputValue as $singleValue)
  346. {
  347. $tmpValue[] = static::convertSingleValueBeforeSave($singleValue, $userfield);
  348. }
  349. // write value back
  350. if ($userfield['MULTIPLE'] == 'N')
  351. {
  352. $data[$k] = $tmpValue[0];
  353. }
  354. else
  355. {
  356. // remove empty (false) values
  357. $tmpValue = array_filter($tmpValue, 'strlen');
  358. $data[$k] = $tmpValue;
  359. $multiValues[$k] = $tmpValue;
  360. }
  361. }
  362. return array($data, $multiValues);
  363. }
  364. protected function convertSingleValueBeforeSave($value, $userfield)
  365. {
  366. if(is_callable(array($userfield["USER_TYPE"]["CLASS_NAME"], "onbeforesave")))
  367. {
  368. $value = call_user_func_array(
  369. array($userfield["USER_TYPE"]["CLASS_NAME"], "onbeforesave"), array($userfield, $value)
  370. );
  371. }
  372. if(strlen($value)<=0)
  373. {
  374. $value = false;
  375. }
  376. return $value;
  377. }
  378. }