7ca6b300a4db27186a50844fd2e1070ce8d929f4
[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-2013 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 );
93 }
94
95 /**
96 * @test
97 * @dataProvider requireClassFileOnceTriggersParserForClassesWithAllowedPrefixesDataProvider
98 * @expectedException \checkClassCacheEntryAndRequireTestException
99 */
100 public function requireClassFileOnceTriggersParserForClassesWithAllowedPrefixes($className) {
101 $mockClassName = uniqid('CompatbilityClassLoaderPhpBelow50307Mock');
102 eval(
103 'if (!class_exists(\'checkClassCacheEntryAndRequireTestException\')) {' . LF .
104 'class checkClassCacheEntryAndRequireTestException extends Exception {}' . LF .
105 '}' . LF .
106 'class ' . $mockClassName . ' extends \\TYPO3\\CMS\\Core\\Compatibility\\CompatbilityClassLoaderPhpBelow50307 {' . LF .
107 'protected static function checkClassCacheEntryAndRequire($classPath) {' . LF .
108 'throw new checkClassCacheEntryAndRequireTestException(\'Class path \' . $classPath);' . LF .
109 '}' . LF .
110 '}'
111 );
112 $mockClassName::requireClassFileOnce('/some/path', $className);
113 }
114
115 /**
116 * @test
117 * @expectedException \ClassPathHasBeenRequired
118 */
119 public function coreClassesAreRequiredImmediately() {
120 $classPath = '/dummy/path';
121 $className = 'TYPO3\\CMS\\Core\\Utility\\GeneralUtility';
122
123 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
124 $mockClassLoaderClass::requireClassFileOnce($classPath, $className);
125 }
126
127 /**
128 * @test
129 * @expectedException \ClassPathHasBeenRequired
130 */
131 public function thirdPartyClassesAreRequiredImmediately() {
132 $classPath = '/dummy/path';
133 $className = 'SwiftMailer';
134
135 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
136 $mockClassLoaderClass::requireClassFileOnce($classPath, $className);
137 }
138
139 /**
140 * @test
141 * @expectedException \ClassPathHasBeenRequired
142 */
143 public function nameSpacedExtensionClassesAreRequiredImmediately() {
144 $classPath = '/dummy/path';
145 $className = 'Vendor\\CoolExtension\\Service\\CoolService';
146
147 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
148 $mockClassLoaderClass::requireClassFileOnce($classPath, $className);
149 }
150
151 /**
152 * @test
153 */
154 public function classCacheOnlyContainsRequireOfOriginalClassIfNothingHasBeenRewritten() {
155 $classPath = '/dummy/path';
156 self::$classCode = sprintf($this->classTemplate,
157 '/**' . LF .
158 ' *' . LF .
159 ' */' . LF .
160 'public function nothing() {' . LF .
161 '}'
162 );
163
164 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
165 $rewrittenContent = $mockClassLoaderClass::rewriteMethodTypeHintsFromClassPath($classPath);
166 $this->assertSame('require_once \'' . $classPath . '\';', $rewrittenContent);
167 }
168
169 /**
170 * @test
171 */
172 public function typeHintInOneLineAbstractFunctionIsCorrectlyRewritten() {
173 $classPath = '/dummy/path';
174 self::$classCode = sprintf($this->classTemplate,
175 '/**' . LF .
176 ' * @abstract' . LF .
177 ' * @param t3lib_div $bar' . LF .
178 ' * @return mixed' . LF .
179 ' */' . LF .
180 'abstract public function bar(t3lib_div $bar);'
181 );
182
183 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
184 $rewrittenContent = $mockClassLoaderClass::rewriteMethodTypeHintsFromClassPath($classPath);
185 $this->assertContains('abstract public function bar(\TYPO3\CMS\Core\Utility\GeneralUtility $bar);', $rewrittenContent);
186 }
187
188 /**
189 * @test
190 */
191 public function typeHintInOneLineFunctionWithOneParameterIsCorrectlyRewritten() {
192 $classPath = '/dummy/path';
193 self::$classCode = sprintf($this->classTemplate,
194 '/**' . LF .
195 ' * @param t3lib_div $foo' . LF .
196 ' */' . LF .
197 'public function foo(t3lib_div $foo) {' . LF .
198 '// this is only a dummy function' . LF .
199 'if ($foo instanceof t3lib_div) {' . LF .
200 'return FALSE;' . LF .
201 '}' . LF .
202 '}' . LF
203 );
204
205 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
206 $rewrittenContent = $mockClassLoaderClass::rewriteMethodTypeHintsFromClassPath($classPath);
207 $this->assertContains('// this is only a dummy function' . LF . 'if', $rewrittenContent, 'Comment not touched, newline after function ignored');
208 $this->assertContains('public function foo(\TYPO3\CMS\Core\Utility\GeneralUtility $foo) {', $rewrittenContent);
209 }
210
211 /**
212 * @test
213 */
214 public function typeHintInTwoLineFunctionWithTwoParametersIsCorrectlyRewritten() {
215 $classPath = '/dummy/path';
216 self::$classCode = sprintf($this->classTemplate,
217 '/**' . LF .
218 ' * @param t3lib_div $foo' . LF .
219 ' * @param $baz' . LF .
220 ' */' . LF .
221 'public function baz(t3lib_div $foo,' . LF .
222 ' $baz) {' . LF .
223 '}' . LF
224 );
225
226 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
227 $rewrittenContent = $mockClassLoaderClass::rewriteMethodTypeHintsFromClassPath($classPath);
228 $this->assertContains('public function baz(\TYPO3\CMS\Core\Utility\GeneralUtility $foo, $baz) {', $rewrittenContent);
229 }
230
231 /**
232 * @test
233 */
234 public function typeHintInTwoLineFunctionWithTwoParametersWhileOneHavingTypehintNotInAliasMapIsCorrectlyRewritten() {
235 $classPath = '/dummy/path';
236 self::$classCode = sprintf($this->classTemplate,
237 ' /**
238 * @param Tx_Extbase_Persistence_QueryInterface $query
239 * @param Tx_News_Domain_Model_DemandInterface $demand
240 */
241 abstract protected function createConstraintsFromDemand(Tx_Extbase_Persistence_QueryInterface $query,
242 Tx_News_Domain_Model_DemandInterface $demand);
243 ');
244
245 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
246 $rewrittenContent = $mockClassLoaderClass::rewriteMethodTypeHintsFromClassPath($classPath);
247 $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');
248 }
249
250 /**
251 * @test
252 */
253 public function functionsWithoutParametersOrTypeHintsNotInAliasMapRemainUntouchedEvenWhenOtherTypeHintsAreRewritten() {
254 $classPath = '/dummy/path';
255 self::$classCode = sprintf($this->classTemplate,
256 ' /**
257 * @param t3lib_div $foo
258 */
259 public function foo(t3lib_div $foo) {
260 }
261
262 /**
263 *
264 */
265 public function nothing() {
266 }
267
268 /**
269 * @param Tx_Core_Tests_Unit_Core_Fixtures_LegacyClassFixture $nothing
270 */
271 protected function stillNothing(Tx_Core_Tests_Unit_Core_Fixtures_LegacyClassFixture $nothing) {
272 }
273 ');
274
275 $mockClassLoaderClass = $this->getCompatibilityClassLoaderMockClass();
276 $rewrittenContent = $mockClassLoaderClass::rewriteMethodTypeHintsFromClassPath($classPath);
277 $this->assertContains('public function foo(\TYPO3\CMS\Core\Utility\GeneralUtility $foo) {', $rewrittenContent);
278 $this->assertContains('public function nothing() {', $rewrittenContent, 'One line one parameter');
279 $this->assertContains('protected function stillNothing(Tx_Core_Tests_Unit_Core_Fixtures_LegacyClassFixture $nothing) {', $rewrittenContent, 'One line on parameter with typehint not in aliasmap');
280 }
281 }
282
283 ?>