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