Proyectos de Subversion Moodle

Rev

Autoría | Ultima modificación | Ver Log |

<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Dash block class.
 *
 * @package    block_dash
 * @copyright  2019 bdecent gmbh <https://bdecent.de>
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

use block_dash\local\block_builder;
use block_dash\local\data_source\data_source_factory;

defined('MOODLE_INTERNAL') || die();

require_once("$CFG->dirroot/blocks/dash/lib.php");
require_once("$CFG->libdir/filelib.php");

/**
 * Dash block class.
 */
class block_dash extends block_base {

    /**
     * Initialize block instance.
     *
     * @throws coding_exception
     */
    public function init() {
        $this->title = get_string('pluginname', 'block_dash');
    }

    /**
     * This block supports configuration fields.
     *
     * @return bool
     */
    public function has_config() {
        return true;
    }

    /**
     * This function is called on your subclass right after an instance is loaded
     * Use this function to act on instance data just after it's loaded and before anything else is done
     * For instance: if your block will have different title's depending on location (site, course, blog, etc)
     *
     * @throws coding_exception
     */
    public function specialization() {
        global $OUTPUT;

        if (isset($this->config->title)) {
            $this->title = $this->title = format_string($this->config->title, true, ['context' => $this->context]);
        } else {
            $this->title = get_string('newblock', 'block_dash');
        }

        try {
            $bb = block_builder::create($this);
            if ($bb->is_collapsible_content_addon()) {
                $addclass = "collapsible-block dash-block-collapse-icon";
                if (!$bb->is_section_expand_content_addon()) {
                    $addclass .= " collapsed";
                }
                $attr = [
                    'data-toggle' => 'collapse',
                    'class' => $addclass,
                    'href' => "#dash-{$this->instance->id}",
                    "aria-expanded" => "false",
                    "aria-controls" => "dash-{$this->instance->id}",
                ];
                $this->title = html_writer::tag('span', $this->title, $attr);
            }
        } catch (\Exception $e) {
            // Configured datasource is missing.
            $this->title = get_string('newblock', 'block_dash');
        }

        $showheader = get_config('block_dash', 'showheader');
        if (isset($this->config->showheader)) {
            $showheader = $this->config->showheader;
        }

        if (!$showheader && !$this->page->user_is_editing()) {
            $this->title = "";
        }
    }

    /**
     * Multiple dashes can be added to a single page.
     *
     * @return bool
     */
    public function instance_allow_multiple() {
        return true;
    }

    /**
     * Serialize and store config data
     *
     * @param string $data
     * @param bool $nolongerused
     * @return void
     */
    public function instance_config_save($data, $nolongerused = false) {
        if (isset($data->backgroundimage)) {
            file_save_draft_area_files($data->backgroundimage, $this->context->id, 'block_dash', 'images',
                0, ['subdirs' => 0, 'maxfiles' => 1]);
        }
        if (isset($data->dash_configure_options) && isset($data->data_source_idnumber)) {
            $datasource = data_source_factory::build_data_source($data->data_source_idnumber,
                $this->context);
            if ($datasource) {
                if (method_exists($datasource, 'set_default_preferences')) {
                    $configpreferences = ['config_preferences' => []];
                    $datasource->set_default_preferences($configpreferences);
                    $data->preferences = $configpreferences['config_preferences'];
                }
            }
            unset($data->dash_configure_options);
        }

        parent::instance_config_save($data, $nolongerused);
    }

    /**
     * Copy any block-specific data when copying to a new block instance.
     *
     * @param int $frominstanceid the id number of the block instance to copy from
     * @return boolean
     */
    public function instance_copy($frominstanceid) {

        // Copy the block instance background image.
        $fromcontext = \context_block::instance($frominstanceid);
        $fs = get_file_storage();
        // Do not use draft files hacks outside of forms.
        $files = $fs->get_area_files($fromcontext->id, 'block_dash', 'images', 0, 'id ASC', false);
        foreach ($files as $file) {
            $filerecord = ['contextid' => $this->context->id];
            $fs->create_file_from_storedfile($filerecord, $file);
        }

        // Copy the datasource images and files.
        $bb = block_builder::create($this);
        $datasource = $bb->get_configuration()->get_data_source();
        if (!empty($datasource) && method_exists($datasource, 'instance_copy')) {
            $datasource->instance_copy($frominstanceid, $this->context->id);
        }

        return true;
    }

    /**
     * Dashes are suitable on all page types.
     *
     * @return array
     */
    public function applicable_formats() {
        return ['all' => true];
    }

