Completed
Push — master ( e8fccc...474902 )
by Andreas
23:28
created

midcom_services_rcs_backend_rcs::test_config()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 6
ccs 3
cts 4
cp 0.75
crap 2.0625
rs 10
1
<?php
2
/**
3
 * @author tarjei huse
4
 * @package midcom.services.rcs
5
 * @copyright The Midgard Project, http://www.midgard-project.org
6
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
7
 */
8
9
/**
10
 * @package midcom.services.rcs
11
 */
12
class midcom_services_rcs_backend_rcs extends midcom_services_rcs_backend
13
{
14 82
    protected function test_config()
15
    {
16 82
        parent::test_config();
17
18 82
        if (!is_executable("{$this->config->get_bin_prefix()}ci")) {
19
            throw new midcom_error("Cannot execute {$this->config->get_bin_prefix()}ci.");
20
        }
21 82
    }
22
23
    /**
24
     * Save a new revision
25
     */
26 74
    public function update($updatemessage = null)
27
    {
28
        // Store user identifier and IP address to the update string
29 74
        $message = $_SERVER['REMOTE_ADDR'] . '|' . $updatemessage;
30 74
        $message = (midcom::get()->auth->user->id ?? 'NOBODY') . '|' . $message;
31
32 74
        $filename = $this->generate_filename();
33 74
        $rcsfilename = "{$filename},v";
34 74
        $message = escapeshellarg($message);
35
36 74
        if (file_exists($rcsfilename)) {
37 37
            $this->exec('co -q -f -l ' . escapeshellarg($filename));
38 37
            $command = 'ci -q -m' . $message . " {$filename}";
39
        } else {
40 64
            $command = 'ci -q -i -t-' . $message . ' -m' . $message . " {$filename}";
41
        }
42 74
        $mapper = new midcom_helper_exporter_xml;
43 74
        file_put_contents($filename, $mapper->object2data($this->object));
44 74
        $this->exec($command);
45
46 74
        if (file_exists($rcsfilename)) {
47 74
            chmod($rcsfilename, 0770);
48
        }
49 74
    }
50
51
    /**
52
     * Get the object of a revision
53
     *
54
     * @param string $revision identifier of revision wanted
55
     * @return array array representation of the object
56
     */
57 4
    public function get_revision($revision) : array
58
    {
59 4
        $filepath = $this->generate_filename();
60
        try {
61 4
            $this->exec('co -q -f -r' . escapeshellarg(trim($revision)) . " {$filepath} 2>/dev/null");
62
        } catch (midcom_error $e) {
63
            $e->log();
64 4
        } finally {
65 4
            if (!file_exists($filepath)) {
66 4
                return [];
67
            }
68
        }
69
70 4
        $data = file_get_contents($filepath);
71 4
        $this->run_command("rm -f {$filepath}");
72
73 4
        $mapper = new midcom_helper_exporter_xml();
74 4
        return $mapper->data2array($data);
75
    }
76
77 7
    protected function load_history() : array
78
    {
79 7
        $filename = $this->generate_filename() . ',v';
80 7
        if (!is_readable($filename)) {
81 3
            debug_add('file ' . $filename . ' is not readable, returning empty result', MIDCOM_LOG_INFO);
82 3
            return [];
83
        }
84 7
        $lines = $this->read_handle($this->config->get_bin_prefix() . 'rlog "' . $filename . '" 2>&1');
85 7
        $total = count($lines);
86 7
        $revisions = [];
87
88 7
        for ($i = 0; $i < $total; $i++) {
89 7
            if (substr($lines[$i], 0, 9) == "revision ") {
90 7
                $history = $this->parse_history_entry($lines[$i], $lines[$i + 1], $lines[$i + 2]);
91 7
                $revisions[$history['revision']] = $history;
92
93 7
                $i += 3;
94 7
                while (   $i < $total
95 7
                        && substr($lines[$i], 0, 4) != '----'
96 7
                        && substr($lines[$i], 0, 5) != '=====') {
97
                    $i++;
98
                }
99
            }
100
        }
101 7
        return $revisions;
102
    }
103
104 7
    private function parse_history_entry(string $line1, string $line2, string $line3) : array
105
    {
106
        // Create potentially empty defaults
107 7
        $history = ['date' => null, 'lines' => null, 'user' => null, 'ip' => null];
108
109
        // Revision number is in format
110
        // revision 1.11
111 7
        $history['revision'] = preg_replace('/(\d+\.\d+).*/', '$1', substr($line1, 9));
112
113
        // Entry metadata is in format
114
        // date: 2006/01/10 09:40:49;  author: www-data;  state: Exp;  lines: +2 -2
115
        // NOTE: Time here appears to be stored as UTC according to http://parand.com/docs/rcs.html
116 7
        $metadata_array = explode(';', $line2);
117 7
        foreach ($metadata_array as $metadata) {
118 7
            $metadata = trim($metadata);
119 7
            if (substr($metadata, 0, 5) == 'date:') {
120 7
                $history['date'] = strtotime(substr($metadata, 6));
121 7
            } elseif (substr($metadata, 0, 6) == 'lines:') {
122 6
                $history['lines'] = substr($metadata, 7);
123
            }
124
        }
125
126
        // Entry message is in format
127
        // user:27b841929d1e04118d53dd0a45e4b93a|84.34.133.194|message
128 7
        $message_array = explode('|', $line3);
129 7
        if (count($message_array) == 1) {
130
            $history['message'] = $message_array[0];
131
        } else {
132 7
            if ($message_array[0] != 'Object') {
133 7
                $history['user'] = $message_array[0];
134
            }
135 7
            $history['ip'] = $message_array[1];
136 7
            $history['message'] = $message_array[2];
137
        }
138 7
        return $history;
139
    }
140
141 78
    private function exec(string $command)
142
    {
143 78
        $this->run_command($this->config->get_bin_prefix() . $command);
144 78
    }
145
}
146