Xaraya: Impose Your Will on Pubtype Sorting 09.14.2005

Article Summary

Sometimes you don't want to sort by publication date or article title. Take advantage of Xaraya's flexibility to sort publications the way you want.

The Problem: The events listings at TAMU Sigmas are just like any other list of events; in order to display them in a logical order, they need to be displayed chronologically according to the date on which the event will occur. Unfortunately, this date is rarely ever the date the event was published, so it doesn't make any sense to sort them by publication date.

A Preliminary Solution

In the administration interface for Xaraya's Articles module, you can specify which field you want each publication type to be sorted by. Note: Xaraya currently does not support sorting by dynamic data fields, therefore you can only sort by the default publication type fields (Summary, Notes, Body, Pubdate, Author). In my setup, I'm using the Summary field to store a beginning and ending date for each event, so I need to sort by this field.

  1. Log into the Administration section of your Xaraya installation.
  2. Go to the administration area for the Articles module.
  3. Click on the "Publication Types" option in the Articles administration menu.
  4. Click on the "Article Config" link next to the publication type you want to alter.
  5. On the resulting page, search for the dropdown list labeled "Default sort order." Select the field you want to sort by from this list (in my case, the selection is set to Summary).

So That Didn't Work?

This preliminary solution works fine if you want to sort in descending order, or if you want to sort the field as a string, but what if you want to sort in ascending order? What if you need to sort a field by its integer value rather than its value as a string?

Sorting in Ascending or Descending Order
By default, the Publication Date field is sortable either way, but what of the other fields? Unfortunately, a bit of hacking is required to get this to work for the other fields. Locate the file modules/articles/xartemplates/admin-modifyconfig.xd in your Xaraya installation and open it up in your HTML editor of choice. Note that you can't override this file by placing a copy with a .xt extension in your theme directory, so it's necessary to edit the original .xd file). Somewhere near line 200 of this file, you'll see the following lines: <label for="defaultsort"> <xar:mlstring> Default sort order </xar:mlstring> </label> Immediately proceeding these lines, you'll see some code for a dropdown list. These are the items that show up in the dropdown list for "Default Sort Order" in the "Article Config" for a publication type. At the end of this list (within the closing tag of the select element), you can add your own sort options (make sure you create a backup of the original file before editing, in case things don't go as expected). Following my example, I needed to sort the summary field (containing the starting times for events) in descending order, so I added the following code to the end of the list (starting around line 345): <xar:if condition="$defaultsort eq 'summary DESC'"> <xar:else /> </xar:if> The first conditional <xar:if condition="$defaultsort eq 'summary DESC'"> allows for this particular option in the select element to be selected by default if it matches the current sort order. Essentially, if the sort order is set to "summary DESC", then this is the option that will appear by default when the page is loaded. Otherwise, one of the other options will be displayed by default. The string 'summary DESC' is the important thing to notice here. If you look at line 290, you'll see (for the sake of comparison): <xar:if condition="$defaultsort eq 'summary'"> <xar:else /> </xar:if> Just by appending the string DESC to the end of the value in the option element, you are able to change the default sort order from ascending to descending. You can add as many different sorting options as necessary for your publication types by copying, editing, and appending this code over and over. Nonetheless, even with this bit of hackery, there still remained one problem…
Sorting Fields by Integer Value

One of the problems with being limited to the default fields for sorting is that only a single field (publication date) is sorted as an integer value. All other fields are sorted as strings. At first this doesn't seem like such a bad thing, but a quick example will show the downside of this situation.

Lets say you have a field that stores numbers. One field has 1000 as a value, while another has 200 as a value. If the field is sorted as a string in ascending order, 1000 will end up preceding 200 in the list.

Why is this? Well, the explanation is outside the scope of this article, nonetheless a solution does indeed exist.

Pertinent to my situation with the TAMU Sigmas website, this phenomenon occurs with the date/time stamp stored in the Summary field for the Events section. The date/time stamp is stored as an integer, and trying to sort the value as a string (which Xaraya does by default as mentioned above) results in unexpected behavior this section.

Xaraya currently doesn't have any capability in its administration interface to handle such a situation, so the only way to solve it is to hack the Xaraya source code. Thanks to some assistance from the Xaraya newsgroups, I discovered that by adding a CAST function to the file modules/articles/userapi/getall.php, the field can be converted to an integer on-the-fly, which solves the problem rather nicely.

Immediately after the following code snippet starting near line 281 in modules/articles/userapi/getall.php:

if ($criteria == 'title') {
    $sortparts[] = $articlesdef['title'] . ' ' . (!empty($sortorder) ? $sortorder : 'ASC');
} elseif ($criteria == 'pubdate' || $criteria == 'date') {
    $sortparts[] = $articlesdef['pubdate'] . ' ' . (!empty($sortorder) ? $sortorder : 'DESC');
} elseif ($criteria == 'hits' && !empty($hitcountdef['hits'])) {
    $sortparts[] = $hitcountdef['hits'] . ' ' . (!empty($sortorder) ? $sortorder : 'DESC');
} elseif ($criteria == 'rating' && !empty($ratingsdef['rating'])) {
    $sortparts[] = $ratingsdef['rating'] . ' ' . (!empty($sortorder) ? $sortorder : 'DESC');
} elseif ($criteria == 'author' && !empty($usersdef['name'])) {
    $sortparts[] = $usersdef['name'] . ' ' . (!empty($sortorder) ? $sortorder : 'ASC');
} elseif ($criteria == 'aid') {
    $sortparts[] = $articlesdef['aid'] . ' ' . (!empty($sortorder) ? $sortorder : 'ASC');
    $seenaid = 1;

…I inserted the following code (make sure you create a backup of the original file before editing it in case you make a mistake and need to roll back):

} elseif ($criteria == 'summary' && !empty($articlesdef['summary'])) {
    $sortparts[] = 'CAST(' . $articlesdef['summary'] . ' AS UNSIGNED)' . ' ' . (!empty($sortorder) ? $sortorder : 'ASC');

Essentially, what's happening here is a group of conditionals are being used to build up a string that will be sent to the server as an SQL query. This particular part of the string specifies how the recordset that is returned by the query is sorted. In this case, the code I've inserted specifically handles the case in which the field to be sorted is the Summary field.

The CAST statement is used here to convert the strings stored in the Summary field to unsigned integers. If either of the sort order statements ASC or DESC are specified, then they will be appended to the SQL statement. Otherwise, by default, the recordset is sorted in ascending order.

Mission Accomplished

I hope that with the information given in this article, you've learned enough to adapt your own publication types to suit whatever situations needed (well, at least as far as sorting is concerned). Experiment even more, and you'll find even more useful ways to use this information. Good luck!