15a38a129SAndreas Gohr<?php 25a38a129SAndreas Gohr 35a38a129SAndreas Gohrnamespace dokuwiki\plugin\config\core; 40a5b05ebSAndreas Gohruse dokuwiki\plugin\config\core\Setting\Setting; 55a38a129SAndreas Gohr 65a38a129SAndreas Gohr/** 75a38a129SAndreas Gohr * Writes the settings to the correct local file 85a38a129SAndreas Gohr */ 95a38a129SAndreas Gohrclass Writer { 105a38a129SAndreas Gohr /** @var string header info */ 115a38a129SAndreas Gohr protected $header = 'Dokuwiki\'s Main Configuration File - Local Settings'; 125a38a129SAndreas Gohr 135a38a129SAndreas Gohr /** @var string the file where the config will be saved to */ 145a38a129SAndreas Gohr protected $savefile; 155a38a129SAndreas Gohr 165a38a129SAndreas Gohr /** 175a38a129SAndreas Gohr * Writer constructor. 185a38a129SAndreas Gohr */ 195a38a129SAndreas Gohr public function __construct() { 205a38a129SAndreas Gohr global $config_cascade; 215a38a129SAndreas Gohr $this->savefile = end($config_cascade['main']['local']); 225a38a129SAndreas Gohr } 235a38a129SAndreas Gohr 245a38a129SAndreas Gohr /** 255a38a129SAndreas Gohr * Save the given settings 265a38a129SAndreas Gohr * 275a38a129SAndreas Gohr * @param Setting[] $settings 285a38a129SAndreas Gohr * @throws \Exception 295a38a129SAndreas Gohr */ 305a38a129SAndreas Gohr public function save($settings) { 315a38a129SAndreas Gohr global $conf; 325a38a129SAndreas Gohr if($this->isLocked()) throw new \Exception('no save'); 335a38a129SAndreas Gohr 345a38a129SAndreas Gohr // backup current file (remove any existing backup) 355a38a129SAndreas Gohr if(file_exists($this->savefile)) { 36*49bcbaeeSAndreas Gohr if(file_exists($this->savefile . '.bak.php')) @unlink($this->savefile . '.bak.php'); 37*49bcbaeeSAndreas Gohr if(!io_rename($this->savefile, $this->savefile . '.bak.php')) throw new \Exception('no backup'); 385a38a129SAndreas Gohr } 395a38a129SAndreas Gohr 405a38a129SAndreas Gohr if(!$fh = @fopen($this->savefile, 'wb')) { 41*49bcbaeeSAndreas Gohr io_rename($this->savefile . '.bak.php', $this->savefile); // problem opening, restore the backup 425a38a129SAndreas Gohr throw new \Exception('no save'); 435a38a129SAndreas Gohr } 445a38a129SAndreas Gohr 455a38a129SAndreas Gohr $out = $this->getHeader(); 465a38a129SAndreas Gohr foreach($settings as $setting) { 47f00299d8SAndreas Gohr if($setting->shouldBeSaved()) { 485a38a129SAndreas Gohr $out .= $setting->out('conf', 'php'); 495a38a129SAndreas Gohr } 50f00299d8SAndreas Gohr } 515a38a129SAndreas Gohr 525a38a129SAndreas Gohr fwrite($fh, $out); 535a38a129SAndreas Gohr fclose($fh); 545a38a129SAndreas Gohr if($conf['fperm']) chmod($this->savefile, $conf['fperm']); 5570b28bcfSAndreas Gohr $this->opcacheUpdate($this->savefile); 565a38a129SAndreas Gohr } 575a38a129SAndreas Gohr 585a38a129SAndreas Gohr /** 595a38a129SAndreas Gohr * Update last modified time stamp of the config file 605a38a129SAndreas Gohr * 615a38a129SAndreas Gohr * Will invalidate all DokuWiki caches 625a38a129SAndreas Gohr * 635a38a129SAndreas Gohr * @throws \Exception when the config isn't writable 645a38a129SAndreas Gohr */ 655a38a129SAndreas Gohr public function touch() { 665a38a129SAndreas Gohr if($this->isLocked()) throw new \Exception('no save'); 675a38a129SAndreas Gohr @touch($this->savefile); 6870b28bcfSAndreas Gohr $this->opcacheUpdate($this->savefile); 6970b28bcfSAndreas Gohr } 7070b28bcfSAndreas Gohr 7170b28bcfSAndreas Gohr /** 7270b28bcfSAndreas Gohr * Invalidate the opcache of the given file 7370b28bcfSAndreas Gohr * 7470b28bcfSAndreas Gohr * @todo this should probably be moved to core 7570b28bcfSAndreas Gohr * @param string $file 7670b28bcfSAndreas Gohr */ 7770b28bcfSAndreas Gohr protected function opcacheUpdate($file) { 7870b28bcfSAndreas Gohr if(!function_exists('opcache_invalidate')) return; 7970b28bcfSAndreas Gohr opcache_invalidate($file); 805a38a129SAndreas Gohr } 815a38a129SAndreas Gohr 825a38a129SAndreas Gohr /** 835a38a129SAndreas Gohr * Configuration is considered locked if there is no local settings filename 845a38a129SAndreas Gohr * or the directory its in is not writable or the file exists and is not writable 855a38a129SAndreas Gohr * 865a38a129SAndreas Gohr * @return bool true: locked, false: writable 875a38a129SAndreas Gohr */ 885a38a129SAndreas Gohr public function isLocked() { 895a38a129SAndreas Gohr if(!$this->savefile) return true; 905a38a129SAndreas Gohr if(!is_writable(dirname($this->savefile))) return true; 915a38a129SAndreas Gohr if(file_exists($this->savefile) && !is_writable($this->savefile)) return true; 925a38a129SAndreas Gohr return false; 935a38a129SAndreas Gohr } 945a38a129SAndreas Gohr 955a38a129SAndreas Gohr /** 965a38a129SAndreas Gohr * Returns the PHP intro header for the config file 975a38a129SAndreas Gohr * 985a38a129SAndreas Gohr * @return string 995a38a129SAndreas Gohr */ 1005a38a129SAndreas Gohr protected function getHeader() { 1015a38a129SAndreas Gohr return join( 1025a38a129SAndreas Gohr "\n", 1035a38a129SAndreas Gohr array( 1045a38a129SAndreas Gohr '<?php', 1055a38a129SAndreas Gohr '/*', 1065a38a129SAndreas Gohr ' * ' . $this->header, 1075a38a129SAndreas Gohr ' * Auto-generated by config plugin', 1085a38a129SAndreas Gohr ' * Run for user: ' . $_SERVER['REMOTE_USER'], 1095a38a129SAndreas Gohr ' * Date: ' . date('r'), 1105a38a129SAndreas Gohr ' */', 1115a38a129SAndreas Gohr '', 1125a38a129SAndreas Gohr '' 1135a38a129SAndreas Gohr ) 1145a38a129SAndreas Gohr ); 1155a38a129SAndreas Gohr } 1165a38a129SAndreas Gohr} 117