Skip to content

Instantly share code, notes, and snippets.

@EclipseGc
Created August 13, 2013 16:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save EclipseGc/6223191 to your computer and use it in GitHub Desktop.
Save EclipseGc/6223191 to your computer and use it in GitHub Desktop.
diff --git a/css/rocketship.main.css b/css/rocketship.main.css
new file mode 100644
index 0000000..fff986f
--- /dev/null
+++ b/css/rocketship.main.css
@@ -0,0 +1,12 @@
+.node-rocketship-issue .field-type-taxonomy-term-reference {
+ display: inline-block;
+ margin: 0;
+}
+
+.node-rocketship-issue .field-type-taxonomy-term-reference ul {
+ display: inline;
+}
+
+.node-rocketship-issue .field-type-taxonomy-term-reference ul li {
+ float: left;
+}
\ No newline at end of file
diff --git a/plugins/content_types/rocketship_legend.inc b/plugins/content_types/rocketship_legend.inc
new file mode 100644
index 0000000..f19ddbc
--- /dev/null
+++ b/plugins/content_types/rocketship_legend.inc
@@ -0,0 +1,48 @@
+<?php
+/**
+ * @file
+ * Ctools content type that displays a legend for the Rocketship issue overview.
+ */
+
+$plugin = array(
+ 'single' => TRUE,
+ 'title' => t('Rocketship Legend'),
+ 'description' => t('Shows a legend for the Rocketship issue colors.'),
+ 'category' => t('Miscellaneous'),
+ 'edit form' => 'rocketship_legend_form',
+ 'render callback' => 'rocketship_legend_render',
+ 'admin info' => 'rocketship_legend_admin_info',
+);
+
+/**
+ * Info callback for the Rocketship legend panel.
+ */
+function rocketship_legend_admin_info($subtype, $conf, $contexts) {
+ if (!empty($conf)) {
+ $block = new stdClass;
+ $block->title = $conf['override_title'] ? $conf['override_title_text'] : '';
+ $block->content = t('Showing a link to the drupal issue queue.');
+ return $block;
+ }
+}
+
+/**
+ * Configuration form for the Rocketship legend panel.
+ */
+function rocketship_legend_form($form, &$form_state) {
+ return $form;
+}
+
+/**
+ * Renders the Rocketship legend panel.
+ */
+function rocketship_legend_render($subtype, $conf, $panel_args, $context = NULL) {
+ $block = new stdClass();
+
+ $block->title = $conf['override_title'] ? $conf['override_title_text'] : t('Legend');
+ $block->content = '<div class="rocketship-critical rocketship-node">' . t('Critical issue') . '</div>';
+ $block->content .= '<div class="rocketship-major rocketship-node">' . t('Major issue') . '</div>';
+ $block->content .= '<div class="rocketship-focus rocketship-node">' . t('Current top priority') . '</div>';
+
+ return $block;
+}
\ No newline at end of file
diff --git a/plugins/content_types/rocketship_link.inc b/plugins/content_types/rocketship_link.inc
new file mode 100644
index 0000000..70d9fe9
--- /dev/null
+++ b/plugins/content_types/rocketship_link.inc
@@ -0,0 +1,66 @@
+<?php
+/**
+ * @file
+ * Ctools content type that displays a link to the issues shown on the
+ * Rocketship issue overview.
+ */
+
+$plugin = array(
+ 'single' => TRUE,
+ 'title' => t('Rocketship Link'),
+ 'description' => t('Shows a link for certain tags to the drupal.org issue queue.'),
+ 'category' => t('Miscellaneous'),
+ 'edit form' => 'rocketship_link_form',
+ 'render callback' => 'rocketship_link_render',
+ 'admin info' => 'rocketship_link_admin_info',
+ 'required context' => array(
+ new ctools_context_optional(t('Term'), 'entity:taxonomy_term'),
+ new ctools_context_required(t('Project'), 'string'),
+ ),
+);
+
+/**
+ * Info callback for the Rocketship link panel.
+ */
+function rocketship_link_admin_info($subtype, $conf, $contexts) {
+ if (!empty($conf)) {
+ $block = new stdClass;
+ $block->title = $conf['override_title'] ? $conf['override_title_text'] : '';
+ $block->content = t('Showing a link to the drupal issue queue.');
+ return $block;
+ }
+}
+
+/**
+ * Configuration form for the Rocketship link panel.
+ */
+function rocketship_link_form($form, &$form_state) {
+ return $form;
+}
+
+/**
+ * Renders the Rocketship link panel.
+ */
+function rocketship_link_render($subtype, $conf, $panel_args, $context = NULL) {
+ $tags = array();
+ if (!empty($context)) {
+ list($term, $string) = $context;
+ if (empty($string->data)) {
+ return;
+ }
+ if (!empty($term->data) && is_object($term->data)) {
+ $tags[$term->data->tid] = $term->data->name;
+ }
+ }
+ $path = rocketship_get_issue_path($tags, $string->data);
+
+ $block = new stdClass();
+
+ $block->title = $conf['override_title'] ? $conf['override_title_text'] : '';
+
+ $block->content = t('See all these issues also at !link. This view of issues is automatically cached and might be out of date up to two hours at times.', array(
+ '!link' => l(url($path['path'], $path), $path['path'], $path),
+ ));
+
+ return $block;
+}
diff --git a/plugins/content_types/rocketship_thanks.inc b/plugins/content_types/rocketship_thanks.inc
new file mode 100644
index 0000000..a6af432
--- /dev/null
+++ b/plugins/content_types/rocketship_thanks.inc
@@ -0,0 +1,110 @@
+<?php
+/**
+ * @file
+ * Ctools content type that displays a tag cloud of users participated in issues
+ * shown on the Rocketship issue overview.
+ */
+
+$plugin = array(
+ 'single' => TRUE,
+ 'title' => t('Rocketship Thanks'),
+ 'description' => t('Shows a tag cloud of the contributors.'),
+ 'category' => t('Miscellaneous'),
+ 'edit form' => 'rocketship_thanks_form',
+ 'render callback' => 'rocketship_thanks_render',
+ 'admin info' => 'rocketship_thanks_admin_info',
+ 'required context' => array(
+ new ctools_context_required(t('Term'), 'entity:taxonomy_term'),
+ new ctools_context_required(t('Project'), 'string'),
+ ),
+);
+
+/**
+ * Info callback for the Rocketship legend panel.
+ */
+function rocketship_thanks_admin_info($subtype, $conf, $contexts) {
+ if (!empty($conf)) {
+ $block = new stdClass;
+ $block->title = $conf['override_title'] ? $conf['override_title_text'] : '';
+ $block->content = t('Tag cloud of the contributors.');
+ return $block;
+ }
+}
+
+/**
+ * Configuration form for the Rocketship legend panel.
+ */
+function rocketship_thanks_form($form, &$form_state) {
+ $form['exclusions'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Users to Exclude'),
+ '#description' => t('Comma separated list of users to exclude. This is useful for excluding contributors to your project/tag that are not in need of thanking. This may include yourself, co-maintainers or other such individuals.'),
+ '#default_value' => $form_state['conf']['exclusions'],
+ );
+ return $form;
+}
+
+function rocketship_thanks_form_submit($form, &$form_state) {
+ $form_state['conf']['exclusions'] = $form_state['values']['exclusions'];
+}
+
+/**
+ * Renders the Rocketship legend panel.
+ */
+function rocketship_thanks_render($subtype, $conf, $panel_args, $context = NULL) {
+ list ($term, $project) = $context;
+ if (empty($term->data) || !is_object($term->data) ||empty($project->data)) {
+ return;
+ }
+ $block = new stdClass();
+
+ $block->title = $conf['override_title'] ? $conf['override_title_text'] : t('Thanks to');
+
+
+ // Include username cloud if the sprint tag is displayed.
+ $participant_stats = variable_get('rocketship_participant_stats', array());
+ if (!empty($participant_stats[$project->data][$term->data->name])) {
+ $lead_users = explode(',', $conf['exclusions']);
+ $participant_uids = variable_get('rocketship_participant_uids', array());
+ $participant_recent = variable_get('rocketship_participant_recent', array());
+
+ // Remove lead user and some users to avoid skewing the stats.
+ if (!empty($lead_users) && is_array($lead_users)) {
+ foreach ($lead_users as $lead_user) {
+ unset($participant_stats[$project->data][$term->data->name][trim($lead_user)]);
+ }
+ }
+
+ unset($participant_stats[$project->data][$term->data->name]['System Message']);
+ unset($participant_stats[$project->data][$term->data->name]['Abandoned Projects']);
+
+ $usercloud = array();
+ $max = max(array_values($participant_stats[$project->data][$term->data->name]));
+ $steps = array(1, 2, 3, 5, 7, 10);
+ foreach ($steps as $i => $step) {
+ foreach ($participant_stats[$project->data][$term->data->name] as $name => $count) {
+ if (($step == 10) || ($count <= $step * ($max/10))) {
+ $class = 'rocketship-cloud-' . ($i+1);
+ if (in_array($participant_uids[$project->data][$term->data->name][$name], $participant_recent[$project->data][$term->data->name])) {
+ $class .= ' rocketship-cloud-recent';
+ }
+ $usercloud[$name] = '<span class="' . $class . '"><a href="http://drupal.org/user/' . $participant_uids[$project->data][$term->data->name][$name] . '">' . check_plain($name) . '</a></span>';
+ unset($participant_stats[$project->data][$term->data->name][$name]);
+ }
+ }
+ }
+
+ // Sort by username in a case insensitive fashion.
+ uksort($usercloud, "strnatcasecmp");
+ $notes = array();
+ $notes[] = t('Based on participation in all @tag issues (font size) using a quasi-logarithmic scale and on recent activity (boldness).', array('@tag' => $term->data->name));
+ if (!empty($lead_users)) {
+ $notes[] = format_plural(count($lead_users), 'Excludes the initiative lead, @lead.', 'Excludes the initiative leads, @lead.', array('@lead' => implode(', ', $lead_users)));
+ }
+
+ $block->content = '<div class="rocketship-cloud">' . join(' ', $usercloud) . '</div>';
+ $block->content .= '<div class="rocketship-note">' . join(' ', $notes) . '</div>';
+ }
+
+ return $block;
+}
\ No newline at end of file
diff --git a/plugins/export_ui/rocketship_settings.inc b/plugins/export_ui/rocketship_settings.inc
new file mode 100644
index 0000000..2be809b
--- /dev/null
+++ b/plugins/export_ui/rocketship_settings.inc
@@ -0,0 +1,52 @@
+<?php
+
+$plugin = array(
+ 'schema' => 'rocketship_settings',
+ 'access' => 'access administration pages',
+ 'menu' => array(
+ 'menu prefix' => 'admin/rocketship',
+ 'menu item' => 'settings',
+ 'menu title' => 'Settings',
+ 'menu description' => 'Administer Rocketship settings groups.',
+ ),
+ 'title singular' => t('settings group'),
+ 'title singular proper' => t('Settings Group'),
+ 'title plural' => t('settings groups'),
+ 'title plural proper' => t('Settings Groups'),
+ 'form' => array(
+ 'settings' => 'rocketship_settings_export_ui_form',
+// 'validate' => 'rocketship_settings_export_ui_form_validate',
+// 'submit' => 'rocketship_settings_export_ui_form_submit',
+ ),
+);
+
+function rocketship_settings_export_ui_form(&$form, &$form_state) {
+ $form['tag'] = array(
+ '#type' => 'textfield',
+ '#required' => TRUE,
+ '#title' => t('Issue Tag'),
+ '#description' => t('The taxonomy issue tag.'),
+ '#default_value' => !empty($form_state['item']->tag) ? $form_state['item']->tag : '',
+ );
+ $form['project'] = array(
+ '#type' => 'textfield',
+ '#required' => TRUE,
+ '#title' => t('Drupal.org Project'),
+ '#description' => t('The drupal.org project for the issues.'),
+ '#default_value' => !empty($form_state['item']->project) ? $form_state['item']->project : 'drupal',
+ );
+ $form['path'] = array(
+ '#type' => 'textfield',
+ '#required' => TRUE,
+ '#title' => t('Path'),
+ '#description' => t('The path at which to display an overview of issues related to this settings group.'),
+ '#default_value' => !empty($form_state['item']->path) ? $form_state['item']->path : '',
+ );
+ $form['exclusions'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Users to Exclude'),
+ '#description' => t('Comma separated list of users to exclude. This is useful for excluding contributors to your project/tag that are not in need of thanking. This may include yourself, co-maintainers or other such individuals.'),
+ '#default_value' => !empty($form_state['item']->exclusions) ? $form_state['item']->exclusions : '',
+ );
+}
+
diff --git a/plugins/layouts/rocketship/rocketship.css b/plugins/layouts/rocketship/rocketship.css
new file mode 100644
index 0000000..426117b
--- /dev/null
+++ b/plugins/layouts/rocketship/rocketship.css
@@ -0,0 +1,143 @@
+.rocketship .panel-col-top,
+.rocketship .panel-col-middle,
+.rocketship .panel-col-bottom,
+.rocketship .panel-separator {
+ width: 100%;
+ clear: both;
+}
+
+.rocketship .panel-col-top .inside,
+.rocketship .panel-col-middle .inside {
+ margin-bottom: 1em;
+}
+
+.rocketship .panel-col-first {
+ float: left;
+ width: 33%;
+}
+
+.rocketship .panel-col-first .inside {
+ margin: 0 .5em 1em 0;
+}
+
+.rocketship .panel-col {
+ float: left;
+ width: 33%;
+}
+
+.rocketship .panel-col .inside {
+ margin: 0 .5em 1em .5em;
+}
+
+.rocketship .panel-col-last {
+ float: left;
+ width: 33%;
+}
+
+.rocketship .panel-col-last .inside {
+ margin: 0 0 1em .5em;
+}
+
+.rocketship .panel-separator {
+ margin: 0 0 1em 0;
+}
+
+.view-id-issues .views-row {
+ margin-bottom: 1em;
+}
+
+.rocketship-node,
+.panel-pane .view-id-issues .node-rocketship-issue {
+ padding: 0.2em 0.3em 0.2em 0.5em;
+ -moz-box-shadow: 0 0 0.5em rgba(0,0,0,0.4);
+ -webkit-box-shadow: 0 0 0.5em rgba(0,0,0,0.4);
+ border: none;
+ border-left: 0.7em solid #F5F5F5;
+}
+
+.panel-pane .view-id-issues .node-rocketship-issue h2 a {
+ font-weight: bold;
+ font-size: 0.8em;
+}
+
+.rocketship-focus,
+.panel-pane .view-id-issues .node-rocketship-issue-focus {
+ border-left-color: #336699;
+}
+
+.rocketship-major,
+.panel-pane .view-id-issues .node-rocketship-issue-major {
+ border-left-color: #FF9900;
+}
+
+.rocketship-critical,
+.panel-pane .view-id-issues .node-rocketship-issue-critical {
+ border-left-color: #FF0000;
+}
+
+.rocketship-needs-tests,
+.panel-pane .view-id-issues .node-rocketship-issue-needs-tests {
+ font-weight: bold;
+}
+
+.view-id-issues .node-rocketship-issue .field-type-taxonomy-term-reference li {
+ background-color: #F5F5F5;
+ margin: 0.1em 0.3em 0.1em 0;
+ padding: 0.1em 0.3em;
+ display: inline-block;
+ border-radius: 0.2em;
+}
+
+.pane-rocketship-legend {
+ float: right;
+ clear: both;
+}
+.pane-rocketship-legend .pane-title,
+.pane-rocketship-legend .pane-content,
+.pane-rocketship-legend .rocketship-node {
+ display: inline-block;
+ margin-left: 6px;
+}
+.panel-pane .view-id-issues .node-rocketship-issue .field-name-rocketship-assignee {
+ background-color: #F5F5F5;
+ margin: -0.2em -0.3em -0.3em -0.5em;
+ padding: 0.1em 1em;
+ border: none;
+ border-top: 0.1em dotted #DDDDDD;
+ font-size: 0.9em;
+}
+.rocketship-cloud-wrapper {
+ border-top: 0.1em solid #3b3b3b;
+ margin-bottom: 2em;
+ clear: both;
+}
+.rocketship-cloud-wrapper p {
+ font-size: 0.8em;
+ margin-top: 1.3em;
+ font-style: italic;
+}
+.rocketship-cloud {
+ line-height: 1.3em;
+ text-align: justify;
+}
+.rocketship-cloud-1 {
+ font-size: 0.8em;
+}
+.rocketship-cloud-2 {
+ font-size: 1em;
+}
+.rocketship-cloud-3 {
+ font-size: 1.4em;
+}
+.rocketship-cloud-4 {
+ font-size: 1.6em;
+}
+.rocketship-cloud-5 {
+ font-size: 1.8em;
+}
+.rocketship-cloud-6 {
+ font-size: 2em;
+}
+.rocketship-cloud-recent a {
+ font-weight: bold;
+}
diff --git a/plugins/layouts/rocketship/rocketship.inc b/plugins/layouts/rocketship/rocketship.inc
new file mode 100644
index 0000000..412c329
--- /dev/null
+++ b/plugins/layouts/rocketship/rocketship.inc
@@ -0,0 +1,25 @@
+<?php
+/**
+ * @file
+ * Ctools layout for the Rocketship issue overview.
+ */
+
+// Plugin definition
+$plugin = array(
+ 'title' => t('Rocketship'),
+ 'category' => t('Columns: 3'),
+ 'icon' => 'rocketship.png',
+ 'theme' => 'rocketship',
+ 'css' => 'rocketship.css',
+ 'regions' => array(
+ 'top' => t('Top'),
+ 'upper_first' => t('Upper First'),
+ 'upper_middle' => t('Upper Middle'),
+ 'upper_last' => t('Upper Last'),
+ 'middle' => t('Middle'),
+ 'lower_first' => t('Lower First'),
+ 'lower_middle' => t('Lower Middle'),
+ 'lower_last' => t('Lower Last'),
+ 'bottom' => t('Bottom')
+ ),
+);
diff --git a/plugins/layouts/rocketship/rocketship.tpl.php b/plugins/layouts/rocketship/rocketship.tpl.php
new file mode 100644
index 0000000..18b6fc2
--- /dev/null
+++ b/plugins/layouts/rocketship/rocketship.tpl.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * @file
+ * Rocketship issue overview template.
+ *
+ * This template provides a two times three column panel display layout, with
+ * additional areas for the top, middle and the bottom.
+ *
+ * Variables:
+ * - $id: An optional CSS id to use for the layout.
+ * - $content: An array of content, each item in the array is keyed to one
+ * panel of the layout. This layout supports the following sections:
+ * - $content['top']: Content in the top row.
+ * - $content['upper_first']: Content in the upper first column.
+ * - $content['upper_middle']: Content in the upper middle column.
+ * - $content['upper_last']: Content in the upper last column.
+ * - $content['middle']: Content in the middle row.
+ * - $content['lower_first']: Content in the lower first column.
+ * - $content['lower_middle']: Content in the lower middle column.
+ * - $content['lower_last']: Content in the lower last column.
+ * - $content['bottom']: Content in the bottom row.
+ */
+?>
+<div class="panel-display rocketship clearfix" <?php if (!empty($css_id)) { print "id=\"$css_id\""; } ?>>
+ <div class="panel-panel panel-col-top">
+ <div class="inside"><?php print $content['top']; ?></div>
+ </div>
+
+ <div class="center-wrapper">
+ <div class="panel-panel panel-col-first panel-col-upper">
+ <div class="inside"><?php print $content['upper_first']; ?></div>
+ </div>
+
+ <div class="panel-panel panel-col panel-col-upper">
+ <div class="inside"><?php print $content['upper_middle']; ?></div>
+ </div>
+
+ <div class="panel-panel panel-col-last panel-col-upper">
+ <div class="inside"><?php print $content['upper_last']; ?></div>
+ </div>
+ </div>
+
+ <div class="panel-panel panel-col-middle">
+ <div class="inside"><?php print $content['middle']; ?></div>
+ </div>
+
+ <div class="center-wrapper">
+ <div class="panel-panel panel-col-first panel-col-lower">
+ <div class="inside"><?php print $content['lower_first']; ?></div>
+ </div>
+
+ <div class="panel-panel panel-col panel-col-lower">
+ <div class="inside"><?php print $content['lower_middle']; ?></div>
+ </div>
+
+ <div class="panel-panel panel-col-last panel-col-lower">
+ <div class="inside"><?php print $content['lower_last']; ?></div>
+ </div>
+ </div>
+
+ <div class="panel-panel panel-col-bottom">
+ <div class="inside"><?php print $content['bottom']; ?></div>
+ </div>
+</div>
diff --git a/rocketship.info b/rocketship.info
index d8933d5..86af454 100644
--- a/rocketship.info
+++ b/rocketship.info
@@ -1,3 +1,24 @@
name = Rocketship
description = Issue augmentation for Drupal initiatives
-core = 7.x
\ No newline at end of file
+core = 7.x
+
+dependencies[] = ctools
+dependencies[] = page_manager
+dependencies[] = panels
+dependencies[] = taxonomy
+dependencies[] = views
+dependencies[] = views_content
+
+
+; Information added by drush on 2013-06-04
+version = "master-dev"
+project = "rocketship"
+datestamp = "1370350776"
+
+
+
+; Information added by drush on 2013-06-06
+version = "master-dev"
+project = "rocketship"
+datestamp = "1370508849"
+
diff --git a/rocketship.install b/rocketship.install
new file mode 100644
index 0000000..2966b50
--- /dev/null
+++ b/rocketship.install
@@ -0,0 +1,287 @@
+<?php
+/**
+ * @file
+ * (Un)Install and updated hooks for Rocketship.
+ */
+
+/**
+ * Implements hook_schema().
+ */
+function rocketship_schema() {
+ $schema['rocketship_settings'] = array(
+ 'description' => 'The base table for nodes.',
+ 'export' => array(
+ 'key' => 'machine_name',
+ 'key name' => 'Machine Name',
+ 'primary key' => 'rsid',
+ 'identifier' => 'settings', // Exports will be as $group
+ 'default hook' => 'rocketship_settings_group_default', // Function hook name.
+ 'api' => array(
+ 'owner' => 'rocketship',
+ 'api' => 'rocketship_settings', // Base name for api include files.
+ 'minimum_version' => 1,
+ 'current_version' => 1,
+ ),
+ 'save callback' => 'rocketship_settings_save',
+ ),
+ 'fields' => array(
+ 'rsid' => array(
+ 'description' => 'The primary identifier for a node.',
+ 'type' => 'serial',
+ 'unsigned' => TRUE,
+ 'not null' => TRUE,
+ 'no export' => TRUE,
+ ),
+ 'machine_name' => array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'The machine name.',
+ ),
+ 'tag' => array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'The tag name.',
+ ),
+ 'project' => array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'The project name.',
+ ),
+ 'path' => array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'The overview path name.',
+ ),
+ 'exclusions' => array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'A comma separated list of users to exclude from thanks on this settings group.',
+ ),
+ ),
+ 'primary key' => array('rsid'),
+ 'foreign keys' => array(
+ 'taxonomy' => array(
+ 'table' => 'taxonomy_term_data',
+ 'columns' => array('tag' => 'name'),
+ ),
+ ),
+ 'indexes' => array(
+ 'tag' => array('tag'),
+ ),
+ );
+ return $schema;
+}
+
+/**
+ * Implements hook_install().
+ */
+function rocketship_install() {
+ variable_set('node_options_rocketship_issue', array('status'));
+ variable_set('node_submitted_rocketship_issue', 0);
+ variable_set('page_manager_node_view_disabled', "FALSE");
+
+ module_load_include('module', 'taxonomy', 'taxonomy');
+ $vocabularies = array(
+ 'rocketship_issue_tags' => t('Issue tags'),
+ 'rocketship_version_tags' => t('Version tags'),
+ 'rocketship_category_tags' => t('Category tags'),
+ 'rocketship_status_tags' => t('Status tags'),
+ 'rocketship_priority_tags' => t('Priority tags'),
+ 'rocketship_component_tags' => t('Component tags'),
+ );
+ $vocabulary_tags = array(
+ 'rocketship_version_tags' => array(
+ '6.x-dev', '7.x-dev',
+ ),
+ 'rocketship_status_tags' => array('patch (to be ported)', 'fixed', 'closed (duplicate)',
+ 'closed (won\'t fix)', 'closed (works as designed)',
+ 'closed (cannot reproduce)', 'closed (fixed)', 'postponed',
+ 'postponed (maintainer needs more info)', 'active', 'needs work',
+ 'reviewed & tested by the community', 'needs review',
+ ),
+ );
+ foreach ($vocabularies as $machine_name => $label) {
+ $vocabulary = taxonomy_vocabulary_machine_name_load($machine_name);
+ if (!$vocabulary) {
+ $vocabulary = (object)array(
+ 'name' => $label,
+ 'machine_name' => $machine_name,
+ 'description' => '',
+ 'hierarchy' => 0,
+ );
+ taxonomy_vocabulary_save($vocabulary);
+ }
+ variable_set($machine_name . '_vid', $vocabulary->vid);
+ if (isset($vocabulary_tags[$machine_name])) {
+ foreach ($vocabulary_tags[$machine_name] as $tag) {
+ if (!taxonomy_get_term_by_name($tag)) {
+ taxonomy_term_save((object) array(
+ 'vid' => $vocabulary->vid,
+ 'name' => $tag,
+ ));
+ }
+ }
+ }
+ }
+
+ if (!field_info_field('rocketship_assignee')) {
+ field_create_field(array(
+ 'field_name' => 'rocketship_assignee',
+ 'type' => 'text',
+ ));
+ }
+
+ if (!field_info_field('rocketship_project')) {
+ field_create_field(array(
+ 'field_name' => 'rocketship_project',
+ 'type' => 'text',
+ ));
+ }
+
+ if (!field_info_field('rocketship_priority')) {
+ field_create_field(array(
+ 'field_name' => 'rocketship_priority',
+ 'type' => 'number_integer',
+ ));
+ }
+
+ foreach ($vocabularies as $machine_name => $label) {
+ if (!field_info_field($machine_name)) {
+ field_create_field(array(
+ 'field_name' => $machine_name,
+ 'type' => 'taxonomy_term_reference',
+ 'settings' => array(
+ 'allowed_values' => array(
+ array('vocabulary' => $machine_name, 'parent' => NULL),
+ ),
+ ),
+ 'cardinality' => -1,
+ ));
+ }
+
+ if (!field_info_instance('node', $machine_name, 'rocketship_issue')) {
+ field_create_instance(array(
+ 'label' => $label,
+ 'field_name' => $machine_name,
+ 'entity_type' => 'node',
+ 'bundle' => 'rocketship_issue',
+ 'widget' => array('type' => 'taxonomy_autocomplete'),
+ 'display' => array(
+ 'default' => array(
+ 'label' => 'hidden',
+ 'type' => 'taxonomy_term_reference_plain',
+ 'weight' => 0,
+ ),
+ 'teaser' => array(
+ 'label' => 'hidden',
+ 'type' => 'taxonomy_term_reference_plain',
+ 'weight' => 0,
+ ),
+ ),
+ ));
+ }
+ }
+
+ if (!field_info_instance('node', 'rocketship_assignee', 'rocketship_issue')) {
+ field_create_instance(array(
+ 'label' => 'Assigned to',
+ 'field_name' => 'rocketship_assignee',
+ 'entity_type' => 'node',
+ 'bundle' => 'rocketship_issue',
+ 'widget' => array('type' => 'text_textfield'),
+ 'display' => array(
+ 'default' => array(
+ 'label' => 'inline',
+ 'type' => 'text_default',
+ 'weight' => 1,
+ ),
+ 'teaser' => array(
+ 'label' => 'inline',
+ 'type' => 'text_default',
+ 'weight' => 1,
+ ),
+ ),
+ ));
+ }
+
+ if (!field_info_instance('node', 'rocketship_project', 'rocketship_issue')) {
+ field_create_instance(array(
+ 'label' => 'Project',
+ 'field_name' => 'rocketship_project',
+ 'entity_type' => 'node',
+ 'bundle' => 'rocketship_issue',
+ 'widget' => array('type' => 'text_textfield'),
+ 'display' => array(
+ 'default' => array(
+ 'label' => 'inline',
+ 'type' => 'text_default',
+ 'weight' => 1,
+ ),
+ 'teaser' => array(
+ 'label' => 'inline',
+ 'type' => 'text_default',
+ 'weight' => 1,
+ ),
+ ),
+ ));
+ }
+
+ if (!field_info_instance('node', 'rocketship_priority', 'rocketship_issue')) {
+ field_create_instance(array(
+ 'label' => 'Priority',
+ 'field_name' => 'rocketship_priority',
+ 'entity_type' => 'node',
+ 'bundle' => 'rocketship_issue',
+ 'widget' => array(
+ 'type' => 'number',
+ ),
+ 'display' => array(
+ 'default' => array('type' => 'hidden'),
+ 'teaser' => array('type' => 'hidden'),
+ ),
+ ));
+ }
+
+ if (!field_info_instance('node', 'rocketship_issue_tags', 'rocketship_focus')) {
+ field_create_instance(array(
+ 'label' => 'Issue tags',
+ 'field_name' => 'rocketship_issue_tags',
+ 'entity_type' => 'node',
+ 'bundle' => 'rocketship_focus',
+ 'widget' => array('type' => 'taxonomy_autocomplete'),
+ ));
+ }
+}
+
+/**
+ * Implements hook_uninstall().
+ */
+function rocketship_uninstall() {
+ $vocabularies = array(
+ 'rocketship_issue_tags' => t('Issue tags'),
+ 'rocketship_version_tags' => t('Version tags'),
+ 'rocketship_category_tags' => t('Category tags'),
+ 'rocketship_status_tags' => t('Status tags'),
+ 'rocketship_priority_tags' => t('Priority tags'),
+ 'rocketship_component_tags' => t('Component tags'),
+ );
+ foreach ($vocabularies as $machine_name => $label) {
+ field_delete_field($machine_name);
+ $vocabulary = taxonomy_vocabulary_machine_name_load($machine_name);
+ taxonomy_vocabulary_delete($vocabulary->vid);
+ }
+ field_delete_field('rocketship_assignee');
+ field_delete_field('rocketship_priority');
+
+
+}
\ No newline at end of file
diff --git a/rocketship.module b/rocketship.module
index 54d0c2d..9d1e19d 100644
--- a/rocketship.module
+++ b/rocketship.module
@@ -1,22 +1,10 @@
<?php
-
/**
* @file
* Issue crawler/scraper and display module built for the Drupal 8 Multilingual Initiative.
*/
/**
- * Local node type for storing the cached issues.
- *
- * Assumptions about this node type:
- * - it has a regular title and body
- * - it has a field_assigned single value, one line text field
- * - it has a tags reference field named "field_issue_tags" using tags from rocketship_tags_vid
- */
-define('ROCKETSHIP_NODE_TYPE', 'issue');
-
-
-/**
* Implements hook_menu().
*/
function rocketship_menu() {
@@ -31,6 +19,60 @@ function rocketship_menu() {
}
/**
+ * Implements hook_node_info().
+ */
+function rocketship_node_info() {
+ $items = array(
+ 'rocketship_issue' => array(
+ 'name' => t('Issue'),
+ 'base' => 'node_content',
+ 'description' => '',
+ 'has_title' => '1',
+ 'title_label' => t('Title'),
+ 'help' => '',
+ ),
+ 'rocketship_focus' => array(
+ 'name' => t('Issue Focus'),
+ 'base' => 'node_content',
+ 'description' => '',
+ 'has_title' => '1',
+ 'title_label' => t('Title'),
+ 'help' => '',
+ ),
+ );
+ return $items;
+}
+
+/**
+ * Implements hook_views_api().
+ */
+function rocketship_views_api() {
+ return array(
+ 'api' => 3,
+ 'path' => drupal_get_path('module', 'rocketship'),
+ );
+}
+
+/**
+ * Implementation of hook_ctools_plugin_api().
+ */
+function rocketship_ctools_plugin_api($module, $api) {
+ if ($module == 'page_manager' && $api == 'pages_default') {
+ return array('version' => 1);
+ }
+}
+
+/**
+ * Implementation of hook_ctools_plugin_directory()
+ */
+function rocketship_ctools_plugin_directory($owner, $plugin_type) {
+ $supported = array('content_types', 'layouts', 'export_ui');
+ if (in_array($plugin_type, $supported)) {
+ return 'plugins/' . $plugin_type;
+ }
+}
+
+/**
* Implements hook_cron().
*/
function rocketship_cron() {
@@ -63,39 +105,58 @@ function rocketship_launch_form_submit() {
/**
* Crawler for drupal.org issue listings.
*/
-function rocketship_parse_all() {
- // Grab the first page of the listings of issues for this tag.
- $issue_page = 'http://drupal.org/project/issues/search/drupal?issue_tags=' . urlencode(variable_get('rocketship_master_tag', 'D8MI'));
- $page_output = drupal_http_request($issue_page);
- if ($page_output->code == 200 && !empty($page_output->data)) {
-
- // Figure out the index number of the last issue list page by scraping.
- $last_page_num = 0;
- if (preg_match('!href="([^"]+)" title="Go to last page"!', $page_output->data, $last_page)) {
- if (preg_match('!\?page=(\d+)&!', $last_page[1], $last_page_find)) {
- $last_page_num = $last_page_find[1];
+function rocketship_parse_all($settings = NULL) {
+ if (!$settings) {
+ ctools_include('export');
+ $tag_groups = ctools_export_crud_load_all('rocketship_settings');
+ }
+ else {
+ $tag_groups = array($settings);
+ }
+ foreach ($tag_groups as $settings) {
+ $tags = array($settings->tag);
+ $path = rocketship_get_issue_path($tags, $settings->project);
+ $url = url($path['path'], $path);
+ $page_output = drupal_http_request($url);
+ if ($page_output->code == 200 && !empty($page_output->data)) {
+
+ // Figure out the index number of the last issue list page by scraping.
+ $last_page_num = 0;
+ if (preg_match('!href="([^"]+)" title="Go to last page"!', $page_output->data, $last_page)) {
+ if (preg_match('!\?page=(\d+)&!', $last_page[1], $last_page_find)) {
+ $last_page_num = $last_page_find[1];
+ }
}
- }
- // Parse this page for issue links and grab those issue nodes.
- rocketship_parse_issue_page($page_output->data);
-
- // If we have more pages, go on to the rest of the pages as well.
- if (!empty($last_page_num)) {
- for ($page_num = 1; $page_num <= $last_page_num; $page_num++) {
- $page_output = drupal_http_request($issue_page . '&page='. $page_num);
- if ($page_output->code == 200 && !empty($page_output->data)) {
- rocketship_parse_issue_page($page_output->data);
+ // Parse this page for issue links and grab those issue nodes.
+ rocketship_parse_issue_page($page_output->data);
+
+ // If we have more pages, go on to the rest of the pages as well.
+ if (!empty($last_page_num)) {
+ for ($page_num = 1; $page_num <= $last_page_num; $page_num++) {
+ $path['query']['page'] = $page_num;
+ $url = url($path['path'], $path);
+ $page_output = drupal_http_request($url);
+ if ($page_output->code == 200 && !empty($page_output->data)) {
+ rocketship_parse_issue_page($page_output->data);
+ }
}
}
}
- }
- // Save all username counts.
- list ($user_names, $user_uids, $recent_uids) = rocketship_stat_add_username();
- variable_set('rocketship_participant_stats', $user_names);
- variable_set('rocketship_participant_uids', $user_uids);
- variable_set('rocketship_participant_recent', $recent_uids);
+ // Save all username counts.
+ list ($user_names, $user_uids, $recent_uids) = rocketship_stat_add_username();
+ $stats = variable_get('rocketship_participant_stats', array());
+ $stats[$settings->project][$settings->tag] = $user_names;
+ variable_set('rocketship_participant_stats', $stats);
+ $uids = variable_get('rocketship_participant_uids', array());
+ $uids[$settings->project][$settings->tag] = $user_uids;
+ variable_set('rocketship_participant_uids', $uids);
+ $recent = variable_get('rocketship_participant_recent', array());
+ $recent[$settings->project][$settings->tag] = $recent_uids;
+ variable_set('rocketship_participant_recent', $recent);
+ rocketship_stat_add_username(NULL, NULL, NULL, TRUE);
+ }
// Make note of the data update in watchdog().
watchdog('rocketship', 'Rocketship data updated.');
@@ -104,10 +165,16 @@ function rocketship_parse_all() {
/**
* Simple stat collector to summarize users participating.
*/
-function rocketship_stat_add_username($username = NULL, $uid = NULL, $time = NULL) {
+function rocketship_stat_add_username($username = NULL, $uid = NULL, $time = NULL, $clear = FALSE) {
static $user_names = array();
static $user_uids = array();
static $recent_uids = array();
+ if ($clear) {
+ $user_names = array();
+ $user_uids = array();
+ $recent_uids = array();
+ return;
+ }
if (isset($username)) {
@$user_names[$username]++;
@@ -123,11 +190,10 @@ function rocketship_stat_add_username($username = NULL, $uid = NULL, $time = NUL
/**
* Data scraper for a drupal.org issue listing page.
*
- * @todo
+ * @todo Drop outdated nodes and unused tags.
* Does not drop outdated nodes (if master tag is removed), only updates old
* ones and create new ones. Also does not drop unused tags.
- * @todo
- * Does not consider multi-page issues. Yeah.
+ * @todo Does not consider multi-page issues. Yeah.
*/
function rocketship_parse_issue_page(&$issue_page_content) {
@@ -146,7 +212,9 @@ function rocketship_parse_issue_page(&$issue_page_content) {
// pattern, where 12345 is the issue nid from drupal.org and "title" is
// the issue title from drupal.org. Since all that stays the same for
// a drupal.org is the issue number, we look for that specifically.
- $nid = db_query("SELECT nid FROM {node} WHERE type = :type AND title LIKE '#" . (int) $match . ":%'", array(':type' => ROCKETSHIP_NODE_TYPE))->fetchField();
+ $nid = db_query("SELECT nid FROM {node} WHERE type = 'rocketship_issue' AND title LIKE :title", array(
+ ':title' => '#' . (int) $match . ':%'
+ ))->fetchField();
if ($nid) {
$node = node_load($nid);
}
@@ -155,7 +223,7 @@ function rocketship_parse_issue_page(&$issue_page_content) {
// and other listings of nodes, taxonomy index data is only stored for
// published nodes, so this is what we can do to get easy results
// quickly.
- $node = (object) array('type' => ROCKETSHIP_NODE_TYPE, 'language' => 'und', 'status' => 1);
+ $node = (object) array('type' => 'rocketship_issue', 'language' => 'und', 'status' => 1);
}
// Grab node title based on drupal.org HTML markup.
@@ -168,64 +236,116 @@ function rocketship_parse_issue_page(&$issue_page_content) {
$node->created = strtotime(str_replace(' at ', ', ', $posted_date[1]));
}
- // Find all participats and count their comments.
+ // Find all participants and count their comments.
if (preg_match_all('!<div class="submitted">Posted by <a href="/user/(\d+)"[^>]+>([^<]+)</a> on <em>(.+)</em>!', $issue_node->data, $participants)) {
foreach ($participants[2] as $i => $participant) {
rocketship_stat_add_username($participant, $participants[1][$i], strtotime(str_replace(' at ', ', ', $participants[3][$i])));
}
}
- // Assumes a "field_assigned" text field is present on this node type.
- if (preg_match('!<td>Assigned:</td><td>(.*)</td>!', $issue_node->data, $assigned)) {
- $node->field_assigned['und'][0]['value'] = strip_tags($assigned[1]);
+ if (preg_match('!<td>Assigned:</td><td>(.*)</td>!', $issue_node->data, $match)) {
+ $assigned = strip_tags($match[1]);
+ if ($assigned != 'Unassigned') {
+ $node->rocketship_assingee['und'][0]['value'] = $assigned;
+ }
+ else {
+ $node->rocketship_assingee['und'] = array();
+ }
}
+ $node->rocketship_project['und'][0]['value'] = rocketship_get_project($issue_node->data);
+
// Store all kinds of metadata as plain tags on this node. We can then
// do listings based on the presence of these tags "easily".
- $tags = array();
+ $tags = array(
+ 'rocketship_version_tags' => array(),
+ 'rocketship_category_tags' => array(),
+ 'rocketship_priority_tags' => array(),
+ 'rocketship_component_tags' => array(),
+ 'rocketship_status_tags' => array(),
+ 'rocketship_issue_tags' => array(),
+ );
if (preg_match('!<td>Version:</td><td>(.*)</td>!', $issue_node->data, $tag)) {
- $tags[] = $tag[1];
+ if (!in_array($tag[1], $tags['rocketship_version_tags'])) {
+ $tags['rocketship_version_tags'][] = $tag[1];
+ }
}
if (preg_match('!<td>Category:</td><td>(.*)</td>!', $issue_node->data, $tag)) {
- $tags[] = $tag[1];
+ if (!in_array($tag[1], $tags['rocketship_category_tags'])) {
+ $tags['rocketship_category_tags'][] = $tag[1];
+ }
}
if (preg_match('!<td>Priority:</td><td>(.*)</td>!', $issue_node->data, $tag)) {
- $tags[] = $tag[1];
+ if (!in_array($tag[1], $tags['rocketship_priority_tags'])) {
+ $tags['rocketship_priority_tags'][] = $tag[1];
+ }
+ }
+ if (preg_match('!<td>Component:</td><td>(.*)</td>!', $issue_node->data, $tag)) {
+ if (!in_array($tag[1], $tags['rocketship_component_tags'])) {
+ $tags['rocketship_component_tags'][] = $tag[1];
+ }
}
if (preg_match('!<td>Status:</td><td>(.*)</td>!', $issue_node->data, $tag)) {
- // "Decode" for "reviewed & tested by the community".
- $tags[] = str_replace('&amp;', '&', $tag[1]);
+ if (!in_array(str_replace('&amp;', '&', $tag[1]), $tags['rocketship_status_tags'])) {
+ // "Decode" for "reviewed & tested by the community".
+ $tags['rocketship_status_tags'][] = str_replace('&amp;', '&', $tag[1]);
+ }
}
if (preg_match('!<td>Issue tags:</td><td>(.*)</td>!', $issue_node->data, $tag)) {
if (preg_match_all('!>([^<]+)</a>!', $tag[1], $more_tags)) {
foreach ($more_tags[1] as $tag) {
- $tags[] = $tag;
+ if (!in_array($tag, $tags['rocketship_issue_tags'])) {
+ $tags['rocketship_issue_tags'][] = $tag;
+ }
}
}
}
// Now try and find existing tags with matching names if present or
// create the new tags if needed.
- $node->field_issue_tags['und'] = array();
- foreach($tags as $tag) {
- // This is an ugly pattern but there might be multiple matching
- // terms, so we need to find the one matching in our vocabulary.
- $matching_terms = taxonomy_get_term_by_name($tag);
- if (!empty($matching_terms)) {
- foreach ($matching_terms as $term) {
- if ($term->vid == variable_get('rocketship_tags_vid', 6)) {
- $node->field_issue_tags['und'][] = array('tid' => $term->tid);
+ foreach($tags as $machine_name => $vocabulary_tags) {
+ $node->$machine_name['und'] = array();
+ $vocabulary = taxonomy_vocabulary_machine_name_load($machine_name);
+ foreach ($vocabulary_tags as $tag) {
+ // This is an ugly pattern but there might be multiple matching
+ // terms, so we need to find the one matching in our vocabulary.
+ $matching_terms = taxonomy_get_term_by_name($tag);
+ if (!empty($matching_terms)) {
+ foreach ($matching_terms as $term) {
+ if ($term->vid == $vocabulary->vid) {
+ $node->{$machine_name}['und'][] = array('tid' => $term->tid);
+ }
}
}
+ else {
+ // Not found, so create a new tag and assign.
+ $term = (object) array(
+ 'vid' => $vocabulary->vid,
+ 'name' => $tag,
+ );
+ taxonomy_term_save($term);
+ $node->{$machine_name}['und'][] = array('tid' => $term->tid);
+ }
}
- else {
- // Not found, so create a new tag and assign.
- $term = (object) array(
- 'vid' => variable_get('rocketship_tags_vid', 6),
- 'name' => $tag,
- );
- taxonomy_term_save($term);
- $node->field_issue_tags['und'][] = array('tid' => $term->tid);
+ if ($machine_name == 'rocketship_priority_tags') {
+ $priority = 0;
+ foreach ($vocabulary_tags as $tag) {
+ switch ($tag) {
+ case 'Needs tests':
+ break;
+ case 'major':
+ $priority = min(-5, $priority);
+ break;
+ case 'critical':
+ $priority = min(-7, $priority);
+ break;
+ case 'sprint':
+ $priority = min(-10, $priority);
+ break;
+ }
+ }
+
+ $node->rocketship_priority['und'][0]['value'] = $priority;
}
}
@@ -236,397 +356,130 @@ function rocketship_parse_issue_page(&$issue_page_content) {
}
}
-/**
- * Display controlled for nodes.
- *
- * This assumes nodes where we want to display a list of issues have a
- * "field_issue_tag_display" single value taxonomy term reference field,
- * which designates the tag that we want to dive into (from all the)
- * issues that we gathered. This can be equal to the rocketship_master_tag
- * variable if we want a list of all locally cached issues.
- *
- * The primary goal here is to group the issues in sensible groups and
- * display them by their group to help produce a visual overview.
- */
-function rocketship_node_view($node, $view_mode, $langcode) {
- if (!empty($node->field_issue_tag_display['und'])) {
-
- // Get more info on the term we are presenting this list for.
- $tid_for_list = $node->field_issue_tag_display['und'][0]['tid'];
- $term_for_list = taxonomy_term_load($tid_for_list);
-
- // Get all the issue nodes that have the tag we need.
- $nids = db_query('SELECT nid FROM {taxonomy_index} WHERE tid = :tid', array(':tid' => $tid_for_list))->fetchAll();
-
- // Look up a cached version for this term if we have it and
- // it is not yet expired (no newer nodes of the issue type
- // available yet).
- if ($cache = cache_get('rocketship:' . $tid_for_list)) {
- $last_issue_update = db_query("SELECT changed FROM {node} WHERE type = :type ORDER BY created DESC", array(':type' => ROCKETSHIP_NODE_TYPE))->fetchField();
- if ($cache->created > $last_issue_update) {
- $node->content['rocketship_issues'] = array(
- '#markup' => $cache->data,
- // Place at the end of the page before book navigation (if present).
- '#weight' => 80,
- );
- return;
+function rocketship_get_project($issue) {
+ $dom = new DOMDocument();
+ @$dom->loadHTML($issue);
+
+ // To hold all your links...
+ $links = array();
+
+ // Get all divs
+ $divs = $dom->getElementsByTagName("div");
+ foreach($divs as $div) {
+ // Check the class attr of each div
+ $cl = $div->getAttribute("class");
+ if ($cl == "breadcrumb") {
+ // Find all hrefs and append it to our $links array
+ $hrefs = $div->getElementsByTagName("a");
+ foreach ($hrefs as $href) {
+ $links[] = $href->getAttribute("href");
}
+ break;
}
+ }
- // Now come some tricky wrangly of the data. We want to display
- // two 3-column tables. The first one is the primary overview
- // with the second more informal about issues we are not currently
- // focusing on.
- $tables = array(
- 1 => t('Currently in the works for Drupal 8'),
- 2 => t('Other related issues'),
- );
+ $link = array_pop($links);
+ $link = explode('/', $link);
+ $project = array_pop($link);
+ return $project;
+}
- // The columns for these two tables are intermingled here to make
- // term matching simpler without complicated conditions. We achieve
- // categorization without complex conditions by prioritizing the
- // placement of issues in categories with their tags.
- $columns = array(
- // Need this first so that we catch the backport patches first and then
- // the rest can sort itself based on simpler tag lookups.
- t('Backport') => array(array('patch (to be ported)', '6.x-dev', '7.x-dev'), 2),
- t('To do') => array(array('active', 'needs work'), 1),
- t('To review') => array(array('needs review'), 1),
- t('To be committed') => array(array('reviewed & tested by the community'), 1),
- t('Postponed') => array(array('postponed', 'postponed (maintainer needs more info)'), 2),
- t('Closed') => array(array('fixed', 'closed (duplicate)', "closed (won't fix)", 'closed (works as designed)', 'closed (cannot reproduce)', 'closed (fixed)'), 2),
+ /**
+ * Gets the drupal issue search path.
+ *
+ * @param array $tags
+ * List of tags to query for
+ * @param $project
+ * The string presenting your project.
+ * @param string $operator
+ * Either 'and' or 'or'
+ *
+ * @return array
+ * url() compatible array structure.
+ */
+function rocketship_get_issue_path(array $tags, $project, $operator = 'and') {
+ $path = array();
+ $path['path'] = 'http://drupal.org/project/issues/search/' . $project;
+
+ if (!empty($tags)) {
+ $path['query'] = array(
+ 'issue_tags' => implode(',', $tags),
+ 'issue_tags_op' => $operator,
);
+ }
- // Some trickery to replace the term names in the $columns array
- // with term ids for easier lookup later and collect a list of
- // all those term IDs for later matching.
- $status_tids = array();
- foreach ($columns as $name => &$terms) {
- foreach ($terms[0] as &$term_name) {
- if ($matching_terms = taxonomy_get_term_by_name($term_name)) {
- foreach ($matching_terms as $term) {
- if ($term->vid == variable_get('rocketship_tags_vid', 6)) {
- // Replace term name in $columns with term ID (the variable
- // is taken by reference, so we directly modify the arary here).
- $term_name = $term->tid;
- // Collect a complete list of all status tids.
- $status_tids[] = $term->tid;
- break;
- }
- }
- }
- else {
- // This might happen if we never had issues with the given status tag,
- // so we don't have the status tag created yet. In this case, we should
- // ignore this tag for now.
- $term_name = 0;
- }
- }
- }
-
- // Now load the nodes we found for the page tag and categorize into
- // the groups defined by terms in $columns.
- $nodes = array();
- foreach($nids as $nid) {
- $issue_node = node_load($nid->nid);
- // Tags on the issue node should be referenced in field_issue_tags[].
- if (!empty($issue_node->field_issue_tags['und'])) {
- foreach ($issue_node->field_issue_tags['und'] as $tag_info) {
- if (in_array($tag_info['tid'], $status_tids)) {
- // If this was a status tid, look at which group it is in,
- // in which case we found where to categorize the node.
- foreach ($columns as $title => $status_map) {
- if (in_array($tag_info['tid'], $status_map[0])) {
- // Save the whole node object categorized under the $columns
- // $title for this column and move two levels up to the next
- // node.
- $nodes[$title][] = $issue_node;
- break 2;
- }
- }
- }
- }
- }
- }
-
- // Now sort the $nodes array into two tables and fill in the table
- // headers and cells appropriately.
- $header_data = array();
- $table_data = array();
- foreach ($columns as $header => $columns_data) {
- // Sort nodes by "priority" defined by current focus as most important and
- // then major and critical being slightly less important and then the rest.
- $cell = array(-10 => '', -7 => '', -5 => '', 0 => '');
- if (!empty($nodes[$header])) {
- foreach ($nodes[$header] as $issue_node) {
- $classes = 'rocketship-node';
- $cell_terms = '';
- $priority = 0;
- foreach ($issue_node->field_issue_tags['und'] as $tag_info) {
- $term = taxonomy_term_load($tag_info['tid']);
- $term_class = 'rocketship-term';
- switch($term->name) {
- // Style the needs tests tag specially.
- // @todo: this has some more potential, think about it.
- case 'Needs tests':
- $term_class .= ' rocketship-needs-tests';
- break;
- // Mark issues with major and critical status.
- case 'major':
- $classes .= ' rocketship-major';
- $priority = min(-5, $priority);
- break;
- case 'critical':
- $classes .= ' rocketship-critical';
- $priority = min(-7, $priority);
- break;
- // Use the "sprint" tag to mark issues for current focus.
- case 'sprint':
- $classes .= ' rocketship-focus';
- $priority = min(-10, $priority);
- break;
- }
- // Remove tags that are "trivial" in this listing. The master tag
- // is always trivial, the tool focuses on 8.x issues, so those
- // not having that tag should be assumed to be 8.x, RTBC and
- // needs review issues are in their respective column, so that is
- // already represented, and the current page tag is presented on
- // the page, so again no need to repeat it on all nodes (it is not
- // a distinguishing factor).
- if (!in_array($term->name, array(variable_get('rocketship_master_tag', 'D8MI'), 'reviewed & tested by the community', 'needs review', '8.x-dev', $term_for_list->name))) {
- // Add up all terms with their respective tags.
- $cell_terms .= '<span class="'. $term_class . '">'. check_plain($term->name) .'</span>';
- }
- }
-
- // Add rocketship-normal class for easier styling.
- if ($priority == 0) {
- $classes .= ' rocketship-normal';
- }
+ return $path;
+}
- // Link to drupal.org node for this issue.
- $drupalorg_nid = preg_replace('!#(\d+):(.*)$!', '\1', $issue_node->title);
- $cell[$priority] .= '<div class="' . $classes . '">'. l($issue_node->title, 'http://drupal.org/node/'. $drupalorg_nid) .'<br />';
- $cell[$priority] .= $cell_terms;
- if (!empty($issue_node->field_assigned['und'][0]['value']) && $issue_node->field_assigned['und'][0]['value'] != 'Unassigned') {
- $cell[$priority] .= '<div class="assigned">' . t('Assigned to @assigned', array('@assigned' => $issue_node->field_assigned['und'][0]['value'])) . "</div>";
+/**
+ * Implements hook_preprocess_node().
+ */
+function rocketship_preprocess_node(&$variables) {
+ if ($variables['type'] == 'rocketship_issue' && !$variables['page']) {
+ drupal_add_css(drupal_get_path('module', 'rocketship') . '/css/rocketship.main.css');
+ $drupalorg_nid = preg_replace('!#(\d+):(.*)$!', '\1', $variables['title']);
+ $variables['node_url'] = 'http://drupal.org/node/' . $drupalorg_nid;
+
+ $rocketship_tags = array();
+ $vocabularies = array(
+ 'rocketship_issue_tags' => t('Issue tags'),
+ 'rocketship_version_tags' => t('Version tags'),
+ 'rocketship_category_tags' => t('Category tags'),
+ 'rocketship_status_tags' => t('Status tags'),
+ 'rocketship_priority_tags' => t('Priority tags'),
+ 'rocketship_component_tags' => t('Component tags'),
+ );
+ foreach ($vocabularies as $machine_name => $label) {
+ $rocketship_tags = field_get_items('node', $variables['node'], $machine_name);
+ if ($rocketship_tags) {
+ foreach ($rocketship_tags as $tag_info) {
+ $term = taxonomy_term_load($tag_info['tid']);
+ switch ($term->name) {
+ // Style the needs tests tag specially.
+ // @todo: this has some more potential, think about it.
+ case 'Needs tests':
+ $variables['classes_array'][] = 'node-rocketship-issue-needs-tests';
+ break;
+ // Mark issues with major and critical status.
+ case 'major':
+ $variables['classes_array'][] = 'node-rocketship-issue-major';
+ break;
+ case 'critical':
+ $variables['classes_array'][] = 'node-rocketship-issue-critical';
+ break;
+ // Use the "sprint" tag to mark issues for current focus.
+ case 'sprint':
+ $variables['classes_array'][] = 'node-rocketship-issue-focus';
+ break;
}
- $cell[$priority] .= '</div>';
}
}
-
- // Store this cell and header in the right table. Each table will only
- // have one cell per column (which might not look nice), but it gets us
- // to the best display results. For purity's sake we might want to
- // rebuild this based on a three column layout, that is what we
- // accomplish with the tables basically.
- $table_data[$columns_data[1]][] = join('', $cell);
- $header_data[$columns_data[1]][] = $header;
}
-
- // Styling and some usabiltiy improvement JS included inline. This is indeed
- // very ugly but is quickly accessible for development and can be refactored
- // later.
- $output = <<<STYLE
-<div class="rocketship-issues">
-<script>
-// UX: Extend click from rocketship-node container to the link inside.
-// I know this looks ugly. It is a quick stop-gap, tips welcome.
-jQuery(document).ready(function($) {
- $('.rocketship-node').click(function() {
- var link = $(this).find('a');
- if (link.length) {
- window.location = link.attr('href');
- }
- });
-});
-</script>
-<style>
- .rocketship-columns {
- width: 100%;
- }
- .rocketship-column {
- width: 31%;
- float: left;
- margin-right: 0.9em;
- }
- @media only screen and (max-width:480px) {
- .rocketship-column {
- width: 100%;
- margin-right: 0;
- }
- }
- @media only screen and (max-width:768px) and (min-width: 481px){
- .rocketship-column {
- width: 47%;
- }
- }
- .rocketship-issues h3 {
- clear: both;
- }
- .rocketship-node {
- margin-bottom: 1em;
- padding: 3px 5px 3px 8px;
- -moz-box-shadow:0px 0px 3px rgba(0,0,0,0.4);
- -webkit-box-shadow:0px 0px 3px rgba(0,0,0,0.4);
- border-left-width: 8px;
- border-left-color: transparent;
- border-left-style: solid;
- border-left-color: #F5F5F5;
- }
- .rocketship-node a {
- font-weight: bold;
- }
- .rocketship-focus {
- border-left-color: #336699;
- }
- .rocketship-major {
- border-left-color: #FF9900;
}
- .rocketship-critical {
- border-left-color: #FF0000;
- }
- .rocketship-term {
- background-color: #F5F5F5;
- margin: 2px 6px 2px 0;
- display: inline-block;
- border-radius: 3px;
- font-size: 0.8em;
- padding: 1px 3px;
- }
- .rocketship-needs-tests {
- font-weight: bold;
- }
- .rocketship-legend {
- float: right;
- font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
- font-size: 0.8em;
- margin-top: 0.2em;
- clear: both;
- }
- .rocketship-legend div {
- display: inline-block;
- margin-left: 2px;
- }
- .rocketship-node .assigned {
- background-color: #F5F5F5;
- margin: 3px -5px 3px -8px;
- padding: 1px 8px;
- border-top: 1px dotted #DDDDDD;
- }
- .rocketship-cloud-wrapper {
- border-top: 1px solid #3b3b3b;
- margin-bottom: 2em;
- clear: both;
- }
- .rocketship-cloud-wrapper p {
- font-size: 0.8em;
- margin-top: 1.3em;
- font-style: italic;
- }
- .rocketship-cloud {
- line-height: 1.3em;
- text-align: justify;
- }
- .rocketship-cloud-1 {
- font-size: 0.8em;
- }
- .rocketship-cloud-2 {
- font-size: 1em;
- }
- .rocketship-cloud-3 {
- font-size: 1.4em;
- }
- .rocketship-cloud-4 {
- font-size: 1.6em;
- }
- .rocketship-cloud-5 {
- font-size: 1.8em;
- }
- .rocketship-cloud-6 {
- font-size: 2em;
- }
- .rocketship-cloud-recent a {
- font-weight: bold;
- }
-</style>
-STYLE;
-
- // Produce a short legend to be included with each table.
- $legend = '<div class="rocketship-legend">Legend: <div class="rocketship-critical rocketship-node">Critical issue</div> <div class="rocketship-major rocketship-node">Major issue</div> <div class="rocketship-focus rocketship-node">Current top priority</div></div>';
- foreach($tables as $num => $title) {
- // Lead the table with a legend.
- $output .= $legend . '<h3>'. $title .'</h3>';
- // Link to drupal.org issue list for the same issue overview. Reassures
- // users that there is no special data showcased here, they can still
- // access all this on drupal.org.
- $issue_list_url = 'http://drupal.org/project/issues/search/drupal?issue_tags=' . urlencode($term_for_list->name) . ($term_for_list->name == variable_get('rocketship_master_tag', 'D8MI') ? '' : '%2C+' . variable_get('rocketship_master_tag', 'D8MI') . '&issue_tags_op=and');
- $output .= '<p style="clear: both;">See all these issues also at <a href="' . check_plain($issue_list_url) . '">' .check_plain($issue_list_url) . '</a>. This view of issues is automatically cached and might be out of date up to two hours at times.</p>';
-
- // Theme the respective "table" with responsive markup.
- $output .= '<div class="rocketship-columns">';
- foreach ($header_data[$num] as $i => $cell) {
- $output .= '<div class="rocketship-column"><h4>' . $cell . '</h4>';
- if (empty($table_data[$num][$i])) {
- $output .= t('(None)');
- }
- else {
- $output .= $table_data[$num][$i];
- }
- $output .= '</div>';
- }
- $output .= '</div>';
- // $output .= theme('table', array('header' => $header_data[$num], 'rows' => array($table_data[$num])));
- }
- $output .= '</div>';
-
- // Include username cloud if the sprint tag is displayed.
- $participant_stats = variable_get('rocketship_participant_stats', array());
- if ($term_for_list->name == 'sprint' && !empty($participant_stats)) {
- $lead_user = variable_get('rocketship_lead_user', 'Gábor Hojtsy');
- $participant_uids = variable_get('rocketship_participant_uids', array());
- $participant_recent = variable_get('rocketship_participant_recent', array());
-
- // Remove lead user and some users to avoid skewing the stats.
- if ($lead_user) {
- unset($participant_stats[$lead_user]);
- }
- unset($participant_stats['System Message']);
- unset($participant_stats['Abandoned Projects']);
-
- $usercloud = array();
- $max = max(array_values($participant_stats));
- $steps = array(1, 2, 3, 5, 7, 10);
- foreach ($steps as $i => $step) {
- foreach ($participant_stats as $name => $count) {
- if (($step == 10) || ($count <= $step * ($max/10))) {
- $class = 'rocketship-cloud-' . ($i+1);
- if (in_array($participant_uids[$name], $participant_recent)) {
- $class .= ' rocketship-cloud-recent';
- }
- $usercloud[$name] = '<span class="' . $class . '"><a href="http://drupal.org/user/' . $participant_uids[$name] . '">' . check_plain($name) . '</a></span>';
- unset($participant_stats[$name]);
- }
- }
- }
- // Sort by username in a case insensitive fashion.
- uksort($usercloud, "strnatcasecmp");
- $note = '<p>' . t('Based on participation in all @tag issues (font size) using a quasi-logarithmic scale and on recent activity (boldness).', array('@tag' => variable_get('rocketship_master_tag', 'D8MI')));
- if ($lead_user) {
- $note .= ' ' . t('Excludes the initiative lead, @lead.', array('@lead' => $lead_user));
- }
- $note .= '</p>';
- $output .= '<div class="rocketship-cloud-wrapper" id="thanks"><h3>' . t('Thanks to') . ' <a href="#thanks">#</a></h3>' . '<div class="rocketship-cloud">' . join(' ', $usercloud) . '</div>' . $note . '</div>';
- }
+}
- // Save the generated page section in the rocketship cache.
- cache_set('rocketship:' . $tid_for_list, $output);
- watchdog('rocketship', 'Rocketship cache miss.');
+/**
+ * CTools Export save callback for rocketship_settings.
+ */
+function rocketship_settings_save($object) {
+ $schema = ctools_export_get_schema('rocketship_settings');
+ $export = $schema['export'];
+ if (empty($export['primary key'])) {
+ return FALSE;
+ }
- $node->content['rocketship_issues'] = array(
- '#markup' => $output,
- // Place at the end of the page before book navigation (if present).
- '#weight' => 80,
- );
+ $key = $export['primary key'];
+ if ($object->export_type & EXPORT_IN_DATABASE) {
+ // Existing record.
+ $update = array($key);
+ }
+ else {
+ // New record.
+ $update = array();
+ $object->export_type = EXPORT_IN_DATABASE;
}
+ drupal_write_record('rocketship_settings', $object, $update);
+ rocketship_parse_all($object);
+ menu_cache_clear_all();
+ return $object;
}
diff --git a/rocketship.pages_default.inc b/rocketship.pages_default.inc
new file mode 100644
index 0000000..449c582
--- /dev/null
+++ b/rocketship.pages_default.inc
@@ -0,0 +1,388 @@
+<?php
+
+/**
+ * Implements hook_default_page_manager_handlers().
+ */
+function rocketship_default_page_manager_handlers() {
+ $export = array();
+
+ $handler = new stdClass();
+ $handler->disabled = FALSE; /* Edit this to true to make a default handler disabled initially */
+ $handler->api_version = 1;
+ $handler->name = 'node_view_panel_context';
+ $handler->task = 'node_view';
+ $handler->subtask = '';
+ $handler->handler = 'panel_context';
+ $handler->weight = 0;
+ $handler->conf = array(
+ 'title' => 'Issues',
+ 'no_blocks' => 0,
+ 'pipeline' => 'standard',
+ 'body_classes_to_remove' => '',
+ 'body_classes_to_add' => '',
+ 'css_id' => '',
+ 'css' => '',
+ 'contexts' => array(),
+ 'relationships' => array(
+ 0 => array(
+ 'identifier' => 'Display Tags',
+ 'keyword' => 'tags',
+ 'name' => 'terms_from_node',
+ 'vocabulary' => array(
+ 'rocketship_tags' => 'rocketship_tags',
+ ),
+ 'concatenator' => ',',
+ 'context' => 'argument_entity_id:node_1',
+ 'id' => 1,
+ ),
+ ),
+ 'access' => array(
+ 'plugins' => array(
+ 0 => array(
+ 'name' => 'entity_bundle:node',
+ 'settings' => array(
+ 'type' => array(
+ 'rocketship_focus' => 'rocketship_focus',
+ ),
+ ),
+ 'context' => 'argument_entity_id:node_1',
+ 'not' => FALSE,
+ ),
+ ),
+ 'logic' => 'and',
+ ),
+ );
+ $display = new panels_display();
+ $display->layout = 'rocketship';
+ $display->layout_settings = array();
+ $display->panel_settings = array(
+ 'style_settings' => array(
+ 'default' => NULL,
+ 'middle' => NULL,
+ 'left' => NULL,
+ 'right' => NULL,
+ 'top' => NULL,
+ 'bottom' => NULL,
+ 'upper_first' => NULL,
+ 'upper_middle' => NULL,
+ 'upper_last' => NULL,
+ 'lower_first' => NULL,
+ 'lower_middle' => NULL,
+ 'lower_last' => NULL,
+ ),
+ );
+ $display->cache = array();
+ $display->title = '%node:title';
+ $display->content = array();
+ $display->panels = array();
+ $pane = new stdClass();
+ $pane->pid = 'new-1';
+ $pane->panel = 'bottom';
+ $pane->type = 'rocketship_thanks';
+ $pane->subtype = 'rocketship_thanks';
+ $pane->shown = TRUE;
+ $pane->access = array();
+ $pane->configuration = array(
+ 'override_title' => 0,
+ 'override_title_text' => '',
+ );
+ $pane->cache = array();
+ $pane->style = array(
+ 'settings' => NULL,
+ );
+ $pane->css = array();
+ $pane->extras = array();
+ $pane->position = 0;
+ $pane->locks = array();
+ $display->content['new-1'] = $pane;
+ $display->panels['bottom'][0] = 'new-1';
+ $pane = new stdClass();
+ $pane->pid = 'new-2';
+ $pane->panel = 'lower_first';
+ $pane->type = 'views_panes';
+ $pane->subtype = 'issues-focus';
+ $pane->shown = TRUE;
+ $pane->access = array();
+ $pane->configuration = array(
+ 'exposed' => array(
+ 'rocketship_tags_tid' => 'patch (to be ported), 6.x-dev, 7.x-dev',
+ ),
+ 'context' => array(
+ 0 => 'relationship_terms_from_node_1',
+ ),
+ 'override_title' => 1,
+ 'override_title_text' => 'Backport',
+ );
+ $pane->cache = array();
+ $pane->style = array(
+ 'settings' => NULL,
+ 'style' => 'default',
+ );
+ $pane->css = array();
+ $pane->extras = array();
+ $pane->position = 0;
+ $pane->locks = array();
+ $display->content['new-2'] = $pane;
+ $display->panels['lower_first'][0] = 'new-2';
+ $pane = new stdClass();
+ $pane->pid = 'new-3';
+ $pane->panel = 'lower_last';
+ $pane->type = 'views_panes';
+ $pane->subtype = 'issues-focus';
+ $pane->shown = TRUE;
+ $pane->access = array();
+ $pane->configuration = array(
+ 'exposed' => array(
+ 'rocketship_tags_tid' => 'fixed, closed (duplicate), closed (won\'t fix), closed (works as designed), closed (cannot reproduce), closed (fixed)',
+ ),
+ 'context' => array(
+ 0 => 'relationship_terms_from_node_1',
+ ),
+ 'override_title' => 1,
+ 'override_title_text' => 'Closed',
+ );
+ $pane->cache = array();
+ $pane->style = array(
+ 'settings' => NULL,
+ 'style' => 'default',
+ );
+ $pane->css = array();
+ $pane->extras = array();
+ $pane->position = 0;
+ $pane->locks = array();
+ $display->content['new-3'] = $pane;
+ $display->panels['lower_last'][0] = 'new-3';
+ $pane = new stdClass();
+ $pane->pid = 'new-4';
+ $pane->panel = 'lower_middle';
+ $pane->type = 'views_panes';
+ $pane->subtype = 'issues-focus';
+ $pane->shown = TRUE;
+ $pane->access = array();
+ $pane->configuration = array(
+ 'exposed' => array(
+ 'rocketship_tags_tid' => 'postponed, postponed (maintainer needs more info)',
+ ),
+ 'context' => array(
+ 0 => 'relationship_terms_from_node_1',
+ ),
+ 'override_title' => 1,
+ 'override_title_text' => 'Postponed',
+ );
+ $pane->cache = array();
+ $pane->style = array(
+ 'settings' => NULL,
+ 'style' => 'default',
+ );
+ $pane->css = array();
+ $pane->extras = array();
+ $pane->position = 0;
+ $pane->locks = array();
+ $display->content['new-4'] = $pane;
+ $display->panels['lower_middle'][0] = 'new-4';
+ $pane = new stdClass();
+ $pane->pid = 'new-5';
+ $pane->panel = 'middle';
+ $pane->type = 'rocketship_legend';
+ $pane->subtype = 'rocketship_legend';
+ $pane->shown = TRUE;
+ $pane->access = array();
+ $pane->configuration = array(
+ 'override_title' => 0,
+ 'override_title_text' => '',
+ );
+ $pane->cache = array();
+ $pane->style = array(
+ 'settings' => NULL,
+ );
+ $pane->css = array();
+ $pane->extras = array();
+ $pane->position = 0;
+ $pane->locks = array();
+ $display->content['new-5'] = $pane;
+ $display->panels['middle'][0] = 'new-5';
+ $pane = new stdClass();
+ $pane->pid = 'new-6';
+ $pane->panel = 'middle';
+ $pane->type = 'rocketship_link';
+ $pane->subtype = 'rocketship_link';
+ $pane->shown = TRUE;
+ $pane->access = array();
+ $pane->configuration = array(
+ 'override_title' => 1,
+ 'override_title_text' => 'Other related issues',
+ 'context' => 'empty',
+ );
+ $pane->cache = array();
+ $pane->style = array(
+ 'settings' => NULL,
+ );
+ $pane->css = array();
+ $pane->extras = array();
+ $pane->position = 1;
+ $pane->locks = array();
+ $display->content['new-6'] = $pane;
+ $display->panels['middle'][1] = 'new-6';
+ $pane = new stdClass();
+ $pane->pid = 'new-7';
+ $pane->panel = 'top';
+ $pane->type = 'node_content';
+ $pane->subtype = 'node_content';
+ $pane->shown = TRUE;
+ $pane->access = array();
+ $pane->configuration = array(
+ 'links' => 1,
+ 'no_extras' => 1,
+ 'override_title' => 0,
+ 'override_title_text' => '',
+ 'identifier' => '',
+ 'link' => 0,
+ 'leave_node_title' => 0,
+ 'build_mode' => 'full',
+ 'context' => 'argument_entity_id:node_1',
+ );
+ $pane->cache = array();
+ $pane->style = array(
+ 'settings' => NULL,
+ );
+ $pane->css = array();
+ $pane->extras = array();
+ $pane->position = 0;
+ $pane->locks = array();
+ $display->content['new-7'] = $pane;
+ $display->panels['top'][0] = 'new-7';
+ $pane = new stdClass();
+ $pane->pid = 'new-8';
+ $pane->panel = 'top';
+ $pane->type = 'rocketship_legend';
+ $pane->subtype = 'rocketship_legend';
+ $pane->shown = TRUE;
+ $pane->access = array();
+ $pane->configuration = array(
+ 'override_title' => 0,
+ 'override_title_text' => '',
+ );
+ $pane->cache = array();
+ $pane->style = array(
+ 'settings' => NULL,
+ );
+ $pane->css = array();
+ $pane->extras = array();
+ $pane->position = 1;
+ $pane->locks = array();
+ $display->content['new-8'] = $pane;
+ $display->panels['top'][1] = 'new-8';
+ $pane = new stdClass();
+ $pane->pid = 'new-9';
+ $pane->panel = 'top';
+ $pane->type = 'rocketship_link';
+ $pane->subtype = 'rocketship_link';
+ $pane->shown = TRUE;
+ $pane->access = array();
+ $pane->configuration = array(
+ 'override_title' => 1,
+ 'override_title_text' => 'Currently in the works for Drupal 8',
+ 'context' => 'relationship_terms_from_node_1',
+ );
+ $pane->cache = array();
+ $pane->style = array(
+ 'settings' => NULL,
+ );
+ $pane->css = array();
+ $pane->extras = array();
+ $pane->position = 2;
+ $pane->locks = array();
+ $display->content['new-9'] = $pane;
+ $display->panels['top'][2] = 'new-9';
+ $pane = new stdClass();
+ $pane->pid = 'new-10';
+ $pane->panel = 'upper_first';
+ $pane->type = 'views_panes';
+ $pane->subtype = 'issues-focus';
+ $pane->shown = TRUE;
+ $pane->access = array();
+ $pane->configuration = array(
+ 'exposed' => array(
+ 'rocketship_tags_tid' => 'active, needs work',
+ ),
+ 'context' => array(
+ 0 => 'relationship_terms_from_node_1',
+ ),
+ 'override_title' => 1,
+ 'override_title_text' => 'To do',
+ );
+ $pane->cache = array();
+ $pane->style = array(
+ 'settings' => NULL,
+ 'style' => 'default',
+ );
+ $pane->css = array();
+ $pane->extras = array();
+ $pane->position = 0;
+ $pane->locks = array();
+ $display->content['new-10'] = $pane;
+ $display->panels['upper_first'][0] = 'new-10';
+ $pane = new stdClass();
+ $pane->pid = 'new-11';
+ $pane->panel = 'upper_last';
+ $pane->type = 'views_panes';
+ $pane->subtype = 'issues-focus';
+ $pane->shown = TRUE;
+ $pane->access = array();
+ $pane->configuration = array(
+ 'exposed' => array(
+ 'rocketship_tags_tid' => 'reviewed & tested by the community',
+ ),
+ 'context' => array(
+ 0 => 'relationship_terms_from_node_1',
+ ),
+ 'override_title' => 1,
+ 'override_title_text' => 'To be committed',
+ );
+ $pane->cache = array();
+ $pane->style = array(
+ 'settings' => NULL,
+ 'style' => 'default',
+ );
+ $pane->css = array();
+ $pane->extras = array();
+ $pane->position = 0;
+ $pane->locks = array();
+ $display->content['new-11'] = $pane;
+ $display->panels['upper_last'][0] = 'new-11';
+ $pane = new stdClass();
+ $pane->pid = 'new-12';
+ $pane->panel = 'upper_middle';
+ $pane->type = 'views_panes';
+ $pane->subtype = 'issues-focus';
+ $pane->shown = TRUE;
+ $pane->access = array();
+ $pane->configuration = array(
+ 'exposed' => array(
+ 'rocketship_tags_tid' => 'needs review',
+ ),
+ 'context' => array(
+ 0 => 'relationship_terms_from_node_1',
+ ),
+ 'override_title' => 1,
+ 'override_title_text' => 'To review',
+ );
+ $pane->cache = array();
+ $pane->style = array(
+ 'settings' => NULL,
+ 'style' => 'default',
+ );
+ $pane->css = array();
+ $pane->extras = array();
+ $pane->position = 0;
+ $pane->locks = array();
+ $display->content['new-12'] = $pane;
+ $display->panels['upper_middle'][0] = 'new-12';
+ $display->hide_title = PANELS_TITLE_NONE;
+ $display->title_pane = '0';
+ $handler->conf['display'] = $display;
+
+ $export['node_view_panel_context'] = $handler;
+
+ return $export;
+}
diff --git a/rocketship.views_default.inc b/rocketship.views_default.inc
new file mode 100644
index 0000000..60732bd
--- /dev/null
+++ b/rocketship.views_default.inc
@@ -0,0 +1,184 @@
+<?php
+
+
+/**
+ * Implements function hook_views_default_views().
+ */
+function rocketship_views_default_views() {
+ $view = new view();
+ $view->name = 'issues';
+ $view->description = '';
+ $view->tag = 'Rocketship';
+ $view->base_table = 'node';
+ $view->human_name = 'Issues';
+ $view->core = 7;
+ $view->api_version = '3.0';
+ $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
+
+ /* Display: Master */
+ $handler = $view->new_display('default', 'Master', 'default');
+ $handler->display->display_options['use_more_always'] = FALSE;
+ $handler->display->display_options['access']['type'] = 'perm';
+ $handler->display->display_options['cache']['type'] = 'none';
+ $handler->display->display_options['query']['type'] = 'views_query';
+ $handler->display->display_options['exposed_form']['type'] = 'basic';
+ $handler->display->display_options['pager']['type'] = 'none';
+ $handler->display->display_options['pager']['options']['offset'] = '0';
+ $handler->display->display_options['style_plugin'] = 'default';
+ $handler->display->display_options['row_plugin'] = 'node';
+ $handler->display->display_options['row_options']['links'] = FALSE;
+ /* No results behavior: Global: Text area */
+ $handler->display->display_options['empty']['area']['id'] = 'area';
+ $handler->display->display_options['empty']['area']['table'] = 'views';
+ $handler->display->display_options['empty']['area']['field'] = 'area';
+ $handler->display->display_options['empty']['area']['empty'] = TRUE;
+ $handler->display->display_options['empty']['area']['content'] = '(None)';
+ $handler->display->display_options['empty']['area']['format'] = 'plain_text';
+ /* Field: Content: Title */
+ $handler->display->display_options['fields']['title']['id'] = 'title';
+ $handler->display->display_options['fields']['title']['table'] = 'node';
+ $handler->display->display_options['fields']['title']['field'] = 'title';
+ $handler->display->display_options['fields']['title']['label'] = '';
+ $handler->display->display_options['fields']['title']['alter']['word_boundary'] = FALSE;
+ $handler->display->display_options['fields']['title']['alter']['ellipsis'] = FALSE;
+ /* Sort criterion: Content: Priority (rocketship_priority) */
+ $handler->display->display_options['sorts']['rocketship_priority_value']['id'] = 'rocketship_priority_value';
+ $handler->display->display_options['sorts']['rocketship_priority_value']['table'] = 'field_data_rocketship_priority';
+ $handler->display->display_options['sorts']['rocketship_priority_value']['field'] = 'rocketship_priority_value';
+ /* Sort criterion: Content: Updated date */
+ $handler->display->display_options['sorts']['changed']['id'] = 'changed';
+ $handler->display->display_options['sorts']['changed']['table'] = 'node';
+ $handler->display->display_options['sorts']['changed']['field'] = 'changed';
+ $handler->display->display_options['sorts']['changed']['order'] = 'DESC';
+ /* Contextual filter: Content: Issue tags (rocketship_issue_tags) */
+ $handler->display->display_options['arguments']['rocketship_issue_tags_tid']['id'] = 'rocketship_issue_tags_tid';
+ $handler->display->display_options['arguments']['rocketship_issue_tags_tid']['table'] = 'field_data_rocketship_issue_tags';
+ $handler->display->display_options['arguments']['rocketship_issue_tags_tid']['field'] = 'rocketship_issue_tags_tid';
+ $handler->display->display_options['arguments']['rocketship_issue_tags_tid']['default_action'] = 'empty';
+ $handler->display->display_options['arguments']['rocketship_issue_tags_tid']['default_argument_type'] = 'fixed';
+ $handler->display->display_options['arguments']['rocketship_issue_tags_tid']['summary']['number_of_records'] = '0';
+ $handler->display->display_options['arguments']['rocketship_issue_tags_tid']['summary']['format'] = 'default_summary';
+ $handler->display->display_options['arguments']['rocketship_issue_tags_tid']['summary_options']['items_per_page'] = '25';
+ $handler->display->display_options['filter_groups']['operator'] = 'OR';
+ /* Filter criterion: Content: Type */
+ $handler->display->display_options['filters']['type']['id'] = 'type';
+ $handler->display->display_options['filters']['type']['table'] = 'node';
+ $handler->display->display_options['filters']['type']['field'] = 'type';
+ $handler->display->display_options['filters']['type']['value'] = array(
+ 'rocketship_issue' => 'rocketship_issue',
+ );
+ $handler->display->display_options['filters']['type']['group'] = 1;
+ /* Filter criterion: Content: Published */
+ $handler->display->display_options['filters']['status']['id'] = 'status';
+ $handler->display->display_options['filters']['status']['table'] = 'node';
+ $handler->display->display_options['filters']['status']['field'] = 'status';
+ $handler->display->display_options['filters']['status']['value'] = 1;
+ $handler->display->display_options['filters']['status']['group'] = 1;
+ $handler->display->display_options['filters']['status']['expose']['operator'] = FALSE;
+ /* Filter criterion: Content: Category tags (rocketship_category_tags) */
+ $handler->display->display_options['filters']['rocketship_category_tags_tid']['id'] = 'rocketship_category_tags_tid';
+ $handler->display->display_options['filters']['rocketship_category_tags_tid']['table'] = 'field_data_rocketship_category_tags';
+ $handler->display->display_options['filters']['rocketship_category_tags_tid']['field'] = 'rocketship_category_tags_tid';
+ $handler->display->display_options['filters']['rocketship_category_tags_tid']['value'] = '';
+ $handler->display->display_options['filters']['rocketship_category_tags_tid']['exposed'] = TRUE;
+ $handler->display->display_options['filters']['rocketship_category_tags_tid']['expose']['operator_id'] = 'rocketship_category_tags_tid_op';
+ $handler->display->display_options['filters']['rocketship_category_tags_tid']['expose']['label'] = 'Category tags (rocketship_category_tags)';
+ $handler->display->display_options['filters']['rocketship_category_tags_tid']['expose']['operator'] = 'rocketship_category_tags_tid_op';
+ $handler->display->display_options['filters']['rocketship_category_tags_tid']['expose']['identifier'] = 'rocketship_category_tags_tid';
+ $handler->display->display_options['filters']['rocketship_category_tags_tid']['expose']['multiple'] = TRUE;
+ $handler->display->display_options['filters']['rocketship_category_tags_tid']['expose']['remember_roles'] = array(
+ 2 => '2',
+ 1 => 0,
+ );
+ $handler->display->display_options['filters']['rocketship_category_tags_tid']['vocabulary'] = 'rocketship_category_tags';
+ /* Filter criterion: Content: Component tags (rocketship_component_tags) */
+ $handler->display->display_options['filters']['rocketship_component_tags_tid']['id'] = 'rocketship_component_tags_tid';
+ $handler->display->display_options['filters']['rocketship_component_tags_tid']['table'] = 'field_data_rocketship_component_tags';
+ $handler->display->display_options['filters']['rocketship_component_tags_tid']['field'] = 'rocketship_component_tags_tid';
+ $handler->display->display_options['filters']['rocketship_component_tags_tid']['value'] = '';
+ $handler->display->display_options['filters']['rocketship_component_tags_tid']['exposed'] = TRUE;
+ $handler->display->display_options['filters']['rocketship_component_tags_tid']['expose']['operator_id'] = 'rocketship_component_tags_tid_op';
+ $handler->display->display_options['filters']['rocketship_component_tags_tid']['expose']['label'] = 'Component tags (rocketship_component_tags)';
+ $handler->display->display_options['filters']['rocketship_component_tags_tid']['expose']['operator'] = 'rocketship_component_tags_tid_op';
+ $handler->display->display_options['filters']['rocketship_component_tags_tid']['expose']['identifier'] = 'rocketship_component_tags_tid';
+ $handler->display->display_options['filters']['rocketship_component_tags_tid']['expose']['multiple'] = TRUE;
+ $handler->display->display_options['filters']['rocketship_component_tags_tid']['expose']['remember_roles'] = array(
+ 2 => '2',
+ 1 => 0,
+ );
+ $handler->display->display_options['filters']['rocketship_component_tags_tid']['vocabulary'] = 'rocketship_component_tags';
+ /* Filter criterion: Content: Priority tags (rocketship_priority_tags) */
+ $handler->display->display_options['filters']['rocketship_priority_tags_tid']['id'] = 'rocketship_priority_tags_tid';
+ $handler->display->display_options['filters']['rocketship_priority_tags_tid']['table'] = 'field_data_rocketship_priority_tags';
+ $handler->display->display_options['filters']['rocketship_priority_tags_tid']['field'] = 'rocketship_priority_tags_tid';
+ $handler->display->display_options['filters']['rocketship_priority_tags_tid']['value'] = '';
+ $handler->display->display_options['filters']['rocketship_priority_tags_tid']['exposed'] = TRUE;
+ $handler->display->display_options['filters']['rocketship_priority_tags_tid']['expose']['operator_id'] = 'rocketship_priority_tags_tid_op';
+ $handler->display->display_options['filters']['rocketship_priority_tags_tid']['expose']['label'] = 'Priority tags (rocketship_priority_tags)';
+ $handler->display->display_options['filters']['rocketship_priority_tags_tid']['expose']['operator'] = 'rocketship_priority_tags_tid_op';
+ $handler->display->display_options['filters']['rocketship_priority_tags_tid']['expose']['identifier'] = 'rocketship_priority_tags_tid';
+ $handler->display->display_options['filters']['rocketship_priority_tags_tid']['expose']['multiple'] = TRUE;
+ $handler->display->display_options['filters']['rocketship_priority_tags_tid']['expose']['remember_roles'] = array(
+ 2 => '2',
+ 1 => 0,
+ );
+ $handler->display->display_options['filters']['rocketship_priority_tags_tid']['vocabulary'] = 'rocketship_priority_tags';
+ /* Filter criterion: Content: Status tags (rocketship_status_tags) */
+ $handler->display->display_options['filters']['rocketship_status_tags_tid']['id'] = 'rocketship_status_tags_tid';
+ $handler->display->display_options['filters']['rocketship_status_tags_tid']['table'] = 'field_data_rocketship_status_tags';
+ $handler->display->display_options['filters']['rocketship_status_tags_tid']['field'] = 'rocketship_status_tags_tid';
+ $handler->display->display_options['filters']['rocketship_status_tags_tid']['value'] = '';
+ $handler->display->display_options['filters']['rocketship_status_tags_tid']['exposed'] = TRUE;
+ $handler->display->display_options['filters']['rocketship_status_tags_tid']['expose']['operator_id'] = 'rocketship_status_tags_tid_op';
+ $handler->display->display_options['filters']['rocketship_status_tags_tid']['expose']['label'] = 'Status tags (rocketship_status_tags)';
+ $handler->display->display_options['filters']['rocketship_status_tags_tid']['expose']['operator'] = 'rocketship_status_tags_tid_op';
+ $handler->display->display_options['filters']['rocketship_status_tags_tid']['expose']['identifier'] = 'rocketship_status_tags_tid';
+ $handler->display->display_options['filters']['rocketship_status_tags_tid']['expose']['multiple'] = TRUE;
+ $handler->display->display_options['filters']['rocketship_status_tags_tid']['expose']['remember_roles'] = array(
+ 2 => '2',
+ 1 => 0,
+ );
+ $handler->display->display_options['filters']['rocketship_status_tags_tid']['vocabulary'] = 'rocketship_status_tags';
+ /* Filter criterion: Content: Version tags (rocketship_version_tags) */
+ $handler->display->display_options['filters']['rocketship_version_tags_tid']['id'] = 'rocketship_version_tags_tid';
+ $handler->display->display_options['filters']['rocketship_version_tags_tid']['table'] = 'field_data_rocketship_version_tags';
+ $handler->display->display_options['filters']['rocketship_version_tags_tid']['field'] = 'rocketship_version_tags_tid';
+ $handler->display->display_options['filters']['rocketship_version_tags_tid']['value'] = '';
+ $handler->display->display_options['filters']['rocketship_version_tags_tid']['exposed'] = TRUE;
+ $handler->display->display_options['filters']['rocketship_version_tags_tid']['expose']['operator_id'] = 'rocketship_version_tags_tid_op';
+ $handler->display->display_options['filters']['rocketship_version_tags_tid']['expose']['label'] = 'Version tags (rocketship_version_tags)';
+ $handler->display->display_options['filters']['rocketship_version_tags_tid']['expose']['operator'] = 'rocketship_version_tags_tid_op';
+ $handler->display->display_options['filters']['rocketship_version_tags_tid']['expose']['identifier'] = 'rocketship_version_tags_tid';
+ $handler->display->display_options['filters']['rocketship_version_tags_tid']['expose']['multiple'] = TRUE;
+ $handler->display->display_options['filters']['rocketship_version_tags_tid']['expose']['remember_roles'] = array(
+ 2 => '2',
+ 1 => 0,
+ );
+ $handler->display->display_options['filters']['rocketship_version_tags_tid']['vocabulary'] = 'rocketship_version_tags';
+
+ /* Display: Focus */
+ $handler = $view->new_display('panel_pane', 'Focus', 'focus');
+ $handler->display->display_options['pane_title'] = 'Taged Issues';
+ $handler->display->display_options['allow']['use_pager'] = 0;
+ $handler->display->display_options['allow']['items_per_page'] = 0;
+ $handler->display->display_options['allow']['offset'] = 0;
+ $handler->display->display_options['allow']['link_to_view'] = 0;
+ $handler->display->display_options['allow']['more_link'] = 0;
+ $handler->display->display_options['allow']['path_override'] = 0;
+ $handler->display->display_options['allow']['title_override'] = 'title_override';
+ $handler->display->display_options['allow']['exposed_form'] = 'exposed_form';
+ $handler->display->display_options['allow']['fields_override'] = 0;
+ $handler->display->display_options['argument_input'] = array(
+ 'rocketship_issue_tags_tid' => array(
+ 'type' => 'context',
+ 'context' => 'entity:taxonomy_term.tid',
+ 'context_optional' => 0,
+ 'panel' => '0',
+ 'fixed' => '',
+ 'label' => 'Content: Issue tags (rocketship_issue_tags)',
+ ),
+ );
+ $handler->display->display_options['inherit_panels_path'] = '0';
+ $views[$view->name] = $view;
+ return $views;
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment