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/>.
declare(strict_types=1);
namespace core_reportbuilder\local\report;
use action_menu_link;
use lang_string;
use moodle_url;
use pix_icon;
use popup_action;
use stdClass;
/**
* Class to represent a report action
*
* @package core_reportbuilder
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class action {
/** @var moodle_url $url */
protected $url;
/** @var pix_icon $icon */
protected $icon;
/** @var array $attributes */
protected $attributes;
/** @var bool $popup */
protected $popup;
/** @var callable[] $callbacks */
protected $callbacks = [];
/** @var lang_string|string $title */
protected $title;
/**
* Create an instance of an action to be added to a report. Both the parameters of the URL, and the attributes parameter
* support placeholders which will be replaced with appropriate row values, e.g.:
*
* new action(new moodle_url('/', ['id' => ':id']), new pix_icon(...), ['data-id' => ':id'])
*
* Note that all expected placeholders should be added as base fields to the report
*
* @param moodle_url $url
* @param pix_icon $icon
* @param string[] $attributes Array of attributes to include in action, each will be cast to string prior to use
* @param bool $popup
* @param ?lang_string $title
*/
public function __construct(
moodle_url $url,
pix_icon $icon,
array $attributes = [],
bool $popup = false,
?lang_string $title = null
) {
$this->url = $url;
$this->icon = $icon;
$this->attributes = $attributes;
$this->popup = $popup;
// If title is not passed, check the title attribute from the icon.
$this->title = $title ?? $icon->attributes['title'] ?? '';
}
/**
* Adds callback to the action. Used to verify action is available to current user, or preprocess values used in placeholders
*
* Multiple callbacks can be added. If at least one returns false then the action will not be displayed
*
* @param callable $callback
* @return self
*/
public function add_callback(callable $callback): self {
$this->callbacks[] = $callback;
return $this;
}
/**
* Return action menu link suitable for output, or null if the action cannot be displayed (because one of its callbacks
* returned false, {@see add_callback})
*
* @param stdClass $row
* @return action_menu_link|null
*/
public function get_action_link(stdClass $row): ?action_menu_link {
foreach ($this->callbacks as $callback) {
$row = clone $row; // Clone so we don't modify the shared row inside a callback.
if (!$callback($row)) {
return null;
}
}
// Create a new moodle_url instance with our filled in placeholders for this row.
$url = new moodle_url(
$this->url->out_omit_querystring(true),
self::replace_placeholders($this->url->params(), $row)
);
// Ensure we have a title attribute set, if one wasn't already provided.
if (!array_key_exists('title', $this->attributes)) {
$this->attributes['title'] = (string) $this->title;
}
$this->attributes['aria-label'] = $this->attributes['title'];
if ($this->popup) {
$this->attributes['data-action'] = 'report-action-popup';
$this->attributes['data-popup-action'] = json_encode(new popup_action('click', $url));
}
// Interpolate any placeholders with correct values.
$attributes = self::replace_placeholders($this->attributes, $row);
// Ensure title attribute isn't duplicated.
$title = $attributes['title'];
unset($attributes['title']);
return new action_menu_link($url, $this->icon, $title, null, $attributes);
}
/**
* Given an array of values, replace all placeholders with corresponding property of the given row
*
* @param string[] $values
* @param stdClass $row
* @return array
*/
private static function replace_placeholders(array $values, stdClass $row): array {
return array_map(static function($value) use ($row) {
return preg_replace_callback('/^:(?<property>.*)$/', static function(array $matches) use ($row): string {
return (string) ($row->{$matches['property']} ?? '');
}, (string) $value);
}, $values);
}
}