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

midcom_services_rcs_backend::test_config()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2.1481

Importance

Changes 0
Metric Value
cc 2
eloc 2
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 4
ccs 2
cts 3
cp 0.6667
crap 2.1481
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
abstract class midcom_services_rcs_backend
13
{
14
    /**
15
     * Cached revision history for the object
16
     *
17
     * @var midcom_services_rcs_history
18
     */
19
    private $history;
20
21
    /**
22
     * The current object
23
     */
24
    protected $object;
25
26
    /**
27
     * @var midcom_services_rcs_config
28
     */
29
    protected $config;
30
31 83
    public function __construct($object, midcom_services_rcs_config $config)
32
    {
33 83
        $this->object = $object;
34 83
        $this->config = $config;
35 83
        $this->test_config();
36 83
    }
37
38 83
    protected function test_config()
39
    {
40 83
        if (!is_writable($this->config->get_rootdir())) {
41
            throw new midcom_error("The root directory {$this->config->get_rootdir()} is not writable!");
42
        }
43 83
    }
44
45 81
    protected function generate_filename() : string
46
    {
47 81
        $guid = $this->object->guid;
48
        // Keep files organized to subfolders to keep filesystem sane
49 81
        $dirpath = $this->config->get_rootdir() . "/{$guid[0]}/{$guid[1]}";
50 81
        if (!file_exists($dirpath)) {
51 58
            debug_add("Directory {$dirpath} does not exist, attempting to create", MIDCOM_LOG_INFO);
52 58
            mkdir($dirpath, 0777, true);
53
        }
54 81
        return "{$dirpath}/{$guid}";
55
    }
56
57 8
    protected function read_handle(string $command) : array
58
    {
59 8
        $fh = popen($command, "r");
60 8
        $output = stream_get_contents($fh);
0 ignored issues
show
Bug introduced by
It seems like $fh can also be of type false; however, parameter $handle of stream_get_contents() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

60
        $output = stream_get_contents(/** @scrutinizer ignore-type */ $fh);
Loading history...
61 8
        pclose($fh);
0 ignored issues
show
Bug introduced by
It seems like $fh can also be of type false; however, parameter $handle of pclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

61
        pclose(/** @scrutinizer ignore-type */ $fh);
Loading history...
62 8
        return explode("\n", $output);
63
    }
64
65 79
    protected function run_command(string $command)
66
    {
67 79
        $status = $output = null;
68 79
        $command .= ' 2>&1';
69 79
        debug_add("Executing '{$command}'");
70 79
        exec($command, $output, $status);
71 79
        if ($status !== 0) {
72
            debug_print_r('Got output: ', $output);
73
            throw new midcom_error("Command '{$command}' returned with status {$status}:" . implode("\n", $output), MIDCOM_LOG_WARN);
74
        }
75 79
    }
76
77
    /**
78
     * Save a revision of an object, or create a revision if none exists
79
     *
80
     * @param midcom_core_dbaobject $object the object to save.
81
     * @param string $updatemessage the message to be saved with the object.
82
     * @throws midcom_error on serious errors.
83
     */
84
    abstract public function update($updatemessage = null);
85
86
    abstract public function get_revision($revision) : array;
87
88
    /**
89
     * Lists the number of changes that has been done to the object
90
     * Order: The first entry is the newest.
91
     */
92
    abstract protected function load_history() : array;
93
94 8
    public function get_history() : midcom_services_rcs_history
95
    {
96 8
        if ($this->history === null) {
97 8
            $revisions = $this->load_history();
98 8
            $this->history = new midcom_services_rcs_history($revisions);
99
        }
100
101 8
        return $this->history;
102
    }
103
104
    /**
105
     * Get a html diff between two versions.
106
     *
107
     * @param string $oldest_revision id of the oldest revision
108
     * @param string $latest_revision id of the latest revision
109
     */
110 2
    public function get_diff($oldest_revision, $latest_revision) : array
111
    {
112 2
        $oldest = $this->get_revision($oldest_revision);
113 2
        $newest = $this->get_revision($latest_revision);
114
115 2
        $return = [];
116 2
        $oldest = array_intersect_key($oldest, $newest);
117
118
        $repl = [
119 2
            '<del>' => "<span class=\"deleted\">",
120
            '</del>' => '</span>',
121
            '<ins>' => "<span class=\"inserted\">",
122
            '</ins>' => '</span>'
123
        ];
124 2
        foreach ($oldest as $attribute => $oldest_value) {
125 2
            if (is_array($oldest_value)) {
126 2
                continue;
127
            }
128
129 2
            $return[$attribute] = [
130 2
                'old' => $oldest_value,
131 2
                'new' => $newest[$attribute]
132
            ];
133
134 2
            if ($oldest_value != $newest[$attribute]) {
135 2
                $lines1 = explode("\n", $oldest_value);
136 2
                $lines2 = explode("\n", $newest[$attribute]);
137
138 2
                $renderer = new midcom_services_rcs_renderer_html_sidebyside(['old' => $oldest_revision, 'new' => $latest_revision]);
139
140 2
                if ($lines1 != $lines2) {
141 2
                    $diff = new Diff($lines1, $lines2);
142
                    // Run the diff
143 2
                    $return[$attribute]['diff'] = $diff->render($renderer);
144
                    // Modify the output for nicer rendering
145 2
                    $return[$attribute]['diff'] = strtr($return[$attribute]['diff'], $repl);
146
                }
147
            }
148
        }
149
150 2
        return $return;
151
    }
152
153
    /**
154
     * Restore an object to a certain revision.
155
     *
156
     * @param string $revision of revision to restore object to.
157
     * @return boolean true on success.
158
     */
159
    public function restore_to_revision($revision) : bool
160
    {
161
        $new = $this->get_revision($revision);
162
        $mapper = new midcom_helper_exporter_xml();
163
        $this->object = $mapper->data2object($new, $this->object);
164
        $this->object->set_rcs_message("Reverted to revision {$revision}");
165
166
        return $this->object->update();
167
    }
168
}
169