| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @file 5 * Menu callback for main module builder page. 6 * 7 */ 8 9 /** 10 * @defgroup module_builder_callback Functions which are the menu callbacks for this module 11 */ 12 13 /** 14 * Displays module builder interface via a multi-step form. 15 * The steps are: 16 * 17 * - input => shows a form where the user can enter module options. 18 * - module => shows the generated module and info files. 19 * - download => pushes a file for download. 20 * - write => writes files. 21 * 22 * @ingroup module_builder_callback 23 * @param $form_values will be NULL when the page is first displayed, 24 * when the form is submitted, this will be an array of the submitted 25 * values. 26 * @return 27 * One of three results depending on the state of this multi-step form. 28 * Form for entering module options 29 * Form showing built module and info file 30 * Nothing, but file is pushed to client for download 31 */ 32 # fun fun fun! 33 # http://drupal.org/node/144132 34 function module_builder_page($form_state) { 35 $step = 'input'; 36 if (isset($form_state['clicked_button'])) { 37 $step = $form_state['clicked_button']['#name']; 38 } 39 #dsm($step); 40 switch ($step) { 41 case 'input': 42 // sanity check first time around 43 _module_builder_check_settings(); 44 // fall through 45 case 'back': 46 $form = module_builder_page_input($form_state); 47 break; 48 case 'generate': 49 $form = module_builder_page_generate($form_state); 50 break; 51 case 'download': 52 $form = module_builder_page_download($form_state); 53 break; 54 } 55 56 return $form; 57 } 58 59 // build page 1 60 function module_builder_page_input($form_state) { 61 /* 62 // built some default values. 63 // these are either hardcoded or what the user already put into the form on a previous go round. 64 $form_default_values = array( 65 'module_root_name' => 'mymodule', 66 ); 67 if (isset($form_state['storage']['input'])) { 68 $form_default_values = array_merge($form_default_values, $form_state['storage']['input']); 69 } 70 71 #dsm($form_default_values); 72 #dsm($form_state['storage']['input']); 73 dsm($form_state); 74 */ 75 76 // sanity check first time around 77 #_module_builder_check_settings(); // moved up to main form builder 78 // Get list of hooks from downloaded documentation, organized in fieldsets. 79 // include the data processing file 80 // TODO: only need the data loading. 81 module_builder_include('process'); 82 83 $hook_groups = module_builder_get_hook_data(); 84 if (!is_array($hook_groups) || !count($hook_groups)) { 85 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'), '%administer' => 'Administer', '%settings' => 'Site configuration', '%modulebuilder' => "Module builder"))); 86 return $form; 87 } 88 89 // Include CSS for formatting 90 drupal_add_css(drupal_get_path('module', 'module_builder') . '/theme/module_builder.css'); 91 92 // Mark form as fresh to enable JS clearing of fields with sample text. 93 if ($form_state['clicked_button']['#name'] != 'back') { 94 $form['#attributes'] = array('class' => 'fresh'); 95 } 96 97 // Module properties 98 $form['module_root_name'] = array( 99 '#type' => 'textfield', 100 '#title' => t('Machine-readable name'), 101 '#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.'), 102 '#required' => TRUE, 103 '#default_value' => t('mymodule'), # $form_default_values['module_root_name'], 104 '#repopulate' => TRUE, 105 ); 106 $form['module_readable_name'] = array( 107 '#type' => 'textfield', 108 '#title' => t('Name'), 109 '#description' => t('Name of your module as it will appear on the module admin page.'), 110 '#required' => TRUE, 111 '#default_value' => t('My Module'), 112 '#repopulate' => TRUE, 113 ); 114 $form['module_short_description'] = array( 115 '#type' => 'textfield', 116 '#title' => t('Description'), 117 '#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')), 118 '#required' => TRUE, 119 '#default_value' => t('Does awesome things. Makes tea. Washes up. Favours of a personal nature.'), 120 '#repopulate' => TRUE, 121 ); 122 $form['module_help_text'] = array( 123 '#type' => 'textarea', 124 '#title' => t('Help text'), 125 '#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')), 126 '#repopulate' => TRUE, 127 ); 128 $form['module_dependencies'] = array( 129 '#type' => 'textfield', 130 '#title' => t('Dependencies'), 131 '#description' => t('Space seperated list of other modules that your module requires.'), 132 '#repopulate' => TRUE, 133 ); 134 $form['module_package'] = array( 135 '#type' => 'textfield', 136 '#title' => t('Package'), 137 '#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.'), 138 '#repopulate' => TRUE, 139 ); 140 141 // Check for custom hook_groups file, else use default 142 $path = drupal_get_path('module', 'module_builder'); 143 if (file_exists($path . MODULE_BUILDER_CUSTOM_HOOK_GROUPS_TEMPLATE_PATH)) { 144 $template_file = file_get_contents($path . MODULE_BUILDER_CUSTOM_HOOK_GROUPS_TEMPLATE_PATH); 145 } 146 else { 147 $template_file = file_get_contents($path . MODULE_BUILDER_HOOK_GROUPS_TEMPLATE_PATH); 148 } 149 150 $form['hook_groups'] = array( 151 '#type' => 'fieldset', 152 '#title' => t('Hook groupings'), 153 '#description' => t('Selecting one or more of these features will automatically select appropriate hooks for you.'), 154 ); 155 156 drupal_add_js($path . '/theme/module_builder.js'); 157 158 // Get list of hook presets from installed template. 159 // Include generating component file. 160 module_builder_include('process'); 161 $hook_presets = module_builder_parse_template($template_file); 162 foreach ($hook_presets as $hook_preset_name => $hook_preset) { 163 $hooks = explode("\n", $hook_preset['template']); 164 $hook_array = array(); 165 foreach ($hooks as $hook) { 166 $hook = trim($hook); 167 if (!empty($hook)) { 168 $hook_array[] = "'$hook'"; 169 } 170 } 171 172 $form['hook_groups']['groups-'. $hook_preset_name] = array( 173 '#type' => 'checkbox', 174 '#title' => $hook_preset_name, 175 '#attributes' => array( 176 'onclick' => 'check_hooks(this, ['. implode(', ', $hook_array) .'])', 177 ), 178 //'#description' => $hook_groups[$i]['data'], 179 180 // TODO: For some reason this gives me some wacky error under PHP 5: 181 // Fatal error: Cannot use string offset as an array 182 //'#default_value' => $edit['hook_groups'][$i], 183 ); 184 } 185 186 187 // Build hooks list 188 $form['hooks'] = array( 189 '#type' => 'checkboxes', 190 '#title' => t('Use the following specific hooks'), 191 // '#description' => '(Note that for now, only core and node hooks will be generated: for the others use drush.)', 192 ); 193 194 foreach ($hook_groups as $hook_group => $hooks) { 195 $form['hooks'][$hook_group] = array( 196 '#type' => 'fieldset', 197 '#title' => $hook_group .' hooks', 198 '#collapsible' => TRUE, 199 '#collapsed' => TRUE, 200 '#theme' => 'module_builder_hook_list', 201 ); 202 foreach ($hooks as $hook) { 203 $name = $hook['name']; 204 $desc = $hook['description']; 205 $form['hooks'][$hook_group][$name] = array( 206 '#type' => 'checkbox', 207 '#title' => preg_replace('/^hook_/', '', $name), 208 '#description' => $desc, 209 '#repopulate' => TRUE, 210 211 212 // TODO: For some reason this gives me some wacky error under PHP 5: 213 // Fatal error: Cannot use string offset as an array 214 //'#default_value' => $edit['hooks'][$hook_group][$hook], 215 216 // TODO: I would *like* to do something like the following, so some of the long 217 // descriptions don't totally mangle the page output, but need a way to do like 218 // a "onmouseover" effect to display the full thing. Note that 'title' is not 219 // a valid attribute for divs. :\ 220 //'#description' => truncate_utf8($desc, 40, TRUE, TRUE), 221 222 ); 223 // Set some default hooks 224 if ($name == 'hook_menu') { 225 $form['hooks'][$hook_group][$name]['#default_value'] = 1; 226 } 227 } 228 // Sort list alphabetically 229 ksort($form['hooks'][$hook_group]); 230 } 231 232 $form['generate_module'] = array( 233 '#type' => 'submit', 234 '#name' => 'generate', 235 '#value' => t('Generate'), 236 ); 237 $form['#submit'] = array('module_builder_page_input_submit'); 238 239 #if ($form_state['rebuild']) { // fails as a test!?!?! 240 if ($form_state['values']) { 241 #dsm('rebuild'); 242 $form = _form_repopulate($form, $form_state); 243 #dsm($form_state['storage']['input']); 244 } 245 246 return $form; 247 } 248 249 /** 250 * Repopulate form with user values. 251 */ 252 function _form_repopulate($form, $form_state) { 253 #dsm($form); 254 #dsm(element_children($form)); 255 #dsm($form_state); 256 foreach (element_children($form) as $key) { 257 if (isset($form[$key]['#repopulate'])) { 258 #dsm('repop: '); 259 #dsm($key); 260 #$form[$key]['#default_value'] = 'repop!'; // this obviously works 261 #$form[$key]['#default_value'] = $form_state['values'][$key]; // arg! here we only have values from page 2! 262 $form[$key]['#default_value'] = $form_state['storage']['input'][$key]; // this obviously works 263 } 264 // recurse into children 265 $form[$key] = _form_repopulate($form[$key], $form_state); 266 } // each element_children 267 return $form; 268 } 269 270 271 /** 272 * Theme function for hook list 273 */ 274 function theme_module_builder_hook_list($form) { 275 $output = "<ul class=\"hook-group clear-block\">\n"; 276 foreach (element_children($form) as $key) { 277 $output .= " <li>". drupal_render($form[$key]) ."</li>\n"; 278 } 279 $output .= "</ul>\n"; 280 return $output; 281 } 282 283 284 /** 285 * submit page 1 286 */ 287 function module_builder_page_input_submit($form, &$form_state) { 288 $form_state['rebuild'] = TRUE; 289 290 // stash input.... these values will follow us around everywhere like a little dog... 291 $form_state['storage']['input'] = $form_state['values']; 292 foreach (array('generate', 'generate_module', 'form_build_id', 'form_token', 'form_id') as $key) { 293 unset($form_state['storage']['input'][$key]); 294 } 295 } 296 297 /** 298 * page 2: generate code 299 */ 300 function module_builder_page_generate($form_state) { 301 module_builder_include('generate'); 302 303 // Build module data 304 $module_data = module_data_from_form($form_state['values']); 305 306 $code_array = module_builder_generate_module($module_data); 307 //dsm($code_array); 308 309 /* 310 // the restitution was all for the DL buttons, no? 311 // these should be ajaxy! 312 if ($form_state['values']['module_code']) { 313 $code = $form_state['values']['module_code']; 314 } 315 else { 316 // Bit messy. This returns an array now. 317 // TODO: the other files! 318 $code_array = module_builder_generate_module($module_data); 319 320 $code = $code_array[$module_data['module_root_name'] . '.module']; 321 } 322 */ 323 module_builder_include('generate_info'); 324 $info = $form_state['values']['module_info'] ? $form_state['values']['module_info'] : module_builder_generate_info($module_data); 325 // damn I miss perl at times like this. fugly syntax. 326 327 $form['back'] = array( 328 '#type' => 'submit', 329 '#value' => t('Back'), 330 '#name' => 'back', 331 ); 332 333 foreach ($code_array as $filename => $code) { 334 $form['code_instructions_' . $filename] = array( 335 '#value' => t('Please copy and paste the following text into a file called !module.', array('!module' => $filename)), 336 '#prefix' => '<div class="module-message">', 337 '#suffix' => '</div>', 338 ); 339 $form['module_code_' . $filename] = array( 340 '#type' => 'textarea', 341 '#title' => t($filename .' code'), 342 '#rows' => 20, 343 '#default_value' => $code, 344 '#prefix' => '<div class="module-code">', 345 '#suffix' => '</div>', 346 ); 347 } 348 349 /* 350 $form['code_instructions'] = array( 351 '#value' => t('Please copy and paste the following text into a file called !module.', array('!module' => $form_state['values']['module_root_name'] .'.module')), 352 '#prefix' => '<div id="module-message">', 353 '#suffix' => '</div>', 354 ); 355 $form['module_code'] = array( 356 '#type' => 'textarea', 357 '#title' => t('Module code'), 358 '#rows' => 20, 359 '#default_value' => $code, 360 '#prefix' => '<div id="module-code">', 361 '#suffix' => '</div>', 362 ); 363 */ 364 /* 365 $form['download_module'] = array( 366 '#type' => 'submit', 367 '#value' => t('Download module'), 368 ); 369 $form['write_module'] = array( 370 '#type' => 'button', 371 '#value' => t('Write module file'), 372 ); 373 */ 374 375 $form['info_instructions'] = array( 376 '#value' => t('Please copy and paste the following text into a file called !module.', array('!module' => $form_state['values']['module_root_name'] .'.info')), 377 '#prefix' => '<div id="module-message">', 378 '#suffix' => '</div>', 379 ); 380 $form['module_info'] = array( 381 '#type' => 'textarea', 382 '#title' => t('Module info'), 383 '#rows' => 20, 384 '#default_value' => $info, 385 '#prefix' => '<div id="module-info">', 386 '#suffix' => '</div>', 387 ); 388 /* 389 $form['download_info'] = array( 390 '#type' => 'submit', 391 '#name' => 'op', 392 '#value' => t('Download info file'), 393 ); 394 $form['write_info'] = array( 395 '#type' => 'button', 396 '#value' => t('Write info file'), 397 ); 398 */ 399 400 // handle the write buttons 401 ## $form['#after_build'] = array('module_builder_write_buttons'); 402 403 return $form; 404 } 405 406 /** 407 * Helper function: creates an array of all the data needed to build the module 408 * from form values, suitable for passing to module_builder_generate_module(). 409 */ 410 function module_data_from_form($form_values) { 411 // Most things come in as we want them from the form. 412 $data = $form_values; 413 414 // Hooks need flattening. 415 $data['hooks'] = array(); 416 foreach ($form_values['hooks'] as $hook_group) { 417 $data['hooks'] += $hook_group; 418 } 419 420 return $data; 421 }
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 |