Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * Dash block class.
19
 *
20
 * @package    block_dash
21
 * @copyright  2019 bdecent gmbh <https://bdecent.de>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
use block_dash\local\block_builder;
26
use block_dash\local\data_source\data_source_factory;
27
 
28
defined('MOODLE_INTERNAL') || die();
29
 
30
require_once("$CFG->dirroot/blocks/dash/lib.php");
31
require_once("$CFG->libdir/filelib.php");
32
 
33
/**
34
 * Dash block class.
35
 */
36
class block_dash extends block_base {
37
 
38
    /**
39
     * Initialize block instance.
40
     *
41
     * @throws coding_exception
42
     */
43
    public function init() {
44
        $this->title = get_string('pluginname', 'block_dash');
45
    }
46
 
47
    /**
48
     * This block supports configuration fields.
49
     *
50
     * @return bool
51
     */
52
    public function has_config() {
53
        return true;
54
    }
55
 
56
    /**
57
     * This function is called on your subclass right after an instance is loaded
58
     * Use this function to act on instance data just after it's loaded and before anything else is done
59
     * For instance: if your block will have different title's depending on location (site, course, blog, etc)
60
     *
61
     * @throws coding_exception
62
     */
63
    public function specialization() {
64
        global $OUTPUT;
65
 
66
        if (isset($this->config->title)) {
67
            $this->title = $this->title = format_string($this->config->title, true, ['context' => $this->context]);
68
        } else {
69
            $this->title = get_string('newblock', 'block_dash');
70
        }
71
 
72
        try {
73
            $bb = block_builder::create($this);
74
            if ($bb->is_collapsible_content_addon()) {
75
                $addclass = "collapsible-block dash-block-collapse-icon";
76
                if (!$bb->is_section_expand_content_addon()) {
77
                    $addclass .= " collapsed";
78
                }
79
                $attr = [
80
                    'data-toggle' => 'collapse',
81
                    'class' => $addclass,
82
                    'href' => "#dash-{$this->instance->id}",
83
                    "aria-expanded" => "false",
84
                    "aria-controls" => "dash-{$this->instance->id}",
85
                ];
86
                $this->title = html_writer::tag('span', $this->title, $attr);
87
            }
88
        } catch (\Exception $e) {
89
            // Configured datasource is missing.
90
            $this->title = get_string('newblock', 'block_dash');
91
        }
92
 
93
        $showheader = get_config('block_dash', 'showheader');
94
        if (isset($this->config->showheader)) {
95
            $showheader = $this->config->showheader;
96
        }
97
 
98
        if (!$showheader && !$this->page->user_is_editing()) {
99
            $this->title = "";
100
        }
101
    }
102
 
103
    /**
104
     * Multiple dashes can be added to a single page.
105
     *
106
     * @return bool
107
     */
108
    public function instance_allow_multiple() {
109
        return true;
110
    }
111
 
112
    /**
113
     * Serialize and store config data
114
     *
115
     * @param string $data
116
     * @param bool $nolongerused
117
     * @return void
118
     */
119
    public function instance_config_save($data, $nolongerused = false) {
120
        if (isset($data->backgroundimage)) {
121
            file_save_draft_area_files($data->backgroundimage, $this->context->id, 'block_dash', 'images',
122
                0, ['subdirs' => 0, 'maxfiles' => 1]);
123
        }
124
        if (isset($data->dash_configure_options) && isset($data->data_source_idnumber)) {
125
            $datasource = data_source_factory::build_data_source($data->data_source_idnumber,
126
                $this->context);
127
            if ($datasource) {
128
                if (method_exists($datasource, 'set_default_preferences')) {
129
                    $configpreferences = ['config_preferences' => []];
130
                    $datasource->set_default_preferences($configpreferences);
131
                    $data->preferences = $configpreferences['config_preferences'];
132
                }
133
            }
134
            unset($data->dash_configure_options);
135
        }
136
 
137
        parent::instance_config_save($data, $nolongerused);
138
    }
139
 
140
    /**
141
     * Copy any block-specific data when copying to a new block instance.
142
     *
143
     * @param int $frominstanceid the id number of the block instance to copy from
144
     * @return boolean
145
     */
146
    public function instance_copy($frominstanceid) {
147
 
148
        // Copy the block instance background image.
149
        $fromcontext = \context_block::instance($frominstanceid);
150
        $fs = get_file_storage();
151
        // Do not use draft files hacks outside of forms.
152
        $files = $fs->get_area_files($fromcontext->id, 'block_dash', 'images', 0, 'id ASC', false);
153
        foreach ($files as $file) {
154
            $filerecord = ['contextid' => $this->context->id];
155
            $fs->create_file_from_storedfile($filerecord, $file);
156
        }
157
 
158
        // Copy the datasource images and files.
159
        $bb = block_builder::create($this);
160
        $datasource = $bb->get_configuration()->get_data_source();
161
        if (!empty($datasource) && method_exists($datasource, 'instance_copy')) {
162
            $datasource->instance_copy($frominstanceid, $this->context->id);
163
        }
164
 
165
        return true;
166
    }
167
 
168
    /**
169
     * Dashes are suitable on all page types.
170
     *
171
     * @return array
172
     */
173
    public function applicable_formats() {
174
        return ['all' => true];
175
    }
176
 
177
    /**
178
     * Return block content. Build dash.
179
     *
180
     * @return \stdClass
181
     */
182
    public function get_content() {
183
        global $OUTPUT;
184
 
185
        // Prevent the jqueryui conflict with bootstrap tooltip.
186
        if (class_exists('\core\navigation\views\secondary')) {
187
            $this->page->requires->js_init_code(
188
                'require(["jquery", "jqueryui"], function($, ui) {
189
                    $.widget.bridge("uibutton", $.ui.button);
190
                    $.widget.bridge("uitooltip", $.ui.tooltip);
191
                });'
192
            );
193
        }
