123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- <?php
- namespace dokuwiki\plugin\config\core;
- use dokuwiki\plugin\config\core\Setting\Setting;
- use dokuwiki\Logger;
- /**
- * Writes the settings to the correct local file
- */
- class Writer {
- /** @var string header info */
- protected $header = 'Dokuwiki\'s Main Configuration File - Local Settings';
- /** @var string the file where the config will be saved to */
- protected $savefile;
- /**
- * Writer constructor.
- */
- public function __construct() {
- global $config_cascade;
- $this->savefile = end($config_cascade['main']['local']);
- }
- /**
- * Save the given settings
- *
- * @param Setting[] $settings
- * @throws \Exception
- */
- public function save($settings) {
- global $conf;
- if($this->isLocked()) throw new \Exception('no save');
- // backup current file (remove any existing backup)
- if(file_exists($this->savefile)) {
- if(file_exists($this->savefile . '.bak.php')) @unlink($this->savefile . '.bak.php');
- if(!io_rename($this->savefile, $this->savefile . '.bak.php')) throw new \Exception('no backup');
- }
- if(!$fh = @fopen($this->savefile, 'wb')) {
- io_rename($this->savefile . '.bak.php', $this->savefile); // problem opening, restore the backup
- throw new \Exception('no save');
- }
- $out = '';
- foreach($settings as $setting) {
- if($setting->shouldBeSaved()) {
- $out .= $setting->out('conf', 'php');
- }
- }
- if($out === '') {
- throw new \Exception('empty config');
- }
- $out = $this->getHeader() . $out;
- fwrite($fh, $out);
- fclose($fh);
- if($conf['fperm']) chmod($this->savefile, $conf['fperm']);
- $this->opcacheUpdate($this->savefile);
- }
- /**
- * Update last modified time stamp of the config file
- *
- * Will invalidate all DokuWiki caches
- *
- * @throws \Exception when the config isn't writable
- */
- public function touch() {
- if($this->isLocked()) throw new \Exception('no save');
- @touch($this->savefile);
- $this->opcacheUpdate($this->savefile);
- }
- /**
- * Invalidate the opcache of the given file (if possible)
- *
- * @todo this should probably be moved to core
- * @param string $file
- */
- protected function opcacheUpdate($file) {
- if(!function_exists('opcache_invalidate')) return;
- set_error_handler(function ($errNo, $errMsg) {
- Logger::debug('Unable to invalidate opcache: ' . $errMsg); }
- );
- opcache_invalidate($file);
- restore_error_handler();
- }
- /**
- * Configuration is considered locked if there is no local settings filename
- * or the directory its in is not writable or the file exists and is not writable
- *
- * @return bool true: locked, false: writable
- */
- public function isLocked() {
- if(!$this->savefile) return true;
- if(!is_writable(dirname($this->savefile))) return true;
- if(file_exists($this->savefile) && !is_writable($this->savefile)) return true;
- return false;
- }
- /**
- * Returns the PHP intro header for the config file
- *
- * @return string
- */
- protected function getHeader() {
- return join(
- "\n",
- array(
- '<?php',
- '/*',
- ' * ' . $this->header,
- ' * Auto-generated by config plugin',
- ' * Run for user: ' . (isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'] : 'Unknown'),
- ' * Date: ' . date('r'),
- ' */',
- '',
- ''
- )
- );
- }
- }
|