1 | <?php |
||||||||||
2 | /** |
||||||||||
3 | * |
||||||||||
4 | */ |
||||||||||
5 | |||||||||||
6 | namespace Elgg\Database\Seeds; |
||||||||||
7 | |||||||||||
8 | use Elgg\Project\Paths; |
||||||||||
9 | use ElggEntity; |
||||||||||
10 | use ElggGroup; |
||||||||||
11 | use ElggObject; |
||||||||||
12 | use ElggUser; |
||||||||||
13 | use Exception; |
||||||||||
14 | use Faker\Factory; |
||||||||||
15 | |||||||||||
16 | /** |
||||||||||
17 | * Seeding trait |
||||||||||
18 | * Can be used to easily create new random users, groups and objects in the database |
||||||||||
19 | * |
||||||||||
20 | * @access private |
||||||||||
21 | */ |
||||||||||
22 | trait Seeding { |
||||||||||
23 | |||||||||||
24 | /** |
||||||||||
25 | * @var int Max number of items to be created by the seed |
||||||||||
26 | */ |
||||||||||
27 | protected $limit = 20; |
||||||||||
28 | |||||||||||
29 | /** |
||||||||||
30 | * @var \Faker\Generator |
||||||||||
31 | */ |
||||||||||
32 | protected $faker; |
||||||||||
33 | |||||||||||
34 | /** |
||||||||||
35 | * Returns an instance of faker |
||||||||||
36 | * |
||||||||||
37 | * @param string $locale Locale |
||||||||||
38 | * |
||||||||||
39 | * @return \Faker\Generator |
||||||||||
40 | */ |
||||||||||
41 | 358 | public function faker($locale = 'en_US') { |
|||||||||
42 | 358 | if (!isset($this->faker)) { |
|||||||||
43 | 358 | $this->faker = Factory::create($locale); |
|||||||||
44 | } |
||||||||||
45 | |||||||||||
46 | 358 | return $this->faker; |
|||||||||
47 | } |
||||||||||
48 | |||||||||||
49 | /** |
||||||||||
50 | * Get site domain |
||||||||||
51 | * @return string |
||||||||||
52 | */ |
||||||||||
53 | public function getDomain() { |
||||||||||
54 | return elgg_get_site_entity()->getDomain(); |
||||||||||
55 | } |
||||||||||
56 | |||||||||||
57 | /** |
||||||||||
58 | * Get valid domain for emails |
||||||||||
59 | * @return string |
||||||||||
60 | */ |
||||||||||
61 | 160 | public function getEmailDomain() { |
|||||||||
62 | 160 | $email = elgg_get_site_entity()->email; |
|||||||||
63 | 160 | if (!$email) { |
|||||||||
64 | $email = "noreply@{$this->getDomain()}"; |
||||||||||
65 | } |
||||||||||
66 | |||||||||||
67 | 160 | list(, $domain) = explode('@', $email); |
|||||||||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||||||||
68 | |||||||||||
69 | 160 | if (sizeof(explode('.', $domain)) <= 1) { |
|||||||||
0 ignored issues
–
show
The call to
sizeof() has too few arguments starting with mode .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.
Loading history...
|
|||||||||||
70 | $domain = 'example.net'; |
||||||||||
71 | } |
||||||||||
72 | |||||||||||
73 | 160 | return $domain; |
|||||||||
74 | } |
||||||||||
75 | |||||||||||
76 | /** |
||||||||||
77 | * Returns random unique subtype |
||||||||||
78 | * @return bool|string |
||||||||||
79 | */ |
||||||||||
80 | 419 | public function getRandomSubtype() { |
|||||||||
81 | 419 | return substr(sha1(microtime() . rand()), 0, 25); |
|||||||||
0 ignored issues
–
show
The call to
rand() has too few arguments starting with min .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.
Loading history...
|
|||||||||||
82 | } |
||||||||||
83 | |||||||||||
84 | /** |
||||||||||
85 | * Create a new fake user |
||||||||||
86 | * |
||||||||||
87 | * @param array $attributes User entity attributes |
||||||||||
88 | * @param array $metadata User entity metadata |
||||||||||
89 | * @param array $options Seeding options |
||||||||||
90 | * |
||||||||||
91 | * @return ElggUser |
||||||||||
92 | */ |
||||||||||
93 | public function createUser(array $attributes = [], array $metadata = [], array $options = []) { |
||||||||||
94 | |||||||||||
95 | 160 | $create = function () use ($attributes, $metadata, $options) { |
|||||||||
96 | 160 | $metadata['__faker'] = true; |
|||||||||
97 | |||||||||||
98 | 160 | if (empty($metadata['password'])) { |
|||||||||
99 | 154 | $metadata['password'] = generate_random_cleartext_password(); |
|||||||||
100 | } |
||||||||||
101 | |||||||||||
102 | 160 | if (empty($metadata['name'])) { |
|||||||||
103 | 160 | $metadata['name'] = $this->faker()->name; |
|||||||||
104 | } |
||||||||||
105 | |||||||||||
106 | 160 | if (empty($metadata['username'])) { |
|||||||||
107 | 160 | $metadata['username'] = $this->getRandomUsername($metadata['name']); |
|||||||||
108 | } |
||||||||||
109 | |||||||||||
110 | 160 | if (empty($metadata['email'])) { |
|||||||||
111 | 160 | $metadata['email'] = "{$metadata['username']}@{$this->getEmailDomain()}"; |
|||||||||
112 | } |
||||||||||
113 | |||||||||||
114 | 160 | if (empty($attributes['subtype'])) { |
|||||||||
115 | 47 | $attributes['subtype'] = 'user'; |
|||||||||
116 | } |
||||||||||
117 | |||||||||||
118 | 160 | $user = false; |
|||||||||
119 | |||||||||||
120 | try { |
||||||||||
121 | 160 | $guid = register_user($metadata['username'], $metadata['password'], $metadata['name'], $metadata['email'], false, $attributes['subtype']); |
|||||||||
0 ignored issues
–
show
It seems like
$metadata['password'] can also be of type true ; however, parameter $password of register_user() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
It seems like
$metadata['name'] can also be of type true ; however, parameter $name of register_user() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
It seems like
$metadata['username'] can also be of type true ; however, parameter $username of register_user() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
It seems like
$metadata['email'] can also be of type true ; however, parameter $email of register_user() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||||||
122 | |||||||||||
123 | 160 | $user = get_user($guid); |
|||||||||
0 ignored issues
–
show
It seems like
$guid can also be of type false ; however, parameter $guid of get_user() does only seem to accept integer , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||||||
124 | 160 | if (!$user) { |
|||||||||
125 | throw new Exception("Unable to create new user with attributes: " . print_r($attributes, true)); |
||||||||||
126 | } |
||||||||||
127 | |||||||||||
128 | 160 | if (isset($metadata['admin'])) { |
|||||||||
129 | 1 | if ($metadata['admin']) { |
|||||||||
130 | 1 | $user->makeAdmin(); |
|||||||||
131 | } else { |
||||||||||
132 | $user->removeAdmin(); |
||||||||||
133 | } |
||||||||||
134 | } |
||||||||||
135 | |||||||||||
136 | 160 | if (isset($metadata['banned'])) { |
|||||||||
137 | 2 | if ($metadata['banned']) { |
|||||||||
138 | 2 | $user->ban('Banned by seeder'); |
|||||||||
139 | } else { |
||||||||||
140 | $user->unban('Unbanned by seeder'); |
||||||||||
141 | } |
||||||||||
142 | } |
||||||||||
143 | |||||||||||
144 | 160 | unset($metadata['username']); |
|||||||||
145 | 160 | unset($metadata['password']); |
|||||||||
146 | 160 | unset($metadata['name']); |
|||||||||
147 | 160 | unset($metadata['email']); |
|||||||||
148 | 160 | unset($metadata['banned']); |
|||||||||
149 | 160 | unset($metadata['admin']); |
|||||||||
150 | |||||||||||
151 | 160 | $user->setValidationStatus($this->faker()->boolean(), 'seeder'); |
|||||||||
152 | |||||||||||
153 | 160 | $user->setNotificationSetting('email', false); |
|||||||||
154 | 160 | $user->setNotificationSetting('site', true); |
|||||||||
155 | |||||||||||
156 | 160 | $profile_fields = elgg_extract('profile_fields', $options, []); |
|||||||||
157 | 160 | $user = $this->populateMetadata($user, $profile_fields, $metadata); |
|||||||||
158 | |||||||||||
159 | 160 | $user->save(); |
|||||||||
160 | |||||||||||
161 | 160 | $this->log("Created new user $user->name [guid: $user->guid]"); |
|||||||||
162 | |||||||||||
163 | 160 | return $user; |
|||||||||
164 | } catch (\RegistrationException $e) { |
||||||||||
165 | if ($user && $user->guid) { |
||||||||||
166 | $user->delete(); |
||||||||||
167 | } |
||||||||||
168 | |||||||||||
169 | $attr_log = print_r($attributes, true); |
||||||||||
170 | $this->log("User creation failed with message {$e->getMessage()} [attributes: $attr_log]"); |
||||||||||
171 | |||||||||||
172 | return false; |
||||||||||
173 | } |
||||||||||
174 | 160 | }; |
|||||||||
175 | |||||||||||
176 | 160 | $ia = elgg_set_ignore_access(true); |
|||||||||
177 | |||||||||||
178 | 160 | $user = false; |
|||||||||
179 | 160 | while (!$user instanceof \ElggUser) { |
|||||||||
180 | 160 | $user = $create(); |
|||||||||
181 | } |
||||||||||
182 | |||||||||||
183 | 160 | elgg_set_ignore_access($ia); |
|||||||||
184 | |||||||||||
185 | 160 | return $user; |
|||||||||
186 | |||||||||||
187 | } |
||||||||||
188 | |||||||||||
189 | /** |
||||||||||
190 | * Create a new fake group |
||||||||||
191 | * |
||||||||||
192 | * @param array $attributes Group entity attributes |
||||||||||
193 | * @param array $metadata Group entity metadata |
||||||||||
194 | * @param array $options Additional options |
||||||||||
195 | * |
||||||||||
196 | * @return ElggGroup |
||||||||||
197 | */ |
||||||||||
198 | public function createGroup(array $attributes = [], array $metadata = [], array $options = []) { |
||||||||||
199 | |||||||||||
200 | 73 | $create = function () use ($attributes, $metadata, $options) { |
|||||||||
201 | 73 | $metadata['__faker'] = true; |
|||||||||
202 | |||||||||||
203 | 73 | if (empty($attributes['access_id'])) { |
|||||||||
204 | 73 | $attributes['access_id'] = ACCESS_PUBLIC; |
|||||||||
205 | } |
||||||||||
206 | |||||||||||
207 | 73 | if (empty($metadata['content_access_mode'])) { |
|||||||||
208 | 73 | $metadata['content_access_mode'] = ElggGroup::CONTENT_ACCESS_MODE_UNRESTRICTED; |
|||||||||
209 | } |
||||||||||
210 | |||||||||||
211 | 73 | if (empty($metadata['membership'])) { |
|||||||||
212 | 73 | $metadata['membership'] = ACCESS_PUBLIC; |
|||||||||
213 | } |
||||||||||
214 | |||||||||||
215 | 73 | if (empty($metadata['name'])) { |
|||||||||
216 | 73 | $metadata['name'] = $this->faker()->sentence(); |
|||||||||
217 | } |
||||||||||
218 | |||||||||||
219 | 73 | if (empty($metadata['description'])) { |
|||||||||
220 | 73 | $metadata['description'] = $this->faker()->text($this->faker()->numberBetween(500, 1000)); |
|||||||||
221 | } |
||||||||||
222 | |||||||||||
223 | 73 | if (empty($attributes['owner_guid'])) { |
|||||||||
224 | 73 | $user = elgg_get_logged_in_user_entity(); |
|||||||||
225 | 73 | if (!$user) { |
|||||||||
226 | 66 | $user = $this->getRandomUser(); |
|||||||||
227 | } |
||||||||||
228 | 73 | if (!$user) { |
|||||||||
229 | $user = $this->createUser(); |
||||||||||
230 | } |
||||||||||
231 | |||||||||||
232 | 73 | $attributes['owner_guid'] = $user->guid; |
|||||||||
233 | } |
||||||||||
234 | |||||||||||
235 | 73 | if (empty($attributes['container_guid'])) { |
|||||||||
236 | 73 | $attributes['container_guid'] = $attributes['owner_guid']; |
|||||||||
237 | } |
||||||||||
238 | |||||||||||
239 | 73 | if (empty($attributes['subtype'])) { |
|||||||||
240 | 6 | $attributes['subtype'] = 'group'; |
|||||||||
241 | } |
||||||||||
242 | |||||||||||
243 | 73 | $owner = get_entity($attributes['owner_guid']); |
|||||||||
244 | 73 | if (!$owner) { |
|||||||||
245 | return false; |
||||||||||
246 | } |
||||||||||
247 | |||||||||||
248 | 73 | $container = get_entity($attributes['container_guid']); |
|||||||||
249 | 73 | if (!$container) { |
|||||||||
250 | return false; |
||||||||||
251 | } |
||||||||||
252 | |||||||||||
253 | 73 | $tool_options = elgg_extract('group_tools_options', $options, []); |
|||||||||
254 | 73 | if ($tool_options) { |
|||||||||
255 | foreach ($tool_options as $group_option) { |
||||||||||
256 | $option_toggle_name = $group_option->name . "_enable"; |
||||||||||
257 | $option_default = $group_option->default_on ? 'yes' : 'no'; |
||||||||||
258 | $metadata[$option_toggle_name] = $option_default; |
||||||||||
259 | } |
||||||||||
260 | } |
||||||||||
261 | |||||||||||
262 | 73 | if ($this->faker()->boolean(20)) { |
|||||||||
263 | 11 | $metadata['featured_group'] = 'yes'; |
|||||||||
264 | } |
||||||||||
265 | |||||||||||
266 | 73 | $group = new ElggGroup(); |
|||||||||
267 | 73 | foreach ($attributes as $name => $value) { |
|||||||||
268 | 73 | $group->$name = $value; |
|||||||||
269 | } |
||||||||||
270 | |||||||||||
271 | 73 | $profile_fields = elgg_extract('profile_fields', $options, []); |
|||||||||
272 | 73 | $group = $this->populateMetadata($group, $profile_fields, $metadata); |
|||||||||
273 | |||||||||||
274 | 73 | $group->save(); |
|||||||||
275 | |||||||||||
276 | 73 | if ($group->access_id == ACCESS_PRIVATE) { |
|||||||||
277 | $acls = $group->getOwnedAccessCollections(['subtype' => 'group_acl']); |
||||||||||
278 | if ($acls) { |
||||||||||
279 | $group->access_id = $acls[0]->id; |
||||||||||
280 | $group->save(); |
||||||||||
281 | } |
||||||||||
282 | } |
||||||||||
283 | |||||||||||
284 | 73 | $group->join(get_entity($attributes['owner_guid'])); |
|||||||||
285 | |||||||||||
286 | 73 | elgg_create_river_item([ |
|||||||||
287 | 73 | 'view' => 'river/group/create', |
|||||||||
288 | 73 | 'action_type' => 'create', |
|||||||||
289 | 73 | 'subject_guid' => $owner->guid, |
|||||||||
290 | 73 | 'object_guid' => $group->guid, |
|||||||||
291 | 73 | 'target_guid' => $container->guid, |
|||||||||
292 | ]); |
||||||||||
293 | |||||||||||
294 | 73 | $this->log("Created new group $group->name [guid: $group->guid]"); |
|||||||||
295 | |||||||||||
296 | 73 | return $group; |
|||||||||
297 | 73 | }; |
|||||||||
298 | |||||||||||
299 | 73 | $ia = elgg_set_ignore_access(true); |
|||||||||
300 | |||||||||||
301 | 73 | $group = false; |
|||||||||
302 | 73 | while (!$group instanceof \ElggGroup) { |
|||||||||
303 | 73 | $group = $create(); |
|||||||||
304 | } |
||||||||||
305 | |||||||||||
306 | 73 | elgg_set_ignore_access($ia); |
|||||||||
307 | |||||||||||
308 | 73 | return $group; |
|||||||||
309 | } |
||||||||||
310 | |||||||||||
311 | /** |
||||||||||
312 | * Create a new fake object |
||||||||||
313 | * |
||||||||||
314 | * @param array $attributes Object entity attributes |
||||||||||
315 | * @param array $metadata Object entity metadata |
||||||||||
316 | * @param array $options Additional options |
||||||||||
317 | * |
||||||||||
318 | * @return ElggObject |
||||||||||
319 | */ |
||||||||||
320 | public function createObject(array $attributes = [], array $metadata = [], array $options = []) { |
||||||||||
321 | |||||||||||
322 | 180 | $create = function () use ($attributes, $metadata, $options) { |
|||||||||
323 | |||||||||||
324 | 180 | $properties = array_merge($metadata, $attributes); |
|||||||||
325 | |||||||||||
326 | 180 | $properties['__faker'] = true; |
|||||||||
327 | |||||||||||
328 | 180 | if (empty($properties['title'])) { |
|||||||||
329 | 179 | $properties['title'] = $this->faker()->sentence(); |
|||||||||
330 | } |
||||||||||
331 | |||||||||||
332 | 180 | if (empty($properties['description'])) { |
|||||||||
333 | 179 | $properties['description'] = $this->faker()->text($this->faker()->numberBetween(500, 1000)); |
|||||||||
334 | } |
||||||||||
335 | |||||||||||
336 | 180 | if (empty($properties['subtype'])) { |
|||||||||
337 | 36 | $properties['subtype'] = $this->getRandomSubtype(); |
|||||||||
338 | } |
||||||||||
339 | |||||||||||
340 | 180 | if (empty($properties['tags'])) { |
|||||||||
341 | 158 | $properties['tags'] = $this->faker()->words(10); |
|||||||||
342 | } |
||||||||||
343 | |||||||||||
344 | 180 | if (empty($properties['container_guid'])) { |
|||||||||
345 | 179 | $container = elgg_get_logged_in_user_entity(); |
|||||||||
346 | 179 | if (!$container) { |
|||||||||
347 | 111 | $container = $this->getRandomUser(); |
|||||||||
348 | } |
||||||||||
349 | 179 | if (!$container) { |
|||||||||
350 | $container = $this->createUser(); |
||||||||||
351 | } |
||||||||||
352 | |||||||||||
353 | 179 | $properties['container_guid'] = $container->guid; |
|||||||||
354 | } |
||||||||||
355 | |||||||||||
356 | 180 | $container = get_entity($properties['container_guid']); |
|||||||||
0 ignored issues
–
show
It seems like
$properties['container_guid'] can also be of type true ; however, parameter $guid of get_entity() does only seem to accept integer , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||||||
357 | 180 | if (!$container) { |
|||||||||
358 | return false; |
||||||||||
359 | } |
||||||||||
360 | |||||||||||
361 | 180 | if (empty($properties['owner_guid'])) { |
|||||||||
362 | 166 | $owner = $container; |
|||||||||
363 | 166 | $properties['owner_guid'] = $owner->guid; |
|||||||||
364 | } |
||||||||||
365 | |||||||||||
366 | 180 | $owner = get_entity($properties['owner_guid']); |
|||||||||
367 | 180 | if (!$owner) { |
|||||||||
368 | return false; |
||||||||||
369 | } |
||||||||||
370 | |||||||||||
371 | 180 | if (!isset($properties['access_id'])) { |
|||||||||
372 | 175 | $properties['access_id'] = ACCESS_PUBLIC; |
|||||||||
373 | } |
||||||||||
374 | |||||||||||
375 | 180 | $class = elgg_get_entity_class('object', $properties['subtype']); |
|||||||||
376 | 180 | if ($class && class_exists($class)) { |
|||||||||
377 | 26 | $object = new $class(); |
|||||||||
378 | } else { |
||||||||||
379 | 155 | $object = new ElggObject(); |
|||||||||
380 | } |
||||||||||
381 | |||||||||||
382 | 180 | foreach ($properties as $name => $value) { |
|||||||||
383 | 180 | $object->$name = $value; |
|||||||||
384 | } |
||||||||||
385 | |||||||||||
386 | 180 | $profile_fields = elgg_extract('profile_fields', $options, []); |
|||||||||
387 | 180 | $object = $this->populateMetadata($object, $profile_fields, $properties); |
|||||||||
388 | |||||||||||
389 | 180 | if (elgg_extract('save', $options, true)) { |
|||||||||
390 | 180 | $object->save(); |
|||||||||
391 | } |
||||||||||
392 | |||||||||||
393 | 180 | $type_str = elgg_echo("item:object:{$object->getSubtype()}"); |
|||||||||
394 | |||||||||||
395 | 180 | $this->log("Created new item in $type_str $object->title [guid: $object->guid]"); |
|||||||||
396 | |||||||||||
397 | 180 | return $object; |
|||||||||
398 | 180 | }; |
|||||||||
399 | |||||||||||
400 | 180 | $ia = elgg_set_ignore_access(true); |
|||||||||
401 | |||||||||||
402 | 180 | $object = false; |
|||||||||
403 | 180 | while (!$object instanceof \ElggObject) { |
|||||||||
404 | 180 | $object = $create(); |
|||||||||
405 | } |
||||||||||
406 | |||||||||||
407 | 180 | elgg_set_ignore_access($ia); |
|||||||||
408 | |||||||||||
409 | 180 | return $object; |
|||||||||
410 | |||||||||||
411 | } |
||||||||||
412 | |||||||||||
413 | /** |
||||||||||
414 | * Create a new fake site |
||||||||||
415 | * |
||||||||||
416 | * @param array $attributes Object entity attributes |
||||||||||
417 | * @param array $metadata Object entity metadata |
||||||||||
418 | * |
||||||||||
419 | * @return ElggObject |
||||||||||
420 | */ |
||||||||||
421 | public function createSite(array $attributes = [], array $metadata = []) { |
||||||||||
422 | // We don't want to create more than one site |
||||||||||
423 | return elgg_get_site_entity(); |
||||||||||
424 | } |
||||||||||
425 | |||||||||||
426 | /** |
||||||||||
427 | * Returns random fake user |
||||||||||
428 | * |
||||||||||
429 | * @param int[] $exclude GUIDs to exclude |
||||||||||
430 | * |
||||||||||
431 | * @return ElggUser|false |
||||||||||
432 | */ |
||||||||||
433 | 178 | public function getRandomUser(array $exclude = []) { |
|||||||||
434 | |||||||||||
435 | 178 | $exclude[] = 0; |
|||||||||
436 | 178 | $exclude_in = implode(',', array_map(function ($e) { |
|||||||||
437 | 178 | return (int) $e; |
|||||||||
438 | 178 | }, $exclude)); |
|||||||||
439 | |||||||||||
440 | 178 | $users = elgg_get_entities([ |
|||||||||
441 | 178 | 'types' => 'user', |
|||||||||
442 | 'metadata_names' => ['__faker'], |
||||||||||
443 | 178 | 'limit' => 1, |
|||||||||
444 | 'wheres' => [ |
||||||||||
445 | 178 | "e.guid NOT IN ($exclude_in)", |
|||||||||
446 | ], |
||||||||||
447 | 178 | 'order_by' => 'RAND()', |
|||||||||
448 | ]); |
||||||||||
449 | |||||||||||
450 | 178 | return $users ? $users[0] : false; |
|||||||||
451 | } |
||||||||||
452 | |||||||||||
453 | /** |
||||||||||
454 | * Returns random fake group |
||||||||||
455 | * |
||||||||||
456 | * @param int[] $exclude GUIDs to exclude |
||||||||||
457 | * |
||||||||||
458 | * @return ElggGroup|false |
||||||||||
459 | */ |
||||||||||
460 | public function getRandomGroup(array $exclude = []) { |
||||||||||
461 | |||||||||||
462 | $exclude[] = 0; |
||||||||||
463 | $exclude_in = implode(',', array_map(function ($e) { |
||||||||||
464 | return (int) $e; |
||||||||||
465 | }, $exclude)); |
||||||||||
466 | |||||||||||
467 | $groups = elgg_get_entities([ |
||||||||||
468 | 'types' => 'group', |
||||||||||
469 | 'metadata_names' => ['__faker'], |
||||||||||
470 | 'limit' => 1, |
||||||||||
471 | 'wheres' => [ |
||||||||||
472 | "e.guid NOT IN ($exclude_in)", |
||||||||||
473 | ], |
||||||||||
474 | 'order_by' => 'RAND()', |
||||||||||
475 | ]); |
||||||||||
476 | |||||||||||
477 | return $groups ? $groups[0] : false; |
||||||||||
478 | } |
||||||||||
479 | |||||||||||
480 | /** |
||||||||||
481 | * Get random access id |
||||||||||
482 | * |
||||||||||
483 | * @param ElggUser $user User |
||||||||||
484 | * @param ElggEntity $container Container |
||||||||||
485 | * |
||||||||||
486 | * @return int |
||||||||||
487 | */ |
||||||||||
488 | public function getRandomAccessId(\ElggUser $user = null, ElggEntity $container = null) { |
||||||||||
489 | |||||||||||
490 | $params = [ |
||||||||||
491 | 'container_guid' => $container ? $container->guid : null, |
||||||||||
492 | ]; |
||||||||||
493 | |||||||||||
494 | $access_array = get_write_access_array($user->guid, null, null, $params); |
||||||||||
495 | |||||||||||
496 | $access_key = array_rand($access_array, 1); |
||||||||||
497 | |||||||||||
498 | return $access_array[$access_key]; |
||||||||||
499 | } |
||||||||||
500 | |||||||||||
501 | /** |
||||||||||
502 | * Generates a unique available and valid username |
||||||||||
503 | * |
||||||||||
504 | * @param string $base_name Display name, email or other prefix to use as basis |
||||||||||
505 | * |
||||||||||
506 | * @return string |
||||||||||
507 | */ |
||||||||||
508 | 172 | public function getRandomUsername($base_name = 'user') { |
|||||||||
509 | |||||||||||
510 | 172 | $available = false; |
|||||||||
511 | |||||||||||
512 | 172 | $base_name = iconv('UTF-8', 'ASCII//TRANSLIT', $base_name); |
|||||||||
513 | 172 | $blacklist = '/[\x{0080}-\x{009f}\x{00a0}\x{2000}-\x{200f}\x{2028}-\x{202f}\x{3000}\x{e000}-\x{f8ff}]/u'; |
|||||||||
514 | $blacklist2 = [ |
||||||||||
515 | 172 | ' ', |
|||||||||
516 | '\'', |
||||||||||
517 | '/', |
||||||||||
518 | '\\', |
||||||||||
519 | '"', |
||||||||||
520 | '*', |
||||||||||
521 | '&', |
||||||||||
522 | '?', |
||||||||||
523 | '#', |
||||||||||
524 | '%', |
||||||||||
525 | '^', |
||||||||||
526 | '(', |
||||||||||
527 | ')', |
||||||||||
528 | '{', |
||||||||||
529 | '}', |
||||||||||
530 | '[', |
||||||||||
531 | ']', |
||||||||||
532 | '~', |
||||||||||
533 | '?', |
||||||||||
534 | '<', |
||||||||||
535 | '>', |
||||||||||
536 | ';', |
||||||||||
537 | '|', |
||||||||||
538 | '¬', |
||||||||||
539 | '`', |
||||||||||
540 | '@', |
||||||||||
541 | '-', |
||||||||||
542 | '+', |
||||||||||
543 | '=' |
||||||||||
544 | ]; |
||||||||||
545 | |||||||||||
546 | 172 | $base_name = preg_replace($blacklist, '', $base_name); |
|||||||||
547 | 172 | $base_name = str_replace($blacklist2, '', $base_name); |
|||||||||
548 | 172 | $base_name = str_replace('.', '_', $base_name); |
|||||||||
549 | |||||||||||
550 | 172 | $ia = elgg_set_ignore_access(true); |
|||||||||
551 | |||||||||||
552 | 172 | $ha = access_get_show_hidden_status(); |
|||||||||
553 | 172 | access_show_hidden_entities(true); |
|||||||||
554 | |||||||||||
555 | 172 | $minlength = elgg_get_config('minusername') ? : 8; |
|||||||||
556 | 172 | if ($base_name) { |
|||||||||
557 | 172 | $fill = $minlength - strlen($base_name); |
|||||||||
558 | } else { |
||||||||||
559 | $fill = 8; |
||||||||||
560 | } |
||||||||||
561 | |||||||||||
562 | 172 | $separator = ''; |
|||||||||
563 | |||||||||||
564 | 172 | if ($fill > 0) { |
|||||||||
565 | 26 | $suffix = (new \ElggCrypto())->getRandomString($fill); |
|||||||||
566 | 26 | $base_name = "$base_name$separator$suffix"; |
|||||||||
567 | } |
||||||||||
568 | |||||||||||
569 | 172 | $iterator = 0; |
|||||||||
570 | 172 | while (!$available) { |
|||||||||
571 | 172 | if ($iterator > 0) { |
|||||||||
572 | $base_name = "$base_name$separator$iterator"; |
||||||||||
573 | } |
||||||||||
574 | 172 | $user = get_user_by_username($base_name); |
|||||||||
575 | 172 | $available = !$user; |
|||||||||
576 | try { |
||||||||||
577 | 172 | if ($available) { |
|||||||||
578 | 172 | validate_username($base_name); |
|||||||||
579 | } |
||||||||||
580 | } catch (\Exception $e) { |
||||||||||
581 | if ($iterator >= 10) { |
||||||||||
582 | // too many failed attempts |
||||||||||
583 | $base_name = (new \ElggCrypto())->getRandomString(8); |
||||||||||
584 | } |
||||||||||
585 | } |
||||||||||
586 | |||||||||||
587 | 172 | $iterator++; |
|||||||||
588 | } |
||||||||||
589 | |||||||||||
590 | 172 | access_show_hidden_entities($ha); |
|||||||||
591 | 172 | elgg_set_ignore_access($ia); |
|||||||||
592 | |||||||||||
593 | 172 | return strtolower($base_name); |
|||||||||
594 | } |
||||||||||
595 | |||||||||||
596 | /** |
||||||||||
597 | * Set random metadata |
||||||||||
598 | * |
||||||||||
599 | * @param ElggEntity $entity Entity |
||||||||||
600 | * @param array $fields An array of profile fields in $name => $input_type format |
||||||||||
601 | * @param array $metadata Other metadata $name => $value pairs to set |
||||||||||
602 | * |
||||||||||
603 | * @return ElggEntity |
||||||||||
604 | */ |
||||||||||
605 | 358 | public function populateMetadata(ElggEntity $entity, array $fields = [], array $metadata = []) { |
|||||||||
606 | |||||||||||
607 | 358 | foreach ($fields as $name => $type) { |
|||||||||
608 | if (isset($metadata[$name])) { |
||||||||||
609 | continue; |
||||||||||
610 | } |
||||||||||
611 | |||||||||||
612 | switch ($name) { |
||||||||||
613 | case 'phone' : |
||||||||||
614 | case 'mobile' : |
||||||||||
615 | $metadata[$name] = $this->faker()->phoneNumber; |
||||||||||
616 | break; |
||||||||||
617 | |||||||||||
618 | default : |
||||||||||
619 | switch ($type) { |
||||||||||
620 | case 'plaintext' : |
||||||||||
621 | case 'longtext' : |
||||||||||
622 | $metadata[$name] = $this->faker()->text($this->faker()->numberBetween(500, 1000)); |
||||||||||
623 | break; |
||||||||||
624 | |||||||||||
625 | case 'text' : |
||||||||||
626 | $metadata[$name] = $this->faker()->sentence; |
||||||||||
627 | break; |
||||||||||
628 | |||||||||||
629 | case 'tags' : |
||||||||||
630 | $metadata[$name] = $this->faker()->words(10); |
||||||||||
631 | break; |
||||||||||
632 | |||||||||||
633 | case 'url' : |
||||||||||
634 | $metadata[$name] = $this->faker()->url; |
||||||||||
635 | break; |
||||||||||
636 | |||||||||||
637 | case 'email' : |
||||||||||
638 | $metadata[$name] = $this->faker()->email; |
||||||||||
639 | break; |
||||||||||
640 | |||||||||||
641 | case 'number' : |
||||||||||
642 | $metadata[$name] = $this->faker()->randomNumber(); |
||||||||||
643 | break; |
||||||||||
644 | |||||||||||
645 | case 'date' : |
||||||||||
646 | $metadata[$name] = $this->faker()->unixTime; |
||||||||||
647 | break; |
||||||||||
648 | |||||||||||
649 | case 'password' : |
||||||||||
650 | $metadata[$name] = generate_random_cleartext_password(); |
||||||||||
651 | break; |
||||||||||
652 | |||||||||||
653 | case 'location' : |
||||||||||
654 | $metadata[$name] = $this->faker()->address; |
||||||||||
655 | $metadata['geo:lat'] = $this->faker()->latitude; |
||||||||||
656 | $metadata['geo:long'] = $this->faker()->longitude; |
||||||||||
657 | break; |
||||||||||
658 | |||||||||||
659 | default : |
||||||||||
660 | $metadata[$name] = ''; |
||||||||||
661 | break; |
||||||||||
662 | } |
||||||||||
663 | |||||||||||
664 | break; |
||||||||||
665 | } |
||||||||||
666 | } |
||||||||||
667 | |||||||||||
668 | 358 | foreach ($metadata as $key => $value) { |
|||||||||
669 | 358 | if (array_key_exists($key, $fields) && $entity instanceof ElggUser) { |
|||||||||
670 | $entity->deleteAnnotations("profile:$key"); |
||||||||||
671 | $value = (array) $value; |
||||||||||
672 | foreach ($value as $val) { |
||||||||||
673 | $entity->annotate("profile:$key", $val, $this->getRandomAccessId($entity), $entity->guid); |
||||||||||
674 | } |
||||||||||
675 | } else { |
||||||||||
676 | 358 | $entity->$key = $value; |
|||||||||
677 | } |
||||||||||
678 | } |
||||||||||
679 | |||||||||||
680 | 358 | return $entity; |
|||||||||
681 | } |
||||||||||
682 | |||||||||||
683 | /** |
||||||||||
684 | * Create an icon for an entity |
||||||||||
685 | * |
||||||||||
686 | * @param ElggEntity $entity Entity |
||||||||||
687 | * |
||||||||||
688 | * @return bool |
||||||||||
689 | */ |
||||||||||
690 | public function createIcon(ElggEntity $entity) { |
||||||||||
691 | |||||||||||
692 | $icon_location = $this->faker()->image(); |
||||||||||
693 | if (empty($icon_location)) { |
||||||||||
694 | return false; |
||||||||||
695 | } |
||||||||||
696 | |||||||||||
697 | $result = $entity->saveIconFromLocalFile($icon_location); |
||||||||||
698 | |||||||||||
699 | if ($result && $entity instanceof ElggUser) { |
||||||||||
700 | elgg_create_river_item([ |
||||||||||
701 | 'view' => 'river/user/default/profileiconupdate', |
||||||||||
702 | 'action_type' => 'update', |
||||||||||
703 | 'subject_guid' => $entity->guid, |
||||||||||
704 | 'object_guid' => $entity->guid, |
||||||||||
705 | ]); |
||||||||||
706 | } |
||||||||||
707 | |||||||||||
708 | return $result; |
||||||||||
709 | } |
||||||||||
710 | |||||||||||
711 | /** |
||||||||||
712 | * Create comments/replies |
||||||||||
713 | * |
||||||||||
714 | * @param ElggEntity $entity Entity to comment on |
||||||||||
715 | * @param int $limit Number of comments to create |
||||||||||
716 | * |
||||||||||
717 | * @return int Number of generated comments |
||||||||||
718 | */ |
||||||||||
719 | public function createComments(ElggEntity $entity, $limit = null) { |
||||||||||
720 | |||||||||||
721 | $ia = elgg_set_ignore_access(true); |
||||||||||
722 | |||||||||||
723 | $tries = 0; |
||||||||||
724 | $success = 0; |
||||||||||
725 | |||||||||||
726 | if (!$limit) { |
||||||||||
727 | $limit = $this->faker()->numberBetween(1, 20); |
||||||||||
728 | } |
||||||||||
729 | |||||||||||
730 | while ($tries < $limit) { |
||||||||||
731 | $comment = new \ElggComment(); |
||||||||||
732 | $comment->subtype = $entity->getSubtype() == 'discussion' ? 'discussion_reply' : 'comment'; |
||||||||||
733 | $comment->owner_guid = $this->getRandomUser()->guid ? : $entity->owner_guid; |
||||||||||
734 | $comment->container_guid = $entity->guid; |
||||||||||
735 | $comment->description = $this->faker()->paragraph; |
||||||||||
736 | |||||||||||
737 | $tries++; |
||||||||||
738 | if ($comment->save()) { |
||||||||||
739 | $success++; |
||||||||||
740 | } |
||||||||||
741 | } |
||||||||||
742 | |||||||||||
743 | elgg_set_ignore_access($ia); |
||||||||||
744 | |||||||||||
745 | return $success; |
||||||||||
746 | |||||||||||
747 | } |
||||||||||
748 | |||||||||||
749 | /** |
||||||||||
750 | * Create likes |
||||||||||
751 | * |
||||||||||
752 | * @param ElggEntity $entity Entity to like |
||||||||||
753 | * @param int $limit Number of likes to create |
||||||||||
754 | * |
||||||||||
755 | * @return int |
||||||||||
756 | */ |
||||||||||
757 | public function createLikes(ElggEntity $entity, $limit = null) { |
||||||||||
758 | |||||||||||
759 | $ia = elgg_set_ignore_access(true); |
||||||||||
760 | |||||||||||
761 | $success = 0; |
||||||||||
762 | |||||||||||
763 | if (!$limit) { |
||||||||||
764 | $limit = $this->faker()->numberBetween(1, 20); |
||||||||||
765 | } |
||||||||||
766 | |||||||||||
767 | while ($success < $limit) { |
||||||||||
768 | if ($entity->annotate('likes', true, $entity->access_id, $this->getRandomUser()->guid)) { |
||||||||||
769 | $success++; |
||||||||||
770 | } |
||||||||||
771 | } |
||||||||||
772 | |||||||||||
773 | elgg_set_ignore_access($ia); |
||||||||||
774 | |||||||||||
775 | return $success; |
||||||||||
776 | } |
||||||||||
777 | |||||||||||
778 | /** |
||||||||||
779 | * Log a message |
||||||||||
780 | * |
||||||||||
781 | * @param string $msg Message to log |
||||||||||
782 | * @param string $level Message level |
||||||||||
783 | * Note that 'ERROR' will terminate further code execution |
||||||||||
784 | * |
||||||||||
785 | * @return void |
||||||||||
786 | */ |
||||||||||
787 | 358 | public function log($msg, $level = 'NOTICE') { |
|||||||||
788 | 358 | elgg_log($msg, $level); |
|||||||||
789 | 358 | } |
|||||||||
790 | |||||||||||
791 | } |