Passed
Push — master ( 540e15...0ef424 )
by Andreas
22:29
created

midcom_services_rcs_handler::load_object()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 2
nop 1
dl 0
loc 10
ccs 5
cts 6
cp 0.8333
crap 3.0416
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package midcom.services.rcs
4
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
6
 */
7
8
use Symfony\Component\HttpFoundation\Request;
9
10
/**
11
 * @package midcom.services.rcs
12
 */
13
abstract class midcom_services_rcs_handler extends midcom_baseclasses_components_handler
14
{
15
    /**
16
     * RCS backend
17
     *
18
     * @var midcom_services_rcs_backend
19
     */
20
    private $backend;
21
22
    /**
23
     * Pointer to midgard object
24
     *
25
     * @var midcom_core_dbaobject
26
     */
27
    protected $object;
28
29
    protected $style_prefix = '';
30
31
    protected $url_prefix = '';
32
33
    abstract protected function get_object_url() : string;
34
35
    abstract protected function handler_callback(string $handler_id);
36
37
    abstract protected function get_breadcrumbs();
38
39 5
    protected function resolve_object_title()
40
    {
41 5
        return midcom_helper_reflector::get($this->object)->get_object_label($this->object);
42
    }
43
44
    /**
45
     * Load the object and the rcs backend
46
     */
47 6
    private function load_object(string $guid)
48
    {
49 6
        $this->object = midcom::get()->dbfactory->get_object_by_guid($guid);
50
51 6
        if (   !midcom::get()->config->get('midcom_services_rcs_enable')
52 6
            || !$this->object->_use_rcs) {
53
            throw new midcom_error_notfound("Revision control not supported for " . get_class($this->object) . ".");
54
        }
55
56 6
        $this->backend = midcom::get()->rcs->load_backend($this->object);
57 6
    }
58
59
    /**
60
     * Prepare version control toolbar
61
     */
62 4
    private function rcs_toolbar(string $revision, string $revision2 = null)
63
    {
64 4
        $this->add_stylesheet(MIDCOM_STATIC_URL . "/midcom.services.rcs/rcs.css");
65 4
        $prefix = midcom_core_context::get()->get_key(MIDCOM_CONTEXT_ANCHORPREFIX) . $this->url_prefix;
0 ignored issues
show
Bug introduced by
Are you sure midcom_core_context::get...M_CONTEXT_ANCHORPREFIX) of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

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

65
        $prefix = /** @scrutinizer ignore-type */ midcom_core_context::get()->get_key(MIDCOM_CONTEXT_ANCHORPREFIX) . $this->url_prefix;
Loading history...
66 4
        $history = $this->backend->get_history();
67 4
        $this->_request_data['rcs_toolbar'] = new midcom_helper_toolbar();
68 4
        $this->populate_rcs_toolbar($history, $prefix, $revision, $revision2);
69
70
        // RCS functional toolbar
71 4
        $this->_request_data['rcs_toolbar_2'] = new midcom_helper_toolbar();
72 4
        $restore = $revision2 ?: $revision;
73
74
        $buttons = [
75
            [
76 4
                MIDCOM_TOOLBAR_URL => "{$prefix}{$this->object->guid}/",
77 4
                MIDCOM_TOOLBAR_LABEL => $this->_l10n->get('show history'),
78 4
                MIDCOM_TOOLBAR_GLYPHICON => 'history',
79
            ], [
80 4
                MIDCOM_TOOLBAR_URL => "{$prefix}restore/{$this->object->guid}/{$restore}/",
81 4
                MIDCOM_TOOLBAR_LABEL => sprintf($this->_l10n->get('restore version %s'), $restore),
82 4
                MIDCOM_TOOLBAR_GLYPHICON => 'recycle',
83 4
                MIDCOM_TOOLBAR_ENABLED => ($restore !== $history->get_last()['revision']),
84
            ]
85
        ];
86 4
        $this->_request_data['rcs_toolbar_2']->add_items($buttons);
87 4
    }
88
89 4
    private function populate_rcs_toolbar(midcom_services_rcs_history $history, string $prefix, string $revision, ?string $revision2)
