AbstractResource::setPart()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 2
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
ccs 3
cts 3
cp 1
crap 1
1
<?php
2
3
/**
4
 * apparat-resource
5
 *
6
 * @category    Apparat
7
 * @package     Apparat\Resource
8
 * @subpackage Apparat\Resource\Domain
9
 * @author      Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright   Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license     http://opensource.org/licenses/MIT The MIT License (MIT)
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
18
 *
19
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
20
 *  this software and associated documentation files (the "Software"), to deal in
21
 *  the Software without restriction, including without limitation the rights to
22
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
23
 *  the Software, and to permit persons to whom the Software is furnished to do so,
24
 *  subject to the following conditions:
25
 *
26
 *  The above copyright notice and this permission notice shall be included in all
27
 *  copies or substantial portions of the Software.
28
 *
29
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
31
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
32
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
33
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 ***********************************************************************************/
36
37
namespace Apparat\Resource\Domain\Model\Resource;
38
39
use Apparat\Resource\Domain\Contract\ReaderInterface;
40
use Apparat\Resource\Domain\Contract\WriterInterface;
41
use Apparat\Resource\Domain\Factory\HydratorFactory;
42
use Apparat\Resource\Domain\Model\Hydrator\HydratorInterface;
43
use Apparat\Resource\Domain\Model\Part\AbstractPart;
44
use Apparat\Resource\Domain\Model\Part\PartInterface;
45
46
/**
47
 * File
48
 *
49
 * @package     Apparat\Resource
50
 * @subpackage Apparat\Resource\Domain
51
 * @method string getMediaTypePart($part = '/') getMediaTypePart($part = '/') Get the media type of a particular part
52
 */
