Skip to content

Commit 5ae3293

Browse files
MC-29362: Sitemap grid does not use base URL
1 parent 902d74d commit 5ae3293

File tree

2 files changed

+116
-22
lines changed

2 files changed

+116
-22
lines changed

app/code/Magento/Sitemap/Model/Sitemap.php

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -739,8 +739,11 @@ protected function _getFormattedLastmodDate($date)
739739
*/
740740
protected function _getDocumentRoot()
741741
{
742-
return $this->filesystem->getDirectoryRead($this->documentRoot->getPath())
743-
->getAbsolutePath();
742+
if (PHP_SAPI === 'cli') {
743+
return $this->getDocumentRootFromBaseDir() ?? '';
744+
}
745+
// phpcs:ignore Magento2.Functions.DiscouragedFunction
746+
return realpath($this->_request->getServer('DOCUMENT_ROOT'));
744747
}
745748

746749
/**
@@ -754,10 +757,14 @@ protected function _getStoreBaseDomain()
754757
$storeParsedUrl = parse_url($this->_getStoreBaseUrl());
755758
$url = $storeParsedUrl['scheme'] . '://' . $storeParsedUrl['host'];
756759

757-
$documentRoot = trim(str_replace('\\', '/', $this->_getDocumentRoot()), '/');
758-
$baseDir = trim(str_replace('\\', '/', $this->_getBaseDir()), '/');
760+
// Set document root to false if we were unable to get it
761+
$documentRoot = $this->_getDocumentRoot() ?: false;
762+
if ($documentRoot) {
763+
$documentRoot = trim(str_replace(DIRECTORY_SEPARATOR, '/', $documentRoot), '/');
764+
}
765+
$baseDir = trim(str_replace(DIRECTORY_SEPARATOR, '/', $this->_getBaseDir()), '/');
759766

760-
if (strpos($baseDir, (string) $documentRoot) === 0) {
767+
if ($documentRoot !== false && strpos($baseDir, (string) $documentRoot) === 0) {
761768
//case when basedir is in document root
762769
$installationFolder = trim(str_replace($documentRoot, '', $baseDir), '/');
763770
$storeDomain = rtrim($url . '/' . $installationFolder, '/');
@@ -878,4 +885,30 @@ public function getIdentities()
878885
Value::CACHE_TAG . '_' . $this->getStoreId(),
879886
];
880887
}
888+
889+
/**
890+
* Get document root using base directory (root directory) and base path (base url path)
891+
*
892+
* Document root is determined using formula: BaseDir = DocumentRoot + BasePath.
893+
* Returns <b>NULL</b> if BaseDir does not end with BasePath (e.g document root contains a symlink to BaseDir).
894+
*
895+
* @return string|null
896+
*/
897+
private function getDocumentRootFromBaseDir(): ?string
898+
{
899+
// phpcs:ignore Magento2.Functions.DiscouragedFunction
900+
$basePath = rtrim(parse_url($this->_getStoreBaseUrl(UrlInterface::URL_TYPE_WEB), PHP_URL_PATH) ?: '', '/');
901+
$basePath = str_replace('/', DIRECTORY_SEPARATOR, $basePath);
902+
$basePath = rtrim($basePath, DIRECTORY_SEPARATOR);
903+
$baseDir = rtrim($this->_getBaseDir(), DIRECTORY_SEPARATOR);
904+
$length = strlen($basePath);
905+
if (!$length) {
906+
$documentRoot = $baseDir;
907+
} elseif (substr($baseDir, -$length) === $basePath) {
908+
$documentRoot = rtrim(substr($baseDir, 0, strlen($baseDir) - $length), DIRECTORY_SEPARATOR);
909+
} else {
910+
$documentRoot = null;
911+
}
912+
return $documentRoot;
913+
}
881914
}

app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php

Lines changed: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento\Sitemap\Test\Unit\Model;
77

8+
use Magento\Framework\App\Request\Http;
89
use Magento\Framework\DataObject;
910
use Magento\Framework\Filesystem;
1011
use Magento\Framework\Filesystem\Directory\Write as DirectoryWrite;
@@ -86,6 +87,15 @@ class SitemapTest extends \PHPUnit\Framework\TestCase
8687
*/
8788
private $configReaderMock;
8889

90+
/**
91+
* @var Http|\PHPUnit_Framework_MockObject_MockObject
92+
*/
93+
private $request;
94+
/**
95+
* @var Store|\PHPUnit_Framework_MockObject_MockObject
96+
*/
97+
private $store;
98+
8999
/**
90100
* @inheritdoc
91101
*/
@@ -143,6 +153,12 @@ protected function setUp()
143153

