Skip to content

Commit ffb2d5d

Browse files
committed
moves all state to a dedicated class
This commit moves all state that might change between serialization/deserialization runs into a dedicated class. This class is available to all classes which are concerned with the serialization and will it make super easy to propagate user specific settings to these classes.
1 parent 032a4f7 commit ffb2d5d

30 files changed

+557
-427
lines changed

UPGRADING.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
From 0.11 to 0.12
2+
=================
3+
4+
- GraphNavigator::detachObject has been removed, you can directly use Context::stopVisiting instead.
5+
- VisitorInterface::getNavigator was deprecated, instead use Context::accept

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
},
3939
"extra": {
4040
"branch-alias": {
41-
"dev-master": "0.11-dev"
41+
"dev-master": "0.12-dev"
4242
}
4343
}
4444
}

src/JMS/Serializer/AbstractVisitor.php

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,11 @@ abstract class AbstractVisitor implements VisitorInterface
2424
{
2525
protected $namingStrategy;
2626

27-
private $serializeNull = false;
28-
2927
public function __construct(PropertyNamingStrategyInterface $namingStrategy)
3028
{
3129
$this->namingStrategy = $namingStrategy;
3230
}
3331

34-
public function setSerializeNull($serializeNull)
35-
{
36-
$this->serializeNull = (bool) $serializeNull;
37-
}
38-
39-
public function shouldSerializeNull()
40-
{
41-
return $this->serializeNull;
42-
}
43-
4432
public function getNamingStrategy()
4533
{
4634
return $this->namingStrategy;

src/JMS/Serializer/Context.php

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
<?php
2+
3+
namespace JMS\Serializer;
4+
5+
use JMS\Serializer\Exception\RuntimeException;
6+
use JMS\Serializer\Exception\LogicException;
7+
use JMS\Serializer\Exclusion\ExclusionStrategyInterface;
8+
use JMS\Serializer\Exclusion\GroupsExclusionStrategy;
9+
use JMS\Serializer\Exclusion\VersionExclusionStrategy;
10+
use PhpCollection\Map;
11+
use PhpOption\None;
12+
use PhpOption\Some;
13+
14+
class Context
15+
{
16+
/**
17+
* @var \PhpCollection\Map
18+
*/
19+
public $attributes;
20+
21+
private $direction;
22+
private $format;
23+
private $visitingSet;
24+
private $visitingStack;
25+
26+
/** @var VisitorInterface */
27+
private $visitor;
28+
29+
/** @var GraphNavigator */
30+
private $navigator;
31+
32+
/** @var ExclusionStrategyInterface */
33+
private $exclusionStrategy;
34+
35+
/** @var boolean */
36+
private $serializeNull;
37+
38+
public static function create()
39+
{
40+
return new self();
41+
}
42+
43+
public function __construct()
44+
{
45+
$this->attributes = new Map();
46+
}
47+
48+
public function initialize($direction, $format, VisitorInterface $visitor, GraphNavigator $navigator)
49+
{
50+
$this->visitingSet = new \SplObjectStorage();
51+
$this->visitingStack = new \SplStack();
52+
$this->direction = $direction;
53+
$this->format = $format;
54+
$this->visitor = $visitor;
55+
$this->navigator = $navigator;
56+
}
57+
58+
public function accept($data, array $type)
59+
{
60+
return $this->navigator->accept($data, $type, $this);
61+
}
62+
63+
public function getVisitor()
64+
{
65+
return $this->visitor;
66+
}
67+
68+
public function getNavigator()
69+
{
70+
return $this->navigator;
71+
}
72+
73+
public function getExclusionStrategy()
74+
{
75+
return $this->exclusionStrategy;
76+
}
77+
78+
public function setAttribute($key, $value)
79+
{
80+
$this->attributes->set($key, $value);
81+
82+
return $this;
83+
}
84+
85+
public function setExclusionStrategy(ExclusionStrategyInterface $strategy)
86+
{
87+
$this->exclusionStrategy = $strategy;
88+
89+
return $this;
90+
}
91+
92+
/**
93+
* @param integer $version
94+
*/
95+
public function setVersion($version)
96+
{
97+
if (null === $version) {
98+
$this->exclusionStrategy = null;
99+
100+
return $this;
101+
}
102+
103+
$this->exclusionStrategy = new VersionExclusionStrategy($version);
104+
105+
return $this;
106+
}
107+
108+
/**
109+
* @param null|array $groups
110+
*/
111+
public function setGroups($groups)
112+
{
113+
if ( ! $groups) {
114+
$this->exclusionStrategy = null;
115+
116+
return $this;
117+
}
118+
119+
$this->exclusionStrategy = new GroupsExclusionStrategy((array) $groups);
120+
121+
return $this;
122+
}
123+
124+
public function setSerializeNull($bool)
125+
{
126+
$this->serializeNull = (boolean) $bool;
127+
128+
return $this;
129+
}
130+
131+
public function shouldSerializeNull()
132+
{
133+
return $this->serializeNull;
134+
}
135+
136+
public function getDirection()
137+
{
138+
return $this->direction;
139+
}
140+
141+
public function getFormat()
142+
{
143+
return $this->format;
144+
}
145+
146+
public function startVisiting($object)
147+
{
148+
if ($this->direction !== GraphNavigator::DIRECTION_SERIALIZATION) {
149+
return;
150+
}
151+
152+
$this->visitingSet->attach($object);
153+
$this->visitingStack->push($object);
154+
}
155+
156+
public function stopVisiting($object)
157+
{
158+
if ($this->direction !== GraphNavigator::DIRECTION_SERIALIZATION) {
159+
return;
160+
}
161+
162+
$this->visitingSet->detach($object);
163+
$poppedObject = $this->visitingStack->pop();
164+
165+
if ($object !== $poppedObject) {
166+
throw new RuntimeException('Context visitingStack not working well');
167+
}
168+
}
169+
170+
public function isVisiting($object)
171+
{
172+
if (! is_object($object)) {
173+
throw new LogicException('Expected object but got ' . gettype($object) . '. Do you have the wrong @Type mapping or could this be a Doctrine many-to-many relation?');
174+
}
175+
return $this->visitingSet->contains($object);
176+
}
177+
178+
public function getPath()
179+
{
180+
$path = array();
181+
foreach ($this->visitingStack as $obj) {
182+
$path[] = get_class($obj);
183+
}
184+
185+
if ( ! $path) {
186+
return null;
187+
}
188+
189+
return implode(' -> ', $path);
190+
}
191+
192+
public function getDepth()
193+
{
194+
return $this->visitingStack->count();
195+
}
196+
197+
public function getObject()
198+
{
199+
return !$this->visitingStack->isEmpty() ? $this->visitingStack->top() : null;
200+
}
201+
}

src/JMS/Serializer/EventDispatcher/Event.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,30 @@
22

33
namespace JMS\Serializer\EventDispatcher;
44

5+
use JMS\Serializer\Context;
56
use JMS\Serializer\VisitorInterface;
67

78
class Event
89
{
910
protected $type;
1011
private $object;
11-
private $visitor;
12+
private $context;
1213

13-
public function __construct(VisitorInterface $visitor, $object, array $type)
14+
public function __construct(Context $context, $object, array $type)
1415
{
15-
$this->visitor = $visitor;
16+
$this->context = $context;
1617
$this->object = $object;
1718
$this->type = $type;
1819
}
1920

2021
public function getVisitor()
2122
{
22-
return $this->visitor;
23+
return $this->context->getVisitor();
24+
}
25+
26+
public function getContext()
27+
{
28+
return $this->context;
2329
}
2430

2531
public function getType()

src/JMS/Serializer/Exclusion/ExclusionStrategyInterface.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
use JMS\Serializer\Metadata\ClassMetadata;
2222
use JMS\Serializer\Metadata\PropertyMetadata;
23-
use JMS\Serializer\NavigatorContext;
23+
use JMS\Serializer\Context;
2424

2525
/**
2626
* Interface for exclusion strategies.
@@ -33,19 +33,19 @@ interface ExclusionStrategyInterface
3333
* Whether the class should be skipped.
3434
*
3535
* @param ClassMetadata $metadata
36-
* @param NavigatorContext $navigatorContext
36+
* @param Context $navigatorContext
3737
*
3838
* @return boolean
3939
*/
40-
public function shouldSkipClass(ClassMetadata $metadata, NavigatorContext $navigatorContext);
40+
public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext);
4141

4242
/**
4343
* Whether the property should be skipped.
4444
*
4545
* @param PropertyMetadata $property
46-
* @param NavigatorContext $navigatorContext
46+
* @param Context $navigatorContext
4747
*
4848
* @return boolean
4949
*/
50-
public function shouldSkipProperty(PropertyMetadata $property, NavigatorContext $navigatorContext);
50+
public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext);
5151
}

