<?PHP
#
#   FILE:  BrowseResources.php
#
#   FUNCTIONS PROVIDED:
#       DisplayClassificationList()
#           - outputs HTML for list of classifications for this page
#       DisplayResourceList()
#           - outputs HTML for list of resources for this page
#       PrintAlphabeticClassificationLinks()
#           - returns HTML for links to classification by starting letter
#       GetClassificationCount()
#           - returns number of classifications on this page
#       GetResourceCount()
#           - returns number of resources on this page
#       PrintRootClassification($ParentId, $LinkStyle)
#           - returns linked HTML for base classification for current page
#       EditingEnabled()
#           - whether user has editing privileges and editing was requested
#       PrintAddClassificationLink()
#           - print link address to add a classification at this point in tree
#       PreviousResourcesAvailable()
#       NextResourcesAvailable()
#           - return TRUE if this is not the first/last page of resources
#       PrintPreviousResourcesLink()
#       PrintNextResourcesLink()
#           - print URL for previous or next page of resources
#       PrintNumberOfPreviousResources()
#       PrintNumberOfNextResources()
#           - print number of resources on previous/next resources page
#
#   FUNCTIONS EXPECTED:
#       MoveToNextClassificationColumn()
#           - called to move to next column in classification HTML table
#       PrintClassificationEntry($ClassName, $LinkAddress, $ResourceCount,
#                   $EditLinkAddress)
#           - called to display classification entry
#       PrintResourceEntry($Title, $Description, $FullRecordLink, $Url,
#                   $DateOfRecordCreation, $DateRecordAdded, $Contributor,
#                   $EditOkay, $EditUrl, $DateLastVerified, $DateLastModified)
#           - called to display resource entry
#
#   Part of the Scout Portal Toolkit
#   Copyright 2004 Internet Scout Project
#   http://scout.wisc.edu
#

require_once("lib/AxisPHP/Axis--StandardLibrary.php");

if (EditingEnabled())
{
    PageTitle("Add / Edit Classifications");
}
else
{
    PageTitle("Browse Resources");
}

# ----- EXPORTED FUNCTIONS ---------------------------------------------------

function GetBrowseLinks()
{
    global $G_User;
    $Schema = new MetadataSchema();
    $BrowsingFieldId = GetBrowsingFieldId();

    $Links = array();

    foreach ($Schema->GetFields(MetadataSchema::MDFTYPE_TREE) as $Field)
    {
        if ($Field->Enabled() && $Field->Id() != $BrowsingFieldId &&
            ($Field->ViewingPrivilege() == 0 ||
             $G_User->HasPriv($Field->ViewingPrivilege())) )
        {
            $Links[$Field->Name()] =
                "index.php?P=BrowseResources&amp;FieldId=".$Field->Id();
        }
    }

    return $Links;
}

function PrintAlphabeticClassificationLinks()
{
    global $ParentId;
    global $DB;
    global $SysConfig;

    # if classification ID passed in
    if ($ParentId > 0)
    {
        # retrieve link string for classification
        $Class = new Classification($ParentId);
        $LinkString = $Class->LinkString();

        # if link string has not yet been set
        if ($LinkString == "")
        {
            # create and save new link string
            $LinkString = BuildClassificationLinkString($ParentId);
            $Class->LinkString($LinkString);
        }
    }
    # else
    else
    {
        # retrieve top-level link string
        $LinkString = $SysConfig->TopLinkString();

        # if top-level link string has not yet been set
        if ($LinkString == "")
        {
            # create and save new top-level link string
            $LinkString = BuildClassificationLinkString(0);
            $SysConfig->TopLinkString($LinkString);

            # extract and save new default top-level begin and end letters
            global $StartingLetter;
            global $EndingLetter;
            $StartingLetter = "";
            $EndingLetter = "";
            if ((strlen($LinkString) > 0) && ($LinkString != "X"))
            {
                list($StartingLetter, $EndingLetter) =
                    explode("&", $LinkString);
                list($Dummy, $Dummy, $StartingLetter) =
                    explode("=", $StartingLetter);
                list($Dummy, $EndingLetter) =
                    explode("=", $EndingLetter);
            }
            $SysConfig->TopLinkBeginLetter($StartingLetter);
            $SysConfig->TopLinkEndLetter($EndingLetter);
        }
    }

    # if link string is placeholder
    if ($LinkString == "X")
    {
        # clear link string
        $LinkString = "";
    }
    # else
    else
    {
        # if link string is not empty
        if ($LinkString != "")
        {
            # insert target browse page name into link string
            $LinkString = preg_replace(
                "/BROWSEPAGE/", "index.php?P=BrowseResources", $LinkString);

            # insert editing flag value into link string
            $LinkString = preg_replace(
                "/EDITFLAG/", (EditingEnabled() ? "1" : "0"), $LinkString);
        }
    }

    # return link string to caller
    return $LinkString;
}

function GetTreeName()
{
    global $Schema;

    $Field = $Schema->GetField(GetBrowsingFieldId());
    return $Field->Name();
}

function PrintTreeName()
{
    print GetTreeName();
}

function GetClassificationCount()
{
    global $ParentId;
    global $StartingLetter;
    global $EndingLetter;

    $ClassDB = new Database();

    $ClassDB->Query(GetClassificationDBQuery(
                        $ParentId, $StartingLetter, $EndingLetter));

    # retrieve count of entries to be displayed
    return $ClassDB->NumRowsSelected();
}

function DisplayClassificationList()
{
    global $NumberOfColumns;
    global $MinEntriesPerColumn;
    global $ParentId;
    global $StartingLetter;
    global $EndingLetter;

    $ClassDB = new Database();

    # retrieve entries to be displayed
    $ClassDB->Query(GetClassificationDBQuery(
                        $ParentId, $StartingLetter, $EndingLetter));

    # retrieve count of entries to be displayed
    $RecordCount = $ClassDB->NumRowsSelected();

    # for each entry
    $ClassCount = 0;
    while ($Class = $ClassDB->FetchRow())
    {
        # if filter function defined
        $ClassId = $Class["ClassificationId"];
        if (function_exists("FilterClassificationBrowseList"))
        {
            # call filter function to find out if okay to display entry
            $DoNotDisplay = FilterClassificationBrowseList($ClassId);
        }
        else
        {
            # assume okay to display entry
            $DoNotDisplay = FALSE;
        }

        # if okay to display entry
        if ($DoNotDisplay == FALSE)
        {
            # if entries per column limit reached
            $ClassCount++;
            if (($ClassCount > intval($RecordCount / intval($NumberOfColumns)))
                && ($ClassCount > $MinEntriesPerColumn))
            {
                # move to next column
                MoveToNextClassificationColumn();
                $ClassCount = 0;
            }

            # construct link address
            $LinkUrl = sprintf("index.php?P=BrowseResources&amp;ParentId=%d",
                               $Class["ClassificationId"]);
            if (EditingEnabled()) {  $LinkUrl .= "&amp;Editing=1";  }

            # construct link address for editing
            $EditLinkUrl = sprintf("index.php?P=EditClassification"
                                   ."&amp;ClassificationId=%d",
                                   $Class["ClassificationId"]);

            # print entry
            PrintClassificationEntry(stripslashes($Class["SegmentName"]),
                                     $LinkUrl,
                                     $Class["ResourceCount"],
                                     $EditLinkUrl);
        }
    }
}

function PrintRootClassification($LinkStyle = "")
{
    global $ParentId;

    # print root classification HTML string
    print(GetRootClassification($ParentId, $LinkStyle=""));
}

function EditingEnabled()
{
    global $User;
    global $Editing;

    if ($Editing == 1 && $User->HasPriv(PRIV_CLASSADMIN))
    {  return true;  } else {  return false;  }
}

function PrintAddClassificationLink()
{
    global $ParentId;
    global $SysConfig;

    print("index.php?P=AddClassification&amp;ParentId=".$ParentId
          ."&amp;FieldId=".GetBrowsingFieldId());
}

