Passed
Push — master ( 1708b3...8af542 )
by Andreas
11:05 queued 14s
created

midcom_services_rcs_backend_rcs::exec()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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