[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/Ui/ -> MediaDiff.php (source)

   1  <?php
   2  
   3  namespace dokuwiki\Ui;
   4  
   5  use dokuwiki\ChangeLog\MediaChangeLog;
   6  use dokuwiki\ChangeLog\RevisionInfo;
   7  use dokuwiki\Form\Form;
   8  use InvalidArgumentException;
   9  use JpegMeta;
  10  
  11  /**
  12   * DokuWiki MediaDiff Interface
  13   *
  14   * @package dokuwiki\Ui
  15   */
  16  class MediaDiff extends Diff
  17  {
  18      /* @var MediaChangeLog */
  19      protected $changelog;
  20  
  21      /* @var RevisionInfo older revision */
  22      protected $RevInfo1;
  23      /* @var RevisionInfo newer revision */
  24      protected $RevInfo2;
  25  
  26      /* @var bool */
  27      protected $is_img;
  28  
  29      /**
  30       * MediaDiff Ui constructor
  31       *
  32       * @param string $id media id
  33       */
  34      public function __construct($id)
  35      {
  36          if (!isset($id)) {
  37              throw new InvalidArgumentException('media id should not be empty!');
  38          }
  39  
  40          // init preference
  41          $this->preference['fromAjax'] = false;  // see dokuwiki\Ajax::callMediadiff()
  42          $this->preference['showIntro'] = false;
  43          $this->preference['difftype'] = 'both'; // diff view type: both, opacity or portions
  44  
  45          parent::__construct($id);
  46      }
  47  
  48      /** @inheritdoc */
  49      protected function setChangeLog()
  50      {
  51          $this->changelog = new MediaChangeLog($this->id);
  52      }
  53  
  54      /**
  55       * Handle requested revision(s) and diff view preferences
  56       *
  57       * @return void
  58       */
  59      protected function handle()
  60      {
  61          global $INPUT;
  62  
  63          // retrieve requested rev or rev2
  64          parent::handle();
  65  
  66          // requested diff view type
  67          if ($INPUT->has('difftype')) {
  68              $this->preference['difftype'] = $INPUT->str('difftype');
  69          }
  70      }
  71  
  72      /**
  73       * Prepare revision info of comparison pair
  74       */
  75      protected function preProcess()
  76      {
  77          $changelog =& $this->changelog;
  78  
  79          // create revision info object for older and newer sides
  80          // RevInfo1 : older, left side
  81          // RevInfo2 : newer, right side
  82  
  83          $changelogRev1 = $changelog->getRevisionInfo($this->rev1);
  84          $changelogRev2 = $changelog->getRevisionInfo($this->rev2);
  85          $changelogRev1['media'] = $changelogRev2['media'] = true;
  86  
  87          $this->RevInfo1 = new RevisionInfo($changelogRev1);
  88          $this->RevInfo2 = new RevisionInfo($changelogRev2);
  89  
  90          $this->is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id);
  91  
  92          foreach ([$this->RevInfo1, $this->RevInfo2] as $RevInfo) {
  93              $isCurrent = $changelog->isCurrentRevision($RevInfo->val('date'));
  94              $RevInfo->isCurrent($isCurrent);
  95  
  96              if ($this->is_img) {
  97                  $rev = $isCurrent ? '' : $RevInfo->val('date');
  98                  $meta = new JpegMeta(mediaFN($this->id, $rev));
  99                  // get image width and height for the media manager preview panel
 100                  $RevInfo->append([
 101                      'previewSize' => media_image_preview_size($this->id, $rev, $meta)
 102                  ]);
 103              }
 104          }
 105  
 106          // re-check image, ensure minimum image width for showImageDiff()
 107          $this->is_img = ($this->is_img
 108              && ($this->RevInfo1->val('previewSize')[0] ?? 0) >= 30
 109              && ($this->RevInfo2->val('previewSize')[0] ?? 0) >= 30
 110          );
 111          // adjust requested diff view type
 112          if (!$this->is_img) {
 113              $this->preference['difftype'] = 'both';
 114          }
 115      }
 116  
 117  
 118      /**
 119       * Shows difference between two revisions of media
 120       *
 121       * @author Kate Arzamastseva <pshns@ukr.net>
 122       */
 123      public function show()
 124      {
 125          global $conf;
 126  
 127          $ns = getNS($this->id);
 128          $auth = auth_quickaclcheck("$ns:*");
 129  
 130          if ($auth < AUTH_READ || !$this->id || !$conf['mediarevisions']) return;
 131  
 132          // retrieve form parameters: rev, rev2, difftype
 133          $this->handle();
 134          // prepare revision info of comparison pair
 135          $this->preProcess();
 136  
 137          // display intro
 138          if ($this->preference['showIntro']) echo p_locale_xhtml('diff');
 139  
 140          // print form to choose diff view type
 141          if ($this->is_img && !$this->preference['fromAjax']) {
 142              $this->showDiffViewSelector();
 143              echo '<div id="mediamanager__diff" >';
 144          }
 145  
 146          switch ($this->preference['difftype']) {
 147              case 'opacity':
 148              case 'portions':
 149                  $this->showImageDiff();
 150                  break;
 151              case 'both':
 152              default:
 153                  $this->showFileDiff();
 154                  break;
 155          }
 156  
 157          if ($this->is_img && !$this->preference['fromAjax']) {
 158              echo '</div>';
 159          }
 160      }
 161  
 162      /**
 163       * Print form to choose diff view type
 164       * the dropdown is to be added through JavaScript, see lib/scripts/media.js
 165       */
 166      protected function showDiffViewSelector()
 167      {
 168          // use timestamp for current revision, date may be false when revisions < 2
 169          [$rev1, $rev2] = [(int)$this->RevInfo1->val('date'), (int)$this->RevInfo2->val('date')];
 170  
 171          echo '<div class="diffoptions group">';
 172  
 173          $form = new Form([
 174              'id' => 'mediamanager__form_diffview',
 175              'action' => media_managerURL([], '&'),
 176              'method' => 'get',
 177              'class' => 'diffView',
 178          ]);
 179          $form->addTagOpen('div')->addClass('no');
 180          $form->setHiddenField('sectok', null);
 181          $form->setHiddenField('mediado', 'diff');
 182          $form->setHiddenField('rev2[0]', $rev1);
 183          $form->setHiddenField('rev2[1]', $rev2);
 184          $form->addTagClose('div');
 185          echo $form->toHTML();
 186  
 187          echo '</div>'; // .diffoptions
 188      }
 189  
 190      /**
 191       * Prints two images side by side
 192       * and slider
 193       *
 194       * @author Kate Arzamastseva <pshns@ukr.net>
 195       */
 196      protected function showImageDiff()
 197      {
 198          $rev1 = $this->RevInfo1->isCurrent() ? '' : $this->RevInfo1->val('date');
 199          $rev2 = $this->RevInfo2->isCurrent() ? '' : $this->RevInfo2->val('date');
 200  
 201          // diff view type: opacity or portions
 202          $type = $this->preference['difftype'];
 203  
 204          // adjust image width, right side (newer) has priority
 205          $rev1Size = $this->RevInfo1->val('previewSize');
 206          $rev2Size = $this->RevInfo2->val('previewSize');
 207          if ($rev1Size != $rev2Size) {
 208              if ($rev2Size[0] > $rev1Size[0]) {
 209                  $rev1Size = $rev2Size;
 210              }
 211          }
 212  
 213          $rev1Src = ml($this->id, ['rev' => $rev1, 'h' => $rev1Size[1], 'w' => $rev1Size[0]]);
 214          $rev2Src = ml($this->id, ['rev' => $rev2, 'h' => $rev1Size[1], 'w' => $rev1Size[0]]);
 215  
 216          // slider
 217          echo '<div class="slider" style="max-width: ' . ($rev1Size[0] - 20) . 'px;" ></div>';
 218  
 219          // two images in divs
 220          echo '<div class="imageDiff ' . $type . '">';
 221          echo '<div class="image1" style="max-width: ' . $rev1Size[0] . 'px;">';
 222          echo '<img src="' . $rev1Src . '" alt="" />';
 223          echo '</div>';
 224          echo '<div class="image2" style="max-width: ' . $rev1Size[0] . 'px;">';
 225          echo '<img src="' . $rev2Src . '" alt="" />';
 226          echo '</div>';
 227          echo '</div>';
 228      }
 229  
 230      /**
 231       * Shows difference between two revisions of media file
 232       *
 233       * @author Kate Arzamastseva <pshns@ukr.net>
 234       */
 235      protected function showFileDiff()
 236      {
 237          global $lang;
 238  
 239          $ns = getNS($this->id);
 240          $auth = auth_quickaclcheck("$ns:*");
 241  
 242          $rev1 = $this->RevInfo1->isCurrent() ? '' : (int)$this->RevInfo1->val('date');
 243          $rev2 = $this->RevInfo2->isCurrent() ? '' : (int)$this->RevInfo2->val('date');
 244  
 245          // revision title
 246          $rev1Title = trim($this->RevInfo1->showRevisionTitle() . ' ' . $this->RevInfo1->showCurrentIndicator());
 247          $rev1Summary = ($this->RevInfo1->val('date'))
 248              ? $this->RevInfo1->showEditSummary() . ' ' . $this->RevInfo1->showEditor()
 249              : '';
 250          $rev2Title = trim($this->RevInfo2->showRevisionTitle() . ' ' . $this->RevInfo2->showCurrentIndicator());
 251          $rev2Summary = ($this->RevInfo2->val('date'))
 252              ? $this->RevInfo2->showEditSummary() . ' ' . $this->RevInfo2->showEditor()
 253              : '';
 254  
 255          $rev1Meta = new JpegMeta(mediaFN($this->id, $rev1));
 256          $rev2Meta = new JpegMeta(mediaFN($this->id, $rev2));
 257  
 258          // display diff view table
 259          echo '<div class="table">';
 260          echo '<table>';
 261          echo '<tr>';
 262          echo '<th>' . $rev1Title . ' ' . $rev1Summary . '</th>';
 263          echo '<th>' . $rev2Title . ' ' . $rev2Summary . '</th>';
 264          echo '</tr>';
 265  
 266          echo '<tr class="image">';
 267          echo '<td>';
 268          media_preview($this->id, $auth, $rev1, $rev1Meta); // $auth not used in media_preview()?
 269          echo '</td>';
 270  
 271          echo '<td>';
 272          media_preview($this->id, $auth, $rev2, $rev2Meta);
 273          echo '</td>';
 274          echo '</tr>';
 275  
 276          echo '<tr class="actions">';
 277          echo '<td>';
 278          media_preview_buttons($this->id, $auth, $rev1); // $auth used in media_preview_buttons()
 279          echo '</td>';
 280  
 281          echo '<td>';
 282          media_preview_buttons($this->id, $auth, $rev2);
 283          echo '</td>';
 284          echo '</tr>';
 285  
 286          $rev1Tags = media_file_tags($rev1Meta);
 287          $rev2Tags = media_file_tags($rev2Meta);
 288          // FIXME rev2Tags-only stuff ignored
 289          foreach ($rev1Tags as $key => $tag) {
 290              if ($tag['value'] != $rev2Tags[$key]['value']) {
 291                  $rev2Tags[$key]['highlighted'] = true;
 292                  $rev1Tags[$key]['highlighted'] = true;
 293              } elseif (!$tag['value'] || !$rev2Tags[$key]['value']) {
 294                  unset($rev2Tags[$key]);
 295                  unset($rev1Tags[$key]);
 296              }
 297          }
 298  
 299          echo '<tr>';
 300          foreach ([$rev1Tags, $rev2Tags] as $tags) {
 301              echo '<td>';
 302  
 303              echo '<dl class="img_tags">';
 304              foreach ($tags as $tag) {
 305                  $value = cleanText($tag['value']);
 306                  if (!$value) $value = '-';
 307                  echo '<dt>' . $lang[$tag['tag'][1]] . '</dt>';
 308                  echo '<dd>';
 309                  if (!empty($tag['highlighted'])) echo '<strong>';
 310                  if ($tag['tag'][2] == 'date') {
 311                      echo dformat($value);
 312                  } else {
 313                      echo hsc($value);
 314                  }
 315                  if (!empty($tag['highlighted'])) echo '</strong>';
 316                  echo '</dd>';
 317              }
 318              echo '</dl>';
 319  
 320              echo '</td>';
 321          }
 322          echo '</tr>';
 323  
 324          echo '</table>';
 325          echo '</div>';
 326      }
 327  }