90
    {
91 4
        $first = $history->get_first()['revision'];
92 4
        $last = $history->get_last()['revision'];
93
94 4
        $revision2 = $revision2 ?? $revision;
95 4
        $diff_view = $revision2 != $revision;
96
97 4
        $previous = $history->get_prev_version($revision) ?? $first;
98 4
        $enabled = $revision !== $first;
99 4
        $this->add_button($prefix . 'preview', $first, 'fast-backward', $enabled || $diff_view, $first);
100 4
        if ($diff_view) {
101 2
            $this->add_button($prefix . 'preview', $revision, 'backward', true, $revision);
102
        } else {
103 2
            $this->add_button($prefix . 'preview', $previous, 'backward', $enabled, $previous);
104
        }
105 4
        $this->add_button($prefix . 'diff', $this->_l10n->get('show differences'), 'step-backward', $enabled, $previous, $revision);
106
107 4
        $this->add_button($prefix . 'preview', $revision2, 'file-o', $diff_view, $revision2);
108
109 4
        $next = $history->get_next_version($revision2) ?? $last;
110 4
        $enabled = $revision2 !== $last;
111 4
        $this->add_button($prefix . 'diff', $this->_l10n->get('show differences'), 'step-forward', $enabled, $revision2, $next);
112 4
        $this->add_button($prefix . 'preview', $next, 'forward', $enabled || $diff_view, $next);
113 4
        $this->add_button($prefix . 'preview', $last, 'fast-forward', $enabled || $diff_view, $last);
114 4
    }
115
116 4
    private function add_button(string $prefix, string $label, string $icon, bool $enabled, ...$args)
117
    {
118 4
        $this->_request_data['rcs_toolbar']->add_item([
119 4
            MIDCOM_TOOLBAR_URL => "{$prefix}/{$this->object->guid}/" . implode('/', $args ?? []),
120 4
            MIDCOM_TOOLBAR_LABEL => $label,
121 4
            MIDCOM_TOOLBAR_GLYPHICON => $icon,
122 4
            MIDCOM_TOOLBAR_ENABLED => $enabled,
123
        ]);
124 4
    }
125
126 6
    private function prepare_request_data(string $view_title)
127
    {
128 6
        $breadcrumbs = $this->get_breadcrumbs();
129 6
        if (!empty($breadcrumbs)) {
130 6
            foreach ($breadcrumbs as $item) {
131 6
                $this->add_breadcrumb($item[MIDCOM_NAV_URL], $item[MIDCOM_NAV_NAME]);
132
            }
133
        }
134 6
        $this->add_breadcrumb($this->url_prefix . "{$this->object->guid}/", $this->_l10n->get('show history'));
135
136 6
        if (!empty($this->_request_data['latest_revision'])) {
137 4
            $this->add_breadcrumb(
138 4
                $this->url_prefix . "preview/{$this->object->guid}/{$this->_request_data['latest_revision']}/",
139 4
                sprintf($this->_l10n->get('version %s'), $this->_request_data['latest_revision'])
140
            );
141
        }
142 6
        if (!empty($this->_request_data['compare_revision'])) {
143 2
            $this->add_breadcrumb(
144 2
                $this->url_prefix . "diff/{$this->object->guid}/{$this->_request_data['compare_revision']}/{$this->_request_data['latest_revision']}/",
145 2
                sprintf($this->_l10n->get('differences between %s and %s'), $this->_request_data['compare_revision'], $this->_request_data['latest_revision'])
146
            );
147
        }
148 6
        $this->_request_data['handler'] = $this;
149 6
        $this->_request_data['view_title'] = $view_title;
150 6
        midcom::get()->head->set_pagetitle($view_title);
151 6
    }
152
153 2
    public function translate(string $string) : string
