Completed
Push — 2.3 ( 07b9ab...95473c )
by Jeroen
24:31 queued 11:55
created

Seed::populateMetadata()   C

Complexity

Conditions 17
Paths 32

Size

Total Lines 74
Code Lines 52

Duplication

Lines 10
Ratio 13.51 %

Importance

Changes 0
Metric Value
cc 17
eloc 52
nc 32
nop 3
dl 10
loc 74
rs 5.3488
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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
use ElggEntity;
6
use ElggGroup;
7
use ElggObject;
8
use ElggUser;
9
use Exception;
10
use Faker\Factory;
11
12
/**
13
 * Abstract seed
14
 *
15
 * Plugins should extend this class to create their own seeders,
16
 * add use 'seeds','database' plugin hook to add their seed to the sequence.
17
 */
18
abstract class Seed {
19
20
	/**
21
	 * @var int Max number of items to be created by the seed
22
	 */
23
	protected $limit = 20;
24
25
	/**
26
	 * @var \Faker\Generator
27
	 */
28
	protected $faker;
29
30
	/**
31
	 * Seed constructor.
32
	 *
33
	 * @param string $locale Locale
34
	 */
35
	public function __construct($locale = 'en_US') {
36
		$this->faker = Factory::create($locale);
37
	}
38
39
	/**
40
	 * Populate database
41
	 * @return mixed
42
	 */
43
	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...
44
45
	/**
46
	 * Removed seeded rows from database
47
	 * @return mixed
48
	 */
49
	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...
50
51
	/**
52
	 * Get site domain
53
	 * @return string
54
	 */
55
	public function getDomain() {
56
		return elgg_get_site_entity()->getDomain();
57
	}
58
59
	/**
60
	 * Create a new faker user
61
	 * @return ElggUser|false
62
	 */
63
	public function createUser(array $attributes = [], array $metadata = []) {
64
65
		$metadata['__faker'] = true;
66
67
		if (empty($attributes['password'])) {
68
			$attributes['password'] = generate_random_cleartext_password();
69
		}
70
71
		if (empty($attributes['username'])) {
72
			$attributes['name'] = $this->faker->name;
73
		}
74
75
		if (empty($attributes['username'])) {
76
			$attributes['username'] = $this->getRandomUsername($attributes['name']);
77
		}
78
79
		if (empty($attributes['email'])) {
80
			$attributes['email'] = "{$attributes['username']}@{$this->getDomain()}";
81
			if (!filter_var($attributes['email'], FILTER_VALIDATE_EMAIL)) {
82
				// Travis tests use localhost as the domain name, which generates invalid email addresses
83
				$attributes['email'] = "{$attributes['username']}@localhost.com";
84
			}
85
		}
86
87
		$user = false;
88
89
		try {
90
			$guid = register_user($attributes['username'], $attributes['password'], $attributes['name'], $attributes['email']);
91
			$user = get_entity($guid);
0 ignored issues
show
Bug introduced by
It seems like $guid defined by register_user($attribute..., $attributes['email']) on line 90 can also be of type false or null; however, get_entity() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
92
			/* @var $user ElggUser */
93
94
			elgg_set_user_validation_status($guid, $this->faker->boolean(), 'seeder');
0 ignored issues
show
Bug introduced by
It seems like $guid defined by register_user($attribute..., $attributes['email']) on line 90 can also be of type false or null; however, elgg_set_user_validation_status() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
95
96
			$user->setNotificationSetting('email', false);
97
			$user->setNotificationSetting('site', true);
98
99
			$profile_fields = elgg_get_config('profile_fields');
100
101
			$user = $this->populateMetadata($user, $profile_fields, $metadata);
102
103
			$user->save();
104
105
			$this->createIcon($user);
106
			$this->createComments($user);
107
			$this->createLikes($user);
108
109
			$this->log("Created new user $user->name [guid: $user->guid]");
110
111
			return $user;
112
		} catch (Exception $e) {
113
			if ($user && $user->guid) {
114
				$user->delete();
115
			}
116
117
			$this->log($e->getMessage());
118
119
			return false;
120
		}
121
122
	}
123
124
	/**
125
	 * Create a new faker group
126
	 * @return ElggGroup|false
127
	 */
128
	public function createGroup(array $attributes = [], array $metadata = []) {
129
130
		$metadata['__faker'] = true;
131
132
		if (empty($attributes['access_id'])) {
133
			$attributes['access_id'] = ACCESS_PUBLIC;
134
		}
135
136
		if (empty($metadata['content_access_mode'])) {
137
			$metadata['content_access_mode'] = ElggGroup::CONTENT_ACCESS_MODE_UNRESTRICTED;
138
		}
139
140
		if (empty($metadata['membership'])) {
141
			$metadata['membership'] = ACCESS_PUBLIC;
142
		}
143
144
		if (empty($attributes['name'])) {
145
			$attributes['name'] = $this->faker->sentence();
146
		}
147
148 View Code Duplication
		if (empty($attributes['description'])) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
149
			$attributes['description'] = $this->faker->text($this->faker->numberBetween(500, 1000));
150
		}
151
152
		if (empty($attributes['owner_guid'])) {
153
			$user = $this->getRandomUser();
154
			if (!$user) {
155
				$user = $this->createUser();
156
			}
157
158
			$attributes['owner_guid'] = $user->guid;
159
		}
160
161
		if (empty($attributes['container_guid'])) {
162
			$attributes['container_guid'] = $attributes['owner_guid'];
163
		}
164
165
		$owner = get_entity($attributes['owner_guid']);
166
		if (!$owner) {
167
			return false;
168
		}
169
170
		$container = get_entity($attributes['container_guid']);
171
		if (!$container) {
172
			return false;
173
		}
174
175
		$tool_options = elgg_get_config('group_tool_options');
176
		if ($tool_options) {
177
			foreach ($tool_options as $group_option) {
178
				$option_toggle_name = $group_option->name . "_enable";
179
				$option_default = $group_option->default_on ? 'yes' : 'no';
180
				$metadata[$option_toggle_name] = $option_default;
181
			}
182
		}
183
184
		if ($this->faker->boolean(20)) {
185
			$metadata['featured_group'] = 'yes';
186
		}
187
188
		$group = false;
189
190
		try {
191
192
			$group = new ElggGroup();
193
			foreach ($attributes as $name => $value) {
194
				$group->$name = $value;
195
			}
196
197
			$group = $this->populateMetadata($group, elgg_get_config('group'), $metadata);
198
199
			$group->save();
200
201
			if ($group->access_id == ACCESS_PRIVATE) {
202
				$group->access_id = $group->group_acl;
1 ignored issue
show
Documentation introduced by
The property group_acl does not exist on object<ElggEntity>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
203
				$group->save();
204
			}
205
206
			$group->join(get_entity($attributes['owner_guid']));
207
208
			$this->createIcon($group);
209
210
			$this->createComments($group);
211
			$this->createLikes($group);
212
213
			elgg_create_river_item([
214
				'view' => 'river/group/create',
215
				'action_type' => 'create',
216
				'subject_guid' => $owner->guid,
217
				'object_guid' => $group->guid,
218
				'target_guid' => $container->guid,
219
			]);
220
221
			$this->log("Created new group $group->name [guid: $group->guid]");
222
223
			return $group;
224
		} catch (Exception $e) {
225
			if ($group && $group->guid) {
226
				$group->delete();
227
			}
228
229
			$this->log($e->getMessage());
230
231
			return false;
232
		}
233
234
	}
235
236
	/**
237
	 * Create a new faker object
238
	 * @return ElggObject|false
239
	 */
240
	public function createObject(array $attributes = [], array $metadata = []) {
241
242
		$metadata['__faker'] = true;
243
244
		if (empty($attributes['title'])) {
245
			$attributes['title'] = $this->faker->sentence();
246
		}
247
248 View Code Duplication
		if (empty($attributes['description'])) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
249
			$attributes['description'] = $this->faker->text($this->faker->numberBetween(500, 1000));
250
		}
251
252
		if (empty($attributes['container_guid'])) {
253
			if ($this->faker->boolean()) {
254
				$container = $this->getRandomGroup();
255
			} else {
256
				$container = $this->getRandomUser();
257
			}
258
259
			$attributes['container_guid'] = $container->guid;
260
		}
261
262
		if (empty($attributes['subtype'])) {
263
			$attributes['subtype'] = strtolower($this->faker->word);
264
		}
265
266
		if (empty($metadata['tags'])) {
267
			$metadata['tags'] = $this->faker->words(10);
268
		}
269
270
		if (empty($attributes['owner_guid'])) {
271
			if ($container instanceof ElggGroup) {
272
				$members = elgg_get_entities_from_relationship([
273
					'types' => 'user',
274
					'relationship' => 'member',
275
					'relationship_guid' => $container->guid,
0 ignored issues
show
Bug introduced by
The variable $container does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
276
					'inverse_relationship' => true,
277
					'limit' => 0,
278
					'metadata_names' => '__faker',
279
					'order_by' => 'RAND()',
280
				]);
281
				$owner = array_shift($members);
282
			} else {
283
				$owner = $container;
284
			}
285
286
			$attributes['owner_guid'] = $owner->guid;
287
		}
