_collectionFactory = $collectionFactory; $this->_themeCollection = $filesystemCollection; } /** * Theme registration * * @return $this */ public function register() { $this->_themeCollection->clear(); foreach ($this->_themeCollection as $theme) { $this->_registerThemeRecursively($theme); } $this->checkPhysicalThemes()->checkAllowedThemeRelations(); return $this; } /** * Register theme and recursively all its ascendants * Second param is optional and is used to prevent circular references in inheritance chain * * @param ThemeInterface &$theme * @param array $inheritanceChain * @return $this * @throws LocalizedException */ protected function _registerThemeRecursively(&$theme, $inheritanceChain = []) { if ($theme->getId()) { return $this; } $themeModel = $this->getThemeFromDb($theme->getFullPath()); if ($themeModel->getId()) { $theme = $themeModel; return $this; } $tempId = $theme->getFullPath(); if (in_array($tempId, $inheritanceChain)) { throw new LocalizedException(__('Circular-reference in theme inheritance detected for "%1"', $tempId)); } $inheritanceChain[] = $tempId; $parentTheme = $theme->getParentTheme(); if ($parentTheme) { $this->_registerThemeRecursively($parentTheme, $inheritanceChain); $theme->setParentId($parentTheme->getId()); } $this->_savePreviewImage($theme); $theme->setType(ThemeInterface::TYPE_PHYSICAL); $theme->save(); return $this; } /** * Save preview image for theme * * @param ThemeInterface $theme * @return $this */ protected function _savePreviewImage(ThemeInterface $theme) { $themeDirectory = $theme->getCustomization()->getThemeFilesPath(); if (!$theme->getPreviewImage() || !$themeDirectory) { return $this; } $imagePath = $themeDirectory . '/' . $theme->getPreviewImage(); if (0 === strpos($imagePath, $themeDirectory)) { $theme->getThemeImage()->createPreviewImage($imagePath); } return $this; } /** * Get theme from DB by full path * * @param string $fullPath * @return ThemeInterface */ public function getThemeFromDb($fullPath) { return $this->_collectionFactory->create()->getThemeByFullPath($fullPath); } /** * Checks all physical themes that they were not deleted * * @return $this */ public function checkPhysicalThemes() { $themes = $this->_collectionFactory->create()->addTypeFilter(ThemeInterface::TYPE_PHYSICAL); /** @var $theme ThemeInterface */ foreach ($themes as $theme) { if (!$this->_themeCollection->hasTheme($theme)) { $theme->setType(ThemeInterface::TYPE_VIRTUAL)->save(); } } return $this; } /** * Check whether all themes have correct parent theme by type * * @return $this */ public function checkAllowedThemeRelations() { foreach ($this->_forbiddenRelations as $typesSequence) { list($parentType, $childType) = $typesSequence; $collection = $this->_collectionFactory->create(); $collection->addTypeRelationFilter($parentType, $childType); /** @var $theme ThemeInterface */ foreach ($collection as $theme) { $parentId = $this->_getResetParentId($theme); if ($theme->getParentId() != $parentId) { $theme->setParentId($parentId)->save(); } } } return $this; } /** * Reset parent themes by type * * @param ThemeInterface $theme * @return int|null */ protected function _getResetParentId(ThemeInterface $theme) { $parentTheme = $theme->getParentTheme(); while ($parentTheme) { foreach ($this->_allowedRelations as $typesSequence) { list($parentType, $childType) = $typesSequence; if ($theme->getType() == $childType && $parentTheme->getType() == $parentType) { return $parentTheme->getId(); } } $parentTheme = $parentTheme->getParentTheme(); } return null; } }