PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/typo3/sysext/extbase/Tests/Unit/Service/ExtensionServiceTest.php

https://github.com/TYPO3/TYPO3.CMS
PHP | 367 lines | 232 code | 38 blank | 97 comment | 0 complexity | e63c602ec33f5c9fe75cb837e151cdf2 MD5 | raw file
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of the TYPO3 CMS project.
  5. *
  6. * It is free software; you can redistribute it and/or modify it under
  7. * the terms of the GNU General Public License, either version 2
  8. * of the License, or any later version.
  9. *
  10. * For the full copyright and license information, please read the
  11. * LICENSE.txt file that was distributed with this source code.
  12. *
  13. * The TYPO3 project - inspiring people to share!
  14. */
  15. namespace TYPO3\CMS\Extbase\Tests\Unit\Service;
  16. use Prophecy\Argument;
  17. use Prophecy\PhpUnit\ProphecyTrait;
  18. use Prophecy\Prophecy\ObjectProphecy;
  19. use TYPO3\CMS\Core\Database\Connection;
  20. use TYPO3\CMS\Core\Database\ConnectionPool;
  21. use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
  22. use TYPO3\CMS\Core\Database\Query\QueryBuilder;
  23. use TYPO3\CMS\Core\Tests\Unit\Database\Mocks\MockPlatform;
  24. use TYPO3\CMS\Core\Utility\GeneralUtility;
  25. use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
  26. use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
  27. use TYPO3\CMS\Extbase\Exception;
  28. use TYPO3\CMS\Extbase\Service\ExtensionService;
  29. use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
  30. /**
  31. * Test case
  32. */
  33. class ExtensionServiceTest extends UnitTestCase
  34. {
  35. use ProphecyTrait;
  36. /**
  37. * @var ConfigurationManagerInterface
  38. */
  39. protected $mockConfigurationManager;
  40. protected ExtensionService $extensionService;
  41. /**
  42. * Due to nested PageRepository / FrontendRestriction Container issues, the Context object is set
  43. */
  44. protected bool $resetSingletonInstances = true;
  45. protected function setUp(): void
  46. {
  47. parent::setUp();
  48. $GLOBALS['TSFE'] = new \stdClass();
  49. $this->extensionService = new ExtensionService();
  50. $this->mockConfigurationManager = $this->createMock(ConfigurationManagerInterface::class);
  51. $this->extensionService->injectConfigurationManager($this->mockConfigurationManager);
  52. $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'] = [
  53. 'ExtensionName' => [
  54. 'plugins' => [
  55. 'SomePlugin' => [
  56. 'controllers' => [
  57. 'Fully\\Qualified\\ControllerName' => [
  58. 'alias' => 'ControllerName',
  59. 'actions' => ['index', 'otherAction'],
  60. ],
  61. ],
  62. ],
  63. 'ThirdPlugin' => [
  64. 'controllers' => [
  65. 'Fully\\Qualified\\ControllerName' => [
  66. 'alias' => 'ControllerName',
  67. 'actions' => ['otherAction', 'thirdAction'],
  68. ],
  69. ],
  70. ],
  71. ],
  72. ],
  73. 'SomeOtherExtensionName' => [
  74. 'plugins' => [
  75. 'SecondPlugin' => [
  76. 'controllers' => [
  77. 'Fully\\Qualified\\ControllerName' => [
  78. 'alias' => 'ControllerName',
  79. 'actions' => ['index', 'otherAction'],
  80. ],
  81. 'Fully\\Qualified\\SecondControllerName' => [
  82. 'actions' => ['someAction', 'someOtherAction'],
  83. 'alias' => 'SecondControllerName',
  84. 'nonCacheableActions' => ['someOtherAction'],
  85. ],
  86. ],
  87. ],
  88. ],
  89. ],
  90. ];
  91. }
  92. /**
  93. * Setup and return a mocked database connection that allows
  94. * the QueryBuilder to work.
  95. *
  96. * @return ObjectProphecy<Connection>
  97. */
  98. protected function getMockDatabaseConnection(): ObjectProphecy
  99. {
  100. $connection = $this->prophesize(Connection::class);
  101. $connection->getDatabasePlatform()->willReturn(new MockPlatform());
  102. $connection->getExpressionBuilder()->willReturn(new ExpressionBuilder($connection->reveal()));
  103. $connection->quoteIdentifier(Argument::cetera())->willReturnArgument(0);
  104. $queryBuilder = new QueryBuilder(
  105. $connection->reveal(),
  106. null,
  107. new \Doctrine\DBAL\Query\QueryBuilder($connection->reveal())
  108. );
  109. $connectionPool = $this->prophesize(ConnectionPool::class);
  110. $connectionPool->getQueryBuilderForTable('tt_content')->willReturn($queryBuilder);
  111. GeneralUtility::addInstance(ConnectionPool::class, $connectionPool->reveal());
  112. return $connection;
  113. }
  114. /**
  115. * DataProvider for getPluginNamespaceByPluginSignatureTests()
  116. *
  117. * @return array
  118. */
  119. public function getPluginNamespaceDataProvider(): array
  120. {
  121. return [
  122. [null, null, 'tx__'],
  123. ['', '', 'tx__'],
  124. ['SomeExtension', 'SomePlugin', 'tx_someextension_someplugin'],
  125. ['NonExistingExtension', 'SomePlugin', 'tx_nonexistingextension_someplugin'],
  126. ['Invalid', '', 'tx_invalid_'],
  127. ];
  128. }
  129. /**
  130. * @test
  131. * @dataProvider getPluginNamespaceDataProvider
  132. * @param string $extensionName
  133. * @param string $pluginName
  134. * @param mixed $expectedResult
  135. */
  136. public function getPluginNamespaceTests($extensionName, $pluginName, $expectedResult): void
  137. {
  138. $this->mockConfigurationManager->expects(self::once())->method('getConfiguration')->willReturn([]);
  139. $actualResult = $this->extensionService->getPluginNamespace($extensionName, $pluginName);
  140. self::assertEquals($expectedResult, $actualResult, 'Failing for extension: "' . $extensionName . '", plugin: "' . $pluginName . '"');
  141. }
  142. /**
  143. * @test
  144. */
  145. public function pluginNamespaceCanBeOverridden(): void
  146. {
  147. $this->mockConfigurationManager->expects(self::once())->method('getConfiguration')->with(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK, 'SomeExtension', 'SomePlugin')->willReturn(['view' => ['pluginNamespace' => 'overridden_plugin_namespace']]);
  148. $expectedResult = 'overridden_plugin_namespace';
  149. $actualResult = $this->extensionService->getPluginNamespace('SomeExtension', 'SomePlugin');
  150. self::assertEquals($expectedResult, $actualResult);
  151. }
  152. /**
  153. * DataProvider for getPluginNameByActionTests()
  154. *
  155. * @return array
  156. */
  157. public function getPluginNameByActionDataProvider(): array
  158. {
  159. return [
  160. ['ExtensionName', 'ControllerName', 'someNonExistingAction', null],
  161. ['ExtensionName', 'ControllerName', 'index', 'SomePlugin'],
  162. ['ExtensionName', 'ControllerName', 'thirdAction', 'ThirdPlugin'],
  163. ['eXtEnSiOnNaMe', 'cOnTrOlLeRnAmE', 'thirdAction', null],
  164. ['eXtEnSiOnNaMe', 'cOnTrOlLeRnAmE', 'ThIrDaCtIoN', null],
  165. ['SomeOtherExtensionName', 'ControllerName', 'otherAction', 'SecondPlugin'],
  166. ];
  167. }
  168. /**
  169. * @test
  170. * @dataProvider getPluginNameByActionDataProvider
  171. * @param string $extensionName
  172. * @param string $controllerName
  173. * @param string $actionName
  174. * @param mixed $expectedResult
  175. */
  176. public function getPluginNameByActionTests(string $extensionName, string $controllerName, string $actionName, $expectedResult): void
  177. {
  178. $this->mockConfigurationManager->expects(self::once())->method('getConfiguration')->with(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK)->willReturn(['view' => ['pluginNamespace' => 'overridden_plugin_namespace']]);
  179. $actualResult = $this->extensionService->getPluginNameByAction($extensionName, $controllerName, $actionName);
  180. self::assertEquals($expectedResult, $actualResult, 'Failing for $extensionName: "' . $extensionName . '", $controllerName: "' . $controllerName . '", $actionName: "' . $actionName . '" - ');
  181. }
  182. /**
  183. * @test
  184. */
  185. public function getPluginNameByActionThrowsExceptionIfMoreThanOnePluginMatches(): void
  186. {
  187. $this->expectException(Exception::class);
  188. $this->expectExceptionCode(1280825466);
  189. $this->mockConfigurationManager->expects(self::once())->method('getConfiguration')->with(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK)->willReturn(['view' => ['pluginNamespace' => 'overridden_plugin_namespace']]);
  190. $this->extensionService->getPluginNameByAction('ExtensionName', 'ControllerName', 'otherAction');
  191. }
  192. /**
  193. * @test
  194. */
  195. public function getPluginNameByActionReturnsCurrentIfItCanHandleTheActionEvenIfMoreThanOnePluginMatches(): void
  196. {
  197. $frameworkConfiguration = [
  198. 'extensionName' => 'CurrentExtension',
  199. 'pluginName' => 'CurrentPlugin',
  200. 'controllerConfiguration' => [
  201. 'Fully\\Qualified\\ControllerName' => [
  202. 'alias' => 'ControllerName',
  203. 'actions' => ['otherAction'],
  204. ],
  205. ],
  206. ];
  207. $this->mockConfigurationManager
  208. ->expects(self::once())
  209. ->method('getConfiguration')
  210. ->with(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK)
  211. ->willReturn($frameworkConfiguration);
  212. $actualResult = $this->extensionService->getPluginNameByAction('CurrentExtension', 'ControllerName', 'otherAction');
  213. $expectedResult = 'CurrentPlugin';
  214. self::assertEquals($expectedResult, $actualResult);
  215. }
  216. /**
  217. * @test
  218. */
  219. public function getTargetPidByPluginSignatureReturnsNullIfConfigurationManagerIsNotInitialized(): void
  220. {
  221. $this->mockConfigurationManager->expects(self::once())->method('getConfiguration')->willReturn([]);
  222. self::assertNull($this->extensionService->getTargetPidByPlugin('ExtensionName', 'PluginName'));
  223. }
  224. /**
  225. * @test
  226. */
  227. public function getTargetPidByPluginSignatureReturnsNullIfDefaultPidIsZero(): void
  228. {
  229. $this->mockConfigurationManager->expects(self::once())->method('getConfiguration')->willReturn(['view' => ['defaultPid' => 0]]);
  230. self::assertNull($this->extensionService->getTargetPidByPlugin('ExtensionName', 'PluginName'));
  231. }
  232. /**
  233. * @test
  234. */
  235. public function getTargetPidByPluginSignatureReturnsTheConfiguredDefaultPid(): void
  236. {
  237. $this->mockConfigurationManager->expects(self::once())->method('getConfiguration')->willReturn(['view' => ['defaultPid' => 123]]);
  238. $expectedResult = 123;
  239. $actualResult = $this->extensionService->getTargetPidByPlugin('ExtensionName', 'SomePlugin');
  240. self::assertEquals($expectedResult, $actualResult);
  241. }
  242. /**
  243. * @test
  244. */
  245. public function getDefaultControllerNameByPluginReturnsNullIfGivenExtensionCantBeFound(): void
  246. {
  247. self::assertNull($this->extensionService->getDefaultControllerNameByPlugin('NonExistingExtensionName', 'SomePlugin'));
  248. }
  249. /**
  250. * @test
  251. */
  252. public function getDefaultControllerNameByPluginReturnsNullIfGivenPluginCantBeFound(): void
  253. {
  254. self::assertNull($this->extensionService->getDefaultControllerNameByPlugin('ExtensionName', 'NonExistingPlugin'));
  255. }
  256. /**
  257. * @test
  258. */
  259. public function getDefaultControllerNameByPluginReturnsFirstControllerNameOfGivenPlugin(): void
  260. {
  261. $expectedResult = 'ControllerName';
  262. $actualResult = $this->extensionService->getDefaultControllerNameByPlugin('ExtensionName', 'SomePlugin');
  263. self::assertEquals($expectedResult, $actualResult);
  264. }
  265. /**
  266. * @test
  267. */
  268. public function getDefaultActionNameByPluginAndControllerReturnsNullIfGivenExtensionCantBeFound(): void
  269. {
  270. self::assertNull($this->extensionService->getDefaultActionNameByPluginAndController('NonExistingExtensionName', 'SomePlugin', 'ControllerName'));
  271. }
  272. /**
  273. * @test
  274. */
  275. public function getDefaultActionNameByPluginAndControllerReturnsNullIfGivenPluginCantBeFound(): void
  276. {
  277. self::assertNull($this->extensionService->getDefaultActionNameByPluginAndController('ExtensionName', 'NonExistingPlugin', 'ControllerName'));
  278. }
  279. /**
  280. * @test
  281. */
  282. public function getDefaultActionNameByPluginAndControllerReturnsNullIfGivenControllerCantBeFound(): void
  283. {
  284. self::assertNull($this->extensionService->getDefaultActionNameByPluginAndController('ExtensionName', 'SomePlugin', 'NonExistingControllerName'));
  285. }
  286. /**
  287. * @test
  288. */
  289. public function getDefaultActionNameByPluginAndControllerReturnsFirstActionNameOfGivenController(): void
  290. {
  291. $expectedResult = 'someAction';
  292. $actualResult = $this->extensionService->getDefaultActionNameByPluginAndController('SomeOtherExtensionName', 'SecondPlugin', 'SecondControllerName');
  293. self::assertEquals($expectedResult, $actualResult);
  294. }
  295. /**
  296. * @test
  297. */
  298. public function getTargetPageTypeByFormatReturnsZeroIfNoMappingIsSet(): void
  299. {
  300. $configurationManagerProphecy = $this->prophesize(ConfigurationManager::class);
  301. $configurationManagerProphecy->getConfiguration(
  302. ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK,
  303. 'extension'
  304. )->willReturn([]);
  305. $this->extensionService->injectConfigurationManager($configurationManagerProphecy->reveal());
  306. $result = $this->extensionService->getTargetPageTypeByFormat('extension', 'json');
  307. self::assertSame(0, $result);
  308. }
  309. /**
  310. * @test
  311. */
  312. public function getTargetPageTypeByFormatReturnsMappedPageTypeFromConfiguration(): void
  313. {
  314. $configurationManagerProphecy = $this->prophesize(ConfigurationManager::class);
  315. $configurationManagerProphecy->getConfiguration(
  316. ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK,
  317. 'extension'
  318. )->willReturn([
  319. 'view' => [
  320. 'formatToPageTypeMapping' => [
  321. 'json' => 111,
  322. ],
  323. ],
  324. ]);
  325. $this->extensionService->injectConfigurationManager($configurationManagerProphecy->reveal());
  326. $result = $this->extensionService->getTargetPageTypeByFormat('extension', 'json');
  327. self::assertSame(111, $result);
  328. }
  329. }