/**
  * Instructs the module to refresh the routing XML cache file
  * This may not be called during manifest initialisation (_config.php) as database access is not available
  */
 public function RefreshCache()
 {
     // Builds XML cache file using all available routes
     $document = new DOMDocument();
     $document->formatOutput = true;
     $routes = $document->createElement('routes');
     $document->appendChild($routes);
     // append all routes
     $holderClasses = DateLink::config()->holder_classes;
     foreach ($holderClasses as $className) {
         foreach (DataObject::get($className) as $holderPage) {
             $route = $document->createElement('route');
             $link = $document->createElement('link', $holderPage->RelativeLink());
             $route->appendChild($link);
             $id = $document->createElement('page_id', $holderPage->ID);
             $route->appendChild($id);
             // Run through children and pull out all distinct year fields
             // We must use years in our URLS to distinguish all routes from non-numeric routes such as
             // page actions. It's not necessary to consider months, as by then the route will be sufficiently
             // distinguished.
             $children = $holderPage->AllChildren();
             $yearList = $this->determineYears($children);
             $years = $document->createElement('years');
             foreach ($yearList as $yearNumber) {
                 $year = $document->createElement('year', $yearNumber);
                 $years->appendChild($year);
             }
             $route->appendChild($years);
             $routes->appendChild($route);
         }
     }
     // Ensure output directory exists
     $outputPath = $this->getCacheFilePath();
     Filesystem::makeFolder(dirname($outputPath));
     $document->save($outputPath);
 }
 /**
  * Using the same rules that were used to generate the routing table, attempt to generate the original matching
  * url that corresponds to the current page
  * 
  * @param string &$base The URL of this page relative to siteroot, not including
  * the action
  * @param string|boolean &$action The action or subpage called on this page.
  * (Legacy support) If this is true, then do not reduce the 'home' urlsegment
  * to an empty link
  */
 public function updateRelativeLink(&$base, &$action)
 {
     // Avoid rewriting urls for pages not to be rewritten
     if (!$this->dateEnabled()) {
         return;
     }
     // Determine raw date
     $dateValue = $this->owner->getRouteDate();
     if (empty($dateValue)) {
         return;
     }
     $date = new DateTime($dateValue);
     // Get pattern to use as a base for this link
     $pattern = DateLink::config()->url_pattern;
     // Substitute parent link
     $parentLink = trim($this->owner->Parent()->RelativeLink());
     $pattern = preg_replace('/\\$ParentLink!?/i', trim($parentLink, '/'), $pattern);
     // Substitute parent segment
     $pattern = preg_replace('/\\$URLSegment!?/i', $this->owner->URLSegment, $pattern);
     // Mapping of wildcards to date formats (in order of replacement)
     $dateReplacements = array('#$Month' => 'm', '$MonthName' => 'F', '$Month' => 'n', '#$Date' => 'd', '$Date' => 'j', '$Year' => 'Y', '$Weekday' => 'l');
     // Extract various date elements
     foreach ($dateReplacements as $search => $dateFormat) {
         $dateText = $date->format($dateFormat);
         $quotedSearch = preg_quote($search);
         $pattern = preg_replace("/{$quotedSearch}!?/i", $dateText, $pattern);
     }
     // Replace everything after the // with /$action
     if ($action === true) {
         $action = '';
     }
     $base = preg_replace('/\\/\\/.*$/', "/{$action}", $pattern);
 }