[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/ChangeLog/ -> RevisionInfo.php (source)

   1  <?php
   2  
   3  namespace dokuwiki\ChangeLog;
   4  
   5  /**
   6   * Class RevisionInfo
   7   *
   8   * Provides methods to show Revision Information in DokuWiki Ui components:
   9   *  - Ui\Recent
  10   *  - Ui\PageRevisions
  11   *  - Ui\MediaRevisions
  12   */
  13  class RevisionInfo
  14  {
  15      /* @var array */
  16      protected $info;
  17  
  18      /**
  19       * Constructor
  20       *
  21       * @param array $info Revision Information structure with entries:
  22       *      - date:  unix timestamp
  23       *      - ip:    IPv4 or IPv6 address
  24       *      - type:  change type (log line type)
  25       *      - id:    page id
  26       *      - user:  user name
  27       *      - sum:   edit summary (or action reason)
  28       *      - extra: extra data (varies by line type)
  29       *      - sizechange: change of filesize
  30       *      additionally,
  31       *      - current:   (optional) whether current revision or not
  32       *      - timestamp: (optional) set only when external edits occurred
  33       *      - mode:  (internal use) ether "media" or "page"
  34       */
  35      public function __construct($info = null)
  36      {
  37          if (is_array($info) && isset($info['id'])) {
  38              // define strategy context
  39              $info['mode'] = $info['media'] ? 'media' : 'page';
  40          } else {
  41              $info = [
  42                  'mode' => 'page',
  43                  'date' => false,
  44              ];
  45          }
  46          $this->info = $info;
  47      }
  48  
  49      /**
  50       * Set or return whether this revision is current page or media file
  51       *
  52       * This method does not check exactly whether the revision is current or not. Instead,
  53       * set value of associated "current" key for internal use. Some UI element like diff
  54       * link button depend on relation to current page or media file. A changelog line does
  55       * not indicate whether it corresponds to current page or media file.
  56       *
  57       * @param bool $value true if the revision is current, otherwise false
  58       * @return bool
  59       */
  60      public function isCurrent($value = null)
  61      {
  62          return (bool) $this->val('current', $value);
  63      }
  64  
  65      /**
  66       * Return or set a value of associated key of revision information
  67       * but does not allow to change values of existing keys
  68       *
  69       * @param string $key
  70       * @param mixed $value
  71       * @return string|null
  72       */
  73      public function val($key, $value = null)
  74      {
  75          if (isset($value) && !array_key_exists($key, $this->info)) {
  76              // setter, only for new keys
  77              $this->info[$key] = $value;
  78          }
  79          if (array_key_exists($key, $this->info)) {
  80              // getter
  81              return $this->info[$key];
  82          }
  83          return null;
  84      }
  85  
  86      /**
  87       * Set extra key-value to the revision information
  88       * but does not allow to change values of existing keys
  89       * @param array $info
  90       * @return void
  91       */
  92      public function append(array $info)
  93      {
  94          foreach ($info as $key => $value) {
  95              $this->val($key, $value);
  96          }
  97      }
  98  
  99  
 100      /**
 101       * file icon of the page or media file
 102       * used in [Ui\recent]
 103       *
 104       * @return string
 105       */
 106      public function showFileIcon()
 107      {
 108          $id = $this->val('id');
 109          switch ($this->val('mode')) {
 110              case 'media': // media file revision
 111                  return media_printicon($id);
 112              case 'page': // page revision
 113                  return '<img class="icon" src="'.DOKU_BASE.'lib/images/fileicons/file.png" alt="'.$id.'" />';
 114          }
 115      }
 116  
 117      /**
 118       * edit date and time of the page or media file
 119       * used in [Ui\recent, Ui\Revisions]
 120       *
 121       * @param bool $checkTimestamp  enable timestamp check, alter formatted string when timestamp is false
 122       * @return string
 123       */
 124      public function showEditDate($checkTimestamp = false)
 125      {
 126          $formatted = dformat($this->val('date'));
 127          if ($checkTimestamp && $this->val('timestamp') === false) {
 128              // exact date is unknown for externally deleted file
 129              // when unknown, alter formatted string "YYYY-mm-DD HH:MM" to "____-__-__ __:__"
 130              $formatted = preg_replace('/[0-9a-zA-Z]/','_', $formatted);
 131          }
 132          return '<span class="date">'. $formatted .'</span>';
 133      }
 134  
 135      /**
 136       * edit summary
 137       * used in [Ui\recent, Ui\Revisions]
 138       *
 139       * @return string
 140       */
 141      public function showEditSummary()
 142      {
 143          return '<span class="sum">'.' – '. hsc($this->val('sum')).'</span>';
 144      }
 145  
 146      /**
 147       * editor of the page or media file
 148       * used in [Ui\recent, Ui\Revisions]
 149       *
 150       * @return string
 151       */
 152      public function showEditor()
 153      {
 154          if ($this->val('user')) {
 155              $html = '<bdi>'. editorinfo($this->val('user')) .'</bdi>';
 156              if (auth_ismanager()) $html .= ' <bdo dir="ltr">('. $this->val('ip') .')</bdo>';
 157          } else {
 158              $html = '<bdo dir="ltr">'. $this->val('ip') .'</bdo>';
 159          }
 160          return '<span class="user">'. $html. '</span>';
 161      }
 162  
 163      /**
 164       * name of the page or media file
 165       * used in [Ui\recent, Ui\Revisions]
 166       *
 167       * @return string
 168       */
 169      public function showFileName()
 170      {
 171          $id = $this->val('id');
 172          $rev = $this->isCurrent() ? '' : $this->val('date');
 173  
 174          switch ($this->val('mode')) {
 175              case 'media': // media file revision
 176                  $params = ['tab_details'=> 'view', 'ns'=> getNS($id), 'image'=> $id];
 177                  if ($rev) $params += ['rev'=> $rev];
 178                  $href = media_managerURL($params, '&');
 179                  $display_name = $id;
 180                  $exists = file_exists(mediaFN($id, $rev));
 181                  break;
 182              case 'page': // page revision
 183                  $params = $rev ? ['rev'=> $rev] : [];
 184                  $href = wl($id, $params, false, '&');
 185                  $display_name = useHeading('navigation') ? hsc(p_get_first_heading($id)) : $id;
 186                  if (!$display_name) $display_name = $id;
 187                  $exists = page_exists($id, $rev);
 188          }
 189  
 190          if($exists) {
 191              $class = 'wikilink1';
 192          } else {
 193              if($this->isCurrent()) {
 194                  //show only not-existing link for current page, which allows for directly create a new page/upload
 195                  $class = 'wikilink2';
 196              } else {
 197                  //revision is not in attic
 198                  return $display_name;
 199              }
 200          }
 201          if ($this->val('type') == DOKU_CHANGE_TYPE_DELETE) {
 202              $class = 'wikilink2';
 203          }
 204          return '<a href="'.$href.'" class="'.$class.'">'.$display_name.'</a>';
 205      }
 206  
 207      /**
 208       * Revision Title for PageDiff table headline
 209       *
 210       * @return string
 211       */
 212      public function showRevisionTitle()
 213      {
 214          global $lang;
 215  
 216          if (!$this->val('date')) return '&mdash;';
 217  
 218          $id = $this->val('id');
 219          $rev = $this->isCurrent() ? '' : $this->val('date');
 220          $params = ($rev) ? ['rev'=> $rev] : [];
 221  
 222          // revision info may have timestamp key when external edits occurred
 223          $date = ($this->val('timestamp') === false)
 224              ? $lang['unknowndate']
 225              : dformat($this->val('date'));
 226  
 227  
 228          switch ($this->val('mode')) {
 229              case 'media': // media file revision
 230                  $href = ml($id, $params, false, '&');
 231                  $exists = file_exists(mediaFN($id, $rev));
 232                  break;
 233              case 'page': // page revision
 234                  $href = wl($id, $params, false, '&');
 235                  $exists = page_exists($id, $rev);
 236          }
 237          if($exists) {
 238              $class = 'wikilink1';
 239          } else {
 240              if($this->isCurrent()) {
 241                  //show only not-existing link for current page, which allows for directly create a new page/upload
 242                  $class = 'wikilink2';
 243              } else {
 244                  //revision is not in attic
 245                  return $id.' ['.$date.']';
 246              }
 247          }
 248          if ($this->val('type') == DOKU_CHANGE_TYPE_DELETE) {
 249              $class = 'wikilink2';
 250          }
 251          return '<bdi><a class="'.$class.'" href="'.$href.'">'.$id.' ['.$date.']'.'</a></bdi>';
 252      }
 253  
 254      /**
 255       * diff link icon in recent changes list, to compare (this) current revision with previous one
 256       * all items in "recent changes" are current revision of the page or media
 257       *
 258       * @return string
 259       */
 260      public function showIconCompareWithPrevious()
 261      {
 262          global $lang;
 263          $id = $this->val('id');
 264  
 265          $href = '';
 266          switch ($this->val('mode')) {
 267              case 'media': // media file revision
 268                  // unlike page, media file does not copied to media_attic when uploaded.
 269                  // diff icon will not be shown when external edit occurred
 270                  // because no attic file to be compared with current.
 271                  $revs = (new MediaChangeLog($id))->getRevisions(0, 1);
 272                  $showLink = (count($revs) && file_exists(mediaFN($id,$revs[0])) && file_exists(mediaFN($id)));
 273                  if ($showLink) {
 274                      $param = ['tab_details'=>'history', 'mediado'=>'diff', 'ns'=> getNS($id), 'image'=> $id];
 275                      $href = media_managerURL($param, '&');
 276                  }
 277                  break;
 278              case 'page': // page revision
 279                  // when a page just created anyway, it is natural to expect no older revisions
 280                  // even if it had once existed but deleted before. Simply ignore to check changelog.
 281                  if ($this->val('type') !== DOKU_CHANGE_TYPE_CREATE) {
 282                      $href = wl($id, ['do'=>'diff'], false, '&');
 283                  }
 284          }
 285  
 286          if ($href) {
 287              return '<a href="'.$href.'" class="diff_link">'
 288                    .'<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
 289                    .' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />'
 290                    .'</a>';
 291          } else {
 292              return '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
 293          }
 294      }
 295  
 296      /**
 297       * diff link icon in revisions list, compare this revision with current one
 298       * the icon does not displayed for the current revision
 299       *
 300       * @return string
 301       */
 302      public function showIconCompareWithCurrent()
 303      {
 304          global $lang;
 305          $id = $this->val('id');
 306          $rev = $this->isCurrent() ? '' : $this->val('date');
 307  
 308          $href = '';
 309          switch ($this->val('mode')) {
 310              case 'media': // media file revision
 311                  if (!$this->isCurrent() && file_exists(mediaFN($id, $rev))) {
 312                      $param = ['mediado'=>'diff', 'image'=> $id, 'rev'=> $rev];
 313                      $href = media_managerURL($param, '&');
 314                  }
 315                  break;
 316              case 'page': // page revision
 317                  if (!$this->isCurrent()) {
 318                      $href = wl($id, ['rev'=> $rev, 'do'=>'diff'], false, '&');
 319                  }
 320          }
 321  
 322          if ($href) {
 323              return '<a href="'.$href.'" class="diff_link">'
 324                    .'<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
 325                    .' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />'
 326                    .'</a>';
 327          } else {
 328              return '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
 329          }
 330      }
 331  
 332      /**
 333       * icon for revision action
 334       * used in [Ui\recent]
 335       *
 336       * @return string
 337       */
 338      public function showIconRevisions()
 339      {
 340          global $lang;
 341  
 342          if (!actionOK('revisions')) {
 343              return '';
 344          }
 345  
 346          $id = $this->val('id');
 347          switch ($this->val('mode')) {
 348              case 'media': // media file revision
 349                  $param  = ['tab_details'=>'history', 'ns'=> getNS($id), 'image'=> $id];
 350                  $href = media_managerURL($param, '&');
 351                  break;
 352              case 'page': // page revision
 353                  $href = wl($id, ['do'=>'revisions'], false, '&');
 354          }
 355          return '<a href="'.$href.'" class="revisions_link">'
 356                . '<img src="'.DOKU_BASE.'lib/images/history.png" width="12" height="14"'
 357                . ' title="'.$lang['btn_revs'].'" alt="'.$lang['btn_revs'].'" />'
 358                . '</a>';
 359      }
 360  
 361      /**
 362       * size change
 363       * used in [Ui\recent, Ui\Revisions]
 364       *
 365       * @return string
 366       */
 367      public function showSizeChange()
 368      {
 369          $class = 'sizechange';
 370          $value = filesize_h(abs($this->val('sizechange')));
 371          if ($this->val('sizechange') > 0) {
 372              $class .= ' positive';
 373              $value = '+' . $value;
 374          } elseif ($this->val('sizechange') < 0) {
 375              $class .= ' negative';
 376              $value = '-' . $value;
 377          } else {
 378              $value = '±' . $value;
 379          }
 380          return '<span class="'.$class.'">'.$value.'</span>';
 381      }
 382  
 383      /**
 384       * current indicator, used in revision list
 385       * not used in Ui\Recent because recent files are always current one
 386       *
 387       * @return string
 388       */
 389      public function showCurrentIndicator()
 390      {
 391          global $lang;
 392          return $this->isCurrent() ? '('.$lang['current'].')' : '';
 393      }
 394  
 395  
 396  }