Completed
Pull Request — master (#11570)
by Juho
119:39 queued 57:42
created

Seed::getRandomUsername()   C

Complexity

Conditions 9
Paths 36

Size

Total Lines 85
Code Lines 63

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
cc 9
eloc 63
nc 36
nop 1
dl 0
loc 85
ccs 0
cts 72
cp 0
crap 90
rs 5.3909
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Elgg\Database\Seeds;
4
5
/**
6
 * Abstract seed
7
 *
8
 * Plugins should extend this class to create their own seeders,
9
 * add use 'seeds','database' plugin hook to add their seed to the sequence.
10
 */
11
abstract class Seed implements Seedable {
12
	/**
13
	 * @var int Max number of items to be created by the seed
14
	 */
15
	protected $limit = 3;
16
17
	use Seeding;
18
19
	/**
20
	 * Seed constructor.
21
	 *
22
	 * @param null $limit Number of item to seed
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $limit is correct as it would always require null to be passed?
Loading history...
23
	 */
24
	public function __construct($limit = null) {
25
		if (isset($limit)) {
26
			$this->limit = $limit;
27
		}
28
	}
29
30
	/**
31
	 * Populate database
32
	 * @return mixed
33
	 */
34
	abstract function seed();
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
35
36
	/**
37
	 * Removed seeded rows from database
38
	 * @return mixed
39
	 */
40
	abstract function unseed();
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
41
42
	/**
43
	 * Get site domain
44
	 * @return string
45
	 */
46
	public function getDomain() {
47
		return elgg_get_site_entity()->getDomain();
48
	}
49
50
	/**
51
	 * Create a new faker user
52
	 * @return ElggUser|false
0 ignored issues
show
Bug introduced by
The type Elgg\Database\Seeds\ElggUser was not found. Did you mean ElggUser? If so, make sure to prefix the type with \.
Loading history...
53
	 */
54
	public function createUser(array $attributes = [], array $metadata = []) {
55
56
		$metadata['__faker'] = true;
57
58
		if (empty($attributes['password'])) {
59
			$attributes['password'] = generate_random_cleartext_password();
60
		}
61
62
		if (empty($attributes['username'])) {
63
			$attributes['name'] = $this->faker->name;
64
		}
65
66
		if (empty($attributes['username'])) {
67
			$attributes['username'] = $this->getRandomUsername($attributes['name']);
68
		}
69
70
		if (empty($attributes['email'])) {
71
			$attributes['email'] = "{$attributes['username']}@{$this->getDomain()}";
72
			if (!filter_var($attributes['email'], FILTER_VALIDATE_EMAIL)) {
73
				// Travis tests use localhost as the domain name, which generates invalid email addresses
74
				$attributes['email'] = "{$attributes['username']}@localhost.com";
75
			}
76
		}
77
78
		$user = false;
79
80
		try {
81
			$guid = register_user($attributes['username'], $attributes['password'], $attributes['name'], $attributes['email']);
82
			$user = get_entity($guid);
0 ignored issues
show
Bug introduced by
It seems like $guid can also be of type false; 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 ignore-type  annotation

82
			$user = get_entity(/** @scrutinizer ignore-type */ $guid);
Loading history...
83
			/* @var $user ElggUser */
84
85
			elgg_set_user_validation_status($guid, $this->faker->boolean(), 'seeder');
0 ignored issues
show
Deprecated Code introduced by
The function elgg_set_user_validation_status() has been deprecated: Use \ElggUser->setValidationStatus() ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

85
			/** @scrutinizer ignore-deprecated */ elgg_set_user_validation_status($guid, $this->faker->boolean(), 'seeder');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
Bug introduced by
It seems like $guid can also be of type false; however, parameter $user_guid of elgg_set_user_validation_status() 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 ignore-type  annotation

85
			elgg_set_user_validation_status(/** @scrutinizer ignore-type */ $guid, $this->faker->boolean(), 'seeder');
Loading history...
86
87
			$user->setNotificationSetting('email', false);
88
			$user->setNotificationSetting('site', true);
89
90
			$profile_fields = elgg_get_config('profile_fields');
91
92
			$user = $this->populateMetadata($user, $profile_fields, $metadata);
93
94
			$user->save();
95
96
			$this->createIcon($user);
97
			$this->createComments($user);
98
			$this->createLikes($user);
99
100
			$this->log("Created new user $user->name [guid: $user->guid]");
101
102
			return $user;
103
		} catch (Exception $e) {
0 ignored issues
show
Bug introduced by
The type Elgg\Database\Seeds\Exception was not found. Did you mean Exception? If so, make sure to prefix the type with \.
Loading history...
104
			if ($user && $user->guid) {
105
				$user->delete();
106
			}
107
108
			$this->log($e->getMessage());
109
110
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the return type mandated by Elgg\Database\Seeds\Seedable::createUser() of ElggUser.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
111
		}
112
113
	}
114
115
	/**
116
	 * Create a new faker group
117
	 * @return ElggGroup|false
118
	 */
119
	public function createGroup(array $attributes = [], array $metadata = []) {
120
121
		$metadata['__faker'] = true;
122
123
		if (empty($attributes['access_id'])) {
124
			$attributes['access_id'] = ACCESS_PUBLIC;
125
		}
126
127
		if (empty($metadata['content_access_mode'])) {
128
			$metadata['content_access_mode'] = ElggGroup::CONTENT_ACCESS_MODE_UNRESTRICTED;
0 ignored issues
show
Bug introduced by
The type Elgg\Database\Seeds\ElggGroup was not found. Did you mean ElggGroup? If so, make sure to prefix the type with \.
Loading history...
129
		}
130
131
		if (empty($metadata['membership'])) {
132
			$metadata['membership'] = ACCESS_PUBLIC;
133
		}
134
135
		if (empty($attributes['name'])) {
136
			$attributes['name'] = $this->faker->sentence();
137
		}
138
139
		if (empty($attributes['description'])) {
140
			$attributes['description'] = $this->faker->text($this->faker->numberBetween(500, 1000));
141
		}
142
143
		if (empty($attributes['owner_guid'])) {
144
			$user = $this->getRandomUser();
145
			if (!$user) {
146
				$user = $this->createUser();
147
			}
148
149
			$attributes['owner_guid'] = $user->guid;
0 ignored issues
show
Bug introduced by
The property guid does not exist on false.
Loading history...
150
		}
151
152
		if (empty($attributes['container_guid'])) {
153
			$attributes['container_guid'] = $attributes['owner_guid'];
154
		}
155
156
		$owner = get_entity($attributes['owner_guid']);
157
		if (!$owner) {
158
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the return type mandated by Elgg\Database\Seeds\Seedable::createGroup() of ElggGroup.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
159
		}
160
161
		$container = get_entity($attributes['container_guid']);
162
		if (!$container) {
163
			return false;
164
		}
165
166
		$tool_options = elgg_get_config('group_tool_options');
167
		if ($tool_options) {
168
			foreach ($tool_options as $group_option) {
169
				$option_toggle_name = $group_option->name . "_enable";
170
				$option_default = $group_option->default_on ? 'yes' : 'no';
171
				$metadata[$option_toggle_name] = $option_default;
172
			}
173
		}
174
175
		if ($this->faker->boolean(20)) {
176
			$metadata['featured_group'] = 'yes';
177
		}
178
179
		$group = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $group is dead and can be removed.
Loading history...
180
181
		try {
182
183
			$group = new ElggGroup();
184
			foreach ($attributes as $name => $value) {
185
				$group->$name = $value;
186
			}
187
188
			$group = $this->populateMetadata($group, elgg_get_config('group'), $metadata);
189
190
			$group->save();
191
192
			if ($group->access_id == ACCESS_PRIVATE) {
193
				$group->access_id = $group->group_acl;
194
				$group->save();
195
			}
196
197
			$group->join(get_entity($attributes['owner_guid']));
198
199
			$this->createIcon($group);
200
201
			$this->createComments($group);
202
			$this->createLikes($group);
203
204
			elgg_create_river_item([
205
				'view' => 'river/group/create',
206
				'action_type' => 'create',
207
				'subject_guid' => $owner->guid,
208
				'object_guid' => $group->guid,
209
				'target_guid' => $container->guid,
210
			]);
211
212
			$this->log("Created new group $group->name [guid: $group->guid]");
213
214
			return $group;
215
		} catch (Exception $e) {
216
			if ($group && $group->guid) {
217
				$group->delete();
218
			}
219
220
			$this->log($e->getMessage());
221
222
			return false;
223
		}
224
225
	}
226
227
	/**
228
	 * Create a new faker object
229
	 * @return ElggObject|false
230
	 */
231
	public function createObject(array $attributes = [], array $metadata = []) {
232
233
		$metadata['__faker'] = true;
234
235
		if (empty($attributes['title'])) {
236
			$attributes['title'] = $this->faker->sentence();
237
		}
238
239
		if (empty($attributes['description'])) {
240
			$attributes['description'] = $this->faker->text($this->faker->numberBetween(500, 1000));
241
		}
242
243
		if (empty($attributes['container_guid'])) {
244
			if ($this->faker->boolean()) {
245
				$container = $this->getRandomGroup();
246
			} else {
247
				$container = $this->getRandomUser();
248
			}
249
250
			$attributes['container_guid'] = $container->guid;
0 ignored issues
show
Bug introduced by
The property guid does not exist on false.
Loading history...
251
		}
252
253
		if (empty($attributes['subtype'])) {
254
			$attributes['subtype'] = strtolower($this->faker->word);
255
		}
256
257
		if (empty($metadata['tags'])) {
258
			$metadata['tags'] = $this->faker->words(10);
259
		}
260
261
		if (empty($attributes['owner_guid'])) {
262
			if ($container instanceof ElggGroup) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $container does not seem to be defined for all execution paths leading up to this point.
Loading history...
263
				$members = elgg_get_entities_from_relationship([
0 ignored issues
show
Deprecated Code introduced by
The function elgg_get_entities_from_relationship() has been deprecated: 3.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

263
				$members = /** @scrutinizer ignore-deprecated */ elgg_get_entities_from_relationship([

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
264
					'types' => 'user',
265
					'relationship' => 'member',
266
					'relationship_guid' => $container->guid,
267
					'inverse_relationship' => true,
268
					'limit' => 0,
269
					'metadata_names' => '__faker',
270
					'order_by' => 'RAND()',
271
				]);
272
				$owner = array_shift($members);
0 ignored issues
show
Bug introduced by
It seems like $members can also be of type integer and false; however, parameter $array of array_shift() does only seem to accept array, 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 ignore-type  annotation

272
				$owner = array_shift(/** @scrutinizer ignore-type */ $members);
Loading history...
273
			} else {
274
				$owner = $container;
275
			}
276
277
			$attributes['owner_guid'] = $owner->guid;
278
		}
279
280
		$owner = get_entity($attributes['owner_guid']);
281
		if (!$owner) {
282
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the return type mandated by Elgg\Database\Seeds\Seedable::createObject() of ElggObject.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
283
		}
284
285
		$container = get_entity($attributes['container_guid']);
286
		if (!$container) {
287
			return false;
288
		}
289
290
		if (empty($attributes['access_id'])) {
291
			$attributes['access_id'] = $this->getRandomAccessId($owner, $container);
292
		}
293
294
		$object = false;
295
296
		try {
297
			$class = get_subtype_class('object', $attributes['subtype']);
0 ignored issues
show
Bug introduced by
The function get_subtype_class was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

297
			$class = /** @scrutinizer ignore-call */ get_subtype_class('object', $attributes['subtype']);
Loading history...
298
			if ($class && class_exists($class)) {
299
				$object = new $class();
300
			} else {
301
				$object = new ElggObject();
0 ignored issues
show
Bug introduced by
The type Elgg\Database\Seeds\ElggObject was not found. Did you mean ElggObject? If so, make sure to prefix the type with \.
Loading history...
302
			}
303
			foreach ($attributes as $name => $value) {
304
				$object->$name = $value;
305
			}
306
307
			$object = $this->populateMetadata($object, [], $metadata);
308
309
			$object->save();
310
311
			$this->createComments($object);
312
			$this->createLikes($object);
313
314
			$type_str = elgg_echo("item:object:{$object->getSubtype()}");
315
316
			$this->log("Created new item in $type_str $object->title [guid: $object->guid]");
317
318
			return $object;
319
		} catch (Exception $e) {
320
			if ($object && $object->guid) {
321
				$object->delete();
322
			}
323
324
			$this->log($e->getMessage());
325
326
			return false;
327
		}
328
329
	}
330
331
	/**
332
	 * Returns random fake user
333
	 *
334
	 * @param int[] $exclude GUIDs to exclude
335
	 *
336
	 * @return ElggUser|false
337
	 */
338
	public function getRandomUser(array $exclude = []) {
339
340
		$exclude[] = 0;
341
		$exclude_in = implode(',', array_map(function ($e) {
342
			return (int) $e;
343
		}, $exclude));
344
345
		$users = elgg_get_entities_from_metadata([
0 ignored issues
show
Deprecated Code introduced by
The function elgg_get_entities_from_metadata() has been deprecated: 3.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

345
		$users = /** @scrutinizer ignore-deprecated */ elgg_get_entities_from_metadata([

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
346
			'types' => 'user',
347
			'metadata_names' => ['__faker'],
348
			'limit' => 1,
349
			'wheres' => [
350
				"e.guid NOT IN ($exclude_in)",
351
			],
352
			'order_by' => 'RAND()',
353
		]);
354
355
		return $users ? $users[0] : false;
356
	}
357
358
	/**
359
	 * Returns random fake group
360
	 *
361
	 * @param int[] $exclude GUIDs to exclude
362
	 *
363
	 * @return ElggGroup|false
364
	 */
365
	public function getRandomGroup(array $exclude = []) {
366
367
		$exclude[] = 0;
368
		$exclude_in = implode(',', array_map(function ($e) {
369
			return (int) $e;
370
		}, $exclude));
371
372
		$groups = elgg_get_entities_from_metadata([
0 ignored issues
show
Deprecated Code introduced by
The function elgg_get_entities_from_metadata() has been deprecated: 3.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

372
		$groups = /** @scrutinizer ignore-deprecated */ elgg_get_entities_from_metadata([

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
373
			'types' => 'group',
374
			'metadata_names' => ['__faker'],
375
			'limit' => 1,
376
			'wheres' => [
377
				"e.guid NOT IN ($exclude_in)",
378
			],
379
			'order_by' => 'RAND()',
380
		]);
381
382
		return $groups ? $groups[0] : false;
383
	}
384
385
	/**
386
	 * Get random access id
387
	 *
388
	 * @param ElggUser   $user      User
389
	 * @param ElggEntity $container Container
390
	 *
391
	 * @return int
392
	 */
393
	public function getRandomAccessId(\ElggUser $user = null, ElggEntity $container = null) {
0 ignored issues
show
Bug introduced by
The type Elgg\Database\Seeds\ElggEntity was not found. Did you mean ElggEntity? If so, make sure to prefix the type with \.
Loading history...
394
395
		$params = [
396
			'container_guid' => $container->guid,
397
		];
398
399
		$access_array = get_write_access_array($user->guid, null, null, $params);
400
401
		$access_key = array_rand($access_array, 1);
402
403
		return $access_array[$access_key];
404
	}
405
406
	/**
407
	 * Generates a unique available and valid username
408
	 *
409
	 * @param string $base_name Display name, email or other prefix to use as basis
410
	 *
411
	 * @return string
412
	 */
413
	public function getRandomUsername($base_name = 'user') {
414
415
		$available = false;
416
417
		$base_name = iconv('UTF-8', 'ASCII//TRANSLIT', $base_name);
418
		$blacklist = '/[\x{0080}-\x{009f}\x{00a0}\x{2000}-\x{200f}\x{2028}-\x{202f}\x{3000}\x{e000}-\x{f8ff}]/u';
419
		$blacklist2 = [
420
			' ',
421
			'\'',
422
			'/',
423
			'\\',
424
			'"',
425
			'*',
426
			'&',
427
			'?',
428
			'#',
429
			'%',
430
			'^',
431
			'(',
432
			')',
433
			'{',
434
			'}',
435
			'[',
436
			']',
437
			'~',
438
			'?',
439
			'<',
440
			'>',
441
			';',
442
			'|',
443
			'¬',
444
			'`',
445
			'@',
446
			'-',
447
			'+',
448
			'='
449
		];
450
451
		$base_name = preg_replace($blacklist, '', $base_name);
452
		$base_name = str_replace($blacklist2, '.', $base_name);
453
454
		$ia = elgg_set_ignore_access(true);
455
456
		$ha = access_get_show_hidden_status();
457
		access_show_hidden_entities(true);
458
459
		$minlength = elgg_get_config('minusername') ? : 4;
460
		if ($base_name) {
461
			$fill = $minlength - strlen($base_name);
462
		} else {
463
			$fill = 8;
464
		}
465
466
		$separator = '.';
467
468
		if ($fill > 0) {
469
			$suffix = (new ElggCrypto())->getRandomString($fill);
0 ignored issues
show
Bug introduced by
The type Elgg\Database\Seeds\ElggCrypto was not found. Did you mean ElggCrypto? If so, make sure to prefix the type with \.
Loading history...
470
			$base_name = "$base_name$separator$suffix";
471
		}
472
473
		$iterator = 0;
474
		while (!$available) {
475
			if ($iterator > 0) {
476
				$base_name = "$base_name$separator$iterator";
477
			}
478
			$user = get_user_by_username($base_name);
479
			$available = !$user;
480
			try {
481
				if ($available) {
482
					validate_username($base_name);
483
				}
484
			} catch (\Exception $e) {
485
				if ($iterator >= 10) {
486
					// too many failed attempts
487
					$base_name = (new ElggCrypto())->getRandomString(8);
488
				}
489
			}
490
491
			$iterator++;
492
		}
493
494
		access_show_hidden_entities($ha);
495
		elgg_set_ignore_access($ia);
496
497
		return strtolower($base_name);
498
	}
499
500
	/**
501
	 * Set random metadata
502
	 *
503
	 * @param ElggEntity $entity   Entity
504
	 * @param array      $fields   An array of profile fields in $name => $input_type format
505
	 * @param array      $metadata Other metadata $name => $value pairs to set
506
	 *
507
	 * @return ElggEntity
508
	 */
509
	public function populateMetadata(ElggEntity $entity, array $fields = [], array $metadata = []) {
510
511
		foreach ($fields as $name => $type) {
512
			if (isset($metadata[$name])) {
513
				continue;
514
			}
515
516
			switch ($name) {
517
				case 'phone' :
518
				case 'mobile' :
519
					$metadata[$name] = $this->faker->phoneNumber;
520
					break;
521
522
				default :
523
					switch ($type) {
524
						case 'plaintext' :
525
						case 'longtext' :
526
							$metadata[$name] = $this->faker->text($this->faker->numberBetween(500, 1000));
527
							break;
528
529
						case 'text' :
530
							$metadata[$name] = $this->faker->sentence;
531
							break;
532
533
						case 'tags' :
534
							$metadata[$name] = $this->faker->words(10);
535
							break;
536
537
						case 'url' :
538
							$metadata[$name] = $this->faker->url;
539
							break;
540
541
						case 'email' :
542
							$metadata[$name] = $this->faker->email;
543
							break;
544
545
						case 'number' :
546
							$metadata[$name] = $this->faker->randomNumber();
547
							break;
548
549
						case 'date' :
550
							$metadata[$name] = $this->faker->unixTime;
551
							break;
552
553
						case 'password' :
554
							$metadata[$name] = generate_random_cleartext_password();
555
							break;
556
557
						case 'location' :
558
							$metadata[$name] = $this->faker->address;
559
							$metadata['geo:lat'] = $this->faker->latitude;
560
							$metadata['geo:long'] = $this->faker->longitude;
561
							break;
562
563
						default :
564
							$metadata[$name] = '';
565
							break;
566
					}
567
568
					break;
569
			}
570
		}
571
572
		foreach ($metadata as $key => $value) {
573
			$entity->$key = $value;
574
		}
575
576
		return $entity;
577
	}
578
579
	/**
580
	 * Create an icon for an entity
581
	 *
582
	 * @param ElggEntity $entity Entity
583
	 *
584
	 * @return bool
585
	 */
586
	public function createIcon(ElggEntity $entity) {
587
588
		$icon_location = $this->faker->image();
589
		if (empty($icon_location)) {
590
			return false;
591
		}
592
593
		$result = $entity->saveIconFromLocalFile($icon_location);
594
595
		if ($result && $entity instanceof ElggUser) {
596
			elgg_create_river_item([
597
				'view' => 'river/user/default/profileiconupdate',
598
				'action_type' => 'update',
599
				'subject_guid' => $entity->guid,
600
				'object_guid' => $entity->guid,
601
			]);
602
		}
603
604
		return $result;
605
	}
606
607
	/**
608
	 * Create comments/replies
609
	 *
610
	 * @param ElggEntity $entity Entity to comment on
611
	 * @param int        $limit  Number of comments to create
612
	 *
613
	 * @return int Number of generated comments
614
	 */
615
	public function createComments(ElggEntity $entity, $limit = null) {
616
617
		$success = 0;
618
619
		if (!$limit) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $limit of type null|integer is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
620
			$limit = $this->faker->numberBetween(1, 20);
621
		}
622
623
		while ($success < $limit) {
624
625
			$comment = new ElggObject();
626
			$comment->subtype = $entity->getSubtype() == 'discussion' ? 'discussion_reply' : 'comment';
627
			$comment->owner_guid = $this->getRandomUser()->guid ? : $entity->owner_guid;
0 ignored issues
show
Bug introduced by
The property guid does not exist on false.
Loading history...
628
			$comment->container_guid = $entity->guid;
629
			$comment->description = $this->faker->paragraph;
630
631
			if ($comment->save()) {
632
				$success++;
633
			}
634
		}
635
636
		return $success;
637
638
	}
639
640
	/**
641
	 * Create likes
642
	 *
643
	 * @param ElggEntity $entity Entity to like
644
	 * @param int        $limit  Number of likes to create
645
	 *
646
	 * @return int
647
	 */
648
	public function createLikes(ElggEntity $entity, $limit = null) {
649
650
		$success = 0;
651
652
		if (!$limit) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $limit of type null|integer is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
653
			$limit = $this->faker->numberBetween(1, 20);
654
		}
655
656
		while ($success < $limit) {
657
			if ($entity->annotate('likes', true, $entity->access_id, $this->getRandomUser()->guid)) {
0 ignored issues
show
Bug introduced by
The property guid does not exist on false.
Loading history...
658
				$success++;
659
			}
660
		}
661
662
		return $success;
663
	}
664
665
	/**
666
	 * Log a message
667
	 *
668
	 * @param string $msg Message to log
669
	 *
670
	 * @return void
671
	 */
672
	public function log($msg, $level = 'NOTICE') {
673
674
		if (php_sapi_name() === 'cli') {
675
			$handle = $level === 'ERROR' ? STDERR : STDOUT;
676
			fwrite($handle, $msg . PHP_EOL);
677
		} else {
678
			elgg_log($msg, $level);
679
		}
680
	}
681
}
682