We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 22851
    • 805 Posts
    That’s most likely because the latest official release contains a function definition in it called trimMe. When including the snippet twice on a page, the code defining the function gets executed twice. This generates a php error, resulting in the blank page.

    You can edit your snippet, wrapping the trimMe function definition with an
    if ( ! function_exists('trimMe') ) { ... }
    block, or you can simply use my modified snippet from the post previous to yours.

    Paul
      YAMS: Yet Another Multilingual Solution for MODx
      YAMS Forums | Latest: YAMS 1.1.9 | YAMS Documentation
      Please consider donating if you appreciate the time and effort spent developing and supporting YAMS.
      • 12379
      • 460 Posts
      Is there any way of formatting the output, via template chunk or other? I was hoping to have the date preceed the article title.


      [!ListIndexer?LIn_root=`184` &LIn_depth=`2` &LIn_mode=`short` &LIn_sort=`date` &LIn_sDesc=`false` &LIn_sQty=`4` $LIn_seeShowInMenu=`1`!]
        Mostly harmless.
        • 22851
        • 805 Posts
        Just had a quick glance at the code. It constructs and outputs the html directly rather than using templates and modx placeholders. Some ideas:

        One method of achieving what you want would be to modify the snippet, swapping over the relevant lines which output the date and description in the code.

        An alternative approach which doesn’t involve having to modify the snippet might be to try to achieve what you want using CSS. You’d do this by floating the LIn_date class to the right. (You might also need to give it a fixed width and display: block; and give the li elements a clear: right too, but I’m not sure without looking up the rules.)

        Finally, if you find you are needing finer control of the formatting of your lists, you could just use ditto instead. With ditto you can specify a template defining how the items are to be formatted.
          YAMS: Yet Another Multilingual Solution for MODx
          YAMS Forums | Latest: YAMS 1.1.9 | YAMS Documentation
          Please consider donating if you appreciate the time and effort spent developing and supporting YAMS.
          • 12379
          • 460 Posts
          Thanks, all good solutions. Probably go with the Ditto solution eventually, although the css would be another quick fix in the meantime.
            Mostly harmless.
            • 13577
            • 302 Posts
            Incidentally, I noticed [from my modx system events log] that the ne’re-do-wells of the world were using this snippet to try to exploit the reflect vulnerability. Clearly fixing ListIndexer is NOT the way to feel protected from this vulnerability, but just as clearly, knowing there’s a gap here should be a concern. The problem is uncleansed query string input in the code:

            $inFolder= isset($_GET['LIn_f'])? $_GET['LIn_f']: 0;
            if ((!$inFolder && $useFastUrls) || !$useFastUrls ){
            ...
            } else {
              $validParents = $_GET['LIn_f'];
            }
            

            Changing to this should help:

            $folders = strip_tags($_GET['LIn_f']);
            $folders = preg_replace('/[^d,]+/','',$folders);
            $folders = $folders ? $folders: 0;
            if ((!$folders && $useFastUrls) || !$useFastUrls ){
            ...
            } else {
              $validParents = $folders;
            }
            


            This would affect versions of ListIndexer at least as far back as 0.9a.
              Standard Disclaimer
              I could be totally wrong.
              • 16028
              • 15 Posts
              Thanks for creating this snippet. It is very effective. However, I’d like to know if anyone knows how I could simply modify the snippet to allow me to display links in the listings which point to pages the user doesn’t yet have access to due to their web_user role (not logged in or not set to the right user group).

              To explain, I want to be able to show links to what a user WOULD be able to access IF they had an account on the service. However, I don’t ALWAYS want to display those links in EVERY ListIndexer list.

              So, I want to modify the snippet to allow for one additional parameter, which is set to true or false through the snippet call. It should default to "false" (ie. don’t show links to pages for which the user has no access), but I should be able to set the parameter to "true" within the snippet call, for those ListIndexer lists where I DO want those links to show.

              Any help would really be appreciated. I think I can see how it could be done, but my programming skills are pretty limited, and it would probably take me hours upon hours to do what is probably a 5 minute edit to the snippet.
                • 32699 ☆ A M B ☆
                • 427 Posts
                W. Shawn Wilkerson Reply #17, 17 years ago
                I never got any email notifications this forum or snippet had been touched.

                I am re-creating my site, and during that task I started going over the snippets I have corrected, updated, enhanced, etc. When I got to this one, I noticed evolution had not included it, so I ended up here to see someone had actually kicked it up another notch.

                Per the license you are free to do what ever you want with the snippet. I only wished, that Evolution had included 1.03 or even 1.02.

                I will download the 1.03 version and merge it / clean it / whatever. I left a little junk in there so people could follow. The database calls have changed in evolution.


                As per the question (I know its way late -- but it is definitely a good one) on showing links to pages people are not allowed to. This snippet does that already. Just look for the hide / private/ menu/ published options.

                What would be even better, is a 1.04 version which will show the page titles but not make them links. Give me a few minutes to look at 1.03 and then add this functionality to it.
                  Get your copy of MODX Revolution Building the Web Your Way http://www.sanitypress.com/books/modx-revolution-building-the-web-your-way.html

                  Check out my MODX || xPDO resources here: http://www.shawnwilkerson.com
                  • 32699 ☆ A M B ☆
                  • 427 Posts
                  W. Shawn Wilkerson Reply #18, 17 years ago
                  I cleaned up the code a little bit as far as the comments are concerned.

                  The addition presented here is to allow the output to return a non linked list of page titles. For situations where you want people to see what is available, without letting them have access or a "join", "beg", or "complain" page.

                  <?php
                  /* File			Snippet: ListIndexer
                   * Created on	Oct 9, 2009
                   * Project		project_name
                   * @package		package_name
                   * @version		2
                   * @category	ModX Snippet
                   * @author		W. Shawn Wilkerson, Nashi Power
                   * @link		http://www.shawnwilkerson.com
                   * @license
                   */
                  
                  # PLEASE NOTE all parameters should be using backticks
                  # in final production [[ListIndexer?LIn_seeThru=`1`]]
                  # not [[ListIndexer?LIn_seeThru=1]]
                  
                  
                  /*
                   * Version 1.0.4
                   * Date: Oct 9, 2009
                   * 1.0.4 update by W. Shawn Wilkerson shawnwilkerson.com
                   * previous licensed recognized, upheld, and re issued
                   * Purpose: to allow the output to return a non linked list of page titles
                   * Specifically instead of <li><a href="mypage.html">My Page</a></li>
                   * 				returns <li>My Page</li>
                   * See LIn_removeLinks below.
                   */
                  
                  
                  /*
                   * Version 1.0.3
                   * Date: 20 Sep 2008
                   * 1.0.3 update by Paul at Nashi Power (http:#nashi.podzone.org/)
                   * Purpose: to allow the specification of a list of documents to be excluded.
                   * See LIn_exclude below.
                   */
                  
                  
                  /*
                   * Version 1.0.2
                   * Date 01 Aug 2008
                   * 1.0.2 update by W. Shawn Wilkerson shawnwilkerson.com
                   * previous licensed recognized, upheld, and re issued
                   *
                   * Added string length triming functionality for
                   * limiting the number of characters displayed
                   * in the link Title as well as in the Description.
                   *
                   * Added $LIn_ dateFormat to make the date format
                   * configurable via snippet call
                   *
                   * This new functionality will allow better control over
                   * page real estate, as well as over all the presentation
                   */
                  
                  /*
                   * Version: 1.0.1
                   * added in 1.0.1: hidePrivate (hide items from unauthorized users)
                   * Derived from ListIndex 0.6j by [email protected]
                   * Now supports Show In Menu
                   * This snippet was designed to be a VERY flexible way
                   * of showing what has been recently added. You can use
                   * this snippet to show news from one folder, or what has
                   * been recently added site wide. You can even show what's
                   * new in a 'section' (everything under a defined folder)!
                   *
                   */
                  
                  /*
                   * Version ListIndex 0.6j by [email protected]
                   */
                  
                  # Configuration Settings
                  
                  # Set the following snippet defaults the way you would normally
                  # use this snippet, then use snippet variables in other situations
                  # to override the default behaviors.
                  
                  # GENERAL OPTIONS
                  
                  # $rootFolder [ NULL | string (comma separated page id's) ]
                  # Decide which folder to pull recent documents from.
                  # If you want to specify a few folders, comma separate them.
                  # The default NULL will set current page as root. Using 0
                  # would search site wide. Can be set with snippet parameter
                  # $LIn_root like:
                  # [[ListIndexer?LIn_root=3,6,88]]
                  $rootFolder = NULL;
                  
                  # $descendentDepth [ int ]
                  # How many levels below the root folder(s) do you want to
                  # include? Can be overridden in snippet call with LIn_depth:
                  # [[ListIndexer?LIn_depth=2]]
                  # Uncomment one of these common two or create your own:
                  # $descendentDepth = 1; # just children of root folder(s)
                  $descendentDepth = 0; # all decendents of root folder(s)
                  
                  # $seeThruUnpub [ true | false ]
                  # When using descendents, do you want to consider files below
                  # an unpublished (hidden) folder? Usually no. But you decide.
                  # Snippet parameter: LIn_seeThru
                  # [[ListIndexer?LIn_seeThru=1]]
                  $seeThruUnpub = false;
                  
                  # $seeShowInMenu [ true | false ]
                  # When using descendents, do you want to consider files flagged
                  # to be hidden from the menus? Usually no. But you decide.
                  # Snippet parameter: LIn_seeShowInMenu
                  # [[ListIndexer?LIn_seeShowInMenu=1]]
                  $seeShowInMenu = false;
                  
                  # $hidePrivate [ true | false ]
                  # Hide items from users that don't have appropriate
                  # rights to view. Usually true. But you decide.
                  # Snippet parameter: LIn_hidePrivate
                  # [[ListIndexer?LIn_hidePrivate=0]]
                  $hidePrivate = true;
                  
                  # $mode [ 'short' | 'full' ]
                  # Defines whether this list should be a full, paged
                  # list of all documents, or a short list of the most
                  # recent few (how many will be defined next). Can be
                  # overridden in snippet call with $LIn_mode:
                  # [[ListIndexer?LIn_mode=full]]
                  $mode = 'short';
                  
                  # $sortBy [ 'alpha' | 'date' | 'menuindex' ]
                  # The default date will sort by most recent items first, but
                  # by using the 'alpha' option, and using full mode, you could
                  # use this to create an index, or directory.
                  # Settable with snippet call $LIn_sort:
                  # [[ListIndexer?LIn_sort=alpha]]
                  $sortBy = 'date';
                  
                  # $sortDir [ 'ASC' | 'DESC' ]
                  # Sort direction ascending or descending. Is applied to whatever $sortBy
                  # field you have chosen above. If left blank, menuindex and alpha will sort
                  # ASC and date DESC.
                  # $LIn_dir in snippet call:
                  # [[ListIndexer?LIn_dir=ASC&LIn_sortBy=menuindex]]
                  $sortDir = '';
                  
                  # $excludeIdList [ NULL | string (comma separated page id's) ]
                  # A comma separated list of document ids that shall be excluded
                  # from the results.
                  # Warning: Children of those documents are not excluded.
                  # $LIn_exclude in snippet call:
                  # [[ListIndexer?LIn_exclude=`3,11`]]
                  $excludeIdList = NULL;
                  
                  # $removeLinks [true | false] bool
                  # Remove Links from output true or false
                  # Directly operates on final output string
                  # LIn_removeLinks in snippet call:
                  # [[ListIndexer?LIn_removeLinks=`1`]]
                  #
                  $removeLinks = false;
                  
                  /*
                   * WHAT TO DISPLAY
                   */
                  
                  # $defaultTitle [ string ]
                  # If you want a default title for your list
                  # you can declare it here. Or use an empty
                  # string to leave this off. This can be overridden
                  # in the snippet call with the variable $LIn_title:
                  # [[ListIndexer?LIn_title=Some new title]]
                  $defaultTitle = '';
                  
                  # $shortDesc [ true | false ]
                  # Show the description on the short list, or not. Snippet
                  # parameter $LIn_sDesc:
                  # [[ListIndexer?LIn_sDesc=0]]
                  $shortDesc = true;
                  
                  # $fullDesc [ true | false ]
                  # Show the description on the full list, or not. Snippet
                  # parameter $LIn_fDesc:
                  # [[ListIndexer?LIn_fDesc=0]]
                  $fullDesc = true;
                  
                  # $linkToIndex [ int ]
                  # If you have a page set up as an 'index' for all the
                  # documents in this list, you can link to it by specifying
                  # its id- can also be set in snippet call with LIn_link:
                  # [[ListIndexer?LIn_link=8]]
                  # The default 0 will eliminate this link
                  $linkToIndex = 0;
                  
                  # $indexText [ string ]
                  # If you want a link to an index (probably a page running this
                  # snippet in "full" mode), you can declare what you want that
                  # link to say here. Or in the snippet call with LIn_indexText:
                  # [[ListIndexer?LIn_indexText=Financial News Index]]
                  $indexText = 'Index';
                  
                  # $showCreationDate [ true | false ]
                  # Decide to include date of creation in output or not. From
                  # snippet call $LIn_showDate use 1 (true) or 0 (false)
                  # [[ListIndexer?LIn_showDate=1]]
                  $showCreationDate = true;
                  
                  # $dateFormat [ string ]
                  # Used to define how date will be displayed (if using date)
                  # Y = 4 digit year     y = 2 digit year
                  # M = Jan - Dec        m = 01 - 12
                  # D = Sun - Sat        d = 01 -31
                  # Other standard PHP characters may be used
                  #[[ListIndexer?$LIn_dateFormat='M d']
                  # W. Shawn Wilkerson expanded this to be included
                  # as a parameter in snippet call
                  $dateFormat = 'M d, Y';
                  
                  # $shortQty [ int ]
                  # Number of entries to list in the short list. Can be
                  # overridden in snippet call with $LIn_sQty:
                  #[[ListIndexer?LIn_sQty=3]]
                  $shortQty = 3;
                  
                  # Display length modifications:  $titleLength[int]  $descriptionLength[int]
                  # added W. Shawn Wilkerson (shawnwilkerson.com)
                  # August 01, 2008
                  
                  # $titleLength[int]
                  # Number of characters sent to output if title.
                  # Default is full title is displayed
                  # [[ListIndexer?LIn_titleLength=15]]
                  $titleLength = 0;
                  
                  # $descriptionLength[int]
                  # Number of characters sent to output if title.
                  # Default is full title is displayed
                  # [[ListIndexer?LIn_descriptionLength=150]]
                  $descriptionLength = 0;
                  
                  /*
                   * PAGING
                   */ 
                  
                  # $fullQty [ int ]
                  # Number of entries PER PAGE to list in the full list
                  # Can be overridden in snippet call with $LIn_fQty:
                  # [[ListIndexer?LIn_fQty=20]]
                  # To show all set to 0 here or in snippet call
                  $fullQty = 10;
                  
                  # $pageSeparator [ string ]
                  # What you want your page number links to be separated by.
                  # You NEED to include spaces if you want them. They are NOT
                  # created automatically to facilitate styling ability.
                  # For instance, " | " will render links like:
                  # 1 | 2 | 3 | 4
                  $pageSeparator = " | ";
                  
                  # $pgPosition [ 'top' | 'bottom' | 'both']
                  # Pick where you want your pagination links to appear.
                  $pgPosition = 'both';
                  
                  /*
                   * PERFORMANCE
                   */
                  
                  
                  # $useFastUrls [ true | false ]
                  # IMPORTANT- using fast urls will reduce database queries
                  # and improve performance WHEN IN FULL MODE ONLY and
                  # should NOT be used when multiple instances of this snippet
                  # appear on the same page. With snippet call LIn_fast use 1
                  # (true) or 0 (false)
                  # [[ListIndexer?LIn_fast=0]]
                  $useFastUrls = false;
                  
                  # $newLinesForLists [ true | false ]
                  # Depending on how you want to style your list, you may
                  # or may not want your <li>s on new lines. Generally, if you
                  # are displaying then inline (horizontal, you do not want new
                  # lines, but standard vertical block styling you do. This is
                  # for IE, real browsers don't care.
                  $newLinesForLists = true;
                  
                  /*
                   * Styles
                   */
                  
                  
                  #
                  # The following are the styles included in this snippet. It is up
                  # to you to include these styles in your stylesheet to get them to
                  # look the way you want.
                  
                  # div.LIn_title {}          List title div
                  # ul.LIn_fullMode {}        UL class
                  # ul.LIn_shortMode {}       UL class
                  # span.LIn_date {}          Span surrounding pub/created date
                  # span.LIn_desc {}          Span surrounding description
                  # div.LIn_pagination        Div surrounding pagination links
                  # span.LIn_currentPage {}   Span surrounding current page of
                  #                           pagination (which wouldn't be css-able
                  #                           by virtue of its <a> tag)
                  
                  
                  # **********************************************************************
                  # END CONFIG SETTINGS
                  # THE REST SHOULD TAKE CARE OF ITSELF
                  # **********************************************************************
                  
                  # Take care of IE list issue
                  $ie = ($newLinesForLists)? "\n" : '' ;
                  # Use snippet call defined variables if set
                  $activeTitle = (isset($LIn_title))? $LIn_title : $defaultTitle;
                  $mode = (isset($LIn_mode))? $LIn_mode : $mode;
                  $descendentDepth = (isset($LIn_depth))? $LIn_depth : $descendentDepth;
                  $seeThruUnpub = (isset($LIn_seeThru))? $LIn_seeThru : $seeThruUnpub;
                  $seeShowInMenu = (isset($LIn_seeShowInMenu))? $LIn_seeShowInMenu : $seeShowInMenu;
                  $hidePrivate = (isset($LIn_hidePrivate))? $LIn_hidePrivate : $hidePrivate;
                  $linkToIndex = (isset($LIn_link))? $LIn_link : $linkToIndex;
                  $rootFolder = (isset($LIn_root))? $LIn_root : $rootFolder;
                  $shortQty = (isset($LIn_sQty))? $LIn_sQty : $shortQty;
                  $fullQty = (isset($LIn_fQty))? $LIn_fQty : $fullQty;
                  $showCreationDate = (isset($LIn_showDate))? $LIn_showDate : $showCreationDate;
                  $indexText = (isset($LIn_indexText))? $LIn_indexText : $indexText;
                  $useFastUrls = (isset($LIn_fast))? $LIn_fast : $useFastUrls;
                  $sortBy = (isset($LIn_sort))? $LIn_sort : $sortBy;
                  $shortDesc = (isset($LIn_sDesc))? $LIn_sDesc : $shortDesc;
                  $fullDesc = (isset($LIn_fDesc))? $LIn_fDesc : $fullDesc;
                  $sortDir = (isset($LIn_dir))? $LIn_dir : $sortDir;
                  if ($sortDir == '') $sortDir = ($sortBy == 'date') ? 'DESC' : 'ASC';
                  # 1.0.4 snippet variable
                  //$removeLinks = (empty($LIn_showDate))? $removeLinks : $LIn_showDate;
                  $removeLinks = (isset($LIn_removeLinks)) ? $LIn_removeLinks : false;
                  # 1.0.3 snippet variable
                  $excludeIdList = (isset($LIn_exclude))? $LIn_exclude : $excludeIdList;
                  # 1.0.2 snippet variables and attached function
                  $titleLength = (isset($LIn_titleLength))? $LIn_titleLength : $titleLength;
                  $descriptionLength = (isset($LIn_descriptionLength))? $LIn_descriptionLength : $descriptionLength;
                  $dateFormat = (isset($LIn_dateFormat))? $LIn_dateFormat : $dateFormat;
                  
                  # ---------------------------------------------------
                  #  Trim a string to specified length and append an end character (default = ...)
                  # added by W. Shawn Wilkerson (shawnwilkerson.com)
                  # ---------------------------------------------------
                  if ( ! function_exists('trimMe') )
                  {
                  	function trimMe($str, $length, $chr = '&#8230;')
                  	{
                  		# If $length is not set then just return full string OR
                  		# If length of string is less than the $length sent, then just return string untouched
                  		if(($length == "0") || (strlen($str = html_entity_decode($str)) <= $length)) return $str;
                  		# Else, cut string down to $length and add suffix character string
                  		return htmlentities(substr($str, 0, $length - 3)).$chr;
                  	}
                  }
                  
                  # Make useful variable shortcut for the content table
                  #$tbl = $modx->dbConfig['dbase'] . "." . $modx->dbConfig['table_prefix'] . "site_content";
                  $tblsc = $modx->getFullTableName("site_content");
                  $tbldg = $modx->getFullTableName("document_groups");
                  
                  # Initialize output
                  $output = '';
                  
                  # ---------------------------------------------------
                  # ---------------------------------------------------
                  # Query db for parent folders, or not. First check to
                  # see if a querystring cheat has been provided- this
                  # should speed things up considerably when using this
                  # in full mode. (a.k.a. fastUrls)
                  # ---------------------------------------------------
                  # ---------------------------------------------------
                  $inFolder= isset($_GET['LIn_f'])? $_GET['LIn_f']: 0;
                  if ((!$inFolder && $useFastUrls) || !$useFastUrls ){
                  	# Only run all the database queries if we don't already
                  	# know the folders AND fastUrls are desired.
                  
                  	# ---------------------------------------------------
                  	# Seed list of viable parents
                  	# ---------------------------------------------------
                  
                  	if ($rootFolder == NULL){
                  		$rootFolder = $modx->documentIdentifier;
                  	}
                  	# Set root level parent array
                  	$seedArray = explode(',',$rootFolder);
                  	$parentsArray = array();
                  	foreach($seedArray AS $seed){
                  		$parentsArray['level_0'][] = $seed;
                  	}
                  
                  	# ---------------------------------------------------
                  	# Make array of all allowed parents
                  	# ---------------------------------------------------
                  
                  	# Process valid parents
                  	$levelCounter = 1;
                  	while (((count($parentsArray) < $descendentDepth) || ($descendentDepth == 0)) && ($levelCounter <= count($parentsArray)) && ($levelCounter < 10)){
                  		# Find all decendant parents for this level
                  		$pLevel = 'level_'.($levelCounter - 1);
                  		$tempLevelArray = $parentsArray[$pLevel];
                  		foreach($tempLevelArray AS $p){
                  			# Get children who are parents (isfolder = 1)
                  			$validParentSql = "";
                  			$validParentSql .= "SELECT id FROM $tblsc sc WHERE ";
                  			$validParentSql .= "isfolder = 1 AND parent = $p ";
                  			$validParentSql .= "AND sc.deleted=0 ";
                  			$validParentSql .= ($seeThruUnpub)? ";" : "AND sc.published = 1;";
                  			# Run statement
                  			$rsTempParents = $modx->dbQuery($validParentSql);
                  			# Get number of results
                  			$countTempParents = $modx->recordCount($rsTempParents);
                  			# If there are results, put them in an array
                  			$tempValidArray = false;
                  			if ($countTempParents){
                  				for ($i=0;$i<$countTempParents;$i++){
                  					$tempId = $modx->fetchRow($rsTempParents);
                  					$tempValidArray[] = $tempId['id'];
                  				} # end while
                  			} # end if
                  
                  	  # populate next level of array
                  	  if ($tempValidArray){
                  	  	foreach($tempValidArray AS $kid){
                  	  		$kidLevel = 'level_'.$levelCounter;
                  	  		$parentsArray[$kidLevel][] = $kid;
                  	  	} # end foreach
                  
                  	  } # end if
                  		} # end foreach
                  
                  		# Do next level
                  		$levelCounter++;
                  
                  	} # end while
                  
                  	# Finalize list of parents
                  	$validParents = '';
                  	foreach ($parentsArray AS $level){
                  		foreach ($level AS $validP){
                  			$validParents .= $validP . ',';
                  		}
                  	}
                  
                  	# Remove trailing comma
                  	$validParents = substr($validParents,0,strlen($validParents)-1);
                  
                  } else {
                  	$validParents = $_GET['LIn_f'];
                  }
                  
                  # ---------------------------------------------------
                  # Make appropriate SQL statement to pull recent items
                  # ---------------------------------------------------
                  
                  # get document groups for current user
                  if($docgrp = $modx->getUserDocGroups()) $docgrp = implode(",",$docgrp);
                  
                  $access = " (".($modx->isFrontend() ? "sc.privateweb=0":"1='".$_SESSION['mgrRole']."' OR sc.privatemgr=0").
                  (!$docgrp ? "":" OR dg.document_group IN ($docgrp)").") AND ";
                  
                  
                  
                  # Initialize
                  $recentSql = "";
                  $recentSql .= "SELECT sc.id, pagetitle, description";
                  # Include pub_date or createdon date if date is desired
                  $recentSql .= ($showCreationDate)? ", IF(pub_date > 0, pub_date, createdon) AS pubDate ": " " ;
                  $recentSql .= "FROM $tblsc sc LEFT JOIN $tbldg dg on dg.document = sc.id ";
                  $recentSql .= "WHERE ";
                  $recentSql .= ($hidePrivate)? $access:"";
                  # Look everywhere, or just under valid parents
                  $recentSql .= (($rootFolder == 0) && $seeThruUnpub && ($descendentDepth == 0))? "" : "parent IN ($validParents) AND " ;
                  # Published
                  $recentSql .= "sc.published = 1 ";
                  # Show In Menu
                  $recentSql .= ($seeShowInMenu)? " " : " AND sc.hidemenu=0 " ;
                  # Not deleted
                  $recentSql .= "AND sc.deleted=0 ";
                  # Not excluded
                  if ( !is_null($excludeIdList) && $excludeIdList != '' )
                  {
                  	$recentSql .= 'AND NOT sc.id IN (' . $excludeIdList . ') ';
                  }
                  # Choose sort method
                  switch ($sortBy){
                  	case 'alpha':
                  		$recentSql .= "ORDER BY pagetitle ";
                  		break;
                  	case 'menuindex':
                  		$recentSql .= "ORDER BY menuindex ";
                  		break;
                  	default:
                  		$recentSql .= "ORDER BY IF(pub_date>0, pub_date, createdon) ";
                  		break;
                  }
                  # Provide a sort direction
                  $recentSql .= $sortDir;
                  
                  # If this is a short list, just pull a limited number
                  $recentSql .= ($mode == 'short')? " LIMIT $shortQty;" : ";" ;
                  
                  # Run statement
                  $rsRecent = $modx->dbQuery($recentSql);
                  # Count records
                  $recentLimit = $modx->recordCount($rsRecent);
                  
                  # ---------------------------------------------------
                  # Generate pagination string if needed
                  # ---------------------------------------------------
                  $offsetParam = isset($_GET['LIn_o'])? $_GET['LIn_o']: 0;
                  $offset = ($offsetParam && ($mode == 'full'))? $offsetParam : 0 ;
                  $pagination = '';
                  
                  # Don't bother unless there are enough records to justify it
                  if ( ($mode == 'full') && ($recentLimit > $fullQty) && ($fullQty) ){
                  	$fullUrl = $_SERVER['REQUEST_URI'];
                  	$urlPieces = parse_url($fullUrl);
                  	$urlPath = $urlPieces['path'];
                  	$otherQs = '';
                  
                  	if ($urlPieces['query']){
                  		foreach($_GET AS $qsKey=>$qsValue){
                  	  if (($qsKey != 'LIn_o') && ($qsKey != 'LIn_f')){
                  	  	$otherQs .= '&'.$qsKey.'='.$qsValue;
                  	  }
                  		}
                  	}
                  
                  	$fastUrl = $urlPath.'?LIn_f='.$validParents.$otherQs;
                  
                  	# Determine number of pages needed to show results
                  	$totalPages = ceil($recentLimit/$fullQty);
                  
                  	# Make links
                  	for ($j = 0 ; $j < $totalPages; $j++){
                  		# only include links to OTHER pages, not current page
                  		if($offset == $j*$fullQty){
                  	  $pagination .= '<span class="LIn_currentPage">'.($j+1) .'</span>';
                  		} else {
                  			$pagination .= '<a href="'.$fastUrl.'&LIn_o='.($j*$fullQty).'" title="'.($j+1).'">'.($j+1) .'</a>';
                  		}
                  		if ($j < $totalPages-1){
                  	  $pagination .= $pageSeparator;
                  		}
                  	}
                  
                  	# Make final pagination link set in it's own div
                  	$pagination = '<div class="LIn_pagination">'."\n".$pagination."\n</div>\n";
                  
                  }
                  
                  
                  # ---------------------------------------------------
                  # Create title if wanted
                  # ---------------------------------------------------
                  
                  if ($activeTitle){
                  	$output .= '<div class="LIn_title">'.$activeTitle.'</div>'."\n";
                  }
                  
                  # ---------------------------------------------------
                  # Create list of recent items
                  # ---------------------------------------------------
                  
                  # Include pagination
                  $output .= ($pgPosition == 'top' || $pgPosition == 'both')? $pagination : '' ;
                  $output .= '<ul class="LIn_'.$mode.'Mode">' . $ie;
                  $recentCounter = $offset;
                  if ($mode == 'short') {
                  	$recentCounterLimit = min($shortQty,$recentLimit);
                  } else {
                  	$recentCounterLimit = ($fullQty)? min(($fullQty+$offset),$recentLimit) : $recentLimit ;
                  }
                  
                  while (($recentCounter < $recentCounterLimit) && $rsRecent && ($recentLimit > 0)){
                  	mysql_data_seek($rsRecent,$recentCounter);
                  	$recentRecord = $modx->fetchRow($rsRecent);
                  	$output .= '<li>';
                  	# Link to page or just page title
                  	$output .= ($removeLinks) ? trimMe($recentRecord['pagetitle'], $titleLength, $chr = '&#8230;'): '<a href="[~'.$recentRecord['id'].'~]" title="'.strip_tags($recentRecord['pagetitle']).'">'. trimMe($recentRecord['pagetitle'], $titleLength, $chr = '&#8230;') .'</a>';
                  
                  	# Date if desired
                  	if ($showCreationDate){
                  		$output .= '<span class="LIn_date">'.date($dateFormat,$recentRecord['pubDate']).'</span> ';
                  	}
                  	# Description if desired
                  	if ((($mode == 'short') && ($shortDesc)) || (($mode == 'full') && ($fullDesc))){
                  		$output .= '<span class="LIn_desc">'. trimMe($recentRecord['description'], $descriptionLength, $chr = '&#8230;') .'</span>';
                  	}
                  	# wrap it up
                  	$output .= '</li>' . $ie;
                  	$recentCounter ++;
                  }
                  
                  $output .= '</ul>' . $ie;
                  
                  $output .= ($pgPosition == 'bottom' || $pgPosition == 'both')? $pagination : '' ;
                  
                  # ---------------------------------------------------
                  # Link to index
                  # ---------------------------------------------------
                  
                  if ($linkToIndex) {
                  	$output .= '<div class="LIn_index">';
                  	$output .= ($removeLinks) ? $indexText : '<a href="[~'.$linkToIndex.'~]" title="'.$indexText.'">'.$indexText.'</a>';
                  	$output .= '</div>';
                  }
                  
                  # ---------------------------------------------------
                  # Send to browser
                  # ---------------------------------------------------
                  
                  return $output;
                  ?>
                    Get your copy of MODX Revolution Building the Web Your Way http://www.sanitypress.com/books/modx-revolution-building-the-web-your-way.html

                    Check out my MODX || xPDO resources here: http://www.shawnwilkerson.com
                    • 26931
                    • 2,314 Posts
                    anonymized-26931 Reply #19, 17 years ago
                    hey wshawn,

                    I cleaned up the code a little bit as far as the comments are concerned.
                    The addition presented here is to allow the output to return a non linked list of page titles. For situations where you want people to see what is available, without letting them have access or a "join", "beg", or "complain" page.

                    great, thanks for sharing!
                      • 32699 ☆ A M B ☆
                      • 427 Posts
                      W. Shawn Wilkerson Reply #20, 17 years ago
                      I have added some SEO functionality as well as cleaned up the MySQL queries. I also added the ability to use a page’s long title instead of the title for the clickable text in the links (if you haven’t decided to utilize 1.04’s ability to strip click links).

                      I will update the repo.

                      The string concatenation was not optimized or properly coded in previous version, which have been contributed by multiple people (including myself).

                      <?php
                      /* File			Snippet: ListIndexer
                       * Created on	Oct 9, 2009
                       * Project		project_name
                       * @package		package_name
                       * @version		2
                       * @category	ModX Snippet
                       * @author		W. Shawn Wilkerson, Nashi Power, jaredc
                       * @link		http://www.shawnwilkerson.com
                       * @license
                       */
                      
                      # PLEASE NOTE all parameters should be using backticks
                      # in final production [[ListIndexer?LIn_seeThru=`1`]]
                      # not [[ListIndexer?LIn_seeThru=1]]
                      
                      /*
                       * Version 1.0.5
                       * Date: Oct 17, 2009
                       * 1.0.5 update by W. Shawn Wilkerson shawnwilkerson.com
                       * previous licensed recognized, upheld, and re issued
                       * Purpose to provide SEO functionality by allowing keywords to be added to the title of the href links
                       * Specifically instead of <a class="pdf" target="_blank" href="Credentials/WilkersonWilliamRESUME.pdf" title="Resume">Resume</a>
                       * 				returns <a class="pdf" target="_blank" href="Credentials/WilkersonWilliamRESUME.pdf" title="Shawn Wilkerson's Resume">Resume</a>
                       * See LIn_SEOprefix to place words before link page title
                       * See LIn_SEOsuffix to place words after link page title
                       * See LIn_SEOlongTitle to use the link page's long title
                       * See LIn_addSeoToLinks to place the LIn_SEOprefix at the begining of the link and/or to place LIn_SEOsuffix at the end
                       *
                       * I also optimized the concatenation of the sql queries by replacing the "" with ''.
                       * Additionally, I applied the correct MySQL syntax for table names, column names and values
                       * Finally, I removed the AND from the end of lines and placed them at the beginning of lines where they should be IF that line was being added to the string
                       * All lines of the queries should now read from left to right and should no longer span across lines of code
                       * I thought about removing the $access variable as it is only used once after instantiation, but a triple Ternary could prove untrustworthy
                       */
                      
                      /*
                       * Version 1.0.4
                       * Date: Oct 9, 2009
                       * 1.0.4 update by W. Shawn Wilkerson shawnwilkerson.com
                       * previous licensed recognized, upheld, and re issued
                       * Purpose: to allow the output to return a non linked list of page titles
                       * Specifically instead of <li><a href="mypage.html">My Page</a></li>
                       * 				returns <li>My Page</li>
                       * See LIn_removeLinks below.
                       */
                      
                      
                      /*
                       * Version 1.0.3
                       * Date: 20 Sep 2008
                       * 1.0.3 update by Paul at Nashi Power (http:#nashi.podzone.org/)
                       * Purpose: to allow the specification of a list of documents to be excluded.
                       * See LIn_exclude below.
                       */
                      
                      
                      /*
                       * Version 1.0.2
                       * Date 01 Aug 2008
                       * 1.0.2 update by W. Shawn Wilkerson shawnwilkerson.com
                       * previous licensed recognized, upheld, and re issued
                       *
                       * Added string length triming functionality for
                       * limiting the number of characters displayed
                       * in the link Title as well as in the Description.
                       *
                       * Added $LIn_ dateFormat to make the date format
                       * configurable via snippet call
                       *
                       * This new functionality will allow better control over
                       * page real estate, as well as over all the presentation
                       */
                      
                      /*
                       * Version: 1.0.1
                       * added in 1.0.1: hidePrivate (hide items from unauthorized users)
                       * Derived from ListIndex 0.6j by [email protected]
                       * Now supports Show In Menu
                       * This snippet was designed to be a VERY flexible way
                       * of showing what has been recently added. You can use
                       * this snippet to show news from one folder, or what has
                       * been recently added site wide. You can even show what's
                       * new in a 'section' (everything under a defined folder)!
                       *
                       */
                      
                      /*
                       * Version ListIndex 0.6j by [email protected]
                       */
                      
                      # Configuration Settings
                      
                      # Set the following snippet defaults the way you would normally
                      # use this snippet, then use snippet variables in other situations
                      # to override the default behaviors.
                      
                      # GENERAL OPTIONS
                      
                      # $rootFolder [ NULL | string (comma separated page id's) ]
                      # Decide which folder to pull recent documents from.
                      # If you want to specify a few folders, comma separate them.
                      # The default NULL will set current page as root. Using 0
                      # would search site wide. Can be set with snippet parameter
                      # $LIn_root like:
                      # [[ListIndexer?LIn_root=3,6,88]]
                      $rootFolder = NULL;
                      
                      # $descendentDepth [ int ]
                      # How many levels below the root folder(s) do you want to
                      # include? Can be overridden in snippet call with LIn_depth:
                      # [[ListIndexer?LIn_depth=2]]
                      # Uncomment one of these common two or create your own:
                      # $descendentDepth = 1; # just children of root folder(s)
                      $descendentDepth = 0; # all decendents of root folder(s)
                      
                      # $seeThruUnpub [ true | false ]
                      # When using descendents, do you want to consider files below
                      # an unpublished (hidden) folder? Usually no. But you decide.
                      # Snippet parameter: LIn_seeThru
                      # [[ListIndexer?LIn_seeThru=1]]
                      $seeThruUnpub = false;
                      
                      # $seeShowInMenu [ true | false ]
                      # When using descendents, do you want to consider files flagged
                      # to be hidden from the menus? Usually no. But you decide.
                      # Snippet parameter: LIn_seeShowInMenu
                      # [[ListIndexer?LIn_seeShowInMenu=1]]
                      $seeShowInMenu = false;
                      
                      # $hidePrivate [ true | false ]
                      # Hide items from users that don't have appropriate
                      # rights to view. Usually true. But you decide.
                      # Snippet parameter: LIn_hidePrivate
                      # [[ListIndexer?LIn_hidePrivate=0]]
                      $hidePrivate = true;
                      
                      # $mode [ 'short' | 'full' ]
                      # Defines whether this list should be a full, paged
                      # list of all documents, or a short list of the most
                      # recent few (how many will be defined next). Can be
                      # overridden in snippet call with $LIn_mode:
                      # [[ListIndexer?LIn_mode=full]]
                      $mode = 'short';
                      
                      # $sortBy [ 'alpha' | 'date' | 'menuindex' ]
                      # The default date will sort by most recent items first, but
                      # by using the 'alpha' option, and using full mode, you could
                      # use this to create an index, or directory.
                      # Settable with snippet call $LIn_sort:
                      # [[ListIndexer?LIn_sort=alpha]]
                      $sortBy = 'date';
                      
                      # $sortDir [ 'ASC' | 'DESC' ]
                      # Sort direction ascending or descending. Is applied to whatever $sortBy
                      # field you have chosen above. If left blank, menuindex and alpha will sort
                      # ASC and date DESC.
                      # $LIn_dir in snippet call:
                      # [[ListIndexer?LIn_dir=ASC&LIn_sortBy=menuindex]]
                      $sortDir = '';
                      
                      # $excludeIdList [ NULL | string (comma separated page id's) ]
                      # A comma separated list of document ids that shall be excluded
                      # from the results.
                      # Warning: Children of those documents are not excluded.
                      # $LIn_exclude in snippet call:
                      # [[ListIndexer?LIn_exclude=`3,11`]]
                      $excludeIdList = NULL;
                      
                      # $removeLinks [true | false] bool
                      # Remove Links from output true or false
                      # Directly operates on final output string
                      # LIn_removeLinks in snippet call:
                      # [[ListIndexer?LIn_removeLinks=`1`]]
                      #
                      $removeLinks = false;
                      
                      /*
                       * WHAT TO DISPLAY
                       */
                      
                      # $defaultTitle [ string ]
                      # If you want a default title for your list
                      # you can declare it here. Or use an empty
                      # string to leave this off. This can be overridden
                      # in the snippet call with the variable $LIn_title:
                      # [[ListIndexer?LIn_title=Some new title]]
                      $defaultTitle = '';
                      
                      # $shortDesc [ true | false ]
                      # Show the description on the short list, or not. Snippet
                      # parameter $LIn_sDesc:
                      # [[ListIndexer?LIn_sDesc=0]]
                      $shortDesc = true;
                      
                      # $fullDesc [ true | false ]
                      # Show the description on the full list, or not. Snippet
                      # parameter $LIn_fDesc:
                      # [[ListIndexer?LIn_fDesc=0]]
                      $fullDesc = true;
                      
                      # $linkToIndex [ int ]
                      # If you have a page set up as an 'index' for all the
                      # documents in this list, you can link to it by specifying
                      # its id- can also be set in snippet call with LIn_link:
                      # [[ListIndexer?LIn_link=8]]
                      # The default 0 will eliminate this link
                      $linkToIndex = 0;
                      
                      # $indexText [ string ]
                      # If you want a link to an index (probably a page running this
                      # snippet in "full" mode), you can declare what you want that
                      # link to say here. Or in the snippet call with LIn_indexText:
                      # [[ListIndexer?LIn_indexText=Financial News Index]]
                      $indexText = 'Index';
                      
                      # $showCreationDate [ true | false ]
                      # Decide to include date of creation in output or not. From
                      # snippet call $LIn_showDate use 1 (true) or 0 (false)
                      # [[ListIndexer?LIn_showDate=1]]
                      $showCreationDate = true;
                      
                      # $dateFormat [ string ]
                      # Used to define how date will be displayed (if using date)
                      # Y = 4 digit year     y = 2 digit year
                      # M = Jan - Dec        m = 01 - 12
                      # D = Sun - Sat        d = 01 -31
                      # Other standard PHP characters may be used
                      #[[ListIndexer?$LIn_dateFormat='M d']
                      # W. Shawn Wilkerson expanded this to be included
                      # as a parameter in snippet call
                      $dateFormat = 'M d, Y';
                      
                      # $shortQty [ int ]
                      # Number of entries to list in the short list. Can be
                      # overridden in snippet call with $LIn_sQty:
                      #[[ListIndexer?LIn_sQty=3]]
                      $shortQty = 3;
                      
                      # $titleLength[int]
                      # Number of characters sent to output if title.
                      # Default is full title is displayed
                      # [[ListIndexer?LIn_titleLength=15]]
                      $titleLength = 0;
                      
                      # $descriptionLength[int]
                      # Number of characters sent to output if title.
                      # Default is full title is displayed
                      # [[ListIndexer?LIn_descriptionLength=150]]
                      $descriptionLength = 0;
                      
                      # $useLongTitle [ true | false ]
                      # Use the page's long title instead of the default short title
                      # Note: requies Long Title to be set on the resource page or this will return nothing
                      # With snippet call LIn_SEOlongTitle use
                      # 1 (true) or 0 (false)
                      # [[ListIndexer?LIn_SEOlongTitle=`0`]]
                      $useLongTitle = false;
                      
                      # $seoPrefix [ string ]
                      # Provide a string to be placed before the page title or long title
                      # This can also be ModX placeholders such as LIn_SEOprefix=`[(site_name)]`
                      # With snippet call LIn_SEOprefix
                      # [[ListIndexer?LIn_SEOprefix=`My terms here`]]
                      $seoPrefix = '';
                      
                      # $seoSuffix [ string ]
                      # Provide a string to be placed after the page title or long title
                      # This can also be ModX placeholders such as LIn_SEOsuffix=`[(site_name)]`
                      # With snippet call LIn_SEOsuffix
                      # [[ListIndexer?LIn_SEOsuffix=`My terms here`]]
                      $seoSuffix = '';
                      
                      # $addSeoToLinks [ true | false ]
                      # Adds the content from  LIn_SEOprefix & LIn_SEOsuffix to the clickable link text
                      # [[ListIndexer?LIn_addSeoToLinks=`1`]]
                      $addSeoToLinks = false;
                      
                      /*
                       * PAGING
                       */
                      
                      # $fullQty [ int ]
                      # Number of entries PER PAGE to list in the full list
                      # Can be overridden in snippet call with $LIn_fQty:
                      # [[ListIndexer?LIn_fQty=20]]
                      # To show all set to 0 here or in snippet call
                      $fullQty = 10;
                      
                      # $pageSeparator [ string ]
                      # What you want your page number links to be separated by.
                      # You NEED to include spaces if you want them. They are NOT
                      # created automatically to facilitate styling ability.
                      # For instance, " | " will render links like:
                      # 1 | 2 | 3 | 4
                      $pageSeparator = " | ";
                      
                      # $pgPosition [ 'top' | 'bottom' | 'both']
                      # Pick where you want your pagination links to appear.
                      $pgPosition = 'both';
                      
                      /*
                       * PERFORMANCE
                       */
                      
                      
                      # $useFastUrls [ true | false ]
                      # IMPORTANT- using fast urls will reduce database queries
                      # and improve performance WHEN IN FULL MODE ONLY and
                      # should NOT be used when multiple instances of this snippet
                      # appear on the same page. With snippet call LIn_fast use 1
                      # (true) or 0 (false)
                      # [[ListIndexer?LIn_fast=0]]
                      $useFastUrls = false;
                      
                      # $newLinesForLists [ true | false ]
                      # Depending on how you want to style your list, you may
                      # or may not want your <li>s on new lines. Generally, if you
                      # are displaying then inline (horizontal, you do not want new
                      # lines, but standard vertical block styling you do. This is
                      # for IE, real browsers don't care.
                      $newLinesForLists = true;
                      
                      /*
                       * Styles
                       */
                      
                      
                      #
                      # The following are the styles included in this snippet. It is up
                      # to you to include these styles in your stylesheet to get them to
                      # look the way you want.
                      
                      # div.LIn_title {}          List title div
                      # ul.LIn_fullMode {}        UL class
                      # ul.LIn_shortMode {}       UL class
                      # span.LIn_date {}          Span surrounding pub/created date
                      # span.LIn_desc {}          Span surrounding description
                      # div.LIn_pagination        Div surrounding pagination links
                      # span.LIn_currentPage {}   Span surrounding current page of
                      #                           pagination (which wouldn't be css-able
                      #                           by virtue of its <a> tag)
                      
                      
                      # **********************************************************************
                      # END CONFIG SETTINGS
                      # THE REST SHOULD TAKE CARE OF ITSELF
                      # **********************************************************************
                      
                      # Take care of IE list issue
                      $ie = ($newLinesForLists)? "\n" : '' ;
                      # Use snippet call defined variables if set
                      $activeTitle = (isset($LIn_title))? $LIn_title : $defaultTitle;
                      $mode = (isset($LIn_mode))? $LIn_mode : $mode;
                      $descendentDepth = (isset($LIn_depth))? $LIn_depth : $descendentDepth;
                      $seeThruUnpub = (isset($LIn_seeThru))? $LIn_seeThru : $seeThruUnpub;
                      $seeShowInMenu = (isset($LIn_seeShowInMenu))? $LIn_seeShowInMenu : $seeShowInMenu;
                      $hidePrivate = (isset($LIn_hidePrivate))? $LIn_hidePrivate : $hidePrivate;
                      $linkToIndex = (isset($LIn_link))? $LIn_link : $linkToIndex;
                      $rootFolder = (isset($LIn_root))? $LIn_root : $rootFolder;
                      $shortQty = (isset($LIn_sQty))? $LIn_sQty : $shortQty;
                      $fullQty = (isset($LIn_fQty))? $LIn_fQty : $fullQty;
                      $showCreationDate = (isset($LIn_showDate))? $LIn_showDate : $showCreationDate;
                      $indexText = (isset($LIn_indexText))? $LIn_indexText : $indexText;
                      $useFastUrls = (isset($LIn_fast))? $LIn_fast : $useFastUrls;
                      $sortBy = (isset($LIn_sort))? $LIn_sort : $sortBy;
                      $shortDesc = (isset($LIn_sDesc))? $LIn_sDesc : $shortDesc;
                      $fullDesc = (isset($LIn_fDesc))? $LIn_fDesc : $fullDesc;
                      $sortDir = (isset($LIn_dir))? $LIn_dir : $sortDir;
                      if ($sortDir == '') $sortDir = ($sortBy == 'date') ? 'DESC' : 'ASC';
                      # 1.0.5 snippet variables
                      $useLongTitle = (isset($LIn_SEOlongTitle)) ? $LIn_SEOlongTitle : false;
                      $seoPrefix = (isset($LIn_SEOprefix)) ? $LIn_SEOprefix : '';
                      $seoSuffix = (isset($LIn_SEOsuffix)) ? $LIn_SEOsuffix : '';
                      $addSeoToLinks = (isset($LIn_addSeoToLinks)) ? $LIn_addSeoToLinks : false;
                      # 1.0.4 snippet variable
                      $removeLinks = (isset($LIn_removeLinks)) ? $LIn_removeLinks : false;
                      # 1.0.3 snippet variable
                      $excludeIdList = (isset($LIn_exclude))? $LIn_exclude : $excludeIdList;
                      # 1.0.2 snippet variables and attached function
                      $titleLength = (isset($LIn_titleLength))? $LIn_titleLength : $titleLength;
                      $descriptionLength = (isset($LIn_descriptionLength))? $LIn_descriptionLength : $descriptionLength;
                      $dateFormat = (isset($LIn_dateFormat))? $LIn_dateFormat : $dateFormat;
                      
                      # ---------------------------------------------------
                      #  Trim a string to specified length and append an end character (default = ...)
                      # added by W. Shawn Wilkerson (shawnwilkerson.com)
                      # ---------------------------------------------------
                      if ( ! function_exists('trimMe') )
                      {
                      	function trimMe($str, $length, $chr = '&#8230;')
                      	{
                      		# If $length is not set then just return full string OR
                      		# If length of string is less than the $length sent, then just return string untouched
                      		if(($length == "0") || (strlen($str = html_entity_decode($str)) <= $length)) return $str;
                      		# Else, cut string down to $length and add suffix character string
                      		return htmlentities(substr($str, 0, $length - 3)).$chr;
                      	}
                      }
                      
                      # Make useful variable shortcut for the content table
                      #$tbl = $modx->dbConfig['dbase'] . "." . $modx->dbConfig['table_prefix'] . "site_content";
                      $tblsc = $modx->getFullTableName("site_content");
                      $tbldg = $modx->getFullTableName("document_groups");
                      
                      # Initialize output
                      $output = '';
                      
                      # ---------------------------------------------------
                      # ---------------------------------------------------
                      # Query db for parent folders, or not. First check to
                      # see if a querystring cheat has been provided- this
                      # should speed things up considerably when using this
                      # in full mode. (a.k.a. fastUrls)
                      # ---------------------------------------------------
                      # ---------------------------------------------------
                      $inFolder= isset($_GET['LIn_f'])? $_GET['LIn_f']: 0;
                      if ((!$inFolder && $useFastUrls) || !$useFastUrls ){
                      	# Only run all the database queries if we don't already
                      	# know the folders AND fastUrls are desired.
                      
                      	# ---------------------------------------------------
                      	# Seed list of viable parents
                      	# ---------------------------------------------------
                      
                      	if ($rootFolder == NULL){
                      		$rootFolder = $modx->documentIdentifier;
                      	}
                      	# Set root level parent array
                      	$seedArray = explode(',',$rootFolder);
                      	$parentsArray = array();
                      	foreach($seedArray AS $seed){
                      		$parentsArray['level_0'][] = $seed;
                      	}
                      
                      	# ---------------------------------------------------
                      	# Make array of all allowed parents
                      	# ---------------------------------------------------
                      
                      	# Process valid parents
                      	$levelCounter = 1;
                      	while (((count($parentsArray) < $descendentDepth) || ($descendentDepth == 0)) && ($levelCounter <= count($parentsArray)) && ($levelCounter < 10)){
                      		# Find all decendant parents for this level
                      		$pLevel = 'level_'.($levelCounter - 1);
                      		$tempLevelArray = $parentsArray[$pLevel];
                      		foreach($tempLevelArray AS $p){
                      			# Get children who are parents (isfolder = 1)
                      			$validParentSql = '';
                      			$validParentSql .= 'SELECT `id` FROM '.$tblsc.' `sc`';
                      			$validParentSql .= ' WHERE `isfolder` = "1" AND `parent` = "'.$p.'"';
                      			$validParentSql .= ' AND `sc`.`deleted`="0"';
                      			$validParentSql .= ($seeThruUnpub)? ';' : ' AND `sc`.`published`= "1";';
                      			# Run statement
                      			$rsTempParents = $modx->dbQuery($validParentSql);
                      			# Get number of results
                      			$countTempParents = $modx->recordCount($rsTempParents);
                      			# If there are results, put them in an array
                      			$tempValidArray = false;
                      			if ($countTempParents){
                      				for ($i=0;$i<$countTempParents;$i++){
                      					$tempId = $modx->fetchRow($rsTempParents);
                      					$tempValidArray[] = $tempId['id'];
                      				} # end while
                      			} # end if
                      
                      	  # populate next level of array
                      	  if ($tempValidArray){
                      	  	foreach($tempValidArray AS $kid){
                      	  		$kidLevel = 'level_'.$levelCounter;
                      	  		$parentsArray[$kidLevel][] = $kid;
                      	  	} # end foreach
                      
                      	  } # end if
                      		} # end foreach
                      
                      		# Do next level
                      		$levelCounter++;
                      
                      	} # end while
                      
                      	# Finalize list of parents
                      	$validParents = '';
                      	foreach ($parentsArray AS $level){
                      		foreach ($level AS $validP){
                      			$validParents .= $validP . ',';
                      		}
                      	}
                      
                      	# Remove trailing comma
                      	$validParents = substr($validParents,0,strlen($validParents)-1);
                      
                      } else {
                      	$validParents = $_GET['LIn_f'];
                      }
                      
                      # ---------------------------------------------------
                      # Make appropriate SQL statement to pull recent items
                      # ---------------------------------------------------
                      
                      # get document groups for current user
                      if($docgrp = $modx->getUserDocGroups()) $docgrp = implode(",",$docgrp);
                      $access = ' ('.($modx->isFrontend() ? '`sc`.`privateweb`="0"':'1="'.$_SESSION['mgrRole'].'" OR `sc`.`privatemgr`="0"').
                      (!$docgrp ? '':' OR dg.document_group IN ($docgrp)').')';
                      # Initialize
                      $recentSql = '';
                      # return the long title of the page or the title of the page
                      $recentSql .= ($useLongTitle) ? 'SELECT `sc`.`id`, `longtitle` AS `pagetitle`, `description`' : 'SELECT `sc`.`id`, `pagetitle`, `description`';
                      # Include pub_date or createdon date if date is desired
                      $recentSql .= ($showCreationDate) ? ', IF(pub_date > 0, pub_date, createdon) AS pubDate ': ' ';
                      $recentSql .= ' FROM '.$tblsc.' `sc` LEFT JOIN '.$tbldg.' `dg` on `dg`.`document` = `sc`.`id`';
                      $recentSql .= ' WHERE ';
                      $recentSql .= ($hidePrivate)? $access:'';
                      # Look everywhere, or just under valid parents
                      $recentSql .= (($rootFolder == 0) && $seeThruUnpub && ($descendentDepth == 0))? '': ' AND `parent` IN ('.$validParents.')';
                      # Published
                      $recentSql .= ' AND `sc`.`published` = "1"';
                      # Show In Menu
                      $recentSql .= ($seeShowInMenu)? ' ' : ' AND `sc`.`hidemenu`="0"' ;
                      # Not deleted
                      $recentSql .= ' AND `sc`.`deleted`="0" ';
                      # Not excluded
                      if ( !is_null($excludeIdList) && $excludeIdList != '' )
                      {
                      	$recentSql .= ' AND NOT `sc`.`id` IN (' . $excludeIdList . ')';
                      }
                      # Choose sort method
                      switch ($sortBy){
                      	case 'alpha':
                      		$recentSql .= ' ORDER BY pagetitle ';
                      		break;
                      	case 'menuindex':
                      		$recentSql .= ' ORDER BY menuindex ';
                      		break;
                      	default:
                      		$recentSql .= ' ORDER BY IF(pub_date>0, pub_date, createdon) ';
                      		break;
                      }
                      # Provide a sort direction
                      $recentSql .= $sortDir;
                      
                      # If this is a short list, just pull a limited number
                      $recentSql .= ($mode == 'short')? " LIMIT $shortQty;" : ";" ;
                      
                      # Run statement
                      $rsRecent = $modx->dbQuery($recentSql);
                      # Count records
                      $recentLimit = $modx->recordCount($rsRecent);
                      
                      # ---------------------------------------------------
                      # Generate pagination string if needed
                      # ---------------------------------------------------
                      $offsetParam = isset($_GET['LIn_o'])? $_GET['LIn_o']: 0;
                      $offset = ($offsetParam && ($mode == 'full'))? $offsetParam : 0 ;
                      $pagination = '';
                      
                      # Don't bother unless there are enough records to justify it
                      if ( ($mode == 'full') && ($recentLimit > $fullQty) && ($fullQty) ){
                      	$fullUrl = $_SERVER['REQUEST_URI'];
                      	$urlPieces = parse_url($fullUrl);
                      	$urlPath = $urlPieces['path'];
                      	$otherQs = '';
                      
                      	if ($urlPieces['query']){
                      		foreach($_GET AS $qsKey=>$qsValue){
                      	  if (($qsKey != 'LIn_o') && ($qsKey != 'LIn_f')){
                      	  	$otherQs .= '&'.$qsKey.'='.$qsValue;
                      	  }
                      		}
                      	}
                      
                      	$fastUrl = $urlPath.'?LIn_f='.$validParents.$otherQs;
                      
                      	# Determine number of pages needed to show results
                      	$totalPages = ceil($recentLimit/$fullQty);
                      
                      	# Make links
                      	for ($j = 0 ; $j < $totalPages; $j++){
                      		# only include links to OTHER pages, not current page
                      		if($offset == $j*$fullQty){
                      	  $pagination .= '<span class="LIn_currentPage">'.($j+1) .'</span>';
                      		} else {
                      			$pagination .= '<a href="'.$fastUrl.'&LIn_o='.($j*$fullQty).'" title="'.($j+1).'">'.($j+1) .'</a>';
                      		}
                      		if ($j < $totalPages-1){
                      	  $pagination .= $pageSeparator;
                      		}
                      	}
                      
                      	# Make final pagination link set in it's own div
                      	$pagination = '<div class="LIn_pagination">'."\n".$pagination."\n</div>\n";
                      
                      }
                      
                      
                      # ---------------------------------------------------
                      # Create title if wanted
                      # ---------------------------------------------------
                      
                      if ($activeTitle){
                      	$output .= '<div class="LIn_title">'.$activeTitle.'</div>'."\n";
                      }
                      
                      # ---------------------------------------------------
                      # Create list of recent items
                      # ---------------------------------------------------
                      
                      # Include pagination
                      $output .= ($pgPosition == 'top' || $pgPosition == 'both')? $pagination : '' ;
                      $output .= '<ul class="LIn_'.$mode.'Mode">' . $ie;
                      $recentCounter = $offset;
                      if ($mode == 'short') {
                      	$recentCounterLimit = min($shortQty,$recentLimit);
                      } else {
                      	$recentCounterLimit = ($fullQty)? min(($fullQty+$offset),$recentLimit) : $recentLimit ;
                      }
                      
                      while (($recentCounter < $recentCounterLimit) && $rsRecent && ($recentLimit > 0)){
                      	mysql_data_seek($rsRecent,$recentCounter);
                      	$recentRecord = $modx->fetchRow($rsRecent);
                      	$output .= '<li>';
                      	# Link to page or just page title
                      	$title = ($addSeoToLinks) ?  trimMe(strip_tags($seoPrefix . $recentRecord['pagetitle'] . $seoSuffix), $titleLength, $chr = '&#8230;') : trimMe(strip_tags($recentRecord['pagetitle']),  $titleLength, $chr = '&#8230;');
                      	$output .= ($removeLinks) ? $title : '<a href="[~'.$recentRecord['id'].'~]" title="'. $seoPrefix . strip_tags($recentRecord['pagetitle']) . $seoSuffix . '">'. $title .'</a>';
                      
                      	# Date if desired
                      	if ($showCreationDate){
                      		$output .= '<span class="LIn_date">'.date($dateFormat,$recentRecord['pubDate']).'</span> ';
                      	}
                      	# Description if desired
                      	if ((($mode == 'short') && ($shortDesc)) || (($mode == 'full') && ($fullDesc))){
                      		$output .= '<span class="LIn_desc">'. trimMe($recentRecord['description'], $descriptionLength, $chr = '&#8230;') .'</span>';
                      	}
                      	# wrap it up
                      	$output .= '</li>' . $ie;
                      	$recentCounter ++;
                      }
                      
                      $output .= '</ul>' . $ie;
                      
                      $output .= ($pgPosition == 'bottom' || $pgPosition == 'both')? $pagination : '' ;
                      
                      # ---------------------------------------------------
                      # Link to index
                      # ---------------------------------------------------
                      
                      if ($linkToIndex) {
                      	$output .= '<div class="LIn_index">';
                      	$output .= ($removeLinks) ? $indexText : '<a href="[~'.$linkToIndex.'~]" title="'.$indexText.'">'.$indexText.'</a>';
                      	$output .= '</div>';
                      }
                      
                      # ---------------------------------------------------
                      # Send to browser
                      # ---------------------------------------------------
                      return $output;
                      ?>


                      I am already have a concept for 1.06 in that it will allow you to choose a number of columns to display for the list items.
                        Get your copy of MODX Revolution Building the Web Your Way http://www.sanitypress.com/books/modx-revolution-building-the-web-your-way.html

                        Check out my MODX || xPDO resources here: http://www.shawnwilkerson.com