Completed
Branch master (4f76a2)
by Andreas
22:32
created

resolve_object_title()   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 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
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($handler_id);
36
37
    abstract protected function get_breadcrumbs();
38
39 6
    protected function resolve_object_title()
40
    {
41 6
        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 6
    private function rcs_toolbar($current = null, $diff_view = false)
63
    {
64 6
        $this->add_stylesheet(MIDCOM_STATIC_URL . "/midcom.services.rcs/rcs.css");
65 6
        $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
67 6
        $this->_request_data['rcs_toolbar'] = new midcom_helper_toolbar();
68
69 6
        $last = $this->build_rcs_toolbar($this->_request_data['rcs_toolbar'], $current, $diff_view);
70
71
        // RCS functional toolbar
72 6
        $this->_request_data['rcs_toolbar_2'] = new midcom_helper_toolbar();
73
        $buttons = [
74
            [
75 6
                MIDCOM_TOOLBAR_URL => "{$prefix}{$this->object->guid}/",
76 6
                MIDCOM_TOOLBAR_LABEL => $this->_l10n->get('show history'),
77 6
                MIDCOM_TOOLBAR_GLYPHICON => 'history',
78
            ]
79
        ];
80
81 6
        if (!empty($current)) {
82 4
            $buttons[] = [
83 4
                MIDCOM_TOOLBAR_URL => "{$prefix}restore/{$this->object->guid}/{$current}/",
84 4
                MIDCOM_TOOLBAR_LABEL => sprintf($this->_l10n->get('restore version %s'), $current),
85 4
                MIDCOM_TOOLBAR_GLYPHICON => 'recycle',
86 4
                MIDCOM_TOOLBAR_ENABLED => ($current !== $last),
87
            ];
88
        }
89 6
        $this->_request_data['rcs_toolbar_2']->add_items($buttons);
90 6
    }
91
92 6
    private function build_rcs_toolbar(midcom_helper_toolbar $toolbar, $current, bool $diff_view)
93
    {
94 6
        $history = $this->backend->get_history();
95 6
        $first = $history->get_first()['revision'] ?? null;
96
97 6
        if (!$first) {
98 2
            return;
99
        }
100 6
        $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

100
        $prefix = /** @scrutinizer ignore-type */ midcom_core_context::get()->get_key(MIDCOM_CONTEXT_ANCHORPREFIX) . $this->url_prefix;
Loading history...
101 6
        $last = $history->get_last()['revision'];
102
103
        $buttons = [[
104 6
            MIDCOM_TOOLBAR_URL => "{$prefix}preview/{$this->object->guid}/{$first}",
105 6
            MIDCOM_TOOLBAR_LABEL => $first,
106 6
            MIDCOM_TOOLBAR_GLYPHICON => 'fast-backward',
107 6
            MIDCOM_TOOLBAR_ENABLED => ($current !== $first || $diff_view),
108
        ]];
109
110 6
        if (!empty($current)) {
111 4
            $previous = $history->get_prev_version($current) ?? $first;
112 4
            $next = $history->get_next_version($current) ?? $last;
113
114 4
            $buttons[] = [
115 4
                MIDCOM_TOOLBAR_URL => "{$prefix}preview/{$this->object->guid}/{$previous}",
116 4
                MIDCOM_TOOLBAR_LABEL => $previous,
117 4
                MIDCOM_TOOLBAR_GLYPHICON => 'backward',
118 4
                MIDCOM_TOOLBAR_ENABLED => ($current !== $first || $diff_view),
119
            ];
120
121 4
            $buttons[] = [
122 4
                MIDCOM_TOOLBAR_URL => "{$prefix}diff/{$this->object->guid}/{$current}/{$previous}/",
123 4
                MIDCOM_TOOLBAR_LABEL => $this->_l10n->get('show differences'),
124 4
                MIDCOM_TOOLBAR_GLYPHICON => 'step-backward',
125 4
                MIDCOM_TOOLBAR_ENABLED => ($current !== $first),
126
            ];
127
128 4
            $buttons[] = [
129 4
                MIDCOM_TOOLBAR_URL => "{$prefix}preview/{$current}/{$current}/",
130 4
                MIDCOM_TOOLBAR_LABEL => sprintf($this->_l10n->get('version %s'), $current),
131 4
                MIDCOM_TOOLBAR_GLYPHICON => 'file-o',
132
                MIDCOM_TOOLBAR_ENABLED => false,
133
            ];
134
135 4
            $buttons[] = [
136 4
                MIDCOM_TOOLBAR_URL => "{$prefix}diff/{$this->object->guid}/{$current}/{$next}/",
137 4
                MIDCOM_TOOLBAR_LABEL => $this->_l10n->get('show differences'),
138 4
                MIDCOM_TOOLBAR_GLYPHICON => 'step-forward',
139 4
                MIDCOM_TOOLBAR_ENABLED => ($current !== $last),
140
            ];
141
142 4
            $buttons[] = [
143 4
                MIDCOM_TOOLBAR_URL => "{$prefix}preview/{$this->object->guid}/{$next}",
144 4
                MIDCOM_TOOLBAR_LABEL => $next,
145 4
                MIDCOM_TOOLBAR_GLYPHICON => 'forward',
146 4
                MIDCOM_TOOLBAR_ENABLED => ($current !== $last || $diff_view),
147
            ];
148
        }
149
150 6
        $buttons[] = [
151 6
            MIDCOM_TOOLBAR_URL => "{$prefix}preview/{$this->object->guid}/{$last}",
152 6
            MIDCOM_TOOLBAR_LABEL => $last,
153 6
            MIDCOM_TOOLBAR_GLYPHICON => 'fast-forward',
154 6
            MIDCOM_TOOLBAR_ENABLED => ($current !== $last || $diff_view),
155
        ];
156
157 6
        $toolbar->add_items($buttons);
158 6
        return $last;
159
    }
160
161 6
    private function prepare_request_data(string $view_title)
162
    {
163 6
        $breadcrumbs = $this->get_breadcrumbs();
164 6
        if (!empty($breadcrumbs)) {
165 6
            foreach ($breadcrumbs as $item) {
166 6
                $this->add_breadcrumb($item[MIDCOM_NAV_URL], $item[MIDCOM_NAV_NAME]);
167
            }
168
        }
169 6
        $this->add_breadcrumb($this->url_prefix . "{$this->object->guid}/", $this->_l10n->get('show history'));
170
171 6
        if (!empty($this->_request_data['latest_revision'])) {
172 4
            $this->add_breadcrumb(
173 4
                $this->url_prefix . "preview/{$this->object->guid}/{$this->_request_data['latest_revision']}/",
174 4
                sprintf($this->_l10n->get('version %s'), $this->_request_data['latest_revision'])
175
            );
176
        }
177 6
        if (!empty($this->_request_data['compare_revision'])) {
178 2
            $this->add_breadcrumb(
179 2
                $this->url_prefix . "diff/{$this->object->guid}/{$this->_request_data['compare_revision']}/{$this->_request_data['latest_revision']}/",
180 2
                sprintf($this->_l10n->get('differences between %s and %s'), $this->_request_data['compare_revision'], $this->_request_data['latest_revision'])
181
            );
182
        }
183 6
        $this->_request_data['handler'] = $this;
184 6
        $this->_request_data['view_title'] = $view_title;
185 6
        midcom::get()->head->set_pagetitle($view_title);
186 6
    }
187
188 2
    public function translate($string) : string
189
    {
190 2
        $translated = $string;
191 2
        $component = midcom::get()->dbclassloader->get_component_for_class($this->object->__midcom_class_name__);
192 2
        if (midcom::get()->componentloader->is_installed($component)) {
193 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

193
            $translated = midcom::get()->i18n->get_l10n(/** @scrutinizer ignore-type */ $component)->get($string);
Loading history...
194
        }
195 2
        if ($translated === $string) {
196 2
            $translated = $this->_l10n->get($string);
197 2
            if ($translated === $string) {
198 2
                $translated = $this->_l10n_midcom->get($string);
199
            }
200
        }
201 2
        return $translated;
202
    }
203
204
    /**
205
     * Show the changes done to the object
206
     */
207 2
    public function _handler_history(Request $request, string $handler_id, array $args)
208
    {
209
        // Check if the comparison request is valid
210 2
        $first = $request->query->get('first');
211 2
        $last = $request->query->get('last');
212 2
        if ($first && $last && $first != $last) {
213
            return new midcom_response_relocate($this->url_prefix . "diff/{$args[0]}/{$first}/{$last}/");
214
        }
215
216 2
        $this->load_object($args[0]);
217 2
        $view_title = sprintf($this->_l10n->get('revision history of %s'), $this->resolve_object_title());
218
219 2
        $this->rcs_toolbar();
220 2
        $this->prepare_request_data($view_title);
221 2
        return $this->handler_callback($handler_id);
222
    }
223
224
    /**
225
     * @param mixed $handler_id The ID of the handler.
226
     * @param array $data The local request data.
227
     */
228 2
    public function _show_history($handler_id, array &$data)
229
    {
230 2
        $data['history'] = $this->backend->get_history();
231 2
        $data['guid'] = $this->object->guid;
232 2
        midcom_show_style($this->style_prefix . 'history');
233 2
    }
234
235
    /**
236
     * Show a diff between two versions
237
     */
238 2
    public function _handler_diff(string $handler_id, array $args, array &$data)
239
    {
240 2
        $this->load_object($args[0]);
241 2
        $history = $this->backend->get_history();
242
243 2
        if (   !$history->version_exists($args[1])
244 2
            || !$history->version_exists($args[2])) {
245
            throw new midcom_error_notfound("One of the revisions {$args[1]} or {$args[2]} does not exist.");
246
        }
247
248
        $data['diff'] = array_filter($this->backend->get_diff($args[1], $args[2]), function($value, $key) {
249 2
            return array_key_exists('diff', $value)
250 2
                && !is_array($value['diff'])
251 2
                && midcom_services_rcs::is_field_showable($key);
252 2
        }, ARRAY_FILTER_USE_BOTH);
253 2
        $data['comment'] = $history->get($args[2]);
254
255
        // Set the version numbers
256 2
        $data['compare_revision'] = $args[1];
257 2
        $data['latest_revision'] = $args[2];
258 2
        $data['guid'] = $args[0];
259
260 2
        $view_title = sprintf($this->_l10n->get('changes done in revision %s to %s'), $data['latest_revision'], $this->resolve_object_title());
261
262
        // Load the toolbars
263 2
        $this->rcs_toolbar($args[2], true);
264 2
        $this->prepare_request_data($view_title);
265 2
        return $this->handler_callback($handler_id);
266
    }
267
268
    /**
269
     * Show the differences between the versions
270
     */
271 2
    public function _show_diff()
272
    {
273 2
        midcom_show_style($this->style_prefix . 'diff');
274 2
    }
275
276
    /**
277
     * View previews
278
     */
279 2
    public function _handler_preview(string $handler_id, array $args, array &$data)
280
    {
281 2
        $revision = $args[1];
282 2
        $data['latest_revision'] = $revision;
283 2
        $data['guid'] = $args[0];
284
285 2
        $this->load_object($args[0]);
286
        $data['preview'] = array_filter($this->backend->get_revision($revision), function ($value, $key) {
287 2
            return !is_array($value)
288 2
                && !in_array($value, ['', '0000-00-00'])
289 2
                && midcom_services_rcs::is_field_showable($key);
290 2
        }, ARRAY_FILTER_USE_BOTH);
291
292 2
        $this->_view_toolbar->hide_item($this->url_prefix . "preview/{$this->object->guid}/{$revision}/");
293
294 2
        $view_title = sprintf($this->_l10n->get('viewing version %s of %s'), $revision, $this->resolve_object_title());
295
        // Load the toolbars
296 2
        $this->rcs_toolbar($revision);
297 2
        $this->prepare_request_data($view_title);
298 2
        return $this->handler_callback($handler_id);
299
    }
300
301 2
    public function _show_preview()
302
    {
303 2
        midcom_show_style($this->style_prefix . 'preview');
304 2
    }
305
306
    /**
307
     * Restore to diff
308
     */
309
    public function _handler_restore(array $args)
310
    {
311
        $this->load_object($args[0]);
312
313
        $this->object->require_do('midgard:update');
314
        // TODO: set another privilege for restoring?
315
316
        if (   $this->backend->get_history()->version_exists($args[1])
317
            && $this->backend->restore_to_revision($args[1])) {
318
            midcom::get()->uimessages->add($this->_l10n->get('midcom.admin.rcs'), sprintf($this->_l10n->get('restore to version %s successful'), $args[1]));
319
            return new midcom_response_relocate($this->get_object_url());
320
        }
321
        throw new midcom_error(sprintf($this->_l10n->get('restore to version %s failed, reason %s'), $args[1], midcom_connection::get_error_string()));
322
    }
323
}
324