[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/lib/plugins/logviewer/ -> admin.php (source)

   1  <?php
   2  
   3  use dokuwiki\Logger;
   4  
   5  /**
   6   * DokuWiki Plugin logviewer (Admin Component)
   7   *
   8   * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
   9   * @author  Andreas Gohr <andi@splitbrain.org>
  10   */
  11  class admin_plugin_logviewer extends DokuWiki_Admin_Plugin
  12  {
  13      const MAX_READ_SIZE = 1048576; // 1 MB
  14  
  15      protected $facilities;
  16      protected $facility;
  17      protected $date;
  18  
  19      /** @inheritDoc */
  20      public function forAdminOnly()
  21      {
  22          return true;
  23      }
  24  
  25      /** @inheritDoc */
  26      public function handle()
  27      {
  28          global $INPUT;
  29  
  30          $this->facilities = $this->getFacilities();
  31          $this->facility = $INPUT->str('facility');
  32          if (!in_array($this->facility, $this->facilities)) {
  33              $this->facility = $this->facilities[0];
  34          }
  35  
  36          $this->date = $INPUT->str('date');
  37          if (!preg_match('/^\d\d\d\d-\d\d-\d\d$/', $this->date)) {
  38              $this->date = gmdate('Y-m-d');
  39          }
  40      }
  41  
  42      /** @inheritDoc */
  43      public function html()
  44      {
  45          echo '<div id="plugin__logviewer">';
  46          echo $this->locale_xhtml('intro');
  47          $this->displayTabs();
  48          $this->displayLog();
  49          echo '</div>';
  50      }
  51  
  52      /**
  53       * Show the navigational tabs and date picker
  54       */
  55      protected function displayTabs()
  56      {
  57          global $ID;
  58  
  59          $form = new dokuwiki\Form\Form(['method' => 'GET']);
  60          $form->setHiddenField('do', 'admin');
  61          $form->setHiddenField('page', 'logviewer');
  62          $form->setHiddenField('facility', $this->facility);
  63          $form->addTextInput('date', $this->getLang('date'))
  64              ->attr('type', 'date')->val($this->date)->addClass('quickselect');
  65          $form->addButton('submit', '>')->attr('type', 'submit');
  66          echo $form->toHTML();
  67  
  68          echo '<ul class="tabs">';
  69          foreach ($this->facilities as $facility) {
  70              echo '<li>';
  71              if ($facility == $this->facility) {
  72                  echo '<strong>' . hsc($facility) . '</strong>';
  73              } else {
  74                  $link = wl($ID,
  75                      ['do' => 'admin', 'page' => 'logviewer', 'date' => $this->date, 'facility' => $facility]);
  76                  echo '<a href="' . $link . '">' . hsc($facility) . '</a>';
  77              }
  78              echo '</li>';
  79          }
  80          echo '</ul>';
  81      }
  82  
  83      /**
  84       * Read and output the logfile contents
  85       */
  86      protected function displayLog()
  87      {
  88          $logfile = Logger::getInstance($this->facility)->getLogfile($this->date);
  89          if (!file_exists($logfile)) {
  90              echo $this->locale_xhtml('nolog');
  91              return;
  92          }
  93  
  94          try {
  95              $lines = $this->getLogLines($logfile);
  96              $this->printLogLines($lines);
  97          } catch (Exception $e) {
  98              msg($e->getMessage(), -1);
  99          }
 100      }
 101  
 102      /**
 103       * Get the available logging facilities
 104       *
 105       * @return array
 106       */
 107      protected function getFacilities()
 108      {
 109          global $conf;
 110  
 111          // default facilities first
 112          $facilities = [
 113              Logger::LOG_ERROR,
 114              Logger::LOG_DEPRECATED,
 115              Logger::LOG_DEBUG,
 116          ];
 117  
 118          // add all other dirs
 119          $dirs = glob($conf['logdir'] . '/*', GLOB_ONLYDIR);
 120          foreach ($dirs as $dir) {
 121              $facilities[] = basename($dir);
 122          }
 123          $facilities = array_unique($facilities);
 124  
 125          return $facilities;
 126      }
 127  
 128      /**
 129       * Read the lines of the logfile and return them as array
 130       *
 131       * @param string $logfilePath
 132       * @return array
 133       * @throws Exception when reading fails
 134       */
 135      protected function getLogLines($logfilePath)
 136      {
 137          global $lang;
 138          $size = filesize($logfilePath);
 139          $fp = fopen($logfilePath, 'r');
 140  
 141          if (!$fp) throw new Exception($lang['log_file_failed_to_open']);
 142  
 143          try {
 144              if ($size < self::MAX_READ_SIZE) {
 145                  $toread = $size;
 146              } else {
 147                  $toread = self::MAX_READ_SIZE;
 148                  fseek($fp, -$toread, SEEK_END);
 149              }
 150  
 151              $logData = fread($fp, $toread);
 152              if (!$logData) throw new Exception($lang['log_file_failed_to_read']);
 153  
 154              $lines = explode("\n", $logData);
 155              unset($logData); // free memory early
 156  
 157              if ($size >= self::MAX_READ_SIZE) {
 158                  array_shift($lines); // Discard the first line
 159                  while (!empty($lines) && (substr($lines[0], 0, 2) === '  ')) {
 160                      array_shift($lines); // Discard indented lines
 161                  }
 162  
 163                  // A message to inform users that previous lines are skipped
 164                  array_unshift($lines, "******\t" . "\t" . '[' . $lang['log_file_too_large'] . ']');
 165              }
 166          } finally {
 167              fclose($fp);
 168          }
 169  
 170          return $lines;
 171      }
 172  
 173      /**
 174       * Get an array of log lines and print them using appropriate styles
 175       *
 176       * @param array $lines
 177       */
 178      protected function printLogLines($lines)
 179      {
 180          $numberOfLines = count($lines);
 181  
 182          echo "<dl>";
 183          for ($i = 0; $i < $numberOfLines; $i++) {
 184              $line = $lines[$i];
 185              if (substr($line, 0, 2) === '  ') {
 186                  // lines indented by two spaces are details, aggregate them
 187                  echo '<dd>';
 188                  while (substr($line, 0, 2) === '  ') {
 189                      echo hsc(substr($line, 2)) . '<br />';
 190                      $i++;
 191                      $line = $lines[$i] ?? '';
 192                  }
 193                  echo '</dd>';
 194                  $i -= 1; // rewind the counter
 195              } else {
 196                  // other lines are actual log lines in three parts
 197                  list($dt, $file, $msg) = sexplode("\t", $line, 3, '');
 198                  echo '<dt>';
 199                  echo '<span class="datetime">' . hsc($dt) . '</span>';
 200                  echo '<span class="log">';
 201                  echo '<span class="msg">' . hsc($msg) . '</span>';
 202                  echo '<span class="file">' . hsc($file) . '</span>';
 203                  echo '</span>';
 204                  echo '</dt>';
 205              }
 206          }
 207          echo "</dl>";
 208      }
 209  }