    /**
     * Return block content. Build dash.
     *
     * @return \stdClass
     */
    public function get_content() {
        global $OUTPUT;

        // Prevent the jqueryui conflict with bootstrap tooltip.
        if (class_exists('\core\navigation\views\secondary')) {
            $this->page->requires->js_init_code(
                'require(["jquery", "jqueryui"], function($, ui) {
                    $.widget.bridge("uibutton", $.ui.button);
                    $.widget.bridge("uitooltip", $.ui.tooltip);
                });'
            );
        }

        if ($this->content !== null) {
            return $this->content;
        }

        if (empty($this->instance)) {
            return '';
        }

        $this->content = new \stdClass();

        if (block_dash_is_disabled()) {
            $this->content->text = is_siteadmin() ? get_string('disableallmessage', 'block_dash') : '';
            return $this->content;
        }

        try {
            $bb = block_builder::create($this);

            if (!$bb->get_configuration()) {
                return $this->content->text = get_string('missingdatasource', 'block_dash');
            }

            $datasource = $bb->get_configuration()->get_data_source();
            // Conditionally hide the block when empty.
            $hidewhenempty = get_config('block_dash', 'hide_when_empty');
            if (isset($this->config->hide_when_empty)) {
                $hidewhenempty = $this->config->hide_when_empty;
            }

            if ($datasource && $hidewhenempty && (($datasource->is_widget() && $datasource->is_empty())
                || (!$datasource->is_widget() && $datasource->get_data()->is_empty()))
                && !$this->page->user_is_editing()) {
                return $this->content;
            }
            $this->content = $bb->get_block_content();

            if ($css = $this->get_extra_css()) {
                $this->content->text .= $css;
            }
        } catch (\Exception $e) {
            $this->content->text = $OUTPUT->notification($e->getMessage() . $e->getTraceAsString(), 'error');
        }

        $this->page->requires->css(new \moodle_url('/blocks/dash/styles/select2.min.css'));
        $this->page->requires->css(new \moodle_url('/blocks/dash/styles/datepicker.css'));
        $this->page->requires->css(new \moodle_url('/blocks/dash/styles/slick.css'));
        return $this->content;
    }

    /**
     * Add block width CSS classes.
     *
     * @return array
     */
    public function html_attributes() {
        $attributes = parent::html_attributes();
        if (isset($this->config->css_class)) {
            $cssclasses = $this->config->css_class;
            if (!is_array($cssclasses)) {
                $cssclasses = explode(',', $cssclasses);
            }
            foreach ($cssclasses as $class) {
                $attributes['class'] .= ' ' . trim($class);
            }

        }
        if (isset($this->config->width)) {
            $attributes['class'] .= ' dash-block-width-' . $this->config->width;
        } else {
            $attributes['class'] .= ' dash-block-width-100';
        }

        if (isset($this->config->preferences['layout'])) {
            $attributes['class'] .= ' ' . str_replace('\\', '-', $this->config->preferences['layout']);
        }

        try {
            $bb = block_builder::create($this);
            if ($bb->is_collapsible_content_addon()) {
                $attributes['class'] .= ' block-collapse-block';
            }
        } catch (\Exception $e) {
            $attributes['class'] .= ' missing-datasource';
        }

        return $attributes;
    }

    /**
     * Get extra CSS styling for this specific block.
     *
     * @return string
     */
    public function get_extra_css() {
        global $OUTPUT;

        $blockcss = [];
        $data = [
            'block' => $this,
            'headerfootercolor' => isset($this->config->headerfootercolor) ? $this->config->headerfootercolor : null,
        ];

        $backgroundgradient = isset($this->config->backgroundgradient)
            ? str_replace(';', '', $this->config->backgroundgradient) : null;

        if ($this->get_background_image_url()) {
            if ($backgroundgradient) {
                $blockcss[] = sprintf('background-image: %s, url(%s);',
                    $backgroundgradient, $this->get_background_image_url()->out()
                );
            } else {
                $blockcss[] = sprintf('background-image: url(%s);', $this->get_background_image_url());
            }
        } else if ($backgroundgradient) {
            $blockcss[] = sprintf('background-image: %s;', $this->config->backgroundgradient);
        }

        // Background postition.
        if (isset($this->config->backgroundimage_position)) {
            $bgpostion = $this->config->backgroundimage_position;
            $bgpostionvalue = ($bgpostion == 'custom') ? $this->config->backgroundimage_customposition : $bgpostion;
            $blockcss[] = sprintf('background-position: %s;', $bgpostionvalue);
        }

        // Background size.
        if (isset($this->config->backgroundimage_size)) {
            $bgsize = $this->config->backgroundimage_size;
            $bgsizevalue = ($bgsize == 'custom') ? $this->config->backgroundimage_customsize : $bgsize;
            $blockcss[] = sprintf('background-size: %s;', $bgsizevalue);
        }

        if (isset($this->config->css) && is_array($this->config->css)) {
            foreach ($this->config->css as $property => $value) {
                if (!empty($value)) {
                    $blockcss[] = sprintf('%s: %s;', $property, $value);
                }
            }
        }

        if (isset($this->config->border_option)) {
            if ($this->config->border_option) {
                $bordervalue = isset($this->config->border) && ($this->config->border) ? $this->config->border
                    : "1px solid rgba(0,0,0,.125)";
                $blockcss[] = sprintf('%s: %s;', 'border', $bordervalue);
            } else {
                $blockcss[] = sprintf('%s: %s;', 'border', "none");
            }
        }

        $data['blockcss'] = implode(PHP_EOL, $blockcss);

        return $OUTPUT->render_from_template('block_dash/extra_css', $data);
    }

    /**
     * Get background image.
     *
     * @return stored_file|null
     * @throws coding_exception
     */
    public function get_background_image() {
        $fs = get_file_storage();
        $backgroundimage = null;
        foreach ($fs->get_area_files($this->context->id, 'block_dash', 'images', 0) as $file) {
            if ($file->is_valid_image()) {
                return $file;
            }
        }

        return null;
    }

    /**
     * Get background image URL.
     *
     * @return moodle_url|null
     */
    public function get_background_image_url() {
        if ($backgroundimage = $this->get_background_image()) {
            return moodle_url::make_pluginfile_url(
                $backgroundimage->get_contextid(),
                $backgroundimage->get_component(),
                $backgroundimage->get_filearea(),
                $backgroundimage->get_itemid(),
                $backgroundimage->get_filepath(),
                $backgroundimage->get_filename()
            );
        }

        return null;
    }

    /**
     * Set dash sorting.
     *
     * @param string $fieldname
     * @param string|null $direction
     * @throws coding_exception
     */
    public function set_sort($fieldname, $direction = null) {
        global $USER;

        $key = $USER->id . '_' . $this->instance->id;

        $cache = \cache::make_from_params(\cache_store::MODE_SESSION, 'block_dash', 'sort');

        if (!$cache->has($key)) {
            $sorting = [];
        } else {
            $sorting = $cache->get($key);
        }

        if (isset($sorting[$fieldname]) && !$direction) {
            if ($sorting[$fieldname] == 'asc') {
                $sorting[$fieldname] = 'desc';
            } else {
                $sorting[$fieldname] = 'asc';
            }
        } else {
            if ($direction) {
                $sorting[$fieldname] = $direction;
            } else {
                $sorting[$fieldname] = 'asc';
            }
        }

        $cache->set($key, [$fieldname => $sorting[$fieldname]]);
    }

    /**
     * Include the preference option to the blocks controls before genreate the output.
     *
     * @param \core_renderer $output
     * @return \block_contents
     */
    public function get_content_for_output($output) {

        $bc = parent::get_content_for_output($output);

        $datasource = $this->config->data_source_idnumber ?? '';

        if ($datasource) {
            $info = \block_dash\local\data_source\data_source_factory::get_data_source_info($datasource);
            $type = $info['type'] ?? 'datasource';

            switch($type) {
                case 'datasource':
                    $hascapability = has_capability('block/dash:managedatasource', $this->context);
                    break;
                case 'widget':
                    $hascapability = has_capability('block/dash:managewidget', $this->context);
                    break;
                case 'custom':
                    $hascapability = $datasource::has_capbility($this->context);
                    break;
            }

        } else {
            $hascapability = true;
        }

        if (!isset($bc->controls) || !$hascapability) {
            return $bc;
        }
        // Move icon.
        $str = new lang_string('preferences', 'core');
        $icon = $output->render(new pix_icon('i/dashboard', $str, 'moodle', ['class' => 'iconsmall', 'title' => '']));

        $newcontrols = [];
        foreach ($bc->controls as $controls) {
            $newcontrols[] = $controls;
            if ($controls->text instanceof lang_string && $controls->text->get_identifier() == 'configureblock') {
                $newcontrols[] = html_writer::link('javascript:void(0);', $icon . $str, ['class' => 'dash-edit-preferences']);
            }
        }
        $bc->controls = $newcontrols;
        return $bc;
    }

}