Reception123 has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/373563 )
Change subject: Convert AuthorProtect to use extension registration.
......................................................................
Convert AuthorProtect to use extension registration.
Bug: T174042
Change-Id: I27fec954e8a5c8ea46c8d040051be2288161bcd8
---
A AuthorProtect.hooks.php
M AuthorProtect.php
A extension.json
3 files changed, 286 insertions(+), 257 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/AuthorProtect
refs/changes/63/373563/1
diff --git a/AuthorProtect.hooks.php b/AuthorProtect.hooks.php
new file mode 100644
index 0000000..312cc18
--- /dev/null
+++ b/AuthorProtect.hooks.php
@@ -0,0 +1,232 @@
+<?php
+
+// internal variables, do not modify
+$wgAuthorProtectDoProtect = false;
+$wgAuthorProtectDelayRun = true;
+
+class AuthorProtect {
+ /**
+ * Extensions like ConfirmAccount do some weird stuff to $wgTitle
during the UserGetRights hook
+ * So this delays the hook's execution to a point where $wgTitle is set
+ */
+ public static function AuthorProtectDelay( $title, &$user, $action,
$result ) {
+ global $wgAuthorProtectDelayRun;
+ if ( $wgAuthorProtectDelayRun ) {
+ $user->mRights = null;
+ $user->getRights(); // delay hook execution for
compatibility w/ ConfirmAccount
+ $act = ( $action == '' || $action == 'view' ) ? 'edit'
: $action;
+ $wgAuthorProtectDelayRun = false;
+ if ( self::userIsAuthor( $title ) &&
self::isAuthorProtected( $title, $act ) ) {
+ $result = true;
+ return false;
+ }
+ }
+ $result = null;
+ return true;
+ }
+
+ public static function AssignAuthor( $user, &$aRights ) {
+ global $wgTitle;
+
+ // don't assign author to anons... messes up logging stuff.
+ // plus it's all user_id based so it is impossible to
differentiate one anon from another
+ if ( self::userIsAuthor( $wgTitle ) && $user->isLoggedIn() ) {
+ $aRights[] = 'author';
+ $aRights = array_unique( $aRights );
+ }
+ // assign protect too if we need to
+ global $wgAuthorProtectDoProtect;
+ if ( $wgAuthorProtectDoProtect ) {
+ $aRights[] = 'protect';
+ $aRights = array_unique( $aRights );
+ }
+ return true;
+ }
+
+ private static function AuthorProtectAssignProtect() {
+ global $wgAuthorProtectDoProtect, $wgUser;
+ $wgAuthorProtectDoProtect = true;
+ $wgUser->mRights = null;
+ $wgUser->getRights(); // re-trigger the above function to
assign the protect right
+ $wgAuthorProtectDoProtect = false;
+ }
+
+ private static function AuthorProtectUnassignProtect() {
+ global $wgUser;
+ $wgUser->mRights = null;
+ $wgUser->getRights();
+ }
+
+ public static function MakeContentAction( $skin, &$links ) {
+ global $wgUser, $wgRequest;
+
+ $title = $skin->getTitle();
+ if ( self::userIsAuthor( $title ) && $wgUser->isAllowed(
'authorprotect' ) && !$wgUser->isAllowed( 'protect' ) ) {
+ $action = $wgRequest->getText( 'action' );
+ $links['actions']['authorprotect'] = array(
+ 'class' => $action == 'authorprotect' ?
'selected' : false,
+ 'text' => wfMessage(
self::AuthorProtectMessage( $title ) ),
+ 'href' => $title->getLocalUrl(
'action=authorprotect' ),
+ );
+ }
+ return true;
+ }
+
+ public static function AuthorProtectForm( $action, $article ) {
+ if ( $action != 'authorprotect' ) {
+ return true; // unknown action, so state that the
action doesn't exist
+ }
+ global $wgOut, $wgUser, $wgRequest, $wgRestrictionTypes;
+ if ( !$wgUser->isAllowed( 'authorprotect' ) ) {
+ throw new PermissionsError( 'authorprotect' );
+ }
+ if ( !self::userIsAuthor( $article->getTitle() ) ) {
+ $wgOut->setPageTitle( wfMessage( 'errorpagetitle' ) );
+ $wgOut->addWikiMsg( 'authorprotect-notauthor',
$user->getName() );
+ return false;
+ }
+ $wgOut->setPageTitle( wfMessage( 'authorprotect' ) );
+ if ( !$wgRequest->wasPosted() ) {
+ $wgOut->addHTML( self::AuthorProtectMakeProtectForm(
$article->getTitle() ) );
+ } else {
+ if ( !$wgUser->matchEditToken( $wgRequest->getText(
'wpToken' ) ) ) {
+ $wgOut->setPageTitle( wfMessage(
'errorpagetitle' ) );
+ $wgOut->addWikiMsg( 'sessionfailure' );
+ return false;
+ }
+ $restrictions = array();
+ $expiration = array();
+ $expiry = self::AuthorProtectExpiry(
$wgRequest->getText( 'wpExpiryTime' ) );
+ foreach ( $wgRestrictionTypes as $type ) {
+ // hack, but don't allow setting create or
upload restrictions
+ if( $type == 'upload' || $type == 'create' ) {
+ continue;
+ }
+ $rest = $article->getTitle()->getRestrictions(
$type );
+ if ( $rest !== array() ) {
+ if ( !$wgUser->isAllowed( $rest[0] ) &&
!in_array( 'author', $rest ) ) {
+ $restrictions[$type] =
$rest[0]; // don't let them lower the protection level
+ continue;
+ }
+ }
+ if ( $wgRequest->getCheck( "check-{$type}" ) ) {
+ $restrictions[$type] = 'author';
+ $expiration[$type] = $expiry;
+ } else {
+ if ( in_array( 'author', $rest ) ) {
+ $restrictions[$type] = '';
+ $expiration[$type] = $expiry;
+ } else {
+ $restrictions[$type] = ( $rest
!== array() ) ? $rest[0] : ''; // we're not setting it
+ $expiration[$type] = $expiry;
+ }
+ }
+ }
+ $cascade = false;
+ self::AuthorProtectAssignProtect();
+ $str = var_export( array(
+ 'restrictions' => $restrictions,
+ 'reason' => $wgRequest->getText( 'wpReason' ),
+ 'cascade' => $cascade,
+ 'expiry' => $expiration ), true );
+ wfDebugLog( 'authorprotect', $str );
+ $success = $article->updateRestrictions(
+ $restrictions, // array of restrictions
+ $wgRequest->getText( 'wpReason' ), // reason
+ $cascade, // cascading protection disabled,
need to pass by reference
+ $expiration // expiration
+ );
+ self::AuthorProtectUnassignProtect();
+ if ( $success ) {
+ $wgOut->addWikiMsg( 'authorprotect-success' );
+ } else {
+ $wgOut->addWikiMsg( 'authorprotect-failure' );
+ }
+ }
+ return false; // still continues hook processing, but doesn't
throw an error message
+ }
+
+ private static function AuthorProtectMakeProtectForm( $title ) {
+ global $wgRestrictionTypes, $wgUser;
+ $token = $wgUser->getEditToken();
+ $form = Html::rawElement( 'p', array(), htmlspecialchars(
wfMessage( 'authorprotect-intro' ) ) );
+ $form .= Html::openElement( 'form', array( 'method' => 'post',
'action' => $title->getLocalUrl( 'action=authorprotect' ) ) );
+
+ $br = Html::element( 'br' );
+
+ foreach ( $wgRestrictionTypes as $type ) {
+ // hack, but don't show create or upload restrictions
+ if( $type == 'upload' || $type == 'create' ) {
+ continue;
+ }
+ $rest = $title->getRestrictions( $type );
+ if ( $rest !== array() ) {
+ if ( !$wgUser->isAllowed( $rest[0] ) &&
!in_array( 'author', $rest ) ) {
+ continue; // it's protected at a level
higher than them, so don't let them change it so they can now mess with stuff
+ }
+ }
+
+ // Give grep a chance to find the usages:
+ // authorprotect-edit, authorprotect-move
+ $checked = in_array( 'author', $rest );
+ $form .= Xml::checkLabel( wfMessage(
"authorprotect-$type" ), "check-$type", "check-$type", $checked ) . $br;
+ }
+
+ $form .= $br . Xml::inputLabel( wfMessage( 'protectexpiry' ),
'wpExpiryTime', 'wpExpiryTime' );
+ $form .= $br . Xml::inputLabel( wfMessage( 'protectcomment',
'reason' ), 'wpReason', 'wpReason' );
+ $form .= $br . Html::hidden( 'wpToken', $token );
+ $form .= $br . Xml::submitButton( wfMessage(
'authorprotect-confirm' ) );
+ $form .= Xml::closeElement( 'form' );
+ return $form;
+ }
+
+ private static function userIsAuthor( $title ) {
+ global $wgUser;
+
+ if ( !$title instanceOf Title ) {
+ return false; // quick hack to prevent the API from
messing up.
+ }
+
+ if ( $wgUser->getID() === 0 ) {
+ return false; // don't allow anons, they shouldn't even
get this far but just in case...
+ }
+
+ $id = $title->getArticleID();
+ $dbr = wfGetDB( DB_SLAVE ); // grab the slave for reading
+ $aid = $dbr->selectField( 'revision', 'rev_user', array(
'rev_page' => $id ), __METHOD__ );
+ return $wgUser->getID() == $aid;
+ }
+
+ private static function AuthorProtectMessage( $title ) {
+ global $wgRestrictionTypes;
+ foreach ( $wgRestrictionTypes as $type ) {
+ if ( in_array( 'author', $title->getRestrictions( $type
) ) ) {
+ return 'unprotect';
+ }
+ }
+ return 'protect';
+ }
+
+ private static function isAuthorProtected( $title, $action ) {
+ $rest = $title->getRestrictions( $action );
+ return in_array( 'author', $rest );
+ }
+
+ // forked from ProtectionForm::getExpiry and modified to rewrite '' to
infinity
+ private static function AuthorProtectExpiry( $value ) {
+ if ( $value == 'infinite' || $value == 'indefinite' || $value
== 'infinity' || $value == '' ) {
+ $time = wfGetDB( DB_SLAVE )->getInfinity();
+ } else {
+ $unix = strtotime( $value );
+
+ if ( !$unix || $unix === -1 ) {
+ return false;
+ }
+
+ // Fixme: non-qualified absolute times are not in users
specified timezone
+ // and there isn't notice about it in the ui
+ $time = wfTimestamp( TS_MW, $unix );
+ }
+ return $time;
+ }
+}
diff --git a/AuthorProtect.php b/AuthorProtect.php
index 9458761..f295c34 100644
--- a/AuthorProtect.php
+++ b/AuthorProtect.php
@@ -4,262 +4,15 @@
* See http://www.mediawiki.org/wiki/Extension:AuthorProtect for more details
*/
-if ( !defined( 'MEDIAWIKI' ) ) {
- echo "This file is an extension to MediaWiki and cannot be run
externally\n";
- die( 1 );
+if ( function_exists( 'wfLoadExtension' ) ) {
+ wfLoadExtension( 'AuthorProtect' );
+ $wgMessageDirs['AuthorProtect'] = __DIR__ . '/i18n';
+ wfWarn(
+ 'Deprecated PHP entry point used for AuthorProtect extension. '
.
+ 'Please use wfLoadExtension instead, ' .
+ 'see https://www.mediawiki.org/wiki/Extension_registration for
more details.'
+ );
+} else {
+ die( 'This version of the AuthorProtect extension requires MediaWiki
1.29+' );
}
-$wgExtensionCredits['other'][] = array(
- 'path' => __FILE__,
- 'name' => 'Author Protect',
- 'author' => 'Ryan Schmidt',
- 'url' => 'https://www.mediawiki.org/wiki/Extension:AuthorProtect',
- 'version' => '1.4.0',
- 'descriptionmsg' => 'authorprotect-desc',
- 'license-name' => 'GPL-2.0+'
-);
-
-$wgAvailableRights[] = 'author'; // dynamically assigned to the author of a
page, but can be set w/ wgGroupPermissions too
-$wgAvailableRights[] = 'authorprotect'; // users without this right cannot
protect pages they author
-$wgMessagesDirs['AuthorProtect'] = __DIR__ . '/i18n';
-$wgExtensionMessagesFiles['AuthorProtect'] = __DIR__ .
'/AuthorProtect.i18n.php';
-$wgGroupPermissions['sysop']['author'] = true; // sysops can edit every page
despite author protection
-$wgGroupPermissions['user']['authorprotect'] = true; // registered users can
protect pages they author
-$wgHooks['SkinTemplateNavigation::Universal'][] =
'AuthorProtect::MakeContentAction';
-$wgHooks['UnknownAction'][] = 'AuthorProtect::AuthorProtectForm';
-$wgHooks['userCan'][] = 'AuthorProtect::AuthorProtectDelay';
-$wgHooks['UserGetRights'][] = 'AuthorProtect::AssignAuthor';
-$wgRestrictionLevels[] = 'author'; // so sysops, etc. using the normal
protection interface can protect and unprotect it at the author level
-$wgAvailableRights[] = 'author';
-$wgAvailableRights[] = 'authorprotect';
-
-// internal variables, do not modify
-$wgAuthorProtectDoProtect = false;
-$wgAuthorProtectDelayRun = true;
-
-class AuthorProtect {
- /**
- * Extensions like ConfirmAccount do some weird stuff to $wgTitle
during the UserGetRights hook
- * So this delays the hook's execution to a point where $wgTitle is set
- */
- public static function AuthorProtectDelay( $title, &$user, $action,
$result ) {
- global $wgAuthorProtectDelayRun;
- if ( $wgAuthorProtectDelayRun ) {
- $user->mRights = null;
- $user->getRights(); // delay hook execution for
compatibility w/ ConfirmAccount
- $act = ( $action == '' || $action == 'view' ) ? 'edit'
: $action;
- $wgAuthorProtectDelayRun = false;
- if ( self::userIsAuthor( $title ) &&
self::isAuthorProtected( $title, $act ) ) {
- $result = true;
- return false;
- }
- }
- $result = null;
- return true;
- }
-
- public static function AssignAuthor( $user, &$aRights ) {
- global $wgTitle;
-
- // don't assign author to anons... messes up logging stuff.
- // plus it's all user_id based so it is impossible to
differentiate one anon from another
- if ( self::userIsAuthor( $wgTitle ) && $user->isLoggedIn() ) {
- $aRights[] = 'author';
- $aRights = array_unique( $aRights );
- }
- // assign protect too if we need to
- global $wgAuthorProtectDoProtect;
- if ( $wgAuthorProtectDoProtect ) {
- $aRights[] = 'protect';
- $aRights = array_unique( $aRights );
- }
- return true;
- }
-
- private static function AuthorProtectAssignProtect() {
- global $wgAuthorProtectDoProtect, $wgUser;
- $wgAuthorProtectDoProtect = true;
- $wgUser->mRights = null;
- $wgUser->getRights(); // re-trigger the above function to
assign the protect right
- $wgAuthorProtectDoProtect = false;
- }
-
- private static function AuthorProtectUnassignProtect() {
- global $wgUser;
- $wgUser->mRights = null;
- $wgUser->getRights();
- }
-
- public static function MakeContentAction( $skin, &$links ) {
- global $wgUser, $wgRequest;
-
- $title = $skin->getTitle();
- if ( self::userIsAuthor( $title ) && $wgUser->isAllowed(
'authorprotect' ) && !$wgUser->isAllowed( 'protect' ) ) {
- $action = $wgRequest->getText( 'action' );
- $links['actions']['authorprotect'] = array(
- 'class' => $action == 'authorprotect' ?
'selected' : false,
- 'text' => wfMessage(
self::AuthorProtectMessage( $title ) ),
- 'href' => $title->getLocalUrl(
'action=authorprotect' ),
- );
- }
- return true;
- }
-
- public static function AuthorProtectForm( $action, $article ) {
- if ( $action != 'authorprotect' ) {
- return true; // unknown action, so state that the
action doesn't exist
- }
- global $wgOut, $wgUser, $wgRequest, $wgRestrictionTypes;
- if ( !$wgUser->isAllowed( 'authorprotect' ) ) {
- throw new PermissionsError( 'authorprotect' );
- }
- if ( !self::userIsAuthor( $article->getTitle() ) ) {
- $wgOut->setPageTitle( wfMessage( 'errorpagetitle' ) );
- $wgOut->addWikiMsg( 'authorprotect-notauthor',
$user->getName() );
- return false;
- }
- $wgOut->setPageTitle( wfMessage( 'authorprotect' ) );
- if ( !$wgRequest->wasPosted() ) {
- $wgOut->addHTML( self::AuthorProtectMakeProtectForm(
$article->getTitle() ) );
- } else {
- if ( !$wgUser->matchEditToken( $wgRequest->getText(
'wpToken' ) ) ) {
- $wgOut->setPageTitle( wfMessage(
'errorpagetitle' ) );
- $wgOut->addWikiMsg( 'sessionfailure' );
- return false;
- }
- $restrictions = array();
- $expiration = array();
- $expiry = self::AuthorProtectExpiry(
$wgRequest->getText( 'wpExpiryTime' ) );
- foreach ( $wgRestrictionTypes as $type ) {
- // hack, but don't allow setting create or
upload restrictions
- if( $type == 'upload' || $type == 'create' ) {
- continue;
- }
- $rest = $article->getTitle()->getRestrictions(
$type );
- if ( $rest !== array() ) {
- if ( !$wgUser->isAllowed( $rest[0] ) &&
!in_array( 'author', $rest ) ) {
- $restrictions[$type] =
$rest[0]; // don't let them lower the protection level
- continue;
- }
- }
- if ( $wgRequest->getCheck( "check-{$type}" ) ) {
- $restrictions[$type] = 'author';
- $expiration[$type] = $expiry;
- } else {
- if ( in_array( 'author', $rest ) ) {
- $restrictions[$type] = '';
- $expiration[$type] = $expiry;
- } else {
- $restrictions[$type] = ( $rest
!== array() ) ? $rest[0] : ''; // we're not setting it
- $expiration[$type] = $expiry;
- }
- }
- }
- $cascade = false;
- self::AuthorProtectAssignProtect();
- $str = var_export( array(
- 'restrictions' => $restrictions,
- 'reason' => $wgRequest->getText( 'wpReason' ),
- 'cascade' => $cascade,
- 'expiry' => $expiration ), true );
- wfDebugLog( 'authorprotect', $str );
- $success = $article->updateRestrictions(
- $restrictions, // array of restrictions
- $wgRequest->getText( 'wpReason' ), // reason
- $cascade, // cascading protection disabled,
need to pass by reference
- $expiration // expiration
- );
- self::AuthorProtectUnassignProtect();
- if ( $success ) {
- $wgOut->addWikiMsg( 'authorprotect-success' );
- } else {
- $wgOut->addWikiMsg( 'authorprotect-failure' );
- }
- }
- return false; // still continues hook processing, but doesn't
throw an error message
- }
-
- private static function AuthorProtectMakeProtectForm( $title ) {
- global $wgRestrictionTypes, $wgUser;
- $token = $wgUser->getEditToken();
- $form = Html::rawElement( 'p', array(), htmlspecialchars(
wfMessage( 'authorprotect-intro' ) ) );
- $form .= Html::openElement( 'form', array( 'method' => 'post',
'action' => $title->getLocalUrl( 'action=authorprotect' ) ) );
-
- $br = Html::element( 'br' );
-
- foreach ( $wgRestrictionTypes as $type ) {
- // hack, but don't show create or upload restrictions
- if( $type == 'upload' || $type == 'create' ) {
- continue;
- }
- $rest = $title->getRestrictions( $type );
- if ( $rest !== array() ) {
- if ( !$wgUser->isAllowed( $rest[0] ) &&
!in_array( 'author', $rest ) ) {
- continue; // it's protected at a level
higher than them, so don't let them change it so they can now mess with stuff
- }
- }
-
- // Give grep a chance to find the usages:
- // authorprotect-edit, authorprotect-move
- $checked = in_array( 'author', $rest );
- $form .= Xml::checkLabel( wfMessage(
"authorprotect-$type" ), "check-$type", "check-$type", $checked ) . $br;
- }
-
- $form .= $br . Xml::inputLabel( wfMessage( 'protectexpiry' ),
'wpExpiryTime', 'wpExpiryTime' );
- $form .= $br . Xml::inputLabel( wfMessage( 'protectcomment',
'reason' ), 'wpReason', 'wpReason' );
- $form .= $br . Html::hidden( 'wpToken', $token );
- $form .= $br . Xml::submitButton( wfMessage(
'authorprotect-confirm' ) );
- $form .= Xml::closeElement( 'form' );
- return $form;
- }
-
- private static function userIsAuthor( $title ) {
- global $wgUser;
-
- if ( !$title instanceOf Title ) {
- return false; // quick hack to prevent the API from
messing up.
- }
-
- if ( $wgUser->getID() === 0 ) {
- return false; // don't allow anons, they shouldn't even
get this far but just in case...
- }
-
- $id = $title->getArticleID();
- $dbr = wfGetDB( DB_SLAVE ); // grab the slave for reading
- $aid = $dbr->selectField( 'revision', 'rev_user', array(
'rev_page' => $id ), __METHOD__ );
- return $wgUser->getID() == $aid;
- }
-
- private static function AuthorProtectMessage( $title ) {
- global $wgRestrictionTypes;
- foreach ( $wgRestrictionTypes as $type ) {
- if ( in_array( 'author', $title->getRestrictions( $type
) ) ) {
- return 'unprotect';
- }
- }
- return 'protect';
- }
-
- private static function isAuthorProtected( $title, $action ) {
- $rest = $title->getRestrictions( $action );
- return in_array( 'author', $rest );
- }
-
- // forked from ProtectionForm::getExpiry and modified to rewrite '' to
infinity
- private static function AuthorProtectExpiry( $value ) {
- if ( $value == 'infinite' || $value == 'indefinite' || $value
== 'infinity' || $value == '' ) {
- $time = wfGetDB( DB_SLAVE )->getInfinity();
- } else {
- $unix = strtotime( $value );
-
- if ( !$unix || $unix === -1 ) {
- return false;
- }
-
- // Fixme: non-qualified absolute times are not in users
specified timezone
- // and there isn't notice about it in the ui
- $time = wfTimestamp( TS_MW, $unix );
- }
- return $time;
- }
-}
diff --git a/extension.json b/extension.json
new file mode 100644
index 0000000..0926e1f
--- /dev/null
+++ b/extension.json
@@ -0,0 +1,44 @@
+{
+ "name": "AuthorProtect",
+ "version": "1.4.0",
+ "author": [
+ "[https://www.mediawiki.org/wiki/User:Skizzerz Ryan Schmidt]"
+ ],
+ "url": "https://www.mediawiki.org/wiki/Extension:AuthorProtect",
+ "descriptionmsg": "accesscontrol-desc",
+ "license-name": "GPL-2.0+",
+ "AutoloadClasses": {
+ "AuthorProtectHooks": "AuthorProtect.hooks.php"
+ },
+ "MessagesDirs": {
+ "AuthorProtect": [
+ "i18n"
+ ]
+ },
+ "Hooks": {
+ "SkinTemplateNavigation::Universal":
"AuthorProtect::MakeContentAction",
+ "UnknownAction": "AuthorProtect::AuthorProtectForm",
+ "userCan": "AuthorProtect::AuthorProtectDelay",
+ "UserGetRights": "AuthorProtect::AssignAuthor"
+
+ },
+ "ExtensionMessagesFiles": {
+ "AuthorProtect": "AuthorProtect.i18n.php"
+ },
+ "AvailableRights": [
+ "author",
+ "authorprotect"
+ ],
+ "GroupPermissions": {
+ "sysop": {
+ "author": true
+ },
+ "user": {
+ "authorprotect": true
+ }
+ },
+ "RestrictionLevels": {
+ "author": true
+ },
+ "manifest_version": 2
+}
\ No newline at end of file
--
To view, visit https://gerrit.wikimedia.org/r/373563
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I27fec954e8a5c8ea46c8d040051be2288161bcd8
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/AuthorProtect
Gerrit-Branch: master
Gerrit-Owner: Reception123 <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits