[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/lib/plugins/config/core/ -> Writer.php (source)

   1  <?php
   2  
   3  namespace dokuwiki\plugin\config\core;
   4  
   5  use dokuwiki\plugin\config\core\Setting\Setting;
   6  use dokuwiki\Logger;
   7  
   8  /**
   9   * Writes the settings to the correct local file
  10   */
  11  class Writer
  12  {
  13      /** @var string header info */
  14      protected $header = 'Dokuwiki\'s Main Configuration File - Local Settings';
  15  
  16      /** @var string the file where the config will be saved to */
  17      protected $savefile;
  18  
  19      /**
  20       * Writer constructor.
  21       */
  22      public function __construct()
  23      {
  24          global $config_cascade;
  25          $this->savefile = end($config_cascade['main']['local']);
  26      }
  27  
  28      /**
  29       * Save the given settings
  30       *
  31       * @param Setting[] $settings
  32       * @throws \Exception
  33       */
  34      public function save($settings)
  35      {
  36          global $conf;
  37          if ($this->isLocked()) throw new \Exception('no save');
  38  
  39          // backup current file (remove any existing backup)
  40          if (file_exists($this->savefile)) {
  41              if (file_exists($this->savefile . '.bak.php')) @unlink($this->savefile . '.bak.php');
  42              if (!io_rename($this->savefile, $this->savefile . '.bak.php')) throw new \Exception('no backup');
  43          }
  44  
  45          if (!$fh = @fopen($this->savefile, 'wb')) {
  46              io_rename($this->savefile . '.bak.php', $this->savefile); // problem opening, restore the backup
  47              throw new \Exception('no save');
  48          }
  49  
  50          $out = '';
  51          foreach ($settings as $setting) {
  52              if ($setting->shouldBeSaved()) {
  53                  $out .= $setting->out('conf', 'php');
  54              }
  55          }
  56  
  57          if ($out === '') {
  58              throw new \Exception('empty config');
  59          }
  60          $out = $this->getHeader() . $out;
  61  
  62          fwrite($fh, $out);
  63          fclose($fh);
  64          if ($conf['fperm']) chmod($this->savefile, $conf['fperm']);
  65          $this->opcacheUpdate($this->savefile);
  66      }
  67  
  68      /**
  69       * Update last modified time stamp of the config file
  70       *
  71       * Will invalidate all DokuWiki caches
  72       *
  73       * @throws \Exception when the config isn't writable
  74       */
  75      public function touch()
  76      {
  77          if ($this->isLocked()) throw new \Exception('no save');
  78          @touch($this->savefile);
  79          $this->opcacheUpdate($this->savefile);
  80      }
  81  
  82      /**
  83       * Invalidate the opcache of the given file (if possible)
  84       *
  85       * @todo this should probably be moved to core
  86       * @param string $file
  87       */
  88      protected function opcacheUpdate($file)
  89      {
  90          if (!function_exists('opcache_invalidate')) return;
  91          set_error_handler(function ($errNo, $errMsg) {
  92              Logger::debug('Unable to invalidate opcache: ' . $errMsg);
  93          });
  94          opcache_invalidate($file);
  95          restore_error_handler();
  96      }
  97  
  98      /**
  99       * Configuration is considered locked if there is no local settings filename
 100       * or the directory its in is not writable or the file exists and is not writable
 101       *
 102       * @return bool true: locked, false: writable
 103       */
 104      public function isLocked()
 105      {
 106          if (!$this->savefile) return true;
 107          if (!is_writable(dirname($this->savefile))) return true;
 108          if (file_exists($this->savefile) && !is_writable($this->savefile)) return true;
 109          return false;
 110      }
 111  
 112      /**
 113       * Returns the PHP intro header for the config file
 114       *
 115       * @return string
 116       */
 117      protected function getHeader()
 118      {
 119          return implode(
 120              "\n",
 121              [
 122                  '<?php',
 123                  '/*',
 124                  ' * ' . $this->header,
 125                  ' * Auto-generated by config plugin',
 126                  ' * Run for user: ' . ($_SERVER['REMOTE_USER'] ?? 'Unknown'),
 127                  ' * Date: ' . date('r'),
 128                  ' */',
 129                  '',
 130                  ''
 131              ]
 132          );
 133      }
 134  }