288
289
		$owner = get_entity($attributes['owner_guid']);
290
		if (!$owner) {
291
			return false;
292
		}
293
294
		$container = get_entity($attributes['container_guid']);
295
		if (!$container) {
296
			return false;
297
		}
298
299
		if (empty($attributes['access_id'])) {
300
			$attributes['access_id'] = $this->getRandomAccessId($owner, $container);
0 ignored issues
show
Documentation introduced by
$owner is of type object<ElggEntity>, but the function expects a null|object<ElggUser>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
301
		}
302
303
		$object = false;
304
305
		try {
306
			$class = get_subtype_class('object', $attributes['subtype']);
307
			if ($class && class_exists($class)) {
1 ignored issue
show
Bug Best Practice introduced by
The expression $class of type string|null is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
308
				$object = new $class();
309
			} else {
310
				$object = new ElggObject();
311
			}
312
			foreach ($attributes as $name => $value) {
313
				$object->$name = $value;
314
			}
315
316
			$object = $this->populateMetadata($object, [], $metadata);
317
318
			$object->save();
319
320
			$this->createComments($object);
321
			$this->createLikes($object);
322
323
			$type_str = elgg_echo("item:object:{$object->getSubtype()}");
324
325
			$this->log("Created new item in $type_str $object->title [guid: $object->guid]");
326
327
			return $object;
328
		} catch (Exception $e) {
329
			if ($object && $object->guid) {
330
				$object->delete();
331
			}
332
333
			$this->log($e->getMessage());
334
335
			return false;
336
		}
337
338
	}
339
340
	/**
341
	 * Returns random fake user
342
	 *
343
	 * @param int[] $exclude GUIDs to exclude
344
	 *
345
	 * @return ElggUser|false
346
	 */
347 View Code Duplication
	public function getRandomUser(array $exclude = []) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
348
349
		$exclude[] = 0;
350
		$exclude_in = implode(',', array_map(function ($e) {
351
			return (int) $e;
352
		}, $exclude));
353
354
		$users = elgg_get_entities_from_metadata([
355
			'types' => 'user',
356
			'metadata_names' => ['__faker'],
357
			'limit' => 1,
358
			'wheres' => [
359
				"e.guid NOT IN ($exclude_in)",
360
			],
361
			'order_by' => 'RAND()',
362
		]);
363
364
		return $users ? $users[0] : false;
365
	}
366
367
	/**
368
	 * Returns random fake group
369
	 *
370
	 * @param int[] $exclude GUIDs to exclude
371
	 *
372
	 * @return ElggGroup|false
373
	 */
374 View Code Duplication
	public function getRandomGroup(array $exclude = []) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
375
376
		$exclude[] = 0;
377
		$exclude_in = implode(',', array_map(function ($e) {
378
			return (int) $e;
379
		}, $exclude));
380
381
		$groups = elgg_get_entities_from_metadata([
382
			'types' => 'group',
383
			'metadata_names' => ['__faker'],
384
			'limit' => 1,
385
			'wheres' => [
386
				"e.guid NOT IN ($exclude_in)",
387
			],
388
			'order_by' => 'RAND()',
389
		]);
390
391
		return $groups ? $groups[0] : false;
392
	}
393
394
	/**
395
	 * Get random access id
396
	 *
397
	 * @param ElggUser   $user      User
398
	 * @param ElggEntity $container Container
399
	 *
400
	 * @return int
401
	 */
402
	public function getRandomAccessId(\ElggUser $user = null, ElggEntity $container = null) {
403
404
		$params = [
405
			'container_guid' => $container->guid,
406
		];
407
408
		$access_array = get_write_access_array($user->guid, null, null, $params);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
409
410
		$access_key = array_rand($access_array, 1);
411
412
		return $access_array[$access_key];
413
	}