154
    {
155 2
        $translated = $string;
156 2
        $component = midcom::get()->dbclassloader->get_component_for_class($this->object->__midcom_class_name__);
157 2
        if (midcom::get()->componentloader->is_installed($component)) {
0 ignored issues
show
Bug introduced by
It seems like $component can also be of type null; however, parameter $path of midcom_helper__componentloader::is_installed() does only seem to accept string, 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

157
        if (midcom::get()->componentloader->is_installed(/** @scrutinizer ignore-type */ $component)) {
Loading history...
158 2
            $translated = midcom::get()->i18n->get_l10n($component)->get($string);
0 ignored issues
show
Bug introduced by
It seems like $component can also be of type null; however, parameter $component of midcom_services_i18n::get_l10n() does only seem to accept string, 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

158
            $translated = midcom::get()->i18n->get_l10n(/** @scrutinizer ignore-type */ $component)->get($string);
Loading history...
159
        }
160 2
        if ($translated === $string) {
161 2
            $translated = $this->_l10n->get($string);
162 2
            if ($translated === $string) {
163 2
                $translated = $this->_l10n_midcom->get($string);
164
            }
165
        }
166 2
        return $translated;
167
    }
168
169
    /**
170
     * Show the changes done to the object
171
     */
172 2
    public function _handler_history(Request $request, string $handler_id, array $args)
173
    {
174
        // Check if the comparison request is valid
175 2
        $first = $request->query->get('first');
176 2
        $last = $request->query->get('last');
177 2
        if ($first && $last && $first != $last) {
178
            return new midcom_response_relocate($this->url_prefix . "diff/{$args[0]}/{$first}/{$last}/");
179
        }
180
181 2
        $this->load_object($args[0]);
182 2
        $view_title = sprintf($this->_l10n->get('revision history of %s'), $this->resolve_object_title());
183
184 2
        $this->prepare_request_data($view_title);
185 2
        return $this->handler_callback($handler_id);
186
    }
187
188
    /**
189
     * @param array $data The local request data.
190
     */
191 2
    public function _show_history(string $handler_id, array &$data)
192
    {
193 2
        $data['history'] = $this->backend->get_history();
194 2
        $data['guid'] = $this->object->guid;
195 2
        midcom_show_style($this->style_prefix . 'history');
196 2
    }
197
198
    /**
199
     * Show a diff between two versions
200
     */
201 2
    public function _handler_diff(string $handler_id, array $args, array &$data)
202
    {
203 2
        $this->load_object($args[0]);
204 2
        $history = $this->backend->get_history();
205
206 2
        if (   !$history->version_exists($args[1])
207 2
            || !$history->version_exists($args[2])) {
208
            throw new midcom_error_notfound("One of the revisions {$args[1]} or {$args[2]} does not exist.");
209
        }
210
211
        $data['diff'] = array_filter($this->backend->get_diff($args[1], $args[2]), function($value, $key) {
212 2
            return array_key_exists('diff', $value)
213 2
                && !is_array($value['diff'])
214 2
                && midcom_services_rcs::is_field_showable($key);
215 2
        }, ARRAY_FILTER_USE_BOTH);
216 2
        $data['comment'] = $history->get($args[2]);
217
218
        // Set the version numbers
219 2
        $data['compare_revision'] = $args[1];
220 2
        $data['latest_revision'] = $args[2];
221 2
        $data['guid'] = $args[0];
222
223 2
        $view_title = sprintf($this->_l10n->get('changes between revisions %s and %s'), $data['compare_revision'], $data['latest_revision']);
224
225
        // Load the toolbars
226 2
        $this->rcs_toolbar($args[1], $args[2]);
227 2
        $this->prepare_request_data($view_title);
228 2
        return $this->handler_callback($handler_id);
229
    }
230
231
    /**
232
     * Show the differences between the versions
233
     */
234 2
    public function _show_diff()
235
    {
236 2
        midcom_show_style($this->style_prefix . 'diff');
237 2
    }
238
239
    /**
240
     * View previews
241
     */
242 2
    public function _handler_preview(string $handler_id, array $args, array &$data)
243
    {
244 2
        $revision = $args[1];
245 2
        $data['latest_revision'] = $revision;
246 2
        $data['guid'] = $args[0];
247
248 2
        $this->load_object($args[0]);
249
        $data['preview'] = array_filter($this->backend->get_revision($revision), function ($value, $key) {
250 2
            return !is_array($value)
251 2
                && !in_array($value, ['', '0000-00-00'])
252 2
                && midcom_services_rcs::is_field_showable($key);
253 2
        }, ARRAY_FILTER_USE_BOTH);
254
255 2
        $this->_view_toolbar->hide_item($this->url_prefix . "preview/{$this->object->guid}/{$revision}/");
256
257 2
        $view_title = sprintf($this->_l10n->get('viewing version %s of %s'), $revision, $this->resolve_object_title());
258
        // Load the toolbars
259 2
        $this->rcs_toolbar($revision);
260 2
        $this->prepare_request_data($view_title);
261 2
        return $this->handler_callback($handler_id);
262
    }
263
264 2
    public function _show_preview()
265
    {
266 2
        midcom_show_style($this->style_prefix . 'preview');
267 2
    }
268
269
    /**
270
     * Restore to diff
271
     */
272
    public function _handler_restore(array $args)
273
    {
274
        $this->load_object($args[0]);
275
276
        $this->object->require_do('midgard:update');
277
        // TODO: set another privilege for restoring?
278
279
        if (   $this->backend->get_history()->version_exists($args[1])
280
            && $this->backend->restore_to_revision($args[1])) {
281
            midcom::get()->uimessages->add($this->_l10n->get('midcom.admin.rcs'), sprintf($this->_l10n->get('restore to version %s successful'), $args[1]));
282
            return new midcom_response_relocate($this->get_object_url());
283
        }
284
        throw new midcom_error(sprintf($this->_l10n->get('restore to version %s failed, reason %s'), $args[1], midcom_connection::get_error_string()));
285
    }
286
}
287