Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
File.php
Go to the documentation of this file.
1 <?php
8 
12 use Magento\Catalog\Model\Product\Exception as ProductException;
15 
22 class File extends \Magento\Catalog\Model\Product\Option\Type\DefaultType
23 {
28  protected $_customOptionDownloadUrl = 'sales/download/downloadCustomOption';
29 
33  protected $_formattedOptionValue = null;
34 
40  protected $_rootDirectory;
41 
45  private $mediaDirectory;
46 
52  protected $_coreFileStorageDatabase = null;
53 
57  protected $_escaper;
58 
64  protected $_urlBuilder;
65 
72 
76  protected $validatorInfo;
77 
81  protected $validatorFile;
82 
86  private $serializer;
87 
91  private $filesystem;
92 
107  public function __construct(
108  \Magento\Checkout\Model\Session $checkoutSession,
109  \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
110  \Magento\Quote\Model\Quote\Item\OptionFactory $itemOptionFactory,
111  \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDatabase,
112  \Magento\Catalog\Model\Product\Option\Type\File\ValidatorInfo $validatorInfo,
113  \Magento\Catalog\Model\Product\Option\Type\File\ValidatorFile $validatorFile,
114  \Magento\Catalog\Model\Product\Option\UrlBuilder $urlBuilder,
115  \Magento\Framework\Escaper $escaper,
116  array $data = [],
117  Filesystem $filesystem = null,
118  Json $serializer = null
119  ) {
120  $this->_itemOptionFactory = $itemOptionFactory;
121  $this->_urlBuilder = $urlBuilder;
122  $this->_escaper = $escaper;
123  $this->_coreFileStorageDatabase = $coreFileStorageDatabase;
124  $this->filesystem = $filesystem ?: \Magento\Framework\App\ObjectManager::getInstance()->get(Filesystem::class);
126  $this->_rootDirectory = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA);
127  $this->mediaDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA);
128  $this->validatorInfo = $validatorInfo;
129  $this->validatorFile = $validatorFile;
130  $this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class);
131  parent::__construct($checkoutSession, $scopeConfig, $data);
132  }
133 
139  public function isCustomizedView()
140  {
141  return true;
142  }
143 
150  public function getCustomizedView($optionInfo)
151  {
152  try {
153  if (isset($optionInfo['option_value'])) {
154  return $this->_getOptionHtml($optionInfo['option_value']);
155  } elseif (isset($optionInfo['value'])) {
156  return $optionInfo['value'];
157  }
158  } catch (\Exception $e) {
159  return $optionInfo['value'];
160  }
161  }
162 
168  protected function _getProcessingParams()
169  {
170  $buyRequest = $this->getRequest();
171  $params = $buyRequest->getData('_processing_params');
172  /*
173  * Notice check for params to be \Magento\Framework\DataObject - by using object we protect from
174  * params being forged and contain data from user frontend input
175  */
176  if ($params instanceof \Magento\Framework\DataObject) {
177  return $params;
178  }
179  return new \Magento\Framework\DataObject();
180  }
181 
188  protected function _getCurrentConfigFileInfo()
189  {
190  $option = $this->getOption();
191  $optionId = $option->getId();
192  $processingParams = $this->_getProcessingParams();
193  $buyRequest = $this->getRequest();
194 
195  // Check maybe restore file from config requested
196  $optionActionKey = 'options_' . $optionId . '_file_action';
197  if ($buyRequest->getData($optionActionKey) == 'save_old') {
198  $fileInfo = [];
199  $currentConfig = $processingParams->getCurrentConfig();
200  if ($currentConfig) {
201  $fileInfo = $currentConfig->getData('options/' . $optionId);
202  }
203  return $fileInfo;
204  }
205  return null;
206  }
207 
217  public function validateUserValue($values)
218  {
219  $this->_checkoutSession->setUseNotice(false);
220 
221  $this->setIsValid(true);
222  $option = $this->getOption();
223 
224  /*
225  * Check whether we receive uploaded file or restore file by: reorder/edit configuration or
226  * previous configuration with no newly uploaded file
227  */
228  $fileInfo = null;
229  if (isset($values[$option->getId()]) && is_array($values[$option->getId()])) {
230  // Legacy style, file info comes in array with option id index
231  $fileInfo = $values[$option->getId()];
232  } else {
233  /*
234  * New recommended style - file info comes in request processing parameters and we
235  * sure that this file info originates from Magento, not from manually formed POST request
236  */
238  }
239  if ($fileInfo !== null) {
240  try {
241  $value = $this->validatorInfo->setUseQuotePath($this->getUseQuotePath())
242  ->validate($fileInfo, $option) ? $fileInfo : null;
243  $this->setUserValue($value);
244  return $this;
245  } catch (LocalizedException $exception) {
246  $this->setIsValid(false);
247  throw $exception;
248  }
249  }
250 
251  // Process new uploaded file
252  try {
253  $value = $this->validatorFile->setProduct($this->getProduct())
254  ->validate($this->_getProcessingParams(), $option);
255  $this->setUserValue($value);
256  } catch (ProductException $e) {
257  switch ($this->getProcessMode()) {
258  case \Magento\Catalog\Model\Product\Type\AbstractType::PROCESS_MODE_FULL:
259  throw new LocalizedException(
260  __(
261  "The product's required option(s) weren't entered. "
262  . "Make sure the options are entered and try again."
263  )
264  );
265  break;
266  default:
267  $this->setUserValue(null);
268  break;
269  }
270  } catch (\Magento\Framework\Validator\Exception $e) {
271  $this->setUserValue(null);
272  } catch (LocalizedException $e) {
273  $this->setIsValid(false);
274  throw new LocalizedException(__($e->getMessage()));
275  } catch (\Exception $e) {
276  if ($this->getSkipCheckRequiredOption()) {
277  $this->setUserValue(null);
278  } else {
279  throw new LocalizedException(__($e->getMessage()));
280  }
281  }
282  return $this;
283  }
284 
290  public function prepareForCart()
291  {
292  $option = $this->getOption();
293  $optionId = $option->getId();
294  $buyRequest = $this->getRequest();
295 
296  // Prepare value and fill buyRequest with option
297  $requestOptions = $buyRequest->getOptions();
298  if ($this->getIsValid() && $this->getUserValue() !== null) {
299  $value = $this->getUserValue();
300 
301  // Save option in request, because we have no $_FILES['options']
302  $requestOptions[$this->getOption()->getId()] = $value;
303  $result = $this->serializer->serialize($value);
304  } else {
305  /*
306  * Clear option info from request, so it won't be stored in our db upon
307  * unsuccessful validation. Otherwise some bad file data can happen in buyRequest
308  * and be used later in reorders and reconfigurations.
309  */
310  if (is_array($requestOptions)) {
311  unset($requestOptions[$this->getOption()->getId()]);
312  }
313  $result = null;
314  }
315  $buyRequest->setOptions($requestOptions);
316 
317  // Clear action key from buy request - we won't need it anymore
318  $optionActionKey = 'options_' . $optionId . '_file_action';
319  $buyRequest->unsetData($optionActionKey);
320 
321  return $result;
322  }
323 
331  {
332  if ($this->_formattedOptionValue === null) {
333  $value = $this->serializer->unserialize($optionValue);
334  if ($value === null) {
335  return $optionValue;
336  }
337  $customOptionUrlParams = $this->getCustomOptionUrlParams()
338  ? $this->getCustomOptionUrlParams()
339  : [
340  'id' => $this->getConfigurationItemOption()->getId(),
341  'key' => $value['secret_key']
342  ];
343 
344  $value['url'] = ['route' => $this->_customOptionDownloadUrl, 'params' => $customOptionUrlParams];
345 
346  $this->_formattedOptionValue = $this->_getOptionHtml($value);
347  $this->getConfigurationItemOption()->setValue($this->serializer->serialize($value));
348  }
350  }
351 
359  protected function _getOptionHtml($optionValue)
360  {
362  try {
363  $sizes = $this->prepareSize($value);
364 
365  $urlRoute = !empty($value['url']['route']) ? $value['url']['route'] : '';
366  $urlParams = !empty($value['url']['params']) ? $value['url']['params'] : '';
367  $title = !empty($value['title']) ? $value['title'] : '';
368 
369  return sprintf(
370  '<a href="%s" target="_blank">%s</a> %s',
371  $this->_getOptionDownloadUrl($urlRoute, $urlParams),
372  $this->_escaper->escapeHtml($title),
373  $sizes
374  );
375  } catch (\Exception $e) {
376  throw new LocalizedException(__('The file options format is invalid. Use a correct format and try again.'));
377  }
378  }
379 
386  protected function _unserializeValue($value)
387  {
388  if (is_array($value)) {
389  return $value;
390  } elseif (is_string($value) && !empty($value)) {
391  return $this->serializer->unserialize($value);
392  } else {
393  return [];
394  }
395  }
396 
404  {
405  return strip_tags($this->getFormattedOptionValue($optionValue));
406  }
407 
417  {
418  $unserializedValue = $this->serializer->unserialize($optionValue);
419  if ($unserializedValue !== null) {
420  return sprintf(
421  '%s [%d]',
422  $this->_escaper->escapeHtml($unserializedValue['title']),
423  $this->getConfigurationItemOption()->getId()
424  );
425  }
426  return $optionValue;
427  }
428 
440  public function parseOptionValue($optionValue, $productOptionValues)
441  {
442  // search quote item option Id in option value
443  if (preg_match('/\[([0-9]+)\]/', $optionValue, $matches)) {
444  $confItemOptionId = $matches[1];
445  $option = $this->_itemOptionFactory->create()->load($confItemOptionId);
446  if ($this->serializer->unserialize($option->getValue()) !== null) {
447  return $option->getValue();
448  }
449  }
450  return null;
451  }
452 
460  {
461  $unserializedValue = $this->serializer->unserialize($optionValue);
462  if ($unserializedValue !== null) {
463  return $unserializedValue;
464  }
465  return null;
466  }
467 
473  public function copyQuoteToOrder()
474  {
475  $quoteOption = $this->getConfigurationItemOption();
476  try {
477  $value = $this->serializer->unserialize($quoteOption->getValue());
478  if (!isset($value['quote_path'])) {
479  throw new \Exception();
480  }
481  $quotePath = $value['quote_path'];
482  $orderPath = $value['order_path'];
483 
484  if (!$this->mediaDirectory->isFile($quotePath) || !$this->mediaDirectory->isReadable($quotePath)) {
485  throw new \Exception();
486  }
487 
488  if ($this->_coreFileStorageDatabase->checkDbUsage()) {
489  $this->_coreFileStorageDatabase->copyFile(
490  $this->mediaDirectory->getAbsolutePath($quotePath),
491  $this->mediaDirectory->getAbsolutePath($orderPath)
492  );
493  } else {
494  $this->mediaDirectory->copyFile($quotePath, $orderPath);
495  }
496  } catch (\Exception $e) {
497  return $this;
498  }
499  return $this;
500  }
501 
509  {
510  $this->_customOptionDownloadUrl = $url;
511  return $this;
512  }
513 
521  protected function _getOptionDownloadUrl($route, $params)
522  {
523  return $this->_urlBuilder->getUrl($route, $params);
524  }
525 
530  protected function prepareSize($value)
531  {
532  $sizes = '';
533  if (!empty($value['width']) && !empty($value['height']) && $value['width'] > 0 && $value['height'] > 0) {
534  $sizes = $value['width'] . ' x ' . $value['height'] . ' ' . __('px.');
535  }
536  return $sizes;
537  }
538 }
__construct(\Magento\Checkout\Model\Session $checkoutSession, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Quote\Model\Quote\Item\OptionFactory $itemOptionFactory, \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDatabase, \Magento\Catalog\Model\Product\Option\Type\File\ValidatorInfo $validatorInfo, \Magento\Catalog\Model\Product\Option\Type\File\ValidatorFile $validatorFile, \Magento\Catalog\Model\Product\Option\UrlBuilder $urlBuilder, \Magento\Framework\Escaper $escaper, array $data=[], Filesystem $filesystem=null, Json $serializer=null)
Definition: File.php:107
$title
Definition: default.phtml:14
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
__()
Definition: __.php:13
$value
Definition: gender.phtml:16
parseOptionValue($optionValue, $productOptionValues)
Definition: File.php:440
foreach($product->getExtensionAttributes() ->getBundleProductOptions() as $option) $buyRequest
$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE]
Definition: website.php:18