[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/ -> Ajax.php (source)

   1  <?php
   2  
   3  namespace dokuwiki;
   4  
   5  use dokuwiki\Ui;
   6  use dokuwiki\Utf8\Sort;
   7  
   8  /**
   9   * Manage all builtin AJAX calls
  10   *
  11   * @todo The calls should be refactored out to their own proper classes
  12   * @package dokuwiki
  13   */
  14  class Ajax {
  15  
  16      /**
  17       * Execute the given call
  18       *
  19       * @param string $call name of the ajax call
  20       */
  21      public function __construct($call) {
  22          $callfn = 'call' . ucfirst($call);
  23          if(method_exists($this, $callfn)) {
  24              $this->$callfn();
  25          } else {
  26              $evt = new Extension\Event('AJAX_CALL_UNKNOWN', $call);
  27              if($evt->advise_before()) {
  28                  print "AJAX call '" . hsc($call) . "' unknown!\n";
  29              } else {
  30                  $evt->advise_after();
  31                  unset($evt);
  32              }
  33          }
  34      }
  35  
  36      /**
  37       * Searches for matching pagenames
  38       *
  39       * @author Andreas Gohr <andi@splitbrain.org>
  40       */
  41      protected function callQsearch() {
  42          global $lang;
  43          global $INPUT;
  44  
  45          $maxnumbersuggestions = 50;
  46  
  47          $query = $INPUT->post->str('q');
  48          if(empty($query)) $query = $INPUT->get->str('q');
  49          if(empty($query)) return;
  50  
  51          $query = urldecode($query);
  52  
  53          $data = ft_pageLookup($query, true, useHeading('navigation'));
  54  
  55          if(!count($data)) return;
  56  
  57          print '<strong>' . $lang['quickhits'] . '</strong>';
  58          print '<ul>';
  59          $counter = 0;
  60          foreach($data as $id => $title) {
  61              if(useHeading('navigation')) {
  62                  $name = $title;
  63              } else {
  64                  $ns = getNS($id);
  65                  if($ns) {
  66                      $name = noNS($id) . ' (' . $ns . ')';
  67                  } else {
  68                      $name = $id;
  69                  }
  70              }
  71              echo '<li>' . html_wikilink(':' . $id, $name) . '</li>';
  72  
  73              $counter++;
  74              if($counter > $maxnumbersuggestions) {
  75                  echo '<li>...</li>';
  76                  break;
  77              }
  78          }
  79          print '</ul>';
  80      }
  81  
  82      /**
  83       * Support OpenSearch suggestions
  84       *
  85       * @link   http://www.opensearch.org/Specifications/OpenSearch/Extensions/Suggestions/1.0
  86       * @author Mike Frysinger <vapier@gentoo.org>
  87       */
  88      protected function callSuggestions() {
  89          global $INPUT;
  90  
  91          $query = cleanID($INPUT->post->str('q'));
  92          if(empty($query)) $query = cleanID($INPUT->get->str('q'));
  93          if(empty($query)) return;
  94  
  95          $data = ft_pageLookup($query);
  96          if(!count($data)) return;
  97          $data = array_keys($data);
  98  
  99          // limit results to 15 hits
 100          $data = array_slice($data, 0, 15);
 101          $data = array_map('trim', $data);
 102          $data = array_map('noNS', $data);
 103          $data = array_unique($data);
 104          Sort::sort($data);
 105  
 106          /* now construct a json */
 107          $suggestions = array(
 108              $query,  // the original query
 109              $data,   // some suggestions
 110              array(), // no description
 111              array()  // no urls
 112          );
 113  
 114          header('Content-Type: application/x-suggestions+json');
 115          print json_encode($suggestions);
 116      }
 117  
 118      /**
 119       * Refresh a page lock and save draft
 120       *
 121       * Andreas Gohr <andi@splitbrain.org>
 122       */
 123      protected function callLock() {
 124          global $ID;
 125          global $INFO;
 126          global $INPUT;
 127  
 128          $ID = cleanID($INPUT->post->str('id'));
 129          if(empty($ID)) return;
 130  
 131          $INFO = pageinfo();
 132  
 133          $response = [
 134              'errors' => [],
 135              'lock' => '0',
 136              'draft' => '',
 137          ];
 138          if(!$INFO['writable']) {
 139              $response['errors'][] = 'Permission to write this page has been denied.';
 140              echo json_encode($response);
 141              return;
 142          }
 143  
 144          if(!checklock($ID)) {
 145              lock($ID);
 146              $response['lock'] = '1';
 147          }
 148  
 149          $draft = new Draft($ID, $INFO['client']);
 150          if ($draft->saveDraft()) {
 151              $response['draft'] = $draft->getDraftMessage();
 152          } else {
 153              $response['errors'] = array_merge($response['errors'], $draft->getErrors());
 154          }
 155          echo json_encode($response);
 156      }
 157  
 158      /**
 159       * Delete a draft
 160       *
 161       * @author Andreas Gohr <andi@splitbrain.org>
 162       */
 163      protected function callDraftdel() {
 164          global $INPUT;
 165          $id = cleanID($INPUT->str('id'));
 166          if(empty($id)) return;
 167  
 168          $client = $_SERVER['REMOTE_USER'];
 169          if(!$client) $client = clientIP(true);
 170  
 171          $draft = new Draft($id, $client);
 172          if ($draft->isDraftAvailable() && checkSecurityToken()) {
 173              $draft->deleteDraft();
 174          }
 175      }
 176  
 177      /**
 178       * Return subnamespaces for the Mediamanager
 179       *
 180       * @author Andreas Gohr <andi@splitbrain.org>
 181       */
 182      protected function callMedians() {
 183          global $conf;
 184          global $INPUT;
 185  
 186          // wanted namespace
 187          $ns = cleanID($INPUT->post->str('ns'));
 188          $dir = utf8_encodeFN(str_replace(':', '/', $ns));
 189  
 190          $lvl = count(explode(':', $ns));
 191  
 192          $data = array();
 193          search($data, $conf['mediadir'], 'search_index', array('nofiles' => true), $dir);
 194          foreach(array_keys($data) as $item) {
 195              $data[$item]['level'] = $lvl + 1;
 196          }
 197          echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li');
 198      }
 199  
 200      /**
 201       * Return list of files for the Mediamanager
 202       *
 203       * @author Andreas Gohr <andi@splitbrain.org>
 204       */
 205      protected function callMedialist() {
 206          global $NS;
 207          global $INPUT;
 208  
 209          $NS = cleanID($INPUT->post->str('ns'));
 210          $sort = $INPUT->post->bool('recent') ? 'date' : 'natural';
 211          if($INPUT->post->str('do') == 'media') {
 212              tpl_mediaFileList();
 213          } else {
 214              tpl_mediaContent(true, $sort);
 215          }
 216      }
 217  
 218      /**
 219       * Return the content of the right column
 220       * (image details) for the Mediamanager
 221       *
 222       * @author Kate Arzamastseva <pshns@ukr.net>
 223       */
 224      protected function callMediadetails() {
 225          global $IMG, $JUMPTO, $REV, $fullscreen, $INPUT;
 226          $fullscreen = true;
 227          require_once (DOKU_INC . 'lib/exe/mediamanager.php');
 228  
 229          $image = '';
 230          if($INPUT->has('image')) $image = cleanID($INPUT->str('image'));
 231          if(isset($IMG)) $image = $IMG;
 232          if(isset($JUMPTO)) $image = $JUMPTO;
 233          $rev = false;
 234          if(isset($REV) && !$JUMPTO) $rev = $REV;
 235  
 236          html_msgarea();
 237          tpl_mediaFileDetails($image, $rev);
 238      }
 239  
 240      /**
 241       * Returns image diff representation for mediamanager
 242       *
 243       * @author Kate Arzamastseva <pshns@ukr.net>
 244       */
 245      protected function callMediadiff() {
 246          global $INPUT;
 247  
 248          $image = '';
 249          if($INPUT->has('image')) $image = cleanID($INPUT->str('image'));
 250          (new Ui\MediaDiff($image))->preference('fromAjax', true)->show();
 251      }
 252  
 253      /**
 254       * Manages file uploads
 255       *
 256       * @author Kate Arzamastseva <pshns@ukr.net>
 257       */
 258      protected function callMediaupload() {
 259          global $NS, $MSG, $INPUT;
 260  
 261          $id = '';
 262          if(isset($_FILES['qqfile']['tmp_name'])) {
 263              $id = $INPUT->post->str('mediaid', $_FILES['qqfile']['name']);
 264          } elseif($INPUT->get->has('qqfile')) {
 265              $id = $INPUT->get->str('qqfile');
 266          }
 267  
 268          $id = cleanID($id);
 269  
 270          $NS = $INPUT->str('ns');
 271          $ns = $NS . ':' . getNS($id);
 272  
 273          $AUTH = auth_quickaclcheck("$ns:*");
 274          if($AUTH >= AUTH_UPLOAD) {
 275              io_createNamespace("$ns:xxx", 'media');
 276          }
 277  
 278          if(isset($_FILES['qqfile']['error']) && $_FILES['qqfile']['error']) unset($_FILES['qqfile']);
 279  
 280          $res = false;
 281          if(isset($_FILES['qqfile']['tmp_name'])) $res = media_upload($NS, $AUTH, $_FILES['qqfile']);
 282          if($INPUT->get->has('qqfile')) $res = media_upload_xhr($NS, $AUTH);
 283  
 284          if($res) {
 285              $result = array(
 286                  'success' => true,
 287                  'link' => media_managerURL(array('ns' => $ns, 'image' => $NS . ':' . $id), '&'),
 288                  'id' => $NS . ':' . $id,
 289                  'ns' => $NS
 290              );
 291          } else {
 292              $error = '';
 293              if(isset($MSG)) {
 294                  foreach($MSG as $msg) {
 295                      $error .= $msg['msg'];
 296                  }
 297              }
 298              $result = array(
 299                  'error' => $error,
 300                  'ns' => $NS
 301              );
 302          }
 303  
 304          header('Content-Type: application/json');
 305          echo json_encode($result);
 306      }
 307  
 308      /**
 309       * Return sub index for index view
 310       *
 311       * @author Andreas Gohr <andi@splitbrain.org>
 312       */
 313      protected function callIndex() {
 314          global $conf;
 315          global $INPUT;
 316  
 317          // wanted namespace
 318          $ns = cleanID($INPUT->post->str('idx'));
 319          $dir = utf8_encodeFN(str_replace(':', '/', $ns));
 320  
 321          $lvl = count(explode(':', $ns));
 322  
 323          $data = array();
 324          search($data, $conf['datadir'], 'search_index', array('ns' => $ns), $dir);
 325          foreach (array_keys($data) as $item) {
 326              $data[$item]['level'] = $lvl + 1;
 327          }
 328          $idx = new Ui\Index;
 329          echo html_buildlist($data, 'idx', [$idx,'formatListItem'], [$idx,'tagListItem']);
 330      }
 331  
 332      /**
 333       * List matching namespaces and pages for the link wizard
 334       *
 335       * @author Andreas Gohr <gohr@cosmocode.de>
 336       */
 337      protected function callLinkwiz() {
 338          global $conf;
 339          global $lang;
 340          global $INPUT;
 341  
 342          $q = ltrim(trim($INPUT->post->str('q')), ':');
 343          $id = noNS($q);
 344          $ns = getNS($q);
 345  
 346          $ns = cleanID($ns);
 347          $id = cleanID($id);
 348  
 349          $nsd = utf8_encodeFN(str_replace(':', '/', $ns));
 350  
 351          $data = array();
 352          if($q !== '' && $ns === '') {
 353  
 354              // use index to lookup matching pages
 355              $pages = ft_pageLookup($id, true);
 356  
 357              // If 'useheading' option is 'always' or 'content',
 358              // search page titles with original query as well.
 359              if ($conf['useheading'] == '1' || $conf['useheading'] == 'content') { 
 360                  $pages = array_merge($pages, ft_pageLookup($q, true, true));
 361                  asort($pages, SORT_STRING);
 362              }
 363          
 364              // result contains matches in pages and namespaces
 365              // we now extract the matching namespaces to show
 366              // them seperately
 367              $dirs = array();
 368  
 369              foreach($pages as $pid => $title) {
 370                  if(strpos(getNS($pid), $id) !== false) {
 371                      // match was in the namespace
 372                      $dirs[getNS($pid)] = 1; // assoc array avoids dupes
 373                  } else {
 374                      // it is a matching page, add it to the result
 375                      $data[] = array(
 376                          'id' => $pid,
 377                          'title' => $title,
 378                          'type' => 'f',
 379                      );
 380                  }
 381                  unset($pages[$pid]);
 382              }
 383              foreach($dirs as $dir => $junk) {
 384                  $data[] = array(
 385                      'id' => $dir,
 386                      'type' => 'd',
 387                  );
 388              }
 389  
 390          } else {
 391  
 392              $opts = array(
 393                  'depth' => 1,
 394                  'listfiles' => true,
 395                  'listdirs' => true,
 396                  'pagesonly' => true,
 397                  'firsthead' => true,
 398                  'sneakyacl' => $conf['sneaky_index'],
 399              );
 400              if($id) $opts['filematch'] = '^.*\/' . $id;
 401              if($id) $opts['dirmatch'] = '^.*\/' . $id;
 402              search($data, $conf['datadir'], 'search_universal', $opts, $nsd);
 403  
 404              // add back to upper
 405              if($ns) {
 406                  array_unshift(
 407                      $data, array(
 408                               'id' => getNS($ns),
 409                               'type' => 'u',
 410                           )
 411                  );
 412              }
 413          }
 414  
 415          // fixme sort results in a useful way ?
 416  
 417          if(!count($data)) {
 418              echo $lang['nothingfound'];
 419              exit;
 420          }
 421  
 422          // output the found data
 423          $even = 1;
 424          foreach($data as $item) {
 425              $even *= -1; //zebra
 426  
 427              if(($item['type'] == 'd' || $item['type'] == 'u') && $item['id'] !== '') $item['id'] .= ':';
 428              $link = wl($item['id']);
 429  
 430              echo '<div class="' . (($even > 0) ? 'even' : 'odd') . ' type_' . $item['type'] . '">';
 431  
 432              if($item['type'] == 'u') {
 433                  $name = $lang['upperns'];
 434              } else {
 435                  $name = hsc($item['id']);
 436              }
 437  
 438              echo '<a href="' . $link . '" title="' . hsc($item['id']) . '" class="wikilink1">' . $name . '</a>';
 439  
 440              if(!blank($item['title'])) {
 441                  echo '<span>' . hsc($item['title']) . '</span>';
 442              }
 443              echo '</div>';
 444          }
 445  
 446      }
 447  
 448  }