Extension:DeletePagePermanently

From MediaWiki.org
Jump to: navigation, search
Warning Warning: This extension is incompatible with CompressOld.php scheme, and may break your wiki if you're using that form of old revision compression. Use with caution if you're using any sort of fancy stuff with the text table
MediaWiki extensions manual
Crystal Clear action run.png
DeletePagePermanently

Release status: beta

Implementation User interface
Description Delete a page permanently from the database
Author(s) Wolfgang Stöttinger, Ludovic MOUTON (LeLorraintalk)
Latest version 2.1.3 (MW1.16.x 2.1.3)
MediaWiki 1.13+, 1.16.x
License GPL
Download This page
Parameters

$wgDeletePagePermanentlyNamespaces

Added rights

deleteperm

Hooks used
SkinTemplateContentActions

SkinTemplateNavigation
UnknownAction

Translate the DeletePagePermanently extension if possible

Check usage and version matrix; code metrics

This extension can delete pages in every namespace configured without leaving any trace in the database. This extension will automatically delete talk pages and subpages, if any.

The extension DeletePagePermanently adds a new tab that allows you to delete a page permanently from the database. Although version 2.0 is safer than version 1.0 it can still harm your wiki, especially when used wrong. Test the extension carefully and backup your database as the extension is still in beta status.

Since version 2.1 it is possible to use the function from other PHP files.

Although this extension deletes the image page, the image will remain in the image folder, undeleted

Installation[edit | edit source]

The extension was designed for MediaWiki 1.13 but it should be compatible with later version as long as the database layout is the same as MediaWiki 1.13.0 for the tables.

As the Table structure of MediaWiki 1.14 is similar to 1.13 it also works here, I tested and did not figure out any problems.

Download[edit | edit source]

Please cut and paste the code found below and place it in:

$IP/extensions/DeletePagePermanently/DeletePagePermanently.php

and

$IP/extensions/DeletePagePermanently/DeletePagePermanently.i18n.php

Note: $IP stands for the root directory of your MediaWiki installation, the same directory that holds the LocalSettings.php file.

Install[edit | edit source]

To install this extension, add the following to LocalSettings.php:

require_once("$IP/extensions/DeletePagePermanently/DeletePagePermanently.php");

Configuration[edit | edit source]

User rights[edit | edit source]

You can configure the user rights in LocalSettings.php:

Defaults from DeletePagePermanently.php:

$wgGroupPermissions['*']         ['deleteperm'] = false;
$wgGroupPermissions['user']      ['deleteperm'] = false;
$wgGroupPermissions['bureaucrat']['deleteperm'] = false;
$wgGroupPermissions['sysop']     ['deleteperm'] = true;

The extension introduces a new user rights deleteperm.

Namespaces[edit | edit source]

Since version 2.0 is the possibility to configure the namespaces in which pages can be deleted. To configure this, add some lines to your LocalSettings.php:

$wgDeletePagePermanentlyNamespaces = array(
	NS_MAIN => true,
	NS_IMAGE => true,
	NS_CATEGORY => true,
	NS_TEMPLATE => true,
	NS_TALK => true,
);

Built-in namespaces are described on meta-wiki.

Code[edit | edit source]

DeletePagePermanently.php[edit | edit source]

For MediaWiki 1.16.x (or later) see below.

<?php
/**
 * DeletePagePermanently.php
 * based on Version 1.0 BETA from Ludovic MOUTON (2008)
 * Wolfgang Stöttinger 2008
 * v. 2.1.3 BETA
 * GPL
 * 
 * BE CAREFUL WHEN USING THIS EXTENSION. ONCE A PAGE IS DELETED, IT CAN NOT BE RESTORED ANY MORE.
 * Changed in Version 2.1.3:
 *		- Delete automatically the talk page 
 *		- Delete subpages and associeted talk pages (for the moment, not recursively)
 * Changed in Version 2.1.2:
 *		- Update category count
 * Changed in Version 2.1.1:
 *		- Title is removed from cache.
 * Changed in Version 2.1.0:
 *		- deletePage() can now be used from outside in PHP.
 * 
 * Features of Version 2.0:
 *		- defined $wgDeletePagePermanentlyNamespaces as an array of namespaces in which pages can be deleted.
 * 			$wgDeletePagePermanentlyNamespaces = array (
 * 				NS_MAIN => true,
 *				NS_IMAGE => true,
 * 				NS_CATEGORY => true,
 * 				NS_TEMPLATE => true,
 * 				NS_TALK => true,
 * 			);
 *		
 *		- The tab "Delete permanently" is only shown on pages that can be deleted.
 * 		- An aditional page to approve the deletion
 *		- Also log entries are deleted.
 *		- Also redirects, external links, language links, searchindex entries, page_restrictions, pagelinks, categorylinks, templatelinks, archive entries and image links are deleted.
 * 		- The watchlist entries are also removed.
 *		- If the page is an image page, all versions of the image are deleted from the database, the archive and the filesystem. (Thumbnlais won't be removed)
*/
 