414
415
	/**
416
	 * Generates a unique available and valid username
417
	 *
418
	 * @param string $base_name Display name, email or other prefix to use as basis
419
	 *
420
	 * @return string
421
	 */
422
	public function getRandomUsername($base_name = 'user') {
423
424
		$available = false;
425
426
		$base_name = iconv('UTF-8', 'ASCII//TRANSLIT', $base_name);
427
		$blacklist = '/[\x{0080}-\x{009f}\x{00a0}\x{2000}-\x{200f}\x{2028}-\x{202f}\x{3000}\x{e000}-\x{f8ff}]/u';
428
		$blacklist2 = [
429
			' ',
430
			'\'',
431
			'/',
432
			'\\',
433
			'"',
434
			'*',
435
			'&',
436
			'?',
437
			'#',
438
			'%',
439
			'^',
440
			'(',
441
			')',
442
			'{',
443
			'}',
444
			'[',
445
			']',
446
			'~',
447
			'?',
448
			'<',
449
			'>',
450
			';',
451
			'|',
452
			'¬',
453
			'`',
454
			'@',
455
			'-',
456
			'+',
457
			'='
458
		];
459
460
		$base_name = preg_replace($blacklist, '', $base_name);
461
		$base_name = str_replace($blacklist2, '.', $base_name);
462
463
		$ia = elgg_set_ignore_access(true);
464
465
		$ha = access_get_show_hidden_status();
466
		access_show_hidden_entities(true);
467
468
		$minlength = elgg_get_config('minusername') ? : 4;
469
		if ($base_name) {
470
			$fill = $minlength - strlen($base_name);
471
		} else {
472
			$fill = 8;
473
		}
474
475
		$separator = '.';
476
477
		if ($fill > 0) {
478
			$suffix = (new ElggCrypto())->getRandomString($fill);
479
			$base_name = "$base_name$separator$suffix";
480
		}
481
482
		$iterator = 0;
483
		while (!$available) {
484
			if ($iterator > 0) {
485
				$base_name = "$base_name$separator$iterator";
486
			}
487
			$user = get_user_by_username($base_name);
488
			$available = !$user;
489
			try {
490
				if ($available) {
491
					validate_username($base_name);
492
				}
493
			} catch (\Exception $e) {
494
				if ($iterator >= 10) {
495
					// too many failed attempts
496
					$base_name = (new ElggCrypto())->getRandomString(8);
497
				}
498
			}
499
500
			$iterator++;
501
		}
502
503
		access_show_hidden_entities($ha);
504
		elgg_set_ignore_access($ia);
505
506
		return strtolower($base_name);
507
	}
508
509
	/**
510
	 * Set random metadata
511
	 *
512
	 * @param ElggEntity $entity   Entity
513
	 * @param array      $fields   An array of profile fields in $name => $input_type format
514
	 * @param array      $metadata Other metadata $name => $value pairs to set
515
	 *
516
	 * @return ElggEntity
517
	 */
518
	public function populateMetadata(ElggEntity $entity, array $fields = [], array $metadata = []) {
519
520
		foreach ($fields as $name => $type) {
521
			if (isset($metadata[$name])) {
522
				continue;
523
			}
524
525
			switch ($name) {
526
				case 'phone' :
527
				case 'mobile' :
528
					$metadata[$name] = $this->faker->phoneNumber;
529
					break;
530
531
				default :
532
					switch ($type) {
533
						case 'plaintext' :
534
						case 'longtext' :
535
							$metadata[$name] = $this->faker->text($this->faker->numberBetween(500, 1000));
536
							break;
537
538
						case 'text' :
539
							$metadata[$name] = $this->faker->sentence;
540
							break;
541
542
						case 'tags' :
543
							$metadata[$name] = $this->faker->words(10);
544
							break;
545
546
						case 'url' :
547
							$metadata[$name] = $this->faker->url;
548
549
						case 'email' :
550
							$metadata[$name] = $this->faker->email;
551
							break;
552
553
						case 'number' :
554
							$metadata[$name] = $this->faker->randomNumber();
555
							break;
556
557
						case 'date' :
558
							$metadata[$name] = $this->faker->unixTime;
559
							break;
560
561
						case 'password' :
562
							$metadata[$name] = generate_random_cleartext_password();
563
							break;
564
565 View Code Duplication
						case 'location' :
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
566
							$metadata[$name] = $this->faker->address;
567
							$metadata['geo:lat'] = $this->faker->latitude;
568
							$metadata['geo:long'] = $this->faker->longitude;
569
							break;
570
571 View Code Duplication
						case 'email' :
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
572
							$metadata[$name] = $this->faker->address;
573
							$metadata['geo:lat'] = $this->faker->latitude;
574
							$metadata['geo:long'] = $this->faker->longitude;
575
							break;
576
577
						default :
578
							$metadata[$name] = '';
579
							break;
580
					}
581
582
					break;
583
			}
584
		}
585
586
		foreach ($metadata as $key => $value) {
587
			$entity->$key = $value;
588
		}
589
590
		return $entity;
591
	}
