This is a simple snippet based on Garry Nutting’s A to Z Listing snippet. Unlike that snippet, this lists all the results on a single page, with anchors for each letter of the alphabet and links to them from the top of the page. It uses ditto to display the output, and you can use ditto’s templating system. You can sort the documents by any of the content fields, and you can use a single basic ditto filter to exclude certain documents.
Here’s the snippet:
<?php
//This snippet lists records alphabetically, with an A to Z header of links to anchors in the text.
//Can sort by any content field, but not by template variables.
//Can filter by any content field or template variable.
//simple use:
//[!atozList? &parents=`6` &listTpl=`atozStaff`!]
//Required fields: &parents and &listTpl
//Optional fields: &sortby &alphabetHeadingSeparator &alphabetHeadingStart &alphabetHeadingEnd &filter &noResults
$alphabet = range("A", "Z");
//Sets the field to sort by. Can't currently use template variables.
$atozSortBy = (isset($sortby)) ? stripslashes($sortby) : 'pagetitle';
//Separate the a-to-z headings.
$atozAlphabetHeadingSeparator = (isset($alphabetHeadingSeparator)) ? $alphabetHeadingSeparator : ' | ';
//a-to-z headings start
$atozAlphabetHeadingStart = (isset($alphabetHeadingStart)) ? $alphabetHeadingStart : '<p>';
//a-to-z headings end
$atozAlphabetHeadingEnd = (isset($alphabetHeadingEnd)) ? $alphabetHeadingEnd : '</p>';
//a-to-z list chunk template. Ditto template
$atozListChunkTpl = (isset($listTpl)) ? $listTpl : '';
//ids of subfolders whose documents will be processed.
$parents = (isset ($parents)) ? stripslashes($parents) : '';
//A single basic ditto filter to exclude.
$filter = (isset ($filter)) ? stripslashes($filter) : '';
//Message to return if no results.
$noResults = (isset ($noResults)) ? stripslashes($noResults) : '';
//If parent folders are defined, continue. Otherwise, do nothing at all!
if (trim($parents) != '') {
//This is the table that contains the document information
$content_table = $modx->getFullTableName("site_content");
//This is the table that contains the values of template variables
$tv_content_table = $modx->getFullTableName("site_tmplvar_contentvalues");
//This is the table that contains the actual template variables
$tv_table = $modx->getFullTableName("site_tmplvars");
if(!empty($filter)) {
$filterArray = explode(',', $filter);
//Find all the field names in the site_content table, so we can identify whether filter relates to a content field or a template variable.
$fields_result = $modx->db->query("SELECT * FROM ". $content_table);
$numberfields = mysql_num_fields($fields_result);
$content_field=FALSE;
for ($i=0; $i<$numberfields ; $i++ ) {
if(trim($filterArray[0])==mysql_field_name($fields_result, $i)){
$content_field=TRUE;
}
}
$filterValue = $filterArray[1];
if(trim($filterArray[2])=='1') {
$condition='=';
}elseif(trim($filterArray[2])=='2') {
$condition='!=';
}elseif(trim($filterArray[2])=='3') {
$condition='>=';
}elseif(trim($filterArray[2])=='4') {
$condition='<=';
}elseif(trim($filterArray[2])=='5') {
$condition='>';
}elseif(trim($filterArray[2])=='6') {
$condition='<';
}elseif(trim($filterArray[2])=='7') {
$condition=' LIKE ';
$filterValue='%'.$filterValue.'%';
}elseif(trim($filterArray[2])=='8') {
$condition=' NOT LIKE ';
$filterValue='%'.$filterValue.'%';
}else{
$condition='='; //Default to equals, to avoid errors
}
$filterValue = "'".$filterValue."'";
}
//First we are going to make a list of parent folders for a MySQL WHERE
//split out the parent values
$startArray = explode(',', $parents);
//loop through each start id and concatenate to list parent folders for database query
$parent_folders = '';
foreach ($startArray as $parentid) {
$parent_folders .= 'parent=' . $parentid . ' OR ';
}
$parent_folders = substr($parent_folders, 0, -4);
//Ensure only published documents that aren't folders are displayed
$conditional_where = ' AND published=1 AND deleted=0 AND privateweb=0 AND isfolder=0';
//Select the pagetitles to have records to count
$content_select = 'pagetitle';
$documentId = $modx->documentIdentifier;
$alphabetHeadings = $atozAlphabetHeadingStart;
$output = '';
foreach($alphabet AS $value) {
//The where statement for the ditto call
$where = $atozSortBy . " LIKE '" . $value . "%'";
//Want to check if there are any records in the database that match, before we start the ditto call.
//First check if there is a filter. If so, see if the filter is on a content field or a template variable.
if(!empty($filter)){
if($content_field){
$full_where = $parent_folders . $conditional_where . " AND " . $where . " AND " . $filterArray[0] . $condition . $filterValue;
$contentResult = $modx->db->select($content_select, $content_table, $full_where, '', '');
$total_rows = $modx->db->getRecordCount( $contentResult );
} else {
//Query to see if there are any values of template variables that match the filter.
$total_rows = 0;
$select = $tv_content_table . ".`contentid` AS contentid";
$from = $tv_content_table . ", " . $tv_table . ", " . $content_table;
$full_where = $content_table . '.`id`=' . $tv_content_table . '.`contentid` AND ' . $tv_table . ".`id`=" . $tv_content_table . ".`tmplvarid` AND value" . $condition . $filterValue . " AND name='" . $filterArray[0] . "' AND " . $where;
$tvResult = $modx->db->select($select, $from, $full_where, '', '');
$number_rows = $modx->db->getRecordCount( $tvResult );
$document_where = "";
if($number_rows>0){
//If there are values of tvs that match the filter, see if there are any results that fit the appropriate A-Z
while($row=$modx->db->getRow($tvResult)) {
$document_where .= $content_table .".`id`=" . $row['contentid'] . " OR ";
}
$document_where = substr($document_where, 0, -4);
$full_where = $parent_folders . $conditional_where . " AND " . $where . " AND " . $document_where;
$contentResult = $modx->db->select($content_select, $content_table, $full_where, '', '');
$total_rows = $modx->db->getRecordCount( $contentResult );
}
}
}else{
$full_where = $parent_folders . $conditional_where . " AND " . $where;
$contentResult = $modx->db->select($content_select, $content_table, $full_where, '', '');
$total_rows = $modx->db->getRecordCount( $contentResult );
}
if($total_rows > 0) {
//Update the A-Z link list at top of page
$alphabetHeadings .= '<a href="'.$modx->makeUrl($documentId).'#jump_to_' . $value . '">' . $value . '</a>';
$alphabetHeadings .= $atozAlphabetHeadingSeparator;
$output .= "<p><a name=\"jump_to_$value\" id=\"jump_to_$value\"></a><strong>" . $value . "</strong></p>";
$output .= $modx->runSnippet("Ditto",array("parents" => "$parents", "display" => "all", "sortBy" => "$atozSortBy", "sortDir" => "ASC", "filter" => "$filter", "tpl" => "$atozListChunkTpl", "hideFolders" => "1", "where" => "$where"));
}
}
$separatorCount = strlen($atozAlphabetHeadingSeparator);
$alphabetHeadings = substr($alphabetHeadings, 0, -$separatorCount);
$alphabetHeadings .= $atozAlphabetHeadingEnd;
if($output) {
$output = $alphabetHeadings . $output;
return $output;
} else {
return $noResults;
}
}
?>
I offer this in case it’s useful to anyone else. I’m sure there are better, easier ways of doing this, but it seems to work. You could reasonably easily expand this to use more than one basic ditto filter and so on, but I haven’t needed to, so I haven’t tried.