Skip to content

Commit 8a3a011

Browse files
committed
Merge remote-tracking branch 'origin/MC-39852' into 2.4-develop-pr117
2 parents e03d067 + 1093ad0 commit 8a3a011

File tree

4 files changed

+202
-14
lines changed

4 files changed

+202
-14
lines changed
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Customer\Controller\Adminhtml\Address;
9+
10+
use Magento\Customer\Api\AddressMetadataInterface;
11+
use Magento\Framework\Exception\NotFoundException;
12+
use Magento\Framework\App\Filesystem\DirectoryList;
13+
use Magento\Framework\Controller\Result\RawFactory;
14+
use Magento\Framework\Url\DecoderInterface;
15+
use Magento\Framework\Controller\ResultInterface;
16+
use Magento\Framework\Filesystem;
17+
use Magento\Framework\Controller\Result\Raw;
18+
use Magento\MediaStorage\Helper\File\Storage;
19+
use Magento\Framework\App\Response\Http\FileFactory;
20+
use Magento\Framework\Filesystem\Io\File as IoFile;
21+
use Magento\Backend\App\Action\Context;
22+
use Magento\Framework\App\Action\HttpGetActionInterface;
23+
use Magento\Backend\App\Action;
24+
25+
/**
26+
* Class Viewfile serves to show file or image by file/image name provided in request parameters.
27+
*/
28+
class Viewfile extends Action implements HttpGetActionInterface
29+
{
30+
/**
31+
* Authorization level of a basic admin session
32+
*/
33+
const ADMIN_RESOURCE = 'Magento_Customer::manage';
34+
35+
/**
36+
* @var RawFactory
37+
*/
38+
private $resultRawFactory;
39+
40+
/**
41+
* @var DecoderInterface
42+
*/
43+
private $urlDecoder;
44+
45+
/**
46+
* @var Filesystem
47+
*/
48+
private $filesystem;
49+
50+
/**
51+
* @var Storage
52+
*/
53+
private $storage;
54+
55+
/**
56+
* @var FileFactory
57+
*/
58+
private $fileFactory;
59+
60+
/**
61+
* @var IoFile
62+
*/
63+
private $ioFile;
64+
65+
/**
66+
* @param Context $context
67+
* @param FileFactory $fileFactory
68+
* @param RawFactory $resultRawFactory
69+
* @param DecoderInterface $urlDecoder
70+
* @param Filesystem $filesystem
71+
* @param Storage $storage
72+
* @param IoFile $ioFile
73+
*/
74+
public function __construct(
75+
Context $context,
76+
FileFactory $fileFactory,
77+
RawFactory $resultRawFactory,
78+
DecoderInterface $urlDecoder,
79+
Filesystem $filesystem,
80+
Storage $storage,
81+
IoFile $ioFile
82+
) {
83+
parent::__construct($context);
84+
$this->resultRawFactory = $resultRawFactory;
85+
$this->urlDecoder = $urlDecoder;
86+
$this->filesystem = $filesystem;
87+
$this->storage = $storage;
88+
$this->fileFactory = $fileFactory;
89+
$this->ioFile = $ioFile;
90+
}
91+
92+
/**
93+
* Customer address view file action
94+
*
95+
* @return ResultInterface|void
96+
* @throws NotFoundException
97+
*/
98+
public function execute()
99+
{
100+
list($file, $plain) = $this->getFileParams();
101+
102+
$directory = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA);
103+
$fileName = AddressMetadataInterface::ENTITY_TYPE_ADDRESS . DIRECTORY_SEPARATOR .
104+
ltrim($file, DIRECTORY_SEPARATOR);
105+
$path = $directory->getAbsolutePath($fileName);
106+
if (mb_strpos($path, '..') !== false
107+
|| (!$directory->isFile($fileName) && !$this->storage->processStorageFile($path))
108+
) {
109+
throw new NotFoundException(__('Page not found.'));
110+
}
111+
112+
$pathInfo = $this->ioFile->getPathInfo($path);
113+
if ($plain) {
114+
$extension = $pathInfo['extension'];
115+
switch (strtolower($extension)) {
116+
case 'gif':
117+
$contentType = 'image/gif';
118+
break;
119+
case 'jpg':
120+
$contentType = 'image/jpeg';
121+
break;
122+
case 'png':
123+
$contentType = 'image/png';
124+
break;
125+
default:
126+
$contentType = 'application/octet-stream';
127+
break;
128+
}
129+
$stat = $directory->stat($fileName);
130+
$contentLength = $stat['size'];
131+
$contentModify = $stat['mtime'];
132+
133+
/** @var Raw $resultRaw */
134+
$resultRaw = $this->resultRawFactory->create();
135+
$resultRaw->setHttpResponseCode(200)
136+
->setHeader('Pragma', 'public', true)
137+
->setHeader('Content-type', $contentType, true)
138+
->setHeader('Content-Length', $contentLength)
139+
->setHeader('Last-Modified', date('r', $contentModify));
140+
$resultRaw->setContents($directory->readFile($fileName));
141+
142+
return $resultRaw;
143+
} else {
144+
$name = $pathInfo['basename'];
145+
$this->fileFactory->create(
146+
$name,
147+
['type' => 'filename', 'value' => $fileName],
148+
DirectoryList::MEDIA
149+
);
150+
}
151+
}
152+
153+
/**
154+
* Get parameters from request.
155+
*
156+
* @return array
157+
* @throws NotFoundException
158+
*/
159+
private function getFileParams() : array
160+
{
161+
$file = null;
162+
$plain = false;
163+
if ($this->getRequest()->getParam('file')) {
164+
// download file
165+
$file = $this->urlDecoder->decode(
166+
$this->getRequest()->getParam('file')
167+
);
168+
} elseif ($this->getRequest()->getParam('image')) {
169+
// show plain image
170+
$file = $this->urlDecoder->decode(
171+
$this->getRequest()->getParam('image')
172+
);
173+
$plain = true;
174+
} else {
175+
throw new NotFoundException(__('Page not found.'));
176+
}
177+
178+
return [$file, $plain];
179+
}
180+
}

