Serializer::convertContext()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.584
c 0
b 0
f 0
cc 4
nc 6
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Ivory Serializer bundle package.
5
 *
6
 * (c) Eric GELOEN <[email protected]>
7
 *
8
 * For the full copyright and license information, please read the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Ivory\SerializerBundle\FOS;
13
14
use FOS\RestBundle\Context\Context as FOSContext;
15
use FOS\RestBundle\Serializer\Serializer as FOSSerializerInterface;
16
use Ivory\Serializer\Context\Context;
17
use Ivory\Serializer\Exclusion\ChainExclusionStrategy;
18
use Ivory\Serializer\Exclusion\ExclusionStrategyInterface;
19
use Ivory\Serializer\Exclusion\GroupsExclusionStrategy;
20
use Ivory\Serializer\Exclusion\MaxDepthExclusionStrategy;
21
use Ivory\Serializer\Exclusion\VersionExclusionStrategy;
22
use Ivory\Serializer\SerializerInterface;
23
24
/**
25
 * @author GeLo <[email protected]>
26
 */
27
class Serializer implements FOSSerializerInterface
28
{
29
    /**
30
     * @var SerializerInterface
31
     */
32
    private $serializer;
33
34
    /**
35
     * @param SerializerInterface $serializer
36
     */
37
    public function __construct(SerializerInterface $serializer)
38
    {
39
        $this->serializer = $serializer;
40
    }
41
42
    /**
43
     * {@inheritdoc}
44
     */
45
    public function serialize($data, $format, FOSContext $context)
46
    {
47
        return $this->serializer->serialize($data, $format, $this->convertContext($context));
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    public function deserialize($data, $type, $format, FOSContext $context)
54
    {
55
        return $this->serializer->deserialize($data, $type, $format, $this->convertContext($context));
56
    }
57
58
    /**
59
     * @param FOSContext $fosContext
60
     *
61
     * @return Context
62
     */
63
    private function convertContext(FOSContext $fosContext)
64
    {
65
        $context = new Context();
66
        $context->addOptions($fosContext->getAttributes());
67
68
        if ($fosContext->getSerializeNull() !== null) {
69
            $context->setIgnoreNull(!$fosContext->getSerializeNull());
70
        }
71
72
        $exclusionStrategies = $this->createExclusionStrategies($fosContext);
73
74
        if (!empty($exclusionStrategies)) {
75
            $exclusionStrategy = count($exclusionStrategies) > 1
76
                ? new ChainExclusionStrategy($exclusionStrategies)
77
                : array_shift($exclusionStrategies);
78
79
            $context->setExclusionStrategy($exclusionStrategy);
0 ignored issues
show
Bug introduced by
It seems like $exclusionStrategy defined by count($exclusionStrategi...t($exclusionStrategies) on line 75 can be null; however, Ivory\Serializer\Context...:setExclusionStrategy() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
80
        }
81
82
        return $context;
83
    }
84
85
    /**
86
     * @param FOSContext $context
87
     *
88
     * @return ExclusionStrategyInterface[]
89
     */
90
    private function createExclusionStrategies(FOSContext $context)
91
    {
92
        $exclusionStrategies = [];
93
94
        $groups = $context->getGroups();
95
        $version = $context->getVersion();
96
97
        if (!empty($groups)) {
98
            $exclusionStrategies[] = new GroupsExclusionStrategy($groups);
99
        }
100
101
        if (!empty($version)) {
102
            $exclusionStrategies[] = new VersionExclusionStrategy($version);
103
        }
104
105
        if (method_exists($context, 'isMaxDepthEnabled')) {
106
            if ($context->isMaxDepthEnabled()) {
107
                $exclusionStrategies[] = new MaxDepthExclusionStrategy();
108
            }
109
        } else {
110
            $maxDepth = $context->getMaxDepth();
0 ignored issues
show
Deprecated Code introduced by
The method FOS\RestBundle\Context\Context::getMaxDepth() has been deprecated with message: since version 2.1, to be removed in 3.0. Use {@link self::isMaxDepthEnabled()} instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
111
112
            if (!empty($maxDepth)) {
113
                $exclusionStrategies[] = new MaxDepthExclusionStrategy($maxDepth);
114
            }
115
        }
116
117
        $customExclusionStrategies = $context->getAttribute($attribute = 'ivory_exclusion_strategies') ?: [];
118
119
        if (!is_array($customExclusionStrategies) && !$customExclusionStrategies instanceof \Traversable) {
120
            throw new \RuntimeException(sprintf(
121
                'The "%s" context attribute must be an array or implement "%s".',
122
                $attribute,
123
                \Traversable::class
124
            ));
125
        }
126
127
        foreach ($customExclusionStrategies as $customExclusionStrategy) {
128
            if (!$customExclusionStrategy instanceof ExclusionStrategyInterface) {
129
                throw new \RuntimeException(sprintf(
130
                    'The "%s" context attribute must be an array of "%s", got "%s".',
131
                    $attribute,
132
                    ExclusionStrategyInterface::class,
133
                    is_object($customExclusionStrategy)
134
                        ? get_class($customExclusionStrategy)
135
                        : gettype($customExclusionStrategy)
136
                ));
137
            }
138
139
            $exclusionStrategies[] = $customExclusionStrategy;
140
        }
141
142
        return $exclusionStrategies;
143
    }
144
}
145