[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

/sites/all/modules/module_builder/ -> module_builder.module (source)

   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  


Generated: Mon Jul 9 18:01:44 2012 Cross-referenced by PHPXref 0.7