From 5eac377d9c2afaa52217c7439c8db15cfb90e22f Mon Sep 17 00:00:00 2001 From: andrewbelcher Date: Tue, 7 Mar 2017 14:21:28 -0500 Subject: [PATCH 1/4] by andrewbelcher: Move towards better quality and quantity for demo content. --- modules/contacts_demo/contacts_demo.info.yml | 11 - .../03d148c4-8cde-4ea4-a924-bccd35a68376.json | 79 ----- .../66ac6619-17e5-41c8-9c25-0bcb57889646.json | 79 ----- .../852ed573-0163-4c2f-9264-eb54f57e0c4d.json | 119 -------- .../c9e213d2-4a7a-40f4-be4b-fe03a06141b7.json | 106 ------- .../096d7ac0-1358-4677-ad71-c05193ccf279.json | 48 --- .../16673f6a-3196-4072-845d-5751e8be98e6.json | 48 --- .../contacts_demo/src/CrmGeneratorBase.php | 282 ++++++++++++++++++ .../Plugin/DevelGenerate/CrmIndivGenerate.php | 145 +++++++++ modules/contacts_demo/src/RandomUser.php | 127 ++++++++ 10 files changed, 554 insertions(+), 490 deletions(-) delete mode 100644 modules/contacts_demo/content/profile/03d148c4-8cde-4ea4-a924-bccd35a68376.json delete mode 100644 modules/contacts_demo/content/profile/66ac6619-17e5-41c8-9c25-0bcb57889646.json delete mode 100644 modules/contacts_demo/content/profile/852ed573-0163-4c2f-9264-eb54f57e0c4d.json delete mode 100644 modules/contacts_demo/content/profile/c9e213d2-4a7a-40f4-be4b-fe03a06141b7.json delete mode 100644 modules/contacts_demo/content/user/096d7ac0-1358-4677-ad71-c05193ccf279.json delete mode 100644 modules/contacts_demo/content/user/16673f6a-3196-4072-845d-5751e8be98e6.json create mode 100644 modules/contacts_demo/src/CrmGeneratorBase.php create mode 100644 modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php create mode 100644 modules/contacts_demo/src/RandomUser.php diff --git a/modules/contacts_demo/contacts_demo.info.yml b/modules/contacts_demo/contacts_demo.info.yml index 07d1a2c..1fcaabd 100644 --- a/modules/contacts_demo/contacts_demo.info.yml +++ b/modules/contacts_demo/contacts_demo.info.yml @@ -6,14 +6,3 @@ core: '8.x' dependencies: - contacts - - default_content - -default_content: - user: - - 16673f6a-3196-4072-845d-5751e8be98e6 - - 096d7ac0-1358-4677-ad71-c05193ccf279 - profile: - - 852ed573-0163-4c2f-9264-eb54f57e0c4d - - c9e213d2-4a7a-40f4-be4b-fe03a06141b7 - - 03d148c4-8cde-4ea4-a924-bccd35a68376 - - 66ac6619-17e5-41c8-9c25-0bcb57889646 diff --git a/modules/contacts_demo/content/profile/03d148c4-8cde-4ea4-a924-bccd35a68376.json b/modules/contacts_demo/content/profile/03d148c4-8cde-4ea4-a924-bccd35a68376.json deleted file mode 100644 index fd560fa..0000000 --- a/modules/contacts_demo/content/profile/03d148c4-8cde-4ea4-a924-bccd35a68376.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "_links": { - "self": { - "href": "http:\/\/default\/profile\/3?_format=hal_json" - }, - "type": { - "href": "http:\/\/drupal.org\/rest\/type\/profile\/crm_notes" - }, - "http:\/\/drupal.org\/rest\/relation\/profile\/crm_notes\/uid": [ - { - "href": "http:\/\/default\/user\/3?_format=hal_json" - } - ] - }, - "profile_id": [ - { - "value": "3" - } - ], - "uuid": [ - { - "value": "03d148c4-8cde-4ea4-a924-bccd35a68376" - } - ], - "revision_id": [ - { - "value": "3" - } - ], - "langcode": [ - { - "value": "en" - } - ], - "type": [ - { - "target_id": "crm_notes" - } - ], - "_embedded": { - "http:\/\/drupal.org\/rest\/relation\/profile\/crm_notes\/uid": [ - { - "_links": { - "self": { - "href": "http:\/\/default\/user\/3?_format=hal_json" - }, - "type": { - "href": "http:\/\/drupal.org\/rest\/type\/user\/user" - } - }, - "uuid": [ - { - "value": "16673f6a-3196-4072-845d-5751e8be98e6" - } - ] - } - ] - }, - "status": [ - { - "value": "1" - } - ], - "is_default": [ - { - "value": "1" - } - ], - "created": [ - { - "value": "1482155816" - } - ], - "changed": [ - { - "value": "1482155816" - } - ] -} \ No newline at end of file diff --git a/modules/contacts_demo/content/profile/66ac6619-17e5-41c8-9c25-0bcb57889646.json b/modules/contacts_demo/content/profile/66ac6619-17e5-41c8-9c25-0bcb57889646.json deleted file mode 100644 index 2b611de..0000000 --- a/modules/contacts_demo/content/profile/66ac6619-17e5-41c8-9c25-0bcb57889646.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "_links": { - "self": { - "href": "http:\/\/default\/profile\/4?_format=hal_json" - }, - "type": { - "href": "http:\/\/drupal.org\/rest\/type\/profile\/crm_notes" - }, - "http:\/\/drupal.org\/rest\/relation\/profile\/crm_notes\/uid": [ - { - "href": "http:\/\/default\/user\/2?_format=hal_json" - } - ] - }, - "profile_id": [ - { - "value": "4" - } - ], - "uuid": [ - { - "value": "66ac6619-17e5-41c8-9c25-0bcb57889646" - } - ], - "revision_id": [ - { - "value": "4" - } - ], - "langcode": [ - { - "value": "en" - } - ], - "type": [ - { - "target_id": "crm_notes" - } - ], - "_embedded": { - "http:\/\/drupal.org\/rest\/relation\/profile\/crm_notes\/uid": [ - { - "_links": { - "self": { - "href": "http:\/\/default\/user\/2?_format=hal_json" - }, - "type": { - "href": "http:\/\/drupal.org\/rest\/type\/user\/user" - } - }, - "uuid": [ - { - "value": "096d7ac0-1358-4677-ad71-c05193ccf279" - } - ] - } - ] - }, - "status": [ - { - "value": "1" - } - ], - "is_default": [ - { - "value": "1" - } - ], - "created": [ - { - "value": "1482155824" - } - ], - "changed": [ - { - "value": "1482155824" - } - ] -} \ No newline at end of file diff --git a/modules/contacts_demo/content/profile/852ed573-0163-4c2f-9264-eb54f57e0c4d.json b/modules/contacts_demo/content/profile/852ed573-0163-4c2f-9264-eb54f57e0c4d.json deleted file mode 100644 index 19a1fc0..0000000 --- a/modules/contacts_demo/content/profile/852ed573-0163-4c2f-9264-eb54f57e0c4d.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "_links": { - "self": { - "href": "http:\/\/default\/profile\/1?_format=hal_json" - }, - "type": { - "href": "http:\/\/drupal.org\/rest\/type\/profile\/crm_indiv" - }, - "http:\/\/drupal.org\/rest\/relation\/profile\/crm_indiv\/uid": [ - { - "href": "http:\/\/default\/user\/2?_format=hal_json" - } - ] - }, - "profile_id": [ - { - "value": "1" - } - ], - "uuid": [ - { - "value": "852ed573-0163-4c2f-9264-eb54f57e0c4d" - } - ], - "revision_id": [ - { - "value": "1" - } - ], - "langcode": [ - { - "value": "en" - } - ], - "type": [ - { - "target_id": "crm_indiv" - } - ], - "_embedded": { - "http:\/\/drupal.org\/rest\/relation\/profile\/crm_indiv\/uid": [ - { - "_links": { - "self": { - "href": "http:\/\/default\/user\/2?_format=hal_json" - }, - "type": { - "href": "http:\/\/drupal.org\/rest\/type\/user\/user" - } - }, - "uuid": [ - { - "value": "096d7ac0-1358-4677-ad71-c05193ccf279" - } - ] - } - ] - }, - "status": [ - { - "value": "1" - } - ], - "is_default": [ - { - "value": "1" - } - ], - "created": [ - { - "value": "1482153603" - } - ], - "changed": [ - { - "value": "1482153603" - } - ], - "crm_address": [ - { - "langcode": null, - "country_code": "GB", - "administrative_area": null, - "locality": "London", - "dependent_locality": null, - "postal_code": "W12 7JT", - "sorting_code": null, - "address_line1": "1 Oxford Street", - "address_line2": "", - "organization": "", - "given_name": "", - "additional_name": null, - "family_name": "", - "lang": "en" - } - ], - "crm_dob": [ - { - "value": "1985-01-01" - } - ], - "crm_email": [ - { - "value": "indiv@test.com", - "lang": "en" - } - ], - "crm_gender": [ - { - "value": "male" - } - ], - "crm_name": [ - { - "value": "Individual Contact", - "lang": "en" - } - ] -} \ No newline at end of file diff --git a/modules/contacts_demo/content/profile/c9e213d2-4a7a-40f4-be4b-fe03a06141b7.json b/modules/contacts_demo/content/profile/c9e213d2-4a7a-40f4-be4b-fe03a06141b7.json deleted file mode 100644 index b0bbf2b..0000000 --- a/modules/contacts_demo/content/profile/c9e213d2-4a7a-40f4-be4b-fe03a06141b7.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "_links": { - "self": { - "href": "http:\/\/default\/profile\/2?_format=hal_json" - }, - "type": { - "href": "http:\/\/drupal.org\/rest\/type\/profile\/crm_org" - }, - "http:\/\/drupal.org\/rest\/relation\/profile\/crm_org\/uid": [ - { - "href": "http:\/\/default\/user\/3?_format=hal_json" - } - ] - }, - "profile_id": [ - { - "value": "2" - } - ], - "uuid": [ - { - "value": "c9e213d2-4a7a-40f4-be4b-fe03a06141b7" - } - ], - "revision_id": [ - { - "value": "2" - } - ], - "langcode": [ - { - "value": "en" - } - ], - "type": [ - { - "target_id": "crm_org" - } - ], - "_embedded": { - "http:\/\/drupal.org\/rest\/relation\/profile\/crm_org\/uid": [ - { - "_links": { - "self": { - "href": "http:\/\/default\/user\/3?_format=hal_json" - }, - "type": { - "href": "http:\/\/drupal.org\/rest\/type\/user\/user" - } - }, - "uuid": [ - { - "value": "16673f6a-3196-4072-845d-5751e8be98e6" - } - ] - } - ] - }, - "status": [ - { - "value": "1" - } - ], - "is_default": [ - { - "value": "1" - } - ], - "created": [ - { - "value": "1482153768" - } - ], - "changed": [ - { - "value": "1482153768" - } - ], - "crm_org_address": [ - { - "langcode": null, - "country_code": "GB", - "administrative_area": null, - "locality": "Manchester", - "dependent_locality": null, - "postal_code": "M14 4WP", - "sorting_code": null, - "address_line1": "1442 Brooke Street", - "address_line2": "", - "organization": "", - "given_name": "", - "additional_name": null, - "family_name": "" - } - ], - "crm_org_email": [ - { - "value": "org@test.com" - } - ], - "crm_org_name": [ - { - "value": "Organisation" - } - ] -} \ No newline at end of file diff --git a/modules/contacts_demo/content/user/096d7ac0-1358-4677-ad71-c05193ccf279.json b/modules/contacts_demo/content/user/096d7ac0-1358-4677-ad71-c05193ccf279.json deleted file mode 100644 index 237bae1..0000000 --- a/modules/contacts_demo/content/user/096d7ac0-1358-4677-ad71-c05193ccf279.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "_links": { - "self": { - "href": "http:\/\/default\/user\/2?_format=hal_json" - }, - "type": { - "href": "http:\/\/drupal.org\/rest\/type\/user\/user" - } - }, - "uid": [ - { - "value": "2" - } - ], - "uuid": [ - { - "value": "096d7ac0-1358-4677-ad71-c05193ccf279" - } - ], - "langcode": [ - { - "value": "en", - "lang": "en" - } - ], - "created": [ - { - "value": "1482153603" - } - ], - "changed": [ - { - "value": "1482153659", - "lang": "en" - } - ], - "roles": [ - { - "target_id": "crm_indiv" - } - ], - "default_langcode": [ - { - "value": "1", - "lang": "en" - } - ] -} \ No newline at end of file diff --git a/modules/contacts_demo/content/user/16673f6a-3196-4072-845d-5751e8be98e6.json b/modules/contacts_demo/content/user/16673f6a-3196-4072-845d-5751e8be98e6.json deleted file mode 100644 index fa55c1f..0000000 --- a/modules/contacts_demo/content/user/16673f6a-3196-4072-845d-5751e8be98e6.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "_links": { - "self": { - "href": "http:\/\/default\/user\/3?_format=hal_json" - }, - "type": { - "href": "http:\/\/drupal.org\/rest\/type\/user\/user" - } - }, - "uid": [ - { - "value": "3" - } - ], - "uuid": [ - { - "value": "16673f6a-3196-4072-845d-5751e8be98e6" - } - ], - "langcode": [ - { - "value": "en", - "lang": "en" - } - ], - "created": [ - { - "value": "1482153698" - } - ], - "changed": [ - { - "value": "1482153768", - "lang": "en" - } - ], - "roles": [ - { - "target_id": "crm_org" - } - ], - "default_langcode": [ - { - "value": "1", - "lang": "en" - } - ] -} \ No newline at end of file diff --git a/modules/contacts_demo/src/CrmGeneratorBase.php b/modules/contacts_demo/src/CrmGeneratorBase.php new file mode 100644 index 0000000..6c8feff --- /dev/null +++ b/modules/contacts_demo/src/CrmGeneratorBase.php @@ -0,0 +1,282 @@ +httpClientFactory = $http_client_factory; + $this->userStorage = $user_storage; + $this->profileStorage = $profile_storage; + + if (empty(static::ROLE_NAME)) { + throw new \Exception(strtr('Role name not defined for @class', [ + '@class' => __CLASS__, + ])); + } + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + $entity_type_manager = $container->get('entity_type.manager'); + return new static( + $configuration, $plugin_id, $plugin_definition, + $container->get('http_client_factory'), + $entity_type_manager->getStorage('user'), + $entity_type_manager->getStorage('profile') + ); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $roles = user_role_names(TRUE); + + $form['num'] = array( + '#type' => 'number', + '#title' => $this->t('How many contacts would you like to generate?'), + '#default_value' => $this->getSetting('num'), + '#required' => TRUE, + '#min' => 0, + ); + + $form['delete'] = array( + '#type' => 'checkbox', + '#title' => $this->t('Delete all @type contacts (except user id 1) before generating new users.', [ + '@type' => $roles[static::ROLE_NAME], + ]), + '#default_value' => $this->getSetting('delete'), + ); + + $options = $roles; + unset($options[AccountInterface::AUTHENTICATED_ROLE]); + unset($options['crm_indiv']); + unset($options['crm_org']); + $form['roles'] = array( + '#type' => 'checkboxes', + '#title' => $this->t('Which roles should the users receive?'), + '#description' => $this->t('Users always receive the authenticated user roles.'), + '#options' => $options, + ); + + return $form; + } + + /** + * {@inheritdoc} + */ + protected function generateElements(array $values) { + $num = $values['num']; + $delete = $values['delete']; + $options = [ + 'roles' => array_filter($values['roles']), + ]; + $options['roles'][] = static::ROLE_NAME; + + if ($delete) { + $this->deleteContacts(static::ROLE_NAME); + } + + if ($num > 0) { + $this->generateContacts($num, $options); + } + + $this->setMessage($this->t('@num created.', array('@num' => $this->formatPlural($num, '1 contact', '@count contacts')))); + } + + /** + * Delete contacts of a given role. + * + * @param string $role + * The role to delete users for. + */ + public function deleteContacts($role) { + $uids = $this->userStorage->getQuery() + ->condition('uid', 1, '>') + ->condition('roles', $role) + ->execute(); + $users = $this->userStorage->loadMultiple($uids); + $this->userStorage->delete($users); + + $this->setMessage($this->formatPlural(count($uids), '1 contact deleted', '@count contacts deleted.')); + } + + /** + * Generate a specified number of individuals based on the given options. + * + * @param int $number + * The number of contacts to create. + * @param array $options + * Options for the generation. + */ + abstract public function generateContacts($number = 1, array $options = array()); + + /** + * Create the user for the result row. + * + * @param \stdClass $result + * The result row to generate for. + * @param array $options + * The options for the generation. + * + * @return \Drupal\user\UserInterface + * The generated user. + */ + protected function createUser(\stdClass $result, array $options = array()) { + $options += [ + 'coupled' => 2, + 'roles' => [], + ]; + $options['roles'][] = static::ROLE_NAME; + $options['roles'] = array_filter($options['roles']); + + // Generate some reasonable timestamps. + $created = strtotime($result->registered); + $login = $created + rand(0, time() - $created); + $access = $login + rand(0, 86400); + $changed = $access + rand(0, time() - $access); + + $user_values = [ + 'mail' => $result->email, + 'status' => 1, + 'created' => $created, + 'changed' => $changed, + 'roles' => $options['roles'], + ]; + + // If we're doing a coupled user, add the additional info. + if ($this->getRandomDecision($options['coupled'])) { + $user_values += [ + 'name' => $result->login->username, + 'pass' => $result->login->password, + 'access' => $access, + 'login' => $login, + ]; + } + + /* @var \Drupal\user\UserInterface $user */ + $user = $this->userStorage->create($user_values); + $user->save(); + return $user; + } + + protected function createProfile($type, array $values, UserInterface $user) { + $values['type'] = $type; + $values['uid'] = $user->id(); + $values += [ + 'status' => 1, + 'is_default' => 1, + 'created' => $user->getCreatedTime(), + 'changed' => $user->getChangedTime(), + ]; + + /* @var \Drupal\profile\Entity\ProfileInterface $profile */ + $profile = $this->profileStorage->create($values); + $profile->save(); + return $profile; + } + + /** + * Make a randomized decision with a given likelihood. + * + * @param bool|int $option + * Either a boolean indicating we should always return the same answer, or + * in integer indicating the likelihood (e.g. 1 in $option will be TRUE). + * Negative numbers reverse the result (e.g. 1 in $option will be FALSE). + * + * @return bool + * The random answer. + * + * @throws \Exception + * Thrown if the option is invalid. + */ + protected function getRandomDecision($option) { + // Check option is valid. + if (!is_bool($option) && (!is_int($option) || $option === 0)) { + throw new \Exception(strtr('Invalid argument "@option" for @method.', [ + '@option' => $option, + '@method' => __METHOD__, + ])); + } + + // If it's a boolean, we simply return it. + if (is_bool($option)) { + return $option; + } + + // Otherwise, generate a random number between 0 and it - 1. + $rand = rand(0, abs($option - 1)); + + // If our original option was positive, we want to return whether it's zero. + // Otherwise return if it's non zero. + return $rand === 0 xor $option < 0; + } + + /** + * {@inheritdoc} + */ + public function validateDrushParams($args) { + $values = array( + 'num' => array_shift($args), + 'roles' => drush_get_option('roles') ? explode(',', drush_get_option('roles')) : array(), + 'delete' => drush_get_option('delete'), + ); + return $values; + } + +} diff --git a/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php new file mode 100644 index 0000000..8afa095 --- /dev/null +++ b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php @@ -0,0 +1,145 @@ + $this->t('Individuals are generated using data provided by randomuser.me.', [ + ':url' => 'https://randomuser.me', + ]), + ); + + return $form; + } + + /** + * {@inheritdoc} + */ + public function generateContacts($number = 1, array $options = array()) { + // Set some default options. + $options += [ + 'api' => [ + 'nat' => 'gb', + ] + ]; + + // Enforce a couple API options. + $options['api']['results'] = $number; + $options['api'][] = 'noinfo'; + + // Retrieve our results. + $results = $this->httpClientFactory->fromOptions()->request('GET', 'https://randomuser.me/api', [ + 'query' => $options['api'], + ]); + $results = json_decode($results); + + // Loop over and create the users and associated entities. + foreach ($results->results as $result) { + $user = $this->createUser($result, $options); + $this->createProfileIndiv($result, $user, $options); + $this->createProfileNotes($result, $user, $options); + } + } + + /** + * Create the individual profile for the result row. + * + * @param \stdClass $result + * The result row to generate for. + * @param \Drupal\user\UserInterface $user + * The user account to attach the profile to. + * @param array $options + * The options for the generation. + * + * @return \Drupal\profile\Entity\ProfileInterface + * The generated profile. + */ + protected function createProfileIndiv(\stdClass $result, UserInterface $user, $options = array()) { + $options += [ + 'photo' => -10, + ]; + + $values = [ + 'crm_name' => ucwords("{$result->name->title} {$result->name->first} {$result->name->last}"), + 'crm_gender' => $result->gender, + 'crm_email' => $result->email, + 'crm_dob' => substr($result->dob, 0, 10), + 'crm_address' => [ + 'country_code' => 'GB', + 'address_line1' => $result->location->street, + 'locality' => $result->location->city, + 'postal_code' => $result->location->postcode, + ], + ]; + + // Generate our photo if required. + if ($this->getRandomDecision($options['photo'])) { + $photo = file_save_data(file_get_contents($result->picture->large)); + $values['crm_photo'] = $photo->id(); + } + + return $this->createProfile('crm_indiv', $values, $user); + } + + /** + * Create the notes profile for the result row. + * + * @param \stdClass $result + * The result row to generate for. + * @param \Drupal\user\UserInterface $user + * The user account to attach the profile to. + * @param array $options + * The options for the generation. + * + * @return \Drupal\profile\Entity\ProfileInterface + * The generated profile. + */ + protected function createProfileNotes(\stdClass $result, UserInterface $user, $options = array()) { + $options += [ + 'notes' => 3, + 'notes_content' => 2, + ]; + + if (!$this->getRandomDecision($options['notes'])) { + return NULL; + } + + $values = [ + 'crm_notes' => $this->getRandomDecision($options['notes_content']) ? "{$result->id->name}: {$result->id->value}" : '', + ]; + + return $this->createProfile('crm_indiv', $values, $user); + } + +} diff --git a/modules/contacts_demo/src/RandomUser.php b/modules/contacts_demo/src/RandomUser.php new file mode 100644 index 0000000..74a955f --- /dev/null +++ b/modules/contacts_demo/src/RandomUser.php @@ -0,0 +1,127 @@ +httpClientFactory = $http_client_factory; + $this->entityTypeManager = $entity_type_manager; + } + + public function generateUsers($number = 1, $options = array()) { + // Set some default options. + $options += [ + 'photos' => 10, + 'api' => [ + 'nat' => 'gb', + ] + ]; + + // Enforce a couple API options. + $options['api']['results'] = $number; + $options['api'][] = 'noinfo'; + + // Retrieve our results. + $results = $this->httpClientFactory->fromOptions()->request('https://randomuser.me/api', [ + 'query' => $options['api'], + ]); + $results = json_decode($results); + + // Loop over and create the users and associated entities. + foreach ($results->results as $result) { + $user = $this->createUser($result, $options); + $this->createProfileIndiv($result, $user, $options); + $this->createProfileNotes($result, $user, $options); + } + } + + protected function createUser(\stdClass $result, $options = array()) { + // Generate some reasonable timestamps. + $created = strtotime($result->registered); + $login = $created + rand(0, time() - $created); + $access = $login + rand(0, 86400); + $changed = $access + rand(0, time() - $access); + + $user_values = [ + 'mail' => $result->email, + 'status' => 1, + 'created' => $created, + 'changed' => $changed, + 'roles' => array('crm_indiv'), + ]; + + // If we're doing a coupled user, add the additional info. + if ($this->getRandomDecision($options['coupled']) ?? 2) { + $user_values += [ + 'name' => $result->login->username, + 'pass' => $result->login->password, + 'access' => $access, + 'login' => $login, + ]; + } + + $user = $this->entityTypeManager->getStorage('user')->create($user_values); + $user->save(); + return $user; + } + + /** + * Make a randomized decision with a given likelihood. + * + * @param bool|int $option + * Either a boolean indicating we should always return the same answer, or + * in integer indicating the likelihood (e.g. 1 in $option will be TRUE). + * Negative numbers reverse the result (e.g. 1 in $option will be FALSE). + * + * @return bool + * The random answer. + * + * @throws \Exception + * Thrown if the option is invalid. + */ + protected function getRandomDecision($option) { + // Check option is valid. + if (!is_bool($option) && (!is_int($option) || $option === 0)) { + throw new \Exception(strtr('Invalid argument "@option" for @method.', [ + '@option' => $option, + '@method' => __METHOD__, + ])); + } + + // If it's a boolean, we simply return it. + if (is_bool($option)) { + return $option; + } + + // Otherwise, generate a random number between 0 and it - 1. + $rand = rand(0, abs($option - 1)); + + // If our original option was positive, we want to return whether it's zero. + // Otherwise return if it's non zero. + return $rand === 0 xor $option < 0; + } +} From f83fde225aa7e8b41169a831d4a375018a2eaf00 Mon Sep 17 00:00:00 2001 From: andrewbelcher Date: Tue, 7 Mar 2017 17:40:58 -0500 Subject: [PATCH 2/4] by andrewbelcher: Generate individuals and organisations from sample data. --- .../contacts_demo/src/CrmGeneratorBase.php | 15 +- .../Plugin/DevelGenerate/CrmIndivGenerate.php | 9 +- .../Plugin/DevelGenerate/CrmOrgGenerate.php | 152 ++++++++++++++++++ 3 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 modules/contacts_demo/src/Plugin/DevelGenerate/CrmOrgGenerate.php diff --git a/modules/contacts_demo/src/CrmGeneratorBase.php b/modules/contacts_demo/src/CrmGeneratorBase.php index 6c8feff..fbf99d5 100644 --- a/modules/contacts_demo/src/CrmGeneratorBase.php +++ b/modules/contacts_demo/src/CrmGeneratorBase.php @@ -183,7 +183,7 @@ protected function createUser(\stdClass $result, array $options = array()) { 'roles' => [], ]; $options['roles'][] = static::ROLE_NAME; - $options['roles'] = array_filter($options['roles']); + $options['roles'] = array_unique($options['roles']); // Generate some reasonable timestamps. $created = strtotime($result->registered); @@ -215,6 +215,19 @@ protected function createUser(\stdClass $result, array $options = array()) { return $user; } + /** + * Create and save a profile of the given type, connecting it to the user. + * + * @param $type + * The profile type. + * @param array $values + * The values to store. + * @param \Drupal\user\UserInterface $user + * The user to connect it with. + * + * @return \Drupal\profile\Entity\ProfileInterface + * The generated profile. + */ protected function createProfile($type, array $values, UserInterface $user) { $values['type'] = $type; $values['uid'] = $user->id(); diff --git a/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php index 8afa095..34b613c 100644 --- a/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php +++ b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php @@ -5,6 +5,7 @@ use Drupal\contacts_demo\CrmGeneratorBase; use Drupal\Core\Form\FormStateInterface; use Drupal\user\UserInterface; +use GuzzleHttp\Client; /** * Generate individuals using the randomuser.me API. @@ -54,15 +55,17 @@ public function generateContacts($number = 1, array $options = array()) { ] ]; + // Enforce a couple API options. $options['api']['results'] = $number; $options['api'][] = 'noinfo'; // Retrieve our results. - $results = $this->httpClientFactory->fromOptions()->request('GET', 'https://randomuser.me/api', [ + $client = $this->httpClientFactory->fromOptions(); + $results = $client->request('GET', 'https://randomuser.me/api', [ 'query' => $options['api'], ]); - $results = json_decode($results); + $results = json_decode($results->getBody()); // Loop over and create the users and associated entities. foreach ($results->results as $result) { @@ -139,7 +142,7 @@ protected function createProfileNotes(\stdClass $result, UserInterface $user, $o 'crm_notes' => $this->getRandomDecision($options['notes_content']) ? "{$result->id->name}: {$result->id->value}" : '', ]; - return $this->createProfile('crm_indiv', $values, $user); + return $this->createProfile('crm_notes', $values, $user); } } diff --git a/modules/contacts_demo/src/Plugin/DevelGenerate/CrmOrgGenerate.php b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmOrgGenerate.php new file mode 100644 index 0000000..d667726 --- /dev/null +++ b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmOrgGenerate.php @@ -0,0 +1,152 @@ + $this->t('Organisation are generated using data provided by www.mockaroo.com with images from www.flamingtext.co.uk.', [ + ':data-url' => 'http://www.mockaroo.com/', + ':image-url' => 'http://www.flamingtext.co.uk/', + ]), + ); + + return $form; + } + + /** + * {@inheritdoc} + */ + public function generateContacts($number = 1, array $options = array()) { + // Organisations never have accounts. + $options['coupled'] = FALSE; + + // Retrieve our results. + $client = $this->httpClientFactory->fromOptions(); + $results = $client->request('GET', 'https://www.mockaroo.com/dddbdc80/download?count=10&key=ee1f5f90', [ + 'query' => [ + 'count' => $number, + 'key' => 'ee1f5f90', + ], + ]); + $results = json_decode($results->getBody()); + + // Loop over and create the users and associated entities. + foreach ($results as $result) { + $user = $this->createUser($result, $options); + $this->createProfileOrg($result, $user, $options); + $this->createProfileNotes($result, $user, $options); + } + } + + /** + * Create the individual profile for the result row. + * + * @param \stdClass $result + * The result row to generate for. + * @param \Drupal\user\UserInterface $user + * The user account to attach the profile to. + * @param array $options + * The options for the generation. + * + * @return \Drupal\profile\Entity\ProfileInterface + * The generated profile. + */ + protected function createProfileOrg(\stdClass $result, UserInterface $user, $options = array()) { + $options += [ + 'logo' => -10, + ]; + + $values = [ + 'crm_org_name' => $result->name, + 'crm_org_email' => $result->email, + 'crm_org_address' => [ + 'country_code' => 'GB', + 'address_line1' => $result->location->street, + 'locality' => $result->location->city, + 'postal_code' => $result->location->postcode, + ], + ]; + + // Generate our photo if required. + if ($this->getRandomDecision($options['logo'])) { + $designs = ['minions', 'comics', 'blackbird']; + $query = [ + 'script' => $designs[rand(0, count($designs) - 1)] . '-logo', + '_loc' => 'generate', + 'imageoutput' => 'true', + 'fillTextType' => 0, + 'fillTextColor' => '#' . dechex(rand(0, 15)) . dechex(rand(0, 15)) . dechex(rand(0, 15)) . dechex(rand(0, 15)) . dechex(rand(0, 15)) . dechex(rand(0, 15)), + 'text' => $result->name, + ]; + $url = 'http://www.flamingtext.co.uk/net-fu/proxy_form.cgi?' . http_build_query($query); + + $photo = file_save_data(file_get_contents($url)); + $values['crm_logo'] = $photo->id(); + } + + return $this->createProfile('crm_org', $values, $user); + } + + /** + * Create the notes profile for the result row. + * + * @param \stdClass $result + * The result row to generate for. + * @param \Drupal\user\UserInterface $user + * The user account to attach the profile to. + * @param array $options + * The options for the generation. + * + * @return \Drupal\profile\Entity\ProfileInterface + * The generated profile. + */ + protected function createProfileNotes(\stdClass $result, UserInterface $user, $options = array()) { + $options += [ + 'notes' => 3, + 'notes_content' => 2, + ]; + + if (!$this->getRandomDecision($options['notes'])) { + return NULL; + } + + $values = [ + 'crm_notes' => $this->getRandomDecision($options['notes_content']) ? $result->slogan : '', + ]; + + return $this->createProfile('crm_notes', $values, $user); + } + +} From 3260fef4e43cd742f20c1ee53598fdfed57f9020 Mon Sep 17 00:00:00 2001 From: andrewbelcher Date: Mon, 13 Mar 2017 06:57:58 -0400 Subject: [PATCH 3/4] by andrewbelcher: Ensure addresses are uppercased. --- .../src/Plugin/DevelGenerate/CrmIndivGenerate.php | 6 +++--- .../src/Plugin/DevelGenerate/CrmOrgGenerate.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php index 34b613c..e26f3cf 100644 --- a/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php +++ b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php @@ -100,9 +100,9 @@ protected function createProfileIndiv(\stdClass $result, UserInterface $user, $o 'crm_dob' => substr($result->dob, 0, 10), 'crm_address' => [ 'country_code' => 'GB', - 'address_line1' => $result->location->street, - 'locality' => $result->location->city, - 'postal_code' => $result->location->postcode, + 'address_line1' => ucwords($result->location->street), + 'locality' => ucwords($result->location->city), + 'postal_code' => strtoupper($result->location->postcode), ], ]; diff --git a/modules/contacts_demo/src/Plugin/DevelGenerate/CrmOrgGenerate.php b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmOrgGenerate.php index d667726..adba880 100644 --- a/modules/contacts_demo/src/Plugin/DevelGenerate/CrmOrgGenerate.php +++ b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmOrgGenerate.php @@ -93,9 +93,9 @@ protected function createProfileOrg(\stdClass $result, UserInterface $user, $opt 'crm_org_email' => $result->email, 'crm_org_address' => [ 'country_code' => 'GB', - 'address_line1' => $result->location->street, - 'locality' => $result->location->city, - 'postal_code' => $result->location->postcode, + 'address_line1' => ucwords($result->location->street), + 'locality' => ucwords($result->location->city), + 'postal_code' => strtoupper($result->location->postcode), ], ]; From 90ea43984f7f1e3c1473d55947c3c212b5a4be58 Mon Sep 17 00:00:00 2001 From: andrewbelcher Date: Mon, 13 Mar 2017 07:33:43 -0400 Subject: [PATCH 4/4] by andrewbelcher: Generate a phone number. --- .../contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php | 1 + .../contacts_demo/src/Plugin/DevelGenerate/CrmOrgGenerate.php | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php index e26f3cf..9fb03b3 100644 --- a/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php +++ b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmIndivGenerate.php @@ -104,6 +104,7 @@ protected function createProfileIndiv(\stdClass $result, UserInterface $user, $o 'locality' => ucwords($result->location->city), 'postal_code' => strtoupper($result->location->postcode), ], + 'crm_phone' => '07000 ' . str_pad(rand(0, 999999), 6, '0', STR_PAD_LEFT), ]; // Generate our photo if required. diff --git a/modules/contacts_demo/src/Plugin/DevelGenerate/CrmOrgGenerate.php b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmOrgGenerate.php index adba880..4999d7b 100644 --- a/modules/contacts_demo/src/Plugin/DevelGenerate/CrmOrgGenerate.php +++ b/modules/contacts_demo/src/Plugin/DevelGenerate/CrmOrgGenerate.php @@ -97,6 +97,7 @@ protected function createProfileOrg(\stdClass $result, UserInterface $user, $opt 'locality' => ucwords($result->location->city), 'postal_code' => strtoupper($result->location->postcode), ], + 'crm_phone' => '07000 ' . str_pad(rand(0, 999999), 6, '0', STR_PAD_LEFT), ]; // Generate our photo if required.