Completed
Pull Request — develop (#14)
by Michael
02:56 queued 52s
created

CachedSchemaStorage   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 130
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 97.62%

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 8
dl 0
loc 130
ccs 41
cts 42
cp 0.9762
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 1
A initializeCache() 0 17 3
A getSchemaByRoute() 0 6 1
A processSchema() 0 21 4
A processReferencesInSchema() 0 12 4
1
<?php
2
3
/*
4
 * This file is part of Sulu.
5
 *
6
 * (c) MASSIVE ART WebServices GmbH
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace Sulu\Bundle\ValidationBundle\JsonSchema;
13
14
use InvalidArgumentException;
15
use JsonSchema\Entity\JsonPointer;
16
use JsonSchema\Iterator\ObjectIterator;
17
use JsonSchema\SchemaStorage;
18
use Sulu\Bundle\ValidationBundle\Exceptions\MalFormedJsonException;
19
use Symfony\Component\Config\ConfigCache;
20
use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
21
use Symfony\Component\Config\FileLocatorInterface;
22
use Symfony\Component\Config\Resource\FileResource;
23
24
class CachedSchemaStorage extends SchemaStorage
25
{
26
    const FILE_PREFIX = 'file://';
27
28
    /**
29
     * @var FileLocatorInterface
30
     */
31
    private $fileLocator;
32
33
    /**
34
     * @var array
35
     */
36
    private $configuredSchemas;
37
38
    /**
39
     * @var bool
40
     */
41
    private $debugMode;
42
43
    /**
44
     * @var string
45
     */
46
    private $cacheFilePath;
47
48
    /**
49
     * @param array                $configuredSchemas array containing all file paths to configured schemas
50
     * @param FileLocatorInterface $fileLocator
51
     * @param string               $cacheFilePath
52
     * @param string               $environment
53
     */
54 10
    public function __construct(
55
        array $configuredSchemas,
56
        FileLocatorInterface $fileLocator,
57
        $cacheFilePath,
58
        $environment
59
    ) {
60 10
        parent::__construct();
61
62 10
        $this->fileLocator = $fileLocator;
63 10
        $this->configuredSchemas = $configuredSchemas;
64 10
        $this->debugMode = $environment !== 'prod';
65 10
        $this->cacheFilePath = $cacheFilePath;
66 10
    }
67
68 9
    public function initializeCache()
69
    {
70 9
        $schemaCache = new ConfigCache($this->cacheFilePath, $this->debugMode);
71
72 9
        if (!$schemaCache->isFresh()) {
73 1
            $resources = [];
74 1
            $processedSchemas = [];
75
76 1
            foreach ($this->configuredSchemas as $schemaPath) {
77 1
                $this->processSchema($schemaPath, $processedSchemas, $resources);
78
            }
79
80 1
            $schemaCache->write(serialize($processedSchemas), $resources);
81
        }
82
83 9
        $this->schemas = unserialize(file_get_contents($schemaCache->getPath()));
84 9
    }
85
86
    /**
87
     * @param string $routeId
88
     *
89
     * @return mixed
90
     *
91
     * @throws InvalidArgumentException
92
     */
93 8
    public function getSchemaByRoute($routeId)
94
    {
95 8
        $schemaFilePath = self::FILE_PREFIX . $this->fileLocator->locate($this->configuredSchemas[$routeId]);
96
97 8
        return $this->getSchema($schemaFilePath);
98
    }
99
100
    /**
101
     * @param string $schemaPath
102
     * @param array  $serializedSchemas
103
     * @param array  $resources
104
     *
105
     * @throws MalFormedJsonException
106
     * @throws InvalidArgumentException
107
     * @throws FileLocatorFileNotFoundException
108
     */
109 1
    protected function processSchema($schemaPath, array &$serializedSchemas, array &$resources)
110
    {
111 1
        if (array_key_exists($schemaPath, $serializedSchemas)) {
112 1
            return;
113
        }
114
115 1
        $absoluteSchemaPath = $this->fileLocator->locate($schemaPath);
116 1
        $schema = json_decode(file_get_contents($absoluteSchemaPath));
117
118 1
        if (json_last_error() !== JSON_ERROR_NONE) {
119
            throw new MalFormedJsonException('Malformed json encountered in ' . $schemaPath);
120
        }
121
122 1
        if (strpos($absoluteSchemaPath, self::FILE_PREFIX) !== 0) {
123 1
            $absoluteSchemaPath = self::FILE_PREFIX . $absoluteSchemaPath;
124
        }
125
126 1
        $serializedSchemas[$absoluteSchemaPath] = $schema;
127 1
        $resources[] = new FileResource($absoluteSchemaPath);
0 ignored issues
show
Bug introduced by
It seems like $absoluteSchemaPath defined by $this->fileLocator->locate($schemaPath) on line 115 can also be of type array; however, Symfony\Component\Config...Resource::__construct() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
128 1
        $this->processReferencesInSchema($schema, $absoluteSchemaPath, $serializedSchemas, $resources);
0 ignored issues
show
Bug introduced by
It seems like $absoluteSchemaPath defined by $this->fileLocator->locate($schemaPath) on line 115 can also be of type array; however, Sulu\Bundle\ValidationBu...essReferencesInSchema() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
129 1
    }
130
131
    /**
132
     * @param mixed  $schema
133
     * @param string $schemaFilePath
134
     * @param array  $serializedSchemas
135
     * @param array  $resources
136
     *
137
     * @throws MalFormedJsonException
138
     * @throws InvalidArgumentException
139
     * @throws FileLocatorFileNotFoundException
140
     */
141 1
    protected function processReferencesInSchema($schema, $schemaFilePath, array &$serializedSchemas, array &$resources)
142
    {
143 1
        $objectIterator = new ObjectIterator($schema);
144 1
        foreach ($objectIterator as $toResolveSchema) {
145 1
            if (property_exists($toResolveSchema, '$ref') && is_string($toResolveSchema->{'$ref'})) {
146 1
                $uri = $this->uriResolver->resolve($toResolveSchema->{'$ref'}, $schemaFilePath);
147 1
                $jsonPointer = new JsonPointer($uri);
148 1
                $toResolveSchema->{'$ref'} = (string) $jsonPointer;
149 1
                $this->processSchema($jsonPointer->getFilename(), $serializedSchemas, $resources);
150
            }
151
        }
152 1
    }
153
}
154