if ( !defined( 'MEDIAWIKI' ) ) {
	exit( 1 ) ;
}
 
$wgExtensionCredits['other'][] = array(
    'name'    => 'DeletePagePermanently',
    'version' => '2.1',
    'author'  => 'Ludovic MOUTON, Wolfgang STÖTTINGER',
    'description' => 'Adds a new delete tab to each page. Pages are deleted permanently from the database.',
    'url'     => 'https://www.mediawiki.org/wiki/Extension:DeletePagePermanently',
);
 
# Default settings
$wgGroupPermissions['*']         ['deleteperm'] = false;
$wgGroupPermissions['user']      ['deleteperm'] = false;
$wgGroupPermissions['bureaucrat']['deleteperm'] = false;
$wgGroupPermissions['sysop']     ['deleteperm'] = true;
 
$wgExtensionMessagesFiles['DeletePagePermanently'] = dirname( __FILE__ ) . '/DeletePagePermanently.i18n.php';
 
$wgExtensionFunctions[] = 'wfDeletePagePermanently';
 
function wfDeletePagePermanently()
{
	new DeletePagePermanently();
	return true;
}
 
class DeletePagePermanently
{
	function DeletePagePermanently()
	{
		global $wgHooks, $wgMessageCache, $wgUser;
 
		wfLoadExtensionMessages( 'DeletePagePermanently' );
 
		$wgMessageCache->addMessage( 'delete_permanently', wfMsg('tab_label'));
		$wgHooks['SkinTemplateContentActions'][] = array(&$this, 'AddContentHook');
		$wgHooks['UnknownAction'][] = array(&$this, 'AddActionHook');
	}
 
	function AddContentHook( &$content_actions )
	{
		global $wgRequest, $wgRequest, $wgTitle, $wgUser, $wgDeletePagePermanentlyNamespaces;
 
		if(!$wgUser->isAllowed( 'deleteperm' ) )
			return false;
 
		$action = $wgRequest->getText( 'action' );
 
 
		#Special pages can not be deleted (special pages have no article id anyway).
		if ( $wgTitle->getArticleID() != 0 && $wgDeletePagePermanentlyNamespaces[$wgTitle->getNamespace()] == true && $wgTitle->getNamespace() != NS_SPECIAL )
		{
			wfLoadExtensionMessages( 'DeletePagePermanently' );
 
			$content_actions['ask_delete_permanently'] = array(
				'class' => $action == 'ask_delete_permanently' ? 'selected' : false,
				'text' => wfMsg( 'delete_permanently' ),
				'href' => $wgTitle->getLocalUrl( 'action=ask_delete_permanently' )
			);
		}
 
		return true;
	}
 
