Forráskód Böngészése

Fixed Tripal content listing page, pager, filters and sorting works

Stephen Ficklin 8 éve
szülő
commit
6cdac0c05b

+ 165 - 55
tripal/includes/TripalEntityUIController.inc

@@ -175,74 +175,171 @@ function tripal_view_entity($entity, $view_mode = 'full') {
   *   A form array describing this listing to the Form API.
   */
  function tripal_content_overview_form($form, &$form_state) {
-   $filter_status = '';
-   $filter_type = '';
-   if (array_key_exists('values', $form_state)) {
-     if ($form_state['values']['status'] != '[any]') {
-       $filter_status = preg_replace('/status-(\d+)/', '\1', $form_state['values']['status']);
-     }
-     if ($form_state['values']['type'] != '[any]') {
-       $filter_type = $form_state['values']['type'];
-     }
-   }
-   // Set the title to be informative (defaults to content for some reason).
-   drupal_set_title('Tripal Content');
 
-   $form['filter'] = array(
-     '#type' => 'fieldset',
-     '#title' => 'Filter',
-     '#collapsible' => TRUE,
-     '#collapsed' => TRUE,
+   // Set form defaults.  The $_SESSION contains the last known selection
+   // by this user. That should be overridden if the $_GET variable contains
+   // values.
+   $etype = '';
+   $status = '';
+   if (array_key_exists('tripal_content_overview', $_SESSION)) {
+     $etype = $_SESSION['tripal_content_overview']['type'];
+     $status = $_SESSION['tripal_content_overview']['status'];
+   }
+   $etype = array_key_exists('type', $_GET) ? $_GET['type'] : $etype;
+   $status = array_key_exists('status', $_GET) ? $_GET['status'] : $status;
+
+   $headers = array(
+     'title' => array(
+       'data' => t('Title'),
+       'type' => 'property',
+       'specifier' => 'title'
+     ),
+     'Type',
+     'Term',
+     'Author',
+     'status' => array(
+       'data' => t('Status'),
+       'type' => 'property',
+       'specifier' => 'status'
+     ),
+     'changed' => array(
+       'data' => t('Updated'),
+       'type' => 'property',
+       'specifier' => 'changed',
+       'sort' => 'desc',
+     ),
+     'Operations',
    );
+   $rows = array();
+
+   // Get the Options arrays used by the fields below. We need to build them
+   // here because we will use them both for creating the item list below
+   // and for the fields.
    $etypes = db_select('tripal_bundle', 'tb')
      ->fields('tb', array('name', 'label'))
      ->execute()
      ->fetchAllKeyed();
-   $etypes = array('[any]' => 'any') +  $etypes;
-   $form['filter']['type'] = array(
-     '#type' => 'select',
-     '#title' => 'Content Type',
-     '#options' => $etypes,
+   $etypes = array('0' => 'any') +  $etypes;
+   $statuses = array(
+     '0' => 'any',
+     'status-1' => 'published',
+     'status-0' => 'not published'
    );
-   $form['filter']['status'] = array(
-     '#type' => 'select',
-     '#title' => 'Status',
-     '#options' => array(
-       '[any]' => 'any',
-       'status-1' => 'published',
-       'status-0' => 'not published'
-     ),
+
+   // Build the list of existing filters.
+   $items = array();
+   if ($etype) {
+     $items[] = 'where <strong>type</strong> is <strong>' . $etypes[$etype] . '</strong>';
+   }
+   if ($status) {
+     $items[] = 'where <strong>status</strong> is <strong>' . $statuses[$status] . '</strong>';
+   }
+   // Add 'and' to the beginning of every filter after the first
+   if (count($items) > 1) {
+     for ($i = 1; $i < count($items); $i++) {
+       $items[$i] = 'and ' . $items[$i];
+     }
+   }
+   $list = theme_item_list(array(
+     'items' => $items,
+     'title' => '',
+     'type' => 'ul',
+     'attributes' => array(),
+   ));
+
+   // Set the title to be informative (defaults to content for some reason).
+   drupal_set_title('Tripal Content');
+
+   $form['filter'] = array(
+     '#type' => 'fieldset',
+     '#title' => 'Show only items where',
+     '#collapsible' => FALSE,
+     '#collapsed' => FALSE,
+     '#prefix' => '<div class="exposed-filters">',
+     '#suffix' => '</div>',
    );
-   $form['filter']['filterbtn'] = array(
-     '#type' => 'submit',
-     '#value' => 'Filter',
+   if (count($items) > 0) {
+     $form['filter']['filters'] = array(
+       '#type' => 'item',
+       '#markup' => $list,
+     );
+   }
+   if (!$status) {
+     $form['filter']['status'] = array(
+       '#type' => 'select',
+       '#title' => 'Status',
+       '#options' => $statuses,
+     );
+   }
+   else {
+     $form['filter']['status'] = array(
+       '#type' => 'value',
+       '#value' => $status,
+     );
+   }
+
+   if (!$etype) {
+     $form['filter']['type'] = array(
+       '#type' => 'select',
+       '#title' => 'Content Type',
+       '#options' => $etypes,
+     );
+   }
+   else {
+     $form['filter']['type'] = array(
+       '#type' => 'value',
+       '#value' => $etype,
+     );
+   }
+
+   $form['filter']['buttons'] = array(
+     '#type' => 'value',
+     '#prefix' => '<div id="edit-actions" class="container-inline form-actions form-wrapper">',
+     '#suffix' => '</div>',
    );
+   if (count($items) > 0) {
+     if (count($items) < 2) {
+       $form['filter']['buttons']['refinebtn'] = array(
+         '#type' => 'submit',
+         '#value' => 'Refine',
+         '#name' => 'refine',
+       );
+     }
+     $form['filter']['buttons']['filterbtn'] = array(
+       '#type' => 'submit',
+       '#value' => 'Reset',
+       '#name' => 'reset',
+     );
+   }
+   else {
+     $form['filter']['buttons']['filterbtn'] = array(
+       '#type' => 'submit',
+       '#value' => 'Filter',
+       '#name' => 'filter',
+     );
+   }
 
-   $query = new TripalFieldQuery();
+   $query = new EntityFieldQuery();
    $query->entityCondition('entity_type', 'TripalEntity');
-   if ($filter_type) {
-     $query->entityCondition('bundle', $filter_type);
-     //$query->fieldCondition('content_type', 'content_type', 'organism');
-     //$query->fieldOrderBy('content_type', 'content_type', 'DESC');
-     //$query->fieldCondition('organism__genus', 'organism__genus', 'Oryza');
+   if ($etype) {
+     $query->entityCondition('bundle', $etype);
    }
+   //$query->propertyOrderBy('created', 'DESC');
 
    // Find out the total number of records and determine what page we're on, and
    // initialize the pager.
    $cquery = clone $query;
    $cquery->count();
    $num_records = $cquery->execute();
-   $num_per_page = 25;
-   $page = pager_default_initialize($num_records, $num_per_page);
-   $offset = $num_per_page * $page;
-   $pager = theme('pager');
 
-
-   $query->range($offset, $num_per_page);
+   // Calculate the range and create a pager.
+   $num_per_page = 25;
+   $offset = array_key_exists('page', $_GET) ? $_GET['page'] : 0;
+   $query->pager($num_per_page);
+   $query->tableSort($headers);
    $results = $query->execute();
+   $pager = theme('pager');
 
-   $headers = array('Title', 'Vocabulary', 'Term', 'Author', 'Status', 'Updated', 'Operations');
-   $rows = array();
 
    // For each entity retrieved add a row to the data listing.
    //while ($entity = $entities->fetchObject()) {
@@ -254,11 +351,15 @@ function tripal_view_entity($entity, $view_mode = 'full') {
      // We don't need all of the attached fields for an entity so, we'll
      // not use the entity_load() function.  Instead just pull it from the
      // database table.
-     $entity = db_select('tripal_entity', 'TE')
-       ->fields('TE')
-       ->condition('TE.id', $entity_id)
-       ->execute()
-       ->fetchObject();
+     $equery = db_select('tripal_entity', 'TE');
+     $equery->join('tripal_bundle', 'TB', 'TE.bundle = TB.name');
+     $equery->fields('TB', array('label'));
+     $equery->fields('TE');
+     $equery->condition('TE.id', $entity_id);
+     $entity = $equery->execute()->fetchObject();
+     if (!$entity) {
+       continue;
+     }
 
      // Get the term
      $term = entity_load('TripalTerm', array('id' => $entity->term_id));
@@ -272,12 +373,11 @@ function tripal_view_entity($entity, $view_mode = 'full') {
 
      // Retrieve details about the user who created this data.
      $author = user_load($entity->uid);
-
      // Add information to the table.
      $rows[] = array(
        l($entity->title, 'bio_data/' . $entity->id),
-       $vocabulary,
-       $term_name,
+       $entity->label,
+       $vocabulary . ':' . $term_name,
        l($author->name, 'user/' . $entity->uid),
        $entity->status == 1 ? 'published' : 'unpublished',
        format_date($entity->changed, 'short'),
@@ -330,6 +430,16 @@ function tripal_view_entity($entity, $view_mode = 'full') {
    // Always just rebuild the form on submit.  that will update the
    // result table using the filters provided.
    $form_state['rebuild'] = TRUE;
+
+   // Save the current user filter settings.
+   if ($form_state['clicked_button']['#name'] == 'filter' or
+       $form_state['clicked_button']['#name'] == 'refine') {
+     $_SESSION['tripal_content_overview']['type'] = array_key_exists('type', $form_state['values']) ? $form_state['values']['type'] : '';
+     $_SESSION['tripal_content_overview']['status'] = array_key_exists('status', $form_state['values']) ? $form_state['values']['status'] : '';
+   }
+   if ($form_state['clicked_button']['#name'] == 'reset') {
+     unset($_SESSION['tripal_content_overview']);
+   }
  }
 
  /**

+ 2 - 3
tripal/includes/TripalFieldQuery.inc

@@ -9,8 +9,7 @@ class TripalFieldQuery extends EntityFieldQuery {
   protected $field_storage = array();
 
   public function execute() {
-
-    // Give a chance to other modules to alter the query.
+    // Give a chance for other modules to alter the query.
     drupal_alter('entity_query', $this);
     $this->altered = TRUE;
 
@@ -29,6 +28,7 @@ class TripalFieldQuery extends EntityFieldQuery {
 
       // Initialize the results array.
       $results = array();
+      dpm($this->field_storage);
 
       // Iterate through the field storage types and call each one.
       foreach ($this->field_storage as $storage_type => $storage_module) {
@@ -60,7 +60,6 @@ class TripalFieldQuery extends EntityFieldQuery {
     else {
       $results = call_user_func($this->queryCallback(), $this);
     }
-
     if ($results and $this->count) {
       return $results;
     }

+ 16 - 18
tripal/includes/tripal.entity.inc

@@ -277,9 +277,6 @@ function tripal_form_tripal_entity_form_alter(&$form, &$form_state, $form_id) {
  * Here we want to overwite unattached fields with a div box that will be
  * recognized by JavaScript that will then use AJAX to load the field.
  *
- * We also want to add tooltips to each field that describes to the user
- * the meaning of the field.
- *
  * The tripal_ajax_attach_field() function is called by an AJAX call to
  * retrieve the field.
  */
@@ -306,21 +303,22 @@ function tripal_entity_view($entity, $type, $view_mode, $langcode) {
           $entity->content[$child_name]['#suffix'] .= '</div>';
         }
 
-        $matches = array();
-        if (array_key_exists('term_vocabulary', $instance['settings'])) {
-          $vocabulary = $instance['settings']['term_vocabulary'];
-          $accession = $instance['settings']['term_accession'];
-          $term = tripal_get_term_details($vocabulary, $accession);
-          if ($term) {
-            $tooltip_img = url(drupal_get_path('module', 'tripal') . '/theme/images/info.gif');
-            $tooltip_text = $term['definition'] ? $term['definition'] : $term['name'];
-            $entity->content[$child_name]['#prefix'] .= '' .
-              '<div class="tripal-tooltip">' .
-                '<img src="' . $tooltip_img . '">' .
-                '<div class="tripal-tooltiptext">' . $tooltip_text . '</div>' .
-              '</div>';
-          }
-        }
+        // Add tooltip to each item.
+//         $matches = array();
+//         if (array_key_exists('term_vocabulary', $instance['settings'])) {
+//           $vocabulary = $instance['settings']['term_vocabulary'];
+//           $accession = $instance['settings']['term_accession'];
+//           $term = tripal_get_term_details($vocabulary, $accession);
+//           if ($term) {
+//             $tooltip_img = url(drupal_get_path('module', 'tripal') . '/theme/images/info.gif');
+//             $tooltip_text = $term['definition'] ? $term['definition'] : $term['name'];
+//             $entity->content[$child_name]['#prefix'] .= '' .
+//               '<div class="tripal-tooltip">' .
+//                 '<img src="' . $tooltip_img . '">' .
+//                 '<div class="tripal-tooltiptext">' . $tooltip_text . '</div>' .
+//               '</div>';
+//           }
+//         }
       }
     }
   }

+ 2 - 2
tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship_widget.inc

@@ -368,7 +368,7 @@ class sbo__relationship_widget extends ChadoFieldWidget {
     }
 
     // Do not proceed if subject ID or object ID does not exist
-    if (!key_exists('subject_id', $fkeys[$base_table]['columns']) || 
+    if (!key_exists('subject_id', $fkeys[$base_table]['columns']) ||
         !key_exists('object_id', $fkeys[$base_table]['columns'])) {
       return;
     }
@@ -382,7 +382,7 @@ class sbo__relationship_widget extends ChadoFieldWidget {
     else {
       $values = array('uniquename' => $subject_name);
       $subject = chado_select_record($base_table, array($fkey_rcolumn), $values);
-      if(count($subject) > 0) {dpm($subject);
+      if(count($subject) > 0) {
         $subject_id = $subject[0]->$fkey_rcolumn;
       }
     }

+ 68 - 62
tripal_chado/includes/tripal_chado.field_storage.inc

@@ -477,80 +477,86 @@ function tripal_chado_field_storage_query($query) {
     }
   } // end foreach ($query->fieldConditions as $index => $condition) {
 
-  // Now get the list for sorting.
-  foreach ($query->order as $index => $sort) {
-    // We only handle ordering by field type here.
-    if ($sort['type'] != 'field') {
-      continue;
-    }
+  // Now join with the chado_entity table to get published records only.
+  $cquery->join('chado_entity', 'CE', "CE.record_id = base.$pkey");
+  $cquery->join('tripal_entity', 'TE', "CE.entity_id = TE.id");
+  $cquery->fields('CE', array('entity_id'));
+  $cquery->fields('TE', array('bundle'));
+  $cquery->condition('CE.data_table', $data_table);
+  if (array_key_exists('start', $query->range)) {
+    $cquery->range($query->range['start'], $query->range['length']);
+  }
 
-    $field = $sort['specifier']['field'];
-    $field_type = $field['type'];
-    $field_name = $field['field_name'];
+  // Now set any ordering.
+  foreach ($query->order as $index => $sort) {
+    // Add in property ordering.
+    if ($order['type'] == 'property') {
 
-    // Skip sorts that don't belong to this storage type.
-    if ($field['storage']['type'] != 'field_chado_storage') {
-      continue;
     }
-    $column = $sort['specifier']['column'];
-    $direction = $sort['direction'];
+    // Add in filter ordering
+    if ($sort['type'] == 'field') {
 
-    // The Chado settings for a field are part of the instance and each bundle
-    // can have the same field but with different Chado mappings. Therefore,
-    // we need to iterate through the bundles to get the field instances.
-    foreach ($field['bundles']['TripalEntity'] as $bundle_name) {
+      $field = $sort['specifier']['field'];
+      $field_type = $field['type'];
+      $field_name = $field['field_name'];
 
-      // If there is a bundle filter for the entity and if the field is not
-      // associated with the bundle then skip it.
-      if (array_key_exists('bundle', $query->entityConditions)) {
-        if (strtolower($query->entityConditions['bundle']['operator']) == 'in' and
-            !array_key_exists($bundle_name, $query->entityConditions['bundle']['value'])) {
-          continue;
-        }
-        else if ($query->entityConditions['bundle']['value'] != $bundle_name) {
-          continue;
-        }
+      // Skip sorts that don't belong to this storage type.
+      if ($field['storage']['type'] != 'field_chado_storage') {
+        continue;
       }
+      $column = $sort['specifier']['column'];
+      $direction = $sort['direction'];
+
+      // The Chado settings for a field are part of the instance and each bundle
+      // can have the same field but with different Chado mappings. Therefore,
+      // we need to iterate through the bundles to get the field instances.
+      foreach ($field['bundles']['TripalEntity'] as $bundle_name) {
+
+        // If there is a bundle filter for the entity and if the field is not
+        // associated with the bundle then skip it.
+        if (array_key_exists('bundle', $query->entityConditions)) {
+          if (strtolower($query->entityConditions['bundle']['operator']) == 'in' and
+              !array_key_exists($bundle_name, $query->entityConditions['bundle']['value'])) {
+            continue;
+          }
+          else if ($query->entityConditions['bundle']['value'] != $bundle_name) {
+            continue;
+          }
+        }
 
-      // See if there is a ChadoField class for this instance. If not then do
-      // our best to order the field.
-      $instance = field_info_instance('TripalEntity', $field_name, $bundle_name);
-      if (tripal_load_include_field_class($field_type)) {
-        $field_obj = new $field_type($field, $instance);
-        $field_obj->queryOrder($cquery, array('column' => $column, 'direction' => $direction));
-      }
-      // There is no class so do our best to order the data by this field
-      else {
-        $base_table = $instance['settings']['base_table'];
-        $chado_table = $instance['settings']['chado_table'];
-        $table_column = tripal_get_chado_semweb_column($chado_table, $column);
-        if ($table_column) {
-           if ($chado_table == $base_table) {
-             $cquery->orderBy('base.' . $table_column, $direction);
-           }
-           else {
-             // TODO: how do we handle a field that doesn't map to the base table.
-             // We would expect that all of these would be custom field and
-             // the ChadoField::queryOrder() function would be implemented.
-           }
+        // See if there is a ChadoField class for this instance. If not then do
+        // our best to order the field.
+        $instance = field_info_instance('TripalEntity', $field_name, $bundle_name);
+        if (tripal_load_include_field_class($field_type)) {
+          $field_obj = new $field_type($field, $instance);
+          $field_obj->queryOrder($cquery, array('column' => $column, 'direction' => $direction));
         }
+        // There is no class so do our best to order the data by this field
         else {
-          // TODO: handle when the name can't be matched to a table column.
+          $base_table = $instance['settings']['base_table'];
+          $chado_table = $instance['settings']['chado_table'];
+          $table_column = tripal_get_chado_semweb_column($chado_table, $column);
+          if ($table_column) {
+             if ($chado_table == $base_table) {
+               $cquery->orderBy('base.' . $table_column, $direction);
+             }
+             else {
+               // TODO: how do we handle a field that doesn't map to the base table.
+               // We would expect that all of these would be custom field and
+               // the ChadoField::queryOrder() function would be implemented.
+             }
+          }
+          else {
+            // TODO: handle when the name can't be matched to a table column.
+          }
         }
-      }
-    }
-  }
+      } // end foreach ($field['bundles']['TripalEntity'] as $bundle_name) {
+    } // end if ($sort['type'] == 'field') {
+  } // end foreach ($query->order as $index => $sort) {
 
-  // Now join with the chado_entity table to get published records only.
-  $cquery->join('chado_entity', 'CE', "CE.record_id = base.$pkey");
-  $cquery->join('tripal_entity', 'TE', "CE.entity_id = TE.id");
-  $cquery->fields('CE', array('entity_id'));
-  $cquery->fields('TE', array('bundle'));
-  $cquery->condition('CE.data_table', $data_table);
-  if (array_key_exists('start', $query->range)) {
-    $cquery->range($query->range['start'], $query->range['length']);
-  }
+dpm($cquery);
   $records = $cquery->execute();
+  dpm($records);
 
   $result = array();
   while ($record = $records->fetchObject()) {