Elgg  Version 2.3
Seed.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Database\Seeds;
4 
13 
20 abstract class Seed {
21 
25  protected $limit = 3;
26 
30  protected $faker;
31 
37  public function __construct($locale = 'en_US') {
38  $this->faker = Factory::create($locale);
39 
40  $this->faker->addProvider(new LocalImage($this->faker));
41  }
42 
47  abstract function seed();
48 
53  abstract function unseed();
54 
59  public function getDomain() {
60  return elgg_get_site_entity()->getDomain();
61  }
62 
67  public function createUser(array $attributes = [], array $metadata = []) {
68 
69  $metadata['__faker'] = true;
70 
71  if (empty($attributes['password'])) {
73  }
74 
75  if (empty($attributes['username'])) {
76  $attributes['name'] = $this->faker->name;
77  }
78 
79  if (empty($attributes['username'])) {
80  $attributes['username'] = $this->getRandomUsername($attributes['name']);
81  }
82 
83  if (empty($attributes['email'])) {
84  $attributes['email'] = "{$attributes['username']}@{$this->getDomain()}";
85  if (!filter_var($attributes['email'], FILTER_VALIDATE_EMAIL)) {
86  // Travis tests use localhost as the domain name, which generates invalid email addresses
87  $attributes['email'] = "{$attributes['username']}@localhost.com";
88  }
89  }
90 
91  $user = false;
92 
93  try {
94  $guid = register_user($attributes['username'], $attributes['password'], $attributes['name'], $attributes['email']);
96  /* @var $user ElggUser */
97 
98  elgg_set_user_validation_status($guid, $this->faker->boolean(), 'seeder');
99 
100  $user->setNotificationSetting('email', false);
101  $user->setNotificationSetting('site', true);
102 
103  $profile_fields = elgg_get_config('profile_fields');
104 
106 
107  $user->save();
108 
109  $this->createIcon($user);
110  $this->createComments($user);
111  $this->createLikes($user);
112 
113  $this->log("Created new user $user->name [guid: $user->guid]");
114 
115  return $user;
116  } catch (Exception $e) {
117  if ($user && $user->guid) {
118  $user->delete();
119  }
120 
121  $this->log($e->getMessage());
122 
123  return false;
124  }
125 
126  }
127 
132  public function createGroup(array $attributes = [], array $metadata = []) {
133 
134  $metadata['__faker'] = true;
135 
136  if (empty($attributes['access_id'])) {
137  $attributes['access_id'] = ACCESS_PUBLIC;
138  }
139 
140  if (empty($metadata['content_access_mode'])) {
142  }
143 
144  if (empty($metadata['membership'])) {
145  $metadata['membership'] = ACCESS_PUBLIC;
146  }
147 
148  if (empty($attributes['name'])) {
149  $attributes['name'] = $this->faker->sentence();
150  }
151 
152  if (empty($attributes['description'])) {
153  $attributes['description'] = $this->faker->text($this->faker->numberBetween(500, 1000));
154  }
155 
156  if (empty($attributes['owner_guid'])) {
157  $user = $this->getRandomUser();
158  if (!$user) {
159  $user = $this->createUser();
160  }
161 
162  $attributes['owner_guid'] = $user->guid;
163  }
164 
165  if (empty($attributes['container_guid'])) {
166  $attributes['container_guid'] = $attributes['owner_guid'];
167  }
168 
169  $owner = get_entity($attributes['owner_guid']);
170  if (!$owner) {
171  return false;
172  }
173 
174  $container = get_entity($attributes['container_guid']);
175  if (!$container) {
176  return false;
177  }
178 
179  $tool_options = elgg_get_config('group_tool_options');
180  if ($tool_options) {
181  foreach ($tool_options as $group_option) {
182  $option_toggle_name = $group_option->name . "_enable";
183  $option_default = $group_option->default_on ? 'yes' : 'no';
184  $metadata[$option_toggle_name] = $option_default;
185  }
186  }
187 
188  if ($this->faker->boolean(20)) {
189  $metadata['featured_group'] = 'yes';
190  }
191 
192  $group = false;
193 
194  try {
195 
196  $group = new ElggGroup();
197  foreach ($attributes as $name => $value) {
198  $group->$name = $value;
199  }
200 
201  $group = $this->populateMetadata($group, elgg_get_config('group'), $metadata);
202 
203  $group->save();
204 
205  if ($group->access_id == ACCESS_PRIVATE) {
206  $group->access_id = $group->group_acl;
207  $group->save();
208  }
209 
210  $group->join(get_entity($attributes['owner_guid']));
211 
212  $this->createIcon($group);
213 
214  $this->createComments($group);
215  $this->createLikes($group);
216 
218  'view' => 'river/group/create',
219  'action_type' => 'create',
220  'subject_guid' => $owner->guid,
221  'object_guid' => $group->guid,
222  'target_guid' => $container->guid,
223  ]);
224 
225  $this->log("Created new group $group->name [guid: $group->guid]");
226 
227  return $group;
228  } catch (Exception $e) {
229  if ($group && $group->guid) {
230  $group->delete();
231  }
232 
233  $this->log($e->getMessage());
234 
235  return false;
236  }
237 
238  }
239 
244  public function createObject(array $attributes = [], array $metadata = []) {
245 
246  $metadata['__faker'] = true;
247 
248  if (empty($attributes['title'])) {
249  $attributes['title'] = $this->faker->sentence();
250  }
251 
252  if (empty($attributes['description'])) {
253  $attributes['description'] = $this->faker->text($this->faker->numberBetween(500, 1000));
254  }
255 
256  if (empty($attributes['container_guid'])) {
257  if ($this->faker->boolean()) {
258  $container = $this->getRandomGroup();
259  } else {
260  $container = $this->getRandomUser();
261  }
262 
263  $attributes['container_guid'] = $container->guid;
264  }
265 
266  if (empty($attributes['subtype'])) {
267  $attributes['subtype'] = strtolower($this->faker->word);
268  }
269 
270  if (empty($metadata['tags'])) {
271  $metadata['tags'] = $this->faker->words(10);
272  }
273 
274  if (empty($attributes['owner_guid'])) {
275  if ($container instanceof ElggGroup) {
277  'types' => 'user',
278  'relationship' => 'member',
279  'relationship_guid' => $container->guid,
280  'inverse_relationship' => true,
281  'limit' => 0,
282  'metadata_names' => '__faker',
283  'order_by' => 'RAND()',
284  ]);
285  $owner = array_shift($members);
286  } else {
287  $owner = $container;
288  }
289 
290  $attributes['owner_guid'] = $owner->guid;
291  }
292 
293  $owner = get_entity($attributes['owner_guid']);
294  if (!$owner) {
295  return false;
296  }
297 
298  $container = get_entity($attributes['container_guid']);
299  if (!$container) {
300  return false;
301  }
302 
303  if (empty($attributes['access_id'])) {
304  $attributes['access_id'] = $this->getRandomAccessId($owner, $container);
305  }
306 
307  $object = false;
308 
309  try {
310  $class = get_subtype_class('object', $attributes['subtype']);
311  if ($class && class_exists($class)) {
312  $object = new $class();
313  } else {
314  $object = new ElggObject();
315  }
316  foreach ($attributes as $name => $value) {
317  $object->$name = $value;
318  }
319 
320  $object = $this->populateMetadata($object, [], $metadata);
321 
322  $object->save();
323 
324  $this->createComments($object);
325  $this->createLikes($object);
326 
327  $type_str = elgg_echo("item:object:{$object->getSubtype()}");
328 
329  $this->log("Created new item in $type_str $object->title [guid: $object->guid]");
330 
331  return $object;
332  } catch (Exception $e) {
333  if ($object && $object->guid) {
334  $object->delete();
335  }
336 
337  $this->log($e->getMessage());
338 
339  return false;
340  }
341 
342  }
343 
351  public function getRandomUser(array $exclude = []) {
352 
353  $exclude[] = 0;
354  $exclude_in = implode(',', array_map(function ($e) {
355  return (int) $e;
356  }, $exclude));
357 
359  'types' => 'user',
360  'metadata_names' => ['__faker'],
361  'limit' => 1,
362  'wheres' => [
363  "e.guid NOT IN ($exclude_in)",
364  ],
365  'order_by' => 'RAND()',
366  ]);
367 
368  return $users ? $users[0] : false;
369  }
370 
378  public function getRandomGroup(array $exclude = []) {
379 
380  $exclude[] = 0;
381  $exclude_in = implode(',', array_map(function ($e) {
382  return (int) $e;
383  }, $exclude));
384 
386  'types' => 'group',
387  'metadata_names' => ['__faker'],
388  'limit' => 1,
389  'wheres' => [
390  "e.guid NOT IN ($exclude_in)",
391  ],
392  'order_by' => 'RAND()',
393  ]);
394 
395  return $groups ? $groups[0] : false;
396  }
397 
406  public function getRandomAccessId(\ElggUser $user = null, ElggEntity $container = null) {
407 
408  $params = [
409  'container_guid' => $container->guid,
410  ];
411 
412  $access_array = get_write_access_array($user->guid, null, null, $params);
413 
414  $access_key = array_rand($access_array, 1);
415 
416  return $access_array[$access_key];
417  }
418 
426  public function getRandomUsername($base_name = 'user') {
427 
428  $available = false;
429 
430  $base_name = iconv('UTF-8', 'ASCII//TRANSLIT', $base_name);
431  $blacklist = '/[\x{0080}-\x{009f}\x{00a0}\x{2000}-\x{200f}\x{2028}-\x{202f}\x{3000}\x{e000}-\x{f8ff}]/u';
432  $blacklist2 = [
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  '+',
461  '='
462  ];
463 
464  $base_name = preg_replace($blacklist, '', $base_name);
465  $base_name = str_replace($blacklist2, '.', $base_name);
466 
467  $ia = elgg_set_ignore_access(true);
468 
471 
472  $minlength = elgg_get_config('minusername') ? : 4;
473  if ($base_name) {
474  $fill = $minlength - strlen($base_name);
475  } else {
476  $fill = 8;
477  }
478 
479  $separator = '.';
480 
481  if ($fill > 0) {
482  $suffix = (new ElggCrypto())->getRandomString($fill);
483  $base_name = "$base_name$separator$suffix";
484  }
485 
486  $iterator = 0;
487  while (!$available) {
488  if ($iterator > 0) {
489  $base_name = "$base_name$separator$iterator";
490  }
491  $user = get_user_by_username($base_name);
492  $available = !$user;
493  try {
494  if ($available) {
495  validate_username($base_name);
496  }
497  } catch (\Exception $e) {
498  if ($iterator >= 10) {
499  // too many failed attempts
500  $base_name = (new ElggCrypto())->getRandomString(8);
501  }
502  }
503 
504  $iterator++;
505  }
506 
509 
510  return strtolower($base_name);
511  }
512 
522  public function populateMetadata(ElggEntity $entity, array $fields = [], array $metadata = []) {
523 
524  foreach ($fields as $name => $type) {
525  if (isset($metadata[$name])) {
526  continue;
527  }
528 
529  switch ($name) {
530  case 'phone' :
531  case 'mobile' :
532  $metadata[$name] = $this->faker->phoneNumber;
533  break;
534 
535  default :
536  switch ($type) {
537  case 'plaintext' :
538  case 'longtext' :
539  $metadata[$name] = $this->faker->text($this->faker->numberBetween(500, 1000));
540  break;
541 
542  case 'text' :
543  $metadata[$name] = $this->faker->sentence;
544  break;
545 
546  case 'tags' :
547  $metadata[$name] = $this->faker->words(10);
548  break;
549 
550  case 'url' :
551  $metadata[$name] = $this->faker->url;
552  break;
553 
554  case 'email' :
555  $metadata[$name] = $this->faker->email;
556  break;
557 
558  case 'number' :
559  $metadata[$name] = $this->faker->randomNumber();
560  break;
561 
562  case 'date' :
563  $metadata[$name] = $this->faker->unixTime;
564  break;
565 
566  case 'password' :
568  break;
569 
570  case 'location' :
571  $metadata[$name] = $this->faker->address;
572  $metadata['geo:lat'] = $this->faker->latitude;
573  $metadata['geo:long'] = $this->faker->longitude;
574  break;
575 
576  default :
577  $metadata[$name] = '';
578  break;
579  }
580 
581  break;
582  }
583  }
584 
585  foreach ($metadata as $key => $value) {
586  $entity->$key = $value;
587  }
588 
589  return $entity;
590  }
591 
599  public function createIcon(ElggEntity $entity) {
600 
601  $icon_location = $this->faker->image();
602  if (empty($icon_location)) {
603  return false;
604  }
605 
606  $result = $entity->saveIconFromLocalFile($icon_location);
607 
608  if ($result && $entity instanceof ElggUser) {
610  'view' => 'river/user/default/profileiconupdate',
611  'action_type' => 'update',
612  'subject_guid' => $entity->guid,
613  'object_guid' => $entity->guid,
614  ]);
615  }
616 
617  return $result;
618  }
619 
628  public function createComments(ElggEntity $entity, $limit = null) {
629 
630  $success = 0;
631 
632  if (!$limit) {
633  $limit = $this->faker->numberBetween(1, 20);
634  }
635 
636  while ($success < $limit) {
637 
638  $comment = new ElggObject();
639  $comment->subtype = $entity->getSubtype() == 'discussion' ? 'discussion_reply' : 'comment';
640  $comment->owner_guid = $this->getRandomUser()->guid ? : $entity->owner_guid;
641  $comment->container_guid = $entity->guid;
642  $comment->description = $this->faker->paragraph;
643 
644  if ($comment->save()) {
645  $success++;
646  }
647  }
648 
649  return $success;
650 
651  }
652 
661  public function createLikes(ElggEntity $entity, $limit = null) {
662 
663  $success = 0;
664 
665  if (!$limit) {
666  $limit = $this->faker->numberBetween(1, 20);
667  }
668 
669  while ($success < $limit) {
670  if ($entity->annotate('likes', true, $entity->access_id, $this->getRandomUser()->guid)) {
671  $success++;
672  }
673  }
674 
675  return $success;
676  }
677 
685  public function log($msg, $level = 'NOTICE') {
686 
687  if (php_sapi_name() === 'cli') {
688  $handle = $level === 'ERROR' ? STDERR : STDOUT;
689  fwrite($handle, $msg . PHP_EOL);
690  } else {
691  elgg_log($msg, $level);
692  }
693  }
694 }
Provide images from a local folder for seeding.
Definition: LocalImage.php:10
$object
These two snippets demonstrates triggering an event and how to register for that event.
Definition: trigger.php:7
elgg_get_config($name, $site_guid=0)
Get an Elgg configuration value.
createIcon(ElggEntity $entity)
Create an icon for an entity.
Definition: Seed.php:599
elgg_get_site_entity($site_guid=0)
Get an entity (default is current site)
Definition: sites.php:18
getSubtype()
Get the entity subtype.
elgg_get_entities_from_metadata(array $options=array())
interfaces
Definition: metadata.php:276
getRandomGroup(array $exclude=[])
Returns random fake group.
Definition: Seed.php:378
if($guid==elgg_get_logged_in_user_guid()) $name
Definition: delete.php:21
elgg_echo($message_key, $args=array(), $language="")
Given a message key, returns an appropriately translated full-text string.
Definition: languages.php:21
$fields
Definition: register.php:26
getRandomUser(array $exclude=[])
Returns random fake user.
Definition: Seed.php:351
$e
Definition: metadata.php:12
$members
getRandomUsername($base_name= 'user')
Generates a unique available and valid username.
Definition: Seed.php:426
$metadata
Definition: entity.php:19
$value
Definition: longtext.php:42
$class
Definition: field.php:20
validate_username($username)
Simple function which ensures that a username contains only valid characters.
Definition: users.php:205
$guid
Removes an admin notice.
saveIconFromLocalFile($filename, $type= 'icon', array $coords=array())
Saves icons using a local file as the source.
createLikes(ElggEntity $entity, $limit=null)
Create likes.
Definition: Seed.php:661
populateMetadata(ElggEntity $entity, array $fields=[], array $metadata=[])
Set random metadata.
Definition: Seed.php:522
register_user($username, $password, $name, $email, $allow_multiple_emails=false)
Registers a user, returning false if the username already exists.
Definition: users.php:316
$comment
Definition: delete.php:10
get_user_by_username($username)
Get user by username.
Definition: users.php:98
createComments(ElggEntity $entity, $limit=null)
Create comments/replies.
Definition: Seed.php:628
createGroup(array $attributes=[], array $metadata=[])
Create a new faker group.
Definition: Seed.php:132
$params
Definition: login.php:72
get_subtype_class($type, $subtype)
Return the class name for a registered type and subtype.
Definition: entities.php:57
log($msg, $level= 'NOTICE')
Log a message.
Definition: Seed.php:685
getRandomAccessId(\ElggUser $user=null, ElggEntity $container=null)
Get random access id.
Definition: Seed.php:406
annotate($name, $value, $access_id=ACCESS_PRIVATE, $owner_guid=0, $vartype="")
Adds an annotation to an entity.
Definition: ElggEntity.php:834
$suffix
Definition: excerpt.php:13
elgg_create_river_item(array $options=array())
Adds an item to the river.
Definition: river.php:39
$owner
Definition: crop.php:8
$key
Definition: summary.php:34
$container
Definition: delete.php:29
elgg_set_ignore_access($ignore=true)
Set if Elgg&#39;s access system should be ignored.
Definition: access.php:43
const CONTENT_ACCESS_MODE_UNRESTRICTED
Definition: ElggGroup.php:15
if(!is_array($accesslevel)) $profile_fields
Definition: edit.php:26
get_write_access_array($user_guid=0, $site_guid=0, $flush=false, array $input_params=array())
Returns an array of access permissions that the user is allowed to save content with.
Definition: access.php:267
$users
Definition: newest.php:8
$user
Definition: ban.php:13
const ACCESS_PRIVATE
Definition: elgglib.php:2082
elgg ElggUser
Definition: ElggUser.js:12
access_get_show_hidden_status()
Return current status of showing disabled entities.
Definition: access.php:170
elgg_log($message, $level= 'NOTICE')
Display or log a message.
Definition: elgglib.php:1028
seed()
Populate database.
const ACCESS_PUBLIC
Definition: elgglib.php:2084
access_show_hidden_entities($show_hidden)
Show or hide disabled entities.
Definition: access.php:158
__construct($locale= 'en_US')
Seed constructor.
Definition: Seed.php:37
$entity
Definition: delete.php:7
Abstract seed.
Definition: Seed.php:20
generate_random_cleartext_password()
Generate a random 12 character clear text password.
Definition: users.php:189
elgg_get_entities_from_relationship($options)
Return entities matching a given query joining against a relationship.
unseed()
Removed seeded rows from database.
elgg_set_user_validation_status($user_guid, $status, $method= '')
Set the validation status for a user.
Definition: users.php:355
createUser(array $attributes=[], array $metadata=[])
Create a new faker user.
Definition: Seed.php:67
$attributes
Definition: ajax_loader.php:13
elgg ElggEntity
Definition: ElggEntity.js:16
http free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:5
createObject(array $attributes=[], array $metadata=[])
Create a new faker object.
Definition: Seed.php:244
getDomain()
Get site domain.
Definition: Seed.php:59
get_entity($guid)
Loads and returns an entity object from a guid.
Definition: entities.php:204
if(!$display_name) $type
Definition: delete.php:27