	function AddActionHook( $action, $wgArticle ) {
		global $wgOut, $wgUser, $wgDeletePagePermanentlyNamespaces;
 
		wfLoadExtensionMessages( 'DeletePagePermanently' );
 
		if(!$wgUser->isAllowed( 'deleteperm' ))
		{
			$wgOut->permissionRequired('deleteperm');
			return false;
		}
 
		# Print a form to approve deletion
		if ($action == 'ask_delete_permanently' )
		{
 
			$action = $wgArticle->getTitle()->escapeLocalUrl( 'action=delete_permanently' );
			$wgOut->addHTML("<form id='ask_delete_permanently' method='post' action=\"$action\">
<table>
        <tr>
                <td>" . wfMsg('ask_deletion') . "</td>
        </tr>
        <tr>
                <td><input type='submit' name='submit' value=\"" . wfMsg('yes') . "\" /></td>
        </tr>
</table></form>"); 		
			return false;
		}
		# Perform actual deletion
		elseif ($action == 'delete_permanently' )
		{
			$ns  = $wgArticle->mTitle->getNamespace();
			$t   = $wgArticle->mTitle->getDBkey();
			$id  = $wgArticle->mTitle->getArticleID();
 
			if ( $t == '' || $id == 0 || $wgDeletePagePermanentlyNamespaces[$ns] != true || $ns == NS_SPECIAL)
			{
				$wgOut->addHTML(wfMsgHtml('del_impossible')); 
				return false;
			}
 
			#delete the page and the talk page too
			$this->deletePermanently($wgArticle->mTitle);
			$this->deletePermanentlyTalkPage($wgArticle->mTitle);
 
			# delete subpages and associeted talk pages
			if($wgArticle->mTitle->hasSubpages())
			{
				$subPagesList = $wgArticle->mTitle->getSubpages();
				if($subPagesList != array())
				{
					foreach( $subPagesList as $subpage )
					{
						$this->deletePermanently($subpage);
						$this->deletePermanentlyTalkPage($subpage);
					}
				}
			}
 
			$wgOut->addHTML(wfMsgHtml('del_done'));
			return false;
		}
		//$wgOut->addHTML(wfMsgHtml('del_not_done')); 
		return true;
	}
 
	function deletePermanently($title){
		global $wgOut;
 
		$ns   = $title->getNamespace();
		$t    = $title->getDBkey();
		$id   = $title->getArticleID();
		$cats = $title->getParentCategories();
 
		$dbw = wfGetDB( DB_MASTER );
 
		$dbw->begin();
 
		####
		## First delete entries, which are in direct relation with the page:
		####
		
		# delete redirect...
		$dbw->delete( 'redirect', array( 'rd_from' => $id ), __METHOD__);
 
		# delete external link...
		$dbw->delete( 'externallinks', array( 'el_from' => $id ), __METHOD__);			
 
		# delete language link...
		$dbw->delete( 'langlinks', array( 'll_from' => $id ), __METHOD__);			
 
		# delete search index...
		$dbw->delete( 'searchindex', array( 'si_page' => $id ), __METHOD__);	
 
		# Delete restrictions for the page
		$dbw->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ );	
 
		# Delete page Links
		$dbw->delete( 'pagelinks', array ( 'pl_from' => $id ), __METHOD__ );				
 
		# delete category links
		$dbw->delete( 'categorylinks', array( 'cl_from' => $id ), __METHOD__);			
 
		# delete template links
		$dbw->delete( 'templatelinks', array( 'tl_from' => $id ), __METHOD__);									
 
		# read text entries for all revisions and delete them.
		$res = $dbw->select ('revision', 'rev_text_id', "rev_page=$id");
		while( $row = $dbw->fetchObject($res) ) 
		{
			$value = $row->rev_text_id;
			$dbw->delete('text', array('old_id'=>$value), __METHOD__);
		}
 
		# In the table 'revision' : Delete all the revision of the page where 'rev_page' = $id
		$dbw->delete('revision', array('rev_page'=>$id), __METHOD__);
 
		# delete image links
		$dbw->delete( 'imagelinks', array( 'il_from' => $id ), __METHOD__);			
 
		####
		## then delete entries which are not in direct relation with the page: 
		####
		
		# Clean up recentchanges entries...
		$dbw->delete( 'recentchanges', array( 'rc_namespace' => $ns, 'rc_title' => $t ), __METHOD__ );
 
		# read text entries for all archived pages and delete them.
		$res = $dbw->select ('archive', 'ar_text_id', array( 'ar_namespace' => $ns, 'ar_title' => $t ));
		while( $row = $dbw->fetchObject($res) ) 
		{
			$value = $row->ar_text_id;
			$dbw->delete('text', array('old_id'=>$value), __METHOD__);
		}
 
		# Clean archive entries...
		$dbw->delete( 'archive', array( 'ar_namespace' => $ns, 'ar_title' => $t ), __METHOD__ );						
 
		# Clean up log entries...
		$dbw->delete( 'logging', array( 'log_namespace' => $ns, 'log_title' => $t ), __METHOD__ );
 
		# Clean up watchlist...
		$dbw->delete( 'watchlist', array( 'wl_namespace' => $ns, 'wl_title' => $t ), __METHOD__ );			
 
		# In the table 'page' : Delete the page entry
		$dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__);	
 
		####
		## If the article belongs to a category, update category counts 
		####
		if(!empty($cats))
		{			
			foreach($cats as $parentcat => $currentarticle)
			{
				$catname = split(':', $parentcat, 2); 
				$cat = Category::newFromName($catname[1]);
				$cat->refreshCounts();
			}
		}
 
