Issues (806)

lib/midcom/services/toolbars.php (9 issues)

1
<?php
2
/**
3
 * @package midcom.services
4
 * @author The Midgard Project, http://www.midgard-project.org
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
 * On-site toolbar service.
11
 *
12
 * This service manages the toolbars used for the on-site administration system.
13
 * For each context, it provides the following set of toolbars:
14
 *
15
 * 1. The <i>Node</i> toolbar is applicable to the current
16
 *    node, which is usually a topic. MidCOM places the topic management operations
17
 *    into this toolbar, where applicable.
18
 *
19
 * 2. The <i>View</i> toolbar is applicable to the specific view ("url"). Usually
20
 *    this maps to a single displayed object (see also the bind_to() member
21
 *    function). MidCOM places the object-specific management operations (like
22
 *    Metadata controls) into this toolbar, if it is bound to an object. Otherwise,
23
 *    this toolbar is not touched by MidCOM.
24
 *
25
 * It is important to understand that the default toolbars made available through this
26
 * service are completely specific to a given request context. If you have a dynamic_load
27
 * running on a given site, it will have its own set of toolbars for each instance.
28
 *
29
 * In addition, components may retrieve a third kind of toolbars, which are not under
30
 * the general control of MidCOM, the <i>Object</i> toolbars. They apply to a single
31
 * database object (like a bound <i>View</i> toolbar). The usage of this kind of
32
 * toolbars is completely component-specific.
33
 *
34
 * <b>Implementation notes</b>
35
 *
36
 * It has yet to prove if the toolbar system is needed for a dynamic_load environments.
37
 * The main reason for this is that dl'ed stuff is often quite tight in space and thus cannot
38
 * display any toolbars in a sane way. Usually, the administrative tasks will be bound to the
39
 * main request.
40
 *
41
 * This could be different for portal applications, which display several components on the
42
 * welcome page, each with its own management options.
43
 *
44
 * <b>Configuration</b>
45
 * See midcom_config for configuration options.
46
 *
47
 * @package midcom.services
48
 */
