diff --git a/devel_generate/src/Plugin/DevelGenerate/MediaDevelGenerate.php b/devel_generate/src/Plugin/DevelGenerate/MediaDevelGenerate.php new file mode 100644 index 0000000..c723407 --- /dev/null +++ b/devel_generate/src/Plugin/DevelGenerate/MediaDevelGenerate.php @@ -0,0 +1,457 @@ +moduleHandler = $module_handler; + $this->mediaStorage = $media_storage; + $this->mediaTypeStorage = $media_type_storage; + $this->userStorage = $user_storage; + $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('media'), + $entity_manager->getStorage('user'), + $entity_manager->getStorage('media_type'), + $container->get('module_handler'), + $container->get('language_manager'), + $container->get('url_generator'), + $container->get('date.formatter') + ); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $types = $this->mediaTypeStorage->loadMultiple(); + + if (empty($types)) { + $create_url = $this->urlGenerator->generateFromRoute('media.bundle_add'); + $this->setMessage($this->t('You do not have any media types that can be generated. Go create a new media type', ['@create-type' => $create_url]), 'error', FALSE); + return []; + } + + $options = []; + foreach ($types as $type) { + $options[$type->id()] = ['type' => ['#markup' => $type->label()]]; + } + + $form['media_types'] = [ + '#type' => 'tableselect', + '#header' => ['type' => $this->t('Media type')], + '#options' => $options, + ]; + + $form['kill'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Delete all media in these types before generating new media.'), + '#default_value' => $this->getSetting('kill'), + ]; + $form['num'] = [ + '#type' => 'number', + '#title' => $this->t('How many media items would you like to generate?'), + '#default_value' => $this->getSetting('num'), + '#required' => TRUE, + '#min' => 0, + ]; + + $options = [1 => $this->t('Now')]; + foreach ([3600, 86400, 604800, 2592000, 31536000] as $interval) { + $options[$interval] = $this->dateFormatter->formatInterval($interval, 1) . ' ' . $this->t('ago'); + } + $form['time_range'] = [ + '#type' => 'select', + '#title' => $this->t('How far back in time should the media be dated?'), + '#description' => $this->t('Media creation dates will be distributed randomly from the current time, back to the selected time.'), + '#options' => $options, + '#default_value' => 604800, + ]; + + $form['name_length'] = [ + '#type' => 'number', + '#title' => $this->t('Maximum number of words in names'), + '#default_value' => $this->getSetting('name_length'), + '#required' => TRUE, + '#min' => 1, + '#max' => 255, + ]; + + $options = []; + // We always need a language. + $languages = $this->languageManager->getLanguages(LanguageInterface::STATE_ALL); + foreach ($languages as $langcode => $language) { + $options[$langcode] = $language->getName(); + } + + $form['add_language'] = [ + '#type' => 'select', + '#title' => $this->t('Set language on media'), + '#multiple' => TRUE, + '#description' => $this->t('Requires locale.module'), + '#options' => $options, + '#default_value' => [ + $this->languageManager->getDefaultLanguage()->getId(), + ], + ]; + + $form['#redirect'] = FALSE; + + return $form; + } + + /** + * {@inheritdoc} + */ + protected function generateElements(array $values) { + if ($values['num'] <= 50) { + $this->generateMedia($values); + } + else { + $this->generateBatchMedia($values); + } + } + + /** + * Method for creating media when number of elements is less than 50. + * + * @param array $values + * Array of values submitted through a form. + */ + private function generateMedia($values) { + $values['media_types'] = array_filter($values['media_types']); + if (!empty($values['kill']) && $values['media_types']) { + $this->mediaKill($values); + } + + if (!empty($values['media_types'])) { + // Generate media. + $this->preGenerate($values); + $start = time(); + for ($i = 1; $i <= $values['num']; $i++) { + $this->createMediaItem($values); + if (function_exists('drush_log') && $i % drush_get_option('feedback', 1000) == 0) { + $now = time(); + drush_log(dt('Completed !feedback media items (!rate media/min)', [ + '!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 media created.', 'Finished creating @count media items.')); + } + + /** + * Method for creating media when number of elements is greater than 50. + * + * @param array $values + * The input values from the settings form. + */ + private function generateBatchMedia($values) { + // Setup the batch operations and save the variables. + $operations[] = [ + 'devel_generate_operation', + [$this, 'batchPreGenerate', $values], + ]; + + // Add the kill operation. + if ($values['kill']) { + $operations[] = [ + 'devel_generate_operation', + [$this, 'batchMediaKill', $values], + ]; + } + + // Add the operations to create the media. + for ($num = 0; $num < $values['num']; $num++) { + $operations[] = [ + 'devel_generate_operation', + [$this, 'batchCreateMediaItem', $values], + ]; + } + + // Start the batch. + $batch = [ + 'title' => $this->t('Generating media'), + 'operations' => $operations, + 'finished' => 'devel_generate_batch_finished', + 'file' => drupal_get_path('module', 'devel_generate') . '/devel_generate.batch.inc', + ]; + batch_set($batch); + } + + /** + * Batch version of preGenerate(). + * + * @param array $vars + * The input values from the settings form. + * @param array $context + * Batch job context. + */ + public function batchPreGenerate($vars, &$context) { + $context['results'] = $vars; + $context['results']['num'] = 0; + $this->preGenerate($context['results']); + } + + /** + * Batch version of createMediaItem(). + * + * @param array $vars + * The input values from the settings form. + * @param array $context + * Batch job context. + */ + public function batchCreateMediaItem($vars, &$context) { + $this->createMediaItem($context['results']); + $context['results']['num']++; + } + + /** + * Batch version of mediaKill(). + * + * @param array $vars + * The input values from the settings form. + * @param array $context + * Batch job context. + */ + public function batchMediaKill($vars, &$context) { + $this->mediaKill($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['name_length'] = drush_get_option('name_length', 6); + $values['num'] = array_shift($args); + $selected_bundles = _convert_csv_to_array(drush_get_option('bundles', [])); + + if (empty($selected_bundles)) { + return drush_set_error('DEVEL_GENERATE_NO_MEDIA_TYPES', dt('No media types available')); + } + + $values['media_types'] = array_combine($selected_bundles, $selected_bundles); + + return $values; + } + + /** + * Deletes all media of given media bundles. + * + * @param array $values + * The input values from the settings form. + */ + protected function mediaKill($values) { + $mids = $this->mediaStorage->getQuery() + ->condition('bundle', $values['media_types'], 'IN') + ->execute(); + + if (!empty($mids)) { + $media = $this->mediaStorage->loadMultiple($mids); + $this->mediaStorage->delete($media); + $this->setMessage($this->t('Deleted %count media items.', ['%count' => count($mids)])); + } + } + + /** + * Code to be run before generating items. + * + * Returns the same array passed in as parameter, but with an array of uids + * for the key 'users'. + * + * @param array $results + * The input values from the settings form. + */ + protected function preGenerate(&$results) { + // Get user id. + $users = $this->userStorage->getQuery() + ->range(0, 50) + ->execute(); + $users = array_merge($users, ['0']); + $results['users'] = $users; + } + + /** + * Create one media item. Used by both batch and non-batch code branches. + * + * @param array $results + * The input values from the settings form. + */ + protected function createMediaItem(&$results) { + if (!isset($results['time_range'])) { + $results['time_range'] = 0; + } + $users = $results['users']; + + $bundle = array_rand(array_filter($results['media_types'])); + $uid = $users[array_rand($users)]; + + $media = $this->mediaStorage->create([ + 'bundle' => $bundle, + 'name' => $this->getRandom()->sentences(mt_rand(1, $results['name_length']), TRUE), + 'uid' => $uid, + 'revision' => mt_rand(0, 1), + 'status' => TRUE, + 'created' => REQUEST_TIME - mt_rand(0, $results['time_range']), + 'langcode' => $this->getLangcode($results), + ]); + + // A flag to let hook implementations know that this is a generated item. + $media->devel_generate = $results; + + // Populate all fields with sample values. + $this->populateFields($media); + + $media->save(); + } + + /** + * Determine language based on $results. + * + * @param array $results + * The input values from the settings form. + */ + 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; + } + +}