Completed
Push — master ( 654c5d...c6e087 )
by Dorian
02:15
created

YamlLibraryFactory::getClassesMap()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 12

Duplication

Lines 15
Ratio 100 %
Metric Value
dl 15
loc 15
rs 9.4285
cc 1
eloc 12
nc 1
nop 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A YamlLibraryFactory::getLibraryDependencies() 0 8 1
1
<?php
2
3
namespace Gnutix\Library\LibraryFactory;
4
5
use Gnutix\Library\Dumper\YamlLibraryDumper;
6
use Gnutix\Library\Loader\YamlFileLoader;
7
use Gnutix\Library\LibraryFactoryInterface;
8
9
/**
10
 * Library Factory for the YAML data
11
 */
12
class YamlLibraryFactory implements LibraryFactoryInterface
13
{
14
    /** @var array */
15
    protected $classes;
16
17
    /** @var \Gnutix\Library\LibraryInterface */
18
    protected $library;
19
20
    /**
21
     * @param \Gnutix\Library\Loader\YamlFileLoader $loader
22
     * @param array                                $classes
23
     */
24
    public function __construct(YamlFileLoader $loader, $classes)
25
    {
26
        $this->classes = $classes;
27
        $this->library = new $this->classes['library']($this->getLibraryDependencies($loader->getData()));
28
    }
29
30
    /**
31
     * {@inheritDoc}
32
     */
33
    public function getLibrary()
34
    {
35
        return $this->library;
36
    }
37
38
    /**
39
     * @param array $data
40
     *
41
     * @return array
42
     */
43
    protected function getLibraryDependencies(array $data)
44
    {
45
        return array(
46
            'books' => $this->buildBooks($this->get($data, 'books', array())),
47
            'categories' => $this->buildClassInstanceFromArray($this->get($data, 'categories', array()), 'category'),
48
            'editors' => $this->buildClassInstanceFromArray($this->get($data, 'editors', array()), 'editor'),
49
        );
50
    }
51
52
    /**
53
     * @return \Gnutix\Library\Dumper\YamlLibraryDumper
54
     */
55
    public function getLibraryDumper()
56
    {
57
        return new YamlLibraryDumper();
58
    }
59
60
    /**
61
     * @param array  $data        The XML data
62
     * @param string $targetClass The target for the class
63
     * @param array  $renameKeys  The rename keys array
64
     *
65
     * @return array
66
     */
67
    protected function buildClassInstanceFromArray(
68
        array $data,
69
        $targetClass,
70
        array $renameKeys = array()
71
    ) {
72
        $elements = array();
73
        $className = $this->classes[$targetClass];
74
75
        foreach ($data as $element) {
76
            $elements[] = new $className($this->renameArrayKeys($element, $renameKeys));
77
        }
78
79
        return $elements;
80
    }
81
82
    /**
83
     * @param array $books
84
     *
85
     * @return array
86
     */
87
    protected function buildBooks(array $books)
88
    {
89
        $booksObjects = array();
90
91
        foreach ($books as $book) {
92
            $booksObjects[] = new $this->classes['book']($this->getBookDependencies($book));
93
        }
94
95
        return $booksObjects;
96
    }
97
98
    /**
99
     * @param array $book
100
     *
101
     * @return array
102
     */
103
    protected function getBookDependencies(array $book)
104
    {
105
        return array(
106
            'category' => new $this->classes['category']($this->get($book, 'category', array())),
107
            'authors' => $this->buildAuthors($book),
108
            'releases' => $this->buildReleases($this->get($book, 'releases', array())),
109
        );
110
    }
111
112
    /**
113
     * @param array $book
114
     *
115
     * @return array
116
     */
117
    protected function buildAuthors(array $book)
118
    {
119
        $authorsObjects = array();
120
121
        if (null !== $author = $this->get($book, 'author')) {
122
            $book['authors'][] = $author;
123
            unset($book['author']);
124
        }
125
126
        foreach ($this->get($book, 'authors') as $author) {
127
            $authorsObjects[] = new $this->classes['author']($author);
128
        }
129
130
        return $authorsObjects;
131
    }
132
133
    /**
134
     * @param array $releases
135
     *
136
     * @return array
137
     */
138
    protected function buildReleases(array $releases)
139
    {
140
        $releasesObjects = array();
141
142
        foreach ($releases as $release) {
143
            $releasesObjects[] = new $this->classes['release']($this->buildReleaseDependencies($release));
144
        }
145
146
        return $releasesObjects;
147
    }
148
149
    /**
150
     * @param array $release
151
     *
152
     * @return array
153
     */
154
    protected function buildReleaseDependencies(array $release)
155
    {
156
        $that = $this;
157
158
        return array(
159
            'title' => $this->get($release, 'title'),
160
            'language' => new $this->classes['language']($this->get($release, 'language', array())),
161
            'editor' => new $this->classes['editor']($this->get($release, 'editor', array())),
162
            'format' => new $this->classes['format']($this->get($release, 'format', array())),
163
            'publicationDate' => $this->get(
164
                $release,
165
                'publicationDate',
166
                null,
167
                function ($data) use ($that) {
168
                    return $that->transformToDateTime($data);
169
                }
170
            ),
171
            'series' => new $this->classes['series'](
172
                $this->get(
173
                    $release,
174
                    'series',
175
                    array(),
176
                    function ($data) use ($that) {
177
                        return $that->renameArrayKeys($data, array('number' => 'bookId'));
178
                    }
179
                )
180
            ),
181
            'owner' => new $this->classes['owner'](
182
                $this->get(
183
                    $release,
184
                    'owner',
185
                    array(),
186
                    function ($data) use ($that) {
187
                        return $that->renameArrayKeys($data, array('copies' => 'nbCopies', 'readings' => 'nbReadings'));
188
                    }
189
                )
190
            ),
191
        );
192
    }
193
194
    /**
195
     * @param array $date
196
     *
197
     * @return \DateTime
198
     */
199
    public function transformToDateTime(array $date)
200
    {
201
        foreach (array('day', 'month', 'year') as $key) {
202
            if (!isset($date[$key])) {
203
                $date[$key] = 0;
204
            }
205
        }
206
207
        $dateTime = new \DateTime();
208
209
        return $dateTime->setDate($date['year'], $date['month'], $date['day']);
210
    }
211
212
    /**
213
     * @param array $data
214
     * @param array $keys
215
     *
216
     * @return array
217
     */
218
    public function renameArrayKeys(array $data, array $keys)
219
    {
220
        foreach ($keys as $old => $new) {
221
222
            // PS: do not use isset as the value may be null
223
            if (!array_key_exists($old, $data)) {
224
                continue;
225
            }
226
227
            $data[$new] = $data[$old];
228
            unset($data[$old]);
229
        }
230
231
        return $data;
232
    }
233
234
    /**
235
     * @param array    $data
236
     * @param string   $index
237
     * @param mixed    $default
238
     * @param \Closure $callback
239
     * @param bool     $throwException
240
     *
241
     * @return mixed
242
     * @throws \InvalidArgumentException
243
     */
244
    protected function get(array $data, $index, $default = null, \Closure $callback = null, $throwException = false)
245
    {
246
        if (isset($data[$index])) {
247
            if (is_callable($callback)) {
248
                return $callback($data[$index]);
249
            }
250
251
            return $data[$index];
252
        }
253
254
        if (!$throwException) {
255
            return $default;
256
        }
257
258
        throw new \InvalidArgumentException('Index "'.$index.'" could not be found.');
259
    }
260
}
261