/**
 * Dynamic Sitemap function
 * 
 * Includes all boxes in includes/boxes/
 * indexes their title and links
 * Converts this into xhtml <ul><li></li></ul>
 * Creates a cache file called <languages_id>_boxes.ser
 * indexing is not needed or performed once the cache is created.
 *
 * @param $cachepath path to the .ser cache files
 * @param $languages_id
 * @param $exclude_array an array of boxes files to exclude
 * mapBoxes is dynamic but a bit stupid/greedy it will try to index everything
 * if a box is just not working then add the filename to the $exclude_array
 * A prime example is best_sellers.php that doesn't use propper html links
 * 
 * @return returns well formed code to be added to the right <td> of catalog/sitemap.php
 */
function mapBoxes($cachepath, $languages_id)
{
    $boxes_cache_path = $cachepath . $languages_id . '_boxes.ser';
    // If the file doesn't exist or we are resetting then we'll recache
    if (!file_exists($boxes_cache_path) || defined('FWR_MENU_RESET') && FWR_MENU_RESET == 'true') {
        // Exclude boxes that are not appropriate for the site map
        $exclude_array = array('categories.php', 'currencies.php', 'languages.php', 'manufacturer.php', 'order_history.php', 'product_notifications.php', 'reviews.php', 'search.php', 'shopping_cart.php', 'specials.php', 'tell_a_friend.php', 'whats_new.php', 'wishlist.php');
        $path = DIR_WS_INCLUDES . 'boxes/';
        $handle = opendir(DIR_WS_INCLUDES . 'boxes/');
        // Grab all the boxes files
        while ($file = readdir($handle)) {
            if ($file != '.' && $file != '..' && $file != '.svn' && strrchr($file, '.php') === '.php') {
                if (is_file($path . $file)) {
                    // Has to be a full path or catches files too
                    if (!in_array($file, $exclude_array)) {
                        $boxes_files[] = $file;
                    }
                }
            }
        }
        closedir($handle);
        $i = 0;
        foreach ($boxes_files as $file) {
            $files[] = $file;
            ob_start();
            // Start output buffering
            include $path . $file;
            // include the /includes/boxes file
            $html = ob_get_contents();
            // Pass buffer contents to $html
            ob_end_clean();
            // Clear the buffer
            $pattern = '@<a[^>]+>([^<]+)</a>@';
            //pattern to grab all propper html links
            preg_match_all($pattern, $html, $matches);
            $all_matches[$file] = $matches;
            unset($html);
        }
        $serialized = serialize($all_matches);
        // Serialize the code for storage
        // Save the serialized code so that next load we have little work to do
        saveSerializedFile($cachepath, $serialized, $languages_id, "_boxes.ser");
    } else {
        // We are not resetting and the cache file exists so lets load the serialized file
        $all_matches = loadSerializedFile($cachepath, $languages_id, "_boxes.ser");
    }
    /**
     * Loop through the matches created by the preg_match_all() search for links for this file
     */
    foreach ($all_matches as $file => $value) {
        $fwr_boxheading = '';
        /**
         * Find the box heading title
         * 
         * Firstly check if the defined exists and is using propper oscommerce structure
         * e.g. the defined heading title for example_box.php should be BOX_HEADING_EXAMPLE_BOX
         * If not we will just have to use the file name and hope it is reasonably named
         * e.g. example_box.php will be converted to Example Box
         */
        if (!empty($value[0])) {
            // If it is empty we'll ignore it and move to the next loop
            ob_start();
            // Start output buffering
            $file_stripped = str_replace('.php', '', $file);
            if (defined('BOX_HEADING_' . strtoupper($file_stripped))) {
                $fwr_boxheading = constant('BOX_HEADING_' . strtoupper($file_stripped));
            } else {
                $fwr_boxheading = ucwords(str_replace(array('_', '-'), array(' ', ' '), $file_stripped));
            }
            ?>
<ul>
  <li><?php 
            echo $fwr_boxheading . "\n";
            ?>
   <ul>
<?php 
            $count = count($value[0]);
            // How many links did we find?
            /**
             * Loop through each <a href="">link</a>
             * Stripping it into its component parts
             */
            for ($i = 0; $i < $count; $i++) {
                // Reformat the url
                $end_link = strstr($value[0][$i], '.php');
                // Holds from .php to the end
                $link_close = strstr($end_link, '"');
                // Holds from the next " after .php to the end of the link ">title</a>
                // Strip down to the querystring and replacing the ? with &
                $querystring = str_replace(array($link_close, '?'), array('', '&'), strstr($end_link, '?'));
                $qs_array = explode('&', $querystring);
                // explode the querystring into an array via &
                $filename = str_replace('/', '', strrchr(str_replace($end_link, '', $value[0][$i]), '/')) . '.php';
                // The filename.php
                unset($end_link, $querystring, $value[0][$i]);
                // Housekeeping
                $count2 = count($qs_array);
                // How many querystring items do we have?
                $seperator = '';
                for ($qsi = 0; $qsi < $count2; $qsi++) {
                    // Loop through the querystring parts
                    if (false === is_integer(strpos($qs_array[$qsi], 'osCsid'))) {
                        // Ignore it if is an osCsid -- GO AWAY NOT WANTED!
                        $params .= $seperator . $qs_array[$qsi];
                        // Add it to our params with the correct seperator
                        $seperator = '&amp;';
                        // If we are here then we have used the '' seperator so we have to start using &
                    }
                }
                // Below we generate a shiny new URL
                ?>
     <li><a href="<?php 
                echo tep_href_link($filename, $params) . $link_close;
                ?>
</li>
<?php 
            }
            ?>
   </ul>  
  </li>
</ul>
<?php 
            $boxes_string .= ob_get_contents();
            // Pass the buffer contents to $boxes_string
            ob_end_clean();
            // Clear the buffer
        }
    }
    return $boxes_string;
    // We've mapped our boxes so send it back to buildSiteMap where it will be added to catalog/sitemap.php
}
} else {
    $cachepath = constant(FWR_MENU_CACHE_PATH);
}
/**
 * Or we simple load the <languages_id>_categories.ser file and use no query.
 * @param $categories variable is created in includes/functions/fwr_cat_functions.php
 * by function buildCategoriesCache() $categories array can be seperated for understanding into 3 sub variables
 * $categories[<category_id>] holds all of the category info and is multi dimensional
 * $categories['menuid_string'] contains the id of all the parent categories which is needed by suckertree
 * $categories['menuid_js'] contains javascript for suckertree that prints var menuids= using $categories['menuid_string']
 */
//  If the cache file exists OR we are resetting the menu we rebuild the cache using our one query.
if (!file_exists($cachepath . $languages_id . "_categories.ser") || defined('FWR_MENU_RESET') && FWR_MENU_RESET == 'true') {
    $categories = buildCategoriesCache($cachepath, FWR_MENU_ORDER_BY, $languages_id);
} else {
    $categories = loadSerializedFile($cachepath, $languages_id, "_categories.ser");
}
/**
 * @param $menuid_string is set from $categories['menuid_string']
 * it is used later by the sitemap addon of this script
 */
$menuid_string = $categories['menuid_string'];
// Print the javascript for the suckertree var menuids
echo $categories['menuid_js'] . PHP_EOL;
unset($categories['menuid_string'], $categories['menuid_js']);
// Housekeeping
$boxHeading = BOX_HEADING_CATEGORIES;
$corner_top_left = 'rounded';
$corner_top_right = 'rounded';
$corner_bottom_left = 'rounded';
$corner_bottom_right = 'rounded';