We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 22770
    • 285 Posts
    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.
      • 10449
      • 956 Posts
      Nice. By the way, there is a shorter way to write
      $alphabet = array("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");

      $ABC = range("A", "Z");
      will do the same smiley

        • 20991
        • 99 Posts
        Oh spit! I think this is part of what I need for my members array I was desiring to figure out. Thanks, man!
          NOTE TO SELF: http://www.muddydogpaws.com/development/wayfinder/examples/example-1.html for all your navigational questions.
          • 22770
          • 285 Posts
          Quote from: ganeshXL at Nov 07, 2007, 11:37 AM

          Nice. By the way, there is a shorter way to write
          $alphabet = array("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");

          $ABC = range("A", "Z");
          will do the same smiley


          Cool. I never knew that. Thanks.
            • 22770
            • 285 Posts
            Okay, I’ve just updated the snippet because I’d done a stupid edit to it just before I posted it that broke it, and I’d forgotten to test it. It’s now working, though.

            nate22: hope it’s useful to you. Let me know if you make any improvements.