/**
  * Load a full configuration (walk the whole heirarchy)
  *
  * @param string $name Name of config to load
  * @return array
  */
 function &GetConfig($name, $setcurrent = true, $role = "", $skipcache = false)
 {
     Profiler::StartTimer("ConfigManager::GetConfig()", 2);
     $ret = array();
     if ($name != "base" && strpos($name, ".") === false && strpos($name, "abtest") === false) {
         $name = "cobrand.{$name}";
     }
     $cachewrapper = null;
     $cachekey = "config.{$role}.{$name}";
     $data = DataManager::singleton();
     $cachewrapper =& $data->caches["apc"]["default"];
     $allversions = $this->GetAllRevisions($role);
     if (!$skipcache && !empty($cachewrapper) && $cachewrapper->enabled) {
         if (($cachedresult = $cachewrapper->get($cachekey)) !== false) {
             /*
             Logger::Info("Found '$cachekey' in apc cache (revision=" . $ret["revision"] . ")");
             $ret = unserialize($cachedresult);
             
             $versions = array();
             if (($cachedversions = $cachewrapper->get($cachekey . ".versions")) !== false ) {
               $versions = unserialize($cachedversions);
               $versionlog = "Found '$cachekey.versions' in apc cache (" . implode(", ", array_map(create_function('$a, $b', 'return "$a=$b";'), array_keys($versions), array_values($versions))) . ")";
               Logger::Info($versionlog);
             }
             $includes = $this->GetConfigHeirarchy($name, $role);
             */
             // New code transitioning to Config object
             // FIXME - this whole function should just be boiled down to a couple class functions
             $cachedcfg = unserialize($cachedresult);
             $ret = $cachedcfg->getConfig();
             $versions = $cachedcfg->getVersions();
             $includes = $cachedcfg->getHeirarchy();
             Logger::Info("Found '{$cachekey}' in apc cache (revision=" . $versions[$name] . " - " . implode(", ", array_map(create_function('$a, $b', 'return "$a=$b";'), array_keys($versions), array_values($versions))) . ")");
             // Check version numbers of all parents - if any have changed, invalidate the config and force a reload
             $allgood = true;
             foreach ($includes as $i => $inc) {
                 //$retinc = unserialize($cachewrapper->get("config.$role.$inc"));
                 //$vinc = $this->GetCobrandidAndRevision($inc, $role);
                 //if ($versions[$inc] < $vinc["revision"]){
                 if ($versions[$inc] < $allversions[$inc]) {
                     Logger::Warn("Revision number for '{$name}' parent '{$inc}' is out of date (old revision=" . $versions[$inc] . " new revision=" . $allversions[$inc] . ")");
                     $ret = array();
                     $skipcache = true;
                     $allgood = false;
                     /*
                     for ($j = $i; $j >= 0; $j--) { // Clear cache entries for anything above this one
                       Logger::Info("Delete cache: {$includes[$j]}");
                       $cachewrapper->delete("config.$role.{$includes[$j]}");
                       $cachewrapper->delete("config.$role.{$includes[$j]}.heirarchy");
                       $cachewrapper->delete("config.$role.{$includes[$j]}.versions");
                     }
                     */
                 }
             }
             if ($allgood) {
                 Logger::Info("Cached config for '{$name}' is up-to-date");
             }
         }
     }
     if (empty($ret)) {
         // Check to see if config exists in memory - if it doesn't, fetch it
         $config = null;
         $configversions = array();
         if (!empty($this->configs[$name])) {
             $config = $this->configs[$name];
         } else {
             $config = $this->Load($name, $role);
         }
         if (!empty($config)) {
             // Process includes first
             if (!empty($config["include"])) {
                 $includes = explode(",", $config["include"]);
                 foreach ($includes as $inc) {
                     $included_config =& $this->GetConfig($inc, false, $role, $skipcache);
                     if (!empty($included_config)) {
                         $this->ConfigMerge($ret, $included_config);
                     }
                 }
             }
             // Merge in my own config...
             $this->ConfigMerge($ret, $config);
             // and then merge in any overrides
             if (!empty($config["override"])) {
                 $includes = explode(",", $config["override"]);
                 foreach ($includes as $inc) {
                     $included_config =& $this->GetConfig($inc, false, $role, $skipcache);
                     if (!empty($included_config)) {
                         $this->ConfigMerge($ret, $included_config);
                     }
                 }
             }
         }
         if (!empty($ret) && !empty($cachewrapper) && $cachewrapper->enabled) {
             // Store merged config result in APC
             $configheirarchy = $this->GetConfigHeirarchy($name, $role, true);
             foreach ($configheirarchy as $inc) {
                 $included_version = $this->GetCobrandidAndRevision($inc, $role);
                 $configversions[$inc] = $allversions[$inc];
                 //$this->configs[$inc]["revision"];
             }
             /*
             Logger::Debug($configheirarchy);
             Logger::Debug($configversions);
             */
             $cachecfg = new Config();
             $cachecfg->setName($name);
             $cachecfg->setConfig($ret);
             $cachecfg->setHeirarchy($configheirarchy);
             $cachecfg->setVersions($configversions);
             $cachewrapper->set($cachekey, serialize($cachecfg));
             //$cachewrapper->set($cachekey . ".versions", serialize($configversions));
             Logger::Info("Set '{$cachekey}' in apc cache");
         }
     }
     if ($setcurrent) {
         $this->current = is_array($this->current) ? array_merge_recursive($this->current, $ret) : $ret;
         // Update locations to reflect any new settings we got from the cobrand config
         $this->locations = $this->getLocations();
     }
     Profiler::StopTimer("ConfigManager::GetConfig()");
     return $ret;
 }