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.
147 lines
5.3 KiB
PHP
147 lines
5.3 KiB
PHP
<?php
|
|
namespace Isekai\Widgets;
|
|
|
|
use ApiMain;
|
|
use Exception;
|
|
use MediaWiki\Request\FauxRequest;
|
|
use MediaWiki\Title\Title;
|
|
use MediaWiki\Html\Html;
|
|
use MediaWiki\Parser\Parser;
|
|
use PPFrame;
|
|
|
|
class PreviewPageListWidget {
|
|
public const CONTAINER_CLASS_NAME = 'isekai-card isekai-preview-page-list-card';
|
|
|
|
/**
|
|
* Build fallback list for browsers that don't support JS and for SEO
|
|
* @param string[] $pageList
|
|
* @return string
|
|
*/
|
|
public static function buildFallbackPageList($pageList) {
|
|
$pageListHtml = [];
|
|
foreach ($pageList as $pageTitle) {
|
|
$title = Title::newFromText($pageTitle);
|
|
if ($title) {
|
|
$pageListHtml[] = Html::rawElement('a', ['class' => 'isekai-list-item', 'href' => $title->getLocalURL()],
|
|
Html::rawElement('div', ['class' => 'isekai-list-item-content'],
|
|
Html::element('div', ['class' => 'isekai-list-item-title'], $title->getPrefixedText())
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
return
|
|
Html::openElement('div', [
|
|
'class' => 'fallback-page-list'
|
|
]) . Html::openElement('ul', [
|
|
'class' => 'isekai-list'
|
|
]) .
|
|
implode("\n", $pageListHtml) .
|
|
Html::closeElement('ul') .
|
|
Html::closeElement('div');
|
|
}
|
|
|
|
public static function create($text, $params, Parser $parser, PPFrame $frame) {
|
|
$parser->getOutput()->addModules(['ext.isekai.previewPageList']);
|
|
|
|
$loader = $params['loader'] ?? 'unknown';
|
|
if ($loader === 'unknown' && !empty(trim($text))) {
|
|
$loader = 'pages';
|
|
}
|
|
|
|
$autoFocus = $params['autofocus'] ?? false;
|
|
if ($autoFocus === 'false' || $autoFocus === '0') {
|
|
$autoFocus = false;
|
|
} else {
|
|
$autoFocus = true;
|
|
}
|
|
|
|
$lazyLoad = $params['lazyload'] ?? false;
|
|
if ($lazyLoad === 'false' || $lazyLoad === '0') {
|
|
$lazyLoad = false;
|
|
} else {
|
|
$lazyLoad = true;
|
|
}
|
|
|
|
$resultHtml = null;
|
|
switch ($loader) {
|
|
case 'pages':
|
|
$pageList = explode("\n", trim($text));
|
|
$pageList = array_map(function ($page) {
|
|
return trim($page);
|
|
}, $pageList);
|
|
|
|
$resultHtml = Html::openElement('div', [
|
|
'class' => self::CONTAINER_CLASS_NAME,
|
|
'data-loader' => $loader,
|
|
'data-autofocus' => $autoFocus,
|
|
'data-lazyload' => $lazyLoad,
|
|
]) .
|
|
Html::openElement('script', [
|
|
'type' => 'application/json',
|
|
'data-pages' => true,
|
|
]) .
|
|
json_encode($pageList) .
|
|
Html::closeElement('script') .
|
|
self::buildFallbackPageList($pageList) .
|
|
Html::closeElement('div');
|
|
break;
|
|
case 'category':
|
|
$category = $params['category'] ?? null;
|
|
if (!$category) {
|
|
return Html::element('span', [
|
|
'class' => 'error'
|
|
], wfMessage('isekai-preview-page-list-error-invalid-category')->parse());
|
|
}
|
|
|
|
$categoryTitle = Title::newFromText($category, NS_CATEGORY);
|
|
$categoryTitleText = $categoryTitle->getPrefixedText();
|
|
|
|
$pageList = [];
|
|
|
|
$request = [
|
|
'action' => 'query',
|
|
'list' => 'categorymembers',
|
|
'cmtitle' => $categoryTitleText,
|
|
'cmtype' => 'page',
|
|
'cmnamespace' => 0,
|
|
'cmlimit' => 100,
|
|
'cmsort' => 'sortkey',
|
|
];
|
|
|
|
$api = new ApiMain(new FauxRequest($request));
|
|
try {
|
|
$api->execute();
|
|
$categoryMembers = $api->getResult()->getResultData(['query', 'categorymembers']);
|
|
foreach ($categoryMembers as $categoryMember) {
|
|
if (is_array($categoryMember) && isset($categoryMember['title'])) {
|
|
$pageList[] = $categoryMember['title'];
|
|
}
|
|
}
|
|
} catch (Exception $e) {
|
|
wfDebugLog('exception', $e->getMessage(), 'all', [
|
|
'exception' => $e
|
|
]);
|
|
}
|
|
|
|
$resultHtml = Html::openElement('div', [
|
|
'class' => self::CONTAINER_CLASS_NAME,
|
|
'data-loader' => $loader,
|
|
'data-category' => $categoryTitleText,
|
|
'data-autofocus' => $autoFocus,
|
|
'data-lazyload' => $lazyLoad,
|
|
]) .
|
|
self::buildFallbackPageList($pageList) .
|
|
Html::closeElement('div');
|
|
break;
|
|
}
|
|
|
|
if (!$resultHtml) {
|
|
$resultHtml = Html::element('span', [
|
|
'class' => 'error'
|
|
], wfMessage('isekai-preview-page-list-error-invalid-loader', $loader)->parse());
|
|
}
|
|
|
|
return $resultHtml;
|
|
}
|
|
} |