Completed
Push — psr2-config ( 0a5b05...eb1b59 )
by Andreas
09:49 queued 04:52
created

Writer::opcacheUpdate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
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
            $out .= $setting->out('conf', 'php');
48
        }
49
50
        fwrite($fh, $out);
51
        fclose($fh);
52
        if($conf['fperm']) chmod($this->savefile, $conf['fperm']);
53
        $this->opcacheUpdate($this->savefile);
54
    }
55
56
    /**
57
     * Update last modified time stamp of the config file
58
     *
59
     * Will invalidate all DokuWiki caches
60
     *
61
     * @throws \Exception when the config isn't writable
62
     */
63
    public function touch() {
64
        if($this->isLocked()) throw new \Exception('no save');
65
        @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...
66
        $this->opcacheUpdate($this->savefile);
67
    }
68
69
    /**
70
     * Invalidate the opcache of the given file
71
     *
72
     * @todo this should probably be moved to core
73
     * @param string $file
74
     */
75
    protected function opcacheUpdate($file) {
76
        if(!function_exists('opcache_invalidate')) return;
77
        opcache_invalidate($file);
78
    }
79
80
    /**
81
     * Configuration is considered locked if there is no local settings filename
82
     * or the directory its in is not writable or the file exists and is not writable
83
     *
84
     * @return bool true: locked, false: writable
85
     */
86
    public function isLocked() {
87
        if(!$this->savefile) return true;
88
        if(!is_writable(dirname($this->savefile))) return true;
89
        if(file_exists($this->savefile) && !is_writable($this->savefile)) return true;
90
        return false;
91
    }
92
93
    /**
94
     * Returns the PHP intro header for the config file
95
     *
96
     * @return string
97
     */
98
    protected function getHeader() {
99
        return join(
100
            "\n",
101
            array(
102
                '<?php',
103
                '/*',
104
                ' * ' . $this->header,
105
                ' * Auto-generated by config plugin',
106
                ' * Run for user: ' . $_SERVER['REMOTE_USER'],
107
                ' * Date: ' . date('r'),
108
                ' */',
109
                '',
110
                ''
111
            )
112
        );
113
    }
114
}
115