592
593
	/**
594
	 * Create an icon for an entity
595
	 *
596
	 * @param ElggEntity $entity Entity
597
	 *
598
	 * @return bool
599
	 */
600
	public function createIcon(ElggEntity $entity) {
601
602
		$icon_url = $this->faker->imageURL();
603
604
		$file_contents = file_get_contents($icon_url);
605
606
		$tmp = new \ElggFile();
607
		$tmp->owner_guid = $entity->guid;
608
		$tmp->setFilename("tmp/icon_src.jpg");
609
		$tmp->open('write');
610
		$tmp->write($file_contents);
611
		$tmp->close();
612
613
		$result = $entity->saveIconFromElggFile($tmp);
614
615
		$tmp->delete();
616
617 View Code Duplication
		if ($result && $entity instanceof ElggUser) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
618
			elgg_create_river_item([
619
				'view' => 'river/user/default/profileiconupdate',
620
				'action_type' => 'update',
621
				'subject_guid' => $entity->guid,
622
				'object_guid' => $entity->guid,
623
			]);
624
		}
625
626
		return $result;
627
	}
628
629
	/**
630
	 * Create comments/replies
631
	 *
632
	 * @param ElggEntity $entity Entity to comment on
633
	 * @param int        $limit  Number of comments to create
634
	 *
635
	 * @return int Number of generated comments
636
	 */
637
	public function createComments(ElggEntity $entity, $limit = null) {
638
639
		$success = 0;
640
641
		if (!$limit) {
1 ignored issue
show
Bug Best Practice introduced by
The expression $limit of type integer|null is loosely compared to false; this is ambiguous if the integer can be zero. 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...
642
			$limit = $this->faker->numberBetween(1, 20);
643
		}
644
645
		while ($success < $limit) {
646
647
			$comment = new ElggObject();
648
			$comment->subtype = $entity->getSubtype() == 'discussion' ? 'discussion_reply' : 'comment';
649
			$comment->owner_guid = $this->getRandomUser()->guid ? : $entity->owner_guid;
650
			$comment->container_guid = $entity->guid;
651
			$comment->description = $this->faker->paragraph;
652
653
			if ($comment->save()) {
654
				$success++;
655
			}
656
		}
657
658
		return $success;
659
660
	}
661
662
	/**
663
	 * Create likes
664
	 *
665
	 * @param ElggEntity $entity Entity to like
666
	 * @param int        $limit  Number of likes to create
667
	 *
668
	 * @return int
669
	 */
670
	public function createLikes(ElggEntity $entity, $limit = null) {
671
672
		$success = 0;
673
674
		if (!$limit) {
1 ignored issue
show
Bug Best Practice introduced by
The expression $limit of type integer|null is loosely compared to false; this is ambiguous if the integer can be zero. 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...
675
			$limit = $this->faker->numberBetween(1, 20);
676
		}
677
678
		while ($success < $limit) {
679
			if ($entity->annotate('likes', true, $entity->access_id, $this->getRandomUser()->guid)) {
680
				$success++;
681
			}
682
		}
683
684
		return $success;
685
	}
686
687
	/**
688
	 * Log a message
689
	 *
690
	 * @param string $msg Message to log
691
	 *
692
	 * @return void
693
	 */
694
	public function log($msg, $level = 'NOTICE') {
695
696
		if (php_sapi_name() === 'cli') {
697
			$handle = $level === 'ERROR' ? STDERR : STDOUT;
698
			fwrite($handle, $msg . PHP_EOL);
699
		} else {
700
			elgg_log($msg, $level);
701
		}
702
	}
703
}