194
 
195
        if ($this->content !== null) {
196
            return $this->content;
197
        }
198
 
199
        if (empty($this->instance)) {
200
            return '';
201
        }
202
 
203
        $this->content = new \stdClass();
204
 
205
        if (block_dash_is_disabled()) {
206
            $this->content->text = is_siteadmin() ? get_string('disableallmessage', 'block_dash') : '';
207
            return $this->content;
208
        }
209
 
210
        try {
211
            $bb = block_builder::create($this);
212
 
213
            if (!$bb->get_configuration()) {
214
                return $this->content->text = get_string('missingdatasource', 'block_dash');
215
            }
216
 
217
            $datasource = $bb->get_configuration()->get_data_source();
218
            // Conditionally hide the block when empty.
219
            $hidewhenempty = get_config('block_dash', 'hide_when_empty');
220
            if (isset($this->config->hide_when_empty)) {
221
                $hidewhenempty = $this->config->hide_when_empty;
222
            }
223
 
224
            if ($datasource && $hidewhenempty && (($datasource->is_widget() && $datasource->is_empty())
225
                || (!$datasource->is_widget() && $datasource->get_data()->is_empty()))
226
                && !$this->page->user_is_editing()) {
227
                return $this->content;
228
            }
229
            $this->content = $bb->get_block_content();
230
 
231
            if ($css = $this->get_extra_css()) {
232
                $this->content->text .= $css;
233
            }
234
        } catch (\Exception $e) {
235
            $this->content->text = $OUTPUT->notification($e->getMessage() . $e->getTraceAsString(), 'error');
236
        }
237
 
238
        $this->page->requires->css(new \moodle_url('/blocks/dash/styles/select2.min.css'));
239
        $this->page->requires->css(new \moodle_url('/blocks/dash/styles/datepicker.css'));
240
        $this->page->requires->css(new \moodle_url('/blocks/dash/styles/slick.css'));
241
        return $this->content;
242
    }
243
 
244
    /**
245
     * Add block width CSS classes.
246
     *
247
     * @return array
248
     */
