| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @file 5 * Builds scaffolding for custom modules. 6 */ 7 8 /** 9 * In case we have an expanded CVS Id, this matches that, and captures the version number (although we don't use that). This is then replaced with MODULE_BUILDER_ID_COMMENT. 10 */ 11 define('MODULE_BUILDER_FULL_ID_PATTERN', '#\/\/ \$Id(.*?)\$#'); 12 /** 13 * Took this regex from the PHP manual page on Functions 14 */ 15 define('MODULE_BUILDER_FUNCTION_PATTERN', '#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*#'); 16 /** 17 * Path from module base to the normal hook groups template. MODULE_BUILDER_CUSTOM_HOOK_GROUPS_TEMPLATE_PATH used if it exists. 18 */ 19 define('MODULE_BUILDER_HOOK_GROUPS_TEMPLATE_PATH', '/templates/hook_groups.template'); 20 /** 21 * Path from module base to the custom hook groups template. Only used if it exists, otherwise MODULE_BUILDER_HOOK_GROUPS_TEMPLATE_PATH is used. 22 */ 23 define('MODULE_BUILDER_CUSTOM_HOOK_GROUPS_TEMPLATE_PATH', '/template/hook_groups-custom.template'); 24 /** 25 * Used to replace a full CVS Id tag with a starter ID. 26 */ 27 // The weird syntax stops this from getting mangled by CVS 28 define('MODULE_BUILDER_ID_COMMENT', '// $'.'Id$'); 29 30 31 /* Default default values for some variables */ 32 define('MODULE_BUILDER_HEADER_DEFAULT', '// $'.'Id$ 33 34 /** 35 * @file 36 * TODO: Enter file description here. 37 */ 38 '); 39 40 41 /** 42 * @defgroup module_builder_core Core Drupal hooks 43 */ 44 45 /** 46 * Implementation of hook_init(). 47 */ 48 function module_builder_init() { 49 // Set our environment. 50 define('MODULE_BUILDER_ENV', 'drupal'); 51 52 // Include common code. 53 include_once('./' . drupal_get_path('module', 'module_builder') . '/includes/common.inc'); 54 } 55 56 57 /** 58 * Implementation of hook_perm(). 59 * 60 * @ingroup module_builder_core 61 */ 62 function module_builder_perm() { 63 return array('access module builder'); 64 } 65 66 /** 67 * Implementation of hook_menu(). 68 * 69 * @ingroup module_builder_core 70 */ 71 function module_builder_menu() { 72 $items['admin/build/module_builder'] = array( 73 'title' => 'Module builder', 74 'description' => t('Builds scaffolding for custom modules.'), 75 'page callback' => 'drupal_get_form', 76 'page arguments' => array('module_builder_page'), 77 'file' => 'includes/module_builder.pages.inc', 78 'access arguments' => array('access module builder'), 79 'type' => MENU_NORMAL_ITEM, 80 ); 81 $items['admin/settings/module_builder'] = array( 82 'title' => 'Module builder', 83 'description' => t('Set default header and footer, api download location, defaults for detail and download and force the api to be re-downloaded.'), 84 'page callback' => 'drupal_get_form', 85 'page arguments' => array('module_builder_admin_settings'), 86 'file' => 'includes/module_builder.admin.inc', 87 'access arguments' => array('access module builder'), 88 'type' => MENU_NORMAL_ITEM, 89 ); 90 $items['admin/settings/module_builder/settings'] = array( 91 'title' => 'Settings', 92 'description' => t('Set default header and footer, folder locations, and defaults for detail.'), 93 'page callback' => 'drupal_get_form', 94 'page arguments' => array('module_builder_admin_settings'), 95 'file' => 'includes/module_builder.admin.inc', 96 'access arguments' => array('access module builder'), 97 'type' => MENU_DEFAULT_LOCAL_TASK, 98 ); 99 $items['admin/settings/module_builder/update'] = array( 100 'title' => 'Update hooks', 101 'description' => t('Download hook documentation.'), 102 'page callback' => 'drupal_get_form', 103 'page arguments' => array('module_builder_admin_update'), 104 'file' => 'includes/module_builder.admin.inc', 105 'access arguments' => array('access module builder'), 106 'type' => MENU_LOCAL_TASK, 107 ); 108 109 return $items; 110 } 111 112 113 /** 114 * Implementation of hook_theme. 115 */ 116 function module_builder_theme($existing, $type, $theme, $path) { 117 return array( 118 'module_builder_hook_list' => array( 119 'arguments' => array('form' => array()), 120 ), 121 ); 122 } 123 124 125 126 ############################# old code below here 127 128 129 130 /** 131 * This still needs some work. Set a bunch of check boxes, forward, back, uncheck 132 * the boxes, forward and back and the boxes get turned back on for some reason. 133 * Otherwise this seems pretty good. 134 */ 135 function _module_builder_save_old_form_values($form, $form_values, $indent='') { 136 static $excludes; 137 138 if (!isset($excludes)) { 139 $excludes = array('op', 'form_build_id', 'form_token', 'form_id', 'generate_module', 'module_code', 'module_info'); 140 } 141 if (isset($form['#multistep_excludes']) && is_array($form['#multistep_excludes'])) { 142 $excludes = array_merge($excludes, $form['#multistep_excludes']); 143 } 144 if (isset($form_values)) { 145 foreach ($form_values as $key => $value) { 146 //print_r($indent . $key .' => '. $value ."\n"); 147 $include = !in_array($key, $excludes); 148 if ($include) { 149 if (is_array($value)) { 150 if (!isset($form[$key])) { 151 $form[$key] = array(); 152 } 153 $form[$key] = _module_builder_save_old_form_values($form[$key], $value, $indent .' '); 154 $form[$key]['#tree'] = TRUE; 155 } 156 else { 157 if (isset($form[$key])) { 158 $form[$key]['#value'] = $value; 159 } 160 else { 161 $form[$key] = array( 162 '#type' => 'hidden', 163 '#value' => $value, 164 ); 165 } 166 } 167 } 168 } 169 } 170 171 return $form; 172 } 173 174 /** 175 * Module form: 'input' step. Collect module data. 176 */ 177 function Xmodule_builder_page_input($form, $form_values) { 178 179 _module_builder_check_settings(); 180 181 // Include CSS for formatting 182 drupal_add_css(drupal_get_path('module', 'module_builder') . '/theme/module_builder.css'); 183 184 // Module properties 185 $form['module_root_name'] = array( 186 '#type' => 'textfield', 187 '#title' => t('Machine-readable name'), 188 '#description' => t('This string is used to name the module files and to prefix all of your functions. This must only contain letters, numbers, and underscores, and may not start with a number.'), 189 '#required' => TRUE, 190 '#default_value' => 'mymodule', 191 ); 192 $form['module_readable_name'] = array( 193 '#type' => 'textfield', 194 '#title' => t('Name'), 195 '#description' => t('Name of your module as it will appear on the module admin page.'), 196 '#required' => TRUE, 197 '#default_value' => 'My Module', 198 ); 199 $form['module_short_description'] = array( 200 '#type' => 'textfield', 201 '#title' => t('Description'), 202 '#description' => t('This text will appear in the module listing at <a href="!listing">%administer >> %build >> %modules</a>.', array('!listing' => url('admin/build/modules'), '%administer' => 'Administer', '%build' => 'Site building', '%modules' => 'Modules')), 203 '#required' => TRUE, 204 '#default_value' => 'Does awesome things. Makes tea. Washes up. Favours of a personal nature.', 205 ); 206 $form['module_help_text'] = array( 207 '#type' => 'textarea', 208 '#title' => t('Help text'), 209 '#description' => t('Help text (HTML) to appear in <a href="!help">%administer >> %help >> module_name</a> page.', array('!help' => url('admin/help'), '%administer' => 'Administer', '%help' => 'Help')), 210 ); 211 $form['module_dependencies'] = array( 212 '#type' => 'textfield', 213 '#title' => t('Dependencies'), 214 '#description' => t('Space seperated list of other modules that your module requires.'), 215 ); 216 $form['module_package'] = array( 217 '#type' => 'textfield', 218 '#title' => t('Package'), 219 '#description' => t('If your module comes with other modules or is meant to be used exclusively with other modules, enter the package name here. Suggested package names: Audio, Bot, CCK, Chat, E-Commerce, Event, Feed parser, Organic groups, Station, Video, Views and Voting.'), 220 ); 221 222 // Check for custom hook_groups file, else use default 223 $path = drupal_get_path('module', 'module_builder'); 224 if (file_exists($path . MODULE_BUILDER_CUSTOM_HOOK_GROUPS_TEMPLATE_PATH)) { 225 $template_file = file_get_contents($path . MODULE_BUILDER_CUSTOM_HOOK_GROUPS_TEMPLATE_PATH); 226 } 227 else { 228 $template_file = file_get_contents($path . MODULE_BUILDER_HOOK_GROUPS_TEMPLATE_PATH); 229 } 230 231 $form['hook_groups'] = array( 232 '#type' => 'fieldset', 233 '#title' => t('Hook groupings'), 234 '#description' => t('Selecting one or more of these features will automatically select appropriate hooks for you.'), 235 ); 236 237 drupal_add_js($path . '/theme/module_builder.js'); 238 239 // Get list of hook groups from installed template. 240 // Include generating component file. 241 module_builder_include('process'); 242 $hook_groups = module_builder_parse_template($template_file); 243 foreach ($hook_groups as $hook_group_name => $hook_group) { 244 $hooks = explode("\n", $hook_group['template']); 245 $hook_array = array(); 246 foreach ($hooks as $hook) { 247 $hook = trim($hook); 248 if (!empty($hook)) { 249 $hook_array[] = "'$hook'"; 250 } 251 } 252 253 $form['hook_groups']['groups-'. $hook_group_name] = array( 254 '#type' => 'checkbox', 255 '#title' => $hook_group_name, 256 '#attributes' => array( 257 'onclick' => 'check_hooks(this, ['. implode(', ', $hook_array) .'])', 258 ), 259 //'#description' => $hook_groups[$i]['data'], 260 261 // TODO: For some reason this gives me some wacky error under PHP 5: 262 // Fatal error: Cannot use string offset as an array 263 //'#default_value' => $edit['hook_groups'][$i], 264 ); 265 } 266 267 // Get list of hooks from downloaded documentation, organized in fieldsets. 268 $hook_groups = module_builder_get_hook_data(); 269 270 if (!is_array($hook_groups) || !count($hook_groups)) { 271 form_set_error('hooks', t('No hooks were found. Please check the documentation path specified in the <a href="!settings">%administer >> %settings >> %modulebuilder</a> page.', array('!settings' => url('admin/settings/module_builder/update'), '%administer' => 'Administer', '%settings' => 'Site configuration', '%modulebuilder' => "Module builder"))); 272 } 273 else { 274 275 // Build hooks list 276 $form['hooks'] = array( 277 '#type' => 'checkboxes', 278 '#title' => t('Use the following specific hooks'), 279 ); 280 281 foreach ($hook_groups as $hook_group => $hooks) { 282 $form['hooks'][$hook_group] = array( 283 '#type' => 'fieldset', 284 '#title' => $hook_group .' hooks', 285 '#collapsible' => TRUE, 286 '#collapsed' => TRUE, 287 '#theme' => 'module_builder_hook_list', 288 ); 289 foreach ($hooks as $hook) { 290 $name = $hook['name']; 291 $desc = $hook['description']; 292 $form['hooks'][$hook_group][$name] = array( 293 '#type' => 'checkbox', 294 '#title' => str_replace('hook_', '', $name), 295 '#description' => $desc, 296 297 // TODO: For some reason this gives me some wacky error under PHP 5: 298 // Fatal error: Cannot use string offset as an array 299 //'#default_value' => $edit['hooks'][$hook_group][$hook], 300 301 // TODO: I would *like* to do something like the following, so some of the long 302 // descriptions don't totally mangle the page output, but need a way to do like 303 // a "onmouseover" effect to display the full thing. Note that 'title' is not 304 // a valid attribute for divs. :\ 305 //'#description' => truncate_utf8($desc, 40, TRUE, TRUE), 306 307 ); 308 // Set some default hooks 309 if ($name == 'hook_menu') { 310 $form['hooks'][$hook_group][$name]['#default_value'] = 1; 311 } 312 } 313 // Sort list alphabetically 314 ksort($form['hooks'][$hook_group]); 315 } 316 317 /* 318 $form['download'] = array( 319 '#type' => 'checkbox', 320 '#title' => t('Automatically generate module file for download?'), 321 '#description' => t('When checked, this will automatically generate your module file for you and prompt your browser to download it.'), 322 '#default_value' => variable_get('module_builder_download', 1), 323 ); 324 */ 325 $form['generate_module'] = array( 326 '#type' => 'submit', 327 '#name' => 'op', 328 '#value' => t('Generate'), 329 ); 330 } 331 332 return $form; 333 } 334 335 336 /** 337 * Module form: 'module' step. Generate the module code. 338 */ 339 function Xmodule_builder_page_module($form, $form_values) { 340 341 // Include link in breadcrumb to go back to main module builder form 342 /* 343 $breadcrumb = drupal_get_breadcrumb(); 344 $breadcrumb[] = l(t('Module builder'), 'module_builder'); 345 drupal_set_breadcrumb($breadcrumb); 346 */ 347 348 $code = $form_values['module_code'] ? $form_values['module_code'] : module_builder_generate_module($form_values); 349 $info = $form_values['module_info'] ? $form_values['module_info'] : module_builder_generate_info($form_values) ; 350 // damn I miss perl at times like this. fugly syntax. 351 352 $form['back'] = array( 353 '#type' => 'submit', 354 '#name' => 'op', 355 '#value' => t('Back'), 356 ); 357 $form['code_instructions'] = array( 358 '#value' => t('Please copy and paste the following text into a file called !module.', array('!module' => $form_values['module_root_name'] .'.module')), 359 '#prefix' => '<div id="module-message">', 360 '#suffix' => '</div>', 361 ); 362 $form['module_code'] = array( 363 '#type' => 'textarea', 364 '#title' => t('Module code'), 365 '#rows' => 20, 366 '#default_value' => $code, 367 '#prefix' => '<div id="module-code">', 368 '#suffix' => '</div>', 369 ); 370 $form['download_module'] = array( 371 '#type' => 'submit', 372 '#name' => 'op', 373 '#value' => t('Download module'), 374 ); 375 $form['write_module'] = array( 376 '#type' => 'button', 377 '#value' => t('Write module file'), 378 ); 379 380 $form['info_instructions'] = array( 381 '#value' => t('Please copy and paste the following text into a file called !module.', array('!module' => $form_values['module_root_name'] .'.info')), 382 '#prefix' => '<div id="module-message">', 383 '#suffix' => '</div>', 384 ); 385 $form['module_info'] = array( 386 '#type' => 'textarea', 387 '#title' => t('Module info'), 388 '#rows' => 20, 389 '#default_value' => $info, 390 '#prefix' => '<div id="module-info">', 391 '#suffix' => '</div>', 392 ); 393 $form['download_info'] = array( 394 '#type' => 'submit', 395 '#name' => 'op', 396 '#value' => t('Download info file'), 397 ); 398 $form['write_info'] = array( 399 '#type' => 'button', 400 '#value' => t('Write info file'), 401 ); 402 $form['#multistep_excludes'] = array('module_code', 'module_info'); 403 404 // handle the write buttons 405 $form['#after_build'] = array('module_builder_write_buttons'); 406 407 return $form; 408 } 409 410 /** 411 * Module form: 'download' step. Download the files. 412 */ 413 function Xmodule_builder_page_download($form, $form_values) { 414 $file_content = ''; 415 $file_ext = '.txt'; 416 if ($form_values['op'] == t('Download module')) { 417 $file_content = $form_values['module_code']; 418 $file_ext = '.module'; 419 } 420 elseif ($form_values['op'] == t('Download info file')) { 421 $file_content = $form_values['module_info']; 422 $file_ext = '.info'; 423 } 424 else { 425 form_set_error('Problem creating file for download.'); 426 drupal_goto('module_builder'); 427 } 428 429 if (strlen($file_content) > 0) { 430 $file_name = $form_values['module_root_name'] . $file_ext; 431 header("Content-disposition: attachment; filename=$file_name"); 432 header('Content-Type: application/force-download'); 433 header('Content-Transfer-Encoding: binary'); 434 header('Content-Length: '. strlen($file_content)); 435 header('Pragma: no-cache'); 436 header('Expires: 0'); 437 echo $file_content; 438 exit(); 439 } 440 } 441 442 /* 443 $form['#after_build'] = array('module_builder_write_buttons'); 444 */ 445 /** 446 * Form after build callback. 447 * If update button was clicked, update hooks documentation. Rest of form is not submitted. 448 * Cribbed from node_form_add_preview() 449 */ 450 function Xmodule_builder_write_buttons($form) { 451 static $been_here = FALSE; // ugly but I'm going round in circles trying to figure out how best to do this 452 if ($been_here) { 453 return $form; 454 } 455 $been_here = TRUE; 456 457 global $form_values; 458 459 $op = isset($form_values['op']) ? $form_values['op'] : ''; 460 461 if ($op == t('Write module file')) { 462 _module_builder_write_file($form_values['module_root_name'], '.module', $form_values['module_code']); 463 } 464 elseif ($op == t('Write info file')) { 465 _module_builder_write_file($form_values['module_root_name'], '.info', $form_values['module_info']); 466 } 467 468 return $form; 469 } 470 471 /** 472 * Helper function to write files 473 * saves moving this code while mucking about with different formsAPI approaches & quicker to shortcircuit 474 */ 475 function _module_builder_write_file($basename, $extension, $content) { 476 if (strlen($content) == 0) { 477 return; 478 } 479 480 $directory = file_create_path(variable_get('module_builder_module_write_directory', 'modules') .'/'. $basename); 481 file_check_directory($directory, FILE_CREATE_DIRECTORY); 482 $file_name = $basename . $extension; 483 484 $created_file = file_save_data($content, "$directory/$file_name", FILE_EXISTS_REPLACE); 485 486 if ($created_file) { 487 drupal_set_message(t("File @file has been written.", array('@file' => $created_file))); 488 } 489 else { 490 drupal_set_message(t("There was a problem writing the file @file.", array('@file' => "$directory/$file_name")), 'error'); 491 } 492 } 493 494 /** 495 * Module form: 'write' step 496 */ 497 function Xmodule_builder_page_write($form, $form_values) { 498 ####### bug!!!!!!!!! 499 dpr('writing page: ' . $form_values['op']); 500 501 if ($form_values['op'] == t('Write module file')) { 502 _module_builder_write_file($form_values['module_root_name'], '.module', $form_values['module_code']); 503 } 504 elseif ($form_values['op'] == t('Write info file')) { 505 _module_builder_write_file($form_values['module_root_name'], '.info', $form_values['module_info']); 506 } 507 else { 508 form_set_error('Problem creating file for writing.'); 509 drupal_goto('module_builder'); 510 } 511 512 if (strlen($file_content) > 0) { 513 $directory = file_create_path(variable_get('module_builder_module_write_directory', 'modules') .'/'. $form_values['module_root_name']); 514 file_check_directory($directory, FILE_CREATE_DIRECTORY); 515 $file_name = $form_values['module_root_name'] . $file_ext; 516 517 $created_file = file_save_data($file_content, "$directory/$file_name", FILE_EXISTS_REPLACE); 518 519 if ($created_file) { 520 drupal_set_message(t("File @file has been written.", array('@file' => $created_file))); 521 } 522 else { 523 drupal_set_message(t("There was a problem writing the file @file.", array('@file' => "$directory/$file_name")), 'error'); 524 } 525 } 526 527 // return to the module step to write or download some more. 528 //return module_builder_page_module($form, $form_values); 529 530 return $form; 531 } 532 533 /** 534 * Makes sure that valid values have been provided to the Module Builder. 535 * 536 * @ingroup module_builder_callback 537 */ 538 function Xmodule_builder_page_validate($form, &$form_state) { 539 # TODO 540 if ($form_values['op'] == 'input') { 541 // Ensure module_root_name was entered, and check for special characters 542 if (!empty($form_values['module_root_name'])) { 543 if (!preg_match(MODULE_BUILDER_FUNCTION_PATTERN, $form_values['module_root_name'])) { 544 form_set_error('module_root_name', t('The module root name must only contain letters, numbers, and underscores, and may not start with a number.')); 545 } 546 } 547 548 // Make sure at least one hook was chosen 549 $hook_selected = FALSE; 550 foreach ($form_values['hooks'] as $file => $hooks) { 551 foreach ($hooks as $hook) { 552 if ($hook == 1) { 553 $hook_selected = TRUE; 554 break; 555 } 556 } 557 if ($hook_selected) { 558 break; 559 } 560 } 561 if (!$hook_selected) { 562 form_set_error('hooks', t('You must select at least one hook.')); 563 } 564 } 565 } 566 ###################################################### end old code 567
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |