Completed
Pull Request — master (#3)
by Eric
160:09 queued 158:23
created

Serializer::convertContext()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 14
cts 14
cp 1
rs 9.0534
c 0
b 0
f 0
cc 4
eloc 12
nc 6
nop 1
crap 4
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 100
    public function __construct(SerializerInterface $serializer)
38
    {
39 100
        $this->serializer = $serializer;
40 100
    }
41
42
    /**
43
     * {@inheritdoc}
44
     */
45 90
    public function serialize($data, $format, FOSContext $context)
46
    {
47 90
        return $this->serializer->serialize($data, $format, $this->convertContext($context));
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53 90
    public function deserialize($data, $type, $format, FOSContext $context)
54
    {
55 90
        return $this->serializer->deserialize($data, $type, $format, $this->convertContext($context));
56
    }
57
58
    /**
59
     * @param FOSContext $fosContext
60
     *
61
     * @return Context
62
     */
63 90
    private function convertContext(FOSContext $fosContext)
64
    {
65 90
        $context = new Context();
66 90
        $context->addOptions($fosContext->getAttributes());
67
68 90
        if ($fosContext->getSerializeNull() !== null) {
69 10
            $context->setIgnoreNull(!$fosContext->getSerializeNull());
70 8
        }
71
72 90
        $exclusionStrategies = $this->createExclusionStrategies($fosContext);
73
74 70
        if (!empty($exclusionStrategies)) {
75 50
            $exclusionStrategy = count($exclusionStrategies) > 1
76 42
                ? new ChainExclusionStrategy($exclusionStrategies)
77 50
                : array_shift($exclusionStrategies);
78
79 50
            $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 40
        }
81
82 70
        return $context;
83
    }
84
85
    /**
86
     * @param FOSContext $context
87
     *
88
     * @return ExclusionStrategyInterface[]
89
     */
90 90
    private function createExclusionStrategies(FOSContext $context)
91
    {
92 90
        $exclusionStrategies = [];
93
94 90
        $groups = $context->getGroups();
95 90
        $version = $context->getVersion();
96
97 90
        if (!empty($groups)) {
98 10
            $exclusionStrategies[] = new GroupsExclusionStrategy($groups);
99 8
        }
100
101 90
        if (!empty($version)) {
102 10
            $exclusionStrategies[] = new VersionExclusionStrategy($version);
103 8
        }
104
105 90
        if (method_exists($context, 'isMaxDepthEnabled')) {
106 72
            if ($context->isMaxDepthEnabled()) {
107 24
                $exclusionStrategies[] = new MaxDepthExclusionStrategy();
108 6
            }
109 54
        } else {
110 18
            $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 18
            if (!empty($maxDepth)) {
113 2
                $exclusionStrategies[] = new MaxDepthExclusionStrategy($maxDepth);
114 2
            }
115
        }
116
117 90
        $customExclusionStrategies = $context->getAttribute($attribute = 'ivory_exclusion_strategies') ?: [];
118
119 90
        if (!is_array($customExclusionStrategies) && !$customExclusionStrategies instanceof \Traversable) {
120 10
            throw new \RuntimeException(sprintf(
121 10
                'The "%s" context attribute must be an array or implement "%s".',
122 8
                $attribute,
123 2
                \Traversable::class
124 8
            ));
125
        }
126
127 80
        foreach ($customExclusionStrategies as $customExclusionStrategy) {
128 30
            if (!$customExclusionStrategy instanceof ExclusionStrategyInterface) {
129 10
                throw new \RuntimeException(sprintf(
130 10
                    'The "%s" context attribute must be an array of "%s", got "%s".',
131 8
                    $attribute,
132 10
                    ExclusionStrategyInterface::class,
133 10
                    is_object($customExclusionStrategy)
134 8
                        ? get_class($customExclusionStrategy)
135 10
                        : gettype($customExclusionStrategy)
136 8
                ));
137
            }
138
139 20
            $exclusionStrategies[] = $customExclusionStrategy;
140 56
        }
141
142 70
        return $exclusionStrategies;
143
    }
144
}
145