53
abstract class AbstractResource
54
{
55
    /**
56
     * Part or part aggregate
57
     *
58
     * @var PartInterface
59
     */
60
    protected $part = null;
61
62
    /**
63
     * Reader instance
64
     *
65
     * @var ReaderInterface
66
     */
67
    protected $reader = null;
68
    /**
69
     * File hydrator
70
     *
71
     * @var HydratorInterface
72
     */
73
    private $hydrator = null;
74
75
    /*******************************************************************************
76
     * PUBLIC METHODS
77
     *******************************************************************************/
78
79
    /**
80
     * Private constructor
81
     *
82
     * @param HydratorInterface|array|string $hydrator File hydrator
83
     * @param ReaderInterface $reader Reader instance
84
     */
85 71
    protected function __construct($hydrator, ReaderInterface $reader = null)
86
    {
87
        // If the hydrator needs to be instantiated from a string or array
88 71
        if (!($hydrator instanceof HydratorInterface)) {
89 71
            $hydrator = HydratorFactory::build((array)$hydrator);
90
        }
91
92
        // Register the hydrator
93 71
        $this->hydrator = $hydrator;
94
95
        // Register the reader if available
96 71
        if ($reader instanceof ReaderInterface) {
97 50
            $this->load($reader);
98
        }
99 71
    }
100
101
    /**
102
     * Set a reader instance for this file
103
     *
104
     * @param ReaderInterface $reader Reader instance
105
     * @return AbstractResource Self reference
106
     */
107 51
    public function load(ReaderInterface $reader)
108
    {
109 51
        $this->reset();
110 51
        $this->reader = $reader;
111 51
        return $this;
112
    }
113
114
    /**
115
     * Reset the file
116
     *
117
     * @return void
118
     */
119 51
    protected function reset()
120
    {
121 51
        $this->part = null;
122 51
    }
123
124
    /**
125
     * Dump this files contents into a writer
126
     *
127
     * @param WriterInterface $writer Writer instance
128
     * @return AbstractResource Self reference
129
     */
130 12
    public function dump(WriterInterface $writer)
131
    {
132 12
        $writer->write($this->getPart('/'));
133 12
        return $this;
134
    }
135
136
    /**
137
     * Return the part's content
138
     *
139
     * @param string $part Part path
140
     * @return string Part content
141
     */
142 46
    public function getPart($part = '/')
143
    {
144 46
        $partPath = $this->partPath($part);
145 44
        $part = $this->part()->get($partPath);
146 39
        return $part->getHydrator()->dehydrate($part);
147
    }
148
149
    /*******************************************************************************
150
     * PRIVATE METHODS
151
     *******************************************************************************/
152
153
    /**
154
     * Set the content of a particular part
155
     *
156
     * @param mixed $data Content
157
     * @param string $part Part path
158
     * @return AbstractResource Self reference
159
     */
160 12
    public function setPart($data, $part = '/')
161
    {
162 12
        $this->part = $this->part()->set($data, $this->partPath($part));
163 12
        return $this;
164
    }
165
166
    /**
167
     * Split a part path string into path identifiers
168
     *
169
     * @param string $path Part path string
170
     * @return array Part path identifiers
171
     */
172 67
    protected function partPath($path)
173
    {
174 67
        return (trim($path) == '/') ? [] : array_map(
175 24
            function ($pathIdentifier) {
176 24
                $pathIdentifier = trim($pathIdentifier);
177 24
                AbstractPart::validatePartIdentifier($pathIdentifier);
178 23
                return $pathIdentifier;
179 24
            },
180 67
            explode('/', ltrim($path, '/'))
181
        );
182
    }
183
184
    /**
185
     * Lazy-hydrate and return the main file part
186
     *
187
     * @return PartInterface Main file part
188
     */
189 66
    protected function part()
190
    {
191 66
        if (!($this->part instanceof PartInterface)) {
192 66
            $this->part = $this->hydrator->hydrate(
193 66
                ($this->reader instanceof ReaderInterface) ? $this->reader->read() : ''
194
            );
195
        }
196 66
        return $this->part;
197
    }
198
199
    /**
200
     * Magic caller for part methods
201
     *
202
     * @param string $name Part method name
203
     * @param array $arguments Part method arguments
204
     * @return mixed|AbstractResource Self reference
205
     * @throw RuntimeException  If an invalid file method is called
206
     * @throw RuntimeException  If an invalid file part method is called
207
     */
208 32
    public function __call($name, array $arguments)
209
    {
210
        // If a (sub)part method is called
211 32
        if (preg_match("%^(.+)Part$%", $name, $partMethod)) {
212 31
            return $this->callPartMethod($partMethod, $arguments);
213
        }
214
215 1
        throw new RuntimeException(
216 1
            sprintf('Invalid file method "%s"', $name),
217 1
            RuntimeException::INVALID_FILE_METHOD
218
        );
219
    }
220
221
    /**
222
     * Call a method on one of the subparts
223
     *
224
     * @param array $partMethod Part method components
225
     * @param array $arguments Part method arguments
226
     * @return mixed|AbstractResource Getter result / self reference
227
     */
228 31
    protected function callPartMethod(array $partMethod, array $arguments)
229
    {
230 31
        $partMethod = $partMethod[1];
231 31
        return strncmp('get', $partMethod, 3)
232 16
            ? $this->callNonGetterPartMethod($partMethod, $arguments)
233 29
            : $this->callGetterPartMethod($partMethod, $arguments);
234
    }
235
236
    /**
237
     * Call a non-getter method on one of the subparts
238
     *
239
     * @param string $partMethod Part method
240
     * @param array $arguments Part method arguments
241
     * @return AbstractResource Self reference
242
     */
243 16
    protected function callNonGetterPartMethod($partMethod, array $arguments)
244
    {
245 16
        $subparts = $this->partPath((count($arguments) > 1) ? $arguments[1] : '/');
246 16
        $this->part = $this->part()->delegate($partMethod, $subparts, array_slice($arguments, 0, 1));
247 14
        return $this;
248
    }
249
250
    /**
251
     * Call a getter method on one of the subparts
252
     *
253
     * @param string $partMethod Part method
254
     * @param array $arguments Part method arguments
255
     * @return mixed Getter result
256
     */
257 19
    protected function callGetterPartMethod($partMethod, array $arguments)
258
    {
259 19
        $subparts = $this->partPath(count($arguments) ? $arguments[0] : '/');
260 19
        return $this->part()->delegate($partMethod, $subparts, []);
261
    }
262
}
263