Index: project_issue.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/project_issue/project_issue.module,v retrieving revision 1.80 diff -u -r1.80 project_issue.module --- project_issue.module 26 Jan 2008 06:41:51 -0000 1.80 +++ project_issue.module 25 Feb 2008 13:42:41 -0000 @@ -542,7 +542,11 @@ ); } - drupal_add_css(drupal_get_path('module', 'project_issue') .'/project_issue.css'); + $project_issue_path = drupal_get_path('module', 'project_issue'); + if (module_exists('views')) { + require_once './'. $project_issue_path .'/project_issue_views.inc'; + } + drupal_add_css($project_issue_path .'/project_issue.css'); } return $items; } @@ -1070,6 +1074,40 @@ } } +/** + * @defgroup project_issue_views Views-integration hooks + */ + +/** + * Implementation of hook_views_tables. + * @ingroup project_issue_views + * @see _project_issue_views_tables + */ +function project_issue_views_tables() { + require_once(drupal_get_path('module', 'project_issue') .'/project_issue_views.inc'); + return _project_issue_views_tables(); +} + +/** + * Implementation of hook_views_arguments. + * @ingroup project_issue_views + * @see _project_issue_views_arguments + */ +function project_issue_views_arguments() { + require_once(drupal_get_path('module', 'project_issue') .'/project_issue_views.inc'); + return _project_issue_views_arguments(); +} + +/** + * Implementation of hook_views_default_views. + * @ingroup project_issue_views + * @see _project_issue_views_default_views + */ +function project_issue_views_default_views() { + require_once(drupal_get_path('module', 'project_issue') .'/project_issue_views.inc'); + return _project_issue_views_default_views(); +} + /** * @defgroup project_issue_filter Project Issue number to link filter. Index: project_issue_views.inc =================================================================== RCS file: project_issue_views.inc diff -N project_issue_views.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ project_issue_views.inc 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,708 @@ + ago". + // Since the 'ago' takes up extra space, we provide our own field + // here that uses a custom handler so that we can omit 'ago'. + $tables['pi_node'] = array( + 'name' => 'node', + 'fields' => array( + 'changed' => array( + 'name' => t('Project issue: Updated Time'), + 'sortable' => true, + 'handler' => views_handler_field_project_issue_since, + 'option' => 'string', + 'help' => t('Display the last time the issue node was updated.'), + ), + ), + ); + + $tables['project_issues'] = array( + 'name' => 'project_issues', + 'join' => array( + 'type' => 'inner', + 'left' => array( + 'table' => 'node', + 'field' => 'nid' + ), + 'right' => array( + 'field' => 'nid' + ), + ), + 'fields' => array( + // To be useful, 'pid' requires another JOIN on {node}, so see + // the project_issue_project_node definition below. + 'category' => array( + 'name' => t('Project Issue: Category'), + 'sortable' => true, + 'help' => t('The issue\'s category (bug, task, feature, etc).'), + ), + 'component' => array( + 'name' => t('Project Issue: Component'), + 'sortable' => true, + 'help' => t('The issue\'s component (the options are controlled per-project).'), + ), + 'priority' => array( + 'name' => t('Project Issue: Priority'), + 'handler' => 'views_handler_field_project_issue_priority', + 'sortable' => true, + 'help' => t('The issue\'s priority (critical, normal, minor).'), + ), + 'rid' => array( + 'name' => t('Project Issue: Version'), + 'query_handler' => 'views_query_handler_field_project_issue_version', + 'handler' => 'views_handler_field_project_issue_version', + 'sortable' => true, + 'help' => t('The version associated with the issue (depends on project_release.module)'), + ), + 'sid' => array( + 'name' => t('Project Issue: Status'), + 'help' => t('The status of each issue.'), + 'sortable' => true, + 'handler' => 'views_handler_field_project_issue_status', + ), + ), + 'filters' => array( + 'category' => array( + 'name' => t('Project Issue: Category'), + 'operator' => array('=' => t('Equals')), + 'list' => 'views_handler_filter_project_issue_category', + 'list-type' => 'select', + 'help' => t('Filter by issue category'), + ), + 'priority' => array( + 'name' => t('Project Issue: Priority'), + 'operator' => array('=' => t('Equals')), + 'list' => 'views_handler_filter_project_issue_priority', + 'list-type' => 'select', + 'help' => t('Filter by issue priority'), + ), + 'sid' => array( + 'name' => t('Project Issue: Status'), + 'operator' => 'views_handler_operator_andor', + 'list' => 'views_handler_filter_project_issue_status', + 'list-type' => 'list', + 'value-type' => 'array', + 'handler' => 'views_handler_filter_project_issue_status_filter', + 'help' => t('Filter by issue status'), + ), + 'assigned' => array( + 'name' => t('Project Issue: Assigned to Current User'), + 'operator' => 'views_handler_operator_eqneq', + 'list' => 'views_handler_filter_usercurrent', + 'list-type' => 'select', + 'help' => t('This allows you to filter by whether or not the issue is assigned to the logged in user.'), + ), + ), + ); + + // Add data from the project module + $tables['project_issue_project_node'] = array( + 'name' => 'node', + 'join' => array( + 'type' => 'inner', + 'left' => array( + 'table' => 'project_issues', + 'field' => 'pid' + ), + 'right' => array( + 'field' => 'nid' + ), + ), + 'fields' => array( + 'title' => array( + 'name' => t('Project Issue Project Node: Title'), + 'handler' => array( + 'views_handler_field_project_issue_project_nodelink' => t('Normal'), + 'views_handler_field_project_issue_project_nodelink_with_mark' => t('With updated mark') + ), + 'option' => array( + '#type' => 'select', + '#options' => array( + 'link' => t('As link'), + 'nolink' => t('Without link') + ), + ), + 'sortable' => true, + 'pid' => 'nid', + 'addlfields' => array('changed', 'nid'), +// 'query_handler' => 'views_query_handler_field_project_issue_project_node', + 'help' => t('Display the title of the project.'), + ), + ), + 'filters' => array( + 'nid' => array( + 'name' => t('Project Issue Project Node: Project'), + 'operator' => array('=' => t('Equals')), + 'list' => 'views_handler_filter_project_issue_project', + 'list-type' => 'select', + 'help' => t('Filter by project'), + ), + ), + ); + // Add data from {project_projects} + $tables['project_issue_project_projects'] = array( + 'name' => 'project_projects', + 'join' => array( + 'type' => 'inner', + 'left' => array( + 'table' => 'project_issues', + 'field' => 'pid' + ), + 'right' => array( + 'field' => 'nid' + ), + ), + 'fields' => array( + 'uri' => array( + 'name' => t('Project Issue Project Node: Short name'), + 'sortable' => true, + 'help' => t('Display the short name of the project.'), + 'option' => array( + '#type' => 'select', + '#options' => array( + 'project_issue_display' => t('Display this field'), + 'project_issue_nodisplay' => t('Do not display this field') + ), + ), + ), + ), + ); + // Add data from the users module + $tables['users'] = array( + 'name' => 'users', + 'join' => array( + 'type' => 'inner', + 'left' => array( + 'table' => 'project_issues', + 'field' => 'assigned' + ), + 'right' => array( + 'field' => 'uid' + ), + ), + 'fields' => array( + // TODO: handlers + 'name' => array( + 'name' => t('Project Issue: Assigned'), + 'help' => t('The user a given issue is assigned to.'), + 'sortable' => true, + 'addlfields' => array('uid', 'name'), + 'handler' => 'views_handler_field_project_issue_assigned', + ), + ), + ); + + return $tables; +} + +/** + * Implementation of hook_views_arguments + */ +function _project_issue_views_arguments() { + $arguments = array( + 'project_issue_project' => array( + 'name' => t('Project issue: Project node'), + 'help' => t('This argument is either a single project short name or one or more project nids separated by + (OR) or , (AND).'), + 'handler' => 'views_handler_argument_project_issue_project', + 'option' => array( + '#type' => 'select', + '#options' => array('equal'), + ), + ), + 'project_issue_status' => array( + 'name' => t('Project issue: status'), + 'help' => t('This argument is one or more project_issue status IDs.'), + 'handler' => 'views_handler_argument_project_issue_status', + 'option' => '', + ), + ); + return $arguments; +} + +/** + * + */ +function views_handler_argument_project_issue_project($op, &$query, $argtype, $arg = '') { + switch($op) { + case 'summary': + $query->add_field("title"); + $fieldinfo['field'] = 'project_issue_project_node.nid'; + return $fieldinfo; + case 'sort': + // do nothing here. + break; + case 'filter': + $args = _views_break_phrase($arg); + if (!empty($args)) { + if ($args[0] == 'and') { + $operator = $argtype['options'] ? '!=' : '='; + foreach ($args[1] as $arg) { + $query->add_where("project_issue_project_node.nid $operator %d", $arg); + } + } + else { + $query->add_where("project_issue_project_node.nid IN (%s)", implode(',', $args[1])); + } + } + elseif (!empty($arg)) { + // Allow $arg to be a project short name instead of a nid. + $query->add_where("project_issue_project_projects.uri = '%s'", $arg); + } + break; + case 'link': + // @todo fix this + return l($query->title, "$arg/$query->nid"); + case 'title': + // @todo get title to work right + $args = _views_break_phrase($query); + if (!empty($args)) { + if ($args[0] == 'and') { + $title = t('multiple projects'); + } + else { + dpm(implode(',', $args[1])); + $titles = array(); + $result = db_query("SELECT title FROM {node} n WHERE n.nid IN ('%s')", implode(',', $args[1])); +// @todo this isn't quite working properly yet + while ($node = db_fetch_object($result)) { + $titles[] = t('%title', array('%title' => $node->title)); + } + $title = implode(', ', $titles); + } + } + elseif (!empty($query)) { + // Allow $arg to be a project short name instead of a nid. + $result = db_query("SELECT title FROM {node} n INNER JOIN {project_projects} pp ON pp.nid = n.nid WHERE pp.uri = '%s'", $query); + while ($node = db_fetch_object($result)) { + $title = t('%project', array('%project' => $node->title)); + } + } + if (empty($title)) { + $title = t('all projects'); + } + return $title; + break; + } +} + +/** + * + */ +function views_handler_argument_project_issue_status($op, &$query, $argtype, $arg = '') { + +} + +/** + * Displays a field indicating the status of an issue. + */ +function views_handler_field_project_issue_status($fieldinfo, $fielddata, $value, $data) { + return project_issue_state($value); +} + +/** + * Displays a field indicating the priority of an issue. + */ +function views_handler_field_project_issue_priority($fieldinfo, $fielddata, $value, $data) { + return project_issue_priority($value); +} + +/** + * Modifies the query for views that include a field for the issue's + * version, and JOIN's against {node} and {project_release_nodes} to + * find the version string of a given release id (rid). + * + * @todo Need to figure out how to make this really work. + */ +function views_query_handler_field_project_issue_version($fielddata, $fieldinfo, &$query) { +/* + $joininfo = array( + 'type' => 'LEFT', + 'left' => array( + 'table' => 'project_issues', + 'field' => 'rid' + ), + 'right' => array( + 'field' => 'nid' + ), + ); + $num = $query->add_table('node', false, 1, $joininfo); + $query->add_field('version', $query->get_table_name('node', $num), $field['tablename'] . '_name'); +*/ +} + + +/** + * Add {project_projects} field 'uri' to the query results. + * + * @todo: get this working as well + */ +/* +function views_query_handler_field_project_issue_project_node($fielddata, $fieldinfo, &$query) { +dpm($fielddata); +dpm($fieldinfo); +dpm($query); + + $joininfo = array( + 'type' => 'inner', + 'left' => array( + 'table' => $fielddata['tablename'], + 'field' => 'nid' + ), + 'right' => array( + 'field' => 'nid' + ), + ); + $num = $query->add_table('project_projects', false, 1, $joininfo); + $query->add_field('uri', $query->get_table_name('project_projects', $num), $fielddata['tablename'] . '_uri'); +dpm($query); +} +*/ + +/** + * Format the assigned field as a username. + * Loosely based on views_handler_field_username, but doesn't return + * "Anonymous" when there is no one assigned. + */ +function views_handler_field_project_issue_assigned($fieldinfo, $fielddata, $value, $data) { + $name = ''; + $obj = new stdClass(); + $uidfield = $fielddata['tablename'] . "_" . $fieldinfo['uid']; + if (is_numeric($data->users_uid) && $data->users_uid != 0) { + // Loading each user seems expensive here, considering we already ahve the data + // but we loose theme_username functionality + //$obj = user_load(array('uid' => $data->$uidfield)); + //$name = theme('username', $obj); + $name = l($data->users_name, 'user/'.$data->users_uid); + } + else { + $name = ''; + } + return $name; +} + +// dpm($fieldinfo); +// dpm($fielddata); +// dpm($value); +// dpm($data); +function views_handler_field_project_issue_version($fieldinfo, $fielddata, $value, $data) { + if (!empty($data->project_issues_rid)) { + $release = node_load(array('nid' => $data->project_issues_rid)); + if (!empty($release)) { + $version = project_release_get_version($release, $project = NULL); + if (!empty($version)) { + return $version; + } + } + } + +} + +/* + * Format a project title to link to the project. + */ +function views_handler_field_project_issue_project_nodelink($fieldinfo, $fielddata, $value, $data) { + if ($fielddata['options'] == 'nolink') { + return check_plain($value); + } + return l($value, "node/$data->project_issue_project_node_nid"); +} + +/* + * Format a project title as a link to the project node with a 'mark' stating whether or not the project has + * updated since it was last viewed by the user. + */ +function views_handler_field_project_issue_project_nodelink_with_mark($fieldinfo, $fielddata, $value, $data) { + if ($fielddata['options'] == 'nolink') { + $link = check_plain($value); + } + else { + $link = l($value, "node/$data->project_issue_project_node_nid"); + } + return $link .' '. theme('mark', node_mark($data->project_issue_project_node_nid, $data->project_issue_project_node_changed)); +} + +/** + * Format a date as "X time". + */ +function views_handler_field_project_issue_since($fieldinfo, $fielddata, $value, $data) { + return $data->node_changed ? t('!time', array('!time' => format_interval(time() - $data->node_changed, 2))) : theme('views_nodate'); +} + +/** + * Filter the list of projects by category + */ +function views_handler_filter_project_issue_category() { + return project_issue_category(); +} + +/** + * Filter the list of projects by priority + * HELP: Is project_issue_priority()supposed to be in the form of + * array(1 => 'critical', 'normal', 'minor'); + */ +function views_handler_filter_project_issue_priority() { + //$priorities = project_issue_priority(); + $priorities = array(1 => 'critical', 2 => 'normal', 3 => 'minor'); + return $priorities; +} + + +/** + * Filter the list of status options to filter by status + */ +function views_handler_filter_project_issue_status() { + $defaults = project_issue_state(0, false, false, 0, true); + return array('defaults' => implode(',', $defaults)) + project_issue_state(); +} + +/** + * Handle special case for status filter + * + * Assumes filter value is an array and looks for special 'defaults' value in + * array. If present, it adds default sids to the list of filter values. + */ +function views_handler_filter_project_issue_status_filter($op, $filter, $filterinfo, &$query) { + $include = array(); + foreach ($filter['value'] as $val) { + if ($val == 'defaults') { + foreach (project_issue_default_states() as $default) { + $include[] = $default; + } + } else { + $include[] = $val; + } + } + $filter['value'] = array_unique($include); + return views_handler_filter_default($op, $filter, $filterinfo, $query); +} + +/** + * Filter the list of projects to filter by project + */ +function views_handler_filter_project_issue_project() { + $project_urls = array(); + $projects = project_projects_select_options($project_urls); + return $projects; +} + +function theme_views_view_table_project_issue($view, $nodes) { + $fields = _views_get_fields(); + foreach ($nodes as $node) { + $class = "state-$node->project_issues_sid"; + $row_data = array(); + foreach ($view->field as $field) { + if ($fields[$field['id']]['visible'] !== FALSE) { + $cell['data'] = views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $node, $view); + $cell['class'] = "view-field ". views_css_safe('view-field-'. $field['queryname']); + $row_data[] = $cell; + } + } + $row_data = array('data' => $row_data, 'class' => $class); + $rows[] = $row_data; + } + $output = '
'; + $output .= theme('table', $view->table_header, $rows); + $output .= '
'; + return $output; +} + +/** + * Implementation of hook_views_pre_view + */ +function project_issue_views_pre_view(&$view) { + // Remove any fields with option set to "project_issue_nodisplay" + // from the view so they aren't displayed. + foreach ($view->field as $index => $field) { + if ($field['options'] == 'project_issue_nodisplay') { + unset($view->field[$index]); + unset($view->table_header[$index]); + } + } +} + +/** + * Implementations of hook_views_default_views + */ +function _project_issue_views_default_views() { + $view = new stdClass(); + $view->name = 'project_issues2'; + $view->description = ''; + $view->access = array ( +); + $view->view_args_php = ''; + $view->page = TRUE; + $view->page_title = 'Issues for all projects'; + $view->page_header = ''; + $view->page_header_format = '1'; + $view->page_footer = ''; + $view->page_footer_format = '1'; + $view->page_empty = 'There are currently no issues to display for the criteria selected.'; + $view->page_empty_format = '1'; + $view->page_type = 'table'; + $view->url = 'project_issues'; + $view->use_pager = TRUE; + $view->nodes_per_page = '50'; + $view->menu = TRUE; + $view->menu_title = 'Project Issues'; + $view->menu_tab = FALSE; + $view->menu_tab_weight = '0'; + $view->menu_tab_default = FALSE; + $view->menu_tab_default_parent = NULL; + $view->menu_tab_default_parent_type = 'tab'; + $view->menu_parent_tab_weight = '0'; + $view->menu_parent_title = ''; + $view->sort = array ( + ); + $view->argument = array ( + array ( + 'type' => 'project_issue_project', + 'argdefault' => '2', + 'title' => '', + 'options' => '0', + 'wildcard' => '', + 'wildcard_substitution' => '', + ), + ); + $view->field = array ( + array ( + 'tablename' => 'project_issue_project_node', + 'field' => 'title', + 'label' => 'Project', + 'handler' => 'views_handler_field_project_issue_project_nodelink_with_mark', + 'sortable' => '1', + 'options' => 'link', + ), + array ( + 'tablename' => 'node', + 'field' => 'title', + 'label' => 'Summary', + ), + array ( + 'tablename' => 'project_issues', + 'field' => 'sid', + 'label' => 'Status', + 'sortable' => '1', + ), + array ( + 'tablename' => 'project_issues', + 'field' => 'priority', + 'label' => 'Priority', + 'sortable' => '1', + ), + array ( + 'tablename' => 'project_issues', + 'field' => 'category', + 'label' => 'Category', + 'sortable' => '1', + ), + array ( + 'tablename' => 'project_issues', + 'field' => 'rid', + 'label' => 'Version', + 'sortable' => '1', + ), + array ( + 'tablename' => 'node', + 'field' => 'changed', + 'label' => 'Last updated', + 'sortable' => '1', + ), + array ( + 'tablename' => 'users', + 'field' => 'name', + 'label' => 'Assigned to', + 'sortable' => '1', + ), + array ( + 'tablename' => 'project_issue_project_projects', + 'field' => 'uri', + 'label' => 'Short name', + 'options' => 'project_issue_nodisplay', + ), + ); + $view->filter = array ( + array ( + 'tablename' => 'project_issue_project_node', + 'field' => 'nid', + 'operator' => '=', + 'options' => '', + 'value' => '201', + ), + array ( + 'tablename' => 'project_issues', + 'field' => 'sid', + 'operator' => '=', + 'options' => '', + 'value' => '1', + ), + array ( + 'tablename' => 'project_issues', + 'field' => 'category', + 'operator' => '=', + 'options' => '', + 'value' => 'bug', + ), + array ( + 'tablename' => 'project_issues', + 'field' => 'priority', + 'operator' => '=', + 'options' => '', + 'value' => '1', + ), + ); + $view->exposed_filter = array ( + array ( + 'tablename' => 'project_issue_project_node', + 'field' => 'nid', + 'label' => 'Project', + 'optional' => '1', + 'is_default' => '0', + 'operator' => '1', + 'single' => '1', + ), + array ( + 'tablename' => 'project_issues', + 'field' => 'sid', + 'label' => 'Status', + 'optional' => '1', + 'is_default' => '0', + 'operator' => '1', + 'single' => '1', + ), + array ( + 'tablename' => 'project_issues', + 'field' => 'category', + 'label' => 'Category', + 'optional' => '1', + 'is_default' => '0', + 'operator' => '1', + 'single' => '1', + ), + array ( + 'tablename' => 'project_issues', + 'field' => 'priority', + 'label' => 'Priority', + 'optional' => '1', + 'is_default' => '0', + 'operator' => '1', + 'single' => '1', + ), + ); + $view->requires = array(project_issue_project_node, node, project_issues, users, project_issue_project_projects); + $views[$view->name] = $view; + return $views; +}