From 43780bd02b35be5017a5536ba6fda35701ea58aa Mon Sep 17 00:00:00 2001 From: Derek Wright Date: Thu, 17 May 2012 00:10:42 -0700 Subject: [PATCH] Issue #1551384 by dww: Initial 'port' to D7 using core Field API. - Removed tons of code for the D6 custom node type and fields. - Added code to define an initial default node type with D7 fields. - Started getting node/add/project-release to work. - Removed the D6 DB updates and added hook_update_last_removed(). - Removed the release settings page since none of them will be needed. - Removed code related to custom "fields" we injected into project nodes in D6. - Removed code for the weird "API compatibility" taxonomy vocabulary. - Removed custom token support (since we should get that for free now). --- release/includes/admin.settings.inc | 112 ---- release/includes/project_release_node_type.inc | 281 ++++++++ release/includes/release_node_form.inc | 580 +---------------- release/project_release.info | 7 +- release/project_release.install | 562 +---------------- release/project_release.module | 830 +----------------------- 6 files changed, 320 insertions(+), 2052 deletions(-) delete mode 100644 release/includes/admin.settings.inc create mode 100644 release/includes/project_release_node_type.inc diff --git a/release/includes/admin.settings.inc b/release/includes/admin.settings.inc deleted file mode 100644 index b808771..0000000 --- a/release/includes/admin.settings.inc +++ /dev/null @@ -1,112 +0,0 @@ - 'textfield', - '#title' => t('Release directory'), - '#default_value' => $rel_dir, - '#size' => 50, - '#maxlength' => 255, - '#description' => t('This setting has been temporarily deprecated. If your site depends on scanning for releases generated by an external tool, you should wait to upgrade until a future version of the project_release.module is available that restores this functionality. Set the value blank to acknowlege that you do not need this behavior, and this error will disappear.'), - ); - } - $form['project_release_default_version_format'] = array( - '#type' => 'textfield', - '#title' => t('Default version format string'), - '#default_value' => variable_get('project_release_default_version_format', PROJECT_RELEASE_DEFAULT_VERSION_FORMAT), - '#size' => 50, - '#maxlength' => 255, - '#description' => t('Customize the default format of the version strings for releases of projects on this site. Users with "administer projects" permissions can override this setting for each project.') .' '. PROJECT_RELEASE_VERSION_FORMAT_HELP, - ); - - $form['project_release_file_extensions'] = array( - '#type' => 'textfield', - '#title' => t('Permitted file extensions'), - '#default_value' => variable_get('project_release_file_extensions', PROJECT_RELEASE_FILE_EXTENSIONS), - '#size' => 50, - '#maxlength' => 255, - '#description' => t('Files uploaded to release nodes will only be allowed if they have an extension that is included in this list.'), - ); - - if ($tree = project_release_get_api_taxonomy()) { - foreach ($tree as $term) { - $terms[$term->tid] = check_plain($term->name); - } - $vocab = taxonomy_vocabulary_load(_project_release_get_api_vid()); - $tids = variable_get('project_release_active_compatibility_tids', array()); - $form['project_release_active_compatibility_tids'] = array( - '#type' => 'checkboxes', - '#title' => t('Active @vocab terms', array('@vocab' => $vocab->name)), - '#default_value' => $tids, - '#options' => $terms, - '#description' => t('Terms from the %vocab vocabulary that should be visibile to end users and project maintainers.', array('%vocab' => $vocab->name)), - ); - - // TODO: put these 2 in a fieldset? - // @TODO: For D6 port, this setting can be deleted. - $terms = array(-1 => t('all')) + $terms; - $form['project_release_browse_versions'] = array( - '#type' => 'checkbox', - '#title' => t('Browse projects by release versions'), - '#default_value' => variable_get('project_release_browse_versions', 0), - '#description' => t('Checking this box will cause the project browsing page to have a version select.'), - ); - $form['project_release_overview'] = array( - '#type' => 'radios', - '#title' => t('Default release overview'), - '#default_value' => variable_get('project_release_overview', -1), - '#options' => $terms, - '#required' => TRUE, - '#description' => t('Default release version to list on the overview page.'), - ); - } - $form['project_release_download_base'] = array( - '#type' => 'textfield', - '#title' => t('Download link base URL'), - '#default_value' => variable_get('project_release_download_base', ''), - '#size' => 50, - '#maxlength' => 255, - '#description' => t("By default, all download links to releases will use the standard download path for the site. However, if you wish to host the downloads at a different location, you can specify the base of the URL that should be used for download links. For example, if you stored releases in %files_path and you want to have download links pointing to %ftp_url, you would set this to %ftp_setting. Note that if you define this, the value should end with a slash ('/').", array('%files_path' => 'files/projects/foo.tar.gz', '%ftp_url' => 'ftp://ftp.example.com/files/projects/foo.tar.gz', '%ftp_setting' => 'ftp://ftp.example.com/')), - ); - return system_settings_form($form); -} - -/** - * Validation callback for the project_release settings form. - */ -function project_release_settings_form_validate($form, &$form_state) { - if (!empty($form_state['values']['project_release_directory'])) { - form_set_error('project_release_directory', t('Release directory setting has been deprecated.')); - } - // Only validate these form elements if the API compatibility form elements - // were even added to the form to avoid PHP notices when there are no terms - // in the API compatibility vocabulary. - if (isset($form_state['values']['project_release_active_compatibility_tids'])) { - $tids = $form_state['values']['project_release_active_compatibility_tids']; - $default_tid = $form_state['values']['project_release_overview']; - if ($default_tid != -1 && !$tids[$default_tid]) { - $vocab = taxonomy_vocabulary_load(_project_release_get_api_vid()); - form_set_error('project_release_overview', t('Project release overview must be one of the active %vocab terms.', array('%vocab' => $vocab->name))); - } - } - - // Make sure the default version format has no bad characters. - _project_release_validate_format_string($form_state['values'], 'project_release_default_version_format'); - - // If set, the project_release_download_base must end with a '/' - if (!empty($form_state['values']['project_release_download_base'])) { - if (substr($form_state['values']['project_release_download_base'], -1) != '/') { - form_set_error('project_release_download_base', t('The Download link base URL should end with a slash.')); - } - } -} - diff --git a/release/includes/project_release_node_type.inc b/release/includes/project_release_node_type.inc new file mode 100644 index 0000000..c644e3a --- /dev/null +++ b/release/includes/project_release_node_type.inc @@ -0,0 +1,281 @@ + 'project_release', + 'name' => $t('Release'), + 'base' => 'node_content', + 'description' => $t('A release of a project with a specific version number.'), + 'has_title' => '1', + 'title_label' => $t('Title'), + 'custom' => 1, + 'modified' => 1, + 'locked' => 0, + 'help' => '', + ); + + $type = node_type_set_defaults($type); + node_type_save($type); + node_add_body_field($type); + + // Define node workflow and comment settings. + variable_set('node_options_project_release', array('status', 'revision')); + variable_set('comment_project_release', COMMENT_NODE_CLOSED); + + // Tell project_release that this node type is a release node type. + variable_set('project_release_project_release', TRUE); + + // Define default fields and field instances. + + // Project + $field = array( + 'entity_types' => array(), + 'settings' => array( + 'target_type' => 'node', + 'handler' => 'base', + 'handler_submit' => 'Change handler', + 'handler_settings' => array( + 'target_bundles' => array( + 'project' => 'project', + ), + ), + ), + 'field_name' => 'field_release_project', + 'type' => 'entityreference', + 'module' => 'entityreference', + 'cardinality' => '1', + 'columns' => array( + 'target_id' => array( + 'description' => 'The id of the target entity', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => FALSE, + ), + ), + ); + field_create_field($field); + + $instance = array( + 'bundle' => 'project_release', + 'entity_types' => array(), + 'settings' => array( + 'target_type' => 'node', + 'handler' => 'base', + 'handler_submit' => 'Change handler', + 'handler_settings' => array( + 'target_bundles' => array( + 'project' => 'project', + ), + 'sort' => array( + 'type' => 'none', + 'property' => 'nid', + 'field' => 'body:value', + 'direction' => 'ASC', + ), + 'behaviors' => array( + 'views-select-list' => array( + 'status' => 0, + ), + ), + ), + ), + 'entity_type' => 'node', + 'required' => 1, + 'description' => '', + 'default_value' => NULL, + 'field_name' => 'field_release_project', + 'label' => $t('Project'), + 'type' => 'entityreference', + 'module' => 'entityreference', + 'widget' => array( + 'weight' => -1, + 'type' => 'options_select', + 'module' => 'options', + 'active' => 1, + 'settings' => array( + 'match_operator' => 'CONTAINS', + 'size' => '60', + 'path' => '', + ), + ), + ); + field_create_instance($instance); + + $field = array( + 'translatable' => '0', + 'settings' => array( + 'max_length' => '255', + ), + 'field_name' => 'field_release_version', + 'type' => 'text', + 'active' => '1', + 'locked' => '0', + 'cardinality' => '1', + ); + field_create_field($field); + + $instance = array( + 'label' => $t('Version'), + 'widget' => array( + 'weight' => '0', + 'type' => 'text_textfield', + 'active' => 1, + 'settings' => array( + 'size' => '60', + ), + ), + 'settings' => array( + 'text_processing' => '0', + 'user_register_form' => FALSE, + ), + 'display' => array( + 'default' => array( + 'label' => 'above', + 'type' => 'text_default', + 'settings' => array(), + 'weight' => 2, + ), + 'teaser' => array( + 'type' => 'hidden', + 'label' => 'above', + 'settings' => array(), + 'weight' => 0, + ), + ), + 'required' => 1, + 'description' => '', + 'default_value' => NULL, + 'field_name' => 'field_release_version', + 'entity_type' => 'node', + 'bundle' => 'project_release', + ); + field_create_instance($instance); + + $field = array( + 'translatable' => '0', + 'settings' => array( + 'max_length' => '255', + ), + 'field_name' => 'field_release_vcs_label', + 'type' => 'text', + 'active' => '1', + 'locked' => '0', + 'cardinality' => '1', + ); + field_create_field($field); + + $instance = array( + 'label' => $t('VCS Label'), + 'widget' => array( + 'weight' => '1', + 'type' => 'text_textfield', + 'active' => 1, + 'settings' => array( + 'size' => '60', + ), + ), + 'settings' => array( + 'text_processing' => '0', + 'user_register_form' => FALSE, + ), + 'display' => array( + 'default' => array( + 'label' => 'above', + 'type' => 'text_default', + 'settings' => array(), + 'weight' => 3, + ), + 'teaser' => array( + 'type' => 'hidden', + 'label' => 'above', + 'settings' => array(), + 'weight' => 0, + ), + ), + 'required' => 0, + 'description' => $t('The label (branch or tag) in a version control system that represents this release.'), + 'default_value' => NULL, + 'field_name' => 'field_release_vcs_label', + 'entity_type' => 'node', + 'bundle' => 'project_release', + ); + field_create_instance($instance); + + $field = array( + 'translatable' => '0', + 'settings' => array( + 'allowed_values' => array( + 'static' => 'Static', + 'dynamic' => 'Dynamic', + ), + 'allowed_values_function' => '', + ), + 'field_name' => 'field_release_build_type', + 'type' => 'list_text', + 'active' => '1', + 'locked' => '0', + 'cardinality' => '1', + ); + field_create_field($field); + + $instance = array( + 'label' => $t('Release type'), + 'widget' => array( + 'weight' => '2', + 'type' => 'options_select', + 'active' => 1, + 'settings' => array(), + ), + 'settings' => array( + 'user_register_form' => FALSE, + ), + 'display' => array( + 'default' => array( + 'label' => 'above', + 'type' => 'list_default', + 'settings' => array(), + 'weight' => 4, + ), + 'teaser' => array( + 'type' => 'hidden', + 'label' => 'above', + 'settings' => array(), + 'weight' => 0, + ), + ), + 'required' => 1, + 'description' => $t("How is this release built? Can be either 'Static' if the files associated with it are built once and remain unchanged (e.g. an official release from a tag), or 'Dynamic' if the files are regularly rebuilt and updated (e.g. a development snapshot rebuilt from the end of a branch)."), + 'default_value' => array( + 0 => array( + 'value' => 'static', + ), + ), + 'field_name' => 'field_release_build_type', + 'entity_type' => 'node', + 'bundle' => 'project_release', + ); + field_create_instance($instance); + +} + +/** + * Uninstall the default project release node type. + */ +function _project_release_delete_release_node_type() { + $fields = array( + 'field_release_project', + ); + foreach ($fields as $field) { + field_delete_field($field); + watchdog('project_release', 'Deleted the :field_name field from all content type instances.', array(':field_name' => $field)); + } +} diff --git a/release/includes/release_node_form.inc b/release/includes/release_node_form.inc index 04eac03..53ed7cf 100644 --- a/release/includes/release_node_form.inc +++ b/release/includes/release_node_form.inc @@ -2,570 +2,30 @@ /** * @file - * Code required for the release node form. + * Code related to node/add/project-release and friends. */ /** - * Private helper to implement hook_form(). - * - * Create the project release node form. - */ -function _project_release_form(&$release, &$form_state) { - if (arg(1) == 'add') { - // Initialize variables and $release object properties to prevent notices. - $is_edit = FALSE; - $admin = NULL; - $pid = (integer) arg(3); - $project = node_load($pid); - if (!isset($project) || $project->type != 'project_project') { - drupal_set_message(t('Node %nid is not a valid project.', array('%nid' => $pid)), 'error'); - drupal_goto('node/add/project-release'); - } - // Make sure this user should have permissions to add releases for - // the requested project - if (!project_user_access($project, 'administer releases')) { - drupal_access_denied(); - module_invoke_all('exit'); - exit; - } - project_project_set_breadcrumb($project, TRUE); - $format = project_release_get_version_format($project); - $release->project_release['pid'] = $pid; - } - else { - global $user; - $admin = user_access('administer projects'); - $is_edit = TRUE; - $project = node_load($release->project_release['pid']); - $breadcrumb[] = l($project->title, 'node/'. $project->nid); - $breadcrumb[] = l(t('Releases'), 'node/'. $project->nid . '/release'); - project_project_set_breadcrumb($project, $breadcrumb); - $format = project_release_get_version_format($project); - } - $form['project'] = array( - '#type' => 'value', - '#value' => $project, - ); - - $modify = $admin || !$is_edit; - - $form['#attributes'] = array("enctype" => "multipart/form-data"); - - if ($is_edit) { - $form['rel_id'] = array( - '#type' => 'fieldset', - '#title' => t('Release identification'), - '#weight' => -4, - '#collapsible' => TRUE, - '#theme' => 'project_release_node_form_version_elements', - ); - } - _project_release_form_add_text_element($form['rel_id']['title'], t('Title'), $release->title, $is_edit, $admin, TRUE, 40, 128); - if (!empty($release->project_release['version'])) { - _project_release_form_add_text_element($form['rel_id']['version'], t('Version string'), $release->project_release['version'], $is_edit, $admin, TRUE, 20, 255); - } - // The version string belongs in $node->project_release[], so we set - // #parents to ensure the form value is placed there during validate, - // preview, and submit. - $form['rel_id']['version']['#parents'] = array('project_release', 'version'); - - $tag = isset($release->project_release['tag']) ? $release->project_release['tag'] : ''; - _project_release_form_add_text_element($form['rel_id']['tag'], t('Tag'), $tag, $is_edit, $admin, TRUE, 40, 255); - $form['rel_id']['tag']['#parents'] = array('project_release', 'tag'); - - $form['project_release'] = array( - '#type' => 'fieldset', - '#tree' => TRUE, - '#title' => t('Version number elements'), - '#collapsible' => TRUE, - '#theme' => 'project_release_node_form_version_elements', - ); - - if (!empty($release->project_release['pid'])) { - $pid = $release->project_release['pid']; - } - elseif (!empty($form_state['values']['project_release']['pid'])) { - $pid = $form_state['values']['project_release']['pid']; - } - // else? - $form['project_release']['pid'] = array( - '#type' => 'value', - '#value' => $pid, - ); - - _project_release_form_add_version_element($form, $release, $modify, $format, 'major', t('Major')); - _project_release_form_add_version_element($form, $release, $modify, $format, 'minor', t('Minor')); - _project_release_form_add_version_element($form, $release, $modify, $format, 'patch', t('Patch-level')); - _project_release_form_add_version_element($form, $release, $modify, $format, 'extra', t('Extra identifier'), t('Optionally specify other identifying information for this version, for example "beta-1", "rc-1" or "dev". In most cases, this should be left blank.'), 40); - - // A boolean to indicate if this release should be regularly rebuilt - // (e.g. from a revision control branch) or not (e.g. an official release - // from a tag). There's no UI for this field, since it's only used if a - // revision-control integration module is enabled. - $form['project_release']['rebuild'] = array( - '#type' => 'value', - '#value' => !empty($release->project_release['rebuild']), - ); - - $form['project_release_files'] = array( - '#type' => 'fieldset', - '#tree' => TRUE, - '#title' => t('File information'), - '#collapsible' => TRUE, - ); - - if (!empty($release->project_release['files'])) { - $files = $release->project_release['files']; - foreach ($files as $fid => $file) { - // In the case of previews, we only have the fid of the file, - // so check for that and load the file object if necessary. - if (is_numeric($file)) { - $file = project_release_load_file($file); - } - $form['project_release_files'][$fid]['file_info'] = array( - '#value' => theme('project_release_download_file', $file, FALSE), - ); - if ($admin) { - $form['project_release_files'][$fid]['delete'] = array( - '#type' => 'checkbox', - '#title' => t('Delete @filename', array('@filename' => $file->filename)), - '#default_value' => isset($release->project_release_files[$fid]['delete']) ? $release->project_release_files[$fid]['delete'] : 0, - // TODO: we'll need to rip this out when multiple files lands. - '#description' => (isset($files) ? t('In order to add a new file, you must first delete %filename.', array('%filename' => $file->filename)) : ''), - ); - } - // Store the fid here in the proper $node->project_release[] array - // so it can be used to generate file previews. - $form['project_release']['files'][$fid] = array( - '#type' => 'value', - '#value' => $fid, - ); - } - } - - // TODO: we'll need to rip out the conditional when multiple files lands. - if (!isset($files)) { - // In case of previews, get any uploaded file info. - if (isset($form_state['project_release']['new_file'])) { - $new_file = $form_state['project_release']['new_file']; - } - elseif (!empty($release->project_release_files['temp'])) { - $new_file = db_fetch_object(db_query("SELECT * FROM {files} WHERE fid = %d", $release->project_release_files['temp'])); - } - $form['project_release_files']['file'] = array( - '#title' => t('File'), - '#type' => 'file', - '#description' => isset($new_file) ? t('A file named %filename has already been uploaded. If you upload another file %filename will be replaced.', array('%filename' => $new_file->filename)) : t('Choose a file that will be associated with this release.'), - ); - // Account for already uploaded files being previewed. - if (isset($new_file)) { - $form['project_release_files']['temp'] = array( - '#type' => 'value', - '#value' => $new_file->fid, - ); - } - } - - $form['body_field'] = node_body_field($release, t('Release notes'), !$admin); - // Add a description to the body field. - $form['body_field']['body']['#description'] = t('Enter a description of this release, such as a list of the major changes or updates.'); - - // Add a custom validation function. - $form['#validate'][] = 'project_release_node_form_validate'; - return $form; -} - -/** - * Modifies the given $form array to add the appropriate form element - * for the requested version field. Since the 20+ lines of code in - * here have to be duplicated 6 times in project_release_form(), this - * function exists so we can reuse the code. - * @see project_release_form - * @ingroup project_release_internal - * - * @param $form Form array to modify - * @param $release Relase node the form is for - * @param $modify Boolean indicating if we should allow modifications - * @param $format Version format string for this project - * @param $name Name of this version element - * @param $title Translatable title of the form element - * @param $description Translatable description of the form element. - * @param $size Size of the form element - * @param $required Boolean for if the form element should be required - */ -function _project_release_form_add_version_element(&$form, $release, $modify, $format, $name, $title, $description = '', $size = 10, $required = FALSE) { - $var_name = 'version_'. $name; - $regexp = "@.*[!#%]$name.*@"; - if (preg_match($regexp, $format)) { - $form['project_release'][$var_name] = array( - '#type' => 'textfield', - '#title' => $title, - '#default_value' => isset($release->project_release[$var_name]) ? $release->project_release[$var_name] : '', - '#size' => $size, - '#maxlength' => $size + 10, - '#attributes' => array('style' => 'width:auto'), - ); - if ($required) { - // TODO: handle this more flexibly for sites not using CVS - // perhaps if the format variable is UPPERCASE it's required, - // and lowercase is optional or something crazy? - $form[$var_name]['#required'] = TRUE; - } - if ($description) { - $form['project_release'][$var_name]['#description'] = $description; - } - if (!$modify) { - $form['project_release'][$var_name]['#attributes'] = array('disabled' => 'disabled'); - $form['project_release'][$var_name]['#value'] = $release->project_release[$var_name]; - } - } - else { - $form['project_release'][$var_name] = array( - '#type' => 'value', - '#value' => isset($release->project_release[$var_name]) ? $release->project_release[$var_name] : '', - ); - } -} - -/** - * Modifies the given $form array to add the appropriate form element - * for the desired text field. Since the 16+ lines of code in here - * have to be duplicated 5 times in project_release_form(), this - * function exists so we can reuse the code. - * @see project_release_form - * @ingroup project_release_internal - * - * @param $form - * Reference to form element to add. - * @param $title - * Translatable title of the form element. - * @param $value - * The value to use in the form. - * @param $is_edit - * Boolean indicating if we're editing or creating. - * @param $admin - * Boolean for if the edit is by a project administrator. - * @param $required - * Boolean for if the field should be required. - * @param $size - * Value to use for the '#size' property. - * @param $maxlength - * Value to use for the '#maxlength' property. - */ -function _project_release_form_add_text_element(&$form, $title, $value, $is_edit, $admin, $required = TRUE, $size = 40, $maxlength = 50) { - if ($is_edit && !empty($value)) { - $form = array( - '#type' => 'textfield', - '#title' => $title, - '#default_value' => $value, - '#required' => $required, - '#size' => $size, - '#maxlength' => $maxlength, - ); - if(!$admin) { - $form['#attributes']['disabled'] = 'disabled'; - $form['#value'] = $value; - } - } - else { - $form = array( - '#type' => 'value', - '#value' => $value, - ); - } -} - -/** - * Private callback to validate a release node form. - * - * @see project_release_node_form_validate() - */ -function _project_release_node_form_validate(&$form, &$form_state) { - global $user; - - // In some cases, the values we need to validate will be in - // $form_state['storage'] but not yet in $form_state['values']. For example, - // when the cvs.module is enabled and it has altered the release node form - // to turn it into a multi-step form, its submit handler will move the - // values from $form_state['storage'] to $form_state['values'] but that - // happens after we get a chance to validate everything. So, if there are - // values in $form_state['storage']['project_release'] we need to validate - // those to be safe. - if (!empty($form_state['storage']['project_release'])) { - $project_release = $form_state['storage']['project_release']; - } - elseif (!empty($form_state['values']['project_release'])) { - $project_release = $form_state['values']['project_release']; - } - else { - form_set_error('project_release][version_major', t('You must fill in some version information.')); - // TODO: find a better form value to mark as the error? - return; - } - if (!isset($project_release['version_major']) && !isset($project_release['version_minor']) && - !isset($project_release['version_patch']) && - (!($project_release['version_extra']) || $project_release['version_extra'] === '')) { - form_set_error('project_release][version_major', t('You must fill in some version information.')); - // TODO: find a better form value to mark as the error? - } - foreach (array('version_major' => t('Major version number'), 'version_minor' => t('Minor version number')) as $field => $name) { - $val = $project_release[$field]; - if (isset($val) && $val !== '' && !is_numeric($val)) { - form_set_error("project_release][$field", t('%name must be a number.', array('%name' => $name))); - } - } - $val = $project_release['version_patch']; - if (isset($val) && $val !== '' && !is_numeric($val) && $val != 'x') { - form_set_error('project_release][version_patch', t("Patch-level version number must be numeric or the letter 'x'.")); - } - - $validators = array( - 'project_release_validate_file_extension' => array(), - ); - - // For some reason, with the $form['project_release_files'] element - // #tree'd, the uploaded file shows up in 'project_release_files' - // and not it's sub-element, so we use that here. - if ($file = file_save_upload('project_release_files', $validators, file_directory_path() . '/project')) { - // We need the file object, so pass that into $form_state here. - $form_state['project_release']['new_file'] = $file; - } - - if (project_release_get_api_taxonomy()) { - $vid = _project_release_get_api_vid(); - if (isset($form_state['values']['taxonomy'])) { - $tid = $form_state['values']['taxonomy'][$vid]; - } - elseif (isset($form_state['values'][$vid])) { - $tid = $form_state['values'][$vid]; - } - if (isset($tid) && is_numeric($tid)) { - $form_state['values']['project_release']['version_api_tid'] = $tid; - $project_release['version_api_tid'] = $tid; - } - } - - if (!isset($form_state['values']['nid'])) { - $version = (object) $project_release; - $version->pid = $form['project']['#value']->nid; - $existing_nid = project_release_exists($version); - if (!empty($existing_nid)) { - // TODO: is there a better form element to mark with this error? - form_set_error('project_release][version_patch', t('This version already exists for this project.', array('@release_url' => url('node/' . $existing_nid)))); - } - } - - // TODO: it'd be nice to automagically reset the version string and - // title based on changes to the version elements on an edit, but we - // have to be careful not to break the fancy N-page form when - // cvs_form_alter() is involved... - $project = isset($form_state['values']['project']) ? $form_state['values']['project'] : new stdClass; - - if (isset($project->project['uri'])) { - $project_name = $project->project['uri']; - } - elseif (isset($project_release['pid'])) { - $project_name = project_get_uri_from_nid($form_state['values']['project_release']['pid']); - } - - if (isset($form_state['values']['title'])) { - // TODO: Magic re-setting to "%project_name %version" ?? - } - elseif (isset($project_release['version']) && $project_release['version'] !== '') { - form_set_value($form['title'], $project_name .' '. $project_release['version'], $form_state); - } - elseif (!empty($project)) { - $version = project_release_get_version((object) $project_release, $project); - form_set_value(array('#parents' => array('project_release', 'version')), $version, $form_state); - $title = !empty($project_name) ? $project_name : $project->title; - form_set_value($form['title'], "$title $version", $form_state); - } -} - -function project_release_validate_file_extension($file) { - // Make sure that the extension on the file is one of the allowed - // extensions for release files. Most of this validation code was - // modified from the code in file_check_upload(). - $extensions = variable_get('project_release_file_extensions', PROJECT_RELEASE_FILE_EXTENSIONS); - $regex = '/\.('. ereg_replace(' +', '|', preg_quote($extensions)) .')$/i'; - if (!preg_match($regex, $file->filename)) { - return array(t('It is only possible to attach files with the following extensions: %files-allowed.', array('%files-allowed' => $extensions))); - } - return array(); -} - -function project_release_node_submit(&$form, $form_state) { - // Get rid of the file upload item, not needed. - unset($form_state['values']['project_release_files']['file']); - // Look for newly uploaded files. - if (isset($form_state['project_release']['new_file'])) { - $new_file = $form_state['project_release']['new_file']; - } - elseif (!empty($form_state['values']['project_release_files']['temp'])) { - $temp = $form_state['values']['project_release_files']['temp']; - // Have to ensure the temp file hasn't been wiped from the files table. - if ($temp_file = db_fetch_object(db_query("SELECT * FROM {files} WHERE fid = %d", $temp))) { - $new_file = $temp_file; - } - unset($form_state['values']['project_release_files']['temp']); - } - $existing_files = !empty($form_state['values']['project_release_files']) ? $form_state['values']['project_release_files'] : NULL; - - if (isset($existing_files)) { - foreach ($existing_files as $fid => $values) { - if ($values['delete']) { - $file = db_fetch_object(db_query("SELECT * FROM {files} WHERE fid = %d", $fid)); - project_release_file_delete($file); - } - } - } - // Add new files. - if (isset($new_file)) { - $status_updated = file_set_status($new_file, FILE_STATUS_PERMANENT); - if ($status_updated) { - $new_file->nid = $form_state['nid']; - $filepath = file_create_path($new_file->filepath); - $new_file->filehash = md5_file($filepath); - drupal_write_record('project_release_file', $new_file); - } - } -} - -/** - * Helper method to take data out of a $node object and store it into - * the DB as necessary. Sadly, db_query() doesn't let us store NULL in - * the DB, since those get cast to 0. Therefore, we have to do some - * manual effort to dynamically create the appropriate SQL depending - * on which version fields are set in the release node. - * @see project_release_insert - * @see project_release_update - * @see db_query - * @ingroup project_release_internal - * - * @param $node - * Object containing form values from the project_release node form. Even - * though this is NOT a fully loaded $node object, the release-related - * values are in the $node->project_release array due to manual #tree and - * #parents hacking in project_release_form(). - * @param $is_new Is this a new release node, or are we updating? - */ -function project_release_db_save($node, $is_new) { - // If the patch field is set to a non-numeric value, we just want to - // keep it as a NULL in the DB, instead of casting it to a 0. - if (isset($node->project_release['version_patch']) && !is_numeric($node->project_release['version_patch'])) { - unset($node->project_release['version_patch']); - } - - $types = array('pid' => "%d", 'version' => "'%s'", 'tag' => "'%s'", - 'rebuild' => "%d", - ); - $values = array( - 'pid' => $node->project_release['pid'], - 'version' => $node->project_release['version'], - 'tag' => $node->project_release['tag'], - 'rebuild' => $node->project_release['rebuild'], - ); - $fields = array('version_major', 'version_minor', 'version_patch', 'version_api_tid'); - foreach ($fields as $field) { - if (isset($node->project_release[$field]) && is_numeric($node->project_release[$field])) { - $types[$field] = "%d"; - $values[$field] = $node->project_release[$field]; - } - } - if (module_exists('taxonomy')) { - // version_api_tid might not be where we think it is, so if we don't have - // a real value by now, look in $node->taxonomy - if (empty($types['version_api_tid'])) { - $vid = _project_release_get_api_vid(); - if (isset($node->taxonomy[$vid])) { - if (is_array($node->taxonomy[$vid])) { - $api_tid = reset($node->taxonomy[$vid]); - } - else { - $api_tid = (int)$node->taxonomy[$vid]; - } - $types['version_api_tid'] = '%d'; - $values['version_api_tid'] = $api_tid; - } - } - - if (($type_vid = _project_release_get_release_type_vid()) && ($security_tid = variable_get('project_release_security_update_tid', 0))) { - $types['security_update'] = '%d'; - $values['security_update'] = !empty($node->taxonomy[$type_vid][$security_tid]); - } - } - - $version_extra_weight_map = project_release_get_version_extra_weight_map(); - if (!empty($node->project_release['version_extra'])) { - $types['version_extra'] = "'%s'"; - $values['version_extra'] = $node->project_release['version_extra']; - // Since we have a version_extra defined, see what the weight should be, - // based on our current mapping of version_extra prefixes to weights. - foreach ($version_extra_weight_map as $prefix => $weight) { - // If the $prefix exists inside version_extra, we have a match. We use - // === 0 to tell the difference between the prefix being at position 0 - // (start of the string) vs. strpos() returning FALSE (not found). - if (strpos($node->project_release['version_extra'], $prefix) === 0) { - $types['version_extra_weight'] = "%d"; - $values['version_extra_weight'] = $weight; - break; - } - } - // If version_extra contains any digits, save them as version_extra_delta. - // This is used to ensure that alpha10 is considered "newer" than alpha9. - $match = array(); - if (preg_match('/(\d+)/', $node->project_release['version_extra'], $match)) { - $types['version_extra_delta'] = "%d"; - $values['version_extra_delta'] = $match[1]; - } - } - // If there's no version_extra, but our mapping defines a weight for 'NULL', - // specify save that weight into the version_extra_weight column. - elseif (!empty($version_extra_weight_map['NULL'])) { - $types['version_extra_weight'] = "%d"; - $values['version_extra_weight'] = $version_extra_weight_map['NULL']; - } - - if ($is_new) { - $types['nid'] = "%d"; - $sql = 'INSERT INTO {project_release_nodes} ('. implode(', ', array_keys($types)) .') VALUES ('. implode(', ', $types) .')'; - } - else { - $arr = array(); - foreach ($types as $key => $value) { - $arr[] = $key .' = '. $value; - } - $sql = 'UPDATE {project_release_nodes} SET '. implode(',', $arr) .' WHERE nid = %d'; - } - $values['nid'] = $node->nid; - db_query($sql, $values); -} - -/** - * Redirect node/add/project_release/* to node/add/project-release/*. - */ -function project_release_add_redirect_page() { - $arg = arg(3); - drupal_goto('node/add/project-release/' . (empty($arg) ? '' : $arg)); -} - -/** * Form builder for a simple form to select a project when creating a new * release (as the first "page", but this is not really a multi-page form). */ -function project_release_pick_project_form() { - $form = array(); - - drupal_set_title(t('Submit @name', array('@name' => node_get_types('name', 'project_release')))); +function project_release_pick_project_form($form, &$form_state, $node_type = 'project-release') { +// drupal_set_title(t('Submit @name', array('@name' => node_get_types('name', 'project_release')))); // Fetch a list of all projects. - $uris = NULL; - $projects = array(0 => t('- Select a project -')) + project_projects_select_options($uris); - if (count($projects) == 1) { + $machine_names = NULL; // We don't need an array of nid => machine_name. + // @todo: blocked on https://drupal.org/node/1580246 + // $projects = array(0 => t('- Select a project -')) + project_projects_select_options($machine_names); + $projects = array( + 1 => 'Devel', + ); + if (count($projects) == 0) { drupal_set_message(t('You do not have access to any projects.'), 'error'); } - $form['pid'] = array( + $form_state['node_type'] = $node_type; + + $form['project_id'] = array( '#type' => 'select', '#title' => t('Project'), '#options' => $projects, @@ -579,15 +39,15 @@ function project_release_pick_project_form() { } function project_release_pick_project_form_validate($form, &$form_state) { - if (empty($form_state['values']['pid'])) { - form_set_error('pid', t('You must select a project.')); - } - $node = node_load($form_state['values']['pid']); - if (empty($node) || $node->type != 'project_project') { - form_set_error('pid', t('Invalid project selected.')); + if (!empty($form_state['values']['project_id'])) { + $node = node_load($form_state['values']['project_id']); + if (!project_node_is_project($node)) { + form_set_error('project_id', t('Invalid project selected.')); + } + $form_state['project_machine_name'] = $node->field_project_machine_name[LANGUAGE_NONE][0]['value']; } } function project_release_pick_project_form_submit($form, &$form_state) { - $form_state['redirect'] = 'node/add/project-release/'. $form_state['values']['pid']; + $form_state['redirect'] = 'node/add/' . $form_state['node_type'] . '/' . $form_state['project_machine_name']; } diff --git a/release/project_release.info b/release/project_release.info index 0ea1e2d..bf1c854 100644 --- a/release/project_release.info +++ b/release/project_release.info @@ -2,7 +2,8 @@ name = Project releases description = Provides a release node type to represent releases of projects. package = Project dependencies[] = project -dependencies[] = taxonomy -dependencies[] = upload dependencies[] = views -core = 6.x +dependencies[] = list +dependencies[] = text +dependencies[] = entityreference +core = 7.x diff --git a/release/project_release.install b/release/project_release.install index a8331d8..7cb5a52 100644 --- a/release/project_release.install +++ b/release/project_release.install @@ -1,27 +1,21 @@ 'The base table for project_project nodes.', - 'fields' => array( - 'nid' => array( - 'description' => 'Primary Key: The {node}.nid of the project_release node.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'pid' => array( - 'description' => 'The {project_projects}.nid of the project_project node with which the project_release node is associated.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'version' => array( - 'description' => 'A string containing the full version of a release. The format of this string for a given project is dictated by {project_release_projects}.version_format.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'tag' => array( - 'description' => 'The name of a CVS branch or tag on which a release is based.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'rebuild' => array( - 'description' => 'A flag indicating whether or not the file associated with a release should be rebuilt periodically. For official releases this should be 0, for development snapshots it should be 1.', - 'type' => 'int', - 'size' => 'tiny', - 'unsigned' => FALSE, - 'not null' => FALSE, - 'default' => 0, - ), - 'version_major' => array( - 'description' => 'The major version number of a release.', - 'type' => 'int', - 'unsigned' => FALSE, - 'not null' => FALSE, - 'default' => NULL, - ), - 'version_minor' => array( - 'description' => 'The minor version number of a release.', - 'type' => 'int', - 'unsigned' => FALSE, - 'not null' => FALSE, - 'default' => NULL, - ), - 'version_patch' => array( - 'description' => 'The patch level version number of a release.', - 'type' => 'int', - 'unsigned' => FALSE, - 'not null' => FALSE, - 'default' => NULL, - ), - 'version_extra' => array( - 'description' => 'A text string that can be used to provide additional information about a release. Ex: BETA', - 'type' => 'varchar', - 'length' => 255, - 'not null' => FALSE, - 'default' => NULL, - ), - 'version_extra_weight' => array( - 'description' => 'Numeric code for ordering releases that define "version_extra".', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), - 'version_extra_delta' => array( - 'description' => 'The first span of digits found in version_extra. This is needed because we cannot natural sort natively without a stored procedure.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), - 'version_api_tid' => array( - 'description' => 'The denormalized {term_node}.tid of the API compatibility term for this release, or 0 if the release has no such term.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => FALSE, - 'default' => NULL, - ), - 'security_update' => array( - 'description' => 'Denormalized flag to record if this release has the "project_release_security_update_tid" taxonomy term set or not', - 'type' => 'int', - 'size' => 'tiny', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'update_status' => array( - 'description' => 'Denormalized flag to record the update status for this release. Allowed values: PROJECT_RELEASE_UPDATE_STATUS_CURRENT (0), PROJECT_RELEASE_UPDATE_STATUS_NOT_CURRENT (1), PROJECT_RELEASE_UPDATE_STATUS_NOT_SECURE (2)', - 'type' => 'int', - 'size' => 'tiny', - 'not null' => TRUE, - 'default' => 0, - ), - ), - 'primary key' => array('nid'), - 'indexes' => array( - 'project_releases_pid' => array('pid') - ), - ); - $schema['project_release_file'] = array( 'description' => 'Stores information about files attached to release nodes.', 'fields' => array( @@ -396,434 +282,8 @@ function project_release_schema() { } /** - * Check for existing project nodes that do not have an entry in the - * {project_release_projects} table, and add them. - */ -function project_release_add_missing_projects() { - $projects = db_query("SELECT n.nid FROM {node} n LEFT JOIN {project_release_projects} prp ON n.nid = prp.nid WHERE n.type = 'project_project' AND prp.nid IS NULL"); - while ($project = db_fetch_object($projects)) { - db_query("INSERT INTO {project_release_projects} (nid) VALUES (%d)", $project->nid); - } -} - -/** - * Populate the {project_release_nodes}.security_update field. - * - * @param $ret - * Reference to an array for hook_update_N() return values. - */ -function _project_release_check_security_updates(&$ret) { - $security_update_tid = variable_get('project_release_security_update_tid', 0); - if (!empty($security_update_tid)) { - $ret[] = update_sql("UPDATE {project_release_nodes} SET security_update = (SELECT tn.tid IS NOT NULL FROM node n LEFT JOIN term_node tn ON n.vid = tn.vid AND tn.tid = $security_update_tid WHERE n.nid = {project_release_nodes}.nid)"); - } -} - -/** - * Populate the {project_release_nodes}.version_extra_weight field. - * - * @param $ret - * Reference to an array for hook_update_N() return values. - */ -function _project_release_update_version_extra_weights(&$ret) { - $weights = project_release_get_version_extra_weight_map(); - foreach ($weights as $prefix => $weight) { - if ($prefix == 'NULL') { - $ret[] = update_sql("UPDATE {project_release_nodes} SET version_extra_weight = $weight WHERE version_extra IS NULL"); - } - else { - $ret[] = update_sql("UPDATE {project_release_nodes} SET version_extra_weight = $weight WHERE LOWER(version_extra) LIKE '" . $prefix . "%'"); - } - } -} - -/** - * Add the 'serialized' field to the {cache_project_release} table. - */ -function project_release_update_6000() { - $ret = array(); - $spec = array( - 'type' => 'int', - 'size' => 'small', - 'default' => 0, - 'not null' => TRUE, - ); - db_add_field($ret, 'cache_project_release', 'serialized', $spec); - return $ret; -} - -/** - * Add {project_release_file}. - */ -function project_release_update_6001() { - $ret = array(); - $schema = project_release_schema(); - db_create_table($ret, 'project_release_file', $schema['project_release_file']); - return $ret; -} - -/** - * Convert release file attachments to use core's file API. - */ -function project_release_update_6002() { - // This determines how many issue nodes will be processed in each - // batch run. A reasonable default has been chosen, but you may - // want to tweak depending on your setup. - $limit = 100; - - // Multi-part update - if (!isset($_SESSION['project_release_update_6002'])) { - $_SESSION['project_release_update_6002'] = 0; - $_SESSION['project_release_update_6002_max'] = db_result(db_query("SELECT COUNT(prn.nid) FROM {project_release_nodes} prn INNER JOIN {node} n ON prn.nid = n.nid WHERE prn.file_path <> ''")); - } - - // Pull the next batch of files. - $files = db_query_range("SELECT prn.*, n.uid FROM {project_release_nodes} prn INNER JOIN {node} n ON prn.nid = n.nid WHERE prn.file_path <> '' ORDER BY prn.nid", $_SESSION['project_release_update_6002'], $limit); - - // Loop through each file. - while ($file = db_fetch_object($files)) { - // Make sure file is still there. - if (file_exists($file->file_path)) { - $filename = basename($file->file_path); - $filesize = filesize(file_create_path($file->file_path)); - $filemime = file_get_mimetype($filename); - db_query("INSERT INTO {files} (uid, filename, filepath, filemime, filesize, status, timestamp) VALUES (%d, '%s', '%s', '%s', '%s', %d, %d)", $file->uid, $filename, $file->file_path, $filemime, $filesize, FILE_STATUS_PERMANENT, $file->file_date); - $fid = db_last_insert_id('files', 'fid'); - db_query("INSERT INTO {project_release_file} (fid, nid, filehash) VALUES (%d, %d,'%s')", $fid, $file->nid, $file->file_hash); - } - $_SESSION['project_release_update_6002']++; - } - - if ($_SESSION['project_release_update_6002'] >= $_SESSION['project_release_update_6002_max']) { - $count = $_SESSION['project_release_update_6002_max']; - unset($_SESSION['project_release_update_6002']); - unset($_SESSION['project_release_update_6002_max']); - return array(array('success' => TRUE, 'query' => t('Converted release file attachments for @count releases', array('@count' => $count)))); - } - return array('#finished' => $_SESSION['project_release_update_6002'] / $_SESSION['project_release_update_6002_max']); - -} - -/** - * Drop unused fields from {project_release_nodes}. - */ -function project_release_update_6003() { - $ret = array(); - db_drop_field($ret, 'project_release_nodes', 'file_path'); - db_drop_field($ret, 'project_release_nodes', 'file_date'); - db_drop_field($ret, 'project_release_nodes', 'file_hash'); - return $ret; -} - -/** - * Add new columns to {project_release_supported_versions}. - */ -function project_release_update_6004() { - $ret = array('#finished' => 0); - if (!isset($_SESSION['project_release_update_6004'])) { - $spec = array('type' => 'int', 'unsigned' => TRUE, 'default' => NULL, 'not null' => FALSE); - db_add_field($ret, 'project_release_supported_versions', 'recommended_release', $spec); - db_add_field($ret, 'project_release_supported_versions', 'latest_release', $spec); - $_SESSION['project_release_update_6004'] = 0; - $_SESSION['project_release_update_6004_max'] = db_result(db_query("SELECT COUNT(*) FROM {project_release_supported_versions}")); - } - - // Number of rows to convert per batch. - $limit = 20; - while ($limit-- && $item = db_fetch_array(db_query_range("SELECT * FROM {project_release_supported_versions} WHERE latest_release IS NULL", 0, 1))) { - // We have a branch we haven't processed yet (latest_release is still - // NULL), so we invoke project_release_check_supported_versions() to - // run some queries to determine the recommended and latest releases on - // that branch. Normally, it updates {project_release_supported_versions} - // with this data in which case it returns TRUE. However, if it returns - // FALSE, it means we didn't find any releases on that branch, and it - // didn't touch the table. In that case, we need to update the table - // ourselves for this branch to mark the new fields as 0 (not NULL) so - // that we don't check this branch again. - if (!project_release_check_supported_versions($item['nid'], $item['tid'], $item['major'], FALSE)) { - db_query("UPDATE {project_release_supported_versions} SET recommended_release = %d, latest_release = %d WHERE nid = %d AND tid = %d AND major = %d", 0, 0, $item['nid'], $item['tid'], $item['major']); - } - $_SESSION['project_release_update_6004']++; - } - - if ($_SESSION['project_release_update_6004'] >= $_SESSION['project_release_update_6004_max']) { - // We're done. Set our new columns to default to 0 from here on out. - $ret[] = update_sql("ALTER TABLE {project_release_supported_versions} ALTER COLUMN recommended_release SET DEFAULT 0"); - $ret[] = update_sql("ALTER TABLE {project_release_supported_versions} ALTER COLUMN latest_release SET DEFAULT 0"); - unset($_SESSION['project_release_update_6004']); - unset($_SESSION['project_release_update_6004_max']); - $ret['#finished'] = 1; - } - else { - $ret['#finished'] = $_SESSION['project_release_update_6004'] / $_SESSION['project_release_update_6004_max']; - } - return $ret; -} - -/** - * Add the 'version_api_tid' column to {project_release_nodes}. - */ -function project_release_update_6005() { - $ret = array(); - - $spec = array( - 'description' => 'The denormalized {term_node}.tid of the API compatibility term for this release, or 0 if the release has no such term.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => FALSE, - 'default' => NULL, - ); - db_add_field($ret, 'project_release_nodes', 'version_api_tid', $spec); - - // Populate the new column from {term_node}. - $api_vid = _project_release_get_api_vid(); - $ret[] = update_sql("UPDATE {project_release_nodes} SET version_api_tid = (SELECT tn.tid FROM {node} n INNER JOIN {term_node} tn ON n.vid = tn.vid INNER JOIN {term_data} td ON tn.tid = td.tid WHERE n.nid = {project_release_nodes}.nid AND td.vid = $api_vid)"); - - return $ret; -} - -/** - * Add security_update and update_status columns to {project_release_nodes}. - */ -function project_release_update_6006() { - $ret = array(); - - $spec = array( - 'description' => 'Denormalized flag to record if this release has the "project_release_security_update_tid" taxonomy term set or not', - 'type' => 'int', - 'size' => 'tiny', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ); - db_add_field($ret, 'project_release_nodes', 'security_update', $spec); - - if (module_exists('taxonomy')) { - // Populate the new column from {term_node}. - _project_release_check_security_updates($ret); - } - - $spec = array( - 'description' => 'Denormalized flag to record the update status for this release. Allowed values: PROJECT_RELEASE_UPDATE_STATUS_CURRENT (0), PROJECT_RELEASE_UPDATE_STATUS_NOT_CURRENT (1), PROJECT_RELEASE_UPDATE_STATUS_NOT_SECURE (2)', - 'type' => 'int', - 'size' => 'tiny', - 'not null' => TRUE, - 'default' => 0, - ); - db_add_field($ret, 'project_release_nodes', 'update_status', $spec); - // This will be initialized by project_release_check_supported_versions() - // in project_release_update_6008(), so we don't need to do that here. - - return $ret; -} - -/** - * Add the 'version_extra_weight' column to {project_release_nodes}. - */ -function project_release_update_6007() { - $ret = array(); - - $spec = array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ); - db_add_field($ret, 'project_release_nodes', 'version_extra_weight', $spec); - - // Initialize the values in the DB based on the existing weights. - _project_release_update_version_extra_weights($ret); - - return $ret; -} - -/** - * Add the {project_release_supported_versions}.latest_security_release field. - */ -function project_release_update_6008() { - $ret = array('#finished' => 0); - if (!isset($_SESSION['project_release_update_6008'])) { - $spec = array( - 'type' => 'int', - 'unsigned' => TRUE, - 'default' => NULL, - 'not null' => FALSE, - ); - db_add_field($ret, 'project_release_supported_versions', 'latest_security_release', $spec); - $_SESSION['project_release_update_6008'] = 0; - $_SESSION['project_release_update_6008_max'] = db_result(db_query("SELECT COUNT(*) FROM {project_release_supported_versions}")); - } - - // Number of rows to convert per batch. - $limit = 20; - while ($limit-- && $item = db_fetch_array(db_query_range("SELECT * FROM {project_release_supported_versions} WHERE latest_security_release IS NULL", 0, 1))) { - // We have a branch we haven't processed yet (latest_security_release is - // still NULL), so we invoke project_release_check_supported_versions() to - // run some queries to determine the recommended, latest, and latest - // security releases on that branch. Normally, it updates - // {project_release_supported_versions} with this data in which case it - // returns TRUE. However, if it returns FALSE, it means we didn't find any - // releases on that branch, and it didn't touch the table. In that case, - // we need to update the table ourselves for this branch to mark - // latest_security_release as 0 (not NULL) so that we don't check this - // branch again. - if (!project_release_check_supported_versions($item['nid'], $item['tid'], $item['major'], FALSE)) { - db_query("UPDATE {project_release_supported_versions} SET latest_security_release = %d WHERE nid = %d AND tid = %d AND major = %d", 0, $item['nid'], $item['tid'], $item['major']); - // If project_release_check_supported_versions() returned FALSE, there - // are no releases on this branch, so there's nothing to initialize - // {project_release_nodes}.update_status for. - } - $_SESSION['project_release_update_6008']++; - } - - if ($_SESSION['project_release_update_6008'] >= $_SESSION['project_release_update_6008_max']) { - // We're done. Set our new columns to default to 0 from here on out. - $ret[] = update_sql("ALTER TABLE {project_release_supported_versions} ALTER COLUMN latest_security_release SET DEFAULT 0"); - unset($_SESSION['project_release_update_6008']); - unset($_SESSION['project_release_update_6008_max']); - $ret['#finished'] = 1; - } - else { - $ret['#finished'] = $_SESSION['project_release_update_6008'] / $_SESSION['project_release_update_6008_max']; - } - return $ret; -} - -/** - * Add the {project_release_nodes}.version_extra_delta field. - * - * Also recompute the latest and recommended releases on each branch, and - * therefore the update_status field, since version_extra_delta is needed - * to properly order alpha10 vs. alpha9, etc. - */ -function project_release_update_6009() { - $ret = array('#finished' => 0); - if (!isset($_SESSION['project_release_update_6009'])) { - $spec = array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'description' => 'The first span of digits found in version_extra. This is needed because we cannot natural sort natively without a stored procedure.', - ); - - db_add_field($ret, 'project_release_nodes', 'version_extra_delta', $spec); - - // Initialize version_extra_delta to -1 to identify the rows to process. - db_query('UPDATE {project_release_nodes} SET version_extra_delta = -1 WHERE version_extra IS NOT NULL'); - - $_SESSION['project_release_update_6009'] = 0; - $_SESSION['project_release_update_6009_max'] = db_result(db_query("SELECT COUNT(*) FROM {project_release_nodes} WHERE version_extra IS NOT NULL")); - } - - // Number of rows to convert per batch. - $limit = 20; - while ($limit-- && $item = db_fetch_array(db_query_range("SELECT nid, pid, version_major, version_api_tid, version_extra FROM {project_release_nodes} WHERE version_extra_delta = -1", 0, 1))) { - // Due to the new sorting method, the "recommended" and "latest" releases - // will change on any releases affected by http://drupal.org/node/649254. - - // Determine the correct version_extra_delta and update it. - $match = array(); - $nmatch = preg_match('/(\d+)/', $item['version_extra'], $match); - db_query('UPDATE {project_release_nodes} SET version_extra_delta = %d WHERE nid = %d', ($nmatch) ? $match[1] : 0, $item['nid']); - - // Finally, recheck the branch. - // Note: this is ineffecient: we only really need to call this - // once per unique branch we're touching, not for every single - // release, but optimizing this isn't worth the effort, and would - // potentially require an enormous array in $_SESSION that could - // cause its own problems. - project_release_check_supported_versions($item['pid'], $item['version_api_tid'], $item['version_major'], FALSE); - - $_SESSION['project_release_update_6009']++; - } - - if ($_SESSION['project_release_update_6009'] >= $_SESSION['project_release_update_6009_max']) { - // Done. Clean up. - unset($_SESSION['project_release_update_6009']); - unset($_SESSION['project_release_update_6009_max']); - $ret['#finished'] = 1; - } - else { - $ret['#finished'] = $_SESSION['project_release_update_6009'] / $_SESSION['project_release_update_6009_max']; - } - return $ret; -} - -/** - * Add the {project_release_project_maintainer} table. - */ -function project_release_update_6010() { - $ret = array(); - - $table = array( - 'description' => t('Users who have various per-project maintainer permissions.'), - 'fields' => array( - 'nid' => array( - 'description' => t('Foreign key: {project_projects}.nid of the project.'), - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'uid' => array( - 'description' => t('Foreign key: {users}.uid of a user with any project maintainer permissions.'), - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'administer_releases' => array( - 'description' => t('Can this user create and administer releases for the given project.'), - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - ), - 'primary key' => array('nid', 'uid'), - ); - db_create_table($ret, 'project_release_project_maintainer', $table); - - // Initially populate the table so that every project owner has full - // powers on their own projects. - $ret[] = update_sql("INSERT INTO {project_release_project_maintainer} (nid, uid, administer_releases) SELECT nid, uid, 1 FROM {node} WHERE type = 'project_project'"); - - // If CVS module is enabled, also populate the table from the - // {cvs_project_maintainers} table so that anyone with CVS access - // who is not the project owner can administer releases. - if (module_exists('cvs')) { - $ret[] = update_sql("INSERT INTO {project_release_project_maintainer} (nid, uid, administer_releases) SELECT cpm.nid, cpm.uid, 1 FROM {cvs_project_maintainers} cpm INNER JOIN {node} n ON cpm.nid = n.nid WHERE cpm.uid != n.uid"); - } - - return $ret; -} - -/** - * Add the 'weight' column to {project_release_file}. + * Implements hook_update_last_removed(). */ -function project_release_update_6011() { - $ret = array(); - $spec = array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'size' => 'tiny', - 'description' => 'Weight of this file in relation to other files in this release.', - ); - db_add_field($ret, 'project_release_file', 'weight', $spec); - return $ret; -} - -/** - * Add the 'downloads' column to {project_release_file}. - */ -function project_release_update_6012() { - $ret = array(); - $spec = array( - 'description' => 'Number of times this file has been downloaded. This value is updated by site specific means.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ); - db_add_field($ret, 'project_release_file', 'downloads', $spec); - return $ret; +function project_release_update_last_removed() { + return 6012; } diff --git a/release/project_release.module b/release/project_release.module index f94d8af..c3a9e56 100644 --- a/release/project_release.module +++ b/release/project_release.module @@ -1,6 +1,5 @@ 'Releases', 'page callback' => 'project_release_project_edit_releases', 'page arguments' => array(1), @@ -55,26 +46,6 @@ function project_release_menu() { 'type' => MENU_CALLBACK, ); - $items['admin/project/project-release-settings'] = array( - 'description' => 'Configure the default version string for releases and other settings for the Project release module.', - 'title' => 'Project release settings', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('project_release_settings_form'), - 'access arguments' => array('administer projects'), - 'weight' => 1, - 'type' => MENU_NORMAL_ITEM, - 'file' => 'includes/admin.settings.inc', - ); - - // Redirect node/add/project_release/* to node/add/project-release. - $items['node/add/project_release'] = array( - 'page callback' => 'project_release_add_redirect_page', - 'access callback' => 'node_access', - 'access arguments' => array('create', 'project_release'), - 'type' => MENU_CALLBACK, - 'file' => 'includes/release_node_form.inc', - ); - return $items; } @@ -105,54 +76,6 @@ function project_release_project_settings_form_access($node) { */ /** - * Implementation of hook_access(). - * @ingroup project_release_node - * - * TODO: Maybe we should add new permissions for accessing release - * nodes, but for now, we're just using the existing project perms. - */ -function project_release_access($op, $node, $account) { - switch ($op) { - case 'view': - // We want to use the identical logic for viewing projects, - // so we call that method directly. - return project_project_access($op, $node, $account); - case 'create': - // Due to how node_menu() works, we have to allow anyone with - // permission to maintain a project to be able to create a - // release node, or else you can have a faulty entry added to - // the {cache_menu} table that thinks you're not allowed to - // create *any* releases. So, we are more relaxed here, and - // enforce more closely in project_release_form(). As with the - // 'view' case above, we want the identical logic as project - // nodes, so we call that hook, instead of duplicating code. - return project_project_access($op, $node, $account); - case 'update': - // We can't just use project_project_access() here, since we - // need to check access to the project itself, not the release - // node, so we use the helper method and pass the project id. - return project_user_access($node->project_release['pid'], 'administer releases'); - case 'delete': - // No one should ever delete a release node, only unpublish it. - return FALSE; - } -} - -/** - * Implementation of hook_node_info(). - * @ingroup project_release_node - */ -function project_release_node_info() { - return array( - 'project_release' => array( - 'name' => t('Project release'), - 'module' => 'project_release', - 'description' => t('A release of a project with a specific version number.'), - ), - ); -} - -/** * Implement hook_project_permission_info() * * This advertises an 'Administer releases' permission if the site is @@ -191,8 +114,8 @@ function project_release_project_maintainer_remove($nid, $uid) { /** * Implement hook_project_maintainer_project_load() */ -function project_release_project_maintainer_project_load($nid, &$maintainers) { - $query = db_query('SELECT u.uid, u.name, prpm.administer_releases FROM {project_release_project_maintainer} prpm INNER JOIN {users} u ON prpm.uid = u.uid WHERE prpm.nid = %d', $nid); +function _project_release_project_maintainer_project_load($nid, &$maintainers) { + $query = db_query('SELECT u.uid, u.name, prpm.administer_releases FROM {project_release_project_maintainer} prpm INNER JOIN {users} u ON prpm.uid = u.uid WHERE prpm.nid = :prpm.nid', array(':prpm.nid' => $nid)); while ($maintainer = db_fetch_object($query)) { if (empty($maintainers[$maintainer->uid])) { $maintainers[$maintainer->uid]['name'] = $maintainer->name; @@ -202,76 +125,6 @@ function project_release_project_maintainer_project_load($nid, &$maintainers) { } /** - * Implement of hook_form() for project_release nodes. - */ -function project_release_form(&$release, &$form_state) { - module_load_include('inc', 'project_release', 'includes/release_node_form'); - return _project_release_form($release, $form_state); -} - -/** - * Validation callback for project release node forms. - * - * @see _project_release_node_form_validate() - */ -function project_release_node_form_validate(&$form, &$form_state) { - module_load_include('inc', 'project_release', 'includes/release_node_form'); - return _project_release_node_form_validate($form, $form_state); -} - - -/** - * Implementation of hook_load(). - * @ingroup project_release_node - */ -function project_release_load($node) { - $additions = db_fetch_array(db_query("SELECT * FROM {project_release_nodes} WHERE nid = %d", $node->nid)); - // Add in file info. - $file_info = db_query("SELECT f.*, prf.filehash, prf.weight FROM {project_release_file} prf INNER JOIN {files} f ON prf.fid = f.fid WHERE prf.nid = %d", $node->nid); - $files = array(); - while ($file = db_fetch_object($file_info)) { - $files[$file->fid] = $file; - } - $additions['files'] = $files; - - $release = new stdClass; - $release->project_release = $additions; - return $release; -} - -/** - * Implementation of hook_insert(). - * - * @param $node - * Object containing form values from the project_release node form. Even - * though this is NOT a fully loaded $node object, the release-related - * values are in the $node->project_release array due to manual #tree and - * #parents hacking in project_release_form(). - * - * @ingroup project_release_node - */ -function project_release_insert($node) { - module_load_include('inc', 'project_release', 'includes/release_node_form'); - project_release_db_save($node, true); -} - -/** - * Implementation of hook_update(). - * - * @param $node - * Object containing form values from the project_release node form. Even - * though this is NOT a fully loaded $node object, the release-related - * values are in the $node->project_release array due to manual #tree and - * #parents hacking in project_release_form(). - * - * @ingroup project_release_node - */ -function project_release_update($node) { - module_load_include('inc', 'project_release', 'includes/release_node_form'); - project_release_db_save($node, false); -} - -/** * Verifies the data for supported release versions, and updates if necessary. * * @param $pid @@ -488,211 +341,9 @@ function project_release_compute_update_status($pid, $api_tid, $major) { } /** - * Implementation of hook_delete(). - * @ingroup project_release_node - */ -function project_release_delete($node) { - if (!empty($node->project_release['files'])) { - foreach ($node->project_release['files'] as $fid => $file) { - project_release_file_delete($file); - } - } - db_query("DELETE FROM {project_release_package_errors} WHERE nid = %d", $node->nid); - db_query("DELETE FROM {project_release_nodes} WHERE nid = %d", $node->nid); -} - -/** - * Deletes release files. - * - * @param $file - * The file object to delete. - */ -function project_release_file_delete($file) { - db_query("DELETE FROM {files} WHERE fid = %d", $file->fid); - db_query("DELETE FROM {project_release_file} WHERE fid = %d", $file->fid); - file_delete(file_create_path($file->filepath)); -} - -/** * @defgroup project_release_api Project release functions that other * modules might want to use */ - -/** - * Returns the version format string for a given project - * @ingroup project_release_api - */ -function project_release_get_version_format($project) { - if (!empty($project->project_release['version_format'])) { - return $project->project_release['version_format']; - } - - $db_format = db_result(db_query("SELECT version_format FROM {project_release_projects} WHERE nid = %d", $project->nid)); - if (!empty($db_format)) { - return $db_format; - } - - return variable_get('project_release_default_version_format', PROJECT_RELEASE_DEFAULT_VERSION_FORMAT); -} - -/** - * Validates a version format string. Only alphanumeric characters and - * [-_.] are allowed. Calls form_set_error() on error, else returns. - * @param $form_values Array of form values passed to validate hook. - * @param $element The name of the form element for the format string. - * @ingroup project_release_internal - */ -function _project_release_validate_format_string($form_values, $element) { - if (!preg_match('/^[a-zA-Z0-9_\-.!%#]+$/', $form_values[$element])) { - form_set_error($element, PROJECT_RELEASE_VERSION_FORMAT_VALID_MSG); - } -} - -/** - * Returns the formatted version string for a given version object. - * - * @param $version - * Object containing the separate version-related fields, such as - * version_major, version_minor, etc. - * @param $project - * Optional project node that the version corresponds with. If not defined, - * the version object should at least include a "pid" field. - * - * @return - * The formatted version string for the given version and project info. - * - * @ingroup project_release_api - */ -function project_release_get_version($version, $project = NULL) { - if (isset($project)) { - $node = $project; - } - else { - $node->nid = $version->pid; - } - $variables = array(); - foreach (array('major', 'minor', 'patch', 'extra') as $field) { - $var = "version_$field"; - if (isset($version->$var) && $version->$var !== '') { - $variables["!$field"] = $version->$var; - $variables["%$field"] = '.'. $version->$var; - $variables["#$field"] = '-'. $version->$var; - } - else { - $variables["!$field"] = ''; - $variables["%$field"] = ''; - $variables["#$field"] = ''; - } - } - $vid = _project_release_get_api_vid(); - if (project_release_get_api_taxonomy() && isset($version->version_api_tid)) { - $term = taxonomy_get_term($version->version_api_tid); - $variables["!api"] = $term->name; - $variables["%api"] = '.'. $term->name; - $variables["#api"] = '-'. $term->name; - } - else { - $variables["!api"] = ''; - $variables["%api"] = ''; - $variables["#api"] = ''; - } - $version_format = project_release_get_version_format($node); - return strtr($version_format, $variables); -} - -/** - * Implementation of hook_view(). - * @ingroup project_release_node - */ -function project_release_view($node, $teaser = FALSE, $page = FALSE) { - $node = node_prepare($node, $teaser); - $project = node_load($node->project_release['pid']); - - if ($page) { - // Breadcrumb navigation - $breadcrumb[] = l($project->title, 'node/'. $project->nid); - $breadcrumb[] = l(t('Releases'), 'node/'. $project->nid .'/release'); - project_project_set_breadcrumb($project, $breadcrumb); - } - - $output = ''; - $max_file_timestamp = 0; - if (!empty($node->project_release['files'])) { - $view_info = variable_get('project_release_files_view', 'project_release_files:default'); - list($view_name, $display_name) = split(':', $view_info); - $output .= views_embed_view($view_name, $display_name, $node->nid); - foreach ($node->project_release['files'] as $file) { - $max_file_timestamp = max($max_file_timestamp, $file->timestamp); - } - $node->content['release_file_info'] = array( - '#value' => '
'. $output .'
', - '#weight' => -4, - ); - } - - $output = ''; - if (project_use_cvs($project) && isset($node->project_release['tag'])) { - if (!empty($node->project_release['rebuild'])) { - $output .= t('Nightly development snapshot from CVS branch: @tag', array('@tag' => $node->project_release['tag'])) .'
'; - } - else { - $output .= t('Official release from CVS tag: @tag', array('@tag' => $node->project_release['tag'])) .'
'; - } - } - - if (!empty($max_file_timestamp)) { - $output .= '
' . t('Last updated: !changed', array('!changed' => format_date($max_file_timestamp))) . '
'; - } - - if (module_exists('project_usage') && user_access('view project usage')) { - $output .= ''; - } - $node->content['release_info'] = array( - '#value' => '
'. $output .'
', - '#weight' => -3, - ); - - if (module_exists('project_package')) { - $output = ''; - if (!empty($node->project_package['count'])) { - $view_info = variable_get('project_package_release_items_view', 'project_package_items:default'); - list($view_name, $display_name) = split(':', $view_info); - $output .= '