function GetResourceCount()
{
    static $ResourceCount;

    # if we have not already calculated count of resources
    if (isset($ResourceCount) == FALSE)
    {
        global $ParentId;

        # if resource browsing filter function is defined
        $ClassId = $ParentId;
        $DB = new Database();
        if (function_exists("FilterResourceBrowseList"))
        {
            # call filter func for each resource to determine count
            $ResourceCount = 0;
            $DB->Query(
                "SELECT Resources.ResourceId AS RsrcId "
                ."FROM Resources, ResourceClassInts "
                ."WHERE ResourceClassInts.ClassificationId = "
                .intval($ClassId)." "
                ."AND Resources.ResourceId = ResourceClassInts.ResourceId "
                ."AND Resources.ReleaseFlag = 1");
            while ($ResourceId = $DB->FetchField("RsrcId"))
            {
                if (FilterResourceBrowseList($ResourceId) == FALSE)
                {
                    $ResourceCount++;
                }
            }
        }
        else
        {
            # retrieve count via DB query
            $ResourceCount = $DB->Query(
                "SELECT COUNT(*) AS ResourceCount "
                ."FROM Resources, ResourceClassInts "
                ."WHERE ResourceClassInts.ClassificationId = "
                .intval($ClassId)." "
                ."AND Resources.ResourceId = ResourceClassInts.ResourceId "
                ."AND Resources.ReleaseFlag = 1",
                "ResourceCount");
        }
    }

    # return count to caller
    return $ResourceCount;
}

function PreviousResourcesAvailable()
{
    global $StartingResourceIndex;
    return ($StartingResourceIndex > 0) ? TRUE : FALSE;
}

