[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/project/ -> project.inc (source)

   1  <?php
   2  // $Id: project.inc,v 1.147 2009/11/25 16:38:15 dww Exp $
   3  
   4  /**
   5   * Implementation of hook_form().
   6   */
   7  function project_project_form($node, $form_state) {
   8    global $user;
   9    project_project_set_breadcrumb($node);
  10  
  11    /* Project taxonomy */
  12    if (project_use_taxonomy()) {
  13      // Since this form is used relatively infrequently, don't allow the js to be aggregated.
  14      drupal_add_js(drupal_get_path('module', 'project') .'/project.js', 'module', 'header', FALSE, TRUE, FALSE);
  15      $project_type_vid = _project_get_vid();
  16      $tree = taxonomy_get_tree($project_type_vid);
  17      $top_level = array();
  18      $options = array();
  19      foreach ($tree as $i => $term) {
  20        if ($term->parents[0] == 0) {
  21          $last_top = $term->tid;
  22          $top_level[$term->tid] = check_plain($term->name);
  23        }
  24        else {
  25          $options[$last_top][$term->tid] = $term->name;
  26        }
  27      }
  28      // See if there are any project specific taxonomy terms already
  29      // saved in this node (i.e. we're editing an existing project) and
  30      // if so, extract the right default values for our custom form
  31      // elements...
  32      $current_top = NULL;
  33      $current_options = array();
  34  
  35      if (!empty($node->taxonomy)) {
  36        // Depending on whether we're previewing the node or not,
  37        // $node->taxonomy will be provided in one of two ways.
  38        if (isset($form_state['node_preview'])) {
  39          // In node previews, $node->taxonomy is an array of vocabularies,
  40          // each of which is an array of selected tids.
  41          if (isset($node->taxonomy[$project_type_vid])) {
  42            foreach ($node->taxonomy[$project_type_vid] as $key => $value) {
  43              if (isset($top_level[$key])) {
  44                $current_top = $key;
  45              }
  46              else {
  47                $current_options[$key] = $key;
  48              }
  49            }
  50          }
  51        }
  52        else {
  53          // $node->taxonomy is an array of term objects
  54          // when we're not previewing the node.
  55          foreach ($node->taxonomy as $tid => $obj) {
  56            if (isset($top_level[$tid])) {
  57              $current_top = $tid;
  58            }
  59            else {
  60              $current_options[$tid] = $tid;
  61            }
  62          }
  63        }
  64      }
  65  
  66      $form['project_taxonomy'] = array(
  67        '#type' => 'fieldset',
  68        '#weight' => '-30',
  69        '#title' => t('Project categories'),
  70        '#collapsible' => TRUE,
  71        '#theme' => 'project_project_node_form_taxonomy',
  72      );
  73  
  74      $form['project_taxonomy']['project_type'] = array(
  75        '#title' => t('Project type'),
  76        '#type' => 'radios',
  77        '#options' => $top_level,
  78        '#default_value' => $current_top,
  79        '#required' => TRUE,
  80      );
  81      $select_size = max(5, 2*count($top_level));
  82      foreach ($options as $tid => $values) {
  83        $form['project_taxonomy']["tid_$tid"] = array(
  84          '#title' => t('!type categories', array('!type' => $top_level[$tid])),
  85          '#type' => 'select',
  86          '#multiple' => TRUE,
  87          '#options' => $values,
  88          '#default_value' => $current_options,
  89          '#attributes' => array('size' => min($select_size, count($values))),
  90        );
  91      }
  92    }
  93  
  94    /* Project properties */
  95    // We can't put the title and body inside $node->project or core gets
  96    // confused (e.g node_body_field() and friends).  So, we put the core node
  97    // fields in their own fieldset (for which is #tree is FALSE).
  98    $form['project_node'] = array(
  99      '#type' => 'fieldset',
 100      '#title' => t('Project information'),
 101      '#collapsible' => TRUE,
 102    );
 103    $form['project_node']['title'] = array(
 104      '#type' => 'textfield',
 105      '#title' => t('Full project name'),
 106      '#default_value' => isset($node->title) ? $node->title : NULL,
 107      '#maxlength' => 128,
 108      '#required' => TRUE,
 109    );
 110    // This is sort of a hack: We want the 'uri' to be in the $node->project
 111    // array during validation and submission of this form, to protect the $node
 112    // namespace, even though from a usability standpoint, this field belongs
 113    // right up next to the title.  So, we add a 'project' subarray in here
 114    // for which #tree is TRUE, and put the 'uri' field in there.  That way, it
 115    // still lives inside the "Project information" fieldset as far as the UI is
 116    // concerned, but the value shows up in the $node->project array for
 117    // validation and submission as far as FAPI is concerned.
 118    $form['project_node']['project'] = array('#tree' => TRUE);
 119    $form['project_node']['project']['uri'] = array(
 120      '#type' => 'textfield',
 121      '#title' => t('Short project name'),
 122      '#default_value' => isset($node->project['uri']) ? $node->project['uri'] : NULL,
 123      '#size' => 40,
 124      '#maxlength' => 50,
 125      '#description' => (variable_get('project_enable_alias', TRUE)) ? t('This will be used to generate a /project/&lt;shortname&gt;/ URL for your project.') : '',
 126      '#required' => TRUE,
 127    );
 128    $form['project_node']['body_field'] = node_body_field($node, t('Full description'), 1);
 129  
 130    $form['project'] = array(
 131      '#type' => 'fieldset',
 132      '#title' => t('Project resources'),
 133      '#collapsible' => TRUE,
 134      '#collapsed' => TRUE,
 135      '#tree' => TRUE,
 136    );
 137    $form['project']['homepage'] = array(
 138      '#type' => 'textfield',
 139      '#title' => t('Homepage'),
 140      '#default_value' => isset($node->project['homepage']) ? $node->project['homepage'] : NULL,
 141      '#size' => 40,
 142      '#maxlength' => 255,
 143      '#description' => t('Link to project homepage.'),
 144    );
 145    $form['project']['documentation'] = array(
 146      '#type' => 'textfield',
 147      '#title' => t('Documentation'),
 148      '#default_value' => isset($node->project['documentation']) ? $node->project['documentation'] : NULL,
 149      '#size' => 40,
 150      '#maxlength' => 255,
 151      '#description' => t('Link to project documentation.'),
 152    );
 153    $form['project']['license'] = array(
 154      '#type' => 'textfield',
 155      '#title' => t('License'),
 156      '#default_value' => isset($node->project['license']) ? $node->project['license'] : NULL,
 157      '#size' => 40,
 158      '#maxlength' => 255,
 159      '#description' => t('Link to project license.'),
 160    );
 161    $form['project']['screenshots'] = array(
 162      '#type' => 'textfield',
 163      '#title' => t('Screenshots'),
 164      '#default_value' => isset($node->project['screenshots']) ? $node->project['screenshots'] : NULL,
 165      '#size' => 40,
 166      '#maxlength' => 255,
 167      '#description' => t('Link to project screenshots.'),
 168    );
 169    $form['project']['changelog'] = array(
 170      '#type' => 'textfield',
 171      '#title' => t('Changelog'),
 172      '#default_value' => isset($node->project['changelog']) ? $node->project['changelog'] : NULL,
 173      '#size' => 40,
 174      '#maxlength' => 255,
 175      '#description' => t('Link to changelog.'),
 176    );
 177    $form['project']['cvs'] = array(
 178      '#type' => 'textfield',
 179      '#title' => t('CVS tree'),
 180      '#default_value' => isset($node->project['cvs']) ? $node->project['cvs'] : NULL,
 181      '#size' => 40,
 182      '#maxlength' => 255,
 183      '#description' => t('Link to webcvs/viewcvs.'),
 184    );
 185    $form['project']['demo'] = array(
 186      '#type' => 'textfield',
 187      '#title' => t('Demo site'),
 188      '#default_value' => isset($node->project['demo']) ? $node->project['demo'] : NULL,
 189      '#size' => 40,
 190      '#maxlength' => 255,
 191      '#description' => t('Link to a live demo.'),
 192    );
 193  
 194    return $form;
 195  }
 196  
 197  /**
 198   * Implementation of hook_validate().
 199   *
 200   * @param $node
 201   *   An object containing values from the project node form.  Note that since
 202   *   this isn't a fully-loaded $node object, not all values will necessarily
 203   *   be in the same location as they would after a node_load().
 204   */
 205  function project_project_validate(&$node) {
 206    // Bail if user hasn't done a preview yet.
 207    if (!isset($node->title)) {
 208      return $node;
 209    }
 210  
 211    // Make sure title isn't already in use
 212    if (db_result(db_query("SELECT COUNT(*) FROM {node} WHERE type = '%s' AND status = %d AND title = '%s' AND nid <> %d", $node->type, 1, $node->title, $node->nid))) {
 213      form_set_error('title', t('This project name is already in use.'));
 214    }
 215  
 216    // Validate uri.
 217    if (empty($node->project['uri'])) {
 218      form_set_error('project][uri', t('A short project name is required.'));
 219    }
 220    else {
 221      // Make sure uri only includes valid characters
 222      if (!preg_match('/^[a-zA-Z0-9_-]+$/', $node->project['uri'])) {
 223        form_set_error('project][uri', t('Please only use alphanumerical characters for the project name.'));
 224      }
 225  
 226      // Make sure uri isn't already in use, or reserved.  Includes all X from
 227      // project/issues/X paths used in project_issues module
 228      $reserved_names = array('user', 'issues', 'releases', 'rss', 'subscribe-mail', 'search', 'add', 'update_project', 'statistics', 'comments', 'autocomplete', 'cvs', 'developers', 'usage');
 229      if (project_use_taxonomy()) {
 230        $terms = taxonomy_get_tree(_project_get_vid());
 231        foreach ($terms as $i => $term) {
 232          if ($term->depth == 0) {
 233            $reserved_names[] = strtolower($term->name);
 234          }
 235        }
 236      }
 237      if (in_array(strtolower($node->project['uri']), $reserved_names)) {
 238        form_set_error('project][uri', t('This project name is reserved.'));
 239      }
 240      $existing_nid = project_get_nid_from_uri($node->project['uri']);
 241      if (!empty($existing_nid) && $existing_nid != $node->nid) {
 242        form_set_error('project][uri', t('This project name is already in use.'));
 243      }
 244    }
 245  
 246    // Make sure all URL fields actually contain URLs.
 247    $fields = array(
 248      'homepage' => t('Homepage'),
 249      'changelog' => t('Changelog'),
 250      'cvs' => t('CVS tree'),
 251      'demo' => t('Demo site'),
 252    );
 253    foreach ($fields as $uri => $name) {
 254      if ($node->project[$uri] && !preg_match('/^(http|https|ftp):\/\//i', $node->project[$uri])) {
 255        form_set_error("project][$uri", t('The %field field is not a valid URL.', array('%field' => $name)));
 256      }
 257    }
 258  
 259    // Validate the project-specific sub-categories, if any...
 260    if (project_use_taxonomy() && isset($node->project_type)) {
 261      $tree = taxonomy_get_tree(_project_get_vid());
 262      $top_level = array();
 263      foreach ($tree as $i => $term) {
 264        if ($term->parents[0] == 0) {
 265          $top_level[$term->tid] = $term->name;
 266        }
 267      }
 268      foreach ($top_level as $tid => $name) {
 269        if ($node->project_type != $tid) {
 270          $tid_field = 'tid_' . $tid;
 271          if (!empty($node->$tid_field)) {
 272            form_set_error($tid, t('Project type %project_type was selected, you can not use values from %invalid_type categories', array('%project_type' => $top_level[$node->project_type], '%invalid_type' => $top_level[$tid])));
 273          }
 274        }
 275      }
 276    }
 277  }
 278  
 279  function project_project_set_breadcrumb($node = NULL, $extra = NULL) {
 280    $breadcrumb = array();
 281    $breadcrumb[] = l(t('Home'), NULL);
 282  
 283    /*
 284      @TODO: This is not an optimal way to do this, because it makes the
 285      assumption that there is only one menu item that links to /project (or
 286      whatever it happens to be called).  Also, it makes the assumption that the
 287      URL alias is intact for the project node (in other words, it's path is
 288      aliased to 'project/<project short name>' However, since in D6 we no
 289      longer have $_menu I'm not sure of a better way to do this.
 290    */
 291    if (!empty($node->path)) {
 292      // Get the path of the project node and remove the name of the project.
 293      $path = array();
 294      $path = explode('/', $node->path);
 295      $path = array_slice($path, 0, count($path) - 1);
 296      $path = implode('/', $path);
 297      $menu_link = db_fetch_object(db_query("SELECT * FROM {menu_links} ml INNER JOIN {menu_router} m ON m.path = ml.router_path WHERE ml.hidden = %d AND ml.link_path = '%s' ORDER BY ml.weight", 0, $path));
 298      if (!empty($menu_link)) {
 299        $breadcrumb[] = l($menu_link->link_title, 'project', array('title' => t('Browse projects')));
 300      }
 301    }
 302  
 303    if (!empty($node->nid) && project_use_taxonomy()) {
 304      $result = db_query(db_rewrite_sql('SELECT t.tid, t.* FROM {term_data} t INNER JOIN {term_hierarchy} h ON t.tid = h.tid INNER JOIN {term_node} r ON t.tid = r.tid WHERE h.parent = %d AND t.vid = %d AND r.vid = %d', 't', 'tid'), 0, _project_get_vid(), $node->vid);
 305      if ($term = db_fetch_object($result)) {
 306        $breadcrumb[] = l($term->name, 'project/'. $term->name);
 307      }
 308    }
 309  
 310    if (is_array($extra)) {
 311      $breadcrumb = array_merge($breadcrumb, $extra);
 312    }
 313    elseif ($extra && !empty($node)) {
 314      $breadcrumb[] = l($node->title, 'node/'. $node->nid);
 315    }
 316  
 317    drupal_set_breadcrumb($breadcrumb);
 318  }
 319  
 320  function project_project_view($node, $teaser = false, $page = false) {
 321    $node = node_prepare($node, $teaser);
 322  
 323    if ($page) {
 324      // Breadcrumb navigation
 325      project_project_set_breadcrumb($node);
 326  
 327      // If theme_project_release_project_download_table is implemented, format
 328      // the download table.  If this function is not implemented (eg. if the
 329      // project_release module is not enabled), there will not be an error
 330      // but of course there will be no release table.
 331      $project_table_output = theme('project_release_project_download_table', $node);
 332      if (!empty($project_table_output)) {
 333        $node->content['download_table'] = array(
 334          '#value' => $project_table_output,
 335          '#weight' => 1,
 336        );
 337      }
 338  
 339      // Retrieve nested array of sections of links to display on node page.
 340      $all_links = project_get_project_link_info($node);
 341  
 342      // Format links in $all_links for display in the project_project node.
 343      // Keep track of the section with the heaviest weight (which will be last)
 344      // so we can add a final clear after it to make sure the floating link
 345      // sections do not interfere with other formatting in the node's content.
 346      $max_weight = -10000;
 347      $last_section = '';
 348      foreach($all_links as $section => $values) {
 349        // Only add the section if there are links, and section type is "inline".
 350        if (!empty($values['links']) && (empty($values['type']) || $values['type'] == 'inline')) {
 351          $weight = !empty($values['weight']) ? $values['weight'] : 0;
 352          $node->content[$section] = array(
 353            '#value' => theme('item_list', $values['links'], isset($values['name']) ? $values['name'] : NULL),
 354            '#weight' => !empty($values['weight']) ? $values['weight'] : 0,
 355            '#prefix' => '<div class="project-links-section" id="project-links-section-'. $section .'">',
 356            '#suffix' => '</div>',
 357          );
 358          if (!empty($values['clear'])) {
 359            $node->content[$section]['#suffix'] .= '<br style="clear:both;" />';
 360          }
 361          if ($weight >= $max_weight) {
 362            $last_section = $section;
 363            $max_weight = $weight;
 364          }
 365        }
 366      }
 367      // We only want to add a clearing <br> after the final section if that
 368      // section didn't already add a clear for itself (e.g. the heaviest
 369      // section might already clear from hook_project_page_link_alter()).
 370      if (empty($all_links[$last_section]['clear']) && !empty($last_section)) {
 371        $node->content[$last_section]['#suffix'] .= '<br style="clear:both;" />';
 372      }
 373    }
 374    return $node;
 375  }
 376  
 377  /**
 378   * hook_nodeapi() implementation specific for project nodes.
 379   * @see project_nodeapi().
 380   */
 381  function project_project_nodeapi(&$node, $op, $arg) {
 382    $language = isset($node->language) ? $node->language : '';
 383    switch ($op) {
 384      case 'insert':
 385        _project_save_taxonomy($node);
 386        if (module_exists('path') && variable_get('project_enable_alias', TRUE)) {
 387          path_set_alias("node/$node->nid", 'project/'. $node->project['uri'], NULL, $language);
 388        }
 389        break;
 390  
 391      case 'update':
 392        _project_save_taxonomy($node);
 393        if (module_exists('path') && variable_get('project_enable_alias', TRUE)) {
 394          path_set_alias("node/$node->nid");  // Clear existing alias.
 395          path_set_alias("node/$node->nid", 'project/'. $node->project['uri'], NULL, $language);
 396        }
 397        break;
 398    }
 399  }
 400  
 401  function project_project_insert($node) {
 402    db_query("INSERT INTO {project_projects} (nid, uri, homepage, changelog, cvs, demo, screenshots, documentation, license) VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", $node->nid, $node->project['uri'], $node->project['homepage'], $node->project['changelog'], $node->project['cvs'], $node->project['demo'], $node->project['screenshots'], $node->project['documentation'], $node->project['license']);
 403  //  project_release_scan_directory($node->project['uri']);
 404  }
 405  
 406  function project_project_update($node) {
 407    db_query("UPDATE {project_projects} SET uri = '%s', homepage = '%s', changelog = '%s', cvs = '%s', demo = '%s', screenshots = '%s', documentation = '%s', license = '%s' WHERE nid = %d", $node->project['uri'], $node->project['homepage'], $node->project['changelog'], $node->project['cvs'], $node->project['demo'], $node->project['screenshots'], $node->project['documentation'], $node->project['license'], $node->nid);
 408  //  project_release_scan_directory($node->project['uri']);
 409  }
 410  
 411  function project_project_delete($node) {
 412    db_query('DELETE FROM {project_projects} WHERE nid = %d', $node->nid);
 413  }
 414  
 415  function project_project_retrieve($key = 0) {
 416    if (!is_numeric($key)) {
 417      $nid = project_get_nid_from_uri($key);
 418    }
 419    $node = node_load($nid);
 420    return ($node->type == 'project_project') ? $node : NULL;
 421  }
 422  
 423  function project_cvs($nid = 0) {
 424    if ($project = node_load($nid)) {
 425      if (node_access('view', $project)) {
 426        $_REQUEST['nid'] = $nid;
 427        $output = module_invoke('cvs', 'show_messages');
 428        drupal_set_title(t('CVS messages for %name', array('%name' => $project->title)));
 429        project_project_set_breadcrumb($project, TRUE);
 430        return $output;
 431      }
 432      else {
 433        drupal_access_denied();
 434      }
 435    }
 436    else {
 437      drupal_not_found();
 438    }
 439  }
 440  
 441  function _project_save_taxonomy(&$node) {
 442    if (project_use_taxonomy() && $node->project_type) {
 443      // First, clear out all terms from the project-specific taxonomy
 444      // in this node. We'll re-add the right ones based on what's saved.
 445      // This way, we're sure to clear out things that have been changed.
 446      $vid = _project_get_vid();
 447      $result = db_query('SELECT tid FROM {term_data} WHERE vid = %d', $vid);
 448      $args = array($node->nid, $node->vid);
 449      $terms = array();
 450      while ($item = db_fetch_object($result)) {
 451        $terms[] = $item->tid;
 452      }
 453      if (count($terms) > 1) {
 454        $sql = 'DELETE FROM {term_node} WHERE nid = %d AND vid = %d AND tid IN ('. db_placeholders($terms) .')';
 455        $args = array_merge($args, $terms);
 456        db_query($sql, $args);
 457      }
 458      $tid = $node->project_type;
 459      _project_db_save_taxonomy($node->nid, $tid, $node->vid);
 460      $tid_field = 'tid_' . $tid;
 461      if (isset($node->$tid_field)) {
 462        foreach ($node->$tid_field as $tid) {
 463          _project_db_save_taxonomy($node->nid, $tid, $node->vid);
 464        }
 465      }
 466    }
 467  }
 468  
 469  function _project_db_save_taxonomy($nid, $tid, $vid) {
 470    db_query('INSERT INTO {term_node} (nid, tid, vid) VALUES (%d, %d, %d)', $nid, $tid, $vid);
 471  }
 472  
 473  /**
 474   * Adds the 'project-taxonomy-element' div to the project_type
 475   * and term select box on the project_project node form.
 476   */
 477  function theme_project_project_node_form_taxonomy($form) {
 478    $output = '';
 479    foreach (element_children($form) as $child) {
 480      $output .= '<div class="project-taxonomy-element">';
 481      $output .= drupal_render($form[$child]);
 482      $output .= '</div>';
 483    }
 484    return $output;
 485  }
 486  
 487  /**
 488   * Build a nested array of sections of links to display on project_project node pages.
 489   */
 490  function project_get_project_link_info($node = NULL) {
 491    static $all_links;
 492  
 493    // We only need to build the links array once per page.
 494    if (is_array($all_links)) {
 495      return $all_links;
 496    }
 497  
 498    // Resources section
 499    $all_links['resources'] = array(
 500      'name' => t('Resources'),
 501      'weight' => 4,
 502      'type' => 'inline',
 503    );
 504    foreach (array('homepage' => t('Home page'), 'documentation' => t('Read documentation'), 'license' => t('Read license'), 'changelog' => t('Read complete log of changes'), 'demo' => t('Try out a demonstration'), 'screenshots' => t('Look at screenshots')) as $uri => $name) {
 505      if (!empty($node->project[$uri])) {
 506        $all_links['resources']['links'][$uri] = l($name, $node->project[$uri]);
 507      }
 508    }
 509  
 510    // Developer section
 511    $all_links['development'] = array(
 512      'name' => t('Development'),
 513      'weight' => 8,
 514      'type' => 'inline',
 515    );
 516    $links = array();
 517    if (!empty($node->project['cvs'])) {
 518      $links['browse_repository'] = l(t('Browse the CVS repository'), $node->project['cvs']);
 519    }
 520  
 521    if (project_use_cvs($node)) {
 522      $links['view_cvs_messages'] = l(t('View CVS messages'), 'project/cvs/'. $node->nid);
 523    }
 524    $all_links['development']['links'] = $links;
 525  
 526    // Allow other modules to add sections of links and/or links to the sections defined above.
 527    drupal_alter('project_page_link', $all_links, $node);
 528  
 529    return $all_links;
 530  }
 531  


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7