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