' . t('In this package') . '

'; - $output .= views_embed_view($view_name, $display_name, $node->nid); - } - if (!empty($output)) { - $node->content['release_package_items'] = array( - '#value' => '
'. $output .'
', - '#weight' => -2, - ); - } - } - - // Display packaging errors to admins. - if (project_user_access($node->project_release['pid'], 'administer releases')) { - $rows = array(); - $result = db_query('SELECT * FROM {project_release_package_errors} WHERE nid = %d', $node->nid); - $error = db_fetch_object($result); - if (!empty($error)) { - $rows = unserialize($error->messages); - if (!empty($rows)) { - $node->content['release_errors'] = array( - '#value' => theme('item_list', $rows, t('Packaging error messages')), - '#weight' => -1, - '#prefix' => '
', - '#suffix' => '
', - ); - } - } - } - - return $node; -} - -function project_release_load_file($fid) { - return db_fetch_object(db_query("SELECT f.*, prf.filehash, prf.weight FROM {project_release_file} prf INNER JOIN {files} f ON prf.fid = f.fid WHERE f.fid = %d", $fid)); -} - function theme_project_release_download_file($file, $download_link = TRUE) { $output = ''; if ($download_link) { @@ -707,102 +358,6 @@ function theme_project_release_download_file($file, $download_link = TRUE) { return $output; } -/* - @TODO: This function is used by project_issue, so we need to keep it here, - even though we're now creating the list of releases at node/XXX/release using - the views module. however, it might be nice if we could replace this function - with views as well just to use views's query builder. Maybe that's a bad - idea in terms of performance, however. -*/ -/** - * Get an array of release nodes - * @ingroup project_release_api - * - * @param $project - * The project node object. - * @param $nodes - * If set, an array of release nodes will be returned. - * Otherwise only the version field will be returned in the array value. - * @param $sort_by - * This can be 'date' or 'version' and determines how the releases - * returned are to be sorted. - * @param $filter_by - * This can be 'all' to include all releases or 'files' to return - * only releases which have a file attached. - * @param $rids - * This is a special parameter that can be used to allow one or more - * releases to be returned even if the node itself is unpublished. - * This is useful when this function is called by the project_issue - * module to allow a user to keep the version of an issue unchanged - * even if the release represented by the version is now unpublished. - * @return - * An array of releases. The keys are the release node nids. The values - * will either be release objects or release version strings, depending - * on the value of the $nodes parameter. - */ -function project_release_get_releases($project, $nodes = TRUE, $sort_by = 'version', $filter_by = 'all', $rids = array()) { - if ($sort_by == 'date') { - $order_by = 'n.created'; - } - else { - $order_by = 'r.version'; - } - $where = ''; - $join = ''; - $args = array($project->nid); - if (!project_user_access($project, 'administer releases')) { - if (!empty($rids)) { - $where = "AND (n.status = %d OR n.nid IN (". db_placeholders($rids) ."))"; - $args[] = 1; - foreach ($rids as $rid) { - $args[] = $rid; - } - } - else { - $where = 'AND (n.status = %d)'; - $args[] = 1; - } - if ($filter_by == 'files') { - $join .= "INNER JOIN {project_release_file} prf ON n.nid = prf.nid"; - } - } - - $result = db_query(db_rewrite_sql("SELECT n.nid, r.* FROM {node} n INNER JOIN {project_release_nodes} r $join ON r.nid = n.nid WHERE (r.pid = %d) $where ORDER BY $order_by DESC"), $args); - $releases = array(); - while ($obj = db_fetch_object($result)) { - if ($nodes) { - $releases[$obj->nid] = node_load($obj->nid); - } - else { - $releases[$obj->nid] = $obj->version; - } - } - return $releases; -} - - -/** - * @defgroup project_release_callback Menu callback functions - */ - -/** - * Returns a listing of all active project release compatibility terms - * in the system. - * @ingroup project_release_api - */ -function project_release_compatibility_list() { - static $terms = array(); - if (empty($terms) && $tree = project_release_get_api_taxonomy()) { - $tids = variable_get('project_release_active_compatibility_tids', array()); - foreach ($tree as $term) { - if (($tids && !empty($tids[$term->tid])) || !$tids) { - $terms[$term->tid] = $term->name; - } - } - } - return $terms; -} - /** * @defgroup project_release_fapi Form API hooks */ @@ -812,9 +367,6 @@ function project_release_compatibility_list() { * @ingroup project_release_fapi */ function project_release_form_alter(&$form, &$form_state, $form_id) { - if ($form_id == 'project_project_node_form') { - return project_release_alter_project_form($form, $form_state); - } if ($form_id == 'project_release_node_form') { return project_release_alter_release_form($form, $form_state); } @@ -830,83 +382,6 @@ function project_release_form_alter(&$form, &$form_state, $form_id) { } /** - * Alters the project_project node form to add release settings. - * @ingroup project_release_fapi - * @see project_release_form_alter - */ -function project_release_alter_project_form(&$form) { - if (!empty($form['project_node']['project']['uri']['#description'])) { - $form['project_node']['project']['uri']['#description'] .= ' ' . t('This string is also used to generate the name of releases associated with this project.'); - } - else { - $form['project_node']['project']['uri']['#description'] = t('This string is used to generate the name of releases associated with this project.'); - } -} - -/** - * Alters the project_release node form to handle the API taxonomy. - * If the vocabulary is empty, this removes the form elements. - * @ingroup project_release_fapi - * @see project_release_form_alter - */ -function project_release_alter_release_form(&$form, &$form_state) { - global $user; - $node = $form['#node']; - $tid = ''; - if (!empty($node->project_release['version_api_tid'])) { - $tid = $node->project_release['version_api_tid']; - } - $vid = _project_release_get_api_vid(); - if (!project_release_get_api_taxonomy() && isset($form['taxonomy'][$vid])) { - unset($form['taxonomy'][$vid]); - } - else { - if (!user_access('administer projects')) { - // The user doesn't have 'administer projects' permission, so - // we restrict their options for the compatibility taxonomy. - if (!empty($tid)) { - // If we already have the term, we want to force it to stay. - $indexes = form_get_options($form['taxonomy'][$vid], $tid); - if ($indexes !== FALSE) { - foreach ($indexes as $index) { - $options[] = $form['taxonomy'][$vid]['#options'][$index]; - } - } - $form['taxonomy'][$vid]['#default_value'] = $tid; - } - elseif ($tids = variable_get('project_release_active_compatibility_tids', array())) { - // We don't have the term since we're adding a new release. - // Restrict to the active terms (if any). - foreach (array_filter($tids) as $tid) { - $indexes = form_get_options($form['taxonomy'][$vid], $tid); - - if ($indexes !== FALSE) { - foreach ($indexes as $index) { - $options[$index] = $form['taxonomy'][$vid]['#options'][$index]; - } - } - } - } - if (!empty($options)) { - $form['taxonomy'][$vid]['#options'] = $options; - } - else { - unset($form['taxonomy'][$vid]); - } - // If they're not project admins, remove the delete button (if any). - unset($form['delete']); - } - } - // If there are no children elements, we should unset the entire - // thing so we don't end up with an empty fieldset. - if (isset($form['taxonomy']) && !element_children($form['taxonomy'])) { - unset($form['taxonomy']); - } - - $form['buttons']['submit']['#submit'][] = 'project_release_node_submit'; -} - -/** * Alters the project settings form. */ function project_release_alter_project_settings_form(&$form, &$form_state) { @@ -976,83 +451,6 @@ function project_release_project_promote_confirm_form_submit($form, &$form_state } /** - * @defgroup project_release_nodeapi Node API hooks - */ - -/** - * hook_nodeapi() implementation. This just decides what type of node - * is being passed, and calls the appropriate type-specific hook. - * @ingroup project_release_nodeapi - * @see project_release_project_nodeapi(). - */ -function project_release_nodeapi(&$node, $op, $arg) { - switch ($node->type) { - case 'project_project': - project_release_project_nodeapi($node, $op, $arg); - break; - case 'project_release': - project_release_release_nodeapi($node, $op, $arg); - break; - } -} - -/** - * hook_nodeapi implementation specific to "project_project" nodes - * (from the project.module) - * @ingroup project_release_nodeapi - * @see project_release_nodeapi(). - */ -function project_release_project_nodeapi(&$node, $op, $arg) { - switch ($op) { - case 'load': - project_release_project_nodeapi_load($node); - break; - - case 'insert': - project_release_project_nodeapi_insert($node); - break; - - case 'delete': - project_release_project_nodeapi_delete($node); - } -} - -/** - * Loads project_release fields into the project node object. - */ -function project_release_project_nodeapi_load(&$node) { - $project = db_fetch_object(db_query('SELECT * FROM {project_release_projects} WHERE nid = %d', $node->nid)); - if (!empty($project)) { - $fields = array('releases', 'version_format'); - foreach ($fields as $field) { - $node->project_release[$field] = $project->$field; - } - $wants_snapshots = db_result(db_query('SELECT tid FROM {project_release_supported_versions} WHERE nid = %d AND snapshot = %d LIMIT %d', $node->nid, 1, 1)); - if (isset($wants_snapshots)) { - $node->project_release['project_release_show_snapshots'] = TRUE; - } - } -} - -/** - * Insert release information about a project node. - */ -function project_release_project_nodeapi_insert(&$node) { - $releases = (!variable_get('project_release_sandbox_allow_release', TRUE) && $node->project['sandbox']) ? 0 : 1; - db_query("INSERT INTO {project_release_projects} (nid, releases, version_format) VALUES (%d, %d, '%s')", $node->nid, $releases, ''); -} - -/** - * Deletes release information when a project is deleted. - */ -function project_release_project_nodeapi_delete(&$node) { - // TODO: unpublish (delete?) all release nodes associated with - // this project, too. - db_query('DELETE FROM {project_release_projects} WHERE nid = %d', $node->nid); - -} - -/** * hook_nodeapi implementation specific to "project_release" nodes. * * We use hook_nodeapi() for our own node type to trigger some code that has @@ -1740,68 +1138,6 @@ function theme_project_release_download_text_unsupported($release, $text_type) { } /** - * Implementation of hook_taxonomy(). - */ -function project_release_taxonomy($op, $type, $array = NULL) { - if ($op == 'delete' && $type == 'vocabulary') { - if ($array['vid'] == _project_release_get_api_vid()) { - variable_del('project_release_api_vocabulary'); - } - elseif ($array['vid'] == _project_release_get_release_type_vid()) { - variable_del('project_release_release_type_vid'); - } - } - elseif ($type == 'term' && $array['vid'] == _project_release_get_api_vid()) { - menu_rebuild(); - } -} - -/** - * If taxonomy is enabled, returns the taxonomy tree for the - * API compatibility vocabulary, otherwise, it returns false. - */ -function project_release_get_api_taxonomy() { - if (!module_exists('taxonomy')) { - return false; - } - static $tree = NULL; - if (!isset($tree)) { - $tree = taxonomy_get_tree(_project_release_get_api_vid()); - } - return $tree; -} - -/** - * Returns the vocabulary id for project release API - */ -function _project_release_get_api_vid() { - return variable_get('project_release_api_vocabulary', ''); -} - -/** - * Return the taxonomy tree for the release type vocabulary (if any). - * - * If taxonomy is disabled, this returns false. - */ -function project_release_get_release_type_vocabulary() { - if (!module_exists('taxonomy')) { - return false; - } - static $tree = NULL; - if (!isset($tree)) { - $tree = taxonomy_get_tree(_project_release_get_release_type_vid()); - } - return $tree; -} - -/** - * Return the vocabulary id for project release type. - */ -function _project_release_get_release_type_vid() { - return variable_get('project_release_release_type_vid', ''); -} - -/** * Determine if a release already exists with the given version. * * @param stdClass $version @@ -1815,48 +1151,7 @@ function _project_release_get_release_type_vid() { * FALSE if no such release already exists. */ function project_release_exists($version) { - $values = array(); - $fields = array('version_major', 'version_minor', 'version_patch', 'version_api_tid'); - foreach ($fields as $field) { - if (isset($version->$field) && is_numeric($version->$field)) { - $types[$field] = "%d"; - $values[$field] = $version->$field; - $foo = $version->$field; - } - else { - $null_types[] = $field; - } - } - $fields = array('version', 'version_extra'); - foreach ($fields as $field) { - if (isset($version->$field) && $version->$field !== '') { - $types[$field] = "'%s'"; - $values[$field] = $version->$field; - $str = $version->$field; - } - elseif ($field == 'version_extra') { - $null_types[] = $field; - } - } - if (empty($types) && empty($null_types)) { - // We have nothing to query, yet... - return false; - } - - $sql = 'SELECT nid FROM {project_release_nodes} WHERE pid = %d'; - if (!empty($types)) { - foreach ($types as $field => $type) { - $sql .= " AND $field = $type"; - } - } - if (!empty($null_types)) { - foreach ($null_types as $field) { - $sql .= " AND $field IS NULL"; - } - } - // we put pid as the first WHERE, so stick it on the front - $values = array_merge(array('pid' => $version->pid), $values); - return db_result(db_query($sql, $values)); + // @todo } /** @@ -2041,123 +1336,6 @@ function theme_project_release_node_form_version_elements($form) { } /** - * Implement hook_token_list() (from token.module) - */ -function project_release_token_list($type) { - if ($type == 'node') { - $tokens['node'] = array( - 'project_release_pid' => t("A release's project nid"), - 'project_release_project_title' => t("A release's project title"), - 'project_release_project_title-raw' => t("A release's project title raw"), - 'project_release_project_shortname' => t("A release's project short name"), - 'project_release_version' => t("A release's version string"), - 'project_release_version_major' => t("A release's major version number"), - 'project_release_version_minor' => t("A release's minor version number"), - 'project_release_version_patch' => t("A release's patch version number"), - 'project_release_version_extra' => t("A release's extra version identifier"), - ); - if (project_release_compatibility_list()) { - $vocab = taxonomy_vocabulary_load(_project_release_get_api_vid()); - $tokens['node']['project_release_version_api_tid'] = t("A release's %api_compatibility term ID", array('%api_compatibility' => $vocab->name)); - $tokens['node']['project_release_version_api_term'] = t("A release's %api_compatibility term name", array('%api_compatibility' => $vocab->name)); - } - return $tokens; - } -} - -/** - * Implement hook_token_values() (from token.module). - */ -function project_release_token_values($type = 'all', $object = NULL) { - if ($type == 'node') { - // Defaults in case it's not a release or we run into other problems. - $values = array( - 'project_release_pid' => '', - 'project_release_project_title' => '', - 'project_release_project_title-raw' => '', - 'project_release_project_shortname' => '', - 'project_release_version' => '', - 'project_release_version_major' => '', - 'project_release_version_minor' => '', - 'project_release_version_patch' => '', - 'project_release_version_extra' => '', - 'project_release_version_api_tid' => '', - 'project_release_version_api_term' => '', - ); - if ($object->type == 'project_release') { - if ($project = node_load($object->project_release['pid'])) { - $values['project_release_pid'] = intval($object->project_release['pid']); - $values['project_release_project_title'] = check_plain($project->title); - $values['project_release_project_title-raw'] = $project->title; - $values['project_release_project_shortname'] = check_plain($project->project['uri']); - } - $values['project_release_version'] = check_plain($object->project_release['version']); - $values['project_release_version_major'] = check_plain($object->project_release['version_major']); - $values['project_release_version_minor'] = check_plain($object->project_release['version_minor']); - $values['project_release_version_patch'] = check_plain($object->project_release['version_patch']); - $values['project_release_version_extra'] = check_plain($object->project_release['version_extra']); - if (!empty($object->project_release['version_api_tid'])) { - $term = taxonomy_get_term($object->project_release['version_api_tid']); - $values['project_release_version_api_tid'] = check_plain($term->tid); - $values['project_release_version_api_term'] = check_plain($term->name); - } - } - return $values; - } -} - -/** - * Determines taxonomy-specific functionality for releases. - */ -function project_release_use_taxonomy() { - return module_exists('taxonomy') && _project_release_get_api_vid(); -} - -/** - * Implementation of hook_help(). - */ -function project_release_help($section) { - switch ($section) { - case 'admin/project/project-release-settings': - if (project_release_use_taxonomy()) { - return _project_release_taxonomy_help(); - } - break; - } - if (arg(0) == 'admin' && arg(1) == 'content' && arg(2) == 'taxonomy') { - $vid = _project_release_get_api_vid(); - if (arg(3) == $vid) { - return _project_release_taxonomy_help($vid, FALSE); - } - } -} - -/** - * Prints help message for release compatibility vocabulary configuration. - * - * @param $vid - * Vocabulary ID of the project taxonomy. - * @param $vocab_link - * Boolean that controls if a link to the vocabulary admin page is added. - */ -function _project_release_taxonomy_help($vid = 0, $vocab_link = TRUE) { - if (!$vid) { - $vid = _project_release_get_api_vid(); - } - if (empty($vid)) { - return; - } - $vocabulary = taxonomy_vocabulary_load($vid); - $text = '

'. t('The Project release module makes special use of the taxonomy (category) system. A special vocabulary, %vocabulary_name, has been created automatically.', array('%vocabulary_name' => $vocabulary->name)) .'

'; - $text .= '

'. t('To categorize project releases by their compatibility with a version of some outside software (eg. a library or API of some sort), add at least one term to this vocabulary. For example, you might add the following terms: "5.x", "6.x", "7.x".') .'

'; - $text .='

'. t('For more information, please see !url.', array('!url' => l('http://drupal.org/node/116544', 'http://drupal.org/node/116544'))) .'

'; - if ($vocab_link) { - $text .= '

'. t('Use the vocabulary admininistration page to view and add terms.', array('@taxonomy-admin' => url('admin/content/taxonomy/'. $vid))) .'

'; - } - return $text; -} - -/** * Implementation of hook_views_api(). */ function project_release_views_api() { -- 1.7.3.5