		####
		## If an image is beeing deleted, some extra work needs to be done
		####
		if ($ns == NS_IMAGE)
		{
 
			$file = wfFindFile($t);
 
			if ($file)
			{
				# Get all filenames of old versions:
				$fields = OldLocalFile::selectFields();
				$res = $dbw->select ('oldimage', $fields, array( 'oi_name' => $t ));
				while( $row = $dbw->fetchObject($res) ) 
				{
					$oldLocalFile = OldLocalFile::newFromRow($row, $file->repo);
					$path = $oldLocalFile->getArchivePath().'/'.$oldLocalFile->getArchiveName();
 
					try
					{
						# Using the FileStore to delete the file
						$transaction = FileStore::deleteFile( $path );
						$transaction->commit();
					}
					catch (Exception $e)
					{
						$wgOut->addHTML($e->getMessage()); 
					}
				}
 
				$path = $file->getPath();
				try
				{
					# Using the FileStore to delete the file itself
					$transaction = FileStore::deleteFile( $path );
					$transaction->commit();		
				}
				catch (Exception $e)
				{
					$wgOut->addHTML($e->getMessage()); 
				}
			}
 
			# clean the filearchive for the given filename:
			$fa_archive_name = array();
			$res = $dbw->select ('filearchive', 'fa_storage_key', array( 'fa_name' => $t ));
 
			while( $row = $dbw->fetchObject($res) ) 
			{
				$key = $row->fa_storage_key;
 
				# Using the FileStore to delete the file
				$store = FileStore::get( 'deleted' );
				$transaction = $store->delete($key);
				$transaction->commit();
			}
 
 
			# Delete old db entries of the image: 
			$dbw->delete( 'oldimage', array( 'oi_name' => $t ), __METHOD__ );
 
			# Delete archive entries of the image:
			$dbw->delete( 'filearchive', array( 'fa_name' => $t ), __METHOD__ );
 
			# Delete image entry:
			$dbw->delete( 'image', array( 'img_name' => $t ), __METHOD__ );
 
			$dbw->commit();
 
			$linkCache = LinkCache::singleton();
			$linkCache->clear();
		}
	}
 
	function deletePermanentlyTalkPage($title)
	{
		global $wgDeletePagePermanentlyNamespaces;
 
		$talkPage = $title->getTalkPage();
		$id       = $title->getArticleID();
		$ns       = $title->getNamespace();
 
		if ( $id != 0 && $wgDeletePagePermanentlyNamespaces[$ns] == true )
		{
			$this->deletePermanently($talkPage);
		}
	}
}

DeletePagePermanently.i18n.php[edit | edit source]

<?php
/**
 * DeletePagePermanently.i18n.php
 * Internationalisation file
 * based on Version 1.0 BETA from Ludovic MOUTON (2008)
 * Wolfgang Stöttinger 2008
 * v. 2.0 BETA
 * GPL
 */
 
$messages = array();
 
/** English */
$messages['en'] = array(
	'tab_label' => 'Delete permanently',
	'del_impossible' => 'This page can not be deleted permanently',
	'ask_deletion' => 'Are you sure, you want to delete this page permanently? All versions and log entries will be deleted. There is no chance to undo this process after completion.',
	'yes' => 'Yes',
	'del_done' => 'The page has been permanently deleted.',
	'del_not_done' => 'The page has NOT been permanently deleted.',
	'right-deleteperm' => 'Delete pages permanently'
);
 
/** German (Deutsch) */
$messages['de'] = array(
	'tab_label' => 'Dauerhaft löschen',
	'del_impossible' => 'Diese Seite kann nicht dauerhaft gelöscht werden.',
	'ask_deletion' => 'Sind Sie sicher, dass Sie diese Seite dauerhaft löschen wollen? Es werden alle Versionen und Logeinträge gelöscht. Danach besteht keine Möglichkeit, diesen Vorgang rückgängig zu machen.',
	'yes' => 'Ja',
	'del_done' => 'Diese Seite wurde dauerhaft gelöscht.',
	'del_not_done' => 'Die Seite wurde nicht dauerhaft gelöscht.',
	'right-deleteperm' => 'Dauerhaft löschen'
);
 
/** French (Français) */
$messages['fr'] = array(
	'tab_label' => 'Supprimer définitivement',
	'del_impossible' => 'Cette page ne peut pas être supprimée définitivement.',
	'ask_deletion' => 'Êtes-vous sûr de vouloir supprimer cette page définitivement ? Toutes les révisions et les entrées du log seront supprimées. Il sera impossible d\’annuler la suppression.',
	'yes' => 'Oui',
	'del_done' => 'La page a été supprimée définitivement.',
	'del_not_done' => 'La page n\’a pas été supprimée définitivement.',
	'right-deleteperm' => 'Supprimer définitivement'
);
 
