xref: /dokuwiki/lib/plugins/config/core/Writer.php (revision 5a38a129ffe7e1949e690730ee9157988de617c0)
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