249
    public function html_attributes() {
250
        $attributes = parent::html_attributes();
251
        if (isset($this->config->css_class)) {
252
            $cssclasses = $this->config->css_class;
253
            if (!is_array($cssclasses)) {
254
                $cssclasses = explode(',', $cssclasses);
255
            }
256
            foreach ($cssclasses as $class) {
257
                $attributes['class'] .= ' ' . trim($class);
258
            }
259
 
260
        }
261
        if (isset($this->config->width)) {
262
            $attributes['class'] .= ' dash-block-width-' . $this->config->width;
263
        } else {
264
            $attributes['class'] .= ' dash-block-width-100';
265
        }
266
 
267
        if (isset($this->config->preferences['layout'])) {
268
            $attributes['class'] .= ' ' . str_replace('\\', '-', $this->config->preferences['layout']);
269
        }
270
 
271
        try {
272
            $bb = block_builder::create($this);
273
            if ($bb->is_collapsible_content_addon()) {
274
                $attributes['class'] .= ' block-collapse-block';
275
            }
276
        } catch (\Exception $e) {
277
            $attributes['class'] .= ' missing-datasource';
278
        }
279
 
280
        return $attributes;
281
    }
282
 
283
    /**
284
     * Get extra CSS styling for this specific block.
285
     *
286
     * @return string
287
     */
288
    public function get_extra_css() {
289
        global $OUTPUT;
290
 
291
        $blockcss = [];
292
        $data = [
293
            'block' => $this,
294
            'headerfootercolor' => isset($this->config->headerfootercolor) ? $this->config->headerfootercolor : null,
295
        ];
296
 
297
        $backgroundgradient = isset($this->config->backgroundgradient)
298
            ? str_replace(';', '', $this->config->backgroundgradient) : null;
299
 
300
        if ($this->get_background_image_url()) {
301
            if ($backgroundgradient) {
302
                $blockcss[] = sprintf('background-image: %s, url(%s);',
303
                    $backgroundgradient, $this->get_background_image_url()->out()
304
                );
305
            } else {
306
                $blockcss[] = sprintf('background-image: url(%s);', $this->get_background_image_url());
307
            }
308
        } else if ($backgroundgradient) {
309
            $blockcss[] = sprintf('background-image: %s;', $this->config->backgroundgradient);
310
        }
311
 
312
        // Background postition.
313
        if (isset($this->config->backgroundimage_position)) {
314
            $bgpostion = $this->config->backgroundimage_position;
315
            $bgpostionvalue = ($bgpostion == 'custom') ? $this->config->backgroundimage_customposition : $bgpostion;
316
            $blockcss[] = sprintf('background-position: %s;', $bgpostionvalue);
317
        }
318
 
319
        // Background size.
320
        if (isset($this->config->backgroundimage_size)) {
321
            $bgsize = $this->config->backgroundimage_size;
322
            $bgsizevalue = ($bgsize == 'custom') ? $this->config->backgroundimage_customsize : $bgsize;
323
            $blockcss[] = sprintf('background-size: %s;', $bgsizevalue);
324
        }
325
 
326
        if (isset($this->config->css) && is_array($this->config->css)) {
327
            foreach ($this->config->css as $property => $value) {
328
                if (!empty($value)) {
329
                    $blockcss[] = sprintf('%s: %s;', $property, $value);
330
                }
331
            }
332
        }
333
 
334
        if (isset($this->config->border_option)) {
335
            if ($this->config->border_option) {
336
                $bordervalue = isset($this->config->border) && ($this->config->border) ? $this->config->border
337
                    : "1px solid rgba(0,0,0,.125)";
338
                $blockcss[] = sprintf('%s: %s;', 'border', $bordervalue);
339
            } else {
340
                $blockcss[] = sprintf('%s: %s;', 'border', "none");
341
            }
342
        }
343
 
344
        $data['blockcss'] = implode(PHP_EOL, $blockcss);
345
 
346
        return $OUTPUT->render_from_template('block_dash/extra_css', $data);
347
    }
348
 
349
    /**
350
     * Get background image.
351
     *
352
     * @return stored_file|null
353
     * @throws coding_exception
354
     */