/** Italian (italiano) */
$messages['it'] = array(
	'tab_label' => 'Cancella permanentemente',
	'del_impossible' => 'Questa pagina non può essere cancellata permanentemente',
	'ask_deletion' => 'Sei sicuro di voler cancellare permanentemente questa pagina? Tutte le vecchie versioni e i log relativi verranno cancellati. Questo processo una volta completato sarà irreversibile.',
	'yes' => 'Sì',
	'del_done' => 'La pagina è stata cancellata permanentemente con successo.',
	'del_not_done' => 'La pagina NON è stata cancellata permanentemente.',
	'right-deleteperm' => 'Cancella pagine permanentemente'
);
 
/** Russian (Русский) */
$messages['ru'] = array(
	'tab_label' => 'Удалить с концами',
	'del_impossible' => 'Эту страницу невозможно удалить.',
	'ask_deletion' => 'Вы собираетесь удалить страницу из БД. Все предыдущие версии записи и история изменений будут удалены без возможности восстановления. Вы уверены?',
	'yes' => 'Да, удалить страницу',
	'del_done' => 'Страница удалена.',
	'del_not_done' => 'Страница НЕ удалена.',
	'right-deleteperm' => 'Удалить с концами'
);
 
/** Polish (Polski) */ 
$messages['pl'] = array( 
	'tab_label' => 'Usuń trwale',
	'del_impossible' => 'Ta strona nie może zostać trwale usunięta',
	'ask_deletion' => 'Czy na pewno chcesz trwale usunąć tę stronę? Wszystkie wersje oraz wpisy w historii zostaną usunięte. Nie będzie możliwości cofnąć tego procesu po jego zakończeniu.',
	'yes' => 'Tak',
	'del_done' => 'Ta strona została trwale usunięta.',
	'del_not_done' => 'Ta strona nie została trwale usunięta.',
	'right-deleteperm' => 'Usuń trwale'
); 
 
/** Portuguese (Português) */
$messages['pt'] = array(
	'tab_label' => 'Eliminar permanentemente',
	'del_impossible' => 'Esta página não pode ser eliminada permanentemente',
	'ask_deletion' => 'Tem certeza que quer eliminar esta página permanentemente? Todas as versões prévias e registros serão excluídos. Não há como reverter este processo após finalizado.',
	'yes' => 'Sim',
	'del_done' => 'A página foi eliminada permanentemente.',
	'del_not_done' => 'A página NÃO foi eliminada.',
	'right-deleteperm' => 'Eliminar permanentemente'
);
$messages['pt-br'] = $messages['pt']; //No differences here between Brazilian and European Portuguese
 
/** Spanish (Español-España)*/
$messages['es'] = array(
	'tab_label' => 'Borrar permanentemente',
	'del_impossible' => 'Esta página no se puede eliminar de forma permanente',
	'ask_deletion' => '¿Está seguro, que desea eliminar esta página de forma permanente? Todas las versiones y las entradas de registro serán borradas. No hay ninguna posibilidad de deshacer este proceso después de su finalización.',
	'yes' => 'Si',
	'del_done' => 'La página ha sido borrada permanentemente.',
	'del_not_done' => 'La página no ha sido borrada permanentemente.',
	'right-deleteperm' => 'Borrar permanentemente'
);
 
/** Japanese(日本語) */
$messages['ja'] = array(
	'tab_label' => '完全削除',
	'del_impossible' => 'このページは完全削除できません。',
	'ask_deletion' => 'あなたはこのページを完全に削除しようとしています。このページに関するデータやログは完全に削除され、恒久的に復元することはできません。',
	'yes' => '上記の内容を完全に理解して完全削除する',
	'del_done' => 'このページは完全に削除されました。',
	'del_not_done' => '完全削除ができませんでした。',
	'right-deleteperm' => 'ページの完全削除'
); 
/** Urdu */
$messages['ur'] = array(
        'tab_label' => 'مستقل حذف کریں',
        'del_impossible' => 'یہ صفحہ مستقلا حذف نہیں ہو سکتا',
        'ask_deletion' => 'کیا آپ واقعی اس صفحے کو مستقلا حذف کرنا چاہتے ہیں؟ تمام دوہرائیاں اور لاگ ساتھ ہی ختم ہو جائیں گے اور ان کی واپسی کا کوئی امکان نہیں۔',
        'yes' => 'جی ہاں',
        'del_done' => 'یہ صفحہ مستقلا حذف کر دیا گیا ہے ',
        'del_not_done' => 'یہ صفحہ مستقلا حذف نہیں کیا جا سکتا۔',
        'right-deleteperm' => 'مستقل حذف'
);
 
