Index: project.css =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/project/project.css,v retrieving revision 1.35 diff -u -p -r1.35 project.css --- project.css 5 Jan 2007 00:21:08 -0000 1.35 +++ project.css 20 Jun 2008 23:17:53 -0000 @@ -1,5 +1,5 @@ /* $Id: project.css,v 1.35 2007/01/05 00:21:08 dww Exp $ */ -/* $Name: $ */ +/* $Name: HEAD $ */ .project table { width: auto; @@ -35,13 +35,11 @@ width: 150px; } -.project .node-form fieldset { - display: block; -} -.project .node-form .project-taxonomy-element { +.node-form .project-taxonomy-element { float: left; padding-right: 2em; } + ul.project-terms { padding-left: 1.5em; } Index: project.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/project/project.inc,v retrieving revision 1.124 diff -u -p -r1.124 project.inc --- project.inc 15 Mar 2008 20:09:39 -0000 1.124 +++ project.inc 20 Jun 2008 23:17:53 -0000 @@ -1,6 +1,6 @@ '; - /* Project taxonomy */ if (project_use_taxonomy()) { - drupal_add_js(drupal_get_path('module', 'project') .'/project.js'); - $tree = taxonomy_get_tree(_project_get_vid()); - $top_level = array(); - $options = array(); - foreach ($tree as $i => $term) { - if ($term->parents[0] == 0) { - $last_top = $term->tid; - $top_level[$term->tid] = check_plain($term->name); - } - else { - $options[$last_top][$term->tid] = $term->name; - } - } - // See if there are any project specific taxonomy terms already - // saved in this node (i.e. we're editing an existing project) and - // if so, extract the right default values for our custom form - // elements... - if ($node->taxonomy) { - foreach ($node->taxonomy as $tid => $obj) { - if ($top_level[$tid]) { - $current_top = $tid; - } - else { - $current_options[$tid] = $tid; - } - } - } - $form['project_taxonomy'] = array( - '#type' => 'fieldset', - '#weight' => '-30', - '#title' => t('Project categories'), - '#collapsible' => TRUE, - ); - $form['project_taxonomy']['project_type'] = array( - '#title' => t('Project type'), - '#type' => 'radios', - '#prefix' => '
'. t('To take full advantage of project categorization, add at least two levels of terms to this vocabulary. The first level will be the basic project types, e.g., "Modules", "Themes", "Translations".') .'
'; $text .= ''. t('Subterms of each of these types will be the categories that users can select to classify the projects. For example, "Modules" might have sub-terms including "Mail" and "XML".') .'
'; @@ -51,6 +51,9 @@ function _project_taxonomy_help($vid = 0 function project_block($op = 'list', $delta = 0) { if ($op == 'list') { $blocks[0]['info'] = t('Project navigation'); + // Note: We can get by with using BLOCK_CACHE_PER_ROLE below because + // block caching is disabled when node access control modules are in use. + $blocks[0]['cache'] = BLOCK_CACHE_PER_ROLE; return $blocks; } else if ($op == 'view') { @@ -211,41 +214,44 @@ function project_find_alias($query, $tab * Callback for the main settings page. */ function project_settings_form() { - $sort_methods = drupal_map_assoc(array_keys(module_invoke_all('project_sort_methods', 'methods'))); - - if (project_use_taxonomy()) { - - // For now, date-based browsing doesn't work once you disable - // taxonomy (only because the code involved is rather complicated - // and needs to be majorly refactored and cleaned up). - $form['project_sort_method'] = array( - '#type' => 'radios', - '#title' => t('Default sort option'), - '#default_value' => variable_get('project_sort_method', 'category'), - '#options' => $sort_methods, - '#description' => t('Default sorting option to use on the overview page'), - ); - $form['sort_methods'] = array( - '#type' => 'fieldset', - '#title' => t('Enabled sorting options'), - '#description' => t('Each type of project on your site will have its own project browsing page at %link. Each browsing page can be configured for different browsing options (by name, by date, etc). The settings below determine which browsing methods are available for each project type.', array('%link' => url('project', NULL, NULL, TRUE) . '/[type]')), - ); - $tree = taxonomy_get_tree(_project_get_vid(), 0 , -1, 1); - foreach ($tree as $term) { - $form['sort_methods']['project_sort_method_used_' . $term->tid] = array( - '#type' => 'checkboxes', - '#title' => $term->name, - '#default_value' => array_filter(variable_get('project_sort_method_used_'. $term->tid, array_keys($sort_methods))), - '#options' => $sort_methods, - ); - } - } - $form['project_browse_nodes'] = array( - '#type' => 'select', '#title' => t('Number of projects to list in paged browsing'), - '#default_value' => variable_get('project_browse_nodes', 30), - '#options' => drupal_map_assoc(array(5, 10, 15, 20, 25, 30, 35, 40, 45, 50)), - '#description' => t('The default maximum number of projects to list when browsing lists, e.g., by category.') - ); + $form = array(); + // @TODO: We should be able to delete these settings below since they won't + // be necessary with views handling project browsing. + //$sort_methods = drupal_map_assoc(array_keys(module_invoke_all('project_sort_methods', 'methods'))); + // + //if (project_use_taxonomy()) { + // + // // For now, date-based browsing doesn't work once you disable + // // taxonomy (only because the code involved is rather complicated + // // and needs to be majorly refactored and cleaned up). + // $form['project_sort_method'] = array( + // '#type' => 'radios', + // '#title' => t('Default sort option'), + // '#default_value' => variable_get('project_sort_method', 'category'), + // '#options' => $sort_methods, + // '#description' => t('Default sorting option to use on the overview page'), + // ); + // $form['sort_methods'] = array( + // '#type' => 'fieldset', + // '#title' => t('Enabled sorting options'), + // '#description' => t('Each type of project on your site will have its own project browsing page at %link. Each browsing page can be configured for different browsing options (by name, by date, etc). The settings below determine which browsing methods are available for each project type.', array('%link' => url('project', array('absolute' => TRUE)) . '/[type]')), + // ); + // $tree = taxonomy_get_tree(_project_get_vid(), 0 , -1, 1); + // foreach ($tree as $term) { + // $form['sort_methods']['project_sort_method_used_' . $term->tid] = array( + // '#type' => 'checkboxes', + // '#title' => $term->name, + // '#default_value' => array_filter(variable_get('project_sort_method_used_'. $term->tid, array_keys($sort_methods))), + // '#options' => $sort_methods, + // ); + // } + //} + //$form['project_browse_nodes'] = array( + // '#type' => 'select', '#title' => t('Number of projects to list in paged browsing'), + // '#default_value' => variable_get('project_browse_nodes', 30), + // '#options' => drupal_map_assoc(array(5, 10, 15, 20, 25, 30, 35, 40, 45, 50)), + // '#description' => t('The default maximum number of projects to list when browsing lists, e.g., by category.') + //); return system_settings_form($form); } @@ -286,11 +292,14 @@ function _project_get_vid() { * Implementation of hook_term_path(). */ function project_term_path($term) { + // Make sure we have the entire term object. + $term = taxonomy_get_term($term->tid); + // The path must include the first-level term name for this term. $tree = taxonomy_get_tree(_project_get_vid()); $parents = taxonomy_get_parents_all($term->tid); foreach($parents as $parent) { - $ancestors[] = $parent->tid; + $ancestors[] = $parent->tid; } foreach ($tree as $t) { if (in_array($t->tid, $ancestors) && $t->depth == 0) { @@ -316,102 +325,142 @@ function project_taxonomy($op, $type, $a } } -function project_menu($may_cache) { +/** + * Determine if the currently logged in user could have access to any project_project nodes. + */ +function project_project_access_any() { + return user_access('access projects') || user_access('access own projects') || user_access('administer projects'); +} + +function project_menu() { $items = array(); - global $user; - if ($may_cache) { - // User pages: - $access_all = user_access('access projects'); - $access_own = user_access('access own projects'); - $access_admin = user_access('administer projects'); - $access = $access_all || $access_own || $access_admin; - - $items[] = array('path' => 'project', - 'title' => t('Projects'), - 'callback' => 'project_page_overview', - 'access' => $access, - 'type' => MENU_NORMAL_ITEM); - - $items[] = array('path' => 'project/autocomplete', - 'title' => t('Autocomplete project'), - 'callback' => 'project_autocomplete', - 'access' => $access, - 'type' => MENU_CALLBACK); - - // Project browsing pages - if (project_use_taxonomy()) { - $default_sort = variable_get('project_sort_method', 'category'); - $sort_methods = module_invoke_all('project_sort_methods', 'methods'); - $terms = taxonomy_get_tree(_project_get_vid()); - $releases = variable_get('project_release_browse_versions', 0); - foreach ($terms as $i => $term) { - // Only use the first-level terms. - if ($term->depth == 0) { - $items[] = array('path' => 'project/'. $term->name, - 'title' => $term->name, - 'access' => $access, - 'type' => MENU_NORMAL_ITEM, - 'weight' => $term->weight, - 'callback arguments' => array($term->name)); - $j = 0; - $term_methods = array_keys(array_filter(variable_get('project_sort_method_used_'. $term->tid, $sort_methods))); - foreach ($term_methods as $sort_method) { - $items[] = array('path' => 'project/' . $term->name . '/'. $sort_method, - 'title' => t('Browse by !sort_method', array('!sort_method' => $sort_method)), - 'access' => $access, - // It's a default task if a) sort method matches default, or b) default sort isn't - // in the list of sort methods, and it's the first tab. - 'type' => (($sort_method == $default_sort || (($j == 0) && !in_array($default_sort, $term_methods))) ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK), - 'weight' => ($sort_method == $default_sort) ? -10 : $j, - 'callback arguments' => array($term->name, $sort_method)); - $j++; - } - } - } - } + // @TODO: This menu definition should be deleted. Make sure that views only shows + // this menu item when the user has the appropriate access privs. + //$items['project'] = array( + // 'title' => 'Projects', + // 'page callback' => 'project_page_overview', + // 'access callback' => 'project_project_access_any', + // 'type' => MENU_NORMAL_ITEM); + + $items['project/autocomplete'] = array( + 'title' => 'Autocomplete project', + 'page callback' => 'project_autocomplete', + 'access callback' => 'project_project_access_any', + 'type' => MENU_CALLBACK); + + // Project browsing pages + // TODO: We can remove this block below when we add views support. + //if (project_use_taxonomy()) { + // $default_sort = variable_get('project_sort_method', 'category'); + // $sort_methods = module_invoke_all('project_sort_methods', 'methods'); + // $terms = taxonomy_get_tree(_project_get_vid()); + // $releases = variable_get('project_release_browse_versions', 0); + // foreach ($terms as $i => $term) { + // // Only use the first-level terms. + // if ($term->depth == 0) { + // $items['project/'. $term->name] = array( + // 'title' => $term->name, // TODO: Fix? + // 'access callback' => 'project_check_access_any', + // 'type' => MENU_NORMAL_ITEM, + // 'weight' => $term->weight, + // 'page arguments' => array($term->name), + // ); + // $j = 0; + // $term_methods = array_keys(array_filter(variable_get('project_sort_method_used_'. $term->tid, $sort_methods))); + // foreach ($term_methods as $sort_method) { + // $items['project/' . $term->name . '/'. $sort_method] = array( + // 'title' => "Browse by $sort_method", // TODO: Fix? + // 'access callback' => 'project_check_access_any', + // // It's a default task if a) sort method matches default, or b) default sort isn't + // // in the list of sort methods, and it's the first tab. + // 'type' => (($sort_method == $default_sort || (($j == 0) && !in_array($default_sort, $term_methods))) ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK), + // 'weight' => ($sort_method == $default_sort) ? -10 : $j, + // 'page arguments' => array($term->name, $sort_method)); + // $j++; + // } + // } + // } + //} + + // Developers + $items['project/developers'] = array( + 'title' => 'Developers', + 'page callback' => 'project_developers', + 'access callback' => 'project_project_access_any', + 'type' => MENU_CALLBACK, + ); + + // CVS messages: + $items['project/cvs'] = array( + 'title' => 'CVS', + 'page callback' => 'project_cvs', + 'access callback' => 'project_project_access_any', + 'type' => MENU_CALLBACK, + ); + + // Administration pages + $items['admin/project'] = array( + 'title' => 'Project administration', + 'description' => 'Administrative interface for project management and related modules.', + 'page callback' => 'system_admin_menu_block_page', + 'access arguments' => array('administer projects'), + 'file' => 'system.admin.inc', + 'file path' => drupal_get_path('module', 'system'), + 'type' => MENU_NORMAL_ITEM, + ); + // @TODO: We can most likely delete this menu item, since there are + // no longer any project module specific settings since views is being used. + //$items['admin/project/project-settings'] = array( + // 'title' => 'Project settings', + // 'description' => 'Configure the behavior and appearance of the project browsing pages and other settings for the Project module.', + // 'page callback' => 'drupal_get_form', + // 'page arguments' => array('project_settings_form'), + // 'access arguments' => array('administer projects'), + // 'type' => MENU_NORMAL_ITEM, + //); + + $items['node/%project_edit_project/edit/project'] = array( + 'title' => 'Project', + 'page callback' => 'node_page', + 'page arguments' => array(1), + 'access callback' => 'node_access', + 'access arguments' => array('update', 1), + 'weight' => -5, 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + return $items; +} - // Developers - $items[] = array('path' => 'project/developers', 'title' => t('Developers'), 'callback' => 'project_developers', 'access' => $access, 'type' => MENU_CALLBACK); - // CVS messages: - $items[] = array('path' => 'project/cvs', 'title' => t('CVS'), 'callback' => 'project_cvs', 'access' => $access, 'type' => MENU_CALLBACK); +/** + * Implementation of hook_init(). + */ +function project_init() { + drupal_add_css(drupal_get_path('module', 'project') .'/project.css'); - // Administration pages - $items[] = array( - 'path' => 'admin/project', - 'title' => t('Project administration'), - 'description' => t('Administrative interface for project management and related modules.'), - 'callback' => 'system_admin_menu_block_page', - 'access' => $access_admin, - 'type' => MENU_NORMAL_ITEM, - ); - $items[] = array( - 'path' => 'admin/project/project-settings', - 'title' => t('Project settings'), - 'description' => t('Configure the behavior and appearance of the project browsing pages and other settings for the Project module.'), - 'callback' => 'drupal_get_form', - 'callback arguments' => array('project_settings_form'), - 'access' => $access_admin, - 'type' => MENU_NORMAL_ITEM, - ); + if (module_exists('views')) { + module_load_include ('inc', 'project', 'project.views'); } - else { - drupal_add_css(drupal_get_path('module', 'project') .'/project.css'); - if (arg(0) == 'node' && is_numeric(arg(1))) { - $node = node_load(arg(1)); - if ($node->type == 'project_project' && node_access('update', $node) && - (module_exists('project_issue') || module_exists('project_release'))) { - $items[] = array( - 'path' => 'node/'. arg(1) .'/edit/project', - 'title' => t('Project'), - 'callback' => 'node_page', - 'weight' => -5, 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - } - } +} + +/** + * Menu loader callback. Load a project_project node if the given + * nid is a project_project node and if the user has permission to edit + * the project and if either the project_issue or project_release module + * exists. + */ +function project_edit_project_load($nid) { + if (!is_numeric($nid)) { + return FALSE; } - return $items; + $node = node_load($nid); + if (!isset($node->type) || $node->type != 'project_project') { + return FALSE; + } + if (!module_exists('project_issue') && !module_exists('project_release')) { + return FALSE; + } + return $node; } function project_check_admin_access($project, $cvs_access = NULL) { @@ -432,7 +481,7 @@ function project_check_admin_access($pro // If $cvs_access is not defined, check to make sure the user has cvs access // and that the user's cvs account is approved. if (project_use_cvs($project_obj) && !isset($cvs_access)) { - if (db_num_rows(db_query("SELECT * FROM {cvs_accounts} WHERE uid = %d AND status = %d", $user->uid, CVS_APPROVED))) { + if (db_result(db_query("SELECT COUNT(*) FROM {cvs_accounts} WHERE uid = %d AND status = %d", $user->uid, CVS_APPROVED))) { $cvs_access = TRUE; } else { @@ -445,7 +494,7 @@ function project_check_admin_access($pro return TRUE; } if (project_use_cvs($project_obj) && $cvs_access) { - if (db_num_rows(db_query("SELECT * FROM {cvs_project_maintainers} WHERE uid = %d AND nid = %d", $user->uid, $project_obj->nid))) { + if (db_result(db_query("SELECT COUNT(*) FROM {cvs_project_maintainers} WHERE uid = %d AND nid = %d", $user->uid, $project_obj->nid))) { return TRUE; } } @@ -458,7 +507,7 @@ function project_check_admin_access($pro * taxonomy.module's form_alter() so we can do our own taxonomy * selection. */ -function project_form_alter($form_id, &$form) { +function project_form_alter(&$form, &$form_state, $form_id) { if ($form_id == 'project_project_node_form') { $vid = _project_get_vid(); if (isset($form['taxonomy'][$vid])) { @@ -466,7 +515,7 @@ function project_form_alter($form_id, &$ } // If there are no children elements, we should unset the entire // thing so we don't end up with an empty fieldset. - if (!element_children($form['taxonomy'])) { + if (!empty($form['taxonomy']) && (!element_children($form['taxonomy']))) { unset($form['taxonomy']); } @@ -514,311 +563,312 @@ function project_page() { } } +// @TODO Delete this function if possible. function project_page_overview($termname = NULL, $sort_method = NULL) { - global $form_values; - - project_project_set_breadcrumb(); - $sort_methods = module_invoke_all('project_sort_methods', 'methods'); - - $output = ''; - if (module_exists('project_release') && variable_get('project_release_browse_versions', 0)) { - $version_form = drupal_get_form('project_release_version_filter_form'); - $output .= $version_form; - // Read in requested version, if any. - $version = isset($_SESSION['project_version']) ? $_SESSION['project_version'] : variable_get('project_release_overview', -1); - } - - // If browsing by taxonomy, only fetch projects for this term. - if (project_use_taxonomy()) { - $vid = _project_get_vid(); - if ($termname) { - - $type = db_fetch_object(db_query(db_rewrite_sql("SELECT t.tid, t.* FROM {term_data} t INNER JOIN {term_hierarchy} th ON t.tid = th.tid WHERE t.vid = %d AND th.parent = 0 AND t.name = '%s'", 't', 'tid'), $vid, $termname)); - // Bad project category passed, return page not found. - if (!$type) { - return drupal_not_found(); - } - if (!$sort_method) { - // For the default, we use the overall default if enabled for this term, and if not we use the first enabled method. - $term_methods = array_filter(variable_get('project_sort_method_used_' . $type->tid, array_keys($sort_methods))); - $sort_method = in_array(variable_get('project_sort_method', 'category'), $term_methods) ? variable_get('project_sort_method', 'category') : array_shift($term_methods); - } - - if ($type->description) { - $output .= '' . filter_xss($type->description) . '
'; - } - - $module = $sort_methods[$sort_method]; - // Bad sort method passed, return page not found. - if (!isset($module)) { - return drupal_not_found(); - } - if (module_invoke($module, 'project_sort_methods', 'set term', $sort_method)) { - $tree = taxonomy_get_tree(_project_get_vid(), $type->tid); - $terms = array(); - if ($tree) { - $tids = array(); - if (variable_get('project_release_browse_versions', 0)) { - $version_params = array(); - if ($version != -1) { - $version_where = 'tr.tid = %d'; - $version_params[] = $version; - } - else { - $placeholders = array(); - $active_tids = project_release_compatibility_list(); - foreach ($active_tids as $tid => $api_term) { - $placeholders[] = '%d'; - $version_params[] = $tid; - } - $version_where = 'tr.tid IN ('. implode(',', $placeholders) .')'; - } - // Find all terms associated with the requested version. - $result = db_query("SELECT tp.tid, COUNT(DISTINCT(n.nid)) AS count FROM {term_node} tp INNER JOIN {project_release_nodes} p ON tp.nid = p.pid INNER JOIN {node} n ON n.nid = p.pid INNER JOIN {term_node} tr ON tr.nid = p.nid WHERE $version_where AND (n.status = 1) GROUP BY tp.tid", $version_params); - $tids = array(); - while ($item = db_fetch_object($result)) { - $tids[$item->tid] = $item->count; - } - } - foreach ($tree as $cterm) { - if (!variable_get('project_release_browse_versions', 0) || ($version == -1) || array_key_exists($cterm->tid, $tids)) { - if ($tids[$cterm->tid]) { - $cterm->count = $tids[$cterm->tid]; - } - else { - // We don't use taxonomy_term_count_nodes() because it includes child terms' counts. - $result = db_query(db_rewrite_sql('SELECT t.tid, COUNT(n.nid) AS c FROM {term_node} t INNER JOIN {node} n ON t.nid = n.nid WHERE n.status = 1 AND t.tid = %d GROUP BY t.tid'), $cterm->tid); - $term = db_fetch_object($result); - $cterm->count = $term->c; - } - $terms[] = $cterm; - } - } - } - - // Look for a specific category term. - if ($arg = arg(3)) { - // Bad term, return page not found. - if (!($term = taxonomy_get_term($arg))) { - return drupal_not_found(); - } - } - } - // The sorting method is not supported by the module, so any term passed is invalid. - // Return page not found if one is found. - elseif (arg(3)) { - return drupal_not_found(); - } - - // Set the default elements that will be used to construct the SQL statement. - $sql_elements = project_empty_query(); - $sql_elements['fields']['pieces'] = array( - 'DISTINCT(n.nid)', - 'n.title', - 'n.sticky', - 'n.type', - 'nr.teaser', - 'nr.format', - ); - $sql_elements['from']['pieces'] = array( - '{node} n ' - ); - $sql_elements['joins']['pieces'] = array( - 'INNER JOIN {node_revisions} nr ON n.vid = nr.vid', - 'INNER JOIN {project_projects} p ON n.nid = p.nid', - 'LEFT JOIN {term_node} r ON n.nid = r.nid' - ); - $sql_elements['wheres']['pieces'] = array( - 'n.status = 1', - 'r.tid = %d' - ); - $sql_elements['parameters']['pieces'] = array( - isset($term) ? $term->tid : $type->tid - ); - - // If the site has enabled issue tracking via the project_issue - // module, we want to add 1 more field and JOIN to our query so - // we can provide the link for "Bugs and feature requests"... - if (module_exists('project_issue')) { - $sql_elements['fields']['pieces'][] = 'pip.issues'; - $sql_elements['joins']['pieces'][] = 'INNER JOIN {project_issue_projects} pip ON n.nid = pip.nid'; - } - - // Only the 'pieces' are returned; the prefix and glue elements remain unchanged. - $sql_settings = module_invoke($module, 'project_sort_methods', 'sql_settings', $sort_method); - if (empty($sql_settings)) { - $sql_settings = array(); - } - - if (module_exists('project_release')) { - $project_release_sql = array( - 'joins' => array('INNER JOIN {project_release_projects} prp ON n.nid = prp.nid'), - 'wheres' => array('prp.releases = 1'), - ); - $sql_settings = array_merge_recursive($sql_settings, $project_release_sql); - } - - if (variable_get('project_release_browse_versions', 0)) { - $release_settings = array( - 'fields' => array('prn.file_path', 'prn.version', 'MAX(prn.file_date) AS changed', 'COUNT(*) AS release_count'), - 'group_bys' => array('n.nid'), - ); - $release_settings['joins'] = array( - 'INNER JOIN {project_release_nodes} prn ON n.nid = prn.pid', - 'INNER JOIN {term_node} tr ON tr.nid = prn.nid', - 'INNER JOIN {node} rn ON rn.nid = prn.nid', - ); - $release_settings['wheres'][] = 'rn.status = 1'; - if ($version != -1) { - $release_settings['joins'][] = 'INNER JOIN {project_release_supported_versions} prsv ON prsv.nid = p.nid AND prsv.tid = tr.tid'; - $release_settings['wheres'][] = 'tr.tid = %d'; - $release_settings['wheres'][] = 'prsv.supported = 1'; - $release_settings['parameters'][] = $version; - } - else { - $placeholders = array(); - $active_tids = project_release_compatibility_list(); - foreach ($active_tids as $tid => $compatibility_term) { - $placeholders[] = '%d'; - $release_settings['parameters'][] = $tid; - } - $where = 'tr.tid IN ('. implode(',', $placeholders) .')'; - $release_settings['wheres'][] = $where; - - // We need to grab the uid for the project node, so - // that node_access() will work properly without a full - // node_load() when we're generating the download table in - // project_release_table(). - $release_settings['fields'][] = 'n.uid'; - } - $sql_settings = array_merge_recursive($sql_settings, $release_settings); - } - - // Merge in $sql_elements - if (!empty($sql_settings)) { - foreach(array_keys($sql_settings) as $key) { - $sql_elements[$key]['pieces'] = array_merge($sql_elements[$key]['pieces'], $sql_settings[$key]); - $sql_elements[$key]['pieces'] = array_unique($sql_elements[$key]['pieces']); - } - } - - $parameters = $sql_elements['parameters']['pieces']; - - $sql = project_build_query($sql_elements); - - $pager = module_invoke($module, 'project_sort_methods', 'pager', $sort_method); - if ($pager) { - $first_field = array_shift($sql_elements['fields']['pieces']); - if (count($sql_elements['group_bys']['pieces'])) { - $first_field = 'DISTINCT(' . $sql_elements['group_bys']['pieces'][0] . ')'; - $sql_elements['group_bys']['pieces'] = array(); - } - $sql_elements['fields']['pieces'] = array("COUNT($first_field)"); - // ORDER BY can screw up COUNT(DISTINCT), and we don't care - // about the order for the count query. - unset($sql_elements['order_bys']); - $count_query = project_build_query($sql_elements); - $result = pager_query($sql, variable_get('project_browse_nodes', 30), 0, $count_query, $parameters); - } - else { - $result = db_query($sql, $parameters); - } - - // If we've just switched versions, we may have a term requested but no matching projects. - // In that case, we returned an uncollapsed fieldset. - if (module_invoke($module, 'project_sort_methods', 'set term', $sort_method)) { - $output .= theme('fieldset', array('#title' => t('Categories'), '#collapsible' => TRUE, '#collapsed' => (arg(3) && db_num_rows($result)) ? TRUE : FALSE, '#children' => theme('project_term_list', $terms, "project/$termname/$sort_method"))); - if (!arg(3) || !db_num_rows($result)) { - return $output; - } - drupal_set_title(t('@project_type: %category', array('@project_type' => $type->name, '%category' => $term->name))); - } - else { - drupal_set_title(check_plain($type->name)); - } - } - // If taxonomy is enabled but no termname is selected, show a list of terms to choose from. - else { - $tree = taxonomy_get_tree($vid, 0, -1, 1); - $items = array(); - foreach ($tree as $term) { - $items[] = theme('project_type', $term); - } - drupal_set_title(t('Project types')); - return theme('item_list', $items); - } - } - // If taxonomy is not enabled, fetch all projects - else { - // Any terms passed without taxonomy module enabled are bogus -- return page not found. - if (isset($termname)) { - return drupal_not_found(); - } - // If the site has enabled issue tracking via the project_issue - // module, we want to add 1 more field and JOIN to our query so - // we can provide the link for "Bugs and feature requests"... - if (module_exists('project_issue')) { - $ISSUES = ', pip.issues'; - $ISSUE_JOIN ='INNER JOIN {project_issue_projects} pip ON n.nid = pip.nid'; - } - $result = db_query(db_rewrite_sql("SELECT n.nid, n.title, nr.teaser, nr.format$ISSUES FROM {node} n INNER JOIN {node_revisions} nr ON n.vid = nr.vid $ISSUE_JOIN WHERE n.status = 1 AND n.type = 'project_project' ORDER BY n.title ASC")); - } - $projects = ''; - $class = 'even'; - while ($project = db_fetch_object($result)) { - $project->body = check_markup($project->teaser, $project->format, FALSE); - if (module_exists('taxonomy')) { - $project->taxonomy = taxonomy_node_get_terms($project->nid); - if (isset($type)) { - // Hide the top-level project type term from the links, but add it to - // the $project object for theme_project_summary() to use if it wants. - unset($project->taxonomy[$type->tid]); - $project->term = $termname; - } - $project->terms = taxonomy_link('taxonomy terms', $project); - } - - // Make sure we have the latest release - if (isset($project->release_count) && $project->release_count > 1 && $version != -1) { - $latest = db_fetch_object(db_query_range("SELECT file_path, version, file_date FROM {project_release_nodes} p INNER JOIN {node} n ON p.nid = n.nid INNER JOIN {term_node} t ON p.nid = t.nid LEFT JOIN {project_release_supported_versions} prsv ON p.pid = prsv.nid AND prsv.tid = t.tid AND prsv.major = p.version_major WHERE p.pid = %d AND t.tid = %d AND prsv.supported = 1 AND n.status = 1 ORDER BY prsv.nid DESC, p.rebuild ASC, p.version_major ASC, p.version_minor DESC, p.version_patch DESC, p.file_date DESC", $project->nid, $version, 0, 1)); - $project->file_path = $latest->file_path; - $project->version = $latest->version; - } - - $project->links = array(); - if ($version != -1) { - if ($project->file_path) { - $project->links['project_download'] = theme('project_release_download_link', $project->file_path, t('Download'), 'array'); - } - } - else { - $project->download_table = theme('project_release_table_overview', $project, 'recommended', 'all', t('Version'), FALSE); - } - - $project->links['project_more_info'] = array( - 'title' => t('Find out more'), - 'href' => "node/$project->nid", - ); - if ($project->issues) { - $project->links['project_issues'] = array( - 'title' => t('Bugs and feature requests'), - 'href' => "project/issues/$project->nid", - ); - } - if (module_invoke($module, 'project_sort_methods', 'group by date', $sort_method) && $date = _project_date($project->changed)) { - $projects .= "' . filter_xss($type->description) . '
'; +// } +// +// $module = $sort_methods[$sort_method]; +// // Bad sort method passed, return page not found. +// if (!isset($module)) { +// return drupal_not_found(); +// } +// if (module_invoke($module, 'project_sort_methods', 'set term', $sort_method)) { +// $tree = taxonomy_get_tree(_project_get_vid(), $type->tid); +// $terms = array(); +// if ($tree) { +// $tids = array(); +// if (variable_get('project_release_browse_versions', 0)) { +// $version_params = array(); +// if ($version != -1) { +// $version_where = 'tr.tid = %d'; +// $version_params[] = $version; +// } +// else { +// $placeholders = array(); +// $active_tids = project_release_compatibility_list(); +// foreach ($active_tids as $tid => $api_term) { +// $placeholders[] = '%d'; +// $version_params[] = $tid; +// } +// $version_where = 'tr.tid IN ('. implode(',', $placeholders) .')'; +// } +// // Find all terms associated with the requested version. +// $result = db_query("SELECT tp.tid, COUNT(DISTINCT(n.nid)) AS count FROM {term_node} tp INNER JOIN {project_release_nodes} p ON tp.nid = p.pid INNER JOIN {node} n ON n.nid = p.pid INNER JOIN {term_node} tr ON tr.nid = p.nid WHERE $version_where AND (n.status = 1) GROUP BY tp.tid", $version_params); +// $tids = array(); +// while ($item = db_fetch_object($result)) { +// $tids[$item->tid] = $item->count; +// } +// } +// foreach ($tree as $cterm) { +// if (!variable_get('project_release_browse_versions', 0) || ($version == -1) || array_key_exists($cterm->tid, $tids)) { +// if ($tids[$cterm->tid]) { +// $cterm->count = $tids[$cterm->tid]; +// } +// else { +// // We don't use taxonomy_term_count_nodes() because it includes child terms' counts. +// $result = db_query(db_rewrite_sql('SELECT t.tid, COUNT(n.nid) AS c FROM {term_node} t INNER JOIN {node} n ON t.nid = n.nid WHERE n.status = 1 AND t.tid = %d GROUP BY t.tid'), $cterm->tid); +// $term = db_fetch_object($result); +// $cterm->count = $term->c; +// } +// $terms[] = $cterm; +// } +// } +// } +// +// // Look for a specific category term. +// if ($arg = arg(3)) { +// // Bad term, return page not found. +// if (!($term = taxonomy_get_term($arg))) { +// return drupal_not_found(); +// } +// } +// } +// // The sorting method is not supported by the module, so any term passed is invalid. +// // Return page not found if one is found. +// elseif (arg(3)) { +// return drupal_not_found(); +// } +// +// // Set the default elements that will be used to construct the SQL statement. +// $sql_elements = project_empty_query(); +// $sql_elements['fields']['pieces'] = array( +// 'DISTINCT(n.nid)', +// 'n.title', +// 'n.sticky', +// 'n.type', +// 'nr.teaser', +// 'nr.format', +// ); +// $sql_elements['from']['pieces'] = array( +// '{node} n ' +// ); +// $sql_elements['joins']['pieces'] = array( +// 'INNER JOIN {node_revisions} nr ON n.vid = nr.vid', +// 'INNER JOIN {project_projects} p ON n.nid = p.nid', +// 'LEFT JOIN {term_node} r ON n.nid = r.nid' +// ); +// $sql_elements['wheres']['pieces'] = array( +// 'n.status = 1', +// 'r.tid = %d' +// ); +// $sql_elements['parameters']['pieces'] = array( +// isset($term) ? $term->tid : $type->tid +// ); +// +// // If the site has enabled issue tracking via the project_issue +// // module, we want to add 1 more field and JOIN to our query so +// // we can provide the link for "Bugs and feature requests"... +// if (module_exists('project_issue')) { +// $sql_elements['fields']['pieces'][] = 'pip.issues'; +// $sql_elements['joins']['pieces'][] = 'INNER JOIN {project_issue_projects} pip ON n.nid = pip.nid'; +// } +// +// // Only the 'pieces' are returned; the prefix and glue elements remain unchanged. +// $sql_settings = module_invoke($module, 'project_sort_methods', 'sql_settings', $sort_method); +// if (empty($sql_settings)) { +// $sql_settings = array(); +// } +// +// if (module_exists('project_release')) { +// $project_release_sql = array( +// 'joins' => array('INNER JOIN {project_release_projects} prp ON n.nid = prp.nid'), +// 'wheres' => array('prp.releases = 1'), +// ); +// $sql_settings = array_merge_recursive($sql_settings, $project_release_sql); +// } +// +// if (variable_get('project_release_browse_versions', 0)) { +// $release_settings = array( +// 'fields' => array('prn.file_path', 'prn.version', 'MAX(prn.file_date) AS changed', 'COUNT(*) AS release_count'), +// 'group_bys' => array('n.nid'), +// ); +// $release_settings['joins'] = array( +// 'INNER JOIN {project_release_nodes} prn ON n.nid = prn.pid', +// 'INNER JOIN {term_node} tr ON tr.nid = prn.nid', +// 'INNER JOIN {node} rn ON rn.nid = prn.nid', +// ); +// $release_settings['wheres'][] = 'rn.status = 1'; +// if ($version != -1) { +// $release_settings['joins'][] = 'INNER JOIN {project_release_supported_versions} prsv ON prsv.nid = p.nid AND prsv.tid = tr.tid'; +// $release_settings['wheres'][] = 'tr.tid = %d'; +// $release_settings['wheres'][] = 'prsv.supported = 1'; +// $release_settings['parameters'][] = $version; +// } +// else { +// $placeholders = array(); +// $active_tids = project_release_compatibility_list(); +// foreach ($active_tids as $tid => $compatibility_term) { +// $placeholders[] = '%d'; +// $release_settings['parameters'][] = $tid; +// } +// $where = 'tr.tid IN ('. implode(',', $placeholders) .')'; +// $release_settings['wheres'][] = $where; +// +// // We need to grab the uid for the project node, so +// // that node_access() will work properly without a full +// // node_load() when we're generating the download table in +// // project_release_table(). +// $release_settings['fields'][] = 'n.uid'; +// } +// $sql_settings = array_merge_recursive($sql_settings, $release_settings); +// } +// +// // Merge in $sql_elements +// if (!empty($sql_settings)) { +// foreach(array_keys($sql_settings) as $key) { +// $sql_elements[$key]['pieces'] = array_merge($sql_elements[$key]['pieces'], $sql_settings[$key]); +// $sql_elements[$key]['pieces'] = array_unique($sql_elements[$key]['pieces']); +// } +// } +// +// $parameters = $sql_elements['parameters']['pieces']; +// +// $sql = project_build_query($sql_elements); +// +// $pager = module_invoke($module, 'project_sort_methods', 'pager', $sort_method); +// if ($pager) { +// $first_field = array_shift($sql_elements['fields']['pieces']); +// if (count($sql_elements['group_bys']['pieces'])) { +// $first_field = 'DISTINCT(' . $sql_elements['group_bys']['pieces'][0] . ')'; +// $sql_elements['group_bys']['pieces'] = array(); +// } +// $sql_elements['fields']['pieces'] = array("COUNT($first_field)"); +// // ORDER BY can screw up COUNT(DISTINCT), and we don't care +// // about the order for the count query. +// unset($sql_elements['order_bys']); +// $count_query = project_build_query($sql_elements); +// $result = pager_query($sql, variable_get('project_browse_nodes', 30), 0, $count_query, $parameters); +// } +// else { +// $result = db_query($sql, $parameters); +// } +// +// // If we've just switched versions, we may have a term requested but no matching projects. +// // In that case, we returned an uncollapsed fieldset. +// if (module_invoke($module, 'project_sort_methods', 'set term', $sort_method)) { +// $output .= theme('fieldset', array('#title' => t('Categories'), '#collapsible' => TRUE, '#collapsed' => (arg(3) && db_num_rows($result)) ? TRUE : FALSE, '#children' => theme('project_term_list', $terms, "project/$termname/$sort_method"))); +// if (!arg(3) || !db_num_rows($result)) { +// return $output; +// } +// drupal_set_title(t('@project_type: %category', array('@project_type' => $type->name, '%category' => $term->name))); +// } +// else { +// drupal_set_title(check_plain($type->name)); +// } +// } +// // If taxonomy is enabled but no termname is selected, show a list of terms to choose from. +// else { +// $tree = taxonomy_get_tree($vid, 0, -1, 1); +// $items = array(); +// foreach ($tree as $term) { +// $items[] = theme('project_type', $term); +// } +// drupal_set_title(t('Project types')); +// return theme('item_list', $items); +// } +// } +// // If taxonomy is not enabled, fetch all projects +// else { +// // Any terms passed without taxonomy module enabled are bogus -- return page not found. +// if (isset($termname)) { +// return drupal_not_found(); +// } +// // If the site has enabled issue tracking via the project_issue +// // module, we want to add 1 more field and JOIN to our query so +// // we can provide the link for "Bugs and feature requests"... +// if (module_exists('project_issue')) { +// $ISSUES = ', pip.issues'; +// $ISSUE_JOIN ='INNER JOIN {project_issue_projects} pip ON n.nid = pip.nid'; +// } +// $result = db_query(db_rewrite_sql("SELECT n.nid, n.title, nr.teaser, nr.format$ISSUES FROM {node} n INNER JOIN {node_revisions} nr ON n.vid = nr.vid $ISSUE_JOIN WHERE n.status = 1 AND n.type = 'project_project' ORDER BY n.title ASC")); +// } +// $projects = ''; +// $class = 'even'; +// while ($project = db_fetch_object($result)) { +// $project->body = check_markup($project->teaser, $project->format, FALSE); +// if (module_exists('taxonomy')) { +// $project->taxonomy = taxonomy_node_get_terms($project->nid); +// if (isset($type)) { +// // Hide the top-level project type term from the links, but add it to +// // the $project object for theme_project_summary() to use if it wants. +// unset($project->taxonomy[$type->tid]); +// $project->term = $termname; +// } +// $project->terms = taxonomy_link('taxonomy terms', $project); +// } +// +// // Make sure we have the latest release +// if (isset($project->release_count) && $project->release_count > 1 && $version != -1) { +// $latest = db_fetch_object(db_query_range("SELECT file_path, version, file_date FROM {project_release_nodes} p INNER JOIN {node} n ON p.nid = n.nid INNER JOIN {term_node} t ON p.nid = t.nid LEFT JOIN {project_release_default_versions} prdv ON p.pid = prdv.nid AND prdv.tid = t.tid AND prdv.major = p.version_major WHERE p.pid = %d AND t.tid = %d AND n.status = 1 ORDER BY prdv.nid DESC, p.rebuild ASC, p.version_major ASC, p.version_minor DESC, p.version_patch DESC, p.file_date DESC", $project->nid, $version, 0, 1)); +// $project->file_path = $latest->file_path; +// $project->version = $latest->version; +// } +// +// $project->links = array(); +// if ($version != -1) { +// if ($project->file_path) { +// $project->links['project_download'] = theme('project_release_download_link', $project->file_path, t('Download'), 'array'); +// } +// } +// else { +// $project->download_table = theme('project_release_table_overview', $project, 'recommended', 'all', t('Version'), FALSE); +// } +// +// $project->links['project_more_info'] = array( +// 'title' => t('Find out more'), +// 'href' => "node/$project->nid", +// ); +// if ($project->issues) { +// $project->links['project_issues'] = array( +// 'title' => t('Bugs and feature requests'), +// 'href' => "project/issues/$project->nid", +// ); +// } +// if (module_invoke($module, 'project_sort_methods', 'group by date', $sort_method) && $date = _project_date($project->changed)) { +// $projects .= "' . implode("\n", array_map('htmlspecialchars', $output))); + wd_err("ERROR: %cmd failed with status !rval" . '' . implode("\n", array_map('htmlspecialchars', $output)), array('%cmd' => $cmd, '!rval' => $rval)); return false; } return true; @@ -679,7 +687,7 @@ function drupal_exec($cmd) { */ function drupal_chdir($dir) { if (!chdir($dir)) { - wd_err(t("ERROR: Can't chdir(@dir)", array('@dir' => $dir))); + wd_err("ERROR: Can't chdir(@dir)", array('@dir' => $dir)); return false; } return true; @@ -694,31 +702,31 @@ function wprint($var) { * Wrapper function for watchdog() to log notice messages. Uses a * different watchdog message type depending on the task (branch vs. tag). */ -function wd_msg($msg, $link = NULL) { +function wd_msg($msg, $variables = array(), $link = NULL) { global $task; - watchdog('package_' . $task, $msg, WATCHDOG_NOTICE, $link); + watchdog('package_' . $task, $msg, $variables, WATCHDOG_NOTICE, $link); echo $msg ."\n"; } /** * Wrapper function for watchdog() to log error messages. */ -function wd_err($msg, $link = NULL) { +function wd_err($msg, $variables = array(), $link = NULL) { global $wd_err_msg; if (!isset($wd_err_msg)) { $wd_err_msg = array(); } - watchdog('package_error', $msg, WATCHDOG_ERROR, $link); - echo $msg ."\n"; - $wd_err_msg[] = $msg; + watchdog('package_error', $msg, $variables, WATCHDOG_ERROR, $link); + echo t($msg, $variables) ."\n"; + $wd_err_msg[] = t($msg, $variables); } /** * Wrapper function for watchdog() to log messages about checking * package metadata. */ -function wd_check($msg, $link = NULL) { - watchdog('package_check', $msg, WATCHDOG_NOTICE, $link); +function wd_check($msg, $variables = array(), $link = NULL) { + watchdog('package_check', $msg, $variables, WATCHDOG_NOTICE, $link); echo $msg ."\n"; } @@ -733,7 +741,7 @@ function initialize_tmp_dir($task) { global $tmp_dir, $tmp_root; if (!is_dir($tmp_root)) { - wd_err(t("ERROR: tmp_root: @dir is not a directory", array('@dir' => $tmp_root))); + wd_err("ERROR: tmp_root: @dir is not a directory", array('@dir' => $tmp_root)); exit(1); } @@ -743,7 +751,7 @@ function initialize_tmp_dir($task) { drupal_exec("$rm -rf $tmp_dir/*"); } else if (!@mkdir($tmp_dir)) { - wd_err(t("ERROR: mkdir(@dir) failed", array('@dir' => $tmp_dir))); + wd_err("ERROR: mkdir(@dir) failed", array('@dir' => $tmp_dir)); exit(1); } } @@ -783,15 +791,15 @@ function fix_info_file_version($file, $u $info .= "\n"; if (!chmod($file, 0644)) { - wd_err(t("ERROR: chmod(@file, 0644) failed", array('@file' => $file))); + wd_err("ERROR: chmod(@file, 0644) failed", array('@file' => $file)); return false; } if (!$info_fd = fopen($file, 'ab')) { - wd_err(t("ERROR: fopen(@file, 'ab') failed", array('@file' => $file))); + wd_err("ERROR: fopen(@file, 'ab') failed", array('@file' => $file)); return false; } if (!fwrite($info_fd, $info)) { - wd_err(t("ERROR: fwrite(@file) failed", array('@file' => $file)) . '' . $info); + wd_err("ERROR: fwrite(@file) failed". '' . $info, array('@file' => $file)); return false; } return true; @@ -817,12 +825,12 @@ function package_release_update_node($ni db_query("UPDATE {project_release_nodes} SET file_path = '%s', file_hash = '%s', file_date = %d WHERE nid = %d", $file_path, $file_hash, $file_date, $nid); // Don't auto-publish security updates. - if ($task == 'tag' && db_num_rows(db_query("SELECT * FROM {term_node} WHERE nid = %d AND tid = %d", $nid, SECURITY_UPDATE_TID))) { - watchdog('package_security', t("Not auto-publishing security update release."), WATCHDOG_NOTICE, l(t('view'), 'node/'. $nid)); + if ($task == 'tag' && db_result(db_query("SELECT COUNT(*) FROM {term_node} WHERE nid = %d AND tid = %d", $nid, SECURITY_UPDATE_TID))) { + watchdog('package_security', "Not auto-publishing security update release.", array(), WATCHDOG_NOTICE, l(t('view'), 'node/'. $nid)); return; } - db_query("UPDATE {node} SET status = 1 WHERE nid = %d", $nid); + db_query("UPDATE {node} SET status = %d WHERE nid = %d", 1, $nid); } /** Index: release/project-release-create-history.php =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/project/release/project-release-create-history.php,v retrieving revision 1.13 diff -u -p -r1.13 project-release-create-history.php --- release/project-release-create-history.php 11 Jun 2008 03:13:12 -0000 1.13 +++ release/project-release-create-history.php 20 Jun 2008 23:17:53 -0000 @@ -2,7 +2,7 @@ BASE_DIRECTORY))); + wd_err("ERROR: History directory (%directory) does not exist, aborting.\n", array('%directory' => BASE_DIRECTORY)); exit(1); } @@ -91,7 +91,7 @@ project_list_generate(); */ function project_release_history_generate_all() { $api_terms = project_release_compatibility_list(); - wd_msg(t('Generating XML release history files for all projects.')); + wd_msg('Generating XML release history files for all projects.'); // Generate all.xml files for projects with releases. $query = db_query("SELECT DISTINCT(pid) FROM {project_release_nodes}"); @@ -104,14 +104,14 @@ function project_release_history_generat // Generate XML files based on API compatibility. $tids = array_keys($api_terms); - $placeholders = implode(',', array_fill(0, count($tids), '%d')); + $placeholders = db_placeholders($tids); $query = db_query("SELECT DISTINCT(prn.pid), tn.tid FROM {project_release_nodes} prn INNER JOIN {term_node} tn ON prn.nid = tn.nid WHERE tn.tid IN ($placeholders)", $tids); $i = 0; while ($project = db_fetch_object($query)) { project_release_history_generate_project_xml($project->pid, $project->tid); $i++; } - wd_msg(t('Completed XML release history files for @num_projects.', array('@num_projects' => format_plural($i, '1 project/version pair', '@count project/version pairs')))); + wd_msg('Completed XML release history files for @num_projects.', array('@num_projects' => format_plural($i, '1 project/version pair', '@count project/version pairs'))); } /** @@ -138,7 +138,7 @@ function project_release_history_generat // Restrict output to a specific API compatibility term. $api_terms = project_release_compatibility_list(); if (!isset($api_terms[$api_tid])) { - wd_err(t('API compatibility term %tid not found.', array('%tid' => $api_tid))); + wd_err('API compatibility term %tid not found.', array('%tid' => $api_tid)); return FALSE; } $api_version = $api_terms[$api_tid]; @@ -153,11 +153,16 @@ function project_release_history_generat $sql = "SELECT n.title, n.nid, n.status, p.uri, u.name AS username FROM {node} n INNER JOIN {project_projects} p ON n.nid = p.nid INNER JOIN {users} u ON n.uid = u.uid WHERE p.nid = %d"; $query = db_query($sql, $project_nid); } - if (!db_num_rows($query)) { - wd_err(t('Project ID %pid not found', array('%pid' => $project_nid))); + + $project_found = FALSE; + while ($project = db_fetch_object($query)) { + $project_found = TRUE; + } + + if (!$project_found) { + wd_err('Project ID %pid not found', array('%pid' => $project_nid)); return FALSE; } - $project = db_fetch_object($query); $xml = ''. check_plain($project->title) ." \n"; $xml .= ''. check_plain($project->uri) ." \n"; @@ -206,7 +211,7 @@ function project_release_history_generat } $xml .= ''. $project_status ." \n"; - $xml .= ''. url("node/$project->nid", NULL, NULL, TRUE) ."\n"; + $xml .= ''. url("node/$project->nid", array('absolute' => TRUE)) ."\n"; // Now, build the query for all the releases for this project and term. $joins = array(); @@ -244,7 +249,8 @@ function project_release_history_generat // duplicate release nodes and ensure we're just looking at the API term, // we need to add a WHERE clause for the API vocabulary id. $joins[] = "INNER JOIN {term_data} td ON tn.tid = td.tid"; - $where[] = 'td.vid = '. _project_release_get_api_vid(); + $where[] = 'td.vid = %d'; + $parameters[] = _project_release_get_api_vid(); $fields[] = 'td.weight'; } @@ -284,7 +290,7 @@ function project_release_history_generat if ($release->status) { // Published, so we should include the links. $xml .= "published \n"; - $xml .= ''. url("node/$release->nid", NULL, NULL, TRUE) ." \n"; + $xml .= ''. url("node/$release->nid", array('absolute' => TRUE)) ." \n"; if (!empty($release->file_path)) { $download_link = theme('project_release_download_link', $release->file_path, NULL, TRUE); $xml .= ''. $download_link['href'] ." \n"; @@ -336,9 +342,9 @@ function project_release_history_write_x $filename = $project_dir .'/project-list-all.xml'; $tmp_filename = $filename .'.new'; $errors = array( - 'mkdir' => t("ERROR: mkdir(@dir) failed, can't write project list.", array('@dir' => $project_dir)), - 'unlink' => t("ERROR: unlink(@file) failed, can't write project list.", array('@file' => $tmp_filename)), - 'rename' => t("ERROR: rename(@old, @new) failed, can't write project list.", array('@old' => $tmp_filename, '@new' => $filename)) + 'mkdir' => array("ERROR: mkdir(@dir) failed, can't write project list.", array('@dir' => $project_dir)), + 'unlink' => array("ERROR: unlink(@file) failed, can't write project list.", array('@file' => $tmp_filename)), + 'rename' => array("ERROR: rename(@old, @new) failed, can't write project list.", array('@old' => $tmp_filename, '@new' => $filename)) ); $full_xml = '\n". $xml ." \n"; } @@ -356,30 +362,30 @@ function project_release_history_write_x $filename = $project_dir .'/'. $project_id; $tmp_filename = $filename .'.new'; $errors = array( - 'mkdir' => t("ERROR: mkdir(@dir) failed, can't write history for %project.", array('@dir' => $project_dir, '%project' => $project->title)), - 'unlink' => t("ERROR: unlink(@file) failed, can't write history for %project.", array('@file' => $tmp_filename, '%project' => $project->title)), - 'rename' => t("ERROR: rename(@old, @new) failed, can't write history for %project.", array('@old' => $tmp_filename, '@new' => $filename, '%project' => $project->title)) + 'mkdir' => array("ERROR: mkdir(@dir) failed, can't write history for %project.", array('@dir' => $project_dir, '%project' => $project->title)), + 'unlink' => array("ERROR: unlink(@file) failed, can't write history for %project.", array('@file' => $tmp_filename, '%project' => $project->title)), + 'rename' => array("ERROR: rename(@old, @new) failed, can't write history for %project.", array('@old' => $tmp_filename, '@new' => $filename, '%project' => $project->title)) ); $full_xml = '\n". $xml ." \n"; } // Make sure we've got the right project-specific subdirectory. if (!is_dir($project_dir) && !mkdir($project_dir)) { - wd_err($errors['mkdir']); + wd_err($errors['mkdir'][0], $errors['mkdir'][1]); return FALSE; } // Make sure the "[project]-[version].xml.new" file doesn't exist. if (is_file($tmp_filename) && !unlink($tmp_filename)) { - wd_err($errors['unlink']); + wd_err($errors['unlink'][0], $errors['unlink'][1]); return FALSE; } // Write the XML history to "[project]-[version].xml.new". if (!$hist_fd = fopen($tmp_filename, 'xb')) { - wd_err(t("ERROR: fopen(@file, 'xb') failed", array('@file' => $tmp_filename))); + wd_err("ERROR: fopen(@file, 'xb') failed", array('@file' => $tmp_filename)); return FALSE; } if (!fwrite($hist_fd, $full_xml)) { - wd_err(t("ERROR: fwrite(@file) failed", array('@file' => $tmp_filename)) . '' . check_plain($full_xml)); + wd_err("ERROR: fwrite(@file) failed" . '' . check_plain($full_xml), array('@file' => $tmp_filename)); return FALSE; } // We have to close this handle before we can rename(). @@ -387,7 +393,7 @@ function project_release_history_write_x // Now we can atomically rename the .new into place in the "live" spot. if (!_rename($tmp_filename, $filename)) { - wd_err($errors['rename']); + wd_err($errors['rename'][0], $errors['rename'][1]); return FALSE; } return TRUE; @@ -449,15 +455,15 @@ function project_list_generate() { /** * Wrapper function for watchdog() to log notice messages. */ -function wd_msg($msg, $link = NULL) { - watchdog('release_history', $msg, WATCHDOG_NOTICE, $link); +function wd_msg($msg, $variables = array(), $link = NULL) { + watchdog('release_history', $msg, $variables, WATCHDOG_NOTICE, $link); } /** * Wrapper function for watchdog() to log error messages. */ -function wd_err($msg, $link = NULL) { - watchdog('release_hist_err', $msg, WATCHDOG_ERROR, $link); +function wd_err($msg, $variables=array(), $link = NULL) { + watchdog('release_hist_err', $msg, $variables, WATCHDOG_ERROR, $link); } /** Index: release/project_release.css =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/project/release/project_release.css,v retrieving revision 1.6 diff -u -p -r1.6 project_release.css --- release/project_release.css 6 Mar 2008 06:41:44 -0000 1.6 +++ release/project_release.css 20 Jun 2008 23:17:53 -0000 @@ -1,20 +1,12 @@ /* $Id: project_release.css,v 1.6 2008/03/06 06:41:44 dww Exp $ */ -/* $Name: $ */ +/* $Name: HEAD $ */ -.project-release .node-form .version-elements fieldset .form-item { +.node-form fieldset .version-elements .form-item { float: left; padding-right: 0.8em; margin: 0.05em 0.1em; } -.project-release .node-form fieldset:after { - content: "."; - display: block; - height: 0; - clear: both; - visibility: hidden; -} - /*************************** * CSS for tables of releases */ Index: release/project_release.info =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/project/release/project_release.info,v retrieving revision 1.3 diff -u -p -r1.3 project_release.info --- release/project_release.info 9 Aug 2007 23:38:52 -0000 1.3 +++ release/project_release.info 20 Jun 2008 23:17:53 -0000 @@ -2,4 +2,7 @@ name = Project releases description = Provides a release node type to represent releases of projects. package = Project -dependencies = project taxonomy +dependencies[] = project +dependencies[] = taxonomy +dependencies[] = views +core = 6.x Index: release/project_release.install =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/project/release/project_release.install,v retrieving revision 1.16 diff -u -p -r1.16 project_release.install --- release/project_release.install 19 Jan 2008 07:10:59 -0000 1.16 +++ release/project_release.install 20 Jun 2008 23:17:53 -0000 @@ -1,138 +1,22 @@ 1, 'not null' => TRUE)); - break; - } - return $ret; -} +function project_release_schema() { + $schema['project_release_nodes'] = array( + 'description' => t('The base table for project_project nodes.'), + 'fields' => array( + 'nid' => array( + 'description' => t('Primary Key: The {node}.nid of the project_release node.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'pid' => array( + 'description' => t('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' => t('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' => t('The name of a CVS branch or tag on which a release is based.'), + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'file_path' => array( + 'description' => t('The path to the downloadable file for the release.'), + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'file_date' => array( + 'description' => t('A Unix timestamp indicating when the file was created.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'file_hash' => array( + 'description' => t('An MD5 hash of the file.'), + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => '', + ), + 'rebuild' => array( + 'description' => t('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' => t('The major version number of a release.'), + 'type' => 'int', + 'unsigned' => FALSE, + 'not null' => FALSE, + 'default' => NULL, + ), + 'version_minor' => array( + 'description' => t('The minor version number of a release.'), + 'type' => 'int', + 'unsigned' => FALSE, + 'not null' => FALSE, + 'default' => NULL, + ), + 'version_patch' => array( + 'description' => t('The patch level version number of a release.'), + 'type' => 'int', + 'unsigned' => FALSE, + 'not null' => FALSE, + 'default' => NULL, + ), + 'version_extra' => array( + 'description' => t('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, + ), + ), + 'primary key' => array('nid'), + 'indexes' => array( + 'project_releases_pid' => array('pid') + ), + ); -/** - * Add a cache table {cache_project_release}. - */ -function project_release_update_5000() { - $ret = array(); - switch ($GLOBALS['db_type']) { - case 'mysql': - case 'mysqli': - $ret[] = update_sql("CREATE TABLE IF NOT EXISTS {cache_project_release} ( - cid varchar(255) BINARY NOT NULL default '', - data longblob, - expire int NOT NULL default '0', - created int NOT NULL default '0', - headers text, - PRIMARY KEY (cid), - INDEX expire (expire) - ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); - break; - case 'pgsql': - if (!db_table_exists('cache_project_release')) { - $ret[] = update_sql("CREATE TABLE {cache_project_release} ( - cid varchar(255) NOT NULL default '', - data bytea, - expire int NOT NULL default '0', - created int NOT NULL default '0', - headers text, - PRIMARY KEY (cid) - )"); - $ret[] = update_sql("CREATE INDEX {cache_project_release}_expire_idx ON {cache_project_release} (expire)"); - } - break; - } - return $ret; -} + $schema['project_release_projects'] = array( + 'description' => t('Table used to store release specific information about projects.'), + 'fields' => array( + 'nid' => array( + 'description' => t('Primary Key: The {project_projects}.nid of the project_project node.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'releases' => array( + 'description' => t('A flag indicating whether or not releases are enabled for a project.'), + 'type' => 'int', + 'size' => 'tiny', + 'unsigned' => FALSE, + 'not null' => TRUE, + 'default' => 1, + ), + 'version_format' => array( + 'description' => t('A string used to designate the format of the {project_release_nodes}.version field for releases of a project.'), + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + ), + 'primary key' => array('nid'), + 'indexes' => array( + 'project_release_projects_releases' => array('releases') + ), + ); -/** - * Remove variables from dead code for serving XML history files, which is - * now handled by project-release-serve-history.php instead. - */ -function project_release_update_5001() { - $ret = array(); - $variables = array( - 'project_release_history_xml', - 'project_release_history_directory', + $schema['project_release_supported_versions'] = array( + 'description' => t('Table used to store information about which major versions of a project are supported and/or recommended.'), + 'fields' => array( + 'nid' => array( + 'description' => t('Primary Key: The {project_projects}.nid of the project_project node.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'tid' => array( + 'description' => t('Primary Key: The {term_data}.tid of the API compatability version associated with a major version of a project.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'major' => array( + 'description' => t('Primary Key: The {project_release_nodes}.version_major of a release node.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'supported' => array( + 'description' => t('A flag to indicate whether or not a given major version of a project is supported.'), + 'type' => 'int', + 'size' => 'tiny', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 1, + ), + 'recommended' => array( + 'description' => t('A flag to indicate whether or not a given major version of a project is recommended.'), + 'type' => 'int', + 'size' => 'tiny', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'snapshot' => array( + 'description' => t('A flag to indicate whether or not snapshot releases of a major version of a project should be shown in the release download table.'), + 'type' => 'int', + 'size' => 'tiny', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + ), + 'primary key' => array('nid', 'tid', 'major'), ); - foreach ($variables as $variable) { - variable_del($variable); - $ret[] = array('success' => TRUE, 'query' => "variable_del($variable)"); - } - return $ret; -} -/** - * Remove a dead variable from before project_release.module existed. - */ -function project_release_update_5002() { - $ret = array(); - variable_del('project_release_unmoderate'); - $ret[] = array('success' => TRUE, 'query' => "variable_del('project_release_unmoderate')"); - return $ret; -} + $schema['project_release_package_errors'] = array( + 'description' => t('Table used to store error messages generated by the scripts that package project_release nodes into tarballs.'), + 'fields' => array( + 'nid' => array( + 'description' => t('Primary Key: The {node}.nid of the project_release node.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'messages' => array( + 'description' => t('The text of any error messages created by the packaging scripts.'), + 'type' => 'text', + 'not null' => FALSE, + ) + ), + 'primary key' => array('nid'), + ); -/** - * Add {project_release_package_errors} table to track packaging errors. - */ -function project_release_update_5003() { - $ret = array(); - switch ($GLOBALS['db_type']) { - case 'mysql': - case 'mysqli': - $ret[] = update_sql("CREATE TABLE IF NOT EXISTS {project_release_package_errors} ( - nid int unsigned NOT NULL default '0', - messages text NOT NULL, - PRIMARY KEY (nid) - ) /*!40100 DEFAULT CHARACTER SET utf8 */;"); - break; - case 'pgsql': - if (!db_table_exists('project_release_package_errors')) { - $ret[] = update_sql("CREATE TABLE {project_release_package_errors} ( - nid int NOT NULL default '0', - messages text, - PRIMARY KEY (nid) - )"); - } - break; - } - return $ret; + $schema['cache_project_release'] = array( + 'description' => t('Cache table used to store the project release download tables.'), + 'fields' => array( + 'cid' => array( + 'description' => t('Primary Key: Unique cache ID.'), + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'data' => array( + 'description' => t('A collection of data to cache.'), + 'type' => 'blob', + 'not null' => FALSE, + 'size' => 'big', + ), + 'expire' => array( + 'description' => t('A Unix timestamp indicating when the cache entry should expire, or 0 for never.'), + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'created' => array( + 'description' => t('A Unix timestamp indicating when the cache entry was created.'), + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'headers' => array( + 'description' => t('Any custom HTTP headers to be added to cached data.'), + 'type' => 'text', + 'not null' => FALSE, + ), + 'serialized' => array( + 'description' => t('A flag to indicate whether content is serialized (1) or not (0).'), + 'type' => 'int', + 'size' => 'small', + 'not null' => TRUE, + 'default' => 0 + ), + ), + 'primary key' => array('cid'), + 'indexes' => array( + 'expire' => array('expire') + ), + ); + return $schema; } /** - * Add the new {project_release_supported_versions} table, transfer data - * from {project_release_default_versions} and {project_release_projects}, - * and drop the stale table and columns. + * Add the 'serialized' field to the {cache_project_release} table. */ -function project_release_update_5200() { +function project_release_update_6000() { + $spec = array( + 'type' => 'int', + 'size' => 'small', + 'default' => 0, + 'not null' => TRUE, + ); $ret = array(); - switch ($GLOBALS['db_type']) { - case 'mysql': - case 'mysqli': - $ret[] = update_sql("CREATE TABLE IF NOT EXISTS {project_release_supported_versions} ( - nid int unsigned NOT NULL default '0', - tid int unsigned NOT NULL default '0', - major int unsigned NOT NULL default '0', - supported tinyint unsigned NOT NULL default '1', - recommended tinyint unsigned NOT NULL default '0', - snapshot tinyint unsigned NOT NULL default '0', - PRIMARY KEY (nid, tid, major) - ) /*!40100 DEFAULT CHARACTER SET utf8 */;"); - break; - case 'pgsql': - if (!db_table_exists('project_release_supported_versions')) { - $ret[] = update_sql("CREATE TABLE {project_release_supported_versions} ( - nid int NOT NULL default '0', - tid int NOT NULL default '0', - major int NOT NULL default '0', - supported smallint NOT NULL default '1', - recommended smallint NOT NULL default '0', - snapshot smallint NOT NULL default '0', - PRIMARY KEY (nid, tid, major) - );"); - } - break; - } - // Now, populate the table with the existing data. First, populate all the - // recommended majors versions from {project_release_default_versions}. - $ret[] = update_sql("INSERT INTO {project_release_supported_versions} (nid, tid, major, supported, recommended, snapshot) SELECT prdv.nid, prdv.tid, prdv.major, 1, 1, prp.snapshot_table FROM {project_release_default_versions} prdv INNER JOIN {project_release_projects} prp ON prdv.nid = prp.nid"); - - // Now, fill in all the non-recommended versions. For the migration path, we - // assume that if it's not recommended, it's also not supported. Project - // maintainers will have to manually visit the new UI if they want to - // specify multiple supported versions. - $vid = _project_release_get_api_vid(); - $ret[] = update_sql("INSERT INTO {project_release_supported_versions} (nid, tid, major, supported, recommended, snapshot) SELECT DISTINCT prn.pid, tn.tid, prn.version_major, 0, 0, 0 FROM {project_release_nodes} prn INNER JOIN {term_node} tn ON prn.nid = tn.nid INNER JOIN {term_data} td ON tn.tid = td.tid INNER JOIN {node} n ON prn.nid = n.nid LEFT JOIN {project_release_default_versions} prdv ON prdv.nid = prn.pid AND prdv.tid = tn.tid AND prdv.major = prn.version_major WHERE n.status = 1 AND td.vid = $vid AND prn.version_major IS NOT NULL AND prdv.major IS NULL"); - - // Finally, drop the stale table and column. - // While testing the upgrade path, these are both commented out for now: - //$ret[] = update_sql('DROP TABLE {project_release_default_versions}'); - //$ret[] = update_sql("ALTER TABLE {project_release_projects} DROP snapshot_table"); - + db_add_field($ret, 'cache_project_release', 'serialized', $spec); return $ret; -} +} \ No newline at end of file Index: release/project_release.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/project/release/project_release.module,v retrieving revision 1.69 diff -u -p -r1.69 project_release.module --- release/project_release.module 11 Jun 2008 18:14:55 -0000 1.69 +++ release/project_release.module 20 Jun 2008 23:17:53 -0000 @@ -1,6 +1,6 @@ type) || $node->type != 'project_project') { + return FALSE; + } + return $node; +} + +/** * Implementation of hook_menu() * @ingroup project_release_core */ -function project_release_menu($may_cache) { +function project_release_menu() { $items = array(); - global $user; - - $access_create = node_access('create', 'project_release'); - if (!$may_cache) { - if (arg(0) == 'node' && is_numeric(arg(1))) { - $node = node_load(arg(1)); - if ($node->type == 'project_project') { - $items[] = array( - 'path' => 'node/'. arg(1) .'/release', - 'title' => t('Releases'), - 'callback' => 'project_release_project_releases', - 'access' => node_access('view', $node), - 'type' => MENU_CALLBACK, - ); - if (node_access('update', $node)) { - $items[] = array( - 'path' => 'node/'. arg(1) .'/release/overview', - 'title' => t('Overview'), - 'callback' => 'project_release_project_releases', - 'access' => node_access('view', $node), - 'type' => MENU_CALLBACK, - ); - $items[] = array( - 'path' => 'node/'. arg(1) .'/edit/releases', - 'title' => t('Releases'), - 'callback' => 'project_release_project_edit_releases', - 'type' => MENU_LOCAL_TASK, - ); - } - } - } - if (arg(0) == 'node' && arg(1) == 'add' && arg(2) == 'project-release' && is_numeric(arg(3))) { - $items[] = array( - 'path' => 'node/add/project-release/'. arg(3), - 'callback' => 'node_add', - 'callback arguments' => array('project-release'), - 'access' => $access_create, - 'type' => MENU_CALLBACK, - ); - } - - drupal_add_css(drupal_get_path('module', 'project_release') .'/project_release.css'); - project_release_get_api_taxonomy(); - } - else { // $may_cache - $items[] = array( - 'path' => 'admin/project/project-release-settings', - 'description' => t('Configure the default version string for releases and other settings for the Project release module.'), - 'title' => t('Project release settings'), - 'callback' => 'drupal_get_form', - 'callback arguments' => 'project_release_settings_form', - 'access' => user_access('administer projects'), - 'weight' => 1, - 'type' => MENU_NORMAL_ITEM, - ); - // Special menu item for the "first page" of submitting a new release. - // Instead of the treachery of a true multipage form, we just have - // a simple form at node/add/project-release that provides a project - // selector which redirects to node/add/project-release/[project-nid]. - $types = node_get_types(); - $items[] = array( - 'path' => 'node/add/project-release', - 'title' => check_plain($types['project_release']->name), - 'callback' => 'project_release_pick_project_page', - 'callback arguments' => array($types['project_release']->name), - 'access' => $access_create, - 'type' => MENU_NORMAL_ITEM, - ); - } + $items['node/%project_release_project/edit/releases'] = array( + 'title' => 'Releases', + 'page callback' => 'project_release_project_edit_releases', + 'page arguments' => array(1), + 'access callback' => 'node_access', + 'access arguments' => array('update', 1), + 'type' => MENU_LOCAL_TASK, + ); + + $items['node/add/project-release/%project_release_project'] = array( + 'page callback' => 'node_add', + 'page arguments' => array('project-release'), + 'access callback' => 'node_access', + 'access arguments' => array('create', 'project_release'), + 'file' => 'node.pages.inc', + 'file path' => drupal_get_path('module', 'node'), + '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, + ); return $items; } /** + * Implementation of hook_menu_alter(). + */ +function project_release_menu_alter(&$callbacks) { + $callbacks['node/add/project-release']['page callback'] = 'drupal_get_form'; + $callbacks['node/add/project-release']['page arguments'] = array('project_release_pick_project_form'); +} + +/** * Callback for the main settings page. * @ingroup project_release_core */ @@ -117,7 +107,7 @@ function project_release_settings_form() foreach ($tree as $term) { $terms[$term->tid] = check_plain($term->name); } - $vocab = taxonomy_get_vocabulary(_project_release_get_api_vid()); + $vocab = taxonomy_vocabulary_load(_project_release_get_api_vid()); $tids = variable_get('project_release_active_compatibility_tids', ''); $form['project_release_active_compatibility_tids'] = array( '#type' => 'checkboxes', @@ -155,23 +145,23 @@ function project_release_settings_form() return system_settings_form($form); } -function project_release_settings_form_validate($form_id, $form_values, $form) { - if (!empty($form_values['project_release_directory'])) { +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.')); } - $tids = $form_values['project_release_active_compatibility_tids']; - $default_tid = $form_values['project_release_overview']; + $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_get_vocabulary(_project_release_get_api_vid()); + $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_values, 'project_release_default_version_format'); + _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_values['project_release_download_base'])) { - if (substr($form_values['project_release_download_base'], -1) != '/') { + 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_base_setting should end with a slash.', array('%download_base_setting' => t('Download link base URL')))); } } @@ -188,13 +178,12 @@ function project_release_settings_form_v * 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) { - global $user; +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); + 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 @@ -204,7 +193,7 @@ function project_release_access($op, $no // 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); + 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 @@ -236,6 +225,19 @@ function project_release_node_info() { */ function project_release_form($release) { if (arg(1) == 'add') { + // Initialize variables and $release object properties to eliminate notices. + $is_edit = FALSE; + $admin = NULL; + $release->version_major = NULL; + $release->version_minor = NULL; + $release->version_patch = NULL; + $release->version_extra = NULL; + $release->tag = ''; + $release->version = ''; + $release->file_path = ''; + $release->file_hash = ''; + $release->file_date = 0; + $release->version_api_tid = NULL; $release->pid = arg(3); $project = node_load($release->pid); project_project_set_breadcrumb($project, TRUE); @@ -262,8 +264,7 @@ function project_release_form($release) global $user; $admin = user_access('administer projects'); $is_edit = true; - $project->nid = $release->pid; - $project = node_load($project); + $project = node_load($release->pid); $breadcrumb[] = l($project->title, 'node/'. $project->nid); $breadcrumb[] = l(t('Releases'), 'node/'. $project->nid . '/release'); project_project_set_breadcrumb($project, $breadcrumb); @@ -271,17 +272,14 @@ function project_release_form($release) } $form['#attributes'] = array("enctype" => "multipart/form-data"); - $form['#prefix'] = ''; - $form['#suffix'] = ''; if ($is_edit) { $form['rel_id'] = array( '#type' => 'fieldset', '#title' => t('Release identification'), - '#prefix' => '', - '#suffix' => '', '#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); @@ -295,19 +293,14 @@ function project_release_form($release) '#type' => 'fieldset', '#title' => t('Version number elements'), '#collapsible' => TRUE, - '#prefix' => '', - '#suffix' => '', + '#theme' => 'project_release_node_form_version_elements', ); $modify = $admin || !$is_edit; $form['validate_version'] = array('#type' => 'hidden', '#value' => 1); - _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); + _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); $form['file'] = array( '#type' => 'fieldset', @@ -315,39 +308,30 @@ function project_release_form($release) '#collapsible' => TRUE, ); if (empty($release->file_path)) { - $file = file_check_upload('file'); + $file = file_save_upload('file'); $form['file']['file'] = array( '#title' => t('File'), '#type' => 'file', - '#description' => ($file ? t('A file named %filename has already been uploaded. If you upload another file %filename will be replaced.', array('%filename' => $file->filename)) : t('Choose the file that will be associated with this release.')), + '#description' => (!empty($file) ? t('A file named %filename has already been uploaded. If you upload another file %filename will be replaced.', array('%filename' => $file->filename)) : t('Choose the file that will be associated with this release.')), ); } - $form['body_filter'] = array( - '#type' => 'fieldset', - '#title' => t('Description'), - '#collapsible' => TRUE, - ); - $form['body_filter']['body'] = array( - '#title' => t('Body'), - '#type' => 'textarea', - '#default_value' => $release->body, - '#rows' => 10, - '#cols' => 40, - '#required' => $admin ? FALSE : TRUE, - '#description' => t('Enter a description of this release, such as a list of the major changes or updates.'), - ); - $form['body_filter']['format'] = filter_form($release->format); + $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.'); _project_release_form_add_text_element($form['tag']['tag'], t('Tag'), $release->tag, $is_edit, $admin, true, 40, 255); $form['tag']['rebuild'] = array( '#type' => 'value', - '#value' => $release->rebuild, + '#value' => empty($release->rebuild) ? 0 : $release->rebuild, ); _project_release_form_add_text_element($form['file']['file_path'], t('File path'), $release->file_path, $is_edit, $admin, false, 40, 255); - _project_release_form_add_text_element($form['file']['file_hash'], t('File md5 hash'), $release->file_hash, $is_edit, false); - _project_release_form_add_text_element($form['file']['file_date'], t('File date'), $release->file_date, $is_edit, false); + _project_release_form_add_text_element($form['file']['file_hash'], t('File md5 hash'), $release->file_hash, $is_edit, false, FALSE); + _project_release_form_add_text_element($form['file']['file_date'], t('File date'), $release->file_date, $is_edit, false, FALSE); + // Add a custom validation function. + $form['#validate'][] = 'project_release_node_form_validate'; + $form['#submit'][] = 'project_release_node_form_submit'; return $form; } @@ -414,12 +398,22 @@ function _project_release_form_add_versi * @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 $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)) { @@ -427,6 +421,7 @@ function _project_release_form_add_text_ '#type' => 'textfield', '#title' => $title, '#default_value' => $value, + '#value' => $value, '#required' => $required, '#size' => $size, '#maxlength' => $maxlength, @@ -443,64 +438,63 @@ function _project_release_form_add_text_ } } -/** - * Implementation of hook_validate(). - * @ingroup project_release_node - */ -function project_release_validate(&$edit, $form) { - global $form_values; - - if ($_POST['validate_version']) { - if (!isset($edit->version_major) && !isset($edit->version_minor) && - !isset($edit->version_patch) && - (!($edit->version_extra) || $edit->version_extra === '')) { +function project_release_node_form_validate(&$form, $form_state) { + if (!empty($form_state['values']['validate_version'])) { + if (!isset($form_state['values']['version_major']) && !isset($form_state['values']['version_minor']) && + !isset($form_state['values']['version_patch']) && + (!($form_state['values']['version_extra']) || $form_state['values']['version_extra'] === '')) { form_set_error('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' => 'Major version number', 'version_minor' => 'Minor version number') as $field => $name) { - $val = $edit->$field; + $val = $form_state['values'][$field]; if (isset($val) && $val !== '' && !is_numeric($val)) { form_set_error($field, t('!name must be a number.', array('!name' => $name))); } } - $val = $edit->version_patch; + $val = $form_state['values']['version_patch']; if (isset($val) && $val !== '' && !is_numeric($val) && $val != 'x') { form_set_error('version_patch', t("Patch-level version number must be numeric or the letter 'x'.")); } } - if ($file = file_check_upload('file')) { - if ($file = file_save_upload($file)) { + // @TODO: Need to add in some validation here. + $validators = array( + + ); + if ($file = file_save_upload('file', $validators, file_directory_path())) { + if (!empty($file)) { // Using $form_values here is an ugly hack, but the caching mechanism - // in file_check_upload() causes problems if we can't pass this object + // in file_check_upload() causes problems if we can't pass this object // @TODO: Edit comment, since file_check_upload() doesn't exist. // to the file_save_upload() call in the submit function which actually // saves the file. - $form_values['release_file'] = $file; + $form_state['project_release']['release_file'] = $file; $filepath = file_create_path($file->filepath); - form_set_value($form['file']['file_path'], $file->filepath); - form_set_value($form['file']['file_date'], filemtime($filepath)); - form_set_value($form['file']['file_hash'], md5_file($filepath)); + form_set_value($form['file']['file_path'], $file->filepath, $form_state); + form_set_value($form['file']['file_date'], filemtime($filepath), $form_state); + form_set_value($form['file']['file_hash'], md5_file($filepath), $form_state); } else { form_set_error('file', t('There was a problem uploading the specified file.')); } } + if (project_release_get_api_taxonomy()) { $vid = _project_release_get_api_vid(); - if (isset($edit->taxonomy)) { - $tid = $edit->taxonomy[$vid]; + if (isset($form_state['values']['taxonomy'])) { + $tid = $form_state['values']['taxonomy'][$vid]; } - elseif (isset($edit->$vid)) { - $tid = $edit->$vid; + elseif (isset($form_state['values']['$vid'])) { + $tid = $form_state['values']['$vid']; } if (isset($tid) && is_numeric($tid)) { - $edit->version_api_tid = $tid; + $form_state['values']['version_api_tid'] = $tid; } } // With cvs.module installed, this validation is already handled. // We only want to do it here if we're *not* doing the N-page form... - if (!project_use_cvs($edit) && !isset($edit->nid) && project_release_exists($edit)) { + if (!project_use_cvs($form_state['values']['pid']) && !isset($form_state['values']['nid']) && project_release_exists($form_state['values'])) { // TODO: is there a better form element to mark with this error? form_set_error('version_patch', t('This version already exists for this project.')); } @@ -519,16 +513,30 @@ function project_release_validate(&$edit // TODO: Magic re-setting to "%project_name %version" ?? } elseif (isset($edit->version) && $edit->version !== '') { - form_set_value($form['title'], "$project_name $edit->version"); + form_set_value($form['title'], "$project_name $edit->version", $form_state); } elseif (isset($edit->project)) { $version = project_release_get_version((object)$edit, $edit->project); - form_set_value(array('#parents' => array('version')), $version); + form_set_value(array('#parents' => array('version')), $version, $form_state); $title = $edit->project->title; - form_set_value($form['title'], "$title $version"); + form_set_value($form['title'], "$title $version", $form_state); } } +function project_release_node_form_submit(&$form, $form_state) { + //// Handle file upload data. + //$file_data = new stdClass(); + //if (isset($form_values['release_file'])) { + // $file_data = file_save_upload($form_values['release_file'], file_directory_path()); + // // If a file was uploaded, this is what we need to use. + // $file_path = $file_data->filepath; + //} + //else { + // // If there's no upload, save whatever value is already in $node. + // $file_path = $node->file_path; + //} +} + /** * Implementation of hook_load(). * @ingroup project_release_node @@ -584,32 +592,31 @@ function project_release_update($node) { * @param $is_new Is this a new release node, or are we updating? */ function project_release_db_save($node, $is_new) { - global $form_values; - // 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->version_patch) && !is_numeric($node->version_patch)) { unset($node->version_patch); } - // Handle file upload data. - $file_data = new stdClass(); - if (isset($form_values['release_file'])) { - $file_data = file_save_upload($form_values['release_file'], file_directory_path()); - // If a file was uploaded, this is what we need to use. - $file_path = $file_data->filepath; - } - else { - // If there's no upload, save whatever value is already in $node. - $file_path = $node->file_path; - } + // @TODO: Fix the file handling here--we just need to save the file now. + //// Handle file upload data. + //$file_data = new stdClass(); + //if (isset($form_values['release_file'])) { + // $file_data = file_save_upload($form_values['release_file'], file_directory_path()); + // // If a file was uploaded, this is what we need to use. + // $file_path = $file_data->filepath; + //} + //else { + // // If there's no upload, save whatever value is already in $node. + // $file_path = $node->file_path; + //} $types = array( 'pid' => "%d", 'version' => "'%s'", 'tag' => "'%s'", 'file_path' => "'%s'", 'file_date' => "%d", 'file_hash' => "'%s'", 'rebuild' => "%d", ); $values = array( 'pid' => $node->pid, 'version' => $node->version, - 'tag' => $node->tag, 'file_path' => $file_path, + 'tag' => $node->tag, 'file_path' => $node->file_path, 'file_date' => $node->file_date, 'file_hash' => $node->file_hash, 'rebuild' => $node->rebuild, ); @@ -655,15 +662,15 @@ function project_release_db_save($node, function project_release_check_supported_versions($pid, $tid, $major, $delete) { if ($delete) { // Make sure this isn't the last release node for the given major. - $active_branch_releases = db_result(db_query("SELECT COUNT(DISTINCT(r.nid)) FROM {project_release_nodes} r INNER JOIN {node} n ON n.nid = r.nid INNER JOIN {term_node} tn ON tn.nid = n.nid WHERE r.pid = %d AND tn.tid = %d AND n.status = 1 AND r.version_major = %d", $pid, $tid, $major)); + $active_branch_releases = db_result(db_query("SELECT COUNT(DISTINCT(r.nid)) FROM {project_release_nodes} r INNER JOIN {node} n ON n.nid = r.nid INNER JOIN {term_node} tn ON tn.nid = n.nid WHERE r.pid = %d AND tn.tid = %d AND n.status = %d AND r.version_major = %d", $pid, $tid, 1, $major)); if (empty($active_branch_releases)) { // Remove the bogus record. db_query("DELETE FROM {project_release_supported_versions} WHERE nid = %d AND tid = %d AND major = %d", $pid, $tid, $major); - $num_recommended = db_result(db_query("SELECT COUNT(*) FROM {project_release_supported_versions} WHERE nid = %d AND tid = %d AND supported = 1 AND recommended = 1", $pid, $tid)); + $num_recommended = db_result(db_query("SELECT COUNT(*) FROM {project_release_supported_versions} WHERE nid = %d AND tid = %d AND supported = %d AND recommended = %d", $pid, $tid, 1, 1)); if ($num_recommended > 1) { // Something seriously bogus, clear out the values and start over. - db_query("UPDATE {project_release_supported_versions} SET recommended = 0 WHERE nid = %d AND tid = %d", $pid, $tid); + db_query("UPDATE {project_release_supported_versions} SET recommended = %d WHERE nid = %d AND tid = %d", 0, $pid, $tid); $num_recommended = 0; } @@ -671,9 +678,9 @@ function project_release_check_supported // We no longer have a recommended major for this API/tid, so select a // sensible default, if possible. Find the lowest supported major // number that has a published release. - $lowest_major = db_result(db_query("SELECT MIN(r.version_major) FROM {project_release_nodes} r INNER JOIN {project_release_supported_versions} prsv ON r.pid = prsv.nid INNER JOIN {node} n ON n.nid = r.nid INNER JOIN {term_node} tn ON tn.nid = n.nid WHERE r.pid = %d AND tn.tid = %d AND prsv.supported = 1 AND n.status = 1", $pid, $tid)); + $lowest_major = db_result(db_query("SELECT MIN(r.version_major) FROM {project_release_nodes} r INNER JOIN {project_release_supported_versions} prsv ON r.pid = prsv.nid INNER JOIN {node} n ON n.nid = r.nid INNER JOIN {term_node} tn ON tn.nid = n.nid WHERE r.pid = %d AND tn.tid = %d AND prsv.supported = %d AND n.status = %d", $pid, $tid, 1, 1)); if ($lowest_major !== NULL && $lowest_major !== FALSE) { - db_query("UPDATE {project_release_supported_versions} SET supported = 1, recommended = 1 WHERE nid = %d AND tid = %d AND major = %d", $pid, $tid, $lowest_major); + db_query("UPDATE {project_release_supported_versions} SET supported = %d, recommended = %d WHERE nid = %d AND tid = %d AND major = %d", 1, 1, $pid, $tid, $lowest_major); } } } @@ -682,7 +689,7 @@ function project_release_check_supported // Adding or editing a release. // First make sure this branch has at least 1 published release node - $published_releases = db_result(db_query("SELECT COUNT(*) FROM {project_release_nodes} r INNER JOIN {node} n ON n.nid = r.nid INNER JOIN {term_node} tn ON tn.nid = n.nid WHERE r.pid = %d AND r.version_major = %d AND tn.tid = %d AND n.status = 1", $pid, $major, $tid)); + $published_releases = db_result(db_query("SELECT COUNT(*) FROM {project_release_nodes} r INNER JOIN {node} n ON n.nid = r.nid INNER JOIN {term_node} tn ON tn.nid = n.nid WHERE r.pid = %d AND r.version_major = %d AND tn.tid = %d AND n.status = %d", $pid, $major, $tid, 1)); if ($published_releases) { // We have at least 1 published release, so make sure we have an entry // for this major version in {project_release_supported_versions}. @@ -706,7 +713,7 @@ function project_release_check_supported $recommended = 0; } if (isset($recommended)) { - db_query("INSERT INTO {project_release_supported_versions} (nid, tid, major, supported, recommended, snapshot) VALUES (%d, %d, %d, 1, %d, 0)", $pid, $tid, $major, $recommended); + db_query("INSERT INTO {project_release_supported_versions} (nid, tid, major, supported, recommended, snapshot) VALUES (%d, %d, %d, %d, %d, %d)", $pid, $tid, $major, 1, $recommended, 0); } } } @@ -828,7 +835,7 @@ function project_release_view($node, $te $output = ''; if (project_use_cvs($project) && isset($node->tag)) { - if ($node->rebuild) { + if (!empty($node->rebuild)) { $output .= t('Nightly development snapshot from CVS branch: @tag', array('@tag' => $node->tag)) .'
'; } else { @@ -836,7 +843,7 @@ function project_release_view($node, $te } } - if ($node->file_path) { + if (!empty($node->file_path)) { $output .= ''. t('Download: !file', array('!file' => theme('project_release_download_link', $node->file_path))) .'
'; $output .= ''. t('Size: !size', array('!size' => format_size(filesize(file_create_path($node->file_path))))) .'
'; $output .= ''. t('md5_file hash: !file_hash', array('!file_hash' => $node->file_hash)) .'
'; @@ -844,7 +851,7 @@ function project_release_view($node, $te if ($node->created) { $output .= ''. t('First released: !created', array('!created' => format_date($node->created))) .'
'; } - if ($node->file_date && ($node->file_date != $node->created)) { + if (!empty($node->file_date) && ($node->file_date != $node->created)) { $output .= ''. t('Last updated: !changed', array('!changed' => format_date($node->file_date))) .'
'; } $node->content['release_info'] = array( @@ -857,14 +864,16 @@ function project_release_view($node, $te $rows = array(); $result = db_query('SELECT * FROM {project_release_package_errors} WHERE nid = %d', $node->nid); $error = db_fetch_object($result); - $rows = unserialize($error->messages); - if (!empty($rows)) { - $node->content['release_errors'] = array( - '#value' => theme('item_list', $rows, t('Packaging error messages')), - '#weight' => -1, - '#prefix' => ' ', - ); + 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' => ' ', + ); + } } } @@ -875,19 +884,25 @@ function project_release_view($node, $te * Display a list of releases for a given project * @ingroup project_release_api */ -function project_release_project_releases() { - $node = node_load(arg(1)); - - // Breadcrumb navigation - $breadcrumb[] = l($node->title, 'node/'. $node->nid); - project_project_set_breadcrumb($node, $breadcrumb); - - $output = project_release_list($node); - - drupal_set_title(t('Releases for %project', array('%project' => $node->title))); - return $output; -} - + // @TODO: I believe we can remove this function since this is now + // provided by the project_release_by_project default view. + // However, we probably need to make sure the breadcrumb is + // properly set in that view. +//function project_release_project_releases($node) { +// // Breadcrumb navigation +// $breadcrumb[] = l($node->title, 'node/'. $node->nid); +// project_project_set_breadcrumb($node, $breadcrumb); +// +// $output = project_release_list($node); +// +// drupal_set_title(t('Releases for %project', array('%project' => $node->title))); +// 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 @@ -925,13 +940,15 @@ function project_release_get_releases($p $args = array($project->nid); if (!project_check_admin_access($project)) { if (!empty($rids)) { - $where = "AND (n.status = 1 OR n.nid IN (". implode(',', array_fill(0, count($rids), '%d')) ."))"; + $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 = 1)'; + $where = 'AND (n.status = %d)'; + $args[] = 1; } if ($filter_by == 'files') { $where .= " AND (r.file_path <> '')"; @@ -960,18 +977,20 @@ function project_release_get_releases($p * Returns a listing of project release nodes * @ingroup project_release_callback */ -function project_release_list($project, $main = 0) { - if ($releases = project_release_get_releases($project, 1, 'date', 'files')) { - $output = ''; - foreach ($releases as $release) { - $output .= node_view($release); - } - } - else { - $output = t('There are no published releases for this project.'); - } - return $output; -} + // @TODO: I believe we can remove this function since this is now + // provided by the project_release_by_project default view. +//function project_release_list($project, $main = 0) { +// if ($releases = project_release_get_releases($project, 1, 'date', 'files')) { +// $output = ''; +// foreach ($releases as $release) { +// $output .= node_view($release); +// } +// } +// else { +// $output = t('There are no published releases for this project.'); +// } +// return $output; +//} /** * Returns a listing of all active project release compatibility terms @@ -1025,32 +1044,32 @@ function project_release_version_filter_ ); $register = ''; if (variable_get('user_register', 1)) { - $register = ' or '. l(t('register'), 'user/register', array(), $destination) .' '; + $register = ' or '. l(t('register'), 'user/register', array('query' => $destination)) .' '; } - $form['version_login'] = array('#value' => l(t('Login'), 'user/login', array(), $destination) . $register . t('to modify the filter.')); + $form['version_login'] = array('#value' => l(t('Login'), 'user/login', array('query' => $destination)) . $register . t('to modify the filter.')); } $form['#redirect'] = FALSE; } return isset($form) ? $form : ''; } -function project_release_version_filter_form_submit($form_id, $form_values) { - if (isset($form_values['version_tid'])) { - $_SESSION['project_version'] = $form_values['version_tid']; +function project_release_version_filter_form_submit($form, &$form_state) { + if (isset($form_state['values']['version_tid'])) { + $_SESSION['project_version'] = $form_state['values']['version_tid']; } } -function project_release_version_filter_form_validate($form_id, $form_values, $form) { +function project_release_version_filter_form_validate($form, &$form_state) { global $user; - if (!$user->uid && $form_values['version_tid'] != variable_get('project_release_overview', -1)) { - $vocab = taxonomy_get_vocabulary(_project_release_get_api_vid()); + if (!$user->uid && $form_state['values']['version_tid'] != variable_get('project_release_overview', -1)) { + $vocab = taxonomy_vocabulary_load(_project_release_get_api_vid()); form_set_error('version_tid', t('You must login or register to modify the @vocab filter.', array('@vocab' => $vocab->name))); } } function theme_project_release_version_filter_form($form) { if (project_release_get_api_taxonomy()) { - $vocab = taxonomy_get_vocabulary(_project_release_get_api_vid()); + $vocab = taxonomy_vocabulary_load(_project_release_get_api_vid()); $label = check_plain($vocab->name); } else { @@ -1069,7 +1088,7 @@ function theme_project_release_version_f * Implementation of hook_form_alter(). * @ingroup project_release_fapi */ -function project_release_form_alter($form_id, &$form) { +function project_release_form_alter(&$form, &$form_state, $form_id) { if ($form_id == 'project_project_node_form') { return project_release_alter_project_form($form); } @@ -1090,14 +1109,13 @@ function project_release_alter_project_f /** * Releases subtab for the project edit tab. */ -function project_release_project_edit_releases() { - $node = node_load(arg(1)); +function project_release_project_edit_releases($node) { project_project_set_breadcrumb($node); drupal_set_title(check_plain($node->title)); return drupal_get_form('project_release_project_edit_form', $node); } -function project_release_project_edit_form($node) { +function project_release_project_edit_form($form_state, $node) { // Get all the data about major versions for this project. $data = _project_release_get_version_major_data($node); @@ -1110,7 +1128,7 @@ function project_release_project_edit_fo '#value' => t('Supported versions'), ); - $vocab = taxonomy_get_vocabulary(_project_release_get_api_vid()); + $vocab = taxonomy_vocabulary_load(_project_release_get_api_vid()); $form['help'] = array( '#type' => 'markup', '#value' => t('For each term in the %api_vocabulary_name vocabulary, the following tables allow you to define which major versions are supported. If there are releases from more than one major version number, you can select which major version should be recommended for new users to download. You can also control if the development snapshot releases should be displayed on the front page of the project. Finally, for each term in the %api_vocabulary_name vocabulary, the current recommended release is shown. If no official releases have been made, the development snapshot from the corresponding branch will be listed. Otherwise, the most recent official release will be listed.', array('%api_vocabulary_name' => $vocab->name)), @@ -1160,13 +1178,9 @@ function _project_release_get_version_ma $data['node'] = $node; $params = array(); $params[] = $node->nid; - $placeholders = array(); $active_tids = project_release_compatibility_list(); - foreach ($active_tids as $tid => $api_term) { - $placeholders[] = '%d'; - $params[] = $tid; - } - $tid_where = 'prsv.tid IN ('. implode(',', $placeholders) .')'; + $params = $params + array_keys($active_tids); + $tid_where = 'prsv.tid IN ('. db_placeholders($active_tids) .')'; $result = db_query("SELECT prsv.*, td.name AS term_name FROM {project_release_supported_versions} prsv INNER JOIN {term_data} td ON prsv.tid = td.tid WHERE prsv.nid = %d AND $tid_where ORDER BY td.weight, td.name", $params); while ($obj = db_fetch_object($result)) { $tid = $obj->tid; @@ -1186,7 +1200,8 @@ function _project_release_get_version_ma } function _project_release_edit_version_major_form($data) { - drupal_add_js(drupal_get_path('module', 'project_release') .'/project_release.js'); +// Since this form is used relatively infrequently, don't allow the js to be aggregated. + drupal_add_js(drupal_get_path('module', 'project_release') .'/project_release.js', 'module', 'header', FALSE, TRUE, FALSE); $form = array(); $node = $data['node']; @@ -1236,7 +1251,7 @@ function _project_release_edit_version_m '#default_value' => $recommended_version, '#attributes' => array('class'=>'recommended'), ); - $recommended_major = db_result(db_query("SELECT major FROM {project_release_supported_versions} WHERE nid = %d AND tid = %d AND recommended = 1", $node->nid, $api_tid)); + $recommended_major = db_result(db_query("SELECT major FROM {project_release_supported_versions} WHERE nid = %d AND tid = %d AND recommended = %d", $node->nid, $api_tid, 1)); if ($recommended_major !== FALSE) { $current_recommended = $form['api'][$api_tid]['major'][$recommended_major]['version_name']['#value']; } @@ -1310,12 +1325,12 @@ function theme_project_release_project_e * @ingroup project_release_fapi * @see project_release_project_edit_releases */ -function project_release_project_edit_form_validate($form_id, $form_values, $form) { - if (!empty($form_values['version_format'])) { - _project_release_validate_format_string($form_values, 'version_format'); +function project_release_project_edit_form_validate($form, &$form_state) { + if (!empty($form_state['values']['version_format'])) { + _project_release_validate_format_string($form_state['values'], 'version_format'); } - if (isset($form_values['api'])) { - foreach ($form_values['api'] as $tid => $api_info) { + if (isset($form_state['values']['api'])) { + foreach ($form_state['values']['api'] as $tid => $api_info) { $supported = FALSE; // First, we just iterate through to see if *any* majors are supported. foreach ($api_info['major'] as $major => $flags) { @@ -1329,15 +1344,15 @@ function project_release_project_edit_fo foreach ($api_info['major'] as $major => $flags) { if (empty($flags['supported']) && !empty($flags['snapshot'])) { $element = 'api]['. $tid .'][major]['. $major .'][snapshot'; - form_set_error($element, t('You can not show a snapshot release for a major version that is not supported for %api_term_name.', array('%api_term_name' => $form['api'][$tid]['#api_term_name']))); + form_set_error($element, t('You can not show a snapshot release for a major version that is not supported for %api_term_name.', array('%api_term_name' => $form_state['values']['api'][$tid]['#api_term_name']))); } } $recommended = $api_info['recommended']; if ($recommended < 0) { - form_set_error("api][$tid][recommended", t('You must select a recommended major version for %api_term_name.', array('%api_term_name' => $form['api'][$tid]['#api_term_name']))); + form_set_error("api][$tid][recommended", t('You must select a recommended major version for %api_term_name.', array('%api_term_name' => $form_state['values']['api'][$tid]['#api_term_name']))); } elseif (empty($api_info['major'][$recommended]['supported'])) { - form_set_error("api][$tid][recommended", t('You can not recommend a major version that is not supported for %api_term_name.', array('%api_term_name' => $form['api'][$tid]['#api_term_name']))); + form_set_error("api][$tid][recommended", t('You can not recommend a major version that is not supported for %api_term_name.', array('%api_term_name' => $form_state['values']['api'][$tid]['#api_term_name']))); } } } @@ -1349,12 +1364,12 @@ function project_release_project_edit_fo * @ingroup project_release_fapi * @see project_release_project_edit_releases */ -function project_release_project_edit_form_submit($form_id, $form_values) { - $nid = $form_values['nid']; - db_query("UPDATE {project_release_projects} SET releases = %d, version_format = '%s' WHERE nid = %d", $form_values['releases'], $form_values['version_format'], $nid); +function project_release_project_edit_form_submit($form, &$form_state) { + $nid = $form_state['values']['nid']; + db_query("UPDATE {project_release_projects} SET releases = %d, version_format = '%s' WHERE nid = %d", $form_state['values']['releases'], $form_state['values']['version_format'], $nid); - if (!empty($form_values['api'])) { - foreach ($form_values['api'] as $tid => $values) { + if (!empty($form_state['values']['api'])) { + foreach ($form_state['values']['api'] as $tid => $values) { if (isset($values['recommended'])) { $recommended_major = $values['recommended']; } @@ -1376,9 +1391,9 @@ function project_release_project_edit_fo } } } - db_query("UPDATE {node} SET changed = %d WHERE nid = %d", time(), $form_values['nid']); + db_query("UPDATE {node} SET changed = %d WHERE nid = %d", time(), $form_state['values']['nid']); - $cid = 'table:'. $form_values['nid'] .':'; + $cid = 'table:'. $form_state['values']['nid'] .':'; cache_clear_all($cid, 'cache_project_release', TRUE); drupal_set_message(t('Release settings have been saved.')); @@ -1446,7 +1461,7 @@ function project_release_alter_release_f } // If there are no children elements, we should unset the entire // thing so we don't end up with an empty fieldset. - if (!element_children($form['taxonomy'])) { + if (isset($form['taxonomy']) && !element_children($form['taxonomy'])) { unset($form['taxonomy']); } } @@ -1483,13 +1498,15 @@ function project_release_project_nodeapi switch ($op) { case 'load': $project = db_fetch_object(db_query('SELECT * FROM {project_release_projects} WHERE nid = %d', $node->nid)); - $fields = array('releases', 'version_format'); - foreach ($fields as $field) { - $node->$field = $project->$field; - } - $wants_snapshots = db_result(db_query('SELECT tid FROM {project_release_supported_versions} WHERE nid = %d AND snapshot = 1 LIMIT 1', $node->nid)); - if (isset($wants_snapshots)) { - $node->project_release_show_snapshots = TRUE; + if (!empty($project)) { + $fields = array('releases', 'version_format'); + foreach ($fields as $field) { + $node->$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_show_snapshots = TRUE; + } } break; @@ -1569,15 +1586,17 @@ function project_release_get_current_rec $join = ' INNER JOIN {term_node} tn ON n.nid = tn.nid AND tn.tid = %d'; $params[] = $api_tid; - $where = 'WHERE (r.pid = %d) AND (n.status = 1)'; + $where = 'WHERE (r.pid = %d) AND (n.status = %d)'; $params[] = $project_nid; + $params[] = 1; if (isset($recommended_major)) { $where .= ' AND (r.version_major = %d)'; $params[] = $recommended_major; } else { - $join .= ' INNER JOIN {project_release_supported_versions} prsv ON prsv.nid = r.pid AND prsv.tid = tn.tid AND prsv.major = r.version_major AND prsv.recommended = 1 '; + $join .= ' INNER JOIN {project_release_supported_versions} prsv ON prsv.nid = r.pid AND prsv.tid = tn.tid AND prsv.major = r.version_major AND prsv.recommended = %d '; + $params[] = 1; } // We always want the dev snapshots to show up last. @@ -1588,10 +1607,11 @@ function project_release_get_current_rec $orderby[] = 'r.file_date DESC'; $order_by = 'ORDER BY '. implode(', ', $orderby); + $params[] = 1; $result = db_query(db_rewrite_sql( "SELECT n.nid, n.title, n.created, r.* FROM {node} n ". "INNER JOIN {project_release_nodes} r ON r.nid = n.nid $join ". - "$where $order_by LIMIT 1"), $params); + "$where $order_by LIMIT %d"), $params); $release = db_fetch_object($result); $current_major[$project_nid][$api_tid][$major] = $release; @@ -1602,7 +1622,7 @@ function project_release_get_current_rec * Theme the appropriate release download table for a project node. */ function theme_project_release_project_download_table($node) { - if (!$node->releases) { + if (empty($node->releases)) { return; } $output = ''. t('Releases') .'
'; @@ -1615,6 +1635,8 @@ function theme_project_release_project_d /** * Implemenation of hook_project_page_link_alter(). + * + * Note: This is *not* an implementation of hook_link_alter(). */ function project_release_project_page_link_alter($node, &$all_links) { $all_links['project_release'] = array( @@ -1686,14 +1708,16 @@ function project_release_table($project, return $cached->data; } - $select = $join = $where = $order_by = ''; + $selects = $join = $where = $order_by = ''; + $args = array(); $tids = project_release_compatibility_list(); if ($tids) { unset($tids[-1]); // get rid of that one. if (!empty($tids)) { $join = ' INNER JOIN {term_node} tn ON n.nid = tn.nid AND tn.tid in (' - . implode(',', array_keys($tids)) .') ' + . db_placeholders($tids) .') ' .' INNER JOIN {term_data} td ON td.tid = tn.tid '; + $args = array_keys($tids); $selects[] = 'tn.tid'; $selects[] = 'td.name as api_term_name'; $orderby[] = 'td.weight'; @@ -1707,24 +1731,31 @@ function project_release_table($project, $selects[] = 'prsv.snapshot'; $join .= ' INNER JOIN {project_release_supported_versions} prsv ON prsv.nid = r.pid AND prsv.tid = tn.tid AND prsv.major = r.version_major '; if ($table_type == 'recommended') { - $join .= 'AND prsv.recommended = 1 '; + $join .= 'AND prsv.recommended = %d '; + $args[] = 1; } elseif ($table_type == 'supported') { - $join .= 'AND prsv.supported = 1 '; + $join .= 'AND prsv.supported = %d '; + $args[] = 1; } } else { // TODO: someday (never?) when project_release doesn't require taxonomy. } + $args[] = $project->nid; // Account for r.pid. + $args[] = 1; // Account for n.status = 1. switch ($release_type) { case 'official': - $where = 'AND r.rebuild <> 1'; + $where = 'AND r.rebuild <> %d'; + $args[] = 1; break; case 'snapshot': // For snapshot tables, restrict to snapshot nodes from branches where // the maintainer wants the snapshot visible. - $where = 'AND r.rebuild = 1 AND prsv.snapshot = 1'; + $where = 'AND r.rebuild = %d AND prsv.snapshot = %d'; + $args[] = 1; + $args[] = 1; break; case 'all': // If we're generating the default releases table, we want the @@ -1751,8 +1782,8 @@ function project_release_table($project, $result = db_query(db_rewrite_sql( "SELECT n.nid, n.created, $select r.* FROM {node} n ". "INNER JOIN {project_release_nodes} r ON r.nid = n.nid $join ". - "WHERE (r.pid = %d) AND (n.status = 1) $where $order_by"), - $project->nid); + "WHERE (r.pid = %d) AND (n.status = %d) $where $order_by"), + $args); $rows = array(); // Rows for the download table. $seen = array(); // Keeps track of which versions we already saw. @@ -1825,7 +1856,7 @@ function project_release_table($project, $output = theme('table', $header, $rows, array('class' => 'releases')); } // Default cache time is 12 hours - will be cleared by the packaging script - cache_set($cid, 'cache_project_release', $output, time() + 43200); + cache_set($cid, $output, 'cache_project_release', time() + 43200); return $output; } @@ -2046,6 +2077,7 @@ function project_release_exists($version return false; } + $taxo_join = $taxo_where = ''; if (isset($version->version_api_tid)) { $taxo_join = ' INNER JOIN {term_node} t ON p.nid = t.nid'; $taxo_where = ' AND t.tid = %d'; @@ -2053,14 +2085,14 @@ function project_release_exists($version $tid = $version->version_api_tid; } - $sql = 'SELECT * FROM {project_release_nodes} p'. $taxo_join .' WHERE p.pid = %d'; + $sql = 'SELECT COUNT(*) FROM {project_release_nodes} p'. $taxo_join .' WHERE p.pid = %d'; foreach ($types as $field => $type) { $sql .= " AND p.$field = $type"; } $sql .= $taxo_where; // we put pid as the first WHERE, so stick it on the front $values = array_merge(array('pid' => $version->pid), $values); - return db_num_rows(db_query($sql, $values)); + return db_result(db_query($sql, $values)); } /** @@ -2166,16 +2198,104 @@ function project_release_pick_project_fo return $form; } -function project_release_pick_project_form_validate($form_id, $form_values) { - if (empty($form_values['pid'])) { +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_values['pid']); + $node = node_load($form_state['values']['pid']); if (empty($node) || $node->type != 'project_project') { form_set_error('pid', t('Invalid project selected.')); } } -function project_release_pick_project_form_submit($form_id, $form_values) { - return 'node/add/project-release/'. $form_values['pid']; +function project_release_pick_project_form_submit($form, &$form_state) { + $form_state['redirect'] = 'node/add/project-release/'. $form_state['values']['pid']; +} + +/** + * Implementation of hook_theme(). + */ +function project_release_theme() { + return array( + 'project_release_download_link' => array( + 'arguments' => array( + 'file_path' => NULL, + 'link_text' => NULL, + 'as_array' => FALSE, + ), + ), + 'project_release_download_table_row' => array( + 'arguments' => array( + 'release' => NULL, + 'recommended' => FALSE, + 'can_edit' => FALSE, + 'print_size' => TRUE, + ), + ), + 'project_release_download_text_recommended' => array( + 'arguments' => array( + 'release' => NULL, + 'text_type' => NULL, + ), + ), + 'project_release_download_text_snapshot' => array( + 'arguments' => array( + 'release' => NULL, + 'text_type' => NULL, + ), + ), + 'project_release_download_text_supported' => array( + 'arguments' => array( + 'release' => NULL, + 'text_type' => NULL, + ), + ), + 'project_release_download_text_unsupported' => array( + 'arguments' => array( + 'release' => NULL, + 'text_type' => NULL, + ), + ), + 'project_release_form_value' => array( + 'arguments' => array( + 'element' => NULL, + ), + ), + 'project_release_project_download_table' => array( + 'arguments' => array( + 'node' => NULL, + ), + ), + 'project_release_project_edit_form' => array( + 'arguments' => array( + 'form' => NULL, + ), + ), + 'project_release_table_overview' => array( + 'arguments' => array( + 'project' => NULL, + 'table_type' => NULL, + 'release_type' => NULL, + 'title' => NULL, + 'print_size' => NULL, + ), + ), + 'project_release_version_filter_form' => array( + 'arguments' => array( + 'form' => NULL, + ), + ), + 'project_release_node_form_version_elements' => array( + 'arguments' => array( + 'form' => NULL, + ), + ), + ); +} + +function theme_project_release_node_form_version_elements($form) { + $output = ''; + $output .= drupal_render($form); + $output .= ''; + return $output; } Index: release/project_release.views.inc =================================================================== RCS file: release/project_release.views.inc diff -N release/project_release.views.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ release/project_release.views.inc 20 Jun 2008 23:17:53 -0000 @@ -0,0 +1,126 @@ + array( + 'left_field' => 'nid', + 'field' => 'nid', + ), + + 'project_projects' => array( + 'type' => 'INNER', + 'left_table' => 'project_projects', + 'left_field' => 'nid', + 'field' => 'pid', + ) + ); + + // pid + $data['project_release_nodes']['pid'] = array( + 'title' => t('Pid'), + 'help' => t('The node ID of the project node a release is tied to.'), + 'field' => array( + 'handler' => 'views_handler_field_node', + 'click sortable' => TRUE, + ), + // Information for accepting a nid as an argument + 'argument' => array( + 'handler' => 'views_handler_argument_node_nid', + 'name field' => 'title', + 'numeric' => TRUE, + 'validate type' => 'nid', + ), + // Information for accepting a nid as a filter + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + ), + // Information for sorting on a nid. + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ); + + // version + $data['project_release_nodes']['version'] = array( + 'title' => t('Version string'), + 'help' => t('The full version string of a release.'), + 'field' => array( + 'group' => t('Project release'), + 'handler' => 'views_handler_field_node', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + ), + ); + + // tag + $data['project_release_nodes']['tag'] = array( + 'title' => t('Tag'), + 'help' => t('The tag associated with a release.'), + 'field' => array( + 'group' => t('Project release'), + 'handler' => 'views_handler_field_node', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + ), + ); + + // @TODO: file_path + // @TODO: file_date + // @TODO: file_hash + // @TODO: rebuild + // @TODO: version_major + // @TODO: version_minor + // @TODO: version_patch + // @TODO: version_extra + + + return $data; +} + + Index: release/project_release.views_default.inc =================================================================== RCS file: release/project_release.views_default.inc diff -N release/project_release.views_default.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ release/project_release.views_default.inc 20 Jun 2008 23:17:53 -0000 @@ -0,0 +1,317 @@ +name = 'project_release_by_project'; + $view->description = 'List the project release nodes associated with a particular project.'; + $view->tag = 'project,releases'; + $view->view_php = ''; + $view->base_table = 'node'; + $view->is_cacheable = '0'; + $view->api_version = 2; + $view->disabled = FALSE; // Edit this to true to make a default view disabled initially + $view->display = array(); + $display = new views_display; + $display->id = 'default'; + $display->display_title = 'Defaults'; + $display->display_plugin = 'default'; + $display->position = '1'; + $display->display_options = array( + 'style_plugin' => 'default', + 'style_options' => array(), + 'row_plugin' => 'node', + 'row_options' => array( + 'teaser' => 1, + 'links' => 1, + ), + 'relationships' => array(), + 'fields' => array( + 'nid' => array( + 'id' => 'nid', + 'table' => 'node', + 'field' => 'nid', + 'label' => 'Nid', + 'relationship' => 'none', + 'link_to_node' => 0, + ), + 'title' => array( + 'id' => 'title', + 'table' => 'node', + 'field' => 'title', + 'label' => 'Title', + 'relationship' => 'none', + 'link_to_node' => 0, + ), + 'version' => array( + 'id' => 'version', + 'table' => 'project_release_nodes', + 'field' => 'version', + 'label' => 'Version string', + 'relationship' => 'none', + 'link_to_node' => 1, + ), + ), + 'sorts' => array( + 'created' => array( + 'id' => 'created', + 'table' => 'node', + 'field' => 'created', + 'order' => 'DESC', + 'granularity' => 'day', + 'relationship' => 'none', + ), + 'name' => array( + 'id' => 'name', + 'table' => 'term_data', + 'field' => 'name', + 'order' => 'DESC', + 'relationship' => 'none', + ), + ), + 'arguments' => array( + 'pid' => array( + 'id' => 'pid', + 'table' => 'project_release_nodes', + 'field' => 'pid', + 'default_action' => 'not found', + 'style_plugin' => 'default_summary', + 'style_options' => array( + 'count' => TRUE, + 'override' => FALSE, + 'items_per_page' => 25, + ), + 'wildcard' => 'all', + 'wildcard_substitution' => 'All', + 'title' => 'Releases for %1', + 'default_argument_type' => 'fixed', + 'default_argument' => '', + 'validate_type' => 'node', + 'validate_fail' => 'not found', + 'relationship' => 'none', + 'default_argument_fixed' => '', + 'default_argument_php' => '', + 'validate_argument_node_type' => array( + 'project_project' => 'project_project', + 'project_release' => 0, + 'book' => 0, + 'page' => 0, + 'story' => 0, + ), + 'validate_argument_vocabulary' => array( + '3' => 0, + '5' => 0, + '2' => 0, + '1' => 0, + '4' => 0, + ), + 'validate_argument_type' => 'tid', + 'validate_argument_php' => '', + 'default_argument_user' => 0, + 'validate_argument_node_access' => 1, + 'validate_argument_nid_type' => 'nid', + 'break_phrase' => 0, + 'not' => 0, + ), + ), + 'filters' => array( + 'type' => array( + 'id' => 'type', + 'table' => 'node', + 'field' => 'type', + 'operator' => 'in', + 'value' => array( + 'project_release' => 'project_release', + ), + 'group' => 0, + 'exposed' => FALSE, + 'expose' => array( + 'operator' => FALSE, + 'label' => '', + ), + 'relationship' => 'none', + 'expose_button' => array( + 'button' => 'Expose', + ), + ), + 'tid' => array( + 'id' => 'tid', + 'table' => 'term_node', + 'field' => 'tid', + 'operator' => 'or', + 'value' => array(), + 'group' => 0, + 'exposed' => TRUE, + 'expose' => array( + 'operator' => '', + 'identifier' => 'api', + 'label' => 'API Version', + 'optional' => 1, + 'single' => 0, + 'remember' => 1, + ), + 'type' => 'select', + 'vid' => '2', + 'relationship' => 'none', + 'expose_button' => array( + 'button' => 'Hide', + ), + 'reduce_duplicates' => 0, + ), + 'status' => array( + 'id' => 'status', + 'table' => 'node', + 'field' => 'status', + 'operator' => '=', + 'value' => 1, + 'group' => 0, + 'exposed' => FALSE, + 'expose' => array( + 'operator' => FALSE, + 'label' => '', + ), + 'relationship' => 'none', + 'expose_button' => array( + 'button' => 'Expose', + ), + ), + ), + 'items_per_page' => 20, + 'offset' => 0, + 'access' => array( + 'type' => 'perm', + 'role' => array( + '3' => 0, + '1' => 0, + '2' => 0, + '6' => 0, + '5' => 0, + '4' => 0, + '7' => 0, + ), + 'perm' => 'access projects', + ), + 'use_pager' => '1', + 'pager_element' => 0, + 'empty' => 'There are no published releases for this project.', + 'empty_format' => '1', + ); + $view->display['default'] = $display; + $display = new views_display; + $display->id = 'page'; + $display->display_title = 'Releases for *project*'; + $display->display_plugin = 'page'; + $display->position = '2'; + $display->display_options = array( + 'defaults' => array( + 'access' => TRUE, + 'title' => TRUE, + 'header' => TRUE, + 'header_format' => TRUE, + 'header_empty' => TRUE, + 'footer' => TRUE, + 'footer_format' => TRUE, + 'footer_empty' => TRUE, + 'empty' => TRUE, + 'empty_format' => TRUE, + 'use_ajax' => TRUE, + 'items_per_page' => TRUE, + 'offset' => TRUE, + 'use_pager' => TRUE, + 'pager_element' => TRUE, + 'use_more' => TRUE, + 'distinct' => TRUE, + 'link_display' => TRUE, + 'style_plugin' => TRUE, + 'style_options' => TRUE, + 'row_plugin' => TRUE, + 'row_options' => TRUE, + 'relationships' => TRUE, + 'fields' => TRUE, + 'sorts' => TRUE, + 'arguments' => TRUE, + 'filters' => TRUE, + ), + 'relationships' => array(), + 'fields' => array(), + 'sorts' => array(), + 'arguments' => array(), + 'filters' => array(), + 'path' => 'node/%/release', + 'menu' => array( + 'type' => 'none', + 'title' => 'Test title', + 'weight' => '0', + ), + ); + $view->display['page'] = $display; + $display = new views_display; + $display->id = 'feed'; + $display->display_title = 'Feed'; + $display->display_plugin = 'feed'; + $display->position = '3'; + $display->display_options = array( + 'defaults' => array( + 'access' => TRUE, + 'title' => TRUE, + 'header' => TRUE, + 'header_format' => TRUE, + 'header_empty' => TRUE, + 'footer' => TRUE, + 'footer_format' => TRUE, + 'footer_empty' => TRUE, + 'empty' => TRUE, + 'empty_format' => TRUE, + 'use_ajax' => TRUE, + 'items_per_page' => TRUE, + 'offset' => TRUE, + 'use_pager' => TRUE, + 'pager_element' => TRUE, + 'use_more' => TRUE, + 'distinct' => TRUE, + 'link_display' => TRUE, + 'style_plugin' => FALSE, + 'style_options' => FALSE, + 'row_plugin' => FALSE, + 'row_options' => FALSE, + 'relationships' => TRUE, + 'fields' => TRUE, + 'sorts' => TRUE, + 'arguments' => TRUE, + 'filters' => TRUE, + ), + 'relationships' => array(), + 'fields' => array(), + 'sorts' => array(), + 'arguments' => array(), + 'filters' => array(), + 'displays' => array( + 'default' => 0, + 'page' => 0, + ), + 'style_plugin' => 'rss', + 'style_options' => array( + 'mission_description' => FALSE, + 'description' => '', + ), + 'row_plugin' => 'node_rss', + 'path' => 'node/%/release/feed', + 'row_options' => array( + 'item_length' => 'default', + ), + ); + $view->display['feed'] = $display; + $views[$view->name] = $view; + + return $views; +} \ No newline at end of file Index: usage/project_usage.install =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/project/usage/project_usage.install,v retrieving revision 1.4 diff -u -p -r1.4 project_usage.install --- usage/project_usage.install 11 Jun 2008 02:50:24 -0000 1.4 +++ usage/project_usage.install 20 Jun 2008 23:17:53 -0000 @@ -1,61 +1,15 @@ t('Table used to store raw usage information.'), + 'fields' => array( + 'project_uri' => array( + 'description' => t('Primary Key: The {project_projects}.uri short name of the project.'), + 'type' => 'varchar', + 'length' => 50, + 'not null' => TRUE, + 'default' => '', + ), + 'timestamp' => array( + 'description' => t('Primary Key: The Unix timestamp of when the request was made.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'site_key' => array( + 'description' => t('Primary Key: An MD5 hash that identifies the site from which the request was made.'), + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => '', + ), + 'api_version' => array( + 'description' => t('The {term_data}.name of the API version requested.'), + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => '', + ), + 'project_version' => array( + 'description' => t('The {project_release_nodes}.version of the requested project.'), + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'pid' => array( + 'description' => t('The {node}.nid of the requested project.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'nid' => array( + 'description' => t('The {node}.nid of the requested release.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'tid' => array( + 'description' => t('The {term_data}.tid of the API compatability version of the requested release.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'ip_addr' => array( + 'description' => t('IP address to prevent abuse of the usage tracking system.'), + 'type' => 'varchar', + 'length' => 128, + 'not null' => TRUE, + 'default' => '', + ), + ), + 'primary key' => array('timestamp', 'project_uri', 'site_key'), + ); - // Since this might take a long time, if we're not in 'safe mode', increase - // the maximum execution time. - if (!ini_get('safe_mode')) { - set_time_limit(240); - } + $schema['project_usage_day'] = array( + 'description' => t('Table used to store daily usage information.'), + 'fields' => array( + 'timestamp' => array( + 'description' => t('Primary Key: The Unix timestamp of when the request was made.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'site_key' => array( + 'description' => t('Primary Key: An MD5 hash that identifies the site from which the request was made.'), + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => '', + ), + 'pid' => array( + 'description' => t('Primary Key: The {node}.nid of the requested project.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'nid' => array( + 'description' => t('The {node}.nid of the requested release.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'tid' => array( + 'description' => t('The {term_data}.tid of the API compatability version of the requested release.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'ip_addr' => array( + 'description' => t('IP address to prevent abuse of the usage tracking system.'), + 'type' => 'varchar', + 'length' => 128, + 'not null' => TRUE, + 'default' => '', + ), + ), + 'primary key' => array('timestamp', 'site_key', 'pid'), + ); - // Key is table name, value is function used to round the timestamp. - $tables = array( - 'project_usage_week_project' => 'project_usage_weekly_timestamp', - 'project_usage_week_release' => 'project_usage_weekly_timestamp', - 'project_usage_raw' => 'project_usage_daily_timestamp', - 'project_usage_day' => 'project_usage_daily_timestamp', + $schema['project_usage_week_project'] = array( + 'description' => t('Table used to store weekly usage information by project and {term_data}.tid.'), + 'fields' => array( + 'nid' => array( + 'description' => t('Primary Key: The {node}.nid of the project.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'timestamp' => array( + 'description' => t('Primary Key: A Unix timestamp.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'tid' => array( + 'description' => t('Primary Key: The {term_data}.tid of the API compatability version of the release.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'count' => array( + 'description' => t('The number of requests.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + ), + 'primary key' => array('nid', 'timestamp', 'tid'), ); - foreach ($tables as $table => $rounding_function) { - $query = db_query("SELECT DISTINCT timestamp FROM {$table} ORDER BY timestamp ASC"); - while ($row = db_fetch_object($query)) { - $old = (int) $row->timestamp; - $new = (int) $rounding_function($old); - if ($old != $new) { - $ret[] = update_sql("UPDATE {$table} SET timestamp = $new WHERE timestamp = $old"); - } - } - } - return $ret; + $schema['project_usage_week_release'] = array( + 'description' => t('Table used to store weekly usage information by project and {term_data}.tid.'), + 'fields' => array( + 'nid' => array( + 'description' => t('Primary Key: The {node}.nid of the project.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'timestamp' => array( + 'description' => t('Primary Key: A Unix timestamp.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'count' => array( + 'description' => t('The number of requests.'), + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + ), + 'primary key' => array('nid', 'timestamp'), + ); + return $schema; } /** @@ -107,12 +216,20 @@ function project_usage_update_5000() { */ function project_usage_update_5001() { $ret = array(); - switch ($GLOBALS['db_type']) { - case 'mysql': - case 'mysqli': - $ret[] = update_sql("ALTER TABLE {project_usage_raw} ADD COLUMN ip_addr varchar(128) NOT NULL default '' AFTER tid"); - $ret[] = update_sql("ALTER TABLE {project_usage_day} ADD COLUMN ip_addr varchar(128) NOT NULL default '' AFTER tid"); - break; - } + // @TODO These were specified "AFTER tid". Is there any way to do the same in schemaAPI? + db_add_field($ret, 'project_usage_raw', 'ip_addr', array( + 'description' => t('IP address to prevent abuse of the usage tracking system.'), + 'type' => 'varchar', + 'length' => 128, + 'not null' => TRUE, + 'default' => '', + )); + db_add_field($ret, 'project_usage_day', 'ip_addr', array( + 'description' => t('IP address to prevent abuse of the usage tracking system.'), + 'type' => 'varchar', + 'length' => 128, + 'not null' => TRUE, + 'default' => '', + )); return $ret; }