xref: /dokuwiki/lib/plugins/config/core/Writer.php (revision 70b28bcf40ec9d6c30831d7c48f3872e43a019ec)
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)) {
365a38a129SAndreas Gohr            if(file_exists($this->savefile . '.bak')) @unlink($this->savefile . '.bak');
375a38a129SAndreas Gohr            if(!io_rename($this->savefile, $this->savefile . '.bak')) throw new \Exception('no backup');
385a38a129SAndreas Gohr        }
395a38a129SAndreas Gohr
405a38a129SAndreas Gohr        if(!$fh = @fopen($this->savefile, 'wb')) {
415a38a129SAndreas Gohr            io_rename($this->savefile . '.bak', $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) {
475a38a129SAndreas Gohr            $out .= $setting->out('conf', 'php');
485a38a129SAndreas Gohr        }
495a38a129SAndreas Gohr
505a38a129SAndreas Gohr        fwrite($fh, $out);
515a38a129SAndreas Gohr        fclose($fh);
525a38a129SAndreas Gohr        if($conf['fperm']) chmod($this->savefile, $conf['fperm']);
53*70b28bcfSAndreas Gohr        $this->opcacheUpdate($this->savefile);
545a38a129SAndreas Gohr    }
555a38a129SAndreas Gohr
565a38a129SAndreas Gohr    /**
575a38a129SAndreas Gohr     * Update last modified time stamp of the config file
585a38a129SAndreas Gohr     *
595a38a129SAndreas Gohr     * Will invalidate all DokuWiki caches
605a38a129SAndreas Gohr     *
615a38a129SAndreas Gohr     * @throws \Exception when the config isn't writable
625a38a129SAndreas Gohr     */
635a38a129SAndreas Gohr    public function touch() {
645a38a129SAndreas Gohr        if($this->isLocked()) throw new \Exception('no save');
655a38a129SAndreas Gohr        @touch($this->savefile);
66*70b28bcfSAndreas Gohr        $this->opcacheUpdate($this->savefile);
67*70b28bcfSAndreas Gohr    }
68*70b28bcfSAndreas Gohr
69*70b28bcfSAndreas Gohr    /**
70*70b28bcfSAndreas Gohr     * Invalidate the opcache of the given file
71*70b28bcfSAndreas Gohr     *
72*70b28bcfSAndreas Gohr     * @todo this should probably be moved to core
73*70b28bcfSAndreas Gohr     * @param string $file
74*70b28bcfSAndreas Gohr     */
75*70b28bcfSAndreas Gohr    protected function opcacheUpdate($file) {
76*70b28bcfSAndreas Gohr        if(!function_exists('opcache_invalidate')) return;
77*70b28bcfSAndreas Gohr        opcache_invalidate($file);
785a38a129SAndreas Gohr    }
795a38a129SAndreas Gohr
805a38a129SAndreas Gohr    /**
815a38a129SAndreas Gohr     * Configuration is considered locked if there is no local settings filename
825a38a129SAndreas Gohr     * or the directory its in is not writable or the file exists and is not writable
835a38a129SAndreas Gohr     *
845a38a129SAndreas Gohr     * @return bool true: locked, false: writable
855a38a129SAndreas Gohr     */
865a38a129SAndreas Gohr    public function isLocked() {
875a38a129SAndreas Gohr        if(!$this->savefile) return true;
885a38a129SAndreas Gohr        if(!is_writable(dirname($this->savefile))) return true;
895a38a129SAndreas Gohr        if(file_exists($this->savefile) && !is_writable($this->savefile)) return true;
905a38a129SAndreas Gohr        return false;
915a38a129SAndreas Gohr    }
925a38a129SAndreas Gohr
935a38a129SAndreas Gohr    /**
945a38a129SAndreas Gohr     * Returns the PHP intro header for the config file
955a38a129SAndreas Gohr     *
965a38a129SAndreas Gohr     * @return string
975a38a129SAndreas Gohr     */
985a38a129SAndreas Gohr    protected function getHeader() {
995a38a129SAndreas Gohr        return join(
1005a38a129SAndreas Gohr            "\n",
1015a38a129SAndreas Gohr            array(
1025a38a129SAndreas Gohr                '<?php',
1035a38a129SAndreas Gohr                '/*',
1045a38a129SAndreas Gohr                ' * ' . $this->header,
1055a38a129SAndreas Gohr                ' * Auto-generated by config plugin',
1065a38a129SAndreas Gohr                ' * Run for user: ' . $_SERVER['REMOTE_USER'],
1075a38a129SAndreas Gohr                ' * Date: ' . date('r'),
1085a38a129SAndreas Gohr                ' */',
1095a38a129SAndreas Gohr                '',
1105a38a129SAndreas Gohr                ''
1115a38a129SAndreas Gohr            )
1125a38a129SAndreas Gohr        );
1135a38a129SAndreas Gohr    }
1145a38a129SAndreas Gohr}
115