/** Simplified Chinese (简体中文) */
$messages['zh'] = array(
        'tab_label' => '永久删除',
        'del_impossible' => '不允许永久删除这个(类)页面',
        'ask_deletion' => '你确定要永久删除这个页面吗?所有版本、日志记录将一并删除。一旦删除完成后就不能撤销。',
        'yes' => '确认',
        'del_done' => '这个页面已被永久删除。',
        'del_not_done' => '这个页面未被永久删除。',
        'right-deleteperm' => '永久删除页面'
);
$messages['zh-hans'] = $messages['zh-cn'] = $messages['zh-sg'] = $messages['zh-my'] = $messages['zh'];
 
/** Traditional Chinese (繁體中文) */
$messages['zh-hant'] = array(
        'tab_label' => '永久刪除',
        'del_impossible' => '不允許永久刪除這個(類)頁面',
        'ask_deletion' => '你確定要永久刪除這個頁面嗎?所有版本、日誌記錄將一併刪除。一旦刪除完成後就不能撤銷。',
        'yes' => '確認',
        'del_done' => '這個頁面已被永久刪除。',
        'del_not_done' => '這個頁面未被永久刪除。',
        'right-deleteperm' => '永久刪除頁面'
);
$messages['zh-hk'] = $messages['zh-tw'] = $messages['zh-mo'] = $messages['zh-hant'];

MediaWiki 1.16.x (or later)[edit | edit source]

If you are using MediaWiki 1.16.x (or later), please use the following code as DeletePagePermanently.php

<?php
/**
 * DeletePagePermanently.php
 * based on Version 1.0 BETA from Ludovic MOUTON (2008)
 * Wolfgang Stöttinger 2008
 * v. 2.1.3 BETA
 * GPL
 * 
 * BE CAREFUL WHEN USING THIS EXTENSION. ONCE A PAGE IS DELETED, IT CAN NOT BE RESTORED ANY MORE.
 * Changed in Version 2.1.3:
 *		- Correctly displays on Vector skin
 *		- Also deletes thumbnails on images
 *		- Using alternate methods to delete files due do deprecation of FileStore in MW 1.16.x
 * Changed in Version 2.1.2:
 *		- Update category count
 * Changed in Version 2.1.1:
 *		- Title is removed from cache.
 * Changed in Version 2.1.0:
 *		- deletePage() can now be used from outside in PHP.
 * 
 * Features of Version 2.0:
 *		- defined $wgDeletePagePermanentlyNamespaces as an array of namespaces in which pages can be deleted.
 * 			$wgDeletePagePermanentlyNamespaces = array (
 * 				NS_MAIN => true,
 *				NS_IMAGE => true,
 * 				NS_CATEGORY => true,
 * 				NS_TEMPLATE => true,
 * 				NS_TALK => true,
 * 			);
 *		
 *		- The tab "Delete permanently" is only shown on pages that can be deleted.
 * 		- An aditional page to approve the deletion
 *		- Also log entries are deleted.
 *		- Also redirects, external links, language links, searchindex entries, page_restrictions, pagelinks, categorylinks, templatelinks, archive entries and image links are deleted.
 * 		- The watchlist entries are also removed.
 *		- If the page is an image page, all versions of the image are deleted from the database, the archive and the filesystem. (Thumbnlais won't be removed)
*/
 
if (!defined('MEDIAWIKI')) {
	exit(1);
}
 
$wgExtensionCredits['other'][] = array (
	'name' => 'DeletePagePermanently',
	'version' => '2.1',
	'author' => 'Ludovic MOUTON, Wolfgang STÖTTINGER',
	'description' => 'Adds a new delete tab to each page. Pages are deleted permanently from the database.',
	'url' => 'http://www.mediawiki.org/wiki/Extension:DeletePagePermanently',
);
 
# Default settings
$wgGroupPermissions['*']['deleteperm'] = false;
$wgGroupPermissions['user']['deleteperm'] = false;
$wgGroupPermissions['bureaucrat']['deleteperm'] = false;
$wgGroupPermissions['sysop']['deleteperm'] = true;
 
$wgDeletePagePermanentlyNamespaces = array (
	NS_MAIN => true,
	NS_IMAGE => true,
	NS_CATEGORY => true,
	NS_TEMPLATE => true,
	NS_TALK => true,
);
 
$wgExtensionMessagesFiles['DeletePagePermanently'] = dirname(__FILE__) . '/DeletePagePermanently.i18n.php';
 
$wgExtensionFunctions[] = 'wfDeletePagePermanently';
 
function wfDeletePagePermanently() {
	new DeletePagePermanently();
	return true;
}
 