function NextResourcesAvailable()
{
    global $StartingResourceIndex;
    global $MaxResourcesPerPage;

    if (($StartingResourceIndex + $MaxResourcesPerPage) < GetResourceCount())
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

function PrintPreviousResourcesLink()
{
    global $StartingResourceIndex;
    global $MaxResourcesPerPage;
    global $ParentId;

    $Url = "index.php?P=BrowseResources&amp;ParentId=".$ParentId
        ."&amp;StartingResourceIndex="
        .($StartingResourceIndex - $MaxResourcesPerPage);
    if (EditingEnabled()) {  $Url .= "&amp;Editing=1";  }
    print($Url);
}

function PrintNextResourcesLink()
{
    global $StartingResourceIndex;
    global $MaxResourcesPerPage;
    global $ParentId;

    $Url = "index.php?P=BrowseResources&amp;ParentId=".$ParentId
        ."&amp;StartingResourceIndex="
        .($StartingResourceIndex + $MaxResourcesPerPage);
    if (EditingEnabled()) {  $Url .= "&amp;Editing=1";  }
    print($Url);
}

function PrintNumberOfPreviousResources()
{
    global $MaxResourcesPerPage;
    print($MaxResourcesPerPage);
}

function PrintNumberOfNextResources()
{
    global $MaxResourcesPerPage;
    global $StartingResourceIndex;
    print(min($MaxResourcesPerPage,
              (GetResourceCount() - ($StartingResourceIndex +
                                     $MaxResourcesPerPage))));
}

function DisplayResourceList()
{
    global $NumberOfColumns;
    global $MinEntriesPerColumn;
    global $ParentId;
    global $StartingLetter;
    global $EndingLetter;
    global $G_User;
    global $StartingResourceIndex;
    global $MaxResourcesPerPage;

    $ResourceDB = new Database();

    # retrieve entries to be displayed
    $ResourceDB->Query(
        "SELECT * FROM Resources, ResourceClassInts "
        ."WHERE ResourceClassInts.ClassificationId = ".intval($ParentId)." "
        ."AND Resources.ResourceId = ResourceClassInts.ResourceId "
        ."AND Resources.ReleaseFlag = 1 "
        ."ORDER BY Resources.Title");

    # for each entry
    $ResourceIndex = 0;
    while ($Record = $ResourceDB->FetchRow())
    {
        # if filter function defined
        $ResourceId = $Record["ResourceId"];
        if (function_exists("FilterResourceBrowseList"))
        {
            # call filter function to find out if okay to display entry
            $DoNotDisplay = FilterResourceBrowseList($ResourceId);
        }
        else
        {
            # assume okay to display entry
            $DoNotDisplay = FALSE;
        }

        # if okay to display entry
        if ($DoNotDisplay == FALSE)
        {
            # if within resource range for this page
            if (($ResourceIndex >= $StartingResourceIndex)
                && ($ResourceIndex <
                    ($StartingResourceIndex + $MaxResourcesPerPage)))
            {
                # print entry
                $ResourceId = $Record["ResourceId"];
                $Resource = new Resource($ResourceId);
                PrintResourceEntry(
                    $Resource,
                    "index.php?P=FullRecord&amp;ResourceId=".$ResourceId,
                    $Resource->UserCanEdit($G_User),
                    "index.php?P=DBEntry&amp;ResourceId=".$ResourceId,
                    $Resource->ScaledCumulativeRating());
            }

            # increment count of resources displayed
            $ResourceIndex++;
        }
    }
}

/**
 * THIS FUNCTION IS DEPRECATED
 */
function PrintBrowsingLinks()
{
    $Links = GetBrowsingLinks();
    foreach ($Links as $Name => $Link)
    {
        print("<a href=\"".$Link."\">Browse by ".$Name."</a><br>");
    }
}

/**
 * THIS FUNCTION IS DEPRECATED
 */
function GetBrowsingLinks()
{
    $Schema = new MetadataSchema();
    $Fields = $Schema->GetFields(MetadataSchema::MDFTYPE_TREE);
    $BrowsingFieldId = GetBrowsingFieldId();

    $Links = array();
    foreach ($Fields as $Field)
    {
        if ($Field->Enabled() && $Field->Viewable()
            && $Field->Id() != $BrowsingFieldId)
        {
            $Links[$Field->Name()] =
                "index.php?P=BrowseResources&amp;FieldId=".$Field->Id();
        }
    }
    return $Links;
}

# ----- LOCAL FUNCTIONS ------------------------------------------------------

function GetBrowsingFieldId()
{
    global $SysConfig;
    global $User;
    global $BrowsingFieldId;

    global $ParentId;
    if (isset($ParentId) && ($ParentId >= 0))
    {
        $Parent = new Classification($ParentId);
        $FieldId = $Parent->FieldId();
    }
    elseif (isset($BrowsingFieldId))
        $FieldId = $BrowsingFieldId;
    else if ($User->IsLoggedIn())
    {
        $FieldId = $User->Get("BrowsingFieldId");
        if (empty($FieldId))
            $FieldId = $SysConfig->BrowsingFieldId();
    }
    else
        $FieldId = $SysConfig->BrowsingFieldId();

    return $FieldId;
}

function BuildClassificationLinkString($ParentId)
{
    global $SysConfig;

    $DB = new SPTDatabase();

    $MaxClassesPerPage = $SysConfig->NumClassesPerBrowsePage();
    if ($MaxClassesPerPage < 1) {  $MaxClassesPerPage = 1;  }

    # load classification names from database
    $DB->Query("SELECT SegmentName FROM Classifications "
               ."WHERE FieldId="
               .GetBrowsingFieldId()." "
               ."AND ".(($ParentId > 0) ? "ParentId="
                        .intval($ParentId)." " : "Depth=0 "
                        ."AND ResourceCount != 0 ")
               ."ORDER BY SegmentName ");
    $TotalClasses = 0;
    while ($Row = $DB->FetchRow())
    {
        $ClassName = trim(stripslashes($Row["SegmentName"]));
        if ($ClassName != "")
        {
            $ClassName = preg_replace("/[^A-Za-z]/", "", $ClassName);
            $ClassNames[$TotalClasses] = ucfirst(strtolower($ClassName));
            $TotalClasses++;
        }
    }

    # if all classes will fit on a single page
    if ($TotalClasses <= $MaxClassesPerPage)
    {
        # set link string to null value
        $LinkString = "X";
    }
    else
    {
        # while not end of classifications
        $Offset = 0;
        $ClassesPerPage = $MaxClassesPerPage;
        $StartingLetter = "A";
        $LinkString = "";
        while ($Offset < $TotalClasses)
        {
            # if starting letter is one letter
            if (strlen($StartingLetter) == 1)
            {
                # if starting letter has more classes than will fit on one page
                $ClassCount = $DB->Query(
                    "SELECT COUNT(*) AS ClassCount FROM Classifications "
                    ."WHERE FieldId="
                    .GetBrowsingFieldId()." "
                    ."AND ".(($ParentId > 0) ? "ParentId="
                             .intval($ParentId)." " : "Depth=0 "
                             ."AND SegmentName>='".$StartingLetter."' "
                             ."AND SegmentName<='".$StartingLetter
                             ."zzzzzzzzzz' "),
                    "ClassCount");
                if ($ClassCount > $MaxClassesPerPage)
                {
                    # calculate classes per page based on
                    # total classes for letter
                    $ClassesPerPage = intval($ClassCount /
                                             ceil($ClassCount /
                                                  $MaxClassesPerPage));

                    # reset starting letter to be first two-letter combo
                    # for letters
                    $StartingLetter .= "a";
                }
            }

            # calc new offset
            $Offset += $ClassesPerPage;

            # if starting letter is two letters
            if (strlen($StartingLetter) == 2)
            {
                # if first letter of offset class is same as starting letter
                if (ord($ClassNames[$Offset]) == ord($StartingLetter))
                {
                    # if at the end of classes
                    if (($Offset + $ClassesPerPage) >= $TotalClasses)
                    {
                        # set offset to last class
                        $Offset = $TotalClasses - 1;
                    }
                    else
                    {
                        # if second letter of offset class is
                        # different from starting letter
                        $OffsetClassLetter = substr($ClassNames[$Offset], 1, 1);
                        if (ord($OffsetClassLetter)
                            > ord(substr($ClassNames[$Offset -
                                                     $ClassesPerPage], 1, 1)))
                        {
                            # step offset backward until second
                            # letter of class changes
                            do
                            {
                                $Offset--;
                                $NewOffsetClassLetter =
                                    substr($ClassNames[$Offset], 1, 1);
                            } while ($NewOffsetClassLetter==$OffsetClassLetter);
                        }
                    }

                    # set ending letter to first two letters of class at offset
                    $EndingLetter = substr($ClassNames[$Offset], 0, 2);
                }
                else
                {
                    # if at the end of classes
                    if (($Offset + $ClassesPerPage) >= $TotalClasses)
                    {
                        # set offset to last class
                        $Offset = $TotalClasses - 1;
                    }
                    else
                    {
                        # step offset backward until first letter
                        # is same as starting letter
                        do
                        {
                            $Offset--;
                        } while (isset($ClassNames[$Offset])
                                 && (ord($ClassNames[$Offset]) >
                                     ord($StartingLetter)));
                    }

                    # set ending letter to first letter of
                    # class at offset plus "z"
                    $EndingLetter = substr($ClassNames[$Offset], 0, 1)."z";

                    # reset classes per page value
                    $ClassesPerPage = $MaxClassesPerPage;
                }
            }
            # else
            else
            {
                # if at the end of classes
                if (($Offset + $ClassesPerPage) >= $TotalClasses)
                {
                    # set offset to last class
                    $Offset = $TotalClasses - 1;
                }
                else
                {
                    # step offset backward until first letter of class changes
                    $Offset = min($Offset, (count($ClassNames) - 1));
                    $OffsetClassLetterVal =
                        ord(substr($ClassNames[$Offset], 0, 1));
                    do
                    {
                        $Offset--;
                    } while (isset($ClassNames[$Offset])
                            && (ord($ClassNames[$Offset]) ==
                                $OffsetClassLetterVal));
                }

                # if starting letter is two letters
                if (strlen($StartingLetter) == 2)
                {
                    # set ending letter to last two-letter combo for letter
                    $EndingLetter = substr($StartingLetter, 0, 1)."z";

                    # reset classes per page value
                    $ClassesPerPage = $MaxClassesPerPage;
                }
                # else
                else
                {
                    # set ending letter to first letter of class at offset
                    $EndingLetter = substr($ClassNames[$Offset], 0, 1);
                }
            }

            # add starting and ending letter to link string
            $LinkString .= " <a href='BROWSEPAGE"
                ."&amp;StartingLetter=".$StartingLetter
                ."&amp;EndingLetter=".$EndingLetter
                .(($ParentId > 0) ? "&amp;ParentId=".$ParentId : "")
                ."&amp;Editing=EDITFLAG'>".$StartingLetter
                .(($StartingLetter == $EndingLetter) ? "" : "-".$EndingLetter)
                ."</a>";

            # step offset forward one
            $Offset++;

            # if ending letter is one letter or is last two-letter combo
            if ((strlen($EndingLetter) == 1) ||
                (substr($EndingLetter, 1, 1) == "z"))
            {
                # set starting letter to next letter after ending letter
                $StartingLetter = chr(ord($EndingLetter)+1);
            }
            else
            {
                # set starting letter to next two-letter combo
                # after ending letter
                $StartingLetter = substr($EndingLetter, 0, 1)
                    .chr(ord(substr($EndingLetter, 1, 1))+1);
            }
        }
    }
    return $LinkString;
}

function GetClassificationDBQuery($ParentId, $StartingLetter, $EndingLetter)
{
    global $SysConfig;

    if ($ParentId > 0)
    {
        $QueryString =
            "SELECT * FROM Classifications "
            ."WHERE ParentId=".intval($ParentId)." AND FieldId="
            .GetBrowsingFieldId()." "
            .(EditingEnabled() ? "" : "AND ResourceCount != 0 ")
            ."ORDER BY ClassificationName";
    }
    else
    {
        $QueryString =
            "SELECT * FROM Classifications "
            ."WHERE Depth=0  AND FieldId="
            .GetBrowsingFieldId()." "
            ."AND ClassificationName >= '".addslashes($StartingLetter)."' "
            ."AND ClassificationName <= '".addslashes($EndingLetter)
            ."ZZZZZZZZZZ' "
            .(EditingEnabled() ? "" : "AND ResourceCount != 0 ")
            ."ORDER BY ClassificationName";
    }
    return $QueryString;
}

function GetResourceDBQuery($ClassId)
{
    $QueryString =
        "SELECT * FROM Resources, ResourceClassInts "
        ."WHERE ResourceClassInts.ClassificationId = ".intval($ClassId)." "
        ."AND Resources.ResourceId = ResourceClassInts.ResourceId "
        ."AND Resources.ReleaseFlag = 1 "
        ."ORDER BY Resources.Title ";

    return $QueryString;
}

function GetRootClassification($ParentId, $LinkStyle="")
{
    # start with empty string
    $RootClassString = "";

    # if top of classification tree specified
    if ($ParentId > 0)
    {
        # do while classification segments left to add
        do
        {
            # if not first segment in string
            if ($RootClassString != "")
            {
                # add segment separator to string
                $RootClassString = " -- ".$RootClassString;
            }

            # get current segment name
            $Class = new Classification($ParentId);

            # add current segment to string
            $RootClassString =
                "<a href='index.php?P=BrowseResources&amp;ParentId="
                .$ParentId
                .(EditingEnabled() ? "&amp;Editing=1" : "")
                ."' class='".$LinkStyle."'>"
                .$Class->SegmentName()."</a>"
                .$RootClassString;

            # move to next segment
            $ParentId = $Class->ParentId();

        } while ($ParentId > 0);
    }

    # return root classification HTML string to caller
    return $RootClassString;
}


# ----- MAIN -----------------------------------------------------------------

# non-standard global variables
global $BrowsingFieldId;
global $Editing;
global $EndingLetter;
global $MaxResourcesPerPage;
global $MinEntriesPerColumn;
global $NumberOfColumns;
global $ParentId;
global $Schema;
global $StartingLetter;
global $StartingResourceIndex;

# set up default display parameters
$NumberOfColumns = $SysConfig->NumColumnsPerBrowsePage();
$MinEntriesPerColumn = 3;
$MaxResourcesPerPage = 10;

if (isset($_GET["Editing"]))
    $Editing = intval($_GET["Editing"]);
else
    $Editing = 0;

$Schema = new MetadataSchema();

if (isset($_POST["F_BrowsingFieldId"]))
{
    $BrowsingFieldId = intval($_POST["F_BrowsingFieldId"]);
    $User->Set("BrowsingFieldId", $BrowsingFieldId);
}
elseif (isset($_GET["FieldId"]))
{
    $BrowsingFieldId = intval($_GET["FieldId"]);
    $User->Set("BrowsingFieldId", $BrowsingFieldId);
}

if (isset($_GET["StartingResourceIndex"]))
    $StartingResourceIndex = intval($_GET["StartingResourceIndex"]);
else
    $StartingResourceIndex = 0;

$ParentId = isset($_GET["ID"]) ? intval($_GET["ID"])
        : (isset($_GET["ParentId"]) ? intval($_GET["ParentId"]) : -1);

# set to stored system default browse range
if (isset($_GET["StartingLetter"]))
    $StartingLetter = substr($_GET["StartingLetter"], 0, 2);
else
    $StartingLetter = NULL;

if (isset($_GET["EndingLetter"]))
    $EndingLetter = substr($_GET["EndingLetter"], 0, 2);
else
    $EndingLetter = NULL;

if (!strlen($StartingLetter))
{
    $StartingLetter = $SysConfig->TopLinkBeginLetter();
    $EndingLetter = $SysConfig->TopLinkEndLetter();
}

if (!strlen($StartingLetter)) {  $StartingLetter = " ";  }
if (!strlen($EndingLetter))   {  $EndingLetter = "Z";  }
