2006-07-26 17:12:30 +00:00
|
|
|
<?php
|
|
|
|
/**
|
2018-04-16 06:50:28 +00:00
|
|
|
* © 2006 Daniel Kinzler
|
|
|
|
*
|
|
|
|
* This program 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 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
* http://www.gnu.org/copyleft/gpl.html
|
2006-07-26 17:12:30 +00:00
|
|
|
*
|
2010-06-06 15:12:22 +00:00
|
|
|
* @file
|
|
|
|
* @ingroup Extensions
|
2007-03-13 11:39:12 +00:00
|
|
|
* @author Daniel Kinzler, brightbyte.de
|
2006-07-26 17:12:30 +00:00
|
|
|
*/
|
|
|
|
|
2021-04-07 22:35:52 +00:00
|
|
|
namespace MediaWiki\Extension\CategoryTree;
|
|
|
|
|
2021-08-31 11:18:30 +00:00
|
|
|
use Html;
|
2021-04-07 22:35:52 +00:00
|
|
|
use HTMLForm;
|
|
|
|
use SearchEngineFactory;
|
|
|
|
use SpecialPage;
|
|
|
|
use Title;
|
|
|
|
|
2018-04-16 06:50:28 +00:00
|
|
|
/**
|
|
|
|
* Special page for the CategoryTree extension, an AJAX based gadget
|
|
|
|
* to display the category structure of a wiki
|
|
|
|
*/
|
2006-08-24 17:12:13 +00:00
|
|
|
class CategoryTreePage extends SpecialPage {
|
2022-11-10 19:49:27 +00:00
|
|
|
/** @var string */
|
2014-08-17 21:03:48 +00:00
|
|
|
public $target = '';
|
2012-11-21 08:31:37 +00:00
|
|
|
|
2021-03-12 20:34:50 +00:00
|
|
|
/** @var SearchEngineFactory */
|
|
|
|
private $searchEngineFactory;
|
|
|
|
|
2022-11-10 19:49:27 +00:00
|
|
|
/** @var CategoryTree */
|
2014-08-17 21:03:48 +00:00
|
|
|
public $tree = null;
|
2008-02-04 09:22:12 +00:00
|
|
|
|
2021-03-12 20:34:50 +00:00
|
|
|
/**
|
|
|
|
* @param SearchEngineFactory $searchEngineFactory
|
|
|
|
*/
|
|
|
|
public function __construct(
|
|
|
|
SearchEngineFactory $searchEngineFactory
|
|
|
|
) {
|
2018-04-11 03:39:03 +00:00
|
|
|
parent::__construct( 'CategoryTree' );
|
2021-03-12 20:34:50 +00:00
|
|
|
$this->searchEngineFactory = $searchEngineFactory;
|
2006-07-26 17:12:30 +00:00
|
|
|
}
|
2008-02-04 09:22:12 +00:00
|
|
|
|
2012-02-09 01:23:31 +00:00
|
|
|
/**
|
2017-10-11 18:25:13 +00:00
|
|
|
* @param string $name
|
2012-02-09 01:23:31 +00:00
|
|
|
* @return mixed
|
|
|
|
*/
|
2018-04-11 03:47:26 +00:00
|
|
|
private function getOption( $name ) {
|
2010-11-26 19:09:35 +00:00
|
|
|
if ( $this->tree ) {
|
|
|
|
return $this->tree->getOption( $name );
|
|
|
|
} else {
|
2021-03-12 19:40:10 +00:00
|
|
|
return $this->getConfig()->get( 'CategoryTreeDefaultOptions' )[$name];
|
2010-11-26 19:09:35 +00:00
|
|
|
}
|
2008-06-28 20:13:20 +00:00
|
|
|
}
|
|
|
|
|
2006-07-26 17:12:30 +00:00
|
|
|
/**
|
|
|
|
* Main execution function
|
2017-10-11 18:25:13 +00:00
|
|
|
* @param string|null $par Parameters passed to the page
|
2006-07-26 17:12:30 +00:00
|
|
|
*/
|
2018-04-11 03:47:26 +00:00
|
|
|
public function execute( $par ) {
|
2006-07-26 17:12:30 +00:00
|
|
|
$this->setHeaders();
|
2019-07-17 19:53:40 +00:00
|
|
|
$this->addHelpLink( 'Extension:CategoryTree' );
|
2012-02-09 01:23:31 +00:00
|
|
|
$request = $this->getRequest();
|
|
|
|
if ( $par ) {
|
2021-09-02 19:29:25 +00:00
|
|
|
$this->target = trim( $par );
|
2012-02-09 01:23:31 +00:00
|
|
|
} else {
|
2021-11-14 16:23:26 +00:00
|
|
|
$this->target = trim( $request->getText( 'target' ) );
|
2021-09-03 10:45:31 +00:00
|
|
|
if ( $this->target === '' ) {
|
2017-09-27 19:27:00 +00:00
|
|
|
$rootcategory = $this->msg( 'rootcategory' );
|
|
|
|
if ( $rootcategory->exists() ) {
|
|
|
|
$this->target = $rootcategory->text();
|
|
|
|
}
|
|
|
|
}
|
2012-02-09 01:23:31 +00:00
|
|
|
}
|
2008-02-04 09:22:12 +00:00
|
|
|
|
2016-10-14 16:11:52 +00:00
|
|
|
$options = [];
|
2021-03-12 19:40:10 +00:00
|
|
|
$config = $this->getConfig();
|
2008-02-04 09:22:12 +00:00
|
|
|
|
2008-06-28 20:13:20 +00:00
|
|
|
# grab all known options from the request. Normalization is done by the CategoryTree class
|
2021-03-12 19:40:10 +00:00
|
|
|
$categoryTreeDefaultOptions = $config->get( 'CategoryTreeDefaultOptions' );
|
|
|
|
$categoryTreeSpecialPageOptions = $config->get( 'CategoryTreeSpecialPageOptions' );
|
|
|
|
foreach ( $categoryTreeDefaultOptions as $option => $default ) {
|
|
|
|
if ( isset( $categoryTreeSpecialPageOptions[$option] ) ) {
|
|
|
|
$default = $categoryTreeSpecialPageOptions[$option];
|
2012-02-09 01:23:31 +00:00
|
|
|
}
|
2008-06-30 14:09:47 +00:00
|
|
|
|
2012-02-09 01:23:31 +00:00
|
|
|
$options[$option] = $request->getVal( $option, $default );
|
2008-06-28 20:13:20 +00:00
|
|
|
}
|
2008-02-04 09:22:12 +00:00
|
|
|
|
2008-06-28 20:13:20 +00:00
|
|
|
$this->tree = new CategoryTree( $options );
|
2008-02-04 09:22:12 +00:00
|
|
|
|
2021-09-01 06:58:51 +00:00
|
|
|
$this->getOutput()->addWikiMsg( 'categorytree-header' );
|
2008-02-04 09:22:12 +00:00
|
|
|
|
2008-07-01 13:36:50 +00:00
|
|
|
$this->executeInputForm();
|
2008-02-04 09:22:12 +00:00
|
|
|
|
2021-09-02 19:29:25 +00:00
|
|
|
if ( $this->target !== '' ) {
|
2021-09-01 06:58:51 +00:00
|
|
|
$this->executeCategoryTree();
|
2006-07-26 17:12:30 +00:00
|
|
|
}
|
|
|
|
}
|
2008-02-04 09:22:12 +00:00
|
|
|
|
2006-07-26 17:12:30 +00:00
|
|
|
/**
|
|
|
|
* Input form for entering a category
|
|
|
|
*/
|
2018-04-11 03:47:26 +00:00
|
|
|
private function executeInputForm() {
|
2021-11-14 16:23:26 +00:00
|
|
|
$namespaces = $this->getRequest()->getRawVal( 'namespaces' );
|
2017-05-30 18:21:54 +00:00
|
|
|
// mode may be overriden by namespaces option
|
2021-11-14 16:23:26 +00:00
|
|
|
$mode = ( $namespaces === null ? $this->getOption( 'mode' ) : CategoryTreeMode::ALL );
|
2021-09-02 08:33:30 +00:00
|
|
|
if ( $mode === CategoryTreeMode::CATEGORIES ) {
|
2016-05-18 16:05:14 +00:00
|
|
|
$modeDefault = 'categories';
|
2021-09-02 08:33:30 +00:00
|
|
|
} elseif ( $mode === CategoryTreeMode::PAGES ) {
|
2016-05-18 16:05:14 +00:00
|
|
|
$modeDefault = 'pages';
|
|
|
|
} else {
|
|
|
|
$modeDefault = 'all';
|
|
|
|
}
|
|
|
|
|
|
|
|
$formDescriptor = [
|
|
|
|
'category' => [
|
|
|
|
'type' => 'title',
|
|
|
|
'name' => 'target',
|
|
|
|
'label-message' => 'categorytree-category',
|
|
|
|
'namespace' => NS_CATEGORY,
|
|
|
|
],
|
|
|
|
|
|
|
|
'mode' => [
|
|
|
|
'type' => 'select',
|
|
|
|
'name' => 'mode',
|
|
|
|
'label-message' => 'categorytree-mode-label',
|
|
|
|
'options-messages' => [
|
|
|
|
'categorytree-mode-categories' => 'categories',
|
|
|
|
'categorytree-mode-pages' => 'pages',
|
|
|
|
'categorytree-mode-all' => 'all',
|
|
|
|
],
|
2016-06-24 16:18:39 +00:00
|
|
|
'default' => $modeDefault,
|
|
|
|
'nodata' => true,
|
2016-05-18 16:05:14 +00:00
|
|
|
],
|
|
|
|
|
|
|
|
'namespace' => [
|
|
|
|
'type' => 'namespaceselect',
|
|
|
|
'name' => 'namespaces',
|
|
|
|
'label-message' => 'namespace',
|
|
|
|
'all' => '',
|
|
|
|
],
|
|
|
|
];
|
|
|
|
|
2018-04-09 01:50:31 +00:00
|
|
|
HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
|
2016-05-18 16:05:14 +00:00
|
|
|
->setWrapperLegendMsg( 'categorytree-legend' )
|
|
|
|
->setSubmitTextMsg( 'categorytree-go' )
|
|
|
|
->setMethod( 'get' )
|
2022-03-27 04:31:39 +00:00
|
|
|
// Strip subpage
|
|
|
|
->setTitle( $this->getPageTitle() )
|
2016-05-18 16:05:14 +00:00
|
|
|
->prepareForm()
|
|
|
|
->displayForm( false );
|
2006-07-26 17:12:30 +00:00
|
|
|
}
|
2015-05-16 11:20:47 +00:00
|
|
|
|
2021-09-01 06:58:51 +00:00
|
|
|
/**
|
|
|
|
* Show the category tree
|
|
|
|
*/
|
|
|
|
private function executeCategoryTree() {
|
|
|
|
$output = $this->getOutput();
|
|
|
|
CategoryTree::setHeaders( $output );
|
|
|
|
|
|
|
|
$title = CategoryTree::makeTitle( $this->target );
|
|
|
|
if ( !$title || !$title->getArticleID() ) {
|
|
|
|
$output->addHTML( Html::rawElement( 'div', [ 'class' => 'CategoryTreeNotice' ],
|
|
|
|
$this->msg( 'categorytree-not-found' )
|
|
|
|
->plaintextParams( $this->target )
|
|
|
|
->parse()
|
|
|
|
) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$parents = $this->tree->renderParents( $title );
|
2021-09-02 08:33:30 +00:00
|
|
|
if ( $parents === '' ) {
|
2021-09-01 06:58:51 +00:00
|
|
|
$parents = $this->msg( 'categorytree-no-parent-categories' )->parse();
|
|
|
|
}
|
|
|
|
|
|
|
|
$output->addHTML( Html::rawElement( 'div', [ 'class' => 'CategoryTreeParents' ],
|
|
|
|
$this->msg( 'categorytree-parents' )->parse() .
|
|
|
|
$this->msg( 'colon-separator' )->escaped() .
|
|
|
|
$parents
|
|
|
|
) );
|
|
|
|
|
|
|
|
$output->addHTML( Html::rawElement( 'div',
|
|
|
|
[
|
|
|
|
'class' => 'CategoryTreeResult CategoryTreeTag',
|
|
|
|
'data-ct-mode' => $this->tree->getOption( 'mode' ),
|
|
|
|
'data-ct-options' => $this->tree->getOptionsAsJsStructure(),
|
|
|
|
],
|
|
|
|
$this->tree->renderNode( $title, 1 )
|
|
|
|
) );
|
|
|
|
}
|
|
|
|
|
2015-12-28 22:03:36 +00:00
|
|
|
/**
|
|
|
|
* Return an array of subpages beginning with $search that this special page will accept.
|
|
|
|
*
|
|
|
|
* @param string $search Prefix to search for
|
|
|
|
* @param int $limit Maximum number of results to return (usually 10)
|
|
|
|
* @param int $offset Number of results to skip (usually 0)
|
|
|
|
* @return string[] Matching subpages
|
|
|
|
*/
|
|
|
|
public function prefixSearchSubpages( $search, $limit, $offset ) {
|
|
|
|
$title = Title::newFromText( $search, NS_CATEGORY );
|
2021-09-02 09:35:57 +00:00
|
|
|
if ( $title && !$title->inNamespace( NS_CATEGORY ) ) {
|
2015-12-28 22:03:36 +00:00
|
|
|
// Someone searching for something like "Wikipedia:Foo"
|
|
|
|
$title = Title::makeTitleSafe( NS_CATEGORY, $search );
|
|
|
|
}
|
|
|
|
if ( !$title ) {
|
|
|
|
// No prefix suggestion outside of category namespace
|
2016-10-14 16:11:52 +00:00
|
|
|
return [];
|
2015-12-28 22:03:36 +00:00
|
|
|
}
|
2021-03-12 20:34:50 +00:00
|
|
|
$searchEngine = $this->searchEngineFactory->create();
|
2019-03-27 20:34:28 +00:00
|
|
|
$searchEngine->setLimitOffset( $limit, $offset );
|
2015-12-28 22:03:36 +00:00
|
|
|
// Autocomplete subpage the same as a normal search, but just for categories
|
2019-03-27 20:34:28 +00:00
|
|
|
$searchEngine->setNamespaces( [ NS_CATEGORY ] );
|
|
|
|
$result = $searchEngine->defaultPrefixSearch( $search );
|
2015-12-28 22:03:36 +00:00
|
|
|
|
2021-05-03 06:57:15 +00:00
|
|
|
return array_map( static function ( Title $t ) {
|
2015-12-28 22:03:36 +00:00
|
|
|
// Remove namespace in search suggestion
|
|
|
|
return $t->getText();
|
|
|
|
}, $result );
|
|
|
|
}
|
|
|
|
|
2019-02-05 14:57:56 +00:00
|
|
|
/**
|
|
|
|
* @inheritDoc
|
|
|
|
*/
|
2015-05-16 11:20:47 +00:00
|
|
|
protected function getGroupName() {
|
|
|
|
return 'pages';
|
|
|
|
}
|
|
|
|
|
2006-07-26 17:12:30 +00:00
|
|
|
}
|