--- module_builder.api.inc.orig 2008-01-02 03:49:33.000000000 +0100 +++ module_builder.api.inc 2008-05-06 03:37:59.000000000 +0200 @@ -11,29 +11,31 @@ * * Components are things like 'node', 'menu', 'comment'. Basically, * a component is a hook (however, like the node component, it is not limnited - * to one Components are supplied with hook_module_builder. It returns an array - * of arrays, which give information about the components. The components each - * have a title, a machine(-readable name) a callback (which returns an FAPI array), + * to one Components are supplied with hook_module_builder. It returns an array + * of arrays, which give information about the components. The components each + * have a title, a machine(-readable name) a callback (which returns an FAPI array), * and a submit function (which is set to a reasonable default). * * @return * An array of all the components * - * @see module_builder_module_builder for the example components array - * @see module_builder_edit_form for an example form + * @see module_builder_module_builder(), module_builder_general_form() */ function module_builder_get_components() { include_once drupal_get_path('module', 'module_builder') .'/module_builder.components.inc'; $return = array(); foreach (module_implements('module_builder') as $module) { - $function = $module .'_module_builder'; - $result = $function(); - foreach ($result as $item) { - $return[$item['machine']] = $item + array( + $queryfunction = $module .'_module_builder'; + $components = $queryfunction(); + foreach ($components as $component) { + $return[$component['machine']] = $component + array( 'title' => '', 'machine' => '', - 'callback' => '', + 'formconstructor' => '', 'default' => FALSE, + 'multiple' => FALSE, + 'multicreatenewtext' => '', + 'multidescription' => '', 'submit' => 'module_builder_default_submit', 'submit_button' => TRUE, 'export' => FALSE, @@ -44,81 +46,210 @@ } /** - * Checks if a module id is valid - * + * Checks if a module id is valid (wildcard loader called for module_builder/%mid urls) + * * @param $mid * The module ID to be loaded * @return * Either the module ID if found or FALSE if it wasn't found */ -function module_builder_load($mid) { - $result = db_fetch_object(db_query("SELECT * FROM {module_builder_basic} WHERE mid = %d", $mid)); +function mid_load($mid) { + $result = db_fetch_object(db_query("SELECT data FROM {module_builder_data} WHERE mid = %d AND type = 'general'", $mid)); if ($result) { - return $result; + $module = unserialize($result->data); + $module->mid = $mid; + return $module; } - else { + else return FALSE; - } } /** - * Builder form - * + * Builder form (this renders all the forms) + * * @param $form_state - * The form state (from form.inc). Passed into the callback. - * @param $callback - * The callback function - * @param $mid - * The module id + * The form state (from form.inc). Passed into the constructor. + * @param $module + * The module entry (loaded by mid_load) * @param $type - * The name of the component (menu, node, comment) + * The type of component form to show (menu, node, comment) + * * @return * An FAPI form array */ function module_builder_build(&$form_state, $module, $type) { - $result = db_result(db_query("SELECT name FROM {module_builder_basic} WHERE mid = %d", $module->mid)); - drupal_set_title($result); + drupal_set_title(t('Project "!name"', array('!name' => $module->name))); $components = module_builder_get_components(); $component = $components[$type]; - $result = unserialize(db_result(db_query("SELECT data FROM {module_builder_data} WHERE mid = %d AND type = '%s'", $module->mid, $type))); - $values = ($result !== FALSE? $result : new stdClass); - $form = $component['callback']($form_state, $values, $module); + + // receive values from form state if already submitted or else from database + if (!empty($form_state['values'])) + $values = (object) $form_state['values']; + else { + $result = unserialize(db_result(db_query("SELECT data FROM {module_builder_data} WHERE mid = %d AND type = '%s'", $module->mid, $type))); + $values = ($result !== FALSE) ? $result : new stdClass(); + } + + // get form from component's constructor callback + $form = $component['formconstructor']($form_state, $values, $module); + $form['mid'] = array( + '#type' => 'value', + '#value' => $module->mid); + $form['type'] = array( + '#type' => 'value', + '#value' => $type); + + // form can have arbritrary number of items of same kind + if ($component['multiple'] == TRUE) { + $prototype = $form['item_prototype']['#value']; + $form['items'] = array( + '#type' => 'fieldset', + '#description' => $component['multidescription'], + '#prefix' => '
', + '#suffix' => '
', + ); + + // if add item button has been clicked, append entry with default values to item list + if ($form_state['values']['itemadded']) + $values->items[] = $form_state['values']['item_default']; + unset($form_state['values']['itemadded']); + + $count = 0; + foreach ($values->items as $key => $item) { + // remove item marked for deletion from list + if (isset($form_state['post']['deleted']) && ((int) $key === (int) $form_state['post']['deleted'])) { + unset($values->items[$key]); + continue; + } + // set form item and populate with existing values + if (is_array($item)) { + $form['items'][$count] = $prototype; + foreach ($item as $field => $value) { + if ($field === "name" || $field === "title") + $form['items'][$count]['#title'] = $value; + $form['items'][$count][$field]['#default_value'] = $value; + } + // add a delete button for each item + $form['items'][$count]["delete_$count"] = array( + '#type' => 'submit', + '#name' => "delete_$count", + '#value' => t('Remove'), + // call store callback, then confirmation form + '#submit' => array($component['submit'], 'module_builder_itemdelete_confirm'), + ); + $count++; + } + } + $form['new'] = array( + '#type' => 'submit', + '#value' => $component['multicreatenewtext'], + '#submit' => array('module_builder_additem_submit'), + '#prefix' => '
', + '#ahah' => array( + 'wrapper' => 'items-wrapper', + 'method' => 'append', + 'path' => 'module_builder/js', + ), + ); + + // set submit handler + $form['#submit'][] = 'module_builder_multiple_submit'; + } + $form['#submit'][] = $component['submit']; + if ($component['submit_button']) { $form['submit'] = array( - '#type' => 'submit', - '#value' => t('Submit'), + '#type' => 'submit', + '#value' => t('Save changes'), ); } - $form['#submit'][] = $component['submit']; - $form['mid'] = array('#type' => 'value', '#value' => $module->mid); - $form['type'] = array('#type' => 'value', '#value' => $type); - + return $form; } /** - * Module builder default submit + * Module builder submit handler for forms with multiple items (filters empty/default items) + */ +function module_builder_multiple_submit($form, &$form_state) { + $unset_items = array(); + foreach ($form_state['values']['items'] as $key => $item) { + $contains_default_values = TRUE; + foreach ($item as $field => $value) { + if ($field === "delete_$key") + continue; + if ($value !== $form_state['values']['item_default'][$field]) + $contains_default_values = FALSE; + } + if ($contains_default_values) + $unset_items[] = $key; + } + foreach ($unset_items as $key) + unset($form_state['values']['items'][$key]); + unset($form_state['values']['new']); +} + +/** + * Module builder default submit (saves entered form data) */ function module_builder_default_submit($form, &$form_state) { + // create a clean copy of the values and store it in the db $values = (object) $form_state['values']; - unset($values->form_id, $values->submit, $values->op, $values->form_build_id, $values->form_token); - $final = new stdClass; - $final->mid = $values->mid; - $final->type = $values->type; + unset($values->form_id, $values->submit, $values->op, $values->form_build_id, $values->form_token, $values->items['new'], $values->item_default, $values->item_prototype); + foreach ($values->items as $key => $item) + foreach ($item as $field => $value) + if ($field === "delete_$key") + unset($values->items[$key][$field]); + $storecomponent = new stdClass(); + $storecomponent->mid = $values->mid; + $storecomponent->type = $values->type; unset($values->mid, $values->type); - $final->data = $values; - if ((bool) db_result(db_query("SELECT mid FROM {module_builder_data} WHERE mid = %d AND type = '%s'", $final->mid, $final->type))) { - drupal_write_record('module_builder_data', $final, array('mid', 'type')); + $storecomponent->data = $values; +drupal_set_message('
$storecomponent'. print_r($storecomponent, TRUE) .'
'); + + if ((bool) db_result(db_query("SELECT mid FROM {module_builder_data} WHERE mid = %d AND type = '%s'", $storecomponent->mid, $storecomponent->type))) { + $ret = drupal_write_record('module_builder_data', $storecomponent, array('mid', 'type')); } else { - drupal_write_record('module_builder_data', $final); + $ret = drupal_write_record('module_builder_data', $storecomponent); } +// drupal_set_message('
$ret= '.print_r($ret, TRUE).'
'); +// $form_state['rebuild'] = TRUE; +} + +function module_builder_additem_submit($form, &$form_state) { +// drupal_set_message('module_builder_additem_submit'); + $form_state['values']['itemadded'] = TRUE; $form_state['rebuild'] = TRUE; } + +function module_builder_itemdelete_confirm($form, &$form_state) { + $key = $form_state['clicked_button']['#parents'][1]; + $type = $form_state['values']['type']; + $mid = $form_state['values']['mid']; + $name = (!empty($form_state['values']['items'][$key]['title'])) ? + $form_state['values']['items'][$key]['title'] : ((!empty($form_state['values']['items'][$key]['name'])) ? + $form_state['values']['items'][$key]['name'] : t('(unnamed)')); + $output = drupal_get_form('module_builder_itemdelete_confirm_form', $type, $mid, $key, $name); + print theme('page', $output); + exit; +} + +function module_builder_itemdelete_confirm_form(&$form_state, $type, $mid, $key, $name) { + $item_deleted = array( + 'deleted' => array( + '#type' => 'hidden', + '#value' => $key, + ), + ); + $form = confirm_form($item_deleted, t('Do you really want to delete the !type "!name"?', + array('!type' => $type, '!name' => $name)), "admin/build/module_builder/edit/$mid/$type"); + return $form; +} + /** * The JavaScript callback. - * + * * Uses magic too complex to be explained here. */ function module_builder_js($param = '') { @@ -126,38 +257,48 @@ $form_state = array('storage' => NULL, 'submitted' => FALSE); $form_build_id = $_POST['form_build_id']; $form = form_get_cache($form_build_id, &$form_state); - // #parameters has $form_id, $form_state and then whatever was passed to - // drupal_get_form. + + // #parameters has $form_id, $form_state and then whatever + // was passed to drupal_get_form. $args = $form['#parameters']; $form_id = array_shift($args); $form['#post'] = $_POST; $form['#redirect'] = FALSE; + // This will set up $form_state['clicked_button'] and // $form_state['storage']['mlid']. drupal_process_form($form_id, $form, $form_state); + // Recreate and re-cache the form. $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id); - // Pick up the parents of the pressed button. - $array_parents = $form_state['clicked_button']['#array_parents']; - // The last parent is the button itself, we need the wrapper instead. - array_pop($array_parents); - while ($array_parents) { - $parent = array_shift($array_parents); - $form = $form[$parent]; - } - // Remove the button. - unset($form['parent_submit']); - // Render messages and selects. - $output = theme('status_messages') . drupal_render($form); + + // get the added form item and add the js pre_render callback + $item = $form['items'][end(element_children($form['items']))]; + $item['#pre_render'] = (!empty($form['#pre_render'])) ? $form['#pre_render'] : ''; + + // render the item and its javascript and send it to the browser via JSON + $output = drupal_render($item) . drupal_get_js('appended'); drupal_json(array('status' => TRUE, 'data' => $output)); } -function module_builder_add_js($name, $a2, $a3, $a4) { +function module_builder_add_js() { +// drupal_set_message('module_builder_add_js'); drupal_add_js(drupal_get_path('module', 'module_builder') .'/module_builder.js'); - switch ($name) { - case 'copy': - drupal_add_js(array('moduleBuilderCopy' => array(array('type' => $a2, 'from' => $a3, 'to' => $a4))), 'setting'); - } +} + +function module_builder_add_item_js($name, $type, $from, $to, $scope = 'header') { +// drupal_set_message('module_builder_add_item_js'); + $js_data = array( + $name => array( + array( + 'type' => $type, + 'from' => $from, + 'to' => $to, + ), + ), + ); +// drupal_set_message('
'.print_r($js_data, TRUE).'
'); + drupal_add_js($js_data, 'setting', $scope); } function module_builder_add_hook($hook, $module) { @@ -170,35 +311,52 @@ } function module_builder_export_callback($module, $file) { - $edit = unserialize(db_result(db_query("SELECT data FROM {module_builder_data} WHERE type = '%s' AND mid = %d", 'edit', $module->mid))); - $module = (object) ((array) $module + (array) $edit + array('description' => '', 'machine' => '')); - if ($file == 'info') { - header('Content-disposition: attachment'); - print _module_builder_export_info($module); - exit(); - } - elseif ($file == 'module') { - header('Content-disposition: attachment'); - print _module_builder_export_module($module); - exit(); - } - elseif ($file == 'tar') { - - } - else { - drupal_not_found(); - } + switch ($file) { + case 'info': + drupal_set_header('Content-type: text/plain'); + drupal_set_header('Content-disposition: attachment; filename="'. $module->machine .'.info"'); + print _module_builder_export_info($module); + exit(); + case 'module': + drupal_set_header('Content-type: text/plain'); + drupal_set_header('Content-disposition: attachment; filename="'. $module->machine .'.module"'); + print _module_builder_export_module($module); + exit(); + case 'tar': + include_once(drupal_get_path('module', 'module_builder') .'/archive_tar/archive_tar.php'); + $tarname = file_directory_path() .'/'. $module->machine .'.tar.gz'; + $tarchive = new Archive_Tar($tarname, 'gz'); + if ($tarchive->addString($module->machine .'/'. $module->machine .'.info', _module_builder_export_info($module)) && + $tarchive->addString($module->machine .'/'. $module->machine .'.module', _module_builder_export_module($module))) { + drupal_set_header('Content-type: application/x-gzip'); + drupal_set_header('Content-disposition: attachment; filename="'. $module->machine .'.tar.gz"'); + print file_get_contents($tarname); + unlink($tarname); + exit(); + } + else { + drupal_set_message('Creating GZ compressed TAR archive failed.', 'error'); + drupal_not_found(); + } + default: + drupal_not_found(); + } } function _module_builder_export_info($module) { - $output = ''; + $output = '; $Id$'."\n"; $info = array(); $info['name'] = '"'. $module->name .'"'; $info['description'] = '"'. $module->description .'"'; + if (!empty($module->package)) $info['package'] = $module->package; $info['core'] = '6.x'; foreach ($info as $key => $value) { $output .= $key .' = '. $value ."\n"; } + $dependencies = (!empty($module->dependencies)) ? explode(' ', $module->dependencies) : ''; + while (!empty($dependencies)) { + $output .= "dependencies[] = ". array_pop($dependencies) ."\n"; + } return $output; } --- module_builder.components.inc.orig 2008-01-02 03:49:33.000000000 +0100 +++ module_builder.components.inc 2008-05-06 02:50:19.000000000 +0200 @@ -4,194 +4,209 @@ function module_builder_module_builder() { return array( array( - 'title' => t('Edit'), - 'machine' => 'edit', - 'callback' => 'module_builder_edit_form', + 'title' => t('General'), + 'machine' => 'general', + 'formconstructor' => 'module_builder_general_form', 'default' => TRUE, - 'submit' => 'module_builder_edit_form_submit', + 'submit' => 'module_builder_general_form_submit', ), array( - 'title' => t('Menu'), + 'title' => t('Menus'), 'machine' => 'menu', - 'callback' => 'module_builder_menu_form', - // 'export' => 'module_builder_menu_export', + 'formconstructor' => 'module_builder_menu_form', + 'multiple' => TRUE, + 'multicreatenewtext' => t('Add menu entry'), + 'multidescription' => t('Add here any menu items the module should define.'), ), array( - 'title' => t('Node'), + 'title' => t('Node types'), 'machine' => 'node', - 'callback' => 'module_builder_node_form', + 'formconstructor' => 'module_builder_node_form', + 'multiple' => TRUE, + 'multicreatenewtext' => t('Add content type'), + 'multidescription' => t('Node content types the module provides can be defined here.'), 'export' => 'module_builder_node_export', ), array( - 'title' => t('Delete'), - 'machine' => 'delete', - 'callback' => 'module_builder_delete_form', - 'submit' => 'module_builder_delete_form_submit', - 'submit_button' => FALSE, + 'title' => t('DB schema'), + 'machine' => 'schema', + 'formconstructor' => 'module_builder_schema_form', + ), + array( + 'title' => t('Functions'), + 'machine' => 'function', + 'formconstructor' => 'module_builder_function_form', + 'multiple' => TRUE, + 'multicreatenewtext' => t('Add function definition'), + 'multidescription' => t('The functions which provide the module\'s ..well ... functionality!'), ), array( - 'title' => t('Export'), + 'title' => t('Export module'), 'machine' => 'export', - 'callback' => 'module_builder_export_form', + 'formconstructor' => 'module_builder_export_form', + 'submit_button' => FALSE, + ), + array( + 'title' => t('Delete project'), + 'machine' => 'delete', + 'formconstructor' => 'module_builder_delete_form', + 'submit' => 'module_builder_delete_form_submit', 'submit_button' => FALSE, ), ); } /** - * The basic edit form + * The general settings form */ -function module_builder_edit_form(&$form_state, $values, $mid) { - $form = array(); - $form['name'] = array( - '#type' => 'textfield', - '#title' => t('Name'), - '#description' => t('The external name of the module'), - '#size' => 40, - '#maxlength' => 255, - '#default_value' => isset($values->name)? $values->name : '', - ); - $form['machine'] = array( - '#type' => 'textfield', - '#title' => t('Machine-readable name'), - '#description' => t('Alpha-numeric characters and underscores only'), - '#size' => 40, - '#maxlength' => 255, - '#default_value' => isset($values->machine)? $values->machine : '', - ); - $form['description'] = array( - '#type' => 'textfield', - '#title' => t('Description'), - '#description' => t('The description of the module'), - '#size' => 40, - '#maxlength' => 255, - '#default_value' => isset($values->description)? $values->description : '', +function module_builder_general_form(&$form_state, $values, $module) { + $form = array( + 'name' => array( + '#type' => 'textfield', + '#title' => t('Name'), + '#description' => t('The human-readable name of the module'), + '#size' => 40, + '#maxlength' => 255, + '#default_value' => isset($values->name)? $values->name : '', + ), + 'machine' => array( + '#type' => 'textfield', + '#title' => t('Machine-readable name'), + '#description' => t('Alpha-numeric characters and underscores only'), + '#size' => 40, + '#maxlength' => 255, + '#default_value' => isset($values->machine)? $values->machine : '', + ), + 'description' => array( + '#type' => 'textfield', + '#title' => t('Description'), + '#description' => t('The description of the module'), + '#size' => 40, + '#maxlength' => 255, + '#default_value' => isset($values->description)? $values->description : '', + ), + 'package' => array( + '#type' => 'textfield', + '#title' => t('Package'), + '#description' => t('Optional category name (f.e. CCK, Development..)'), + '#size' => 40, + '#maxlength' => 255, + '#default_value' => isset($values->package)? $values->package : '', + ), + 'dependencies' => array( + '#type' => 'textfield', + '#title' => t('Dependencies'), + '#description' => t('Machine-readable names of needed modules (space seperated)'), + '#size' => 40, + '#maxlength' => 255, + '#default_value' => isset($values->dependencies)? $values->dependencies : '', + ), + '#pre_render' => array('module_builder_general_js_magic'), ); - module_builder_add_js('copy', 'makeUnderscore', '#edit-name', '#edit-machine'); return $form; } + +function module_builder_general_js_magic($form, $foo) { +// drupal_set_message('module_builder_general_js_magic'); + module_builder_add_js(); + module_builder_add_item_js('moduleBuilderCopy', 'makeUnderscore', '#edit-name', '#edit-machine'); + return $form; +} + /** - * Submit callback for the edit form + * Submit callback for general settings form + * (updates the project table after saving form values) */ -function module_builder_edit_form_submit($form, &$form_state) { +function module_builder_general_form_submit($form, &$form_state) { module_builder_default_submit($form, $form_state); - db_query("UPDATE {module_builder_basic} SET name = '%s' WHERE mid = %d", $form_state['values']['name'], $form_state['values']['mid']); + db_query("UPDATE {module_builder_projects} SET name = '%s' WHERE mid = '%d'", $form_state['values']['name'], $form_state['values']['mid']); } function module_builder_node_form(&$form_state, $values) { - if (isset($form_state['storage']['node_type_count']) && $form_state['storage']['node_type_count'] > 1 && isset($form_state['storage']['types']) && !empty($form_state['storage']['types'])) { - $node_type_count = $form_state['storage']['node_type_count']; - $types = $form_state['storage']['types']; - } - elseif (isset($values->types)) { - $node_type_count = count($values->types); - $types = $values->types; - } - else { - $node_type_count = 1; - } - $default_type = array( +// drupal_set_message('module_builder_node_form'); + $item_default = array( 'name' => '', 'machine' => '', 'description' => '', - 'locked' => FALSE, + 'locked' => 0, ); - - $form = array( - '#cache' => TRUE, - '#tree' => TRUE, - ); - $form['integration'] = array( - '#type' => 'checkbox', - '#title' => t('Integrate with the node module'), - '#description' => t('If your module needs to interact with node types other than the ones it defines, check this'), - '#default_value' => isset($values->integration)? (bool) $values->integration : FALSE, - ); - $form['types'] = array( + $prototype = array( '#type' => 'fieldset', - '#title' => t('Node types'), - '#description' => t('If the module defines any node types, fill out these values.'), - '#collapsible' => FALSE, - '#prefix' => '
', - '#suffix' => '
', - ); - for ($delta = 0; $delta < $node_type_count; $delta++) { - if (!isset($types[$delta])) { - $type = $default_type; - } - else { - $type = $types[$delta] + $default_type; - } - $form['types'][$delta] = array( - '#type' => 'fieldset', - '#title' => t('Node type'), // As an added bonus, change it to (!empty($type['name'])? $type['name'] : t('Node type')) - '#collapsible' => TRUE, - ); - $form['types'][$delta]['name'] = array( + '#collapsible' => TRUE, + 'name' => array( '#type' => 'textfield', '#title' => t('Name'), - '#description' => t('The external (not machine-readable) name of the content type.'), - '#default_value' => $type['name'], - ); - $form['types'][$delta]['machine'] = array( + '#description' => t('The human-readable name of the content type.'), + ), + 'machine' => array( '#type' => 'textfield', '#title' => t('Machine-readable name'), '#description' => t('The machine-readable name of the content type.'), - '#default_value' => $type['machine'], - ); - $form['types'][$delta]['description'] = array( + ), + 'description' => array( '#type' => 'textfield', '#title' => t('Description'), '#description' => t('The description of the content type'), - '#default_value' => $type['description'], - ); - $form['types'][$delta]['locked'] = array( + ), + 'locked' => array( '#type' => 'checkbox', '#title' => t('Locked'), - '#description' => t('If the content type is locked, the user can\'t modify any properties from the interface'), - '#default_value' => $type['locked'], - ); - } - $form['types']['new'] = array( - '#type' => 'submit', - '#value' => t('New node type'), - '#submit' => array('_module_builder_node_submit'), - '#ahah' => array( - 'wrapper' => 'node-types-wrapper', - 'path' => 'module_builder/js', + '#description' => t('If the content type is locked, the user can not modify any of its properties.'), ), ); - - $form['#pre_render'][] = 'module_builder_node_after_build'; + $form = array( + '#cache' => FALSE, + '#tree' => TRUE, + 'item_default' => array( + '#type' => 'value', + '#value' => $item_default, + ), + 'item_prototype' => array( + '#type' => 'value', + '#value' => $prototype, + ), + 'nodeapiintegration' => array( + '#type' => 'checkbox', + '#title' => t('Integrate with the node module (adds a nodeapi hook)'), + '#description' => t('Check this if your module needs to interact with node types other than its own.'), + '#default_value' => (isset($values->nodeapiintegration)) ? $values->nodeapiintegration : 0, + '#suffix' => '
', + ), + '#pre_render' => array('module_builder_node_js_magic'), + ); return $form; } -function module_builder_node_after_build($form) { - foreach (element_children($form['types']) as $key) { - if (is_numeric($key)) { - module_builder_add_js('copy', 'makeUnderscore', '#'. $form['types'][$key]['name']['#id'], '#'. $form['types'][$key]['machine']['#id']); +// can be passed the whole form or just the items part +function module_builder_node_js_magic($form, $foo) { + if (isset($form['items'])) { + $items = $form['items']; + foreach (element_children($items) as $key) { + if (is_numeric($key)) { +// drupal_set_message('id='.$items[$key]['name']['#id']); + module_builder_add_js(); + module_builder_add_item_js('moduleBuilderCopy', 'makeUnderscore', '#'. $items[$key]['name']['#id'], '#'. $items[$key]['machine']['#id']); + } } } + else { + // handle single item that gets appended into page + $item = $form; + module_builder_add_item_js('moduleBuilderCopy', 'makeUnderscore', '#'. $item['name']['#id'], '#'. $item['machine']['#id'], 'appended'); + } return $form; } -function _module_builder_node_submit($form, &$form_state) { - $form_state['storage']['node_type_count'] = count(element_children($form['types'])); - $types = $form_state['values']['types']; - unset($types['new']); - $form_state['storage']['types'] = $types; -} - function module_builder_node_export($values, $module) { $output = ""; - if (isset($values->integration) && $values->integration == 1) { + if (isset($values->nodeapiintegration) && $values->nodeapiintegration == 1) { $output .= module_builder_add_hook('nodeapi', $module); } if (isset($values->types) && count($values->types)) { $output .= "/**\n * Implementation of hook_node_info().\n */\nfunction ". $module->machine ."_node_info() {\n return array(\n"; foreach ($values->types as $type) { if (!empty($type['machine']) && $type['machine'] != "N") { - $output .= " '". $type['machine'] ."' => array(,\n"; + $output .= " '". $type['machine'] ."' => array(\n"; $output .= " 'name' => t('". $type['name'] ."'),\n"; $output .= " 'module' => '". $module->machine ."',\n"; $output .= " 'description' => t('". $type['description'] ."'),\n"; @@ -206,64 +221,74 @@ return $output; } +function module_builder_function_form(&$form_state, $values) { + $item_default = array( + 'name' => '', + 'header' => '', + 'body' => '', + ); + $prototype = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + 'name' => array( + '#type' => 'textfield', + '#title' => t('Function name'), + '#description' => t('(Functions called externally should be prefixed with the module\'s name.)'), + ), + 'header' => array( + '#type' => 'textarea', + '#title' => t('Header comment'), + '#description' => t('Can be used to describe the purpose of the function and it\'s parameters and return value.'), + '#rows' => 2, + ), + 'body' => array( + '#type' => 'textarea', + '#title' => t('Function Body'), + '#description' => t('Code goes here.'), + '#rows' => 10, + ), + ); + $form = array( + '#cache' => FALSE, + '#tree' => TRUE, + 'item_default' => array( + '#type' => 'value', + '#value' => $item_default, + ), + 'item_prototype' => array( + '#type' => 'value', + '#value' => $prototype, + ), + ); + return $form; +} +function module_builder_schema_form(&$form_state, $values) { + $form = array(); + return $form; +} function module_builder_menu_form(&$form_state, $values) { - if (isset($form_state['storage']['menu_item_count']) && $form_state['storage']['menu_item_count'] > 1 && isset($form_state['storage']['items']) && !empty($form_state['storage']['items'])) { - $menu_item_count = $form_state['storage']['menu_item_count']; - $items = $form_state['storage']['items']; - } - elseif (isset($values->items)) { - $menu_item_count = count($values->items); - $items = $values->items; - } - else { - $menu_item_count = 1; - } - $default_item = array( + $item_default = array( 'title' => '', 'path' => '', 'type' => 'Normal', 'callback' => '', ); - - $form = array( - '#cache' => FALSE, - '#tree' => TRUE, - ); - $form['items'] = array( + $prototype = array( '#type' => 'fieldset', - '#title' => t('Menu items'), - '#description' => t('If the module defines any menu items, fill out these values.'), - '#collapsible' => FALSE, - '#prefix' => '', - ); - for ($delta = 0; $delta < $menu_item_count; $delta++) { - if (!isset($items[$delta])) { - $item = $default_item; - } - else { - $item = $items[$delta] + $default_item; - } - $form['items'][$delta] = array( - '#type' => 'fieldset', - '#title' => t('Menu item'), // As an added bonus, change it to (!empty($item['title'])? $item['title'] : t('Menu item')) - '#collapsible' => TRUE, - ); - $form['items'][$delta]['title'] = array( + '#collapsible' => TRUE, + 'title' => array( '#type' => 'textfield', '#title' => t('Title'), '#description' => t('The title of the menu item'), - '#default_value' => $item['title'], - ); - $form['items'][$delta]['path'] = array( + ), + 'path' => array( '#type' => 'textfield', '#title' => t('Path'), '#description' => t('The path of the menu item, such as admin/build/modules'), - '#default_value' => $item['path'], - ); - $form['items'][$delta]['type'] = array( + ), + 'type' => array( '#type' => 'select', '#title' => t('Type'), '#multiple' => FALSE, @@ -273,59 +298,74 @@ 'Default tab', 'Callback', 'Suggested item', - '#default_value' => $item['type'], )), - ); - $form['items'][$delta]['callback'] = array( + ), + 'callback' => array( '#type' => 'textfield', '#title' => t('Callback'), '#description' => t('The title you enter here appears on the page.'), '#size' => 40, '#maxlength' => 255, - '#default_value' => $item['callback'], - ); - - } - $form['items']['new'] = array( - '#type' => 'submit', - '#value' => t('New menu item'), - '#submit' => array('_module_builder_menu_submit'), - '#ahah' => array( - 'wrapper' => 'menu-items-wrapper', - 'path' => 'module_builder/js', + ) + ); + $form = array( + '#cache' => FALSE, + '#tree' => TRUE, + 'item_default' => array( + '#type' => 'value', + '#value' => $item_default, + ), + 'item_prototype' => array( + '#type' => 'value', + '#value' => $prototype, ), ); return $form; } -function _module_builder_menu_submit($form, &$form_state) { - $form_state['storage']['menu_item_count'] = count(element_children($form['items'])); - $items = $form_state['values']['items']; - unset($items['new']); - $form_state['storage']['items'] = $items; -} - -function module_builder_export_form() { - $form = array(); - if (!module_builder_archive_tar_enabled()) { - $form['note'] = array( +function module_builder_export_form(&$form_state, $values) { + $form = array( + 'note' => array( '#type' => 'item', - '#value' => t('Several file downloads have started. Please put them all in a single directory, %dir.', array('%dir' => unserialize(db_result(db_query("SELECT data FROM {module_builder_data} WHERE mid = '%d' AND type = '%s'", menu_get_object('module_builder', 4)->mid, 'edit')))->machine)), - ); - $form['info_file'] = array( - '#value' => '', - '#prefix' => '
', - ); - $form['module_file'] = array( - '#value' => '', - '#suffix' => '
', - ); + '#value' => t('The module skeleton has been generated. Please download the files below and put them in a single directory %dir.', array('%dir' => menu_get_object('mid', 4)->machine)), + ), + 'info_file' => array( + '#value' => '.info file', + '#suffix' => '
', + ), + 'module_file' => array( + '#value' => '.module file', + ), + ); + if (!module_builder_archive_tar_enabled()) { $form['enhanced'] = array( '#type' => 'item', '#value' => t('Note: For enhanced export capabilities, please download the archive tar package and put it in the module_builder directory.', array('!archive_tar' => 'http://dmitrizone.com/files/archive_tar.tgz')), ); } else { + $form['tar_note'] = array( + '#type' => 'item', + '#value' => t('Click below to download a GZipped TAR archive of the module directory.'), + ); + $form['tar_file'] = array( + '#value' => '.tar.gz file', + ); } return $form; } + +function module_builder_delete_form(&$form_state, $values, $module) { + return confirm_form( + array('#modulename' => $module->name), + t('Are you sure you want to delete the module "!module"?', array('!module' => $module->name)), + 'admin/build/module_builder/edit/'. $module->mid + ); +} + +function module_builder_delete_form_submit($form, &$form_state) { + if (db_query('DELETE FROM {module_builder_data} WHERE mid = %d', $form_state['values']['mid']) && + db_query('DELETE FROM {module_builder_projects} WHERE mid = %d', $form_state['values']['mid'])) + drupal_set_message(t('The project "!name" has been deleted.', array('!name' => $form['#modulename']))); + $form_state['redirect'] = 'admin/build/module_builder'; +} --- module_builder.info.orig 2008-01-03 13:05:02.000000000 +0100 +++ module_builder.info 2008-05-01 17:22:42.000000000 +0200 @@ -1,7 +1,9 @@ ; $Id: module_builder.info,v 1.2.4.2 2008/01/02 02:49:33 dmitrig01 Exp $ name = Module Builder description = Assists in the process of building modules +package = Development core = 6.x + ; Information added by drupal.org packaging script on 2008-01-03 version = "6.x-1.x-dev" core = "6.x" --- module_builder.install.orig 2008-01-02 03:49:33.000000000 +0100 +++ module_builder.install 2008-05-06 03:50:52.000000000 +0200 @@ -2,60 +2,45 @@ // $Id: module_builder.install,v 1.1.2.2 2008/01/02 02:49:33 dmitrig01 Exp $ /** - * Implementation of hook_install(). + * Implementation of hook_schema(). */ -function module_builder_install() { - // Create tables. - drupal_install_schema('module_builder'); - - drupal_set_message('Module builder installed'); -} - -/** - * Implementation of hook_uninstall(). - */ -function module_builder_uninstall() { - // Remove tables. - drupal_uninstall_schema('module_builder'); -} - function module_builder_schema() { - $schema['module_builder_basic'] = array( - 'description' => t('Stores data having to do with modules.'), + $schema['module_builder_projects'] = array( + 'description' => t('Stores ids and names of modules.'), 'fields' => array( 'mid' => array( 'type' => 'serial', 'description' => t('The id of the module.'), ), 'name' => array( - 'type' => 'varchar', - 'length' => '255', + 'type' => 'varchar', + 'length' => '255', 'default' => '', - 'not null' => TRUE, + 'not null' => TRUE, 'description' => t('The name of the module.'), ), ), 'primary key' => array('mid'), ); $schema['module_builder_data'] = array( - 'description' => t('Stores data having to do with modules built with the module builder.'), + 'description' => t('Stores each component of modules built with module_builder as data blob.'), 'fields' => array( 'mid' => array( - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, 'default' => 0, 'description' => t('The module this data is attached to.'), ), 'type' => array( - 'type' => 'varchar', - 'length' => '64', + 'type' => 'varchar', + 'length' => '64', 'default' => '', - 'not null' => TRUE, + 'not null' => TRUE, 'description' => t('The type, such as "node" or "comment" or "menu".'), ), 'data' => array( - 'type' => 'blob', + 'type' => 'blob', 'description' => t('The data'), 'serialize' => TRUE ), @@ -63,4 +48,30 @@ 'indexes' => array('data' => array('mid', 'type')), ); return $schema; -} \ No newline at end of file +} + +/** + * Implementation of hook_install(). + */ +function module_builder_install() { + // Create tables. + drupal_install_schema('module_builder'); + + drupal_set_message('Module builder installed'); +} + +/** + * Implementation of hook_uninstall(). + */ +function module_builder_uninstall() { + // Remove tables. + drupal_uninstall_schema('module_builder'); +} + +function module_builder_update_1() { + $ret = array(); + $ret[] = update_sql("RENAME TABLE {module_builder_basic} TO {module_builder_projects}"); + $ret[] = update_sql("UPDATE {module_builder_data} SET type = 'general' WHERE type = 'edit'"); + $ret[] = update_sql("UPDATE {module_builder_data} SET type = 'menu' WHERE type = 'menu'"); + return $ret; +} --- module_builder.module.orig 2008-01-02 03:49:33.000000000 +0100 +++ module_builder.module 2008-05-06 00:08:41.000000000 +0200 @@ -14,35 +14,36 @@ 'page callback' => 'module_builder_home', 'access arguments' => array('build modules'), 'file' => 'module_builder.pages.inc', - 'description' => 'Make and customize new modules without writing code', + 'description' => 'Create Drupal modules through a supportive interface.', ); - $modules = module_builder_get_components(); + $components = module_builder_get_components(); $default = array(); $count = 0; - foreach ($modules as $builder) { - $items['admin/build/module_builder/edit/%module_builder/'. $builder['machine']] = array( - 'title' => $builder['title'], + foreach ($components as $component) { + $items['admin/build/module_builder/edit/%mid/'. $component['machine']] = array( + 'title' => $component['title'], 'page callback' => 'drupal_get_form', 'page arguments' => array('module_builder_build', 4, 5), - 'type' => $builder['default'] == TRUE ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK, + 'access arguments' => array('build modules'), + 'type' => $component['default'] == TRUE ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK, 'file' => 'module_builder.pages.inc', - 'description' => 'Make and customize new modules', + 'description' => 'Create Drupal modules', 'weight' => $count, ); $count++; - if ($builder['default'] == TRUE) { - $default = $builder; + if ($component['default'] == TRUE) { + $default = $component; } } - $items['admin/build/module_builder/edit/%module_builder'] = array( - 'title' => $default['title'], + $items['admin/build/module_builder/edit/%mid'] = array( 'page callback' => 'drupal_get_form', 'page arguments' => array('module_builder_build', 4, $default['machine']), + 'access arguments' => array('build modules'), 'type' => MENU_CALLBACK, 'file' => 'module_builder.pages.inc', ); $items['admin/build/module_builder/new'] = array( - 'title' => 'Module Builder', + 'title' => t('Creating a new module..'), 'page callback' => 'drupal_get_form', 'page arguments' => array('module_builder_build_new'), 'access arguments' => array('build modules'), @@ -50,14 +51,12 @@ 'file' => 'module_builder.pages.inc', ); $items['module_builder/js'] = array( - 'title' => 'Module Builder', 'page callback' => 'module_builder_js', 'access arguments' => array('build modules'), 'type' => MENU_CALLBACK, 'file' => 'module_builder.api.inc', ); - $items['module_builder/export/%module_builder/%'] = array( - 'title' => 'Module Builder', + $items['module_builder/export/%mid/%'] = array( 'page callback' => 'module_builder_export_callback', 'page arguments' => array(2, 3), 'access arguments' => array('build modules'), --- module_builder.pages.inc.orig 2008-01-02 03:49:33.000000000 +0100 +++ module_builder.pages.inc 2008-05-06 02:39:23.000000000 +0200 @@ -4,22 +4,16 @@ include_once drupal_get_path('module', 'module_builder') .'/module_builder.components.inc'; /** - * Menu callback; home page + * Menu callback; entry page */ function module_builder_home() { $items = array(); - $new = l('New module!', 'admin/build/module_builder/new', array('html' => TRUE)); - $query = db_query("SELECT name, mid FROM {module_builder_basic}"); + $query = db_query("SELECT name, mid FROM {module_builder_projects}"); while ($result = db_fetch_array($query)) { $items[] = l($result['name'], 'admin/build/module_builder/edit/'. $result['mid']); } - if (!count($items)) { - $output = '

'. $new .'

'; - } - else { - $items[] = ''. $new .''; - $output = theme('item_list', $items); - } + $output = (!empty($items)) ? theme('item_list', $items, 'Existing module development projects:') : 'No existing projects found.'; + $output .= '
'. l(t('Create a new module!'), 'admin/build/module_builder/new'); return $output; } @@ -28,15 +22,15 @@ */ function module_builder_build_new() { $form = array(); - $form['title'] = array( + $form['name'] = array( '#type' => 'textfield', - '#title' => t('Title'), - '#description' => t('The title of the module (not the machine-readable name).'), + '#title' => t('Project name'), + '#description' => t('The title of the module to be created (not the machine-readable name).'), '#size' => 40, '#maxlength' => 255, ); $form['submit'] = array( - '#type' => 'submit', + '#type' => 'submit', '#value' => t('Submit'), ); @@ -44,23 +38,16 @@ } function module_builder_build_new_submit($form, &$form_state) { - $save = (object) array('name' => $form_state['values']['title']); - drupal_write_record('module_builder_basic', $save); - $prepared_form_values = array('values' => array('mid' => $save->mid, 'type' => 'edit', 'name' => $save->name)); - module_builder_default_submit(array(), $prepared_form_values); - $form_state['redirect'] = 'admin/build/module_builder/edit/'. $save->mid; -} + $newmodule = new stdClass(); + $newmodule->name = $form_state['values']['name']; + drupal_write_record('module_builder_projects', $newmodule); -function module_builder_delete_form(&$form_state, $values, $module) { - return confirm_form( - array(), - t('Are you sure you want to delete the module %module?', array('%module' => $module->name)), - 'admin/build/module_builder/edit/'. $module->mid - ); -} - -function module_builder_delete_form_submit($form, &$form_state) { - db_query('DELETE FROM {module_builder_data} WHERE mid = %d', $form_state['values']['mid']); - db_query('DELETE FROM {module_builder_basic} WHERE mid = %d', $form_state['values']['mid']); - $form_state['redirect'] = 'admin/build/module_builder'; + // make the entered name appear on the general form then redirect to it + $prepared_form_values = array( + 'values' => array( + 'mid' => $newmodule->mid, + 'type' => 'general', + 'name' => $newmodule->name)); + module_builder_default_submit(array(), $prepared_form_values); + $form_state['redirect'] = 'admin/build/module_builder/edit/'. $newmodule->mid; }