You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
4.3 KiB
PHP
139 lines
4.3 KiB
PHP
<?php
|
|
namespace Isekai;
|
|
|
|
use Html;
|
|
|
|
class IsekaiChart {
|
|
/**
|
|
* @param \Parser &$parser
|
|
*/
|
|
public static function onParserSetup(&$parser) {
|
|
$parser->setHook('isekaichart', self::class . '::create');
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param string $input
|
|
* @param string[] $args
|
|
* @param \Parser $parser
|
|
* @param \PPFrame $frame
|
|
*/
|
|
public static function create($input, $args, $parser, $frame) {
|
|
if (isset($args['type'])) {
|
|
switch ($args['type']) {
|
|
case 'radar':
|
|
return self::createRadar($input, $args, $parser, $frame);
|
|
break;
|
|
}
|
|
return '<span class="error">' . wfMessage("isekai-chart-unknow-type", $args['type'])->parse() . '</span>';
|
|
}
|
|
return '<span class="error">' . wfMessage("isekai-chart-undefined-type")->parse() . '</span>';
|
|
}
|
|
|
|
public static function parseArgs(&$args, $defaultArgs = []) {
|
|
$newArgs = array_merge([
|
|
'legend' => true,
|
|
'width' => 350,
|
|
'height' => 300,
|
|
], $defaultArgs);
|
|
$argsType = [
|
|
'width' => 'int',
|
|
'height' => 'int',
|
|
];
|
|
foreach ($args as $key => $arg) {
|
|
if (isset($argsType[$key])) {
|
|
switch ($argsType[$key]) {
|
|
case 'int':
|
|
$arg = intval($arg);
|
|
break;
|
|
case 'float':
|
|
$arg = floatval($arg);
|
|
break;
|
|
}
|
|
}
|
|
$newArgs[$key] = $arg;
|
|
}
|
|
return $newArgs;
|
|
}
|
|
|
|
/**
|
|
* @param string $input
|
|
* @param string[] $args
|
|
* @param \Parser $parser
|
|
* @param \PPFrame $frame
|
|
*/
|
|
public static function createRadar(&$input, &$inputArgs, &$parser, &$frame) {
|
|
$parser->getOutput()->addModules("ext.isekai.chart"); // 添加样式和脚本
|
|
|
|
$allowedArgs = ['width', 'height', 'shape'];
|
|
$args = self::parseArgs($inputArgs, [
|
|
'shape' => 'polygon'
|
|
]);
|
|
$legend = $args['legend'];
|
|
|
|
$lines = explode("\n", $input);
|
|
$csvData = [];
|
|
foreach ($lines as $line) {
|
|
if (!empty(trim($line))) {
|
|
$csvData[] = str_getcsv($line);
|
|
}
|
|
}
|
|
|
|
$names = [];
|
|
$values = [];
|
|
if (count($csvData) > 1) {
|
|
if (count($csvData[0]) > 1 && $csvData[0][0] === "") { // 标题行
|
|
$names = array_slice($csvData[0], 1);
|
|
array_splice($csvData, 0, 1);
|
|
} else { // 不存在标题行
|
|
$legend = false;
|
|
$valueLen = count($csvData[0]);
|
|
for ($i = 0; $i < $valueLen; $i ++) { // 创建默认标题
|
|
$names[] = wfMessage('isekai-chart-default-row-name', $i + 1)->text();
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach ($csvData as $csvLine) {
|
|
$valueLine = [];
|
|
foreach ($csvLine as $pos => $csvCol) {
|
|
if ($pos === 0) {
|
|
$valueLine[$pos] = $csvCol;
|
|
} else {
|
|
$valueLine[$pos] = floatval($csvCol);
|
|
}
|
|
}
|
|
$values[] = $valueLine;
|
|
}
|
|
|
|
$nameJson = json_encode($names, JSON_UNESCAPED_UNICODE);
|
|
$valueJson = json_encode($values, JSON_UNESCAPED_UNICODE);
|
|
if (!$valueJson) {
|
|
return '<span class="error">' . wfMessage("isekai-chart-transform-error", "Cannot encode json")->parse() . '</span>';
|
|
}
|
|
|
|
$attr = [];
|
|
foreach ($args as $key => $val) {
|
|
if (in_array($key, $allowedArgs)) {
|
|
$attr['data-' . $key] = $val;
|
|
}
|
|
}
|
|
|
|
$attr = array_merge($attr, [
|
|
'class' => 'isekai-chart',
|
|
'style' => "width: {$args['width']}px; height: {$args['height']}px; display: inline-block",
|
|
'data-name' => $nameJson,
|
|
'data-value' => $valueJson,
|
|
'data-legend' => $legend ? 'on' : 'off',
|
|
]);
|
|
|
|
ksort($attr);
|
|
$chartId = md5(serialize($attr));
|
|
|
|
$attr['data-chart-id'] = $chartId;
|
|
|
|
$html = Html::openElement('div', $attr);
|
|
$html .= Html::closeElement('div');
|
|
return $html;
|
|
}
|
|
} |