Storage.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\MediaStorage\Model\File;
  7. use Magento\Framework\App\Filesystem\DirectoryList;
  8. use Magento\Framework\Filesystem;
  9. use Magento\Framework\Model\AbstractModel;
  10. /**
  11. * Class Storage
  12. *
  13. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  14. * @api
  15. * @since 100.0.2
  16. */
  17. class Storage extends AbstractModel
  18. {
  19. /**
  20. * Storage systems ids
  21. */
  22. const STORAGE_MEDIA_FILE_SYSTEM = 0;
  23. const STORAGE_MEDIA_DATABASE = 1;
  24. /**
  25. * Config paths for storing storage configuration
  26. */
  27. const XML_PATH_STORAGE_MEDIA = 'system/media_storage_configuration/media_storage';
  28. const XML_PATH_STORAGE_MEDIA_DATABASE = 'system/media_storage_configuration/media_database';
  29. const XML_PATH_MEDIA_RESOURCE_WHITELIST = 'system/media_storage_configuration/allowed_resources';
  30. const XML_PATH_MEDIA_UPDATE_TIME = 'system/media_storage_configuration/configuration_update_time';
  31. /**
  32. * Prefix of model events names
  33. *
  34. * @var string
  35. */
  36. protected $_eventPrefix = 'media_storage_file_storage';
  37. /**
  38. * Core file storage
  39. *
  40. * @var \Magento\MediaStorage\Helper\File\Storage
  41. */
  42. protected $_coreFileStorage = null;
  43. /**
  44. * Core store config
  45. *
  46. * @var \Magento\Framework\App\Config\ScopeConfigInterface
  47. */
  48. protected $_scopeConfig;
  49. /**
  50. * @var \Magento\Framework\App\Config\ScopeConfigInterface
  51. */
  52. protected $_coreConfig;
  53. /**
  54. * Core file storage flag
  55. *
  56. * @var \Magento\MediaStorage\Model\File\Storage\Flag
  57. */
  58. protected $_fileFlag;
  59. /**
  60. * File factory
  61. *
  62. * @var \Magento\MediaStorage\Model\File\Storage\FileFactory
  63. */
  64. protected $_fileFactory;
  65. /**
  66. * @var \Magento\MediaStorage\Model\File\Storage\DatabaseFactory
  67. */
  68. protected $_databaseFactory;
  69. /**
  70. * Filesystem instance
  71. *
  72. * @var Filesystem
  73. */
  74. protected $filesystem;
  75. /**
  76. * @param \Magento\Framework\Model\Context $context
  77. * @param \Magento\Framework\Registry $registry
  78. * @param \Magento\MediaStorage\Helper\File\Storage $coreFileStorage
  79. * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
  80. * @param \Magento\Framework\App\Config\ScopeConfigInterface $coreConfig
  81. * @param \Magento\MediaStorage\Model\File\Storage\Flag $fileFlag
  82. * @param \Magento\MediaStorage\Model\File\Storage\FileFactory $fileFactory
  83. * @param \Magento\MediaStorage\Model\File\Storage\DatabaseFactory $databaseFactory
  84. * @param Filesystem $filesystem
  85. * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
  86. * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
  87. * @param array $data
  88. * @SuppressWarnings(PHPMD.ExcessiveParameterList)
  89. */
  90. public function __construct(
  91. \Magento\Framework\Model\Context $context,
  92. \Magento\Framework\Registry $registry,
  93. \Magento\MediaStorage\Helper\File\Storage $coreFileStorage,
  94. \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
  95. \Magento\Framework\App\Config\ScopeConfigInterface $coreConfig,
  96. \Magento\MediaStorage\Model\File\Storage\Flag $fileFlag,
  97. \Magento\MediaStorage\Model\File\Storage\FileFactory $fileFactory,
  98. \Magento\MediaStorage\Model\File\Storage\DatabaseFactory $databaseFactory,
  99. Filesystem $filesystem,
  100. \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
  101. \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
  102. array $data = []
  103. ) {
  104. $this->_coreFileStorage = $coreFileStorage;
  105. $this->_scopeConfig = $scopeConfig;
  106. $this->_coreConfig = $coreConfig;
  107. $this->_fileFlag = $fileFlag;
  108. $this->_fileFactory = $fileFactory;
  109. $this->_databaseFactory = $databaseFactory;
  110. $this->filesystem = $filesystem;
  111. parent::__construct($context, $registry, $resource, $resourceCollection, $data);
  112. }
  113. /**
  114. * Show if there were errors while synchronize process
  115. *
  116. * @param \Magento\Framework\Model\AbstractModel $sourceModel
  117. * @param \Magento\Framework\Model\AbstractModel $destinationModel
  118. * @return bool
  119. */
  120. protected function _synchronizeHasErrors($sourceModel, $destinationModel)
  121. {
  122. if (!$sourceModel || !$destinationModel) {
  123. return true;
  124. }
  125. return $sourceModel->hasErrors() || $destinationModel->hasErrors();
  126. }
  127. /**
  128. * Return synchronize process status flag
  129. *
  130. * @return \Magento\MediaStorage\Model\File\Storage\Flag
  131. */
  132. public function getSyncFlag()
  133. {
  134. return $this->_fileFlag->loadSelf();
  135. }
  136. /**
  137. * Retrieve storage model
  138. * If storage not defined - retrieve current storage
  139. *
  140. * params = array(
  141. * connection => string, - define connection for model if needed
  142. * init => bool - force initialization process for storage model
  143. * )
  144. *
  145. * @param int|null $storage
  146. * @param array $params
  147. * @return AbstractModel|bool
  148. */
  149. public function getStorageModel($storage = null, $params = [])
  150. {
  151. if ($storage === null) {
  152. $storage = $this->_coreFileStorage->getCurrentStorageCode();
  153. }
  154. switch ($storage) {
  155. case self::STORAGE_MEDIA_FILE_SYSTEM:
  156. $model = $this->_fileFactory->create();
  157. break;
  158. case self::STORAGE_MEDIA_DATABASE:
  159. $connection = isset($params['connection']) ? $params['connection'] : null;
  160. $model = $this->_databaseFactory->create(['connectionName' => $connection]);
  161. break;
  162. default:
  163. return false;
  164. }
  165. if (isset($params['init']) && $params['init']) {
  166. $model->init();
  167. }
  168. return $model;
  169. }
  170. /**
  171. * Synchronize current media storage with defined
  172. * $storage = array(
  173. * type => int
  174. * connection => string
  175. * )
  176. *
  177. * @param array $storage
  178. * @return $this
  179. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  180. * @SuppressWarnings(PHPMD.NPathComplexity)
  181. */
  182. public function synchronize($storage)
  183. {
  184. if (is_array($storage) && isset($storage['type'])) {
  185. $storageDest = (int)$storage['type'];
  186. $connection = isset($storage['connection']) ? $storage['connection'] : null;
  187. $helper = $this->_coreFileStorage;
  188. // if unable to sync to internal storage from itself
  189. if ($storageDest == $helper->getCurrentStorageCode() && $helper->isInternalStorage()) {
  190. return $this;
  191. }
  192. $sourceModel = $this->getStorageModel();
  193. $destinationModel = $this->getStorageModel(
  194. $storageDest,
  195. ['connection' => $connection, 'init' => true]
  196. );
  197. if (!$sourceModel || !$destinationModel) {
  198. return $this;
  199. }
  200. $hasErrors = false;
  201. $flag = $this->getSyncFlag();
  202. $flagData = [
  203. 'source' => $sourceModel->getStorageName(),
  204. 'destination' => $destinationModel->getStorageName(),
  205. 'destination_storage_type' => $storageDest,
  206. 'destination_connection_name' => (string)$destinationModel->getConnectionName(),
  207. 'has_errors' => false,
  208. 'timeout_reached' => false,
  209. ];
  210. $flag->setFlagData($flagData);
  211. $destinationModel->clear();
  212. $offset = 0;
  213. while (($dirs = $sourceModel->exportDirectories($offset)) !== false) {
  214. $flagData['timeout_reached'] = false;
  215. if (!$hasErrors) {
  216. $hasErrors = $this->_synchronizeHasErrors($sourceModel, $destinationModel);
  217. if ($hasErrors) {
  218. $flagData['has_errors'] = true;
  219. }
  220. }
  221. $flag->setFlagData($flagData)->save();
  222. $destinationModel->importDirectories($dirs);
  223. $offset += count($dirs);
  224. }
  225. unset($dirs);
  226. $offset = 0;
  227. while (($files = $sourceModel->exportFiles($offset, 1)) !== false) {
  228. $flagData['timeout_reached'] = false;
  229. if (!$hasErrors) {
  230. $hasErrors = $this->_synchronizeHasErrors($sourceModel, $destinationModel);
  231. if ($hasErrors) {
  232. $flagData['has_errors'] = true;
  233. }
  234. }
  235. $flag->setFlagData($flagData)->save();
  236. $destinationModel->importFiles($files);
  237. $offset += count($files);
  238. }
  239. unset($files);
  240. }
  241. return $this;
  242. }
  243. /**
  244. * Return current media directory, allowed resources for get.php script, etc.
  245. *
  246. * @return array
  247. */
  248. public function getScriptConfig()
  249. {
  250. $config = [];
  251. $config['media_directory'] = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath();
  252. $allowedResources = $this->_coreConfig->getValue(self::XML_PATH_MEDIA_RESOURCE_WHITELIST, 'default');
  253. foreach ($allowedResources as $allowedResource) {
  254. $config['allowed_resources'][] = $allowedResource;
  255. }
  256. $config['update_time'] = $this->_scopeConfig->getValue(
  257. self::XML_PATH_MEDIA_UPDATE_TIME,
  258. \Magento\Store\Model\ScopeInterface::SCOPE_STORE
  259. );
  260. return $config;
  261. }
  262. }