Version 1
[yaffs-website] / web / modules / contrib / devel / devel_generate / src / Plugin / DevelGenerate / TermDevelGenerate.php
1 <?php
2
3 namespace Drupal\devel_generate\Plugin\DevelGenerate;
4
5 use Drupal\Core\Entity\EntityStorageInterface;
6 use Drupal\Core\Form\FormStateInterface;
7 use Drupal\Core\Language\Language;
8 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
9 use Drupal\devel_generate\DevelGenerateBase;
10 use Symfony\Component\DependencyInjection\ContainerInterface;
11
12 /**
13  * Provides a TermDevelGenerate plugin.
14  *
15  * @DevelGenerate(
16  *   id = "term",
17  *   label = @Translation("terms"),
18  *   description = @Translation("Generate a given number of terms. Optionally delete current terms."),
19  *   url = "term",
20  *   permission = "administer devel_generate",
21  *   settings = {
22  *     "num" = 10,
23  *     "title_length" = 12,
24  *     "kill" = FALSE,
25  *   }
26  * )
27  */
28 class TermDevelGenerate extends DevelGenerateBase implements ContainerFactoryPluginInterface {
29
30   /**
31    * The vocabulary storage.
32    *
33    * @var \Drupal\Core\Entity\EntityStorageInterface
34    */
35   protected $vocabularyStorage;
36
37   /**
38    * The term storage.
39    *
40    * @var \Drupal\Core\Entity\EntityStorageInterface
41    */
42   protected $termStorage;
43
44   /**
45    * Constructs a new TermDevelGenerate object.
46    *
47    * @param array $configuration
48    *   A configuration array containing information about the plugin instance.
49    * @param string $plugin_id
50    *   The plugin_id for the plugin instance.
51    * @param mixed $plugin_definition
52    *   The plugin implementation definition.
53    * @param \Drupal\Core\Entity\EntityStorageInterface $vocabulary_storage
54    *   The vocabulary storage.
55    * @param \Drupal\Core\Entity\EntityStorageInterface $term_storage
56    *   The term storage.
57    */
58   public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityStorageInterface $vocabulary_storage, EntityStorageInterface $term_storage) {
59     parent::__construct($configuration, $plugin_id, $plugin_definition);
60
61     $this->vocabularyStorage = $vocabulary_storage;
62     $this->termStorage = $term_storage;
63   }
64
65   /**
66    * {@inheritdoc}
67    */
68   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
69     $entity_manager = $container->get('entity.manager');
70     return new static(
71       $configuration, $plugin_id, $plugin_definition,
72       $entity_manager->getStorage('taxonomy_vocabulary'),
73       $entity_manager->getStorage('taxonomy_term')
74     );
75   }
76
77   /**
78    * {@inheritdoc}
79    */
80   public function settingsForm(array $form, FormStateInterface $form_state) {
81     $options = array();
82     foreach ($this->vocabularyStorage->loadMultiple() as $vocabulary) {
83       $options[$vocabulary->id()] = $vocabulary->label();
84     }
85     $form['vids'] = array(
86       '#type' => 'select',
87       '#multiple' => TRUE,
88       '#title' => $this->t('Vocabularies'),
89       '#required' => TRUE,
90       '#default_value' => 'tags',
91       '#options' => $options,
92       '#description' => $this->t('Restrict terms to these vocabularies.'),
93     );
94     $form['num'] = array(
95       '#type' => 'number',
96       '#title' => $this->t('Number of terms?'),
97       '#default_value' => $this->getSetting('num'),
98       '#required' => TRUE,
99       '#min' => 0,
100     );
101     $form['title_length'] = array(
102       '#type' => 'number',
103       '#title' => $this->t('Maximum number of characters in term names'),
104       '#default_value' => $this->getSetting('title_length'),
105       '#required' => TRUE,
106       '#min' => 2,
107       '#max' => 255,
108     );
109     $form['kill'] = array(
110       '#type' => 'checkbox',
111       '#title' => $this->t('Delete existing terms in specified vocabularies before generating new terms.'),
112       '#default_value' => $this->getSetting('kill'),
113     );
114
115     return $form;
116   }
117
118   /**
119    * {@inheritdoc}
120    */
121   public function generateElements(array $values) {
122     if ($values['kill']) {
123       $this->deleteVocabularyTerms($values['vids']);
124       $this->setMessage($this->t('Deleted existing terms.'));
125     }
126
127     $vocabs = $this->vocabularyStorage->loadMultiple($values['vids']);
128     $new_terms = $this->generateTerms($values['num'], $vocabs, $values['title_length']);
129     if (!empty($new_terms)) {
130       $this->setMessage($this->t('Created the following new terms: @terms', array('@terms' => implode(', ', $new_terms))));
131     }
132   }
133
134   /**
135    * Deletes all terms of given vocabularies.
136    *
137    * @param array $vids
138    *   Array of vocabulary vid.
139    */
140   protected function deleteVocabularyTerms($vids) {
141     $tids = $this->vocabularyStorage->getToplevelTids($vids);
142     $terms = $this->termStorage->loadMultiple($tids);
143     $this->termStorage->delete($terms);
144   }
145
146   /**
147    * Generates taxonomy terms for a list of given vocabularies.
148    *
149    * @param int $records
150    *   Number of terms to create in total.
151    * @param \Drupal\taxonomy\TermInterface[] $vocabs
152    *   List of vocabularies to populate.
153    * @param int $maxlength
154    *   (optional) Maximum length per term.
155    *
156    * @return array
157    *   The list of names of the created terms.
158    */
159   protected function generateTerms($records, $vocabs, $maxlength = 12) {
160     $terms = array();
161
162     // Insert new data:
163     $max = db_query('SELECT MAX(tid) FROM {taxonomy_term_data}')->fetchField();
164     $start = time();
165     for ($i = 1; $i <= $records; $i++) {
166       $name = $this->getRandom()->word(mt_rand(2, $maxlength));
167
168       $values = array(
169         'name' => $name,
170         'description' => 'description of ' . $name,
171         'format' => filter_fallback_format(),
172         'weight' => mt_rand(0, 10),
173         'langcode' => Language::LANGCODE_NOT_SPECIFIED,
174       );
175
176       switch ($i % 2) {
177         case 1:
178           $vocab = $vocabs[array_rand($vocabs)];
179           $values['vid'] = $vocab->id();
180           $values['parent'] = array(0);
181           break;
182
183         default:
184           while (TRUE) {
185             // Keep trying to find a random parent.
186             $candidate = mt_rand(1, $max);
187             $query = db_select('taxonomy_term_data', 't');
188             $parent = $query
189               ->fields('t', array('tid', 'vid'))
190               ->condition('t.vid', array_keys($vocabs), 'IN')
191               ->condition('t.tid', $candidate, '>=')
192               ->range(0, 1)
193               ->execute()
194               ->fetchAssoc();
195             if ($parent['tid']) {
196               break;
197             }
198           }
199           $values['parent'] = array($parent['tid']);
200           // Slight speedup due to this property being set.
201           $values['vid'] = $parent['vid'];
202           break;
203       }
204
205       $term = $this->termStorage->create($values);
206
207       // Populate all fields with sample values.
208       $this->populateFields($term);
209       $term->save();
210
211       $max++;
212
213       if (function_exists('drush_log')) {
214         $feedback = drush_get_option('feedback', 1000);
215         if ($i % $feedback == 0) {
216           $now = time();
217           drush_log(dt('Completed @feedback terms (@rate terms/min)', array('@feedback' => $feedback, '@rate' => $feedback * 60 / ($now - $start))), 'ok');
218           $start = $now;
219         }
220       }
221
222       // Limit memory usage. Only report first 20 created terms.
223       if ($i < 20) {
224         $terms[] = $term->label();
225       }
226
227       unset($term);
228     }
229
230     return $terms;
231   }
232
233   /**
234    * {@inheritdoc}
235    */
236   public function validateDrushParams($args) {
237     $vocabulary_name = array_shift($args);
238     $number = array_shift($args);
239
240     if ($number === NULL) {
241       $number = 10;
242     }
243
244     if (!$vocabulary_name) {
245       return drush_set_error('DEVEL_GENERATE_INVALID_INPUT', dt('Please provide a vocabulary machine name.'));
246     }
247
248     if (!$this->isNumber($number)) {
249       return drush_set_error('DEVEL_GENERATE_INVALID_INPUT', dt('Invalid number of terms: @num', array('@num' => $number)));
250     }
251
252     // Try to convert machine name to a vocabulary id.
253     if (!$vocabulary = $this->vocabularyStorage->load($vocabulary_name)) {
254       return drush_set_error('DEVEL_GENERATE_INVALID_INPUT', dt('Invalid vocabulary name: @name', array('@name' => $vocabulary_name)));
255     }
256
257     $values = [
258       'num' => $number,
259       'kill' => drush_get_option('kill'),
260       'title_length' => 12,
261       'vids' => [$vocabulary->id()],
262     ];
263
264     return $values;
265   }
266
267 }