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 = '