[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/File/ -> Resolver.php (source)

   1  <?php
   2  
   3  namespace dokuwiki\File;
   4  
   5  /**
   6   * Resolving relative IDs to absolute ones
   7   */
   8  abstract class Resolver
   9  {
  10      /** @var string context page ID */
  11      protected $contextID;
  12      /** @var string namespace of context page ID */
  13      protected $contextNS;
  14  
  15      /**
  16       * @param string $contextID the current pageID that's the context to resolve relative IDs to
  17       */
  18      public function __construct($contextID)
  19      {
  20          $this->contextID = $contextID;
  21          $this->contextNS = (string)getNS($contextID);
  22      }
  23  
  24      /**
  25       * Resolves a given ID to be absolute
  26       *
  27       * @param string $id The ID to resolve
  28       * @param string|int|false $rev The revision time to use when resolving
  29       * @param bool $isDateAt Is the given revision only a datetime hint not an exact revision?
  30       * @return string
  31       */
  32      public function resolveId($id, $rev = '', $isDateAt = false)
  33      {
  34          global $conf;
  35  
  36          // some pre cleaning for useslash:
  37          if ($conf['useslash']) $id = str_replace('/', ':', $id);
  38          // on some systems, semicolons might be used instead of colons:
  39          $id = str_replace(';', ':', $id);
  40  
  41          $id = $this->resolvePrefix($id);
  42          return $this->resolveRelatives($id);
  43      }
  44  
  45      /**
  46       * Handle IDs starting with . or ~ and prepend the proper prefix
  47       *
  48       * @param string $id
  49       * @return string
  50       */
  51      protected function resolvePrefix($id)
  52      {
  53          if ($id === '') return $id;
  54  
  55          // relative to current page (makes the current page a start page)
  56          if ($id[0] === '~') {
  57              $id = $this->contextID . ':' . substr($id, 1);
  58          }
  59  
  60          // relative to current namespace
  61          if ($id[0] === '.') {
  62              // normalize initial dots without a colon
  63              $id = preg_replace('/^((\.+:)*)(\.+)(?=[^:\.])/', '\1\3:', $id);
  64              $id = $this->contextNS . ':' . $id;
  65          }
  66  
  67          // auto-relative, because there is a context namespace but no namespace in the ID
  68          if ($this->contextID !== '' && strpos($id, ':') === false) {
  69              $id = $this->contextNS . ':' . $id;
  70          }
  71  
  72          return $id;
  73      }
  74  
  75      /**
  76       * Handle . and .. within IDs
  77       *
  78       * @param string $id
  79       * @return string
  80       */
  81      protected function resolveRelatives($id)
  82      {
  83          $id = rtrim($id, '.'); // trailing dots are invalid
  84          if ($id === '') return '';
  85          $trail = ($id[-1] === ':') ? ':' : ''; // keep trailing colon
  86  
  87          $result = [];
  88          $parts = explode(':', $id);
  89  
  90          foreach ($parts as $dir) {
  91              if ($dir === '.') continue;
  92              if ($dir === '') continue;
  93              if ($dir === '..') {
  94                  array_pop($result);
  95                  continue;
  96              }
  97              $result[] = $dir;
  98          }
  99  
 100          $id = implode(':', $result);
 101          $id .= $trail;
 102  
 103          return $id;
 104      }
 105  }