Completed
Pull Request — develop (#14)
by Michael
06:03
created

CachedSchemaStorage::getSchemaByRoute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Sulu\Bundle\ValidationBundle\JsonSchema;
4
5
use InvalidArgumentException;
6
use JsonSchema\Entity\JsonPointer;
7
use JsonSchema\Iterator\ObjectIterator;
8
use JsonSchema\SchemaStorage;
9
use Sulu\Bundle\ValidationBundle\Exceptions\MalFormedJsonException;
10
use Symfony\Component\Config\ConfigCache;
11
use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
12
use Symfony\Component\Config\FileLocatorInterface;
13
use Symfony\Component\Config\Resource\FileResource;
14
15
class CachedSchemaStorage extends SchemaStorage
16
{
17
    const FILE_PREFIX = 'file://';
18
19
    /**
20
     * @var FileLocatorInterface
21
     */
22
    private $fileLocator;
23
24
    /**
25
     * @var array
26
     */
27
    private $configuredSchemas;
28
29
    /**
30
     * @var bool
31
     */
32
    private $debugMode;
33
34
    /**
35
     * @var string
36
     */
37
    private $cacheFilePath;
38
39
    /**
40
     * @param array                $configuredSchemas array containing all file paths to configured schemas
41
     * @param FileLocatorInterface $fileLocator
42
     * @param string               $cacheFilePath
43
     * @param string               $environment
44
     */
45 10
    public function __construct(
46
        array $configuredSchemas,
47
        FileLocatorInterface $fileLocator,
48
        $cacheFilePath,
49
        $environment
50
    ) {
51 10
        parent::__construct();
52
53 10
        $this->fileLocator = $fileLocator;
54 10
        $this->configuredSchemas = $configuredSchemas;
55 10
        $this->debugMode = $environment !== 'prod';
56 10
        $this->cacheFilePath = $cacheFilePath;
57 10
    }
58
59 8
    public function initializeCache()
60
    {
61 8
        $schemaCache = new ConfigCache($this->cacheFilePath, $this->debugMode);
62
63 8
        if (!$schemaCache->isFresh()) {
64 1
            $resources = [];
65 1
            $processedSchemas = [];
66
67 1
            foreach ($this->configuredSchemas as $schemaPath) {
68 1
                $this->processSchema($schemaPath, $processedSchemas, $resources);
69
            }
70
71 1
            $schemaCache->write(serialize($processedSchemas), $resources);
72
        }
73
74 8
        $this->schemas = unserialize(file_get_contents($schemaCache->getPath()));
75 8
    }
76
77
    /**
78
     * @param string $routeId
79
     *
80
     * @return object
81
     * @throws InvalidArgumentException
82
     */
83 8
    public function getSchemaByRoute($routeId)
84
    {
85 8
        $schemaFilePath = self::FILE_PREFIX . $this->fileLocator->locate($this->configuredSchemas[$routeId]);
86
87 8
        return $this->getSchema($schemaFilePath);
88
    }
89
90
    /**
91
     * @param string $schemaPath
92
     * @param array  $serializedSchemas
93
     * @param array  $resources
94
     *
95
     * @throws MalFormedJsonException
96
     * @throws InvalidArgumentException
97
     * @throws FileLocatorFileNotFoundException
98
     */
99 1
    protected function processSchema($schemaPath, array &$serializedSchemas, array &$resources)
100
    {
101 1
        if (array_key_exists($schemaPath, $serializedSchemas)) {
102 1
            return;
103
        }
104
105 1
        $absoluteSchemaPath = $this->fileLocator->locate($schemaPath);
106 1
        $schema = json_decode(file_get_contents($absoluteSchemaPath));
107
108 1
        if (json_last_error() !== JSON_ERROR_NONE) {
109
            throw new MalFormedJsonException('Malformed json encountered in ' . $schemaPath);
110
        }
111
112 1
        if (strpos($absoluteSchemaPath, self::FILE_PREFIX) !== 0) {
113 1
            $absoluteSchemaPath = self::FILE_PREFIX . $absoluteSchemaPath;
114
        }
115
116 1
        $serializedSchemas[$absoluteSchemaPath] = $schema;
117 1
        $resources[] = new FileResource($absoluteSchemaPath);
0 ignored issues
show
Bug introduced by
It seems like $absoluteSchemaPath defined by $this->fileLocator->locate($schemaPath) on line 105 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...
118 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 105 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...
119 1
    }
120
121
    /**
122
     * @param mixed  $schema
123
     * @param string $schemaFilePath
124
     * @param array  $serializedSchemas
125
     * @param array  $resources
126
     *
127
     * @throws MalFormedJsonException
128
     * @throws InvalidArgumentException
129
     * @throws FileLocatorFileNotFoundException
130
     */
131 1
    protected function processReferencesInSchema($schema, $schemaFilePath, array &$serializedSchemas, array &$resources)
132
    {
133 1
        $objectIterator = new ObjectIterator($schema);
134 1
        foreach ($objectIterator as $toResolveSchema) {
135 1
            if (property_exists($toResolveSchema, '$ref') && is_string($toResolveSchema->{'$ref'})) {
136 1
                $uri = $this->uriResolver->resolve($toResolveSchema->{'$ref'}, $schemaFilePath);
137 1
                $jsonPointer = new JsonPointer($uri);
138 1
                $toResolveSchema->{'$ref'} = (string)$jsonPointer;
139 1
                $this->processSchema($jsonPointer->getFilename(), $serializedSchemas, $resources);
140
            }
141
        }
142 1
    }
143
}
144