Security update for Core, with self-updated composer
[yaffs-website] / vendor / symfony / serializer / Tests / Normalizer / GetSetMethodNormalizerTest.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\Serializer\Tests\Normalizer;
13
14 use Doctrine\Common\Annotations\AnnotationReader;
15 use PHPUnit\Framework\TestCase;
16 use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
17 use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
18 use Symfony\Component\Serializer\Serializer;
19 use Symfony\Component\Serializer\SerializerInterface;
20 use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
21 use Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy;
22 use Symfony\Component\Serializer\Tests\Fixtures\MaxDepthDummy;
23 use Symfony\Component\Serializer\Tests\Fixtures\SiblingHolder;
24 use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
25 use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
26 use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy;
27
28 class GetSetMethodNormalizerTest extends TestCase
29 {
30     /**
31      * @var GetSetMethodNormalizer
32      */
33     private $normalizer;
34     /**
35      * @var SerializerInterface
36      */
37     private $serializer;
38
39     protected function setUp()
40     {
41         $this->serializer = $this->getMockBuilder(__NAMESPACE__.'\SerializerNormalizer')->getMock();
42         $this->normalizer = new GetSetMethodNormalizer();
43         $this->normalizer->setSerializer($this->serializer);
44     }
45
46     public function testInterface()
47     {
48         $this->assertInstanceOf('Symfony\Component\Serializer\Normalizer\NormalizerInterface', $this->normalizer);
49         $this->assertInstanceOf('Symfony\Component\Serializer\Normalizer\DenormalizerInterface', $this->normalizer);
50     }
51
52     public function testNormalize()
53     {
54         $obj = new GetSetDummy();
55         $object = new \stdClass();
56         $obj->setFoo('foo');
57         $obj->setBar('bar');
58         $obj->setBaz(true);
59         $obj->setCamelCase('camelcase');
60         $obj->setObject($object);
61
62         $this->serializer
63             ->expects($this->once())
64             ->method('normalize')
65             ->with($object, 'any')
66             ->will($this->returnValue('string_object'))
67         ;
68
69         $this->assertEquals(
70             array(
71                 'foo' => 'foo',
72                 'bar' => 'bar',
73                 'baz' => true,
74                 'fooBar' => 'foobar',
75                 'camelCase' => 'camelcase',
76                 'object' => 'string_object',
77             ),
78             $this->normalizer->normalize($obj, 'any')
79         );
80     }
81
82     public function testDenormalize()
83     {
84         $obj = $this->normalizer->denormalize(
85             array('foo' => 'foo', 'bar' => 'bar', 'baz' => true, 'fooBar' => 'foobar'),
86             __NAMESPACE__.'\GetSetDummy',
87             'any'
88         );
89         $this->assertEquals('foo', $obj->getFoo());
90         $this->assertEquals('bar', $obj->getBar());
91         $this->assertTrue($obj->isBaz());
92     }
93
94     public function testDenormalizeWithObject()
95     {
96         $data = new \stdClass();
97         $data->foo = 'foo';
98         $data->bar = 'bar';
99         $data->fooBar = 'foobar';
100         $obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\GetSetDummy', 'any');
101         $this->assertEquals('foo', $obj->getFoo());
102         $this->assertEquals('bar', $obj->getBar());
103     }
104
105     public function testDenormalizeNull()
106     {
107         $this->assertEquals(new GetSetDummy(), $this->normalizer->denormalize(null, __NAMESPACE__.'\GetSetDummy'));
108     }
109
110     public function testConstructorDenormalize()
111     {
112         $obj = $this->normalizer->denormalize(
113             array('foo' => 'foo', 'bar' => 'bar', 'baz' => true, 'fooBar' => 'foobar'),
114             __NAMESPACE__.'\GetConstructorDummy', 'any');
115         $this->assertEquals('foo', $obj->getFoo());
116         $this->assertEquals('bar', $obj->getBar());
117         $this->assertTrue($obj->isBaz());
118     }
119
120     public function testConstructorDenormalizeWithNullArgument()
121     {
122         $obj = $this->normalizer->denormalize(
123             array('foo' => 'foo', 'bar' => null, 'baz' => true),
124             __NAMESPACE__.'\GetConstructorDummy', 'any');
125         $this->assertEquals('foo', $obj->getFoo());
126         $this->assertNull($obj->getBar());
127         $this->assertTrue($obj->isBaz());
128     }
129
130     public function testConstructorDenormalizeWithMissingOptionalArgument()
131     {
132         $obj = $this->normalizer->denormalize(
133             array('foo' => 'test', 'baz' => array(1, 2, 3)),
134             __NAMESPACE__.'\GetConstructorOptionalArgsDummy', 'any');
135         $this->assertEquals('test', $obj->getFoo());
136         $this->assertEquals(array(), $obj->getBar());
137         $this->assertEquals(array(1, 2, 3), $obj->getBaz());
138     }
139
140     public function testConstructorDenormalizeWithOptionalDefaultArgument()
141     {
142         $obj = $this->normalizer->denormalize(
143             array('bar' => 'test'),
144             __NAMESPACE__.'\GetConstructorArgsWithDefaultValueDummy', 'any');
145         $this->assertEquals(array(), $obj->getFoo());
146         $this->assertEquals('test', $obj->getBar());
147     }
148
149     /**
150      * @requires PHP 5.6
151      */
152     public function testConstructorDenormalizeWithVariadicArgument()
153     {
154         $obj = $this->normalizer->denormalize(
155             array('foo' => array(1, 2, 3)),
156             'Symfony\Component\Serializer\Tests\Fixtures\VariadicConstructorArgsDummy', 'any');
157         $this->assertEquals(array(1, 2, 3), $obj->getFoo());
158     }
159
160     /**
161      * @requires PHP 5.6
162      */
163     public function testConstructorDenormalizeWithMissingVariadicArgument()
164     {
165         $obj = $this->normalizer->denormalize(
166             array(),
167             'Symfony\Component\Serializer\Tests\Fixtures\VariadicConstructorArgsDummy', 'any');
168         $this->assertEquals(array(), $obj->getFoo());
169     }
170
171     public function testConstructorWithObjectDenormalize()
172     {
173         $data = new \stdClass();
174         $data->foo = 'foo';
175         $data->bar = 'bar';
176         $data->baz = true;
177         $data->fooBar = 'foobar';
178         $obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\GetConstructorDummy', 'any');
179         $this->assertEquals('foo', $obj->getFoo());
180         $this->assertEquals('bar', $obj->getBar());
181     }
182
183     public function testConstructorWArgWithPrivateMutator()
184     {
185         $obj = $this->normalizer->denormalize(array('foo' => 'bar'), __NAMESPACE__.'\ObjectConstructorArgsWithPrivateMutatorDummy', 'any');
186         $this->assertEquals('bar', $obj->getFoo());
187     }
188
189     public function testGroupsNormalize()
190     {
191         $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
192         $this->normalizer = new GetSetMethodNormalizer($classMetadataFactory);
193         $this->normalizer->setSerializer($this->serializer);
194
195         $obj = new GroupDummy();
196         $obj->setFoo('foo');
197         $obj->setBar('bar');
198         $obj->setFooBar('fooBar');
199         $obj->setSymfony('symfony');
200         $obj->setKevin('kevin');
201         $obj->setCoopTilleuls('coopTilleuls');
202
203         $this->assertEquals(array(
204             'bar' => 'bar',
205         ), $this->normalizer->normalize($obj, null, array(GetSetMethodNormalizer::GROUPS => array('c'))));
206
207         $this->assertEquals(array(
208             'symfony' => 'symfony',
209             'foo' => 'foo',
210             'fooBar' => 'fooBar',
211             'bar' => 'bar',
212             'kevin' => 'kevin',
213             'coopTilleuls' => 'coopTilleuls',
214         ), $this->normalizer->normalize($obj, null, array(GetSetMethodNormalizer::GROUPS => array('a', 'c'))));
215     }
216
217     public function testGroupsDenormalize()
218     {
219         $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
220         $this->normalizer = new GetSetMethodNormalizer($classMetadataFactory);
221         $this->normalizer->setSerializer($this->serializer);
222
223         $obj = new GroupDummy();
224         $obj->setFoo('foo');
225
226         $toNormalize = array('foo' => 'foo', 'bar' => 'bar');
227
228         $normalized = $this->normalizer->denormalize(
229             $toNormalize,
230             'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
231             null,
232             array(GetSetMethodNormalizer::GROUPS => array('a'))
233         );
234         $this->assertEquals($obj, $normalized);
235
236         $obj->setBar('bar');
237
238         $normalized = $this->normalizer->denormalize(
239             $toNormalize,
240             'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
241             null,
242             array(GetSetMethodNormalizer::GROUPS => array('a', 'b'))
243         );
244         $this->assertEquals($obj, $normalized);
245     }
246
247     public function testGroupsNormalizeWithNameConverter()
248     {
249         $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
250         $this->normalizer = new GetSetMethodNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
251         $this->normalizer->setSerializer($this->serializer);
252
253         $obj = new GroupDummy();
254         $obj->setFooBar('@dunglas');
255         $obj->setSymfony('@coopTilleuls');
256         $obj->setCoopTilleuls('les-tilleuls.coop');
257
258         $this->assertEquals(
259             array(
260                 'bar' => null,
261                 'foo_bar' => '@dunglas',
262                 'symfony' => '@coopTilleuls',
263             ),
264             $this->normalizer->normalize($obj, null, array(GetSetMethodNormalizer::GROUPS => array('name_converter')))
265         );
266     }
267
268     public function testGroupsDenormalizeWithNameConverter()
269     {
270         $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
271         $this->normalizer = new GetSetMethodNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
272         $this->normalizer->setSerializer($this->serializer);
273
274         $obj = new GroupDummy();
275         $obj->setFooBar('@dunglas');
276         $obj->setSymfony('@coopTilleuls');
277
278         $this->assertEquals(
279             $obj,
280             $this->normalizer->denormalize(array(
281                 'bar' => null,
282                 'foo_bar' => '@dunglas',
283                 'symfony' => '@coopTilleuls',
284                 'coop_tilleuls' => 'les-tilleuls.coop',
285             ), 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy', null, array(GetSetMethodNormalizer::GROUPS => array('name_converter')))
286         );
287     }
288
289     /**
290      * @dataProvider provideCallbacks
291      */
292     public function testCallbacks($callbacks, $value, $result, $message)
293     {
294         $this->normalizer->setCallbacks($callbacks);
295
296         $obj = new GetConstructorDummy('', $value, true);
297
298         $this->assertEquals(
299             $result,
300             $this->normalizer->normalize($obj, 'any'),
301             $message
302         );
303     }
304
305     /**
306      * @expectedException \InvalidArgumentException
307      */
308     public function testUncallableCallbacks()
309     {
310         $this->normalizer->setCallbacks(array('bar' => null));
311
312         $obj = new GetConstructorDummy('baz', 'quux', true);
313
314         $this->normalizer->normalize($obj, 'any');
315     }
316
317     public function testIgnoredAttributes()
318     {
319         $this->normalizer->setIgnoredAttributes(array('foo', 'bar', 'baz', 'camelCase', 'object'));
320
321         $obj = new GetSetDummy();
322         $obj->setFoo('foo');
323         $obj->setBar('bar');
324         $obj->setBaz(true);
325
326         $this->assertEquals(
327             array('fooBar' => 'foobar'),
328             $this->normalizer->normalize($obj, 'any')
329         );
330     }
331
332     public function provideCallbacks()
333     {
334         return array(
335             array(
336                 array(
337                     'bar' => function ($bar) {
338                         return 'baz';
339                     },
340                 ),
341                 'baz',
342                 array('foo' => '', 'bar' => 'baz', 'baz' => true),
343                 'Change a string',
344             ),
345             array(
346                 array(
347                     'bar' => function ($bar) {
348                     },
349                 ),
350                 'baz',
351                 array('foo' => '', 'bar' => null, 'baz' => true),
352                 'Null an item',
353             ),
354             array(
355                 array(
356                     'bar' => function ($bar) {
357                         return $bar->format('d-m-Y H:i:s');
358                     },
359                 ),
360                 new \DateTime('2011-09-10 06:30:00'),
361                 array('foo' => '', 'bar' => '10-09-2011 06:30:00', 'baz' => true),
362                 'Format a date',
363             ),
364             array(
365                 array(
366                     'bar' => function ($bars) {
367                         $foos = '';
368                         foreach ($bars as $bar) {
369                             $foos .= $bar->getFoo();
370                         }
371
372                         return $foos;
373                     },
374                 ),
375                 array(new GetConstructorDummy('baz', '', false), new GetConstructorDummy('quux', '', false)),
376                 array('foo' => '', 'bar' => 'bazquux', 'baz' => true),
377                 'Collect a property',
378             ),
379             array(
380                 array(
381                     'bar' => function ($bars) {
382                         return count($bars);
383                     },
384                 ),
385                 array(new GetConstructorDummy('baz', '', false), new GetConstructorDummy('quux', '', false)),
386                 array('foo' => '', 'bar' => 2, 'baz' => true),
387                 'Count a property',
388             ),
389         );
390     }
391
392     /**
393      * @expectedException \Symfony\Component\Serializer\Exception\LogicException
394      * @expectedExceptionMessage Cannot normalize attribute "object" because the injected serializer is not a normalizer
395      */
396     public function testUnableToNormalizeObjectAttribute()
397     {
398         $serializer = $this->getMockBuilder('Symfony\Component\Serializer\SerializerInterface')->getMock();
399         $this->normalizer->setSerializer($serializer);
400
401         $obj = new GetSetDummy();
402         $object = new \stdClass();
403         $obj->setObject($object);
404
405         $this->normalizer->normalize($obj, 'any');
406     }
407
408     /**
409      * @expectedException \Symfony\Component\Serializer\Exception\CircularReferenceException
410      */
411     public function testUnableToNormalizeCircularReference()
412     {
413         $serializer = new Serializer(array($this->normalizer));
414         $this->normalizer->setSerializer($serializer);
415         $this->normalizer->setCircularReferenceLimit(2);
416
417         $obj = new CircularReferenceDummy();
418
419         $this->normalizer->normalize($obj);
420     }
421
422     public function testSiblingReference()
423     {
424         $serializer = new Serializer(array($this->normalizer));
425         $this->normalizer->setSerializer($serializer);
426
427         $siblingHolder = new SiblingHolder();
428
429         $expected = array(
430             'sibling0' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
431             'sibling1' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
432             'sibling2' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
433         );
434         $this->assertEquals($expected, $this->normalizer->normalize($siblingHolder));
435     }
436
437     public function testCircularReferenceHandler()
438     {
439         $serializer = new Serializer(array($this->normalizer));
440         $this->normalizer->setSerializer($serializer);
441         $this->normalizer->setCircularReferenceHandler(function ($obj) {
442             return get_class($obj);
443         });
444
445         $obj = new CircularReferenceDummy();
446
447         $expected = array('me' => 'Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy');
448         $this->assertEquals($expected, $this->normalizer->normalize($obj));
449     }
450
451     public function testObjectToPopulate()
452     {
453         $dummy = new GetSetDummy();
454         $dummy->setFoo('foo');
455
456         $obj = $this->normalizer->denormalize(
457             array('bar' => 'bar'),
458             __NAMESPACE__.'\GetSetDummy',
459             null,
460             array(GetSetMethodNormalizer::OBJECT_TO_POPULATE => $dummy)
461         );
462
463         $this->assertEquals($dummy, $obj);
464         $this->assertEquals('foo', $obj->getFoo());
465         $this->assertEquals('bar', $obj->getBar());
466     }
467
468     public function testDenormalizeNonExistingAttribute()
469     {
470         $this->assertEquals(
471             new GetSetDummy(),
472             $this->normalizer->denormalize(array('non_existing' => true), __NAMESPACE__.'\GetSetDummy')
473         );
474     }
475
476     public function testDenormalizeShouldNotSetStaticAttribute()
477     {
478         $obj = $this->normalizer->denormalize(array('staticObject' => true), __NAMESPACE__.'\GetSetDummy');
479
480         $this->assertEquals(new GetSetDummy(), $obj);
481         $this->assertNull(GetSetDummy::getStaticObject());
482     }
483
484     public function testNoTraversableSupport()
485     {
486         $this->assertFalse($this->normalizer->supportsNormalization(new \ArrayObject()));
487     }
488
489     public function testNoStaticGetSetSupport()
490     {
491         $this->assertFalse($this->normalizer->supportsNormalization(new ObjectWithJustStaticSetterDummy()));
492     }
493
494     public function testPrivateSetter()
495     {
496         $obj = $this->normalizer->denormalize(array('foo' => 'foobar'), __NAMESPACE__.'\ObjectWithPrivateSetterDummy');
497         $this->assertEquals('bar', $obj->getFoo());
498     }
499
500     public function testMaxDepth()
501     {
502         $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
503         $this->normalizer = new GetSetMethodNormalizer($classMetadataFactory);
504         $serializer = new Serializer(array($this->normalizer));
505         $this->normalizer->setSerializer($serializer);
506
507         $level1 = new MaxDepthDummy();
508         $level1->bar = 'level1';
509
510         $level2 = new MaxDepthDummy();
511         $level2->bar = 'level2';
512         $level1->child = $level2;
513
514         $level3 = new MaxDepthDummy();
515         $level3->bar = 'level3';
516         $level2->child = $level3;
517
518         $level4 = new MaxDepthDummy();
519         $level4->bar = 'level4';
520         $level3->child = $level4;
521
522         $result = $serializer->normalize($level1, null, array(GetSetMethodNormalizer::ENABLE_MAX_DEPTH => true));
523
524         $expected = array(
525             'bar' => 'level1',
526             'child' => array(
527                     'bar' => 'level2',
528                     'child' => array(
529                             'bar' => 'level3',
530                             'child' => array(
531                                     'child' => null,
532                                 ),
533                         ),
534                 ),
535             );
536
537         $this->assertEquals($expected, $result);
538     }
539 }
540
541 class GetSetDummy
542 {
543     protected $foo;
544     private $bar;
545     private $baz;
546     protected $camelCase;
547     protected $object;
548     private static $staticObject;
549
550     public function getFoo()
551     {
552         return $this->foo;
553     }
554
555     public function setFoo($foo)
556     {
557         $this->foo = $foo;
558     }
559
560     public function getBar()
561     {
562         return $this->bar;
563     }
564
565     public function setBar($bar)
566     {
567         $this->bar = $bar;
568     }
569
570     public function isBaz()
571     {
572         return $this->baz;
573     }
574
575     public function setBaz($baz)
576     {
577         $this->baz = $baz;
578     }
579
580     public function getFooBar()
581     {
582         return $this->foo.$this->bar;
583     }
584
585     public function getCamelCase()
586     {
587         return $this->camelCase;
588     }
589
590     public function setCamelCase($camelCase)
591     {
592         $this->camelCase = $camelCase;
593     }
594
595     public function otherMethod()
596     {
597         throw new \RuntimeException('Dummy::otherMethod() should not be called');
598     }
599
600     public function setObject($object)
601     {
602         $this->object = $object;
603     }
604
605     public function getObject()
606     {
607         return $this->object;
608     }
609
610     public static function getStaticObject()
611     {
612         return self::$staticObject;
613     }
614
615     public static function setStaticObject($object)
616     {
617         self::$staticObject = $object;
618     }
619
620     protected function getPrivate()
621     {
622         throw new \RuntimeException('Dummy::getPrivate() should not be called');
623     }
624 }
625
626 class GetConstructorDummy
627 {
628     protected $foo;
629     private $bar;
630     private $baz;
631
632     public function __construct($foo, $bar, $baz)
633     {
634         $this->foo = $foo;
635         $this->bar = $bar;
636         $this->baz = $baz;
637     }
638
639     public function getFoo()
640     {
641         return $this->foo;
642     }
643
644     public function getBar()
645     {
646         return $this->bar;
647     }
648
649     public function isBaz()
650     {
651         return $this->baz;
652     }
653
654     public function otherMethod()
655     {
656         throw new \RuntimeException('Dummy::otherMethod() should not be called');
657     }
658 }
659
660 abstract class SerializerNormalizer implements SerializerInterface, NormalizerInterface
661 {
662 }
663
664 class GetConstructorOptionalArgsDummy
665 {
666     protected $foo;
667     private $bar;
668     private $baz;
669
670     public function __construct($foo, $bar = array(), $baz = array())
671     {
672         $this->foo = $foo;
673         $this->bar = $bar;
674         $this->baz = $baz;
675     }
676
677     public function getFoo()
678     {
679         return $this->foo;
680     }
681
682     public function getBar()
683     {
684         return $this->bar;
685     }
686
687     public function getBaz()
688     {
689         return $this->baz;
690     }
691
692     public function otherMethod()
693     {
694         throw new \RuntimeException('Dummy::otherMethod() should not be called');
695     }
696 }
697
698 class GetConstructorArgsWithDefaultValueDummy
699 {
700     protected $foo;
701     protected $bar;
702
703     public function __construct($foo = array(), $bar)
704     {
705         $this->foo = $foo;
706         $this->bar = $bar;
707     }
708
709     public function getFoo()
710     {
711         return $this->foo;
712     }
713
714     public function getBar()
715     {
716         return $this->bar;
717     }
718
719     public function otherMethod()
720     {
721         throw new \RuntimeException('Dummy::otherMethod() should not be called');
722     }
723 }
724
725 class GetCamelizedDummy
726 {
727     private $kevinDunglas;
728     private $fooBar;
729     private $bar_foo;
730
731     public function __construct($kevinDunglas = null)
732     {
733         $this->kevinDunglas = $kevinDunglas;
734     }
735
736     public function getKevinDunglas()
737     {
738         return $this->kevinDunglas;
739     }
740
741     public function setFooBar($fooBar)
742     {
743         $this->fooBar = $fooBar;
744     }
745
746     public function getFooBar()
747     {
748         return $this->fooBar;
749     }
750
751     public function setBar_foo($bar_foo)
752     {
753         $this->bar_foo = $bar_foo;
754     }
755
756     public function getBar_foo()
757     {
758         return $this->bar_foo;
759     }
760 }
761
762 class ObjectConstructorArgsWithPrivateMutatorDummy
763 {
764     private $foo;
765
766     public function __construct($foo)
767     {
768         $this->setFoo($foo);
769     }
770
771     public function getFoo()
772     {
773         return $this->foo;
774     }
775
776     private function setFoo($foo)
777     {
778         $this->foo = $foo;
779     }
780 }
781
782 class ObjectWithPrivateSetterDummy
783 {
784     private $foo = 'bar';
785
786     public function getFoo()
787     {
788         return $this->foo;
789     }
790
791     private function setFoo($foo)
792     {
793     }
794 }
795
796 class ObjectWithJustStaticSetterDummy
797 {
798     private static $foo = 'bar';
799
800     public static function getFoo()
801     {
802         return self::$foo;
803     }
804
805     public static function setFoo($foo)
806     {
807         self::$foo = $foo;
808     }
809 }