Extension:AllBooks

From MediaWiki.org
Jump to: navigation, search
MediaWiki extensions manual
Crystal Clear action run.png
AllBooks

Release status: beta

Implementation Special page, Variable
Description Allows listing of all books in a Wikibooks wiki, and creates the {{NUMBEROFBOOKS}} variable.
Author(s) Ramac, Pietrodn (Ramactalk)
Latest version 1.9 (2008-04-14)
MediaWiki 1.11
Database changes No
License No license specified
Download see the code section
Hooks used
LanguageGetSpecialPageAliases

LanguageGetMagic
ParserGetVariableValueSwitch
MagicWordwgVariableIDs

Translate the AllBooks extension if it is available at translatewiki.net

Check usage and version matrix; code metrics

The AllBooks extension will list all books in a Wikibooks wiki when using two of the most common naming schemes: Book/Chapter and Book:Chapter.

  • Currently books with a subtitle like Book: Subtitle are not detected as a book (they are considered not to be a top-level page because there is a colon in the title); they should be "registered" with this extension by providing a soft redirect from Book to Book: Subtitle so that the book will be listed and counted properly. The All pages links on Special:AllBooks links to Special:PrefixIndex/Book, so the book subpages will not be listed there. Users will have to click the link at the soft redirect to get to your book. Perhaps using that naming convention isn't the best thing to do anyways, as it makes very long pagenames.
    This behaviour may change in the future to accommodate additional naming schemes in use on the various language editions of Wikibooks, or to better accommodate the two mentioned above.

Usage[edit | edit source]

  • "Special:AllBooks" lists all books, and links to the appropriate PrefixIndex.
    Allows you to list books starting at some point in the alphabet using ?offset=
  • {{NUMBEROFBOOKS}} is the number of books on the wiki.

Installation[edit | edit source]

  • Copy the code into files and extract the file(s) in a directory called AllBooks in your extensions/ folder.
  • Add the following code at the bottom of your LocalSettings.php:
require_once "$IP/extensions/AllBooks/AllBooks.php";
require_once "$IP/extensions/AllBooks/NumberOfBooks.php";
  • Done! Navigate to "Special:Version" on your wiki to verify that the extension is successfully installed.

Code[edit | edit source]

AllBooks.php[edit | edit source]

  • This code goes in the file $IP/extensions/AllBooks/AllBooks.php
<?php
# Alert the user that this is not a valid entry point to MediaWiki if they try to access the skin file directly.
if( !defined( "MEDIAWIKI" ) ) {
  echo "This file is a MediaWiki extension and should not be used directly.";
  die( 1 );
}
 
$dir = dirname(__FILE__) . '/';
 
$wgAutoloadClasses['AllBooks'] = $dir . 'AllBooks_body.php'; # Tell MediaWiki to load the extension body.
$wgExtensionMessagesFiles['AllBooks'] = $dir . 'AllBooks.i18n.php';
$wgSpecialPages['AllBooks'] = 'AllBooks'; # Let MediaWiki know about the new special page.
$wgHooks['LanguageGetSpecialPageAliases'][] = 'AllBooksLocalizedPageName'; # Add any aliases for the special page.

$wgExtensionCredits['specialpage'][] = array(
	'name' => 'All Books',
	'version' => 1.9,
	'author' => array('Ramac', 'Pietrodn'),
	'url' => 'http://www.mediawiki.org/wiki/Extension:AllBooks',
	'description' => 'List all books in the wiki',
);
 
function AllBooksLocalizedPageName(&$specialPageArray, $code) {
  # The localized title of the special page is among the messages of the extension:
  wfLoadExtensionMessages('AllBooks');
  $text = wfMsg('allbooks-url');
 
  # Convert from title in text form to DBKey and put it into the alias array:
  $title = Title::newFromText($text);
  $specialPageArray['AllBooks'][] = $title->getDBKey();
 
  return true;
 
  }

AllBooks_body.php[edit | edit source]

  • This code goes in the file $IP/extensions/AllBooks/AllBooks_body.php
<?php
class AllBooks extends SpecialPage {
 
  function AllBooks() {
    SpecialPage::SpecialPage("AllBooks");
    wfLoadExtensionMessages('AllBooks');
  }
 