144154
$this->configReaderMock = $this->getMockForAbstractClass(SitemapConfigReaderInterface::class);
145155
$this->itemProviderMock = $this->getMockForAbstractClass(ItemProviderInterface::class);
156+
$this->request = $this->createMock(Http::class);
157+
$this->store = $this->createPartialMock(Store::class, ['isFrontUrlSecure', 'getBaseUrl']);
158+
$this->storeManagerMock = $this->createMock(StoreManagerInterface::class);
159+
$this->storeManagerMock->expects($this->any())
160+
->method('getStore')
161+
->willReturn($this->store);
146162
}
147163

148164
/**
@@ -476,25 +492,15 @@ function ($from, $to) {
476492

477493
$model = $this->getModelMock(true);
478494

479-
$storeMock = $this->getMockBuilder(Store::class)
480-
->setMethods(['isFrontUrlSecure', 'getBaseUrl'])
481-
->disableOriginalConstructor()
482-
->getMock();
483-
484-
$storeMock->expects($this->atLeastOnce())
495+
$this->store->expects($this->atLeastOnce())
485496
->method('isFrontUrlSecure')
486497
->willReturn(false);
487498

488-
$storeMock->expects($this->atLeastOnce())
499+
$this->store->expects($this->atLeastOnce())
489500
->method('getBaseUrl')
490501
->with($this->isType('string'), false)
491502
->willReturn('http://store.com/');
492503

493-
$this->storeManagerMock->expects($this->atLeastOnce())
494-
->method('getStore')
495-
->with(1)
496-
->willReturn($storeMock);
497-
498504
return $model;
499505
}
500506

@@ -599,10 +605,6 @@ private function getModelConstructorArgs()
599605
->disableOriginalConstructor()
600606
->getMock();
601607

602-
$this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class)
603-
->setMethods(['getStore'])
604-
->getMockForAbstractClass();
605-
606608
$objectManager = new ObjectManager($this);
607609
$escaper = $objectManager->getObject(\Magento\Framework\Escaper::class);
608610

@@ -617,7 +619,8 @@ private function getModelConstructorArgs()
617619
'filesystem' => $this->filesystemMock,
618620
'itemProvider' => $this->itemProviderMock,
619621
'configReader' => $this->configReaderMock,
620-
'escaper' => $escaper
622+
'escaper' => $escaper,
623+
'request' => $this->request,
621624
]
622625
);
623626
$constructArguments['resource'] = null;
@@ -732,4 +735,62 @@ public static function siteUrlDataProvider()
732735
]
733736
];
734737
}
738+
739+
/**
740+
* Check site URL getter
741+
*
742+
* @param string $storeBaseUrl
743+
* @param string $baseDir
744+
* @param string $documentRoot
745+
* @dataProvider getDocumentRootFromBaseDirUrlDataProvider
746+
*/
747+
public function testGetDocumentRootFromBaseDir(
748+
string $storeBaseUrl,
749+
string $baseDir,
750+
?string $documentRoot
751+
) {
752+
$this->store->setCode('store');
753+
$this->store->method('getBaseUrl')->willReturn($storeBaseUrl);
754+
$this->directoryMock->method('getAbsolutePath')->willReturn($baseDir);
755+
/** @var $model Sitemap */
756+
$model = $this->getMockBuilder(Sitemap::class)
757+
->setMethods(['_construct'])
758+
->setConstructorArgs($this->getModelConstructorArgs())
759+
->getMock();
760+
761+
$method = new \ReflectionMethod($model, 'getDocumentRootFromBaseDir');
762+
$method->setAccessible(true);
763+
$this->assertSame($documentRoot, $method->invoke($model));
764+
}
765+
766+
/**
767+
* Provides test cases for document root testing
768+
*
769+
* @return array
770+
*/
771+
public function getDocumentRootFromBaseDirUrlDataProvider(): array
772+
{
773+
return [
774+
[
775+
'http://magento.com/',
776+
'/var/www',
777+
'/var/www',
778+
],
779+
[
780+
'http://magento.com/usa',
781+
'/var/www/usa',
782+
'/var/www',
783+
],
784+
[
785+
'http://magento.com/usa/tx',
786+
'/var/www/usa/tx',
787+
'/var/www',
788+
],
789+
'symlink <document root>/usa/txt -> /var/www/html' => [
790+
'http://magento.com/usa/tx',
791+
'/var/www/html',
792+
null,
793+
],
794+
];
795+
}
735796
}

0 commit comments

Comments
 (0)