Completed
Push — master ( 9e945f...ca30df )
by Joschi
03:04
created

AbstractObjectMutator::formatRelation()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 2
c 0
b 0
f 0
nc 1
nop 3
dl 0
loc 4
ccs 0
cts 0
cp 0
crap 6
rs 10
1
<?php
2
3
/**
4
 * apparat-dev
5
 *
6
 * @category    Apparat
7
 * @package     Apparat\Dev
8
 * @subpackage  Apparat\Dev\Infrastructure
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\Dev\Infrastructure\Mutator;
38
39
use Apparat\Dev\Ports\RuntimeException;
40
use Apparat\Object\Domain\Model\Object\ObjectInterface;
41
use Apparat\Object\Ports\Types\Relation;
42
use Faker\Generator;
43
44
/**
45
 * Abstract object mutator
46
 *
47
 * @package Apparat\Server
48
 * @subpackage Apparat\Dev\Infrastructure\Mutator
49
 * @method ObjectInterface setRandomTitle(ObjectInterface $object, $probability)
50
 * @method ObjectInterface setRandomDescription(ObjectInterface $object, $probability)
51
 * @method ObjectInterface setRandomAbstract(ObjectInterface $object, $probability)
52
 * @method ObjectInterface setRandomCategories(ObjectInterface $object, $probability)
53
 * @method ObjectInterface setRandomKeywords(ObjectInterface $object, $probability)
54
 * @method ObjectInterface setRandomLocation(ObjectInterface $object, $probability)
55
 * @method ObjectInterface setRandomSyndication(ObjectInterface $object, $probability)
56
 * @method ObjectInterface setRandomFeatured(ObjectInterface $object, $probability)
57
 * @method ObjectInterface setRandomAdditionalAuthor(ObjectInterface $object, $probability)
58
 * @method ObjectInterface setRandomAdditionalSyndication(ObjectInterface $object, $probability)
59
 */