  function execute( $par ) {
    global $wgRequest, $wgOut, $wgContLang;
 
    $this->setHeaders();
    $namespaces = $wgContLang->getNamespaces();
 
    #create the pager
    $pager = new AllBooksPager();
 
    #get some request data
    $off = ucfirst($wgRequest->getText('offset'));
    $namespace = $wgRequest->getInt('namespace');
    if (is_null($namespace)) $namespace = NS_MAIN;
 
    $wgOut->setPagetitle(wfMsg( 'allbooks' ));		
 
    #string for the selection form
    $modulo = '
    <form action="'.$this->getTitle()->getLocalURL().'" method="get">
	<fieldset><legend>'.wfMsg( 'allbooks' ).'</legend>
	<table>
      <tr><td class="mw-label">' . 
	  Xml::label(wfMsg('allbooks-startfrom'), "allbooks-offset") . 
	  '</td><td>'.
	  Xml::input("offset", false, htmlspecialchars($off), array("id" => "allbooks-offset")) .
      ( count( $this->getNamespaces( wfMsg('allbooksnamespaces') ) ) > 1 ? '</td></tr>
	  <tr><td class="mw-label">' .
	  Xml::label(wfMsg('namespace'), "namespace") .
	  '</td><td>' .
	  $this->getCheckboxes($this->getNamespaces( wfMsg('allbooksnamespaces') ) ) : '').
	  Xml::submitButton(wfMsg('allbooks-go')) .
      '</td></tr>
    </table></fieldset></form><hr/>
    ';
 
    #output
    $wgOut->addHTML(
      wfMsgExt( 'allbookspagetext', array( 'parse' ) ) . $modulo .
      $pager->getNavigationBar() .
      $pager->getBody() .
      $pager->getNavigationBar()
    );
 
  }
 
  function transform( $text ) {
	return trim( $text, ' *' );
  }
 
  function isUsable( $text ) {
	return substr( $text, 0, 1 ) == '*';
  }
 
  function getNamespaces($input) {
	global $wgContLang, $wgRequest;
	$lines = explode( "\n", $input );
	$ns = array();
    foreach( $lines as $line ) {
		$line = trim( $line );
		#check if line is usable and if namespace exists
		if( AllBooks::isUsable( $line ) ) {
			$line = AllBooks::transform($line);
			if ($line == 'main') { $line = wfMsg( 'blanknamespace');} #default
			$nsId = $wgContLang->getLocalNsIndex($line);
			$ns[$nsId] = $line;
		}
	}
	return $ns;
  }
 
  function getCheckboxes ($ns) {
	global $wgRequest;
	$fields = '';
	$allfalse = true;
  	foreach($ns as $nsId => $line)
		$allfalse = $allfalse && !( $wgRequest->getCheck( 'ns' . $nsId ) );
	foreach($ns as $nsId => $line) {
  			$fields .= Xml::openElement('span', array('style' => 'white-space: nowrap;')) .
						Xml::checkLabel($line, "ns$nsId", "ns".$line, $wgRequest->getCheck( 'ns' . $nsId) || $allfalse) .
						Xml::closeElement('span')." \n";
	}
	return $fields;
  }
 
  function getNsOK ($ns) {
	global $wgRequest;
	$r = array();
	$allfalse = true;
  	foreach($ns as $nsId => $line)
		$allfalse = $allfalse && !( $wgRequest->getCheck( 'ns' . $nsId ) );
 
	foreach($ns as $nsId => $line) {
		if  ( $wgRequest->getCheck( 'ns' . $nsId) || $allfalse ) 
			$r[$nsId] = $line;
	} 
 
	return $r;
  }
 
}
 
class AllBooksPager extends AlphabeticPager {
  #return the information for querying the database
  function getQueryInfo() {
    global $wgRequest;
 
    #get request data
	$allb_ns = AllBooks::getNsOK(AllBooks::getNamespaces(wfMsg('allbooksnamespaces')));
	$allb_ns = array_keys($allb_ns);
 
    return array(
      'tables' => 'page',
      'fields' => array("page_title","page_namespace"),
      'conds' => array("page_is_redirect" => 0, "page_namespace" => $allb_ns, "page_title NOT REGEXP '".wfMsg('allbooks-regex')."'")
      );
  }
 
  function getStartBody() { return '<ol>'; }
  function getEndBody() { return '</ol>'; }
 
  function getEmptyBody() {
    return Xml::elementClean('em', null, wfMsg( 'allbooks-empty') );
  }
 
  #get the field used for indexing
  function getIndexField() { return "page_title"; }
 
  #return a row
  function formatRow( $row ) {
    global $wgContLang;
 
    #get a new title from the db key
	$title = $wgContLang->getNsText($row->page_namespace).":".$row->page_title;
    $titolo = Title::newFromDBkey($title);
 
    #link to allpages
    $allp = Title::newFromText($wgContLang->specialPage("Prefixindex"));
    $allp = $allp->getFullURL("from=".$titolo->getPartialURL()."&namespace=".$row->page_namespace);
 
    #get a list item
	$link = Xml::elementClean('a', array('href' => $titolo->getFullURL()), $titolo->getPrefixedText());
	$allp_l = Xml::elementClean('a', array('href' => $allp), wfMsg('allbooks-allp'));
	$s = "<li>$link <small>($allp_l)</small></li>";
    return  $s;
  }
 
}

AllBooks.i18n.php[edit | edit source]

  • This code goes in the file $IP/extensions/AllBooks/AllBooks.i18n.php