src/JMS/Serializer/Exclusion/GroupsExclusionStrategy.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
use JMS\Serializer\Metadata\ClassMetadata;
2222
use JMS\Serializer\Metadata\PropertyMetadata;
23-
use JMS\Serializer\NavigatorContext;
23+
use JMS\Serializer\Context;
2424

2525
class GroupsExclusionStrategy implements ExclusionStrategyInterface
2626
{
@@ -42,15 +42,15 @@ public function __construct(array $groups)
4242
/**
4343
* {@inheritDoc}
4444
*/
45-
public function shouldSkipClass(ClassMetadata $metadata, NavigatorContext $navigatorContext)
45+
public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext)
4646
{
4747
return false;
4848
}
4949

5050
/**
5151
* {@inheritDoc}
5252
*/
53-
public function shouldSkipProperty(PropertyMetadata $property, NavigatorContext $navigatorContext)
53+
public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext)
5454
{
5555
if ( ! $property->groups) {
5656
return ! isset($this->groups[self::DEFAULT_GROUP]);

src/JMS/Serializer/Exclusion/VersionExclusionStrategy.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
use JMS\Serializer\Metadata\ClassMetadata;
2222
use JMS\Serializer\Metadata\PropertyMetadata;
23-
use JMS\Serializer\NavigatorContext;
23+
use JMS\Serializer\Context;
2424

2525
class VersionExclusionStrategy implements ExclusionStrategyInterface
2626
{
@@ -34,15 +34,15 @@ public function __construct($version)
3434
/**
3535
* {@inheritDoc}
3636
*/
37-
public function shouldSkipClass(ClassMetadata $metadata, NavigatorContext $navigatorContext)
37+
public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext)
3838
{
3939
return false;
4040
}
4141

4242
/**
4343
* {@inheritDoc}
4444
*/
45-
public function shouldSkipProperty(PropertyMetadata $property, NavigatorContext $navigatorContext)
45+
public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext)
4646
{
4747
if ((null !== $version = $property->sinceVersion) && version_compare($this->version, $version, '<')) {
4848
return true;

0 commit comments

Comments
 (0)