7d03fab6774e1ba87ba2833edf775d46320bbcfc
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / Reflection / ClassSchemaTest.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Tests\Unit\Reflection;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Utility\GeneralUtility;
18 use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
19 use TYPO3\CMS\Extbase\Reflection\ClassSchema;
20
21 /**
22 * Test case
23 */
24 class ClassSchemaTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
25 {
26 /**
27 * @test
28 */
29 public function classSchemaForModelIsSetAggregateRootIfRepositoryClassIsFoundForNamespacedClasses()
30 {
31 /** @var \TYPO3\CMS\Extbase\Reflection\ReflectionService $service */
32 $service = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class);
33 $classSchema = $service->getClassSchema(Fixture\DummyModel::class);
34 $this->assertTrue($classSchema->isAggregateRoot());
35 }
36
37 public function testClassSchemaHasConstructor()
38 {
39 $classSchema = new ClassSchema(Fixture\DummyClassWithConstructorAndConstructorArguments::class);
40 static::assertTrue($classSchema->hasConstructor());
41 }
42
43 public function testClassSchemaDetectsConstructorArguments()
44 {
45 $classSchema = new ClassSchema(Fixture\DummyClassWithConstructorAndConstructorArguments::class);
46 static::assertTrue($classSchema->hasConstructor());
47
48 $constructorArguments = $classSchema->getConstructorArguments();
49 static::assertArrayHasKey('foo', $constructorArguments);
50 static::assertArrayHasKey('bar', $constructorArguments);
51
52 $classSchema = new ClassSchema(Fixture\DummyClassWithConstructorAndWithoutConstructorArguments::class);
53 static::assertTrue($classSchema->hasConstructor());
54 static::assertSame([], $classSchema->getConstructorArguments());
55
56 $classSchema = new ClassSchema(Fixture\DummyClassWithoutConstructor::class);
57 static::assertFalse($classSchema->hasConstructor());
58 static::assertSame([], $classSchema->getConstructorArguments());
59 }
60
61 public function testClassSchemaDetectsConstructorArgumentsWithDependencies()
62 {
63 $classSchema = new ClassSchema(Fixture\DummyClassWithConstructorAndConstructorArgumentsWithDependencies::class);
64 static::assertTrue($classSchema->hasConstructor());
65
66 $methodDefinition = $classSchema->getMethod('__construct');
67 static::assertArrayHasKey('foo', $methodDefinition['params']);
68 static::assertSame(Fixture\DummyClassWithGettersAndSetters::class, $methodDefinition['params']['foo']['dependency']);
69 }
70
71 public function testClassSchemaGetProperties()
72 {
73 static::assertSame(
74 [
75 'publicProperty',
76 'protectedProperty',
77 'privateProperty',
78 'publicStaticProperty',
79 'protectedStaticProperty',
80 'privateStaticProperty',
81 'propertyWithIgnoredTags',
82 'propertyWithInjectAnnotation',
83 'propertyWithTransientAnnotation',
84 'propertyWithCascadeAnnotation',
85 'propertyWithCascadeAnnotationWithoutVarAnnotation',
86 'propertyWithObjectStorageAnnotation'
87 ],
88 array_keys((new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class))->getProperties())
89 );
90 }
91
92 public function testClassSchemaHasMethod()
93 {
94 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class);
95 static::assertTrue($classSchema->hasMethod('publicMethod'));
96 static::assertFalse($classSchema->hasMethod('nonExistentMethod'));
97 }
98
99 public function testClassSchemaGetMethods()
100 {
101 static::assertSame(
102 [
103 'publicMethod',
104 'protectedMethod',
105 'privateMethod',
106 'methodWithIgnoredTags',
107 'injectSettings',
108 'injectMethodWithoutParam',
109 'injectMethodThatIsProtected',
110 'injectFoo',
111 'staticMethod',
112 'methodWithMandatoryParam',
113 'methodWithNullableParam',
114 'methodWithDefaultValueParam',
115 'methodWithTypeHintedParam'
116 ],
117 array_keys((new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class))->getMethods())
118 );
119 }
120
121 public function testClassSchemaDetectsMethodVisibility()
122 {
123 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class);
124
125 $methodDefinition = $classSchema->getMethod('publicMethod');
126 static::assertTrue($methodDefinition['public']);
127 static::assertFalse($methodDefinition['protected']);
128 static::assertFalse($methodDefinition['private']);
129
130 $methodDefinition = $classSchema->getMethod('protectedMethod');
131 static::assertFalse($methodDefinition['public']);
132 static::assertTrue($methodDefinition['protected']);
133 static::assertFalse($methodDefinition['private']);
134
135 $methodDefinition = $classSchema->getMethod('privateMethod');
136 static::assertFalse($methodDefinition['public']);
137 static::assertFalse($methodDefinition['protected']);
138 static::assertTrue($methodDefinition['private']);
139 }
140
141 public function testClassSchemaDetectsInjectProperties()
142 {
143 $classSchema = new ClassSchema(Fixture\DummyClassWithInjectDoctrineAnnotation::class);
144 static::assertTrue($classSchema->hasInjectProperties());
145
146 $injectProperties = $classSchema->getInjectProperties();
147 static::assertArrayHasKey('propertyWithFullQualifiedClassName', $injectProperties);
148 static::assertSame(Fixture\DummyClassWithInjectDoctrineAnnotation::class, $injectProperties['propertyWithFullQualifiedClassName']);
149
150 static::assertArrayHasKey('propertyWithRelativeClassName', $injectProperties);
151 static::assertSame('DummyClassWithInjectDoctrineAnnotation', $injectProperties['propertyWithRelativeClassName']);
152
153 static::assertArrayHasKey('propertyWithImportedClassName', $injectProperties);
154 static::assertSame('ClassSchemaTest', $injectProperties['propertyWithImportedClassName']);
155
156 static::assertArrayHasKey('propertyWithImportedAndAliasedClassName', $injectProperties);
157 static::assertSame('AliasedClassSchemaTest', $injectProperties['propertyWithImportedAndAliasedClassName']);
158 }
159
160 public function testClassSchemaDetectsInjectMethods()
161 {
162 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class);
163 static::assertTrue($classSchema->hasInjectMethods());
164
165 $methodDefinition = $classSchema->getMethod('injectSettings');
166 static::assertFalse($methodDefinition['injectMethod']);
167
168 $methodDefinition = $classSchema->getMethod('injectMethodWithoutParam');
169 static::assertFalse($methodDefinition['injectMethod']);
170
171 $methodDefinition = $classSchema->getMethod('injectMethodThatIsProtected');
172 static::assertFalse($methodDefinition['injectMethod']);
173
174 $methodDefinition = $classSchema->getMethod('injectFoo');
175 static::assertTrue($methodDefinition['injectMethod']);
176
177 $injectMethods = $classSchema->getInjectMethods();
178 static::assertArrayHasKey('injectFoo', $injectMethods);
179 }
180
181 public function testClassSchemaDetectsPropertiesWithLazyAnnotation()
182 {
183 $classSchema = new ClassSchema(Fixture\DummyClassWithLazyDoctrineAnnotation::class);
184 static::assertTrue($classSchema->getProperty('propertyWithLazyAnnotation')['annotations']['lazy']);
185 }
186
187 public function testClassSchemaDetectsStaticMethods()
188 {
189 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class);
190
191 $methodDefinition = $classSchema->getMethod('staticMethod');
192 static::assertTrue($methodDefinition['static']);
193 }
194
195 public function testClassSchemaDetectsMandatoryParams()
196 {
197 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class);
198
199 $methodDefinition = $classSchema->getMethod('methodWithMandatoryParam');
200 static::assertFalse($methodDefinition['params']['param']['optional']);
201 }
202
203 public function testClassSchemaDetectsNullableParams()
204 {
205 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class);
206
207 $methodDefinition = $classSchema->getMethod('methodWithNullableParam');
208 static::assertTrue($methodDefinition['params']['param']['nullable']);
209 }
210
211 public function testClassSchemaDetectsDefaultValueParams()
212 {
213 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class);
214
215 $methodDefinition = $classSchema->getMethod('methodWithDefaultValueParam');
216 static::assertSame('foo', $methodDefinition['params']['param']['default']);
217 }
218
219 public function testClassSchemaDetectsParamTypeFromTypeHint()
220 {
221 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class);
222
223 $methodDefinition = $classSchema->getMethod('methodWithTypeHintedParam');
224 static::assertSame('string', $methodDefinition['params']['param']['type']);
225 }
226
227 public function testClassSchemaDetectsPropertyVisibility()
228 {
229 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class);
230
231 $propertyDefinition = $classSchema->getProperty('publicProperty');
232 static::assertTrue($propertyDefinition['public']);
233 static::assertFalse($propertyDefinition['protected']);
234 static::assertFalse($propertyDefinition['private']);
235
236 $propertyDefinition = $classSchema->getProperty('protectedProperty');
237 static::assertFalse($propertyDefinition['public']);
238 static::assertTrue($propertyDefinition['protected']);
239 static::assertFalse($propertyDefinition['private']);
240
241 $propertyDefinition = $classSchema->getProperty('privateProperty');
242 static::assertFalse($propertyDefinition['public']);
243 static::assertFalse($propertyDefinition['protected']);
244 static::assertTrue($propertyDefinition['private']);
245 }
246
247 public function testClassSchemaDetectsInjectProperty()
248 {
249 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class);
250
251 $propertyDefinition = $classSchema->getProperty('propertyWithInjectAnnotation');
252 static::assertTrue($propertyDefinition['annotations']['inject']);
253 }
254
255 public function testClassSchemaDetectsTransientProperty()
256 {
257 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class);
258
259 $propertyDefinition = $classSchema->getProperty('propertyWithTransientAnnotation');
260 static::assertTrue($propertyDefinition['annotations']['transient']);
261 }
262
263 public function testClassSchemaDetectsCascadeProperty()
264 {
265 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class);
266
267 $propertyDefinition = $classSchema->getProperty('propertyWithCascadeAnnotation');
268 static::assertSame('remove', $propertyDefinition['annotations']['cascade']);
269 }
270
271 public function testClassSchemaDetectsCascadePropertyOnlyWithVarAnnotation()
272 {
273 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class);
274
275 $propertyDefinition = $classSchema->getProperty('propertyWithCascadeAnnotationWithoutVarAnnotation');
276 static::assertNull($propertyDefinition['annotations']['cascade']);
277 }
278
279 public function testClassSchemaDetectsIgnoreValidationAnnotation()
280 {
281 $classSchema = new ClassSchema(Fixture\DummyControllerWithIgnoreValidationDoctrineAnnotation::class);
282 static::assertTrue(isset($classSchema->getMethod('someAction')['tags']['ignorevalidation']));
283 static::assertTrue(in_array('foo', $classSchema->getMethod('someAction')['tags']['ignorevalidation'], true));
284 static::assertTrue(in_array('bar', $classSchema->getMethod('someAction')['tags']['ignorevalidation'], true));
285 static::assertFalse(in_array('baz', $classSchema->getMethod('someAction')['tags']['ignorevalidation'], true));
286 }
287
288 public function testClassSchemaDetectsTypeAndElementType()
289 {
290 $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class);
291
292 $propertyDefinition = $classSchema->getProperty('propertyWithObjectStorageAnnotation');
293 static::assertSame(ObjectStorage::class, $propertyDefinition['type']);
294 static::assertSame(Fixture\DummyClassWithAllTypesOfProperties::class, $propertyDefinition['elementType']);
295 }
296
297 public function testClassSchemaDetectsSingletons()
298 {
299 static::assertTrue((new ClassSchema(Fixture\DummySingleton::class))->isSingleton());
300 }
301
302 public function testClassSchemaDetectsModels()
303 {
304 static::assertTrue((new ClassSchema(Fixture\DummyEntity::class))->isModel());
305 static::assertTrue((new ClassSchema(Fixture\DummyValueObject::class))->isModel());
306 }
307
308 public function testClassSchemaDetectsEntities()
309 {
310 static::assertTrue((new ClassSchema(Fixture\DummyEntity::class))->isEntity());
311 }
312
313 public function testClassSchemaDetectsValueObjects()
314 {
315 static::assertTrue((new ClassSchema(Fixture\DummyValueObject::class))->isValueObject());
316 }
317
318 public function testClassSchemaDetectsClassName()
319 {
320 static::assertSame(Fixture\DummyModel::class, (new ClassSchema(Fixture\DummyModel::class))->getClassName());
321 }
322
323 public function testClassSchemaDetectsNonStaticProperties()
324 {
325 static::assertTrue((new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class))->hasProperty('publicProperty'));
326 static::assertTrue((new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class))->hasProperty('protectedProperty'));
327 static::assertTrue((new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class))->hasProperty('privateProperty'));
328 }
329
330 public function testClassSchemaDetectsStaticProperties()
331 {
332 static::assertTrue((new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class))->hasProperty('publicStaticProperty'));
333 static::assertTrue((new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class))->hasProperty('protectedStaticProperty'));
334 static::assertTrue((new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class))->hasProperty('privateStaticProperty'));
335 }
336
337 public function testClassSchemaGetTags()
338 {
339 $tags = (new ClassSchema(Fixture\DummyClassWithTags::class))->getTags();
340 static::assertArrayHasKey('see', $tags);
341
342 // test ignored tags
343 static::assertArrayNotHasKey('package', $tags);
344 static::assertArrayNotHasKey('subpackage', $tags);
345 static::assertArrayNotHasKey('license', $tags);
346 static::assertArrayNotHasKey('copyright', $tags);
347 static::assertArrayNotHasKey('author', $tags);
348 static::assertArrayNotHasKey('version', $tags);
349 }
350
351 /**
352 * @test
353 */
354 public function classSchemaDetectsValidateAnnotation()
355 {
356 $classSchema = new ClassSchema(Fixture\DummyClassWithValidateAnnotation::class);
357
358 static::assertSame(
359 [],
360 $classSchema->getProperty('propertyWithoutValidateAnnotations')['annotations']['validators']
361 );
362 static::assertSame(
363 [
364 'NotEmpty',
365 'Empty (Foo=Bar)'
366 ],
367 $classSchema->getProperty('propertyWithValidateAnnotations')['annotations']['validators']
368 );
369
370 static::assertSame(
371 [],
372 $classSchema->getMethod('methodWithoutValidateAnnotations')['annotations']['validators']
373 );
374
375 static::assertSame(
376 [
377 '$fooParam FooValidator (FooValidatorOptionKey=FooValidatorOptionValue)',
378 '$fooParam BarValidator'
379 ],
380 $classSchema->getMethod('methodWithValidateAnnotations')['annotations']['validators']
381 );
382 }
383 }