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))); |
|
|
|
|
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))); |
|
|
|
|
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); |
|
|
|
|
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
|
|
|
|
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.