[ 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          $cname = getCacheName($client . $id, '.draft');
 172          @unlink($cname);
 173      }
 174  
 175      /**
 176       * Return subnamespaces for the Mediamanager
 177       *
 178       * @author Andreas Gohr <andi@splitbrain.org>
 179       */
 180      protected function callMedians() {
 181          global $conf;
 182          global $INPUT;
 183  
 184          // wanted namespace
 185          $ns = cleanID($INPUT->post->str('ns'));
 186          $dir = utf8_encodeFN(str_replace(':', '/', $ns));
 187  
 188          $lvl = count(explode(':', $ns));
 189  
 190          $data = array();
 191          search($data, $conf['mediadir'], 'search_index', array('nofiles' => true), $dir);
 192          foreach(array_keys($data) as $item) {
 193              $data[$item]['level'] = $lvl + 1;
 194          }
 195          echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li');
 196      }
 197  
 198      /**
 199       * Return list of files for the Mediamanager
 200       *
 201       * @author Andreas Gohr <andi@splitbrain.org>
 202       */
 203      protected function callMedialist() {
 204          global $NS;
 205          global $INPUT;
 206  
 207          $NS = cleanID($INPUT->post->str('ns'));
 208          $sort = $INPUT->post->bool('recent') ? 'date' : 'natural';
 209          if($INPUT->post->str('do') == 'media') {
 210              tpl_mediaFileList();
 211          } else {
 212              tpl_mediaContent(true, $sort);
 213          }
 214      }
 215  
 216      /**
 217       * Return the content of the right column
 218       * (image details) for the Mediamanager
 219       *
 220       * @author Kate Arzamastseva <pshns@ukr.net>
 221       */
 222      protected function callMediadetails() {
 223          global $IMG, $JUMPTO, $REV, $fullscreen, $INPUT;
 224          $fullscreen = true;
 225          require_once (DOKU_INC . 'lib/exe/mediamanager.php');
 226  
 227          $image = '';
 228          if($INPUT->has('image')) $image = cleanID($INPUT->str('image'));
 229          if(isset($IMG)) $image = $IMG;
 230          if(isset($JUMPTO)) $image = $JUMPTO;
 231          $rev = false;
 232          if(isset($REV) && !$JUMPTO) $rev = $REV;
 233  
 234          html_msgarea();
 235          tpl_mediaFileDetails($image, $rev);
 236      }
 237  
 238      /**
 239       * Returns image diff representation for mediamanager
 240       *
 241       * @author Kate Arzamastseva <pshns@ukr.net>
 242       */
 243      protected function callMediadiff() {
 244          global $NS;
 245          global $INPUT;
 246  
 247          $image = '';
 248          if($INPUT->has('image')) $image = cleanID($INPUT->str('image'));
 249          $NS = getNS($image);
 250          $auth = auth_quickaclcheck("$NS:*");
 251          media_diff($image, $NS, $auth, true);
 252      }
 253  
 254      /**
 255       * Manages file uploads
 256       *
 257       * @author Kate Arzamastseva <pshns@ukr.net>
 258       */
 259      protected function callMediaupload() {
 260          global $NS, $MSG, $INPUT;
 261  
 262          $id = '';
 263          if(isset($_FILES['qqfile']['tmp_name'])) {
 264              $id = $INPUT->post->str('mediaid', $_FILES['qqfile']['name']);
 265          } elseif($INPUT->get->has('qqfile')) {
 266              $id = $INPUT->get->str('qqfile');
 267          }
 268  
 269          $id = cleanID($id);
 270  
 271          $NS = $INPUT->str('ns');
 272          $ns = $NS . ':' . getNS($id);
 273  
 274          $AUTH = auth_quickaclcheck("$ns:*");
 275          if($AUTH >= AUTH_UPLOAD) {
 276              io_createNamespace("$ns:xxx", 'media');
 277          }
 278  
 279          if(isset($_FILES['qqfile']['error']) && $_FILES['qqfile']['error']) unset($_FILES['qqfile']);
 280  
 281          $res = false;
 282          if(isset($_FILES['qqfile']['tmp_name'])) $res = media_upload($NS, $AUTH, $_FILES['qqfile']);
 283          if($INPUT->get->has('qqfile')) $res = media_upload_xhr($NS, $AUTH);
 284  
 285          if($res) {
 286              $result = array(
 287                  'success' => true,
 288                  'link' => media_managerURL(array('ns' => $ns, 'image' => $NS . ':' . $id), '&'),
 289                  'id' => $NS . ':' . $id,
 290                  'ns' => $NS
 291              );
 292          } else {
 293              $error = '';
 294              if(isset($MSG)) {
 295                  foreach($MSG as $msg) {
 296                      $error .= $msg['msg'];
 297                  }
 298              }
 299              $result = array(
 300                  'error' => $error,
 301                  'ns' => $NS
 302              );
 303          }
 304  
 305          header('Content-Type: application/json');
 306          echo json_encode($result);
 307      }
 308  
 309      /**
 310       * Return sub index for index view
 311       *
 312       * @author Andreas Gohr <andi@splitbrain.org>
 313       */
 314      protected function callIndex() {
 315          global $conf;
 316          global $INPUT;
 317  
 318          // wanted namespace
 319          $ns = cleanID($INPUT->post->str('idx'));
 320          $dir = utf8_encodeFN(str_replace(':', '/', $ns));
 321  
 322          $lvl = count(explode(':', $ns));
 323  
 324          $data = array();
 325          search($data, $conf['datadir'], 'search_index', array('ns' => $ns), $dir);
 326          foreach (array_keys($data) as $item) {
 327              $data[$item]['level'] = $lvl + 1;
 328          }
 329          $idx = new Ui\Index;
 330          echo html_buildlist($data, 'idx', [$idx,'formatListItem'], [$idx,'tagListItem']);
 331      }
 332  
 333      /**
 334       * List matching namespaces and pages for the link wizard
 335       *
 336       * @author Andreas Gohr <gohr@cosmocode.de>
 337       */
 338      protected function callLinkwiz() {
 339          global $conf;
 340          global $lang;
 341          global $INPUT;
 342  
 343          $q = ltrim(trim($INPUT->post->str('q')), ':');
 344          $id = noNS($q);
 345          $ns = getNS($q);
 346  
 347          $ns = cleanID($ns);
 348          $id = cleanID($id);
 349  
 350          $nsd = utf8_encodeFN(str_replace(':', '/', $ns));
 351  
 352          $data = array();
 353          if($q !== '' && $ns === '') {
 354  
 355              // use index to lookup matching pages
 356              $pages = ft_pageLookup($id, true);
 357  
 358              // result contains matches in pages and namespaces
 359              // we now extract the matching namespaces to show
 360              // them seperately
 361              $dirs = array();
 362  
 363              foreach($pages as $pid => $title) {
 364                  if(strpos(noNS($pid), $id) === false) {
 365                      // match was in the namespace
 366                      $dirs[getNS($pid)] = 1; // assoc array avoids dupes
 367                  } else {
 368                      // it is a matching page, add it to the result
 369                      $data[] = array(
 370                          'id' => $pid,
 371                          'title' => $title,
 372                          'type' => 'f',
 373                      );
 374                  }
 375                  unset($pages[$pid]);
 376              }
 377              foreach($dirs as $dir => $junk) {
 378                  $data[] = array(
 379                      'id' => $dir,
 380                      'type' => 'd',
 381                  );
 382              }
 383  
 384          } else {
 385  
 386              $opts = array(
 387                  'depth' => 1,
 388                  'listfiles' => true,
 389                  'listdirs' => true,
 390                  'pagesonly' => true,
 391                  'firsthead' => true,
 392                  'sneakyacl' => $conf['sneaky_index'],
 393              );
 394              if($id) $opts['filematch'] = '^.*\/' . $id;
 395              if($id) $opts['dirmatch'] = '^.*\/' . $id;
 396              search($data, $conf['datadir'], 'search_universal', $opts, $nsd);
 397  
 398              // add back to upper
 399              if($ns) {
 400                  array_unshift(
 401                      $data, array(
 402                               'id' => getNS($ns),
 403                               'type' => 'u',
 404                           )
 405                  );
 406              }
 407          }
 408  
 409          // fixme sort results in a useful way ?
 410  
 411          if(!count($data)) {
 412              echo $lang['nothingfound'];
 413              exit;
 414          }
 415  
 416          // output the found data
 417          $even = 1;
 418          foreach($data as $item) {
 419              $even *= -1; //zebra
 420  
 421              if(($item['type'] == 'd' || $item['type'] == 'u') && $item['id'] !== '') $item['id'] .= ':';
 422              $link = wl($item['id']);
 423  
 424              echo '<div class="' . (($even > 0) ? 'even' : 'odd') . ' type_' . $item['type'] . '">';
 425  
 426              if($item['type'] == 'u') {
 427                  $name = $lang['upperns'];
 428              } else {
 429                  $name = hsc($item['id']);
 430              }
 431  
 432              echo '<a href="' . $link . '" title="' . hsc($item['id']) . '" class="wikilink1">' . $name . '</a>';
 433  
 434              if(!blank($item['title'])) {
 435                  echo '<span>' . hsc($item['title']) . '</span>';
 436              }
 437              echo '</div>';
 438          }
 439  
 440      }
 441  
 442  }