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