Adamw has submitted this change and it was merged.
Change subject: No undeletion of courses of deleted institutions
......................................................................
No undeletion of courses of deleted institutions
When a user tries to view a course that has been deleted, links to
restore it are displayed. With this patch, if the course's
institution has also been deleted, links to restore the institution
are shown instead. The patch also prevents users from restoring
such courses by manually entering the URL to restore them.
Bug: 57837
Change-Id: I18cf2411f395388d2560eec87dc53c67818853ef
---
M EducationProgram.i18n.php
M EducationProgram.php
A includes/CourseUndeletionHelper.php
M includes/actions/Action.php
M includes/actions/EditAction.php
M includes/actions/EditCourseAction.php
M includes/actions/UndeleteAction.php
7 files changed, 313 insertions(+), 37 deletions(-)
Approvals:
Adamw: Verified; Looks good to me, approved
jenkins-bot: Verified
diff --git a/EducationProgram.i18n.php b/EducationProgram.i18n.php
index 0e5184d..9bb4eb7 100644
--- a/EducationProgram.i18n.php
+++ b/EducationProgram.i18n.php
@@ -462,6 +462,10 @@
'coursepage-edit-undelete-revisions' => 'This course has been deleted.
You can $1.',
'coursepage-edit-undelete-link' => 'restore $1
{{PLURAL:$1|revision|revisions}}',
+ // undeletion restrictions
+ 'ep-undelete-course-no-rights' => 'This course has been deleted, but
you don\'t have permission to restore it.',
+ 'ep-undelete-course-org-deleted' => 'This course and its institution,
[[$1|$2]], have been deleted. To restore this course, first [$3 restore $2].',
+
// ep.pager
'ep-pager-confirm-delete' => 'Are you sure you want to delete this
item?',
'ep-pager-delete-fail' => 'Could not delete this item.',
@@ -1489,6 +1493,11 @@
* $1 is a restore link',
'coursepage-edit-undelete-link' => 'Restore link text. Parameters:
* $1 is the amount of number to be restored',
+ 'ep-undelete-course-no-rights' => 'Error message shown instead of a
course undeletion link, if the user is not authorized to undelete courses.',
+ 'ep-undelete-course-org-deleted' => 'Message explaining that the course
and institution were deleted. Parameters:
+* $1 the title of the deleted institution
+* $2 the name of the deleted institution
+* $3 the URL to restore the deleted institution',
'ep-pager-confirm-delete' => 'Asks for deletion confirmation',
'ep-pager-delete-fail' => 'Error message saying stuff could not be
deleted',
'ep-pager-confirm-delete-selected' => 'Deletion confirmation.
Parameters:
diff --git a/EducationProgram.php b/EducationProgram.php
index 7707487..f4d5116 100644
--- a/EducationProgram.php
+++ b/EducationProgram.php
@@ -84,6 +84,7 @@
$wgAutoloadClasses['EducationProgram\ViewCourseAction']
= $dir . '/includes/actions/ViewCourseAction.php';
$wgAutoloadClasses['EducationProgram\ViewCourseActivityAction'] = $dir
. '/includes/actions/ViewCourseActivityAction.php';
$wgAutoloadClasses['EducationProgram\ViewOrgAction']
= $dir . '/includes/actions/ViewOrgAction.php';
+$wgAutoloadClasses['EducationProgram\CourseUndeletionHelper'] = $dir
. '/includes/CourseUndeletionHelper.php';
// includes/api (deriving from ApiBase)
// Many of the actions can also be performed through the API.
diff --git a/includes/CourseUndeletionHelper.php
b/includes/CourseUndeletionHelper.php
new file mode 100644
index 0000000..b34d33c
--- /dev/null
+++ b/includes/CourseUndeletionHelper.php
@@ -0,0 +1,187 @@
+<?php
+
+namespace EducationProgram;
+
+/**
+ * Helps to check that a course can be undeleted, and to create an appropriate
+ * message if it can't be.
+ *
+ * These functions are provided through this helper class because they are
+ * required by classes on different branches of the Action hierarchy
+ * (EditCourseAction and UndeleteAction). They are specific enough to course
+ * undeletion that putting them in the Action superclass would be ugly.
+ *
+ * @since 0.4 alpha
+ *
+ * @ingroup EducationProgram
+ *
+ * @licence GNU GPL v2+
+ * @author Andrew Green < [email protected] >
+ */
+ class CourseUndeletionHelper {
+
+ /**
+ * @since 0.4 alpha
+ *
+ * @var EPRevision
+ */
+ protected $revision;
+
+ /**
+ * @since 0.4 alpha
+ *
+ * @var \IContextSource
+ */
+ protected $context;
+
+ /**
+ * @since 0.4 alpha
+ *
+ * @var EducationPage
+ */
+ protected $educationPage;
+
+ /**
+ * @since 0.4 alpha
+ *
+ * @var CourseUndelCheck
+ */
+ protected $undeletionCheck = CourseUndelCheck::NOT_CHECKED;
+
+ /**
+ * @since 0.4 alpha
+ *
+ * @var int
+ */
+ protected $deletedOrgId;
+
+ /**
+ * @param EPRevision $revision the latest revision of the course that
may or
+ * may not be undeleted
+ *
+ * @param \IContextSource $context the current context
+ *
+ * @param EducationPage $educationPage the EducationPage object for the
+ * course that may or may not be undeleted
+ */
+ public function __construct( EPRevision $revision,
+ \IContextSource $context, EducationPage $educationPage ) {
+
+ $this->revision = $revision;
+ $this->context = $context;
+ $this->educationPage = $educationPage;
+ }
+
+ /**
+ * Determine whether or not the course can be undeleted.
+ *
+ * @return boolean
+ */
+ public function checkRestrictions() {
+
+ // Is the user allowed to edit this page?
+ if ( !$this->context->getUser()->isAllowed(
+ $this->educationPage->getEditRight() ) ) {
+
+ $this->undeletionCheck = CourseUndelCheck::NO_RIGHTS;
+ return false;
+ }
+
+ $deletedCourse = $this->revision->getObject();
+ $this->deletedOrgId = $deletedCourse->getField( 'org_id' );
+
+ $org = Orgs::singleton()->selectRow( null,
+ array( 'id' => $this->deletedOrgId ) );
+
+ if ( $org === false ) {
+ $this->undeletionCheck = CourseUndelCheck::ORG_DELETED;
+ return false;
+ }
+
+ $this->undeletionCheck = CourseUndelCheck::CAN_UNDELETE;
+ return true;
+ }
+
+ /**
+ * Output a message (via the OutputPage from the context provided in the
+ * constructor) explaining why the course can't be undeleted.
+ */
+ public function outputCantUndeleteMsg() {
+ switch ( $this->undeletionCheck ) {
+ case CourseUndelCheck::NOT_CHECKED:
+ throw new \MWException( 'Must check undeletion
restrictions ' .
+ 'before outputting message.' );
+ break;
+
+ case CourseUndelCheck::NO_RIGHTS:
+
+ // Output a message explaining that the user
doesn't have
+ // permission to undelete a course.
+ $this->context->getOutput()->addHTML(
+ $this->context->msg(
'ep-undelete-course-no-rights' )->
+ escaped()
+ );
+
+ break;
+
+ case CourseUndelCheck::ORG_DELETED:
+
+ // Output a message explaining that the
institution
+ // must be undeleted before the course is
undeleted.
+
+ // First get the latest revision of the deleted
org.
+ // If we're here, we can assume that
deletedOrgId has been set.
+ $deletedOrgRev =
Revisions::singleton()->getLatestRevision(
+ array(
+ 'object_id' =>
$this->deletedOrgId,
+ 'type' =>
Orgs::singleton()->getRevisionedObjectTypeId(),
+ )
+ );
+
+ // Check that we actually got a revision.
+ if ( $deletedOrgRev !== false ) {
+
+ // Get an object for the deleted org
and get some info.
+ $deletedOrg =
$deletedOrgRev->getObject();
+ $deletedOrgTitle =
$deletedOrg->getTitle();
+ $deletedOrgName =
$deletedOrg->getField( 'name' );
+
+ // To prevent the restore link from
showing as a redlink, we
+ // include it as if it were external
and use the plainlinks
+ // css class.
+ $html = \Html::openElement(
+ 'span',
+ array( 'class' => 'plainlinks'
) );
+
+ $html .= $this->context->msg(
+
'ep-undelete-course-org-deleted',
+ $deletedOrgTitle,
+ $deletedOrgName,
+ $deletedOrgTitle->getFullURL()
+ )->parse();
+
+ $html .= \Html::closeElement( 'span' );
+
+ $this->context->getOutput()->addHTML(
$html );
+
+ // If we didn't get a revision, something is
quite wrong.
+ } else {
+ throw new \MWException( 'Couldn\'t find
a revision for ' .
+ 'deleted institution id ' .
+ $this->deletedOrgId );
+ }
+
+ break;
+ }
+ }
+}
+
+/**
+ * Constants for possible results of check for restrictions.
+ */
+class CourseUndelCheck {
+ const NOT_CHECKED = -1;
+ const CAN_UNDELETE = 0;
+ const NO_RIGHTS = 1;
+ const ORG_DELETED = 2;
+}
\ No newline at end of file
diff --git a/includes/actions/Action.php b/includes/actions/Action.php
index 9e1337c..b6f8205 100644
--- a/includes/actions/Action.php
+++ b/includes/actions/Action.php
@@ -46,28 +46,29 @@
}
/**
- * Display an undeletion link if the user is alloed to undelete and
- * if there are any previous revions that can be used to undelete.
+ * Display an undeletion link if the user is allowed to undelete and
+ * if there are any previous revisions that can be used to undelete.
+ *
+ * Note: as of version 0.4 alpha, moving check for user rights out of
here,
+ * to the callers.
*
* @since 0.1
*/
public function displayUndeletionLink() {
- if ( $this->getUser()->isAllowed( $this->page->getEditRight() )
) {
- $revisionCount = Revisions::singleton()->count( array(
- 'object_identifier' =>
$this->getTitle()->getText()
- ) );
+ $revisionCount = Revisions::singleton()->count( array(
+ 'object_identifier' => $this->getTitle()->getText()
+ ) );
- if ( $revisionCount > 0 ) {
- $this->getOutput()->addHTML( $this->msg(
- $this->prefixMsg( 'undelete-revisions'
),
- \Message::rawParam( \Linker::linkKnown(
- $this->getTitle(),
- $this->msg( $this->prefixMsg(
'undelete-link' ) )->numParams( $revisionCount )->escaped(),
- array(),
- array( 'action' => 'epundelete'
)
- ) )
- )->text() );
- }
+ if ( $revisionCount > 0 ) {
+ $this->getOutput()->addHTML( $this->msg(
+ $this->prefixMsg( 'undelete-revisions' ),
+ \Message::rawParam( \Linker::linkKnown(
+ $this->getTitle(),
+ $this->msg( $this->prefixMsg(
'undelete-link' ) )->numParams( $revisionCount )->escaped(),
+ array(),
+ array( 'action' => 'epundelete' )
+ ) )
+ )->text() );
}
}
diff --git a/includes/actions/EditAction.php b/includes/actions/EditAction.php
index 2abdac5..fea7871 100644
--- a/includes/actions/EditAction.php
+++ b/includes/actions/EditAction.php
@@ -118,7 +118,17 @@
}
else {
if ( $object === false ) {
- $this->displayUndeletionLink();
+
+ // Note: this fragment of code is only executed
by
+ // EditOrgAction, that is, when the user tries
to edit an
+ // institution. The conditions for displaying
an undeletion
+ // link for courses are checked in
EditCourseAction::onView().
+ if ( $this->getUser()
+ ->isAllowed(
$this->page->getEditRight() ) ) {
+
+ $this->displayUndeletionLink();
+ }
+
$this->displayDeletionLog();
$this->isNew = true;
diff --git a/includes/actions/EditCourseAction.php
b/includes/actions/EditCourseAction.php
index 1b8ecdd..b567a34 100644
--- a/includes/actions/EditCourseAction.php
+++ b/includes/actions/EditCourseAction.php
@@ -63,8 +63,33 @@
$identifier = Courses::normalizeTitle(
$this->getTitle()->getText() );
if ( !$this->isNewPost() && !$this->table->hasIdentifier(
$identifier ) ) {
- $this->displayUndeletionLink();
- $this->displayDeletionLog();
+
+ // Get the most recent revision here, so we can check
that the
+ // institution hasn't been deleted before displaying
undelete
+ // info.
+ $latestRevision =
Revisions::singleton()->getLatestRevision(
+ array(
+ 'object_identifier' => $identifier,
+ 'type' =>
Courses::singleton()->getRevisionedObjectTypeId(),
+ )
+ );
+
+ // Make sure there are indeed previous revisions to
undelete
+ if ( $latestRevision !== false ) {
+
+ // use CourseUndeletionHelper to check
restrictions on
+ // undeletion and display a message if we can't
undelete.
+ $undeletionHelper = new CourseUndeletionHelper(
+ $latestRevision, $this->context,
$this->page );
+
+ if ( $undeletionHelper->checkRestrictions() ) {
+ $this->displayUndeletionLink();
+ } else {
+
$undeletionHelper->outputCantUndeleteMsg();
+ }
+
+ $this->displayDeletionLog();
+ }
list( $name, $term ) = $this->titleToNameAndTerm(
$this->getTitle()->getText() );
diff --git a/includes/actions/UndeleteAction.php
b/includes/actions/UndeleteAction.php
index bfd26e6..9516ab7 100644
--- a/includes/actions/UndeleteAction.php
+++ b/includes/actions/UndeleteAction.php
@@ -59,28 +59,37 @@
$this->getOutput()->redirect(
$this->getTitle()->getLocalURL() );
}
else {
- $req = $this->getRequest();
- if ( $req->wasPosted() &&
$this->getUser()->matchEditToken( $req->getText( 'undeleteToken' ),
$this->getSalt() ) ) {
- $success = $this->doUndelete( $revision
);
+ // This will check that we can undelete, and
will output an
+ // appropriate message if we can't.
+ $canUndelete =
$this->checkAndHandleRestrictions( $revision );
- if ( $success ) {
-
$this->getRequest()->setSessionData(
- 'epsuccess',
- $this->msg(
$this->prefixMsg( 'undeleted' ), $this->getTitle()->getText() )->text()
- );
+ // If there are no problems, do the undelete or
proceed to show
+ // the form.
+ if ( $canUndelete ) {
+ $req = $this->getRequest();
+
+ if ( $req->wasPosted() &&
$this->getUser()->matchEditToken( $req->getText( 'undeleteToken' ),
$this->getSalt() ) ) {
+ $success = $this->doUndelete(
$revision );
+
+ if ( $success ) {
+
$this->getRequest()->setSessionData(
+ 'epsuccess',
+ $this->msg(
$this->prefixMsg( 'undeleted' ), $this->getTitle()->getText() )->text()
+ );
+ }
+ else {
+
$this->getRequest()->setSessionData(
+ 'epfail',
+ $this->msg(
$this->prefixMsg( 'undelete-failed' ), $this->getTitle()->getText() )->text()
+ );
+ }
+
+ $this->getOutput()->redirect(
$this->getTitle()->getLocalURL() );
}
else {
-
$this->getRequest()->setSessionData(
- 'epfail',
- $this->msg(
$this->prefixMsg( 'undelete-failed' ), $this->getTitle()->getText() )->text()
- );
+ $this->displayForm( $revision );
}
-
- $this->getOutput()->redirect(
$this->getTitle()->getLocalURL() );
- }
- else {
- $this->displayForm( $revision );
}
}
}
@@ -96,6 +105,40 @@
}
/**
+ * Check that we can perform the requested undeletion. If there are no
+ * problems, do nothing and return true. If there are problems, output
+ * any messages and return false.
+ *
+ * @since 0.4 alpha
+ *
+ * @param EPRevision $revision The latest revision of the object to
undelete
+ *
+ * @return boolean
+ *
+ */
+ protected function checkAndHandleRestrictions( $revision ) {
+
+ // only worrying about restrictions for courses, specifically
+ // checking that the associated institution is not also deleted
+ if ( get_class( $this->page ) === 'EducationProgram\CoursePage'
) {
+
+ $undeletionHelper = new CourseUndeletionHelper(
+ $revision, $this->context, $this->page
);
+
+ if ( $undeletionHelper->checkRestrictions() ) {
+ return true;
+ } else {
+ $undeletionHelper->outputCantUndeleteMsg();
+ return false;
+ }
+
+ // institutions are always good
+ } else {
+ return true;
+ }
+ }
+
+ /**
* Does the actual undeletion action.
*
* @since 0.1
--
To view, visit https://gerrit.wikimedia.org/r/110143
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I18cf2411f395388d2560eec87dc53c67818853ef
Gerrit-PatchSet: 7
Gerrit-Project: mediawiki/extensions/EducationProgram
Gerrit-Branch: master
Gerrit-Owner: AndyRussG <[email protected]>
Gerrit-Reviewer: Adamw <[email protected]>
Gerrit-Reviewer: AndyRussG <[email protected]>
Gerrit-Reviewer: Nikerabbit <[email protected]>
Gerrit-Reviewer: Ragesoss <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits