示例#1
0
 /**
  * @param $pa_hits Array of row_ids to sort. *MUST HAVE row_ids AS KEYS, NOT VALUES*
  */
 public function sortHits($pa_hits, $ps_field, $ps_direction = 'asc', $pa_options = null)
 {
     if (!in_array(strtolower($ps_direction), array('asc', 'desc'))) {
         $ps_direction = 'asc';
     }
     if (!is_array($pa_hits) || !sizeof($pa_hits)) {
         return $pa_hits;
     }
     $vs_search_tmp_table = $this->loadListIntoTemporaryResultTable($pa_hits, $pa_options['search']);
     $t_table = $this->opo_datamodel->getInstanceByTableNum($this->opn_tablenum, true);
     $vs_table_pk = $t_table->primaryKey();
     $vs_table_name = $this->ops_tablename;
     $va_fields = explode(';', $ps_field);
     $va_sorted_hits = array();
     $vn_num_locales = ca_locales::numberOfCataloguingLocales();
     foreach ($va_fields as $vs_field) {
         $va_joins = $va_orderbys = array();
         $vs_locale_where = $vs_is_preferred_sql = '';
         $va_tmp = explode('.', $vs_field);
         // Rewrite for <table>.preferred_labels.* syntax
         if ($va_tmp[1] == 'preferred_labels') {
             if ($t_labeled_item_table = $this->opo_datamodel->getInstanceByTableName($va_tmp[0], true)) {
                 if ($t_label_table = $t_labeled_item_table->getLabelTableInstance()) {
                     $va_tmp2 = array($t_label_table->tableName());
                     if (isset($va_tmp[2]) && $t_label_table->hasField($va_tmp[2])) {
                         $va_tmp2[] = $va_tmp[2];
                     } else {
                         $va_tmp2[] = $t_labeled_item_table->getLabelDisplayField();
                     }
                     $va_tmp = $va_tmp2;
                     $vs_field = join(".", $va_tmp);
                 }
             }
         }
         if ($va_tmp[0] == $vs_table_name) {
             //
             // sort field is in search table
             //
             if (!$t_table->hasField($va_tmp[1])) {
                 //
                 // is it an attribute?
                 //
                 $t_element = new ca_metadata_elements();
                 $vs_sort_element_code = array_pop($va_tmp);
                 if ($t_element->load(array('element_code' => $vs_sort_element_code))) {
                     $vn_element_id = $t_element->getPrimaryKey();
                     if (!($vs_sortable_value_fld = Attribute::getSortFieldForDatatype($t_element->get('datatype')))) {
                         return $pa_hits;
                     }
                     if ((int) $t_element->get('datatype') == 3) {
                         $vs_sortable_value_fld = 'lil.name_plural';
                         $vs_sort_field = array_pop(explode('.', $vs_sortable_value_fld));
                         $vs_locale_where = $vn_num_locales > 1 ? ', lil.locale_id' : '';
                         $vs_sql = "\n\t\t\t\t\t\t\t\tSELECT attr.row_id, lil.locale_id, lower({$vs_sortable_value_fld}) {$vs_sort_field}\n\t\t\t\t\t\t\t\tFROM ca_attributes attr\n\t\t\t\t\t\t\t\tINNER JOIN ca_attribute_values AS attr_vals ON attr_vals.attribute_id = attr.attribute_id\n\t\t\t\t\t\t\t\tINNER JOIN ca_list_item_labels AS lil ON lil.item_id = attr_vals.item_id\n\t\t\t\t\t\t\t\tINNER JOIN {$vs_browse_tmp_table} ON {$vs_browse_tmp_table}.row_id = attr.row_id\n\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t(attr_vals.element_id = ?) AND (attr.table_num = ?) AND (lil.{$vs_sort_field} IS NOT NULL)\n\t\t\t\t\t\t\t\tORDER BY lil.{$vs_sort_field}\n\t\t\t\t\t\t\t";
                     } else {
                         $vs_sortable_value_fld = 'attr_vals.' . $vs_sortable_value_fld;
                         $vs_sort_field = array_pop(explode('.', $vs_sortable_value_fld));
                         $vs_locale_where = $vn_num_locales > 1 ? 'attr.locale_id' : '';
                         $vs_sql = "\n\t\t\t\t\t\t\t\tSELECT attr.row_id, attr.locale_id, lower({$vs_sortable_value_fld}) {$vs_sort_field}\n\t\t\t\t\t\t\t\tFROM ca_attributes attr\n\t\t\t\t\t\t\t\tINNER JOIN ca_attribute_values AS attr_vals ON attr_vals.attribute_id = attr.attribute_id\n\t\t\t\t\t\t\t\tINNER JOIN {$vs_search_tmp_table} ON {$vs_search_tmp_table}.row_id = attr.row_id\n\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t(attr_vals.element_id = ?) AND (attr.table_num = ?) AND (attr_vals.{$vs_sort_field} IS NOT NULL)\n\t\t\t\t\t\t\t\tORDER BY attr_vals.{$vs_sort_field}\n\t\t\t\t\t\t\t";
                         //print $vs_sql." ; $vn_element_id/; ".$this->opn_tablenum."<br>";
                     }
                     $qr_sort = $this->opo_db->query($vs_sql, (int) $vn_element_id, (int) $this->opn_tablenum);
                     while ($qr_sort->nextRow()) {
                         $va_row = $qr_sort->getRow();
                         if (!$va_row['row_id']) {
                             continue;
                         }
                         if ($vn_num_locales > 1) {
                             $va_sorted_hits[$va_row['row_id']][$va_row['locale_id']] .= trim(str_replace(array("'", '"'), array('', ''), $va_row[$vs_sort_field]));
                         } else {
                             $va_sorted_hits[$va_row['row_id']] .= trim(str_replace(array("'", '"'), array('', ''), $va_row[$vs_sort_field]));
                         }
                         unset($pa_hits[$va_row['row_id']]);
                     }
                     // Add on hits that aren't sorted because they don't have an attribute associated
                     foreach ($pa_hits as $vn_id => $va_row) {
                         if (!is_array($va_row)) {
                             $va_row = array();
                         }
                         if ($vn_num_locales > 1) {
                             $va_sorted_hits[$vn_id][1] = $va_row;
                         } else {
                             $va_sorted_hits[$vn_id] = $va_row;
                         }
                     }
                 }
                 continue;
             } else {
                 $va_field_info = $t_table->getFieldInfo($va_tmp[1]);
                 if ($va_field_info['START'] && $va_field_info['END']) {
                     $va_orderbys[] = $va_field_info['START'] . ' ' . $ps_direction;
                     $va_orderbys[] = $va_field_info['END'] . ' ' . $ps_direction;
                 } else {
                     $va_orderbys[] = $vs_field . ' ' . $ps_direction;
                 }
                 if ($t_table->hasField('locale_id')) {
                     $vs_locale_where = ", " . $vs_table_name . ".locale_id";
                 }
                 $vs_sortable_value_fld = $vs_field;
             }
         } else {
             // sort field is in related table
             $va_path = $this->opo_datamodel->getPath($vs_table_name, $va_tmp[0]);
             if (sizeof($va_path) > 2) {
                 // many-many
                 $vs_last_table = null;
                 // generate related joins
                 foreach ($va_path as $vs_table => $va_info) {
                     $t_table = $this->opo_datamodel->getInstanceByTableName($vs_table, true);
                     if (!$vs_last_table) {
                         //$va_joins[$vs_table] = "INNER JOIN ".$vs_table." ON ".$vs_table.".".$t_table->primaryKey()." = ca_sql_search_search_final.row_id";
                     } else {
                         $va_rels = $this->opo_datamodel->getOneToManyRelations($vs_last_table, $vs_table);
                         if (!sizeof($va_rels)) {
                             $va_rels = $this->opo_datamodel->getOneToManyRelations($vs_table, $vs_last_table);
                         }
                         if ($vs_table == $va_rels['one_table']) {
                             $va_joins[$vs_table] = "INNER JOIN " . $va_rels['one_table'] . " ON " . $va_rels['one_table'] . "." . $va_rels['one_table_field'] . " = " . $va_rels['many_table'] . "." . $va_rels['many_table_field'];
                         } else {
                             $va_joins[$vs_table] = "INNER JOIN " . $va_rels['many_table'] . " ON " . $va_rels['many_table'] . "." . $va_rels['many_table_field'] . " = " . $va_rels['one_table'] . "." . $va_rels['one_table_field'];
                         }
                     }
                     $t_last_table = $t_table;
                     $vs_last_table = $vs_table;
                 }
                 $va_orderbys[] = $vs_field . ' ' . $ps_direction;
                 $vs_sortable_value_fld = $vs_field;
             } else {
                 $va_rels = $this->opo_datamodel->getRelationships($vs_table_name, $va_tmp[0]);
                 if (!$va_rels) {
                     return $pa_hits;
                 }
                 // return hits unsorted if field is not valid
                 $t_rel = $this->opo_datamodel->getInstanceByTableName($va_tmp[0], true);
                 if (!$t_rel->hasField($va_tmp[1])) {
                     return $pa_hits;
                 }
                 $va_joins[$va_tmp[0]] = 'LEFT JOIN ' . $va_tmp[0] . ' ON ' . $vs_table_name . '.' . $va_rels[$vs_table_name][$va_tmp[0]][0][0] . ' = ' . $va_tmp[0] . '.' . $va_rels[$vs_table_name][$va_tmp[0]][0][1] . "\n";
                 $va_orderbys[] = $vs_field . ' ' . $ps_direction;
                 // if the related supports preferred values (eg. *_labels tables) then only consider those in the sort
                 if ($t_rel->hasField('is_preferred')) {
                     $vs_is_preferred_sql = " " . $va_tmp[0] . ".is_preferred = 1";
                 }
                 if ($t_rel->hasField('locale_id')) {
                     $vs_locale_where = ", " . $va_tmp[0] . ".locale_id";
                 }
                 $vs_sortable_value_fld = $vs_field;
             }
         }
         //
         // Grab values and index for sorting later
         //
         $va_tmp = explode('.', $vs_sortable_value_fld);
         $vs_sort_field = array_pop($va_tmp);
         $vs_join_sql = join("\n", $va_joins);
         $vs_sql = "\n\t\t\t\tSELECT {$vs_table_name}.{$vs_table_pk}{$vs_locale_where}, lower({$vs_sortable_value_fld}) {$vs_sort_field}\n\t\t\t\tFROM {$vs_table_name}\n\t\t\t\t{$vs_join_sql}\n\t\t\t\tINNER JOIN {$vs_search_tmp_table} ON {$vs_search_tmp_table}.row_id = {$vs_table_name}.{$vs_table_pk}\n\t\t\t\t" . ($vs_is_preferred_sql ? 'WHERE' : '') . "\n\t\t\t\t\t{$vs_is_preferred_sql}\n\t\t\t";
         //print $vs_sql;
         $qr_sort = $this->opo_db->query($vs_sql);
         while ($qr_sort->nextRow()) {
             $va_row = $qr_sort->getRow();
             if (!($vs_sortable_value = str_replace(array("'", '"'), array('', ''), $va_row[$vs_sort_field]))) {
                 $vs_sortable_value = '';
             }
             if ($vn_num_locales > 1 && $vs_locale_where) {
                 $va_sorted_hits[$va_row[$vs_table_pk]][$va_row['locale_id']] .= $vs_sortable_value;
             } else {
                 $va_sorted_hits[$va_row[$vs_table_pk]] .= $vs_sortable_value;
             }
         }
     }
     //
     // Actually sort the hits here...
     //
     if ($vn_num_locales > 1 && $vs_locale_where) {
         $va_sorted_hits = caExtractValuesByUserLocale($va_sorted_hits);
     }
     asort($va_sorted_hits, SORT_STRING);
     if ($ps_direction == 'desc') {
         $va_sorted_hits = array_reverse($va_sorted_hits, true);
     }
     $this->cleanupTemporaryResultTable();
     return $va_sorted_hits;
 }