app/code/Magento/Customer/Model/FileProcessor.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,10 @@ public function getViewUrl($filePath, $type)
158158
$viewUrl = '';
159159

160160
if ($this->entityTypeCode == AddressMetadataInterface::ENTITY_TYPE_ADDRESS) {
161-
$filePath = $this->entityTypeCode . '/' . ltrim($filePath, '/');
162-
$viewUrl = $this->urlBuilder->getBaseUrl(['_type' => UrlInterface::URL_TYPE_MEDIA])
163-
. $this->mediaDirectory->getRelativePath($filePath);
161+
$viewUrl = $this->urlBuilder->getUrl(
162+
'customer/address/viewfile',
163+
[$type => $this->urlEncoder->encode(ltrim($filePath, '/'))]
164+
);
164165
}
165166

166167
if ($this->entityTypeCode == CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) {

app/code/Magento/Customer/Test/Unit/Model/FileProcessorTest.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -162,22 +162,22 @@ public function testGetViewUrlCustomer()
162162
public function testGetViewUrlCustomerAddress()
163163
{
164164
$filePath = 'filename.ext1';
165+
$encodedFilePath = 'encodedfilenameext1';
165166

166-
$baseUrl = 'baseUrl';
167-
$relativeUrl = 'relativeUrl';
167+
$fileUrl = 'fileUrl';
168168

169-
$this->urlBuilder->expects($this->once())
170-
->method('getBaseUrl')
171-
->with(['_type' => UrlInterface::URL_TYPE_MEDIA])
172-
->willReturn($baseUrl);
169+
$this->urlEncoder->expects($this->once())
170+
->method('encode')
171+
->with($filePath)
172+
->willReturn($encodedFilePath);
173173

174-
$this->mediaDirectory->expects($this->once())
175-
->method('getRelativePath')
176-
->with(AddressMetadataInterface::ENTITY_TYPE_ADDRESS . '/' . $filePath)
177-
->willReturn($relativeUrl);
174+
$this->urlBuilder->expects($this->once())
175+
->method('getUrl')
176+
->with('customer/address/viewfile', ['image' => $encodedFilePath])
177+
->willReturn($fileUrl);
178178

179179
$model = $this->getModel(AddressMetadataInterface::ENTITY_TYPE_ADDRESS);
180-
$this->assertEquals($baseUrl . $relativeUrl, $model->getViewUrl($filePath, 'image'));
180+
$this->assertEquals($fileUrl, $model->getViewUrl($filePath, 'image'));
181181
}
182182

183183
public function testRemoveUploadedFile()

pub/media/customer_address/.htaccess

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<IfVersion < 2.4>
2+
order allow,deny
3+
deny from all
4+
</IfVersion>
5+
<IfVersion >= 2.4>
6+
Require all denied
7+
</IfVersion>

0 commit comments

Comments
 (0)