class DeletePagePermanently
{
	function DeletePagePermanently() {
		global $wgHooks, $wgMessageCache, $wgUser;
 
		wfLoadExtensionMessages('DeletePagePermanently');
 
		$wgMessageCache->addMessage('delete_permanently', wfMsg('tab_label'));
		$wgHooks['SkinTemplateContentActions'][] = array (
			&$this,
			'AddContentHook'
		);
 
		$wgHooks['SkinTemplateNavigation'][] = array (
			&$this,
			'AddVectorHook'
		);
 
		$wgHooks['UnknownAction'][] = array (
			&$this,
			'AddActionHook'
		);
	}
 
	function AddContentHook(&$content_actions) {
		global $wgRequest, $wgRequest, $wgTitle, $wgUser, $wgDeletePagePermanentlyNamespaces;
 
		if (!$wgUser->isAllowed('deleteperm'))
			return false;
 
		$action = $wgRequest->getText('action');
 
 
		#Special pages can not be deleted (special pages have no article id anyway).
		if ($wgTitle->getArticleID() != 0 && $wgDeletePagePermanentlyNamespaces[$wgTitle->getNamespace()] == true && $wgTitle->getNamespace() != NS_SPECIAL) {
			wfLoadExtensionMessages('DeletePagePermanently');
 
			$content_actions['ask_delete_permanently'] = array (
				'class' => $action == 'ask_delete_permanently' ? 'selected' : false,
				'text' => wfMsg('tab_label'),
				'href' => $wgTitle->getLocalUrl('action=ask_delete_permanently')
			);
		}
 
		return true;
	}
 
	function AddVectorHook(&$sktemplate, &$links) {
		global $wgRequest, $wgRequest, $wgTitle, $wgUser, $wgDeletePagePermanentlyNamespaces;
 
		if (!$wgUser->isAllowed('deleteperm'))
			return false;
 
		$action = $wgRequest->getText('action');
 
 
		#Special pages can not be deleted (special pages have no article id anyway).
		if ($wgTitle->getArticleID() != 0 && $wgDeletePagePermanentlyNamespaces[$wgTitle->getNamespace()] == true && $wgTitle->getNamespace() != NS_SPECIAL) {
			wfLoadExtensionMessages('DeletePagePermanently');
 
			$links['actions']['ask_delete_permanently'] = array (
				'class' => $action == 'ask_delete_permanently' ? 'selected' : false,
				'text' => wfMsg('delete_permanently'),
				'href' => $wgTitle->getLocalUrl('action=ask_delete_permanently')
			);
		}
 
		return true;
	}
 
