Slightly better info messages.
[project/devel.git] / devel_generate.inc
1 <?php
2 // $Id$
3 // If not in 'safe mode', increase the maximum execution time:
4 if (!ini_get('safe_mode')) {
5 set_time_limit(240);
6 }
7
8 /**
9 * Generate some random users.
10 *
11 * @param $num
12 * Number of users to generate.
13 * @param $kill
14 * Boolean that indicates if existing users should be removed first.
15 * @param $age
16 * The max age of each randomly-generated user, in seconds.
17 */
18 function devel_create_users($num, $kill, $age = 0) {
19 $url = parse_url($GLOBALS['base_url']);
20 if ($kill) {
21 db_query('DELETE FROM {users} WHERE uid > 1');
22 drupal_set_message(t('Users deleted.'));
23 }
24 if ($num > 0) {
25 $names = array();
26 while (count($names) < $num) {
27 $length = mt_rand(6, 12);
28 $name = devel_generate_word($length);
29 $names[$name] = '';
30 }
31 foreach ($names as $name => $value) {
32 $pass = md5(user_password());
33 $mail = $name .'@'. $url['host'];
34 $now = time();
35 $created = ($age ? mt_rand($now - $age, $now) : $now - 1);
36 $account = user_save(NULL, array('name' => $name, 'pass' => $pass, 'mail' => $mail, 'status' =>'1', 'created' => $created, 'access' => $now, 'devel_generate' => TRUE));
37 }
38 drupal_set_message(t('!num_users created.', array('!num_users' => format_plural($num, '1 user', '@count users'))));
39 }
40 }
41
42 /**
43 * The main API function for creating content.
44 *
45 * See devel_generate_content_form() for the supported keys in $form_state['values'].
46 * Other modules may participate by form_alter() on that form and then handling their data during hook_nodeapi('pre_save') or in own submit handler for the form.
47 *
48 * @param string $form_state
49 * @return void
50 */
51 function devel_generate_content($form_state) {
52 if ($form_state['values']['kill_content']) {
53 devel_generate_content_kill($form_state['values']);
54 }
55
56 if (count($form_state['values']['node_types'])) {
57 // Generate nodes.
58 devel_generate_content_pre_node($form_state['values']);
59 for ($i = 1; $i <= $form_state['values']['num_nodes']; $i ++) {
60 devel_generate_content_add_node($form_state['values']);
61 }
62 }
63
64 drupal_set_message(format_plural($form_state['values']['num_nodes'], '1 node created.', '@count nodes created'));
65 }
66
67 function devel_generate_add_comments($node, $users, $max_comments, $title_length = 8) {
68 // Insert new data:
69 $num_comments = mt_rand(1, $max_comments);
70 for ($i = 1; $i <= $num_comments; $i++) {
71 $comment->nid = $node->nid;
72 $comment->cid = NULL;
73 $comment->format = FILTER_FORMAT_DEFAULT;
74 $comment->name = 'devel generate';
75 $comment->mail = 'devel_generate@example.com';
76 $comment->timestamp = mt_rand($node->created, time());
77
78 switch ($i % 3) {
79 case 1:
80 $comment->pid = db_result(db_query_range("SELECT cid FROM {comments} WHERE pid = 0 AND nid = %d ORDER BY RAND()", $comment->nid, 0, 1));
81 break;
82 case 2:
83 $comment->pid = db_result(db_query("SELECT cid FROM {comments} WHERE pid > 0 AND nid = %d ORDER BY RAND()", $comment->nid, 0, 1));
84 break;
85 default:
86 $comment->pid = 0;
87 }
88
89 $comment->subject = devel_create_greeking(mt_rand(1, $title_length), TRUE);
90 $comment->comment = devel_create_content();
91 $comment->uid = $users[array_rand($users)];
92
93 // this is slow but gets the threading right.
94 comment_save((array)$comment);
95
96 }
97 }
98
99 function devel_generate_vocabs($records, $maxlength = 12, $types = array('story', 'blog', 'forum', 'page')) {
100 $vocs = array();
101
102 // Insert new data:
103 for ($i = 1; $i <= $records; $i++) {
104 $voc = array();
105 $voc['name'] = devel_generate_word(rand(2, $maxlength));
106 $voc['description'] = "description of ". $voc['name'];
107 $voc['nodes'] = array_flip(array($types[array_rand($types)]));
108 foreach ($voc['nodes'] as $key => $value) {
109 $voc['nodes'][$key] = $key;
110 }
111 $voc['multiple'] = 1;
112 $voc['required'] = 0;
113 $voc['relations'] = 1;
114 $voc['hierarchy'] = 1;
115 $voc['weight'] = mt_rand(0,10);
116
117 taxonomy_save_vocabulary($voc);
118 $vocs[] = $voc['name'];
119 }
120 return $vocs;
121 }
122
123 function devel_generate_terms($records, $vocs, $maxlength = 12) {
124 $terms = array();
125
126 // Insert new data:
127 for ($i = 1; $i <= $records; $i++) {
128 switch ($i % 2) {
129 case 1:
130 $term['vid'] = $vocs[array_rand($vocs)];
131 // dont set a parent. handled by taxonomy_save_term()
132 // $term->parent = 0;
133 break;
134 case 2:
135 default:
136 $parent = db_fetch_object(db_query_range("SELECT t.tid, v.vid FROM {term_data} t INNER JOIN {vocabulary} v ON t.vid = v.vid ORDER BY RAND()", 0, 1));
137 $term['parent'] = array($parent->tid);
138 $term['vid'] = $parent->vid;
139 break;
140 }
141
142 $term['name'] = devel_generate_word(mt_rand(2, $maxlength));
143 $term['description'] = "description of ". $term['name'];
144 $term['weight'] = mt_rand(0,10);
145
146 $status = taxonomy_save_term($term);
147 $output = NULL;
148
149 if ($status) {
150 $terms[] = $term['name'];
151 }
152
153 unset($term);
154 }
155 return $terms;
156 }
157
158 function devel_generate_get_vocabs() {
159 $vocs = array();
160 $result = db_query("SELECT vid FROM {vocabulary}");
161 while($voc = db_fetch_object($result)){
162 $vocs[] = $voc->vid;
163 }
164 return $vocs;
165 }
166
167 function devel_generate_taxonomy_data($num_vocab, $num_terms, $title_length, $kill) {
168
169 if ($kill) {
170 db_query("DELETE FROM {term_data}");
171 db_query("DELETE FROM {term_node}");
172 db_query("DELETE FROM {term_hierarchy}");
173 db_query("DELETE FROM {term_relation}");
174 db_query("DELETE FROM {term_synonym}");
175 db_query("DELETE FROM {vocabulary}");
176 db_query("DELETE FROM {vocabulary_node_types}");
177 switch ($GLOBALS['db_type']) {
178 case 'mysql':
179 case 'mysqli':
180 db_query("ALTER TABLE {vocabulary} AUTO_INCREMENT = 1");
181 db_query("ALTER TABLE {term_data} AUTO_INCREMENT = 1");
182 break;
183 case 'pgsql':
184 db_query("SELECT setval('{vocabulary}_vid_seq', 1, false)");
185 db_query("SELECT setval('{term_data}_tid_seq', 1, false)");
186 break;
187 }
188 drupal_set_message(t('Deleted taxonomy.'));
189 }
190
191 $new_vocs = devel_generate_vocabs($num_vocab, $title_length);
192 if (!empty($new_vocs)) {
193 drupal_set_message(t('Created the following new vocabularies: !vocs', array('!vocs' => theme('item_list', $new_vocs))));
194 }
195 $vocs = devel_generate_get_vocabs();
196 $new_terms = devel_generate_terms($num_terms, $vocs, $title_length);
197 if (!empty($new_terms)) {
198 drupal_set_message(t('Created the following new terms: !terms', array('!terms' => theme('item_list', $new_terms))));
199 }
200 }
201
202 function devel_generate_word($length){
203 srand((double)microtime()*1000000);
204
205 $vowels = array("a", "e", "i", "o", "u");
206 $cons = array("b", "c", "d", "g", "h", "j", "k", "l", "m", "n", "p", "r", "s", "t", "u", "v", "w", "tr",
207 "cr", "br", "fr", "th", "dr", "ch", "ph", "wr", "st", "sp", "sw", "pr", "sl", "cl", "sh");
208
209 $num_vowels = count($vowels);
210 $num_cons = count($cons);
211 $word = '';
212
213 while(strlen($word) < $length){
214 $word .= $cons[mt_rand(0, $num_cons - 1)] . $vowels[mt_rand(0, $num_vowels - 1)];
215 }
216
217 return substr($word, 0, $length);
218 }
219
220 function devel_create_content($type = NULL) {
221 $nparas = mt_rand(1,12);
222 $type = empty($type) ? mt_rand(0,3) : $type;
223
224 $output = "";
225 switch($type % 3) {
226 case 1: // html
227 for ($i = 1; $i <= $nparas; $i++) {
228 $output .= devel_create_para(mt_rand(10, 60), 1);
229 }
230 break;
231
232 case 2: // brs only
233 for ($i = 1; $i <= $nparas; $i++) {
234 $output .= devel_create_para(mt_rand(10, 60), 2);
235 }
236 break;
237
238 default: // plain text
239 for ($i = 1; $i <= $nparas; $i++) {
240 $output .= devel_create_para(mt_rand(10,60)) ."\n\n";
241 }
242 }
243
244 return $output;
245 }
246
247 // Return an $options array of content types.
248 function devel_generate_content_types() {
249 $options = array();
250
251 if (module_exists('content')) {
252 $types = content_types();
253 foreach ($types as $type) {
254 $warn = '';
255 if (count($type['fields'])) {
256 $warn = t('. This type contains CCK fields which will only be populated by fields that implement the content_generate hook.');
257 }
258 $options[$type['type']] = t($type['name']). $warn;
259 }
260 }
261 else {
262 $types = node_get_types();
263 foreach ($types as $type) {
264 $options[$type->type] = t($type->name);
265 }
266 }
267
268 // we cannot currently generate valid polls.
269 unset($options['poll']);
270
271 return $options;
272 }
273
274
275 function devel_create_para($words, $type = 0) {
276 $output = "";
277 switch ($type) {
278 case 1:
279 $output .= "<p>";
280 $output .= devel_create_greeking($words);
281 $output = trim($output) ."</p>";
282 break;
283
284 case 2:
285 $output .= devel_create_greeking($words);
286 $output = trim($output) ."<br />";
287 break;
288
289 default:
290 $output .= devel_create_greeking($words);
291 $output = trim($output);
292 }
293 return $output;
294 }
295
296 function devel_create_greeking($words, $title = FALSE) {
297 $dictionary = array("abbas", "abdo", "abico", "abigo", "abluo", "accumsan",
298 "acsi", "ad", "adipiscing", "aliquam", "aliquip", "amet", "antehabeo",
299 "appellatio", "aptent", "at", "augue", "autem", "bene", "blandit",
300 "brevitas", "caecus", "camur", "capto", "causa", "cogo", "comis",
301 "commodo", "commoveo", "consectetuer", "consequat", "conventio", "cui",
302 "damnum", "decet", "defui", "diam", "dignissim", "distineo", "dolor",
303 "dolore", "dolus", "duis", "ea", "eligo", "elit", "enim", "erat",
304 "eros", "esca", "esse", "et", "eu", "euismod", "eum", "ex", "exerci",
305 "exputo", "facilisi", "facilisis", "fere", "feugiat", "gemino",
306 "genitus", "gilvus", "gravis", "haero", "hendrerit", "hos", "huic",
307 "humo", "iaceo", "ibidem", "ideo", "ille", "illum", "immitto",
308 "importunus", "imputo", "in", "incassum", "inhibeo", "interdico",
309 "iriure", "iusto", "iustum", "jugis", "jumentum", "jus", "laoreet",
310 "lenis", "letalis", "lobortis", "loquor", "lucidus", "luctus", "ludus",
311 "luptatum", "macto", "magna", "mauris", "melior", "metuo", "meus",
312 "minim", "modo", "molior", "mos", "natu", "neo", "neque", "nibh",
313 "nimis", "nisl", "nobis", "nostrud", "nulla", "nunc", "nutus", "obruo",
314 "occuro", "odio", "olim", "oppeto", "os", "pagus", "pala", "paratus",
315 "patria", "paulatim", "pecus", "persto", "pertineo", "plaga", "pneum",
316 "populus", "praemitto", "praesent", "premo", "probo", "proprius",
317 "quadrum", "quae", "qui", "quia", "quibus", "quidem", "quidne", "quis",
318 "ratis", "refero", "refoveo", "roto", "rusticus", "saepius",
319 "sagaciter", "saluto", "scisco", "secundum", "sed", "si", "similis",
320 "singularis", "sino", "sit", "sudo", "suscipere", "suscipit", "tamen",
321 "tation", "te", "tego", "tincidunt", "torqueo", "tum", "turpis",
322 "typicus", "ulciscor", "ullamcorper", "usitas", "ut", "utinam",
323 "utrum", "uxor", "valde", "valetudo", "validus", "vel", "velit",
324 "veniam", "venio", "vereor", "vero", "verto", "vicis", "vindico",
325 "virtus", "voco", "volutpat", "vulpes", "vulputate", "wisi", "ymo",
326 "zelus");
327
328 $greeking = "";
329
330 if (!$title) {
331 while ($words > 0) {
332 $sentence_length = mt_rand(3,10);
333
334 $greeking .= ucfirst($dictionary[array_rand($dictionary)]);
335 for ($i = 1; $i < $sentence_length; $i++) {
336 $greeking .= " " . $dictionary[array_rand($dictionary)];
337 }
338
339 $greeking .= ". ";
340 $words -= $sentence_length;
341 }
342 }
343 else {
344 // use different method for titles
345 $title_length = $words;
346 $array = array();
347 for ($i = 0; $i < $words; $i++) {
348 $array[] = $dictionary[array_rand($dictionary)];
349 }
350 $greeking = ucwords(implode(' ', $array));
351 }
352 return $greeking;
353 }
354
355 function devel_generate_add_terms(&$node) {
356 $vocabs = taxonomy_get_vocabularies($node->type);
357 foreach ($vocabs as $vocab) {
358 $sql = "SELECT tid FROM {term_data} WHERE vid = %d ORDER BY RAND()";
359 $result = db_query_range($sql, $vocab->vid, 0, 5);
360 while ($row = db_fetch_object($result)) {
361 $node->taxonomy[] = $row->tid;
362 if (!$vocab->multiple) {
363 break;
364 }
365 }
366 }
367 }
368
369 function devel_get_users() {
370 $users = array();
371 $result = db_query_range("SELECT uid FROM {users}", 0, 50);
372 while($user = db_fetch_object($result)){
373 $users[] = $user->uid;
374 }
375 return $users;
376 }
377
378 function devel_generate_add_upload(&$node) {
379 $source = 'misc/blog.png';
380 $size = filesize($source);
381
382 // $after this call, $source contains the new path.
383 file_copy($source);
384 $file = new stdClass();
385 $file->filename = 'blog.png';
386 $file->filepath = $source;
387 $file->filemime = 'image/png';
388 $file->list = variable_get('upload_list_default', TRUE);
389 $file->description = 'b log.png was here';
390 $file->filesize = $size;
391 $file->weight = mt_rand(0,10);
392 $file->new = TRUE;
393
394 // If we made it this far it's safe to record this file in the database.
395 db_query("INSERT INTO {files} (uid, filename, filepath, filemime, filesize, status, timestamp) VALUES (%d, '%s', '%s', '%s', %d, %d, %d)", $node->uid, $file->filename, $file->filepath, $file->filemime, $file->filesize, FILE_STATUS_TEMPORARY, time());
396 $file->fid = db_last_insert_id('files', 'fid');
397 $node->files[$file->fid] = $file;
398 }
399
400 /**
401 * Generate statistics information for a node.
402 *
403 * @param $node
404 * A node object.
405 */
406 function devel_generate_add_statistics($node) {
407 $totalcount = mt_rand(0, 500);
408 $daycount = mt_rand(0, $totalcount);
409 $timestamp = time() - mt_rand(0, $node->created);
410 db_query('INSERT INTO {node_counter} (nid, daycount, totalcount, timestamp) VALUES (%d, %d, %d, %d)', $node->nid, $daycount, $totalcount, $timestamp);
411 }
412
413 /**
414 * Handle the devel_generate_content_form request to kill all of the content.
415 * This is used by both the batch and non-batch branches of the code.
416 *
417 * @param $num
418 * array of options obtained from devel_generate_content_form.
419 */
420 function devel_generate_content_kill($results) {
421 $sql = 'SELECT nid FROM {node} WHERE type IN ('. db_placeholders($results['node_types'], 'text'). ')';
422 $result = db_query($sql, $results['node_types']);
423 $i=0;
424 while ($row = db_fetch_object($result)) {
425 node_delete($row->nid);
426 $i++;
427 }
428 drupal_set_message(format_plural($i, 'Deleted one post', 'Deleted @count posts'));
429 }
430
431 /**
432 * Pre-process the devel_generate_content_form request. This is needed so
433 * batch api can get the list of users once. This is used by both the batch
434 * and non-batch branches of the code.
435 *
436 * @param $num
437 * array of options obtained from devel_generate_content_form.
438 */
439 function devel_generate_content_pre_node(&$results) {
440 // Get user id.
441 $users = devel_get_users();
442 $users = array_merge($users, array('0'));
443 $results['users'] = $users;
444 }
445
446 /**
447 * Create one node. This is used by both the batch and non-batch branches of
448 * the code.
449 *
450 * @param $num
451 * array of options obtained from devel_generate_content_form.
452 */
453 function devel_generate_content_add_node(&$results) {
454 // Insert new data:
455 $node->type = array_rand($results['node_types']);
456 module_load_include('inc', 'node', 'node.pages');
457 $type = node_get_types('type', $node->type);
458 node_object_prepare($node);
459 $users = $results['users'];
460 $node->uid = $users[array_rand($users)];
461
462 $node->title = devel_create_greeking(mt_rand(1, $results['title_length']), TRUE);
463 if ($type->has_body) {
464 $node->body = "node ($node->type) - ". devel_create_content();
465 $node->teaser = node_teaser($node->body);
466 $node->filter = variable_get('filter_default_format', 1);
467 $node->format = FILTER_FORMAT_DEFAULT;
468 }
469 $node->language = '';
470 $node->revision = mt_rand(0,1);
471 $node->promote = mt_rand(0, 1);
472 $node->created = time() - mt_rand(0, $results['time_range']);
473
474 // A flag to let hook_nodeapi() implementations know that this is a generated node.
475 $node->devel_generate = $results;
476 // See devel_generate_nodeapi() for actions that happen before and after this save.
477 node_save($node);
478
479 }
480
481 function devel_generate_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
482 if (isset($node->devel_generate)) {
483 $results = $node->devel_generate;
484 switch ($op) {
485 // Modules that want to affect generated nodes may implement hook_nodeapi('presave'). See OG module or CCK.
486 // A few implementations live here because core doesn't do bulk node generation.
487 case 'presave':
488 if ($results['add_upload']) {
489 devel_generate_add_upload($node);
490 }
491
492 if ($results['add_terms']) {
493 devel_generate_add_terms($node);
494 }
495 if (isset($results['add_language']) && variable_get('language_content_type_' . $node->type, 0)) {
496 $languages = array_keys($results['add_language']);
497 $node->language = $languages[array_rand($languages)];
498 }
499 break;
500 case 'insert':
501 if ($results['max_comments'] && $node->comment >= COMMENT_NODE_READ_WRITE) {
502 devel_generate_add_comments($node, $results['users'], $results['max_comments'], $results['title_length']);
503 }
504
505 // Add an url alias. Cannot happen before save becasue we don't know the nid.
506 if ($results['add_alias']) {
507 path_set_alias("node/$node->nid", "node-$node->nid-$node->type");
508 }
509
510 // Add node statistics.
511 if ($results['add_statistics']) {
512 devel_generate_add_statistics($node);
513 }
514 break;
515 }
516 }
517 }