xref: /dokuwiki/lib/plugins/config/core/Configuration.php (revision 8ea5685f773a0565c35e0ace70b8b2797845ba6e)
1<?php
2/**
3 * Configuration Class
4 *
5 * @author  Chris Smith <chris@jalakai.co.uk>
6 * @author  Ben Coburn <btcoburn@silicodon.net>
7 */
8
9namespace dokuwiki\plugin\config\core;
10
11/**
12 * Class configuration
13 */
14class Configuration {
15
16    const KEYMARKER = '____';
17
18    protected $_name = 'conf';     // name of the config variable found in the files (overridden by $config['varname'])
19    protected $_format = 'php';    // format of the config file, supported formats - php (overridden by $config['format'])
20    protected $_heading = '';      // heading string written at top of config file - don't include comment indicators
21
22    /** @var ConfigParser */
23    protected $parser;
24
25    protected $_loaded = false;    // set to true after configuration files are loaded
26    protected $_metadata = array();// holds metadata describing the settings
27
28    public $locked = false;     // configuration is considered locked if it can't be updated
29    public $show_disabled_plugins = false;
30
31    // configuration filenames
32    protected $_default_files = array();
33    protected $_local_files = array();      // updated configuration is written to the first file
34    protected $_protected_files = array();
35
36    protected $_plugin_list = null;
37
38    /** @var ConfigSettings FIXME better name? */
39    protected $confset;
40
41
42    /**
43     * constructor
44     *
45     * @param string $datafile path to config metadata file
46     */
47    public function __construct($datafile) {
48        global $conf, $config_cascade;
49
50        if(!file_exists($datafile)) {
51            msg('No configuration metadata found at - ' . htmlspecialchars($datafile), -1);
52            return;
53        }
54
55        /** @var array $config gets loaded via include here */
56        /* FIXME I think we can remove this
57        include($datafile);
58        if(isset($config['varname'])) $this->_name = $config['varname'];
59        if(isset($config['format'])) $this->_format = $config['format'];
60        if(isset($config['heading'])) $this->_heading = $config['heading'];
61        */
62
63        $this->_local_files = $config_cascade['main']['local']; // FIXME simplify and remove this later
64        $this->locked = $this->_is_locked();
65
66        $this->confset = new ConfigSettings();
67    }
68
69    /**
70     * Stores setting[] array to file
71     *
72     * @param string $id Name of plugin, which saves the settings
73     * @param string $header Text at the top of the rewritten settings file
74     * @param bool $backup backup current file? (remove any existing backup)
75     * @return bool succesful?
76     */
77    public function save_settings($id, $header = '', $backup = true) {
78        global $conf;
79
80        if($this->locked) return false;
81
82        // write back to the last file in the local config cascade
83        $file = end($this->_local_files);
84
85        // backup current file (remove any existing backup)
86        if(file_exists($file) && $backup) {
87            if(file_exists($file . '.bak')) @unlink($file . '.bak');
88            if(!io_rename($file, $file . '.bak')) return false;
89        }
90
91        if(!$fh = @fopen($file, 'wb')) {
92            io_rename($file . '.bak', $file);     // problem opening, restore the backup
93            return false;
94        }
95
96        if(empty($header)) $header = $this->_heading;
97
98        $out = $this->_out_header($id, $header);
99
100        foreach($this->confset->getSettings() as $setting) {
101            $out .= $setting->out($this->_name, $this->_format);
102        }
103
104        $out .= $this->_out_footer();
105
106        @fwrite($fh, $out);
107        fclose($fh);
108        if($conf['fperm']) chmod($file, $conf['fperm']);
109        return true;
110    }
111
112    /**
113     * Update last modified time stamp of the config file
114     *
115     * @return bool
116     */
117    public function touch_settings() {
118        if($this->locked) return false;
119        $file = end($this->_local_files);
120        return @touch($file);
121    }
122
123    /**
124     * Returns header of rewritten settings file
125     *
126     * @param string $id plugin name of which generated this output
127     * @param string $header additional text for at top of the file
128     * @return string text of header
129     */
130    protected function _out_header($id, $header) {
131        $out = '';
132        if($this->_format == 'php') {
133            $out .= '<' . '?php' . "\n" .
134                "/*\n" .
135                " * " . $header . "\n" .
136                " * Auto-generated by " . $id . " plugin\n" .
137                " * Run for user: " . $_SERVER['REMOTE_USER'] . "\n" .
138                " * Date: " . date('r') . "\n" .
139                " */\n\n";
140        }
141
142        return $out;
143    }
144
145    /**
146     * Returns footer of rewritten settings file
147     *
148     * @return string text of footer
149     */
150    protected function _out_footer() {
151        $out = '';
152        if($this->_format == 'php') {
153            $out .= "\n// end auto-generated content\n";
154        }
155
156        return $out;
157    }
158
159    /**
160     * Configuration is considered locked if there is no local settings filename
161     * or the directory its in is not writable or the file exists and is not writable
162     *
163     * @return bool true: locked, false: writable
164     */
165    protected function _is_locked() {
166        if(!$this->_local_files) return true;
167
168        $local = $this->_local_files[0];
169
170        if(!is_writable(dirname($local))) return true;
171        if(file_exists($local) && !is_writable($local)) return true;
172
173        return false;
174    }
175
176}
177
178