PageRenderTime 26ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/application/modules/exchange/classes/Categories.php

https://github.com/imagecms/ImageCMS
PHP | 302 lines | 176 code | 44 blank | 82 comment | 23 complexity | 6ded335317351287d066d5d4f40085b1 MD5 | raw file
  1. <?php
  2. namespace exchange\classes;
  3. use CMSFactory\ModuleSettings;
  4. use core\models\Route;
  5. use core\models\RouteQuery;
  6. use Propel\Runtime\Exception\PropelException;
  7. /**
  8. *
  9. *
  10. *
  11. * @author kolia
  12. */
  13. final class Categories extends ExchangeBase
  14. {
  15. /**
  16. *
  17. * @var array
  18. */
  19. private $categoriesNames = [];
  20. /**
  21. * Parsed categories from XML to one-dimension array
  22. * @var array
  23. */
  24. private $categoriesXml = [];
  25. /**
  26. *
  27. * @var array
  28. */
  29. private $existing = [];
  30. /**
  31. *
  32. */
  33. private $externalIds;
  34. /**
  35. *
  36. * @var array
  37. */
  38. private $new = [];
  39. /**
  40. * Check if category exists (by external id) (helper)
  41. * @param string $externalId
  42. * @param boolean $returnCategoryId if TRUE, then method will return id of category
  43. * @return boolean|int FALSE if category is new, TRUE otherwise
  44. */
  45. public function categoryExists2($externalId, $returnCategoryId = FALSE) {
  46. if (null === $this->externalIds) {
  47. $this->externalIds = [];
  48. foreach ($this->categories as $categoryId => $categoryData) {
  49. if (!empty($categoryData['external_id'])) {
  50. $this->externalIds[$categoryData['external_id']] = $categoryId;
  51. }
  52. }
  53. }
  54. $exists = isset($this->externalIds[$externalId]);
  55. if ($exists == TRUE) {
  56. return $returnCategoryId !== TRUE ? TRUE : $this->externalIds[$externalId];
  57. }
  58. return FALSE;
  59. }
  60. /**
  61. * Starting import of the categories
  62. * @return boolean|array FALSE|array(count of inserted, count of deleted)
  63. * @throws \Exception
  64. */
  65. protected function import_() {
  66. // getting categories names for checking fr unique names
  67. $categoriesI18n = $this->db
  68. ->where('locale', \MY_Controller::getCurrentLocale())
  69. ->get('shop_category_i18n')
  70. ->result_array();
  71. /** @var array $categoriesI18n */
  72. foreach ($categoriesI18n as $category) {
  73. array_push($this->categoriesNames, $category['name']);
  74. }
  75. // creating one-dimention array of categories
  76. $this->processCategories($this->importData);
  77. // inserting
  78. $insertCount = count($this->new);
  79. if ($insertCount > 0) {
  80. $dbArray = $this->getPreparedData($this->new);
  81. $this->insertBatch('shop_category', $dbArray);
  82. $this->dataLoad->getNewData('categories');
  83. $i18nData = $this->getI18nData($this->new);
  84. $this->insertBatch('shop_category_i18n', $i18nData);
  85. }
  86. $ignoreExisting = ModuleSettings::ofModule('exchange')->get('ignore_existing');
  87. // updating
  88. $updateCount = count($this->existing);
  89. if ($updateCount > 0 && !isset($ignoreExisting['categories'])) {
  90. $dbArray = $this->getPreparedData($this->existing);
  91. $this->updateBatch('shop_category', $dbArray, 'external_id');
  92. $this->dataLoad->getNewData('categories');
  93. $i18nData = $this->getI18nData($this->existing);
  94. $this->updateBatch('shop_category_i18n', $i18nData, 'id');
  95. }
  96. $pathsAndParents = $this->getPathsAndParents();
  97. $this->updateBatch('shop_category', $pathsAndParents, 'id');
  98. $this->dataLoad->getNewData('categories');
  99. }
  100. /**
  101. * Creates one-dimension array with categories from XML-file
  102. * (method is filling $categories, $new and $existing arrays of class instance)
  103. * @param \SimpleXMLElement $categories
  104. * @param string $parent (default null) external id of parent if there is
  105. */
  106. private function processCategories(\SimpleXMLElement $categories, $parent = NULL) {
  107. foreach ($categories as $category) {
  108. $externalId = (string) $category->Ид;
  109. // splitting on those which need to be updated and new (by external id)
  110. if (FALSE == $this->categoryExists($externalId)) {
  111. $this->new[] = $externalId;
  112. $name = $this->getCategoryName((string) $category->Наименование);
  113. } else {
  114. $this->existing[] = $externalId;
  115. $name = (string) $category->Наименование;
  116. }
  117. $this->categoriesXml[$externalId] = [
  118. 'name' => $name,
  119. 'active' => (string) $category->Статус === 'Удален' ? 0 : 1,
  120. 'external_id' => $externalId,
  121. 'parent_external_id' => $parent === null ? 0 : $parent,
  122. ];
  123. if (isset($category->Группы)) {
  124. $this->processCategories($category->Группы->Группа, $externalId);
  125. }
  126. }
  127. }
  128. /**
  129. * Check if category exists (by external id) (helper)
  130. * @param string $externalId
  131. * @return boolean FALSE if category is new, FALSE otherwise
  132. */
  133. public function categoryExists($externalId) {
  134. foreach ($this->categories as $categoryId => $categoryData) {
  135. if ($externalId == $categoryData['external_id']) {
  136. return TRUE;
  137. }
  138. }
  139. return FALSE;
  140. }
  141. /**
  142. * @param string $name
  143. * @return string
  144. */
  145. private function getCategoryName($name) {
  146. $nameTemp = $name;
  147. $i = 1;
  148. while (in_array($nameTemp, $this->categoriesNames, true)) {
  149. $nameTemp = $name . ' ' . $i++;
  150. }
  151. array_push($this->categoriesNames, $nameTemp);
  152. return $nameTemp;
  153. }
  154. /**
  155. * Prepare array for DB insert/update query
  156. * (returns array ready to inserting in database)
  157. * @param array $categoriesExternalIds
  158. * @return array
  159. */
  160. private function getPreparedData(array $categoriesExternalIds) {
  161. $dbArray = [];
  162. foreach ($categoriesExternalIds as $externalId) {
  163. // fitment of category url (might be busy)
  164. // preparing array for insert
  165. $dbArray[] = [
  166. 'external_id' => $externalId,
  167. 'active' => $this->categoriesXml[$externalId]['active'],
  168. ];
  169. }
  170. return $dbArray;
  171. }
  172. /**
  173. * @param array $categoriesExternalIds
  174. * @return array
  175. */
  176. private function getI18nData($categoriesExternalIds) {
  177. $i18n = [];
  178. foreach ($this->categories as $categoryId => $categoryData) {
  179. if (in_array($categoryData['external_id'], $categoriesExternalIds, true)) {
  180. $i18n[] = [
  181. 'id' => $categoryData['id'],
  182. 'locale' => $this->locale,
  183. 'name' => $this->categoriesXml[$categoryData['external_id']]['name'],
  184. ];
  185. }
  186. }
  187. return $i18n;
  188. }
  189. /**
  190. * Filling parent ids of
  191. * @return array
  192. */
  193. private function getPathsAndParents() {
  194. $categoriesExternalIds = array_merge($this->new, $this->existing);
  195. // UPDATING INSERTED CATEGORIES (add parent ids & full path)
  196. $this->dataLoad->getNewData('categories'); // getting categories form db again
  197. // getting only categories which was inserted
  198. $categories = [];
  199. // "parent data" is in $this->categories (db),
  200. foreach ($this->categories as $categoryId => $categoryData) {
  201. if (in_array($categoryData['external_id'], $categoriesExternalIds, true)) {
  202. $categories[$categoryData['id']] = [
  203. 'id' => $categoryData['id'],
  204. 'parent_id' => $this->getParentIdDb($categoryData['external_id']),
  205. 'external_id' => $categoryData['external_id'],
  206. ];
  207. }
  208. }
  209. // creating id-paths and url-paths of each category
  210. foreach ($categories as $categoryId => $categoryData) {
  211. $currentPathIds = [];
  212. $neededCid = $categoryData['parent_id'];
  213. while ($neededCid != 0) {
  214. $currentPathIds[] = $neededCid;
  215. $neededCid = $categories[$neededCid]['parent_id'];
  216. }
  217. $parentUrl = RouteQuery::create()->filterByEntityId($categoryData['parent_id'])->filterByType(Route::TYPE_SHOP_CATEGORY)->findOne();
  218. try {
  219. $route = RouteQuery::create()
  220. ->filterByType(Route::TYPE_SHOP_CATEGORY)
  221. ->filterByEntityId($categoryData['id'])
  222. ->findOne();
  223. if (!$route) {
  224. $route = new Route();
  225. $route->setParentUrl($parentUrl ? $parentUrl->getFullUrl() : '')
  226. ->setUrl(translit_url($this->categoriesXml[$categoryData['external_id']]['name']))
  227. ->setType(Route::TYPE_SHOP_CATEGORY)
  228. ->setEntityId($categoryData['id'])
  229. ->save();
  230. }
  231. } catch (PropelException $exp) {
  232. echo $exp->getPrevious()->getMessage();
  233. } catch (\Exception $exp) {
  234. echo $exp->getMessage();
  235. }
  236. $categories[$categoryId]['route_id'] = $route->getId();
  237. $categories[$categoryId]['full_path_ids'] = serialize(array_reverse($currentPathIds));
  238. }
  239. return $categories;
  240. }
  241. /**
  242. * Returning DB id of category by external_id (helper)
  243. * @param string $externalId
  244. * @return int|boolean id (DB primary key) of category|FALSE
  245. */
  246. private function getParentIdDb($externalId) {
  247. $parentExternalId = $this->categoriesXml[$externalId]['parent_external_id'];
  248. if ((string) $parentExternalId == '0') {
  249. return 0;
  250. }
  251. foreach ($this->categories as $categoryData) {
  252. if ($parentExternalId == $categoryData['external_id']) {
  253. return $categoryData['id'];
  254. }
  255. }
  256. return 0;
  257. }
  258. }