7a17f1da7dd8fe4c868118ff00f4ffcc9513cee4
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Compatibility / CompatbilityClassLoaderPhpBelow50307Test.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Compatibility;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2012 Helmut Hummel <helmut.hummel@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26
27 /**
28 * Testcase for TYPO3\CMS\Core\Compatibility\CompatbilityClassLoaderPhpBelow50307
29 *
30 */
31 class CompatbilityClassLoaderPhpBelow50307Test extends \TYPO3\CMS\Core\Tests\UnitTestCase {
32
33 /**
34 * Class name of the fixture class
35 *
36 * @var string
37 */
38 protected $testClassName = 'Tx_Core_Tests_Unit_Core_Fixtures_LegacyClassFixture';
39
40 /**
41 * Fixture class template
42 *
43 * @var string
44 */
45 protected $classTemplate = 'abstract class Tx_Core_Tests_Unit_Core_Fixtures_LegacyClassFixture {
46 %s
47 }';
48
49 /**
50 * Fixture class code
51 *
52 * @var string
53 */
54 public static $classCode = '';
55
56 /**
57 * @var \TYPO3\CMS\Core\Compatibility\CompatbilityClassLoaderPhpBelow50307|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject
58 */
59 protected $fixture;
60
61 /**
62 * @return string
63 */
64 protected function getCompatibilityClassLoaderMockClass() {
65 $className = uniqid('CompatbilityClassLoaderPhpBelow50307Mock');
66 eval(
67 'if (!class_exists(\'ClassPathHasBeenRequired\')) {' . LF .
68 'class ClassPathHasBeenRequired extends Exception {}' . LF .
69 '}' . LF .
70 'class ' . $className . ' extends \\TYPO3\\CMS\\Core\\Compatibility\\CompatbilityClassLoaderPhpBelow50307 {' . LF .
71 'protected static function requireClassFile($classPath) {' . LF .
72 'throw new ClassPathHasBeenRequired(\'Class path \' . $classPath);' . LF .
73 '}' . LF .
74 'static public function getClassFileContent() {' . LF .
75 ' return TYPO3\\CMS\\Core\\Tests\Unit\Compatibility\\CompatbilityClassLoaderPhpBelow50307Test::$classCode;' . LF .
76 '}' . LF .
77 'static public function rewriteMethodTypeHintsFromClassPath($classPath) {' . LF .
78 ' return parent::rewriteMethodTypeHintsFromClassPath($classPath);' . LF .
79 '}' . LF .
80 '}'
81 );
82 return $className;
83 }
84
85 public function requireClassFileOnceTriggersParserForClassesWithAllowedPrefixesDataProvider() {
86 return array(
87 'tx_' => array('tx_Foo'),
88 'Tx_' => array('Tx_bar'),
89 'user_' => array('user_fooBar'),
90 'User_' => array('User_Barfoo'),
91 'ux_' => array('ux_Foo'),
92 'Ux_' => array('Ux_bar'),
93 );
94 }
95
96 /**
97 * @test
98 * @dataProvider requireClassFileOnceTriggersParserForClassesWithAllowedPrefixesDataProvider
99 * @expectedException \checkClassCacheEntryAndRequireTestException
100 */
101 public function requireClassFileOnceTriggersParserForClassesWithAllowedPrefixes($className) {
102 $mockClassName = uniqid('CompatbilityClassLoaderPhpBelow50307Mock');
103 eval(
104 'if (!class_exists(\'checkClassCacheEntryAndRequireTestException\')) {' . LF .
105 'class checkClassCacheEntryAndRequireTestException extends Exception {}' . LF .
106 '}' . LF .
107 'class ' . $mockClassName . ' extends \\TYPO3\\CMS\\Core\\Compatibility\\CompatbilityClassLoaderPhpBelow50307 {' . LF .
108 'protected static function checkClassCacheEntryAndRequire($classPath) {' . LF .
109 'throw new checkClassCacheEntryAndRequireTestException(\'Class path \' . $classPath);' . LF .
110 '}' . LF .
111 '}'
112 );
113 $mockClassName::requireClassFileOnce('/some/path', $className);
114 }
115
116 /**
117 * @test
118 * @expectedException \ClassPathHasBeenRequired
119 */
120 public function coreClassesAreRequiredImmediately() {
121 $classPath = '/dummy/path';
122 $className = 'TYPO3\\CMS\\Core\\Utility\\GeneralUtility';
123
124 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
125 $mockClassLoaderClass::requireClassFileOnce($classPath, $className);
126 }
127
128 /**
129 * @test
130 * @expectedException \ClassPathHasBeenRequired
131 */
132 public function thirdPartyClassesAreRequiredImmediately() {
133 $classPath = '/dummy/path';
134 $className = 'SwiftMailer';
135
136 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
137 $mockClassLoaderClass::requireClassFileOnce($classPath, $className);
138 }
139
140 /**
141 * @test
142 * @expectedException \ClassPathHasBeenRequired
143 */
144 public function nameSpacedExtensionClassesAreRequiredImmediately() {
145 $classPath = '/dummy/path';
146 $className = 'Vendor\\CoolExtension\\Service\\CoolService';
147
148 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
149 $mockClassLoaderClass::requireClassFileOnce($classPath, $className);
150 }
151
152 /**
153 * @test
154 */
155 public function classCacheOnlyContainsRequireOfOriginalClassIfNothingHasBeenRewritten() {
156 $classPath = '/dummy/path';
157 self::$classCode = sprintf($this->classTemplate,
158 '/**' . LF .
159 ' *' . LF .
160 ' */' . LF .
161 'public function nothing() {' . LF .
162 '}'
163 );
164
165 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
166 $rewrittenContent = $mockClassLoaderClass::rewriteMethodTypeHintsFromClassPath($classPath);
167 $this->assertSame('require_once \'' . $classPath . '\';', $rewrittenContent);
168 }
169
170 /**
171 * @test
172 */
173 public function typeHintInOneLineAbstractFunctionIsCorrectlyRewritten() {
174 $classPath = '/dummy/path';
175 self::$classCode = sprintf($this->classTemplate,
176 '/**' . LF .
177 ' * @abstract' . LF .
178 ' * @param t3lib_div $bar' . LF .
179 ' * @return mixed' . LF .
180 ' */' . LF .
181 'abstract public function bar(t3lib_div $bar);'
182 );
183
184 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
185 $rewrittenContent = $mockClassLoaderClass::rewriteMethodTypeHintsFromClassPath($classPath);
186 $this->assertContains('abstract public function bar(\TYPO3\CMS\Core\Utility\GeneralUtility $bar);', $rewrittenContent);
187 }
188
189 /**
190 * @test
191 */
192 public function typeHintInOneLineFunctionWithOneParameterIsCorrectlyRewritten() {
193 $classPath = '/dummy/path';
194 self::$classCode = sprintf($this->classTemplate,
195 '/**' . LF .
196 ' * @param t3lib_div $foo' . LF .
197 ' */' . LF .
198 'public function foo(t3lib_div $foo) {' . LF .
199 '// this is only a dummy function' . LF .
200 'if ($foo instanceof t3lib_div) {' . LF .
201 'return FALSE;' . LF .
202 '}' . LF .
203 '}' . LF
204 );
205
206 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
207 $rewrittenContent = $mockClassLoaderClass::rewriteMethodTypeHintsFromClassPath($classPath);
208 $this->assertContains('// this is only a dummy function' . LF . 'if', $rewrittenContent, 'Comment not touched, newline after function ignored');
209 $this->assertContains('public function foo(\TYPO3\CMS\Core\Utility\GeneralUtility $foo) {', $rewrittenContent);
210 }
211
212 /**
213 * @test
214 */
215 public function typeHintInTwoLineFunctionWithTwoParametersIsCorrectlyRewritten() {
216 $classPath = '/dummy/path';
217 self::$classCode = sprintf($this->classTemplate,
218 '/**' . LF .
219 ' * @param t3lib_div $foo' . LF .
220 ' * @param $baz' . LF .
221 ' */' . LF .
222 'public function baz(t3lib_div $foo,' . LF .
223 ' $baz) {' . LF .
224 '}' . LF
225 );
226
227 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
228 $rewrittenContent = $mockClassLoaderClass::rewriteMethodTypeHintsFromClassPath($classPath);
229 $this->assertContains('public function baz(\TYPO3\CMS\Core\Utility\GeneralUtility $foo, $baz) {', $rewrittenContent);
230 }
231
232 /**
233 * @test
234 */
235 public function typeHintInTwoLineFunctionWithTwoParametersWhileOneHavingTypehintNotInAliasMapIsCorrectlyRewritten() {
236 $classPath = '/dummy/path';
237 self::$classCode = sprintf($this->classTemplate,
238 ' /**
239 * @param Tx_Extbase_Persistence_QueryInterface $query
240 * @param Tx_News_Domain_Model_DemandInterface $demand
241 */
242 abstract protected function createConstraintsFromDemand(Tx_Extbase_Persistence_QueryInterface $query,
243 Tx_News_Domain_Model_DemandInterface $demand);
244 ');
245
246 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
247 $rewrittenContent = $mockClassLoaderClass::rewriteMethodTypeHintsFromClassPath($classPath);
248 $this->assertContains('protected function createConstraintsFromDemand(\TYPO3\CMS\Extbase\Persistence\QueryInterface $query, Tx_News_Domain_Model_DemandInterface $demand);', $rewrittenContent, 'Multi line abstract and second parameter with own typehint not in aliasmap');
249 }
250
251 /**
252 * @test
253 */
254 public function functionsWithoutParametersOrTypeHintsNotInAliasMapRemainUntouchedEvenWhenOtherTypeHintsAreRewritten() {
255 $classPath = '/dummy/path';
256 self::$classCode = sprintf($this->classTemplate,
257 ' /**
258 * @param t3lib_div $foo
259 */
260 public function foo(t3lib_div $foo) {
261 }
262
263 /**
264 *
265 */
266 public function nothing() {
267 }
268
269 /**
270 * @param Tx_Core_Tests_Unit_Core_Fixtures_LegacyClassFixture $nothing
271 */
272 protected function stillNothing(Tx_Core_Tests_Unit_Core_Fixtures_LegacyClassFixture $nothing) {
273 }
274 ');
275
276 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
277 $rewrittenContent = $mockClassLoaderClass::rewriteMethodTypeHintsFromClassPath($classPath);
278 $this->assertContains('public function foo(\TYPO3\CMS\Core\Utility\GeneralUtility $foo) {', $rewrittenContent);
279 $this->assertContains('public function nothing() {', $rewrittenContent, 'One line one parameter');
280 $this->assertContains('protected function stillNothing(Tx_Core_Tests_Unit_Core_Fixtures_LegacyClassFixture $nothing) {', $rewrittenContent, 'One line on parameter with typehint not in aliasmap');
281 }
282 }
283
284 ?>