Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2020 Adobe
* All Rights Reserved.
*/

declare(strict_types=1);

namespace Magento\Csp\Model\Collector\CspWhitelistXml;

use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Config\CompositeFileIteratorFactory;
use Magento\Framework\Config\FileResolverInterface;
use Magento\Framework\Filesystem;
use Magento\Framework\View\Design\ThemeInterface;
use Magento\Framework\View\DesignInterface;
use Magento\Framework\Filesystem\Directory\ReadInterface as DirectoryRead;
use Magento\Framework\View\Design\Theme\CustomizationInterface;
use Magento\Framework\View\Design\Theme\CustomizationInterfaceFactory;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem\Directory\ReadInterface as DirectoryRead;
use Magento\Framework\Config\CompositeFileIteratorFactory;
use Magento\Framework\View\Design\ThemeInterface;
use Magento\Framework\View\DesignInterface;

/**
* Combines configuration files from both modules and current theme.
Expand Down Expand Up @@ -74,22 +74,29 @@ public function __construct(
*/
public function get($filename, $scope)
{
$configs = $this->moduleFileResolver->get($filename, $scope);
if ($scope === 'global') {
$files = [];
$theme = $this->theme;
while ($theme) {
/** @var CustomizationInterface $info */
$info = $this->themeInfoFactory->create(['theme' => $theme]);
$file = $info->getThemeFilesPath() .'/etc/' .$filename;
if ($this->rootDir->isExist($file)) {
$files[] = $file;
$configs = $this->moduleFileResolver->get($filename, $scope);

switch ($scope) {
case 'frontend':
case 'adminhtml':
$files = [];
$theme = $this->theme;
while ($theme) {
/** @var CustomizationInterface $info */
$info = $this->themeInfoFactory->create(['theme' => $theme]);
$file = $info->getThemeFilesPath() . '/etc/' . $filename;
if ($this->rootDir->isExist($file)) {
$files[] = $file;
}
$theme = $theme->getParentTheme();
}
$theme = $theme->getParentTheme();
}
$configs = $this->iteratorFactory->create(
['paths' => array_reverse($files), 'existingIterator' => $configs]
);
$configs = $this->iteratorFactory->create(
['paths' => array_reverse($files), 'existingIterator' => $configs]
);
break;
case 'global':
default:
break;
}

return $configs;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
<?php
/**
* Copyright 2025 Adobe
* All Rights Reserved.
*/

declare(strict_types=1);

namespace Magento\Csp\Test\Unit\Model\Collector\CspWhitelistXml;

use Magento\Framework\Filesystem;
use Magento\Framework\View\Design\Theme\CustomizationInterface;
use Magento\Framework\View\Design\ThemeInterface;
use PHPUnit\Framework\TestCase;
use Magento\Framework\Config\FileResolverInterface;
use Magento\Csp\Model\Collector\CspWhitelistXml\FileResolver;
use Magento\Framework\View\DesignInterface;
use Magento\Framework\Config\CompositeFileIteratorFactory;
use Magento\Framework\View\Design\Theme\CustomizationInterfaceFactory;
use Magento\Framework\Filesystem\Directory\ReadInterface;
use Magento\Framework\App\Filesystem\DirectoryList;

class FileResolverTest extends TestCase
{
/**
* @var FileResolver
*/
private $model;

/**
* @var FileResolverInterface
*/
private $moduleFileResolverMock;

/**
* @var DesignInterface
*/
private $designMock;

/**
* @var CustomizationInterfaceFactory
*/
private $customizationFactoryMock;

/**
* @var Filesystem
*/
private $filesystemMock;

/**
* @var CompositeFileIteratorFactory
*/
private $iteratorFactoryMock;

/**
* @var ReadInterface
*/
private $readInterfaceMock;

/**
* @var ThemeInterface
*/
private $themeInterFaceMock;

/**
* @var CustomizationInterface
*/
private $customizationInterfaceMock;

protected function setUp(): void
{
$this->moduleFileResolverMock = $this->getMockBuilder(FileResolverInterface::class)
->disableOriginalConstructor()
->onlyMethods(['get'])
->getMockForAbstractClass();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getMockForAbstractClass method has been deprecated, please use alternative.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


$this->designMock = $this->getMockBuilder(DesignInterface::class)
->disableOriginalConstructor()
->onlyMethods(['getDesignTheme'])
->getMockForAbstractClass();

$this->themeInterFaceMock = $this->getMockBuilder(ThemeInterface::class)
->getMockForAbstractClass();

$this->designMock->expects($this->once())
->method('getDesignTheme')
->willReturn($this->themeInterFaceMock);

$this->customizationFactoryMock = $this->getMockBuilder(CustomizationInterfaceFactory::class)
->disableOriginalConstructor()
->onlyMethods(['create'])
->getMock();

$this->customizationInterfaceMock = $this->getMockBuilder(CustomizationInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();

$this->filesystemMock = $this->createPartialMock(Filesystem::class, ['getDirectoryRead']);

$this->readInterfaceMock = $this->getMockBuilder(ReadInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();

$this->filesystemMock->expects($this->once())
->method('getDirectoryRead')
->with(DirectoryList::ROOT)
->willReturn($this->readInterfaceMock);

$this->iteratorFactoryMock = $this->getMockBuilder(CompositeFileIteratorFactory::class)
->disableOriginalConstructor()
->getMock();

$this->model = new FileResolver(
$this->moduleFileResolverMock,
$this->designMock,
$this->customizationFactoryMock,
$this->filesystemMock,
$this->iteratorFactoryMock
);
}

/**
* Test for get method with frontend scope.
*
* @param string $filename
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PHPDoc comment signature is not complete

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

* @param array $fileList
*
* @return void
* @dataProvider providerGetFrontend
*/
public function testGetFrontend(string $scope, string $filename, array $fileList, string $themeFilesPath): void
{
$this->moduleFileResolverMock->expects($this->once())
->method('get')
->with($filename, $scope)
->willReturn($fileList);

$this->customizationFactoryMock->expects($this->any())
->method('create')
->with(['theme' => $this->themeInterFaceMock])
->willReturn($this->customizationInterfaceMock);

$this->customizationInterfaceMock->expects($this->once())
->method('getThemeFilesPath')
->willReturn($themeFilesPath);

$this->readInterfaceMock->expects($this->once())
->method('isExist')
->with($themeFilesPath.'/etc/'.$filename)
->willReturn(true);

$this->iteratorFactoryMock->expects($this->once())
->method('create')
->with(
[
'paths' => array_reverse([$themeFilesPath.'/etc/'.$filename]),
'existingIterator' => $fileList
]
)
->willReturn($fileList);

$this->assertEquals($fileList, $this->model->get($filename, $scope));
}

/**
* Test for get method with global scope.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PHPDoc comment signature is not complete

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

*
* @param string $filename
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param string $filename
* @param string $fileName

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

* @param array $fileList
*
* @return void
* @dataProvider providerGetGlobal
*/
public function testGetGlobal(string $scope, string $fileName, array $fileList): void
{
$this->moduleFileResolverMock->expects($this->once())
->method('get')
->with($fileName, $scope)
->willReturn($fileList);
$this->assertEquals($fileList, $this->model->get($fileName, $scope));
}

/**
* Data provider for get glocal scope tests.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Data provider for get glocal scope tests.
* Data provider for get global scope tests.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

*
* @return array
*/
public static function providerGetGlobal(): array
{
return [
[
'global',
'csp_whitelist.xml',
['anyvendor/anymodule/etc/csp_whitelist.xml']
]
];
}

/**
* Data provider for get frontend & adminhtml scope tests.
*
* @return array
*/
public static function providerGetFrontend(): array
{
return [
[
'frontend',
'csp_whitelist.xml',
['themevendor/theme/etc/csp_whitelist.xml'],
'themevendor/theme'
],
[
'adminhtml',
'csp_whitelist.xml',
['adminthemevendor/admintheme/etc/csp_whitelist.xml'],
'adminthemevendor/admintheme'
]
];
}
}