'Module builder', 'description' => t('Builds scaffolding for custom modules.'), 'page callback' => 'drupal_get_form', 'page arguments' => array('module_builder_page'), 'file' => 'includes/module_builder.pages.inc', 'access arguments' => array('access module builder'), 'type' => MENU_NORMAL_ITEM, ); $items['admin/settings/module_builder'] = array( 'title' => 'Module builder', 'description' => t('Set default header and footer, api download location, defaults for detail and download and force the api to be re-downloaded.'), 'page callback' => 'drupal_get_form', 'page arguments' => array('module_builder_admin_settings'), 'file' => 'includes/module_builder.admin.inc', 'access arguments' => array('access module builder'), 'type' => MENU_NORMAL_ITEM, ); $items['admin/settings/module_builder/settings'] = array( 'title' => 'Settings', 'description' => t('Set default header and footer, folder locations, and defaults for detail.'), 'page callback' => 'drupal_get_form', 'page arguments' => array('module_builder_admin_settings'), 'file' => 'includes/module_builder.admin.inc', 'access arguments' => array('access module builder'), 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items['admin/settings/module_builder/update'] = array( 'title' => 'Update hooks', 'description' => t('Download hook documentation.'), 'page callback' => 'drupal_get_form', 'page arguments' => array('module_builder_admin_update'), 'file' => 'includes/module_builder.admin.inc', 'access arguments' => array('access module builder'), 'type' => MENU_LOCAL_TASK, ); return $items; } /** * Implementation of hook_theme. */ function module_builder_theme($existing, $type, $theme, $path) { return array( 'module_builder_hook_list' => array( 'arguments' => array('form' => array()), ), ); } ############################# old code below here /** * This still needs some work. Set a bunch of check boxes, forward, back, uncheck * the boxes, forward and back and the boxes get turned back on for some reason. * Otherwise this seems pretty good. */ function _module_builder_save_old_form_values($form, $form_values, $indent='') { static $excludes; if (!isset($excludes)) { $excludes = array('op', 'form_build_id', 'form_token', 'form_id', 'generate_module', 'module_code', 'module_info'); } if (isset($form['#multistep_excludes']) && is_array($form['#multistep_excludes'])) { $excludes = array_merge($excludes, $form['#multistep_excludes']); } if (isset($form_values)) { foreach ($form_values as $key => $value) { //print_r($indent . $key .' => '. $value ."\n"); $include = !in_array($key, $excludes); if ($include) { if (is_array($value)) { if (!isset($form[$key])) { $form[$key] = array(); } $form[$key] = _module_builder_save_old_form_values($form[$key], $value, $indent .' '); $form[$key]['#tree'] = TRUE; } else { if (isset($form[$key])) { $form[$key]['#value'] = $value; } else { $form[$key] = array( '#type' => 'hidden', '#value' => $value, ); } } } } } return $form; } /** * Module form: 'input' step. Collect module data. */ function Xmodule_builder_page_input($form, $form_values) { _module_builder_check_settings(); // Include CSS for formatting drupal_add_css(drupal_get_path('module', 'module_builder') . '/theme/module_builder.css'); // Module properties $form['module_root_name'] = array( '#type' => 'textfield', '#title' => t('Machine-readable name'), '#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.'), '#required' => TRUE, '#default_value' => 'mymodule', ); $form['module_readable_name'] = array( '#type' => 'textfield', '#title' => t('Name'), '#description' => t('Name of your module as it will appear on the module admin page.'), '#required' => TRUE, '#default_value' => 'My Module', ); $form['module_short_description'] = array( '#type' => 'textfield', '#title' => t('Description'), '#description' => t('This text will appear in the module listing at %administer >> %build >> %modules.', array('!listing' => url('admin/build/modules'), '%administer' => 'Administer', '%build' => 'Site building', '%modules' => 'Modules')), '#required' => TRUE, '#default_value' => 'Does awesome things. Makes tea. Washes up. Favours of a personal nature.', ); $form['module_help_text'] = array( '#type' => 'textarea', '#title' => t('Help text'), '#description' => t('Help text (HTML) to appear in %administer >> %help >> module_name page.', array('!help' => url('admin/help'), '%administer' => 'Administer', '%help' => 'Help')), ); $form['module_dependencies'] = array( '#type' => 'textfield', '#title' => t('Dependencies'), '#description' => t('Space seperated list of other modules that your module requires.'), ); $form['module_package'] = array( '#type' => 'textfield', '#title' => t('Package'), '#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.'), ); // Check for custom hook_groups file, else use default $path = drupal_get_path('module', 'module_builder'); if (file_exists($path . MODULE_BUILDER_CUSTOM_HOOK_GROUPS_TEMPLATE_PATH)) { $template_file = file_get_contents($path . MODULE_BUILDER_CUSTOM_HOOK_GROUPS_TEMPLATE_PATH); } else { $template_file = file_get_contents($path . MODULE_BUILDER_HOOK_GROUPS_TEMPLATE_PATH); } $form['hook_groups'] = array( '#type' => 'fieldset', '#title' => t('Hook groupings'), '#description' => t('Selecting one or more of these features will automatically select appropriate hooks for you.'), ); drupal_add_js($path . '/theme/module_builder.js'); // Get list of hook groups from installed template. // Include generating component file. module_builder_include('process'); $hook_groups = module_builder_parse_template($template_file); foreach ($hook_groups as $hook_group_name => $hook_group) { $hooks = explode("\n", $hook_group['template']); $hook_array = array(); foreach ($hooks as $hook) { $hook = trim($hook); if (!empty($hook)) { $hook_array[] = "'$hook'"; } } $form['hook_groups']['groups-'. $hook_group_name] = array( '#type' => 'checkbox', '#title' => $hook_group_name, '#attributes' => array( 'onclick' => 'check_hooks(this, ['. implode(', ', $hook_array) .'])', ), //'#description' => $hook_groups[$i]['data'], // TODO: For some reason this gives me some wacky error under PHP 5: // Fatal error: Cannot use string offset as an array //'#default_value' => $edit['hook_groups'][$i], ); } // Get list of hooks from downloaded documentation, organized in fieldsets. $hook_groups = module_builder_get_hook_data(); if (!is_array($hook_groups) || !count($hook_groups)) { form_set_error('hooks', t('No hooks were found. Please check the documentation path specified in the %administer >> %settings >> %modulebuilder page.', array('!settings' => url('admin/settings/module_builder/update'), '%administer' => 'Administer', '%settings' => 'Site configuration', '%modulebuilder' => "Module builder"))); } else { // Build hooks list $form['hooks'] = array( '#type' => 'checkboxes', '#title' => t('Use the following specific hooks'), ); foreach ($hook_groups as $hook_group => $hooks) { $form['hooks'][$hook_group] = array( '#type' => 'fieldset', '#title' => $hook_group .' hooks', '#collapsible' => TRUE, '#collapsed' => TRUE, '#theme' => 'module_builder_hook_list', ); foreach ($hooks as $hook) { $name = $hook['name']; $desc = $hook['description']; $form['hooks'][$hook_group][$name] = array( '#type' => 'checkbox', '#title' => str_replace('hook_', '', $name), '#description' => $desc, // TODO: For some reason this gives me some wacky error under PHP 5: // Fatal error: Cannot use string offset as an array //'#default_value' => $edit['hooks'][$hook_group][$hook], // TODO: I would *like* to do something like the following, so some of the long // descriptions don't totally mangle the page output, but need a way to do like // a "onmouseover" effect to display the full thing. Note that 'title' is not // a valid attribute for divs. :\ //'#description' => truncate_utf8($desc, 40, TRUE, TRUE), ); // Set some default hooks if ($name == 'hook_menu') { $form['hooks'][$hook_group][$name]['#default_value'] = 1; } } // Sort list alphabetically ksort($form['hooks'][$hook_group]); } /* $form['download'] = array( '#type' => 'checkbox', '#title' => t('Automatically generate module file for download?'), '#description' => t('When checked, this will automatically generate your module file for you and prompt your browser to download it.'), '#default_value' => variable_get('module_builder_download', 1), ); */ $form['generate_module'] = array( '#type' => 'submit', '#name' => 'op', '#value' => t('Generate'), ); } return $form; } /** * Module form: 'module' step. Generate the module code. */ function Xmodule_builder_page_module($form, $form_values) { // Include link in breadcrumb to go back to main module builder form /* $breadcrumb = drupal_get_breadcrumb(); $breadcrumb[] = l(t('Module builder'), 'module_builder'); drupal_set_breadcrumb($breadcrumb); */ $code = $form_values['module_code'] ? $form_values['module_code'] : module_builder_generate_module($form_values); $info = $form_values['module_info'] ? $form_values['module_info'] : module_builder_generate_info($form_values) ; // damn I miss perl at times like this. fugly syntax. $form['back'] = array( '#type' => 'submit', '#name' => 'op', '#value' => t('Back'), ); $form['code_instructions'] = array( '#value' => t('Please copy and paste the following text into a file called !module.', array('!module' => $form_values['module_root_name'] .'.module')), '#prefix' => '
', '#suffix' => '
', ); $form['module_code'] = array( '#type' => 'textarea', '#title' => t('Module code'), '#rows' => 20, '#default_value' => $code, '#prefix' => '
', '#suffix' => '
', ); $form['download_module'] = array( '#type' => 'submit', '#name' => 'op', '#value' => t('Download module'), ); $form['write_module'] = array( '#type' => 'button', '#value' => t('Write module file'), ); $form['info_instructions'] = array( '#value' => t('Please copy and paste the following text into a file called !module.', array('!module' => $form_values['module_root_name'] .'.info')), '#prefix' => '
', '#suffix' => '
', ); $form['module_info'] = array( '#type' => 'textarea', '#title' => t('Module info'), '#rows' => 20, '#default_value' => $info, '#prefix' => '
', '#suffix' => '
', ); $form['download_info'] = array( '#type' => 'submit', '#name' => 'op', '#value' => t('Download info file'), ); $form['write_info'] = array( '#type' => 'button', '#value' => t('Write info file'), ); $form['#multistep_excludes'] = array('module_code', 'module_info'); // handle the write buttons $form['#after_build'] = array('module_builder_write_buttons'); return $form; } /** * Module form: 'download' step. Download the files. */ function Xmodule_builder_page_download($form, $form_values) { $file_content = ''; $file_ext = '.txt'; if ($form_values['op'] == t('Download module')) { $file_content = $form_values['module_code']; $file_ext = '.module'; } elseif ($form_values['op'] == t('Download info file')) { $file_content = $form_values['module_info']; $file_ext = '.info'; } else { form_set_error('Problem creating file for download.'); drupal_goto('module_builder'); } if (strlen($file_content) > 0) { $file_name = $form_values['module_root_name'] . $file_ext; header("Content-disposition: attachment; filename=$file_name"); header('Content-Type: application/force-download'); header('Content-Transfer-Encoding: binary'); header('Content-Length: '. strlen($file_content)); header('Pragma: no-cache'); header('Expires: 0'); echo $file_content; exit(); } } /* $form['#after_build'] = array('module_builder_write_buttons'); */ /** * Form after build callback. * If update button was clicked, update hooks documentation. Rest of form is not submitted. * Cribbed from node_form_add_preview() */ function Xmodule_builder_write_buttons($form) { static $been_here = FALSE; // ugly but I'm going round in circles trying to figure out how best to do this if ($been_here) { return $form; } $been_here = TRUE; global $form_values; $op = isset($form_values['op']) ? $form_values['op'] : ''; if ($op == t('Write module file')) { _module_builder_write_file($form_values['module_root_name'], '.module', $form_values['module_code']); } elseif ($op == t('Write info file')) { _module_builder_write_file($form_values['module_root_name'], '.info', $form_values['module_info']); } return $form; } /** * Helper function to write files * saves moving this code while mucking about with different formsAPI approaches & quicker to shortcircuit */ function _module_builder_write_file($basename, $extension, $content) { if (strlen($content) == 0) { return; } $directory = file_create_path(variable_get('module_builder_module_write_directory', 'modules') .'/'. $basename); file_check_directory($directory, FILE_CREATE_DIRECTORY); $file_name = $basename . $extension; $created_file = file_save_data($content, "$directory/$file_name", FILE_EXISTS_REPLACE); if ($created_file) { drupal_set_message(t("File @file has been written.", array('@file' => $created_file))); } else { drupal_set_message(t("There was a problem writing the file @file.", array('@file' => "$directory/$file_name")), 'error'); } } /** * Module form: 'write' step */ function Xmodule_builder_page_write($form, $form_values) { ####### bug!!!!!!!!! dpr('writing page: ' . $form_values['op']); if ($form_values['op'] == t('Write module file')) { _module_builder_write_file($form_values['module_root_name'], '.module', $form_values['module_code']); } elseif ($form_values['op'] == t('Write info file')) { _module_builder_write_file($form_values['module_root_name'], '.info', $form_values['module_info']); } else { form_set_error('Problem creating file for writing.'); drupal_goto('module_builder'); } if (strlen($file_content) > 0) { $directory = file_create_path(variable_get('module_builder_module_write_directory', 'modules') .'/'. $form_values['module_root_name']); file_check_directory($directory, FILE_CREATE_DIRECTORY); $file_name = $form_values['module_root_name'] . $file_ext; $created_file = file_save_data($file_content, "$directory/$file_name", FILE_EXISTS_REPLACE); if ($created_file) { drupal_set_message(t("File @file has been written.", array('@file' => $created_file))); } else { drupal_set_message(t("There was a problem writing the file @file.", array('@file' => "$directory/$file_name")), 'error'); } } // return to the module step to write or download some more. //return module_builder_page_module($form, $form_values); return $form; } /** * Makes sure that valid values have been provided to the Module Builder. * * @ingroup module_builder_callback */ function Xmodule_builder_page_validate($form, &$form_state) { # TODO if ($form_values['op'] == 'input') { // Ensure module_root_name was entered, and check for special characters if (!empty($form_values['module_root_name'])) { if (!preg_match(MODULE_BUILDER_FUNCTION_PATTERN, $form_values['module_root_name'])) { 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.')); } } // Make sure at least one hook was chosen $hook_selected = FALSE; foreach ($form_values['hooks'] as $file => $hooks) { foreach ($hooks as $hook) { if ($hook == 1) { $hook_selected = TRUE; break; } } if ($hook_selected) { break; } } if (!$hook_selected) { form_set_error('hooks', t('You must select at least one hook.')); } } } ###################################################### end old code