355
    public function get_background_image() {
356
        $fs = get_file_storage();
357
        $backgroundimage = null;
358
        foreach ($fs->get_area_files($this->context->id, 'block_dash', 'images', 0) as $file) {
359
            if ($file->is_valid_image()) {
360
                return $file;
361
            }
362
        }
363
 
364
        return null;
365
    }
366
 
367
    /**
368
     * Get background image URL.
369
     *
370
     * @return moodle_url|null
371
     */
372
    public function get_background_image_url() {
373
        if ($backgroundimage = $this->get_background_image()) {
374
            return moodle_url::make_pluginfile_url(
375
                $backgroundimage->get_contextid(),
376
                $backgroundimage->get_component(),
377
                $backgroundimage->get_filearea(),
378
                $backgroundimage->get_itemid(),
379
                $backgroundimage->get_filepath(),
380
                $backgroundimage->get_filename()
381
            );
382
        }
383
 
384
        return null;
385
    }
386
 
387
    /**
388
     * Set dash sorting.
389
     *
390
     * @param string $fieldname
391
     * @param string|null $direction
392
     * @throws coding_exception
393
     */
394
    public function set_sort($fieldname, $direction = null) {
395
        global $USER;
396
 
397
        $key = $USER->id . '_' . $this->instance->id;
398
 
399
        $cache = \cache::make_from_params(\cache_store::MODE_SESSION, 'block_dash', 'sort');
400
 
401
        if (!$cache->has($key)) {
402
            $sorting = [];
403
        } else {
404
            $sorting = $cache->get($key);
405
        }
406
 
407
        if (isset($sorting[$fieldname]) && !$direction) {
408
            if ($sorting[$fieldname] == 'asc') {
409
                $sorting[$fieldname] = 'desc';
410
            } else {
411
                $sorting[$fieldname] = 'asc';
412
            }
413
        } else {
414
            if ($direction) {
415
                $sorting[$fieldname] = $direction;
416
            } else {
417
                $sorting[$fieldname] = 'asc';
418
            }
419
        }
420
 
421
        $cache->set($key, [$fieldname => $sorting[$fieldname]]);
422
    }
423
 
424
    /**
425
     * Include the preference option to the blocks controls before genreate the output.
426
     *
427
     * @param \core_renderer $output
428
     * @return \block_contents
429
     */
430
    public function get_content_for_output($output) {
431
 
432
        $bc = parent::get_content_for_output($output);
433
 
434
        $datasource = $this->config->data_source_idnumber ?? '';
435
 
436
        if ($datasource) {
437
            $info = \block_dash\local\data_source\data_source_factory::get_data_source_info($datasource);
438
            $type = $info['type'] ?? 'datasource';
439
 
440
            switch($type) {
441
                case 'datasource':
442
                    $hascapability = has_capability('block/dash:managedatasource', $this->context);
443
                    break;
444
                case 'widget':
445
                    $hascapability = has_capability('block/dash:managewidget', $this->context);
446
                    break;
447
                case 'custom':
448
                    $hascapability = $datasource::has_capbility($this->context);
449
                    break;
450
            }
451
 
452
        } else {
453
            $hascapability = true;
454
        }
455
 
456
        if (!isset($bc->controls) || !$hascapability) {
457
            return $bc;
458
        }
459
        // Move icon.
460
        $str = new lang_string('preferences', 'core');
461
        $icon = $output->render(new pix_icon('i/dashboard', $str, 'moodle', ['class' => 'iconsmall', 'title' => '']));
462
 
463
        $newcontrols = [];
464
        foreach ($bc->controls as $controls) {
465
            $newcontrols[] = $controls;
466
            if ($controls->text instanceof lang_string && $controls->text->get_identifier() == 'configureblock') {
467
                $newcontrols[] = html_writer::link('javascript:void(0);', $icon . $str, ['class' => 'dash-edit-preferences']);
468
            }
469
        }
470
        $bc->controls = $newcontrols;
471
        return $bc;
472
    }
473
 
474
}