60
abstract class AbstractObjectMutator implements ObjectMutatorInterface
61
{
62
    /**
63 1
     * Fake data generator
64
     *
65 1
     * @var Generator
66 1
     */
67
    protected $generator;
68
    /**
69
     * Twitter status URL
70
     *
71
     * @var string
72
     */
73
    const TWITTER_STATUS = 'https://twitter.com/%s/status/%s';
74
    /**
75
     * Facebook post URL
76 1
     *
77
     * @var string
78
     */
79 1
    const FACEBOOK_POST = 'https://www.facebook.com/%s/posts/%s';
80 1
    /**
81
     * Google+ post URL
82
     *
83
     * @var string
84
     */
85
    const GOOGLEPLUS_POST = 'https://plus.google.com/+%s/posts/%s';
86
    /**
87
     * Instagram post URL
88 1
     *
89
     * @var string
90
     */
91
    const INSTAGRAM_POST = 'https://www.instagram.com/p/%s/';
92
93 1
    /**
94 1
     * Abstract object mutator constructor
95
     *
96
     * @param Generator $generator
97 1
     */
98
    public function __construct(Generator $generator)
99
    {
100
        $this->generator = $generator;
101
    }
102
103
    /**
104
     * Magic setter for randomization of setter calls
105
     *
106
     * @param string $method Method name
107
     * @param array $arguments Arguments
108
     * @return ObjectInterface Object
109
     * @throws RuntimeException If the randomized setter is invalid
110
     */
111
    public function __call($method, array $arguments)
112
    {
113
        // If the randomized setter is invalid
114
        $setterMethod = 'set'.substr($method, 9);
115
        if (strncmp('setRandom', $method, 9) || !is_callable([$this, $setterMethod])) {
116
            throw new RuntimeException(
117
                sprintf('Invalid randomized setter "%s"', $setterMethod),
118
                RuntimeException::INVALID_RANDOMIZED_SETTER
119
            );
120
        }
121
122
        // If no object is given
123
        if (!count($arguments) || !($arguments[0] instanceof ObjectInterface)) {
124
            throw new RuntimeException('Invalid mutator subject', RuntimeException::INVALID_MUTATOR_SUBJECT);
125
        }
126
127
        // If the setter call should be randomized
128
        if ((count($arguments) > 1) && !$this->happens($arguments[1])) {
129
            return $arguments[0];
130
        }
131
132
        return $this->$setterMethod(...$arguments);
133
    }
134
135
136
    /**
137
     * Set the object title
138
     *
139
     * @param ObjectInterface $object Object
140
     * @return ObjectInterface $object Object
141
     */
142
    protected function setTitle(ObjectInterface $object)
143
    {
144
        return $object->setTitle($this->generator->text(70));
145
    }
146
147
    /**
148
     * Set the object title
149
     *
150
     * @param ObjectInterface $object Object
151
     * @return ObjectInterface $object Object
152
     */
153
    protected function setLocation(ObjectInterface $object)
154
    {
155
        /** @noinspection PhpUndefinedMethodInspection */
156
        $object = $object->setLatitude($this->generator->latitude());
157
        /** @noinspection PhpUndefinedMethodInspection */
158
        $object = $object->setLongitude($this->generator->longitude());
159
        /** @var $object ObjectInterface */
160
        return $this->happens(.3) ? $object->setElevation($this->generator->randomFloat(5, -10, 1000)) : $object;
161
    }
162
163
    /**
164
     * Set the object description
165
     *
166
     * @param ObjectInterface $object Object
167
     * @return ObjectInterface $object Object
168
     */
169
    protected function setDescription(ObjectInterface $object)
170
    {
171
        return $object->setDescription($this->generator->text(200));
172
    }
173
174
    /**
175
     * Set the object abstract
176
     *
177
     * @param ObjectInterface $object Object
178
     * @return ObjectInterface $object Object
179
     */
180
    protected function setAbstract(ObjectInterface $object)
181
    {
182
        return $object->setAbstract($this->generator->realText(250));
183
    }
184
185
    /**
186
     * Set the object keywords
187
     *
188
     * @param ObjectInterface $object Object
189
     * @return ObjectInterface $object Object
190
     */
191
    protected function setKeywords(ObjectInterface $object)
192
    {
193
        return $object->setKeywords($this->generator->words(rand(0, 5)));
0 ignored issues
show
Bug introduced by
It seems like $this->generator->words(rand(0, 5)) targeting Faker\Generator::words() can also be of type string; however, Apparat\Object\Domain\Mo...nterface::setKeywords() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
194
    }
195
196
    /**
197
     * Set the object categories
198
     *
199
     * @param ObjectInterface $object Object
200
     * @return ObjectInterface $object Object
201
     */
202
    protected function setCategories(ObjectInterface $object)
203
    {
204
        return $object->setCategories($this->generator->words(rand(0, 5)));
0 ignored issues
show
Bug introduced by
It seems like $this->generator->words(rand(0, 5)) targeting Faker\Generator::words() can also be of type string; however, Apparat\Object\Domain\Mo...erface::setCategories() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
205
    }
206
207
    /**
208
     * Set the object authors
209
     *
210
     * @param ObjectInterface $object Object
211
     * @return ObjectInterface $object Object
212
     */
213
    protected function setAuthors(ObjectInterface $object)
214
    {
215
        // Run through a random number of authors between 1 and 2
216
        for ($author = 0, $maxAuthors = rand(1, 2); $author < $maxAuthors; ++$author) {
217
            $this->setAdditionalAuthor($object);
218
        }
219
220
        return $object;
221
    }
222
223
    /**
224
     * Add an additional author to the object
225
     *
226
     * @param ObjectInterface $object Object
227
     * @return ObjectInterface
228
     */
229
    protected function setAdditionalAuthor(ObjectInterface $object)
230
    {
231
        $url = $this->happens(.3) ? $this->generator->url : '';
232
        $email = $this->happens(.7) ? $this->generator->email : '';
233
        $label = $this->happens(.5) ? $this->generator->name : '';
234
        $author = $this->formatRelation($url, $email, $label);
235
        if (strlen($author)) {
236
            $object->addRelation($author, Relation::CONTRIBUTED_BY);
237
        }
238
239
        return $object;
240
    }
241
242
    /**
243
     * Set the object syndication URLs
244
     *
245
     * @param ObjectInterface $object Object
246
     * @return ObjectInterface $object Object
247
     */
248
    protected function setSyndication(ObjectInterface $object)
249
    {
250
        // Run through a random number of syndication URLs between 1 and 3
251
        for ($syndication = 0, $maxSyndication = rand(1, 2); $syndication < $maxSyndication; ++$syndication) {
252
            $this->setAdditionalSyndication($object);
253
        }
254
255
        return $object;
256
    }
257
258
    /**
259
     * Add an additional syndication URL to the object
260
     *
261
     * @param ObjectInterface $object Object
262
     * @return ObjectInterface $object Object
263
     */
264
    protected function setAdditionalSyndication(ObjectInterface $object)
265
    {
266
        $syndicationUrls = [
267
            sprintf(self::TWITTER_STATUS, $this->generator->userName, $this->generator->creditCardNumber),
268
            sprintf(self::FACEBOOK_POST, $this->generator->userName, $this->generator->creditCardNumber),
269
            sprintf(self::GOOGLEPLUS_POST, $this->generator->userName,
270
                substr(base64_encode($this->generator->md5), 0, 12)),
271
            sprintf(self::INSTAGRAM_POST, substr(base64_encode($this->generator->md5), 0, 12))
272
        ];
273
274
        return $object->addRelation($this->generator->randomElement($syndicationUrls), Relation::SYNDICATED_TO);
0 ignored issues
show
Bug introduced by
The call to randomElement() misses some required arguments starting with $'b'.
Loading history...
275
    }
276
277
    /**
278
     * Set an object feature image
279
     *
280
     * @param ObjectInterface $object Object
281
     * @return ObjectInterface $object Object
282
     */
283
    protected function setFeatured(ObjectInterface $object)
284
    {
285
        return $object->setDomainProperty('featured', $this->generator->imageUrl(1024, 768));
286
    }
287
288
    /**
289
     * Create a random signal with a particular probability
290
     *
291
     * @param float $probability Probability
292
     * @return bool Signal
293
     */
294
    protected function happens($probability = 0.0)
295
    {
296
        return rand(0, 100) <= (max(0, min(1, floatval($probability))) * 100);
297
    }
298
299
    /**
300
     * Format a relation string
301
     *
302
     * @param string $url URL
303
     * @param string $email Email address
304
     * @param string $label Label
305
     * @return string Relation string
306
     */
307
    protected function formatRelation($url = '', $email = '', $label = '')
308
    {
309
        return implode(' ', array_filter([trim($url), trim($email) ? "<$email>" : '', trim($label)]));
310
    }
311
}
312