moduleHandler = $module_handler; $this->nodeStorage = $node_storage; $this->nodeTypeStorage = $node_type_storage; $this->commentManager = $comment_manager; $this->languageManager = $language_manager; $this->urlGenerator = $url_generator; $this->dateFormatter = $date_formatter; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { $entity_manager = $container->get('entity.manager'); return new static( $configuration, $plugin_id, $plugin_definition, $entity_manager->getStorage('node'), $entity_manager->getStorage('node_type'), $container->get('module_handler'), $container->has('comment.manager') ? $container->get('comment.manager') : NULL, $container->get('language_manager'), $container->get('url_generator'), $container->get('date.formatter') ); } /** * {@inheritdoc} */ public function settingsForm(array $form, FormStateInterface $form_state) { $types = $this->nodeTypeStorage->loadMultiple(); if (empty($types)) { $create_url = $this->urlGenerator->generateFromRoute('node.type_add'); $this->setMessage($this->t('You do not have any content types that can be generated. Go create a new content type', array(':create-type' => $create_url)), 'error', FALSE); return; } $options = array(); foreach ($types as $type) { $options[$type->id()] = array( 'type' => array('#markup' => $type->label()), ); if ($this->commentManager) { $comment_fields = $this->commentManager->getFields('node'); $map = array($this->t('Hidden'), $this->t('Closed'), $this->t('Open')); $fields = array(); foreach ($comment_fields as $field_name => $info) { // Find all comment fields for the bundle. if (in_array($type->id(), $info['bundles'])) { $instance = FieldConfig::loadByName('node', $type->id(), $field_name); $default_value = $instance->getDefaultValueLiteral(); $default_mode = reset($default_value); $fields[] = new FormattableMarkup('@field: @state', array( '@field' => $instance->label(), '@state' => $map[$default_mode['status']], )); } } // @todo Refactor display of comment fields. if (!empty($fields)) { $options[$type->id()]['comments'] = array( 'data' => array( '#theme' => 'item_list', '#items' => $fields, ), ); } else { $options[$type->id()]['comments'] = $this->t('No comment fields'); } } } $header = array( 'type' => $this->t('Content type'), ); if ($this->commentManager) { $header['comments'] = array( 'data' => $this->t('Comments'), 'class' => array(RESPONSIVE_PRIORITY_MEDIUM), ); } $form['node_types'] = array( '#type' => 'tableselect', '#header' => $header, '#options' => $options, ); $form['kill'] = array( '#type' => 'checkbox', '#title' => $this->t('Delete all content in these content types before generating new content.'), '#default_value' => $this->getSetting('kill'), ); $form['num'] = array( '#type' => 'number', '#title' => $this->t('How many nodes would you like to generate?'), '#default_value' => $this->getSetting('num'), '#required' => TRUE, '#min' => 0, ); $options = array(1 => $this->t('Now')); foreach (array(3600, 86400, 604800, 2592000, 31536000) as $interval) { $options[$interval] = $this->dateFormatter->formatInterval($interval, 1) . ' ' . $this->t('ago'); } $form['time_range'] = array( '#type' => 'select', '#title' => $this->t('How far back in time should the nodes be dated?'), '#description' => $this->t('Node creation dates will be distributed randomly from the current time, back to the selected time.'), '#options' => $options, '#default_value' => 604800, ); $form['max_comments'] = array( '#type' => $this->moduleHandler->moduleExists('comment') ? 'number' : 'value', '#title' => $this->t('Maximum number of comments per node.'), '#description' => $this->t('You must also enable comments for the content types you are generating. Note that some nodes will randomly receive zero comments. Some will receive the max.'), '#default_value' => $this->getSetting('max_comments'), '#min' => 0, '#access' => $this->moduleHandler->moduleExists('comment'), ); $form['title_length'] = array( '#type' => 'number', '#title' => $this->t('Maximum number of words in titles'), '#default_value' => $this->getSetting('title_length'), '#required' => TRUE, '#min' => 1, '#max' => 255, ); $form['add_alias'] = array( '#type' => 'checkbox', '#disabled' => !$this->moduleHandler->moduleExists('path'), '#description' => $this->t('Requires path.module'), '#title' => $this->t('Add an url alias for each node.'), '#default_value' => FALSE, ); $form['add_statistics'] = array( '#type' => 'checkbox', '#title' => $this->t('Add statistics for each node (node_counter table).'), '#default_value' => TRUE, '#access' => $this->moduleHandler->moduleExists('statistics'), ); $options = array(); // We always need a language. $languages = $this->languageManager->getLanguages(LanguageInterface::STATE_ALL); foreach ($languages as $langcode => $language) { $options[$langcode] = $language->getName(); } $form['add_language'] = array( '#type' => 'select', '#title' => $this->t('Set language on nodes'), '#multiple' => TRUE, '#description' => $this->t('Requires locale.module'), '#options' => $options, '#default_value' => array( $this->languageManager->getDefaultLanguage()->getId(), ), ); $form['#redirect'] = FALSE; return $form; } /** * {@inheritdoc} */ function settingsFormValidate(array $form, FormStateInterface $form_state) { if (!array_filter($form_state->getValue('node_types'))) { $form_state->setErrorByName('node_types', $this->t('Please select at least one content type')); } } /** * {@inheritdoc} */ protected function generateElements(array $values) { if ($values['num'] <= 50 && $values['max_comments'] <= 10) { $this->generateContent($values); } else { $this->generateBatchContent($values); } } /** * Method responsible for creating content when * the number of elements is less than 50. */ private function generateContent($values) { $values['node_types'] = array_filter($values['node_types']); if (!empty($values['kill']) && $values['node_types']) { $this->contentKill($values); } if (!empty($values['node_types'])) { // Generate nodes. $this->develGenerateContentPreNode($values); $start = time(); for ($i = 1; $i <= $values['num']; $i++) { $this->develGenerateContentAddNode($values); if (function_exists('drush_log') && $i % drush_get_option('feedback', 1000) == 0) { $now = time(); drush_log(dt('Completed @feedback nodes (@rate nodes/min)', array('@feedback' => drush_get_option('feedback', 1000), '@rate' => (drush_get_option('feedback', 1000) * 60) / ($now - $start))), 'ok'); $start = $now; } } } $this->setMessage($this->formatPlural($values['num'], '1 node created.', 'Finished creating @count nodes')); } /** * Method responsible for creating content when * the number of elements is greater than 50. */ private function generateBatchContent($values) { // Setup the batch operations and save the variables. $operations[] = array('devel_generate_operation', array($this, 'batchContentPreNode', $values)); // Add the kill operation. if ($values['kill']) { $operations[] = array('devel_generate_operation', array($this, 'batchContentKill', $values)); } // Add the operations to create the nodes. for ($num = 0; $num < $values['num']; $num ++) { $operations[] = array('devel_generate_operation', array($this, 'batchContentAddNode', $values)); } // Start the batch. $batch = array( 'title' => $this->t('Generating Content'), 'operations' => $operations, 'finished' => 'devel_generate_batch_finished', 'file' => drupal_get_path('module', 'devel_generate') . '/devel_generate.batch.inc', ); batch_set($batch); } public function batchContentPreNode($vars, &$context) { $context['results'] = $vars; $context['results']['num'] = 0; $this->develGenerateContentPreNode($context['results']); } public function batchContentAddNode($vars, &$context) { $this->develGenerateContentAddNode($context['results']); $context['results']['num']++; } public function batchContentKill($vars, &$context) { $this->contentKill($context['results']); } /** * {@inheritdoc} */ public function validateDrushParams($args) { $add_language = drush_get_option('languages'); if (!empty($add_language)) { $add_language = explode(',', str_replace(' ', '', $add_language)); // Intersect with the enabled languages to make sure the language args // passed are actually enabled. $values['values']['add_language'] = array_intersect($add_language, array_keys($this->languageManager->getLanguages(LanguageInterface::STATE_ALL))); } $values['kill'] = drush_get_option('kill'); $values['title_length'] = 6; $values['num'] = array_shift($args); $values['max_comments'] = array_shift($args); $all_types = array_keys(node_type_get_names()); $default_types = array_intersect(array('page', 'article'), $all_types); $selected_types = _convert_csv_to_array(drush_get_option('types', $default_types)); // Validates the input format for content types option. if (drush_get_option('types', $default_types) === TRUE) { return drush_set_error('DEVEL_GENERATE_INVALID_INPUT', dt('Wrong syntax or no content type selected. The correct syntax uses "=", eg.: --types=page,article')); } if (empty($selected_types)) { return drush_set_error('DEVEL_GENERATE_NO_CONTENT_TYPES', dt('No content types available')); } $values['node_types'] = array_combine($selected_types, $selected_types); $node_types = array_filter($values['node_types']); if (!empty($values['kill']) && empty($node_types)) { return drush_set_error('DEVEL_GENERATE_INVALID_INPUT', dt('Please provide content type (--types) in which you want to delete the content.')); } // Checks for any missing content types before generating nodes. if (array_diff($node_types, $all_types)) { return drush_set_error('DEVEL_GENERATE_INVALID_INPUT', dt('One or more content types have been entered that don\'t exist on this site')); } return $values; } /** * Deletes all nodes of given node types. * * @param array $values * The input values from the settings form. */ protected function contentKill($values) { $nids = $this->nodeStorage->getQuery() ->condition('type', $values['node_types'], 'IN') ->execute(); if (!empty($nids)) { $nodes = $this->nodeStorage->loadMultiple($nids); $this->nodeStorage->delete($nodes); $this->setMessage($this->t('Deleted %count nodes.', array('%count' => count($nids)))); } } /** * Return the same array passed as parameter * but with an array of uids for the key 'users'. */ protected function develGenerateContentPreNode(&$results) { // Get user id. $users = $this->getUsers(); $users = array_merge($users, array('0')); $results['users'] = $users; } /** * Create one node. Used by both batch and non-batch code branches. */ protected function develGenerateContentAddNode(&$results) { if (!isset($results['time_range'])) { $results['time_range'] = 0; } $users = $results['users']; $node_type = array_rand(array_filter($results['node_types'])); $uid = $users[array_rand($users)]; $node = $this->nodeStorage->create(array( 'nid' => NULL, 'type' => $node_type, 'title' => $this->getRandom()->sentences(mt_rand(1, $results['title_length']), TRUE), 'uid' => $uid, 'revision' => mt_rand(0, 1), 'status' => TRUE, 'promote' => mt_rand(0, 1), 'created' => REQUEST_TIME - mt_rand(0, $results['time_range']), 'langcode' => $this->getLangcode($results), )); // A flag to let hook_node_insert() implementations know that this is a // generated node. $node->devel_generate = $results; // Populate all fields with sample values. $this->populateFields($node); // See devel_generate_node_insert() for actions that happen before and after // this save. $node->save(); } /** * Determine language based on $results. */ protected function getLangcode($results) { if (isset($results['add_language'])) { $langcodes = $results['add_language']; $langcode = $langcodes[array_rand($langcodes)]; } else { $langcode = $this->languageManager->getDefaultLanguage()->getId(); } return $langcode; } /** * Retrive 50 uids from the database. */ protected function getUsers() { $users = array(); $result = db_query_range("SELECT uid FROM {users}", 0, 50); foreach ($result as $record) { $users[] = $record->uid; } return $users; } }