49
class midcom_services_toolbars
50
{
51
    /**
52
     * The toolbars currently available.
53
     *
54
     * This array is indexed by context id; each value consists of a flat array
55
     * of two toolbars, the first object being the Node toolbar, the second
56
     * View toolbar. The toolbars are created on-demand.
57
     */
58
    private array $_toolbars = [];
59
60
    /**
61
     * Whether we're in centralized mode, i.e. centralized toolbar has been shown
62
     */
63
    private bool $_centralized_mode = false;
64
65
    public function get_class_magic_default_privileges() : array
66
    {
67
        return [
68
            'EVERYONE' => [],
69
            'ANONYMOUS' => [],
70
            'USERS' => []
71
        ];
72
    }
73
74
    /**
75
     * Returns the host toolbar of the current context.
76
     * The toolbar will be created if this is the first request.
77
     */
78
    function get_host_toolbar() : midcom_helper_toolbar_host
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
79
    {
80
        return $this->_get_toolbar(MIDCOM_TOOLBAR_HOST);
81
    }
82
83
    /**
84
     * Returns the node toolbar of the current context.
85
     * The toolbar will be created if this is the first request.
86
     */
87 351
    public function get_node_toolbar() : midcom_helper_toolbar_node
88
    {
89 351
        return $this->_get_toolbar(MIDCOM_TOOLBAR_NODE);
90
    }
91
92
    /**
93
     * Returns the view toolbar of the current context.
94
     * The toolbar will be created if this is the first request.
95
     */
96 351
    public function get_view_toolbar() : midcom_helper_toolbar_view
97
    {
98 351
        return $this->_get_toolbar(MIDCOM_TOOLBAR_VIEW);
99
    }
100
101
    /**
102
     * Returns the help toolbar of the current context.
103
     * The toolbar will be created if this is the first request.
104
     */
105
    public function get_help_toolbar() : midcom_helper_toolbar_help
106
    {
107
        return $this->_get_toolbar(MIDCOM_TOOLBAR_HELP);
108
    }
109
110 351
    private function _get_toolbar(string $identifier) : midcom_helper_toolbar
111
    {
112 351
        $context = midcom_core_context::get();
113
114 351
        if (!array_key_exists($context->id, $this->_toolbars)) {
115 351
            $this->_toolbars[$context->id] = [
116 351
                MIDCOM_TOOLBAR_HELP => null,
117 351
                MIDCOM_TOOLBAR_HOST => null,
118 351
                MIDCOM_TOOLBAR_NODE => null,
119 351
                MIDCOM_TOOLBAR_VIEW => null
120 351
            ];
121
        }
122 351
        if (!isset($this->_toolbars[$context->id][$identifier])) {
123
            switch ($identifier) {
124
                case MIDCOM_TOOLBAR_HELP:
125 7
                    $component = $context->get_key(MIDCOM_CONTEXT_COMPONENT);
126 7
                    $toolbar = new midcom_helper_toolbar_help($component);
0 ignored issues
show
It seems like $component can also be of type false; however, parameter $component of midcom_helper_toolbar_help::__construct() 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

126
                    $toolbar = new midcom_helper_toolbar_help(/** @scrutinizer ignore-type */ $component);
Loading history...
127 7
                    break;
128
                case MIDCOM_TOOLBAR_HOST:
129 7
                    $toolbar = new midcom_helper_toolbar_host;
130 7
                    break;
131
                case MIDCOM_TOOLBAR_NODE:
132 351
                    $topic = $context->get_key(MIDCOM_CONTEXT_CONTENTTOPIC);
133 351
                    $toolbar = new midcom_helper_toolbar_node($topic);
0 ignored issues
show
It seems like $topic can also be of type false; however, parameter $topic of midcom_helper_toolbar_node::__construct() does only seem to accept midcom_db_topic, 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

133
                    $toolbar = new midcom_helper_toolbar_node(/** @scrutinizer ignore-type */ $topic);
Loading history...
134 351
                    break;
135
                case MIDCOM_TOOLBAR_VIEW:
136 351
                    $toolbar = new midcom_helper_toolbar_view;
137 351
                    break;
138
                default:
139 7
                    $toolbar = new midcom_helper_toolbar;
140 7
                    break;
141
            }
142 351
            $this->_toolbars[$context->id][$identifier] = $toolbar;
143
        }
144 351
        return $this->_toolbars[$context->id][$identifier];
145
    }
146
147
    /**
148
     * Add a toolbar
149
     *
150
     * @param string $identifier
151
     */
152 7
    function add_toolbar($identifier, midcom_helper_toolbar $toolbar)
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
153
    {
154 7
        $context_id = midcom_core_context::get()->id;
155 7
        $this->_toolbars[$context_id][$identifier] = $toolbar;
156
    }
157
158
    /**
159
     * Renders the specified toolbar for the current context.
160
     *
161
     * If the toolbar is undefined, an empty string is returned.
162
     *
163
     * @param int $toolbar_identifier The toolbar identifier constant (one of
164
     *     MIDCOM_TOOLBAR_NODE or MIDCOM_TOOLBAR_VIEW etc.)
165
     * @see midcom_helper_toolbar::render()
166
     */
167 13
    function _render_toolbar($toolbar_identifier) : string
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
168
    {
169 13
        $this->add_head_elements();
170 13
        return $this->_get_toolbar($toolbar_identifier)->render();
171
    }
172
173
    /**
174
     * Renders the node toolbar for the current context. If the toolbar is undefined,
175
     * an empty string is returned. If you want to show the toolbar directly, look for
176
     * the show_xxx_toolbar methods.
177
     *
178
     * @see midcom_helper_toolbar::render()
179
     */
180
    public function render_node_toolbar() : string
181
    {
182
        return $this->_render_toolbar(MIDCOM_TOOLBAR_NODE);
183
    }
184
185
    /**
186
     * Renders the view toolbar for the current context. If the toolbar is undefined,
187
     * an empty string is returned. If you want to show the toolbar directly, look for
188
     * the show_xxx_toolbar methods.
189
     *
190
     * @see midcom_helper_toolbar::render()
191
     */
192 13
    public function render_view_toolbar() : string
193
    {
194 13
        return $this->_render_toolbar(MIDCOM_TOOLBAR_VIEW);
195
    }
196
197
    /**
198
     * Renders the host toolbar for the current context. If the toolbar is undefined,
199
     * an empty string is returned. If you want to show the toolbar directly, look for
200
     * the show_xxx_toolbar methods.
201
     *
202
     * @see midcom_helper_toolbar::render()
203
     */
204
    public function render_host_toolbar() : string
205
    {
206
        return $this->_render_toolbar(MIDCOM_TOOLBAR_HOST);
207
    }
208
209
    /**
210
     * Renders the help toolbar for the current context. If the toolbar is undefined,
211
     * an empty string is returned. If you want to show the toolbar directly, look for
212
     * the show_xxx_toolbar methods.
213
     *
214
     * @see midcom_helper_toolbar::render()
215
     */
216
    public function render_help_toolbar() : string
217
    {
218
        return $this->_render_toolbar(MIDCOM_TOOLBAR_HELP);
219
    }
220
221
    /**
222
     * Displays the node toolbar for the current context. If the toolbar is undefined,
223
     * an empty string is returned.
224
     *
225
     * @see midcom_helper_toolbar::render()
226
     */
227
    function show_node_toolbar()
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
228
    {
229
        if (!$this->_centralized_mode) {
230
            echo $this->render_node_toolbar();
231
        }
232
    }
233
234
    /**
235
     * Displays the host toolbar for the current context. If the toolbar is undefined,
236
     * an empty string is returned.
237
     *
238
     * @see midcom_helper_toolbar::render()
239
     */
240
    function show_host_toolbar()
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
241
    {
242
        if (!$this->_centralized_mode) {
243
            echo $this->render_host_toolbar();
244
        }
245
    }
246
247
    /**
248
     * Displays the view toolbar for the current context. If the toolbar is undefined,
249
     * an empty string is returned.
250
     *
251
     * @see midcom_helper_toolbar::render()
252
     */
253 10
    public function show_view_toolbar()
254
    {
255 10
        if (!$this->_centralized_mode) {
256 6
            echo $this->render_view_toolbar();
257
        }
258
    }
259
260
    /**
261
     * Displays the help toolbar for the current context. If the toolbar is undefined,
262
     * an empty string is returned.
263
     *
264
     * @see midcom_helper_toolbar::render()
265
     */
266
    function show_help_toolbar()
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
267
    {
268
        if (!$this->_centralized_mode) {
269
            echo $this->render_help_toolbar();
270
        }
271
    }
272
273 13
    private function add_head_elements(bool $centralized = false) : bool
274
    {
275 13
        if (   !midcom::get()->auth->user
276 8
            || !midcom::get()->config->get('toolbars_enable_centralized')
277 13
            || !midcom::get()->auth->can_user_do('midcom:centralized_toolbar', class: __CLASS__)) {
278 5
            return false;
279
        }
280 8
        if ($centralized && midcom::get()->auth->can_user_do('midcom:ajax', class: $this)) {
0 ignored issues
show
$this of type midcom_services_toolbars is incompatible with the type string expected by parameter $class of midcom_services_auth::can_user_do(). ( Ignorable by Annotation )

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

280
        if ($centralized && midcom::get()->auth->can_user_do('midcom:ajax', /** @scrutinizer ignore-type */ class: $this)) {
Loading history...
281 7
            $this->_centralized_mode = true;
282 7
            midcom::get()->head->enable_jquery_ui(['mouse', 'draggable']);
283 7
            midcom::get()->head->add_jsfile(MIDCOM_STATIC_URL . '/midcom.services.toolbars/jquery.midcom_services_toolbars.js');
284 7
            midcom::get()->head->prepend_stylesheet(MIDCOM_STATIC_URL . '/midcom.services.toolbars/fancy.css', 'screen');
285
        } else {
286 8
            $path = midcom::get()->config->get('toolbars_simple_css_path', MIDCOM_STATIC_URL . "/midcom.services.toolbars/simple.css");
287 8
            midcom::get()->head->prepend_stylesheet($path, 'screen');
288
        }
289 8
        midcom::get()->head->add_stylesheet(MIDCOM_STATIC_URL . '/stock-icons/font-awesome-4.7.0/css/font-awesome.min.css');
290 8
        return true;
291
    }
292
293
    /**
294
     * Displays the combined MidCOM toolbar system for the current context.
295
     *
296
     * @see midcom_helper_toolbar::render()
297
     */
298 7
    public function show()
299
    {
300 7
        $context_id = midcom_core_context::get()->id;
301
302 7
        if (empty($this->_toolbars[$context_id]) || !$this->add_head_elements(true)) {
303
            return;
304
        }
305
306 7
        $enable_drag = false;
307 7
        $toolbar_style = "";
308 7
        $toolbar_class = "midcom_services_toolbars_simple";
309
310 7
        if (midcom::get()->auth->can_user_do('midcom:ajax', class: __CLASS__)) {
311 7
            $enable_drag = true;
312 7
            $toolbar_class = "midcom_services_toolbars_fancy";
313 7
            $toolbar_style = "display: none;";
314
        }
315
316 7
        echo "<div class=\"{$toolbar_class}\" style=\"{$toolbar_style}\">\n";
317 7
        echo "    <div class=\"minimizer\">\n";
318 7
        echo "    </div>\n";
319 7
        echo "    <div class=\"items\">\n";
320
321 7
        foreach (array_reverse($this->_toolbars[$context_id], true) as $identifier => $toolbar) {
322 7
            $toolbar ??= $this->_get_toolbar($identifier);
323 7
            if (!$toolbar->is_rendered()) {
324 7
                $this->show_toolbar($identifier, $toolbar);
325
            }
326
        }
327 7
        echo "</div>\n";
328
329 7
        if ($enable_drag) {
330 7
            echo "     <div class=\"dragbar\"></div>\n";
331
        }
332 7
        echo "</div>\n";
333 7
        echo '<script type="text/javascript">';
334 7
        echo "jQuery('body div.midcom_services_toolbars_fancy').midcom_services_toolbar();";
335 7
        echo '</script>';
336
    }
337
338 7
    private function show_toolbar($identifier, midcom_helper_toolbar $toolbar)
339
    {
340 7
        if (empty($toolbar->items)) {
341
            return;
342
        }
343
        switch ($identifier) {
344
            case MIDCOM_TOOLBAR_VIEW:
345
                $id = $class = 'page';
346
                break;
347
            case MIDCOM_TOOLBAR_NODE:
348 7
                $id = $class = 'folder';
349 7
                break;
350
            case MIDCOM_TOOLBAR_HOST:
351 7
                $id = $class = 'host';
352 7
                break;
353
            case MIDCOM_TOOLBAR_HELP:
354 7
                $id = $class = 'help';
355 7
                break;
356
            default:
357
                $id = 'custom-' . $identifier;
358
                $class = 'custom';
359
                break;
360
        }
361 7
        echo "        <div id=\"midcom_services_toolbars_topic-{$id}\" class=\"item\">\n";
362 7
        echo "            <span class=\"midcom_services_toolbars_topic_title {$class}\">" . $toolbar->get_label() . "</span>\n";
363 7
        echo $toolbar->render();
364 7
        echo "        </div>\n";
365
    }
366
}
367