	function AddActionHook($action, $wgArticle) {
		global $wgOut, $wgUser, $wgDeletePagePermanentlyNamespaces;
 
		wfLoadExtensionMessages('DeletePagePermanently');
 
		if (!$wgUser->isAllowed('deleteperm')) {
			$wgOut->permissionRequired('deleteperm');
			return false;
		}
 
		# Print a form to approve deletion
		if ($action == 'ask_delete_permanently') {
 
			$action = $wgArticle->getTitle()->escapeLocalUrl() . "&action=delete_permanently";
			$wgOut->addHTML("<form id='ask_delete_permanently' method='post' action=\"$action\">
<table>
        <tr>
                <td>" . wfMsg('ask_deletion') . "</td>
        </tr>
        <tr>
                <td><input type='submit' name='submit' value=\"" . wfMsg('yes') . "\" /></td>
        </tr>
</table></form>");
			return false;
		}
		# Perform actual deletion
		elseif ($action == 'delete_permanently') {
			$ns = $wgArticle->mTitle->getNamespace();
			$t = $wgArticle->mTitle->getDBkey();
			$id = $wgArticle->mTitle->getArticleID();
 
			if ($t == '' || $id == 0 || $wgDeletePagePermanentlyNamespaces[$ns] != true || $ns == NS_SPECIAL) {
				$wgOut->addHTML(wfMsgHtml('del_impossible'));
				return false;
			}
 
			$this->deletePermanently($wgArticle->mTitle);
			$wgOut->addHTML(wfMsgHtml('del_done'));
			return false;
		}
		//$wgOut->addHTML(wfMsgHtml('del_not_done'));
		return true;
	}
 
	function deletePermanently($title) {
		global $wgOut;
 
		$ns = $title->getNamespace();
		$t = $title->getDBkey();
		$id = $title->getArticleID();
		$cats = $title->getParentCategories();
 
		$dbw = wfGetDB(DB_MASTER);
 
		$dbw->begin();
 
		####
		## First delete entries, which are in direct relation with the page:
		####

		# delete redirect...
		$dbw->delete('redirect', array ('rd_from' => $id), __METHOD__);
 
		# delete external link...
		$dbw->delete('externallinks', array ('el_from' => $id), __METHOD__);
 
		# delete language link...
		$dbw->delete('langlinks', array ('ll_from' => $id), __METHOD__);
 
		# delete search index...
		$dbw->delete('searchindex', array ('si_page' => $id), __METHOD__);
 
		# Delete restrictions for the page
		$dbw->delete('page_restrictions', array ('pr_page' => $id), __METHOD__);
 
		# Delete page Links
		$dbw->delete('pagelinks', array ('pl_from' => $id), __METHOD__);
 
		# delete category links
		$dbw->delete('categorylinks', array ('cl_from' => $id), __METHOD__);
 
		# delete template links
		$dbw->delete('templatelinks', array ('tl_from' => $id), __METHOD__);
 
		# read text entries for all revisions and delete them.
		$res = $dbw->select('revision', 'rev_text_id', "rev_page=$id");
 
		while ($row = $dbw->fetchObject($res)) {
			$value = $row->rev_text_id;
			$dbw->delete('text', array ('old_id' => $value), __METHOD__);
		}
 
		# In the table 'revision' : Delete all the revision of the page where 'rev_page' = $id
		$dbw->delete('revision', array ('rev_page' => $id), __METHOD__);
 
		# delete image links
		$dbw->delete('imagelinks', array ('il_from' => $id), __METHOD__);
 
		####
		## then delete entries which are not in direct relation with the page:
		####

		# Clean up recentchanges entries...
		$dbw->delete('recentchanges', array (
			'rc_namespace' => $ns,
			'rc_title' => $t
		), __METHOD__);
 
		# read text entries for all archived pages and delete them.
		$res = $dbw->select('archive', 'ar_text_id', array (
			'ar_namespace' => $ns,
			'ar_title' => $t
		));
 
		while ($row = $dbw->fetchObject($res)) {
			$value = $row->ar_text_id;
			$dbw->delete('text', array ('old_id' => $value), __METHOD__);
		}
 
		# Clean archive entries...
		$dbw->delete('archive', array (
			'ar_namespace' => $ns,
			'ar_title' => $t
		), __METHOD__);
 
		# Clean up log entries...
		$dbw->delete('logging', array (
			'log_namespace' => $ns,
			'log_title' => $t
		), __METHOD__);
 
		# Clean up watchlist...
		$dbw->delete('watchlist', array (
			'wl_namespace' => $ns,
			'wl_title' => $t
		), __METHOD__);
 
		# In the table 'page' : Delete the page entry
		$dbw->delete('page', array ('page_id' => $id), __METHOD__);
 
		####
		## If the article belongs to a category, update category counts
		####
		if (!empty($cats)) {
			foreach ($cats as $parentcat => $currentarticle) {
				$catname = split(':', $parentcat, 2);
				$cat = Category::newFromName($catname[1]);
				$cat->refreshCounts();
			}
		}
 
		####
		## If an image is beeing deleted, some extra work needs to be done
		####
		if ($ns == NS_IMAGE) {
 
			$file = wfFindFile($t);
 
			if ($file) {
				# Get all filenames of old versions:
				$fields = OldLocalFile::selectFields();
				$res = $dbw->select('oldimage', $fields, array ('oi_name' => $t));
 
				while ($row = $dbw->fetchObject($res)) {
					$oldLocalFile = OldLocalFile::newFromRow($row, $file->repo);
					$path = $oldLocalFile->getArchivePath() . '/' . $oldLocalFile->getArchiveName();
 
					try { @unlink($path); }
					catch (Exception $e) { $wgOut->addHTML($e->getMessage()); }
				}
 
				$path = $file->getPath();
 
				try {
					$file->purgeThumbnails();
					@unlink($path);
				} catch (Exception $e) { $wgOut->addHTML($e->getMessage()); }
			}
 
			# clean the filearchive for the given filename:
			$dbw->delete('filearchive', array ('fa_name' => $t), __METHOD__);
 
			# Delete old db entries of the image:
			$dbw->delete('oldimage', array ('oi_name' => $t), __METHOD__);
 
			# Delete archive entries of the image:
			$dbw->delete('filearchive', array ('fa_name' => $t), __METHOD__);
 
			# Delete image entry:
			$dbw->delete('image', array ('img_name' => $t), __METHOD__);
 
			$dbw->commit();
 
			$linkCache = LinkCache::singleton();
			$linkCache->clear();
		}
	}
}

History[edit | edit source]

The original Version of this extension was created by Ludovic MOUTON. The original Version can be found at Extension:DeletePagePermanently/1.0

See also[edit | edit source]