Failed Conditions
Pull Request — psr2 (#2382)
by Andreas
08:02 queued 12s
created

Writer::save()   D

Complexity

Conditions 9
Paths 24

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 9
eloc 17
c 2
b 0
f 1
nc 24
nop 1
dl 0
loc 27
rs 4.909
1
<?php
2
3
namespace dokuwiki\plugin\config\core;
4
use dokuwiki\plugin\config\core\Setting\Setting;
5
6
/**
7
 * Writes the settings to the correct local file
8
 */
9
class Writer {
10
    /** @var string header info */
11
    protected $header = 'Dokuwiki\'s Main Configuration File - Local Settings';
12
13
    /** @var string the file where the config will be saved to */
14
    protected $savefile;
15
16
    /**
17
     * Writer constructor.
18
     */
19
    public function __construct() {
20
        global $config_cascade;
21
        $this->savefile = end($config_cascade['main']['local']);
22
    }
23
24
    /**
25
     * Save the given settings
26
     *
27
     * @param Setting[] $settings
28
     * @throws \Exception
29
     */
30
    public function save($settings) {
31
        global $conf;
32
        if($this->isLocked()) throw new \Exception('no save');
33
34
        // backup current file (remove any existing backup)
35
        if(file_exists($this->savefile)) {
36
            if(file_exists($this->savefile . '.bak')) @unlink($this->savefile . '.bak');
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
37
            if(!io_rename($this->savefile, $this->savefile . '.bak')) throw new \Exception('no backup');
38
        }
39
40
        if(!$fh = @fopen($this->savefile, 'wb')) {
41
            io_rename($this->savefile . '.bak', $this->savefile); // problem opening, restore the backup
42
            throw new \Exception('no save');
43
        }
44
45
        $out = $this->getHeader();
46
        foreach($settings as $setting) {
47
            if($setting->shouldBeSaved()) {
48
                $out .= $setting->out('conf', 'php');
49
            }
50
        }
51
52
        fwrite($fh, $out);
53
        fclose($fh);
54
        if($conf['fperm']) chmod($this->savefile, $conf['fperm']);
55
        $this->opcacheUpdate($this->savefile);
56
    }
57
58
    /**
59
     * Update last modified time stamp of the config file
60
     *
61
     * Will invalidate all DokuWiki caches
62
     *
63
     * @throws \Exception when the config isn't writable
64
     */
65
    public function touch() {
66
        if($this->isLocked()) throw new \Exception('no save');
67
        @touch($this->savefile);
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
68
        $this->opcacheUpdate($this->savefile);
69
    }
70
71
    /**
72
     * Invalidate the opcache of the given file
73
     *
74
     * @todo this should probably be moved to core
75
     * @param string $file
76
     */
77
    protected function opcacheUpdate($file) {
78
        if(!function_exists('opcache_invalidate')) return;
79
        opcache_invalidate($file);
80
    }
81
82
    /**
83
     * Configuration is considered locked if there is no local settings filename
84
     * or the directory its in is not writable or the file exists and is not writable
85
     *
86
     * @return bool true: locked, false: writable
87
     */
88
    public function isLocked() {
89
        if(!$this->savefile) return true;
90
        if(!is_writable(dirname($this->savefile))) return true;
91
        if(file_exists($this->savefile) && !is_writable($this->savefile)) return true;
92
        return false;
93
    }
94
95
    /**
96
     * Returns the PHP intro header for the config file
97
     *
98
     * @return string
99
     */
100
    protected function getHeader() {
101
        return join(
102
            "\n",
103
            array(
104
                '<?php',
105
                '/*',
106
                ' * ' . $this->header,
107
                ' * Auto-generated by config plugin',
108
                ' * Run for user: ' . $_SERVER['REMOTE_USER'],
109
                ' * Date: ' . date('r'),
110
                ' */',
111
                '',
112
                ''
113
            )
114
        );
115
    }
116
}
117