<?php
$messages = array();
/* English */
$messages['en'] = array( 
	'allbooks-url' => 'AllBooks',
	'allbooks' => 'All books',
	'allbooks-allp' => 'All pages',
	'allbookspagetext' => 'This page lists all books in this wiki (all pages with no "/" or ":" in the title)',
	'allbooks-startfrom' => 'Display pages starting from:',
	'allbooks-go' => 'Go',
	'allbooks-empty' => 'No books',
	'allbooksinnamespace' => 'All books in namespace $1',
	'allbooksnamespaces' => "* main",
	'allbooks-regex' => '(/|:[[:alnum:]])'
);
/* Finnish (Jack Phoenix) */
$messages['fi'] = array( 
	'allbooks-url' => 'KaikkiKirjat',
	'allbooks' => 'Kaikki kirjat',
	'allbooks-allp' => 'Kaikki sivut',
	'allbookspagetext' => 'Tämä sivu listaa kaikki kirjat tässä wikissä (kaikki sivut, joiden nimessä ei ole "/" tai ":")',
	'allbooks-startfrom' => 'Näytä sivut alkaen:',
	'allbooks-go' => 'Siirry',
	'allbooks-empty' => 'Ei kirjoja',
	'allbooksinnamespace' => 'Kaikki kirjat nimiavaruudessa $1',
	'allbooksnamespaces' => "* pää",
);
/* French */
$messages['fr'] = array(
	'allbooks-url' => 'ToutesLivres',
	'allbooks' => 'Toutes Livres',
	'allbooks-allp' =>  'Toutes Pages',
	'allbookspagetext' => 'Cette page liste toutes les livres dans cette wiki (toutes pages sans "/" ou ":" dans le titre',
	'allbooks-startfrom' => 'Afficher les pages commençant par le préfixe: ',
	'allbooks-go' => 'Valider'
);
/* Italian */
$messages['it'] = array(
	'allbooks-url' => 'TuttiILibri',
	'allbooks' => 'Tutti i libri',
	'allbooks-allp' => 'Tutte le pagine',
	'allbookspagetext' => 'Questa pagina elenca tutti i libri di questa wiki (tutte le pagine senza "/" o ":" nel titolo)',
	'allbooks-startfrom' => 'Mostra le pagine che iniziano con:',
	'allbooks-empty' => 'Non è possibile trovare alcun libro',
	'allbooksinnamespace' => 'Tutti i libri nel namespace $1',
	'allbooks-go' => 'Vai'
);
/* Portuguese */
$messages['pt'] = array( 
	'allbooks-url' => 'TodosOsLivros',
	'allbooks' => 'Todos os livros',
	'allbooks-allp' => 'Todas as páginas',
	'allbookspagetext' => 'Esta página lista todos os livros desta wiki (todas as páginas cujo título não possui "/" nem ":")',
	'allbooks-startfrom' => 'Exibir páginas a partir de:',
	'allbooks-go' => 'Ir',
	'allbooks-empty' => 'Sem livros',
	'allbooksinnamespace' => 'Todos os livros no domínio $1',
	'allbooksnamespaces' => "* principal"
);

NumberOfBooks.php[edit | edit source]

  • This code goes in the file $IP/extensions/AllBooks/NumberOfBooks.php
<?php
 
# Not a valid entry point, skip unless MediaWiki is defined
if( !defined( "MEDIAWIKI" ) ) {
  echo "This file is a MediaWiki extension and should not be used directly.";
  die( 1 );
}
 
define( "MAG_NOB", "numberofbooks");
 
$wgExtensionCredits['variable'][] = array(
  'name' => 'NumberOfBooks',
  'description' => 'Gives the number of books in Wikibooks',
  'author' => array('Pietrodn', 'Ramac'),
  'url' => 'http://www.mediawiki.org/wiki/Extension:AllBooks',
  'version' => '1.0'
);
 
$wgHooks['LanguageGetMagic'][] = 'wfNumberOfBooksDefine';
$wgHooks['ParserGetVariableValueSwitch'][] = 'wfNumberOfBooksAssign';
$wgHooks['MagicWordwgVariableIDs'][] = 'wfNumberOfBooksDeclare';
 
function wfNumberOfBooksDefine( &$aWikiWords, &$langID ) {
  $aWikiWords[ MAG_NOB ] = array( 0, "NumberOfBooks" );
  return true;
}
 
function wfNumberOfBooksAssign( &$parser, &$cache, &$magicWordId, &$ret ) {
  static book_count;
 
  if ( MAG_NOB != $magicWordId )
    return false;
  if ( is_null(book_count) ) {
    $dbr = wfGetDB( DB_SLAVE );
 
    #get request data
    $allb_ns = AllBooks::getNamespaces(wfMsg('allbooksnamespaces'));
    $allb_ns = array_keys($allb_ns);
 
    #query the db
    $conta = $dbr->select("page", "page_id", array("page_is_redirect" => "0", "page_namespace" => $allb_ns, "page_title NOT REGEXP '".wfMsg('allbooks-regex')."'"));
    $book_count = $conta->numRows();
  }
 
  $ret = $book_count;
  return true;
}
 
function wfNumberOfBooksDeclare( &$aCustomVariableIds ) {
  $aCustomVariableIds[] = MAG_NOB;
  return true;
}

See also[edit | edit source]