Completed
Pull Request — master (#3)
by Eric
64:57
created

Serializer::serialize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 3
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
        if ($context->getGroups() !== null) {
95
            $exclusionStrategies[] = new GroupsExclusionStrategy($context->getGroups());
96
        }
97
98
        if ($context->getVersion() !== null) {
99
            $exclusionStrategies[] = new VersionExclusionStrategy($context->getVersion());
100
        }
101
102
        if ($context->isMaxDepthEnabled() !== null) {
103
            $exclusionStrategies[] = new MaxDepthExclusionStrategy();
104
        }
105
106
        $customExclusionStrategies = $context->getAttribute($attribute = 'ivory_exclusion_strategies') ?: [];
107
108
        if (!is_array($customExclusionStrategies) && !$customExclusionStrategies instanceof \Traversable) {
109
            throw new \RuntimeException(sprintf(
110
                'The "%s" context attribute must be an array or implement "%s".',
111
                $attribute,
112
                \Traversable::class
113
            ));
114
        }
115
116
        foreach ($customExclusionStrategies as $customExclusionStrategy) {
117
            if (!$customExclusionStrategy instanceof ExclusionStrategyInterface) {
118
                throw new \RuntimeException(sprintf(
119
                    'The "%s" context attribute must be an array of "%s", got "%s".',
120
                    $attribute,
121
                    ExclusionStrategyInterface::class,
122
                    is_object($customExclusionStrategy)
123
                        ? get_class($customExclusionStrategy)
124
                        : gettype($customExclusionStrategy)
125
                ));
126
            }
127
128
            $exclusionStrategies[] = $customExclusionStrategy;
129
        }
130
131
        return $exclusionStrategies;
132
    }
133
}
134