Completed
Pull Request — master (#5)
by David
02:09
created

DiscoveryFileLoader   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 117
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 4
dl 0
loc 117
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
C loadDiscoveryFile() 0 25 7
A isAssoc() 0 7 2
A getContents() 0 11 2
A toAssetOperation() 0 8 2
A saveDiscoveryFile() 0 9 2
A simplify() 0 12 2
1
<?php
2
3
4
namespace TheCodingMachine\Discovery;
5
6
use Seld\JsonLint\JsonParser;
7
use Seld\JsonLint\ParsingException;
8
use TheCodingMachine\Discovery\Utils\IOException;
9
use TheCodingMachine\Discovery\Utils\JsonException;
10
11
/**
12
 * Class in charge of loading a discovery.json file.
13
 */
14
class DiscoveryFileLoader
15
{
16
    /**
17
     * Returns an array of array of asset operations indexed by asset type.
18
     *
19
     * @param \SplFileInfo $file
20
     * @return AssetOperation[][]
21
     * @throws JsonException
22
     */
23
    public function loadDiscoveryFile(\SplFileInfo $file, string $package, string $packageDir) : array
24
    {
25
        $jsonParser = new JsonParser();
26
        try {
27
            $result = $jsonParser->parse($this->getContents($file), JsonParser::PARSE_TO_ASSOC);
28
        } catch (ParsingException $e) {
29
            throw new JsonException(sprintf('Invalid JSON in file "%s": %s', $file->getPath(), $e->getMessage()), 0, $e);
30
        }
31
32
        if (!is_array($result) || !$this->isAssoc($result)) {
33
            throw new JsonException(sprintf('File "%s" should contain a JSON object.', $file->getPath()));
34
        }
35
36
        $assetTypes = [];
37
38
        foreach ($result as $type => $array) {
39
            if (!is_array($array)) {
40
                $array = [$array];
41
            }
42
            foreach ($array as $value) {
43
                $assetTypes[$type][] = $this->toAssetOperation($value, $package, $packageDir);
44
            }
45
        }
46
        return $assetTypes;
47
    }
48
49
    /**
50
     * Returns false if the array is numerically indexed, starting at 0.
51
     *
52
     * @param array $arr
53
     * @return bool
54
     */
55
    private function isAssoc(array $arr)
56
    {
57
        if (array() === $arr) {
58
            return true;
59
        }
60
        return array_keys($arr) !== range(0, count($arr) - 1);
61
    }
62
63
    /**
64
     * Returns the contents of the file.
65
     *
66
     * @param \SplFileInfo $file
67
     * @return string the contents of the file
68
     *
69
     */
70
    private function getContents(\SplFileInfo $file)
71
    {
72
        $level = error_reporting(0);
73
        $content = file_get_contents($file->getPathname());
74
        error_reporting($level);
75
        if (false === $content) {
76
            $error = error_get_last();
77
            throw new IOException($error['message']);
78
        }
79
        return $content;
80
    }
81
82
    /**
83
     * Transforms a value string into a value array.
84
     * Also, if a value array is passed, checks it contains valid data.
85
     *
86
     * @param mixed $value
87
     * @return AssetOperation
88
     */
89
    private function toAssetOperation($value, string $package, string $packageDir) : AssetOperation
90
    {
91
        if (is_array($value)) {
92
            return AssetOperation::buildFromArray($value, $package, $packageDir);
93
        } else {
94
            return AssetOperation::buildFromString((string) $value, $package, $packageDir);
95
        }
96
    }
97
98
    /**
99
     * Saves the list of asset operations into a file.
100
     *
101
     * @param AssetOperation[][] $assetOperationTypes
102
     * @param \SplFileObject $file
103
     */
104
    public function saveDiscoveryFile(array $assetOperationTypes, \SplFileObject $file)
105
    {
106
        $simpleAssetOperationTypes = [];
107
        foreach ($assetOperationTypes as $assetType => $assetOperations) {
108
            $simpleAssetOperationTypes[$assetType] = $this->simplify($assetOperations);
109
        }
110
111
        $file->fwrite(json_encode($simpleAssetOperationTypes, JSON_PRETTY_PRINT));
112
    }
113
114
    /**
115
     * @param AssetOperation[] $assetOperations
116
     * @return array|string
117
     */
118
    private function simplify(array $assetOperations)
119
    {
120
        $simplifiedAssetOperations = array_map(function(AssetOperation $assetOperation) {
121
            return $assetOperation->toSimpleArray();
122
        }, $assetOperations);
123
124
        if (count($simplifiedAssetOperations) === 1) {
125
            return array_values($simplifiedAssetOperations)[0];
126
        } else {
127
            return $simplifiedAssetOperations;
128
        }
129
    }
130
}
131