r110231 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r110230‎ | r110231 | r110232 >
Date:11:35, 29 January 2012
Author:jeroendedauw
Status:deferred (Comments)
Tags:
Comment:
moved special pages for managing orgs and courses to actions in corresponding namespaces
Modified paths:
  • /trunk/extensions/EducationProgram/EducationProgram.hooks.php (modified) (history)
  • /trunk/extensions/EducationProgram/EducationProgram.i18n.alias.php (modified) (history)
  • /trunk/extensions/EducationProgram/EducationProgram.i18n.ns.php (added) (history)
  • /trunk/extensions/EducationProgram/EducationProgram.i18n.php (modified) (history)
  • /trunk/extensions/EducationProgram/EducationProgram.php (modified) (history)
  • /trunk/extensions/EducationProgram/actions (added) (history)
  • /trunk/extensions/EducationProgram/actions/CourseHistoryAction.php (added) (history)
  • /trunk/extensions/EducationProgram/actions/EPEditAction.php (added) (history)
  • /trunk/extensions/EducationProgram/actions/EPHistoryAction.php (added) (history)
  • /trunk/extensions/EducationProgram/actions/EPViewAction.php (added) (history)
  • /trunk/extensions/EducationProgram/actions/EditCourseAction.php (added) (history)
  • /trunk/extensions/EducationProgram/actions/EditOrgAction.php (added) (history)
  • /trunk/extensions/EducationProgram/actions/OrgHistoryAction.php (added) (history)
  • /trunk/extensions/EducationProgram/actions/ViewCourseAction.php (added) (history)
  • /trunk/extensions/EducationProgram/actions/ViewOrgAction.php (added) (history)
  • /trunk/extensions/EducationProgram/includes/EPCoursePager.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPOrgPager.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPPageObject.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPRevisionPager.php (modified) (history)
  • /trunk/extensions/EducationProgram/pages (added) (history)
  • /trunk/extensions/EducationProgram/pages/CoursePage.php (added) (history)
  • /trunk/extensions/EducationProgram/pages/EPPage.php (added) (history)
  • /trunk/extensions/EducationProgram/pages/OrgPage.php (added) (history)
  • /trunk/extensions/EducationProgram/specials/SpecialEnroll.php (modified) (history)

Diff [purge]

Index: trunk/extensions/EducationProgram/EducationProgram.i18n.ns.php
@@ -0,0 +1,22 @@
 2+<?php
 3+
 4+/**
 5+ * Namespace internationalizationfor the Education Program extension.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file EducationProgram.i18n.ns.php
 10+ * @ingroup EducationProgram
 11+ *
 12+ * @licence GNU GPL v3+
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+
 16+$namespaceNames = array();
 17+
 18+$namespaceNames['en'] = array(
 19+ EP_NS_COURSE => 'Course',
 20+ EP_NS_COURSE_TALK => 'Course_talk',
 21+ EP_NS_INSTITUTION => 'Institution',
 22+ EP_NS_INSTITUTION_TALK => 'Institution_talk',
 23+);
Property changes on: trunk/extensions/EducationProgram/EducationProgram.i18n.ns.php
___________________________________________________________________
Added: svn:eol-style
124 + native
Index: trunk/extensions/EducationProgram/EducationProgram.php
@@ -53,11 +53,22 @@
5454 // i18n
5555 $wgExtensionMessagesFiles['EducationProgram'] = dirname( __FILE__ ) . '/EducationProgram.i18n.php';
5656 $wgExtensionMessagesFiles['EducationProgramAlias'] = dirname( __FILE__ ) . '/EducationProgram.i18n.alias.php';
 57+$wgExtensionMessagesFiles['EPNamespaces'] = dirname( __FILE__ ) . '/EducationProgram.i18n.ns.php';
5758
5859 // Autoloading
5960 $wgAutoloadClasses['EPHooks'] = dirname( __FILE__ ) . '/EducationProgram.hooks.php';
6061 $wgAutoloadClasses['EPSettings'] = dirname( __FILE__ ) . '/EducationProgram.settings.php';
6162
 63+$wgAutoloadClasses['CourseHistoryAction'] = dirname( __FILE__ ) . '/actions/CourseHistoryAction.php';
 64+$wgAutoloadClasses['EditCourseAction'] = dirname( __FILE__ ) . '/actions/EditCourseAction.php';
 65+$wgAutoloadClasses['EditOrgAction'] = dirname( __FILE__ ) . '/actions/EditOrgAction.php';
 66+$wgAutoloadClasses['EPEditAction'] = dirname( __FILE__ ) . '/actions/EPEditAction.php';
 67+$wgAutoloadClasses['EPHistoryAction'] = dirname( __FILE__ ) . '/actions/EPHistoryAction.php';
 68+$wgAutoloadClasses['EPViewAction'] = dirname( __FILE__ ) . '/actions/EPViewAction.php';
 69+$wgAutoloadClasses['OrgHistoryAction'] = dirname( __FILE__ ) . '/actions/OrgHistoryAction.php';
 70+$wgAutoloadClasses['ViewCourseAction'] = dirname( __FILE__ ) . '/actions/ViewCourseAction.php';
 71+$wgAutoloadClasses['ViewOrgAction'] = dirname( __FILE__ ) . '/actions/ViewOrgAction.php';
 72+
6273 $wgAutoloadClasses['ApiDeleteEducation'] = dirname( __FILE__ ) . '/api/ApiDeleteEducation.php';
6374 $wgAutoloadClasses['ApiInstructor'] = dirname( __FILE__ ) . '/api/ApiInstructor.php';
6475 $wgAutoloadClasses['ApiRefreshEducation'] = dirname( __FILE__ ) . '/api/ApiRefreshEducation.php';
@@ -83,6 +94,10 @@
8495 $wgAutoloadClasses['EPRevisionPager'] = dirname( __FILE__ ) . '/includes/EPRevisionPager.php';
8596 $wgAutoloadClasses['EPPageObject'] = dirname( __FILE__ ) . '/includes/EPPageObject.php';
8697
 98+$wgAutoloadClasses['CoursePage'] = dirname( __FILE__ ) . '/pages/CoursePage.php';
 99+$wgAutoloadClasses['EPPage'] = dirname( __FILE__ ) . '/pages/EPPage.php';
 100+$wgAutoloadClasses['OrgPage'] = dirname( __FILE__ ) . '/pages/OrgPage.php';
 101+
87102 $wgAutoloadClasses['SpecialCourse'] = dirname( __FILE__ ) . '/specials/SpecialCourse.php';
88103 $wgAutoloadClasses['SpecialCourses'] = dirname( __FILE__ ) . '/specials/SpecialCourses.php';
89104 $wgAutoloadClasses['SpecialEditCourse'] = dirname( __FILE__ ) . '/specials/SpecialEditCourse.php';
@@ -160,7 +175,10 @@
161176 $wgHooks['UnitTestsList'][] = 'EPHooks::registerUnitTests';
162177 $wgHooks['PersonalUrls'][] = 'EPHooks::onPersonalUrls';
163178 $wgHooks['GetPreferences'][] = 'EPHooks::onGetPreferences';
 179+$wgHooks['SkinTemplateNavigation'][] = 'EPHooks::onPageTabs';
164180 $wgHooks['SkinTemplateNavigation::SpecialPage'][] = 'EPHooks::onSpecialPageTabs';
 181+$wgHooks['ArticleFromTitle'][] = 'EPHooks::onArticleFromTitle';
 182+$wgHooks['CanonicalNamespaces'][] = 'EPHooks::onCanonicalNamespaces';
165183
166184 // Logging
167185 $wgLogTypes[] = 'institution';
@@ -284,6 +302,12 @@
285303 $wgAddGroups['epadmin'] = array( 'eponlineamb', 'epcampamb', 'epinstructor' );
286304 $wgRemoveGroups['epadmin'] = array( 'eponlineamb', 'epcampamb', 'epinstructor' );
287305
 306+// Namespaces
 307+define( 'EP_NS_COURSE', 442 + 0 );
 308+define( 'EP_NS_COURSE_TALK', 442 + 1 );
 309+define( 'EP_NS_INSTITUTION', 422 + 2 );
 310+define( 'EP_NS_INSTITUTION_TALK', 442 + 3 );
 311+
288312 // Resource loader modules
289313 $moduleTemplate = array(
290314 'localBasePath' => dirname( __FILE__ ) . '/resources',
Index: trunk/extensions/EducationProgram/EducationProgram.i18n.alias.php
@@ -5,7 +5,7 @@
66 *
77 * @since 0.1
88 *
9 - * @file EducationProgram.alias.php
 9+ * @file EducationProgram.i18n.alias.php
1010 * @ingroup EducationProgram
1111 *
1212 * @licence GNU GPL v3+
Index: trunk/extensions/EducationProgram/pages/CoursePage.php
@@ -0,0 +1,17 @@
 2+<?php
 3+
 4+
 5+
 6+class CoursePage extends EPPage {
 7+
 8+ protected function getActions() {
 9+ return array(
 10+ 'view' => 'ViewCourseAction',
 11+ 'edit' => 'EditCourseAction',
 12+ 'history' => 'CourseHistoryAction',
 13+ 'enroll' => 'CourseEnrollAction',
 14+ );
 15+ }
 16+
 17+}
 18+
Property changes on: trunk/extensions/EducationProgram/pages/CoursePage.php
___________________________________________________________________
Added: svn:eol-style
119 + native
Index: trunk/extensions/EducationProgram/pages/EPPage.php
@@ -0,0 +1,88 @@
 2+<?php
 3+
 4+abstract class EPPage extends Page implements IContextSource {
 5+
 6+ protected $context;
 7+ protected $page;
 8+
 9+ public function __construct( Title $title ) {
 10+ $this->page = new WikiPage( $title );
 11+ }
 12+
 13+ public function setContext( IContextSource $context ) {
 14+ $this->context = $context;
 15+ }
 16+
 17+ public function getContext() {
 18+ return $this->context;
 19+ }
 20+
 21+ public function getPage() {
 22+ return $this->page;
 23+ }
 24+
 25+ public function isRedirect() {
 26+ return false;
 27+ }
 28+
 29+ public function getTitle() {
 30+ return $this->page->getTitle();
 31+ }
 32+
 33+ public function getRequest() {
 34+ return $this->getContext()->getRequest();
 35+ }
 36+
 37+ public function canUseWikiPage() {
 38+ return $this->getContext()->canUseWikiPage();
 39+ }
 40+
 41+ public function getWikiPage() {
 42+ return $this->getContext()->getWikiPage();
 43+ }
 44+
 45+ public function getOutput() {
 46+ return $this->getContext()->getOutput();
 47+ }
 48+
 49+ public function getUser() {
 50+ return $this->getContext()->getUser();
 51+ }
 52+
 53+ public function getLanguage() {
 54+ return $this->getContext()->getLanguage();
 55+ }
 56+
 57+ public function getSkin() {
 58+ return $this->getContext()->getSkin();
 59+ }
 60+
 61+ public function msg( /* $args */ ) {
 62+ $args = func_get_args();
 63+ return call_user_func_array( array( $this->getContext(), 'msg' ), $args );
 64+ }
 65+
 66+ protected abstract function getActions();
 67+
 68+ public function getActionOverrides() {
 69+ $actions = $this->getActions();
 70+
 71+ foreach ( $GLOBALS['wgActions'] as $actionName => $actionValue ) {
 72+ if ( !array_key_exists( $actionName, $actions ) ) {
 73+ $actions[$actionName] = false;
 74+ }
 75+ }
 76+
 77+ return $actions;
 78+ }
 79+
 80+ public function getTouched() {
 81+ return '19700101000000';
 82+ }
 83+
 84+ public function getLang() {
 85+ wfDeprecated( __METHOD__, '1.19' );
 86+ return $this->getLanguage();
 87+ }
 88+
 89+}
Property changes on: trunk/extensions/EducationProgram/pages/EPPage.php
___________________________________________________________________
Added: svn:eol-style
190 + native
Index: trunk/extensions/EducationProgram/pages/OrgPage.php
@@ -0,0 +1,14 @@
 2+<?php
 3+
 4+
 5+class OrgPage extends EPPage {
 6+
 7+ protected function getActions() {
 8+ return array(
 9+ 'view' => 'ViewOrgAction',
 10+ 'edit' => 'EditOrgAction',
 11+ 'history' => 'OrgHistoryAction',
 12+ );
 13+ }
 14+
 15+}
\ No newline at end of file
Property changes on: trunk/extensions/EducationProgram/pages/OrgPage.php
___________________________________________________________________
Added: svn:eol-style
116 + native
Index: trunk/extensions/EducationProgram/actions/ViewCourseAction.php
@@ -0,0 +1,103 @@
 2+<?php
 3+
 4+class ViewCourseAction extends EPViewAction {
 5+
 6+ public function getName() {
 7+ return 'viewcourse';
 8+ }
 9+
 10+ protected function getDescription() {
 11+ return wfMsg( 'viewcourse' );
 12+ }
 13+
 14+ /**
 15+ *
 16+ *
 17+ * @return String HTML
 18+ */
 19+ public function onView() {
 20+ $out = $this->getOutput();
 21+
 22+ $name = $this->getTitle()->getText();
 23+
 24+ $course = EPCourse::get( $name );
 25+
 26+ if ( $course === false ) {
 27+ $this->displayNavigation();
 28+
 29+ if ( $this->getUser()->isAllowed( 'ep-course' ) ) {
 30+ $out->addWikiMsg( 'ep-course-create', $name );
 31+ EPCourse::displayAddNewRegion( $this->getContext(), array( 'name' => $name ) );
 32+ }
 33+ else {
 34+ $out->addWikiMsg( 'ep-course-none', $name );
 35+ }
 36+ }
 37+ else {
 38+ $this->displayNavigation();
 39+
 40+ $this->displaySummary( $course );
 41+
 42+ $out->addHTML( Html::element( 'h2', array(), wfMsg( 'ep-course-description' ) ) );
 43+
 44+ $out->addHTML( $this->getOutput()->parse( $course->getField( 'description' ) ) );
 45+
 46+ $studentIds = array_map(
 47+ function( EPStudent $student ) {
 48+ return $student->getId();
 49+ },
 50+ $course->getStudents( 'id' )
 51+ );
 52+
 53+ if ( count( $studentIds ) > 0 ) {
 54+ $out->addHTML( Html::element( 'h2', array(), wfMsg( 'ep-course-students' ) ) );
 55+ EPStudent::displayPager( $this->getContext(), array( 'id' => $studentIds ) );
 56+ }
 57+ else {
 58+ // TODO
 59+ }
 60+ }
 61+
 62+ return '';
 63+ }
 64+
 65+ /**
 66+ * Gets the summary data.
 67+ *
 68+ * @since 0.1
 69+ *
 70+ * @param EPCourse $course
 71+ *
 72+ * @return array
 73+ */
 74+ protected function getSummaryData( EPDBObject $course ) {
 75+ $stats = array();
 76+
 77+ $org = EPOrg::selectFieldsRow( 'name', array( 'id' => $course->getField( 'org_id' ) ) );
 78+
 79+ $stats['org'] = Linker::linkKnown(
 80+ SpecialPage::getTitleFor( 'Institution', $org ),
 81+ htmlspecialchars( $org )
 82+ );
 83+
 84+ $lang = $this->getLanguage();
 85+
 86+ $stats['term'] = htmlspecialchars( $course->getField( 'term' ) );
 87+ $stats['start'] = htmlspecialchars( $lang->timeanddate( $course->getField( 'start' ), true ) );
 88+ $stats['end'] = htmlspecialchars( $lang->timeanddate( $course->getField( 'end' ), true ) );
 89+
 90+ $stats['students'] = htmlspecialchars( $lang->formatNum( $course->getField( 'students' ) ) );
 91+
 92+ $stats['status'] = htmlspecialchars( EPCourse::getStatusMessage( $course->getStatus() ) );
 93+
 94+ if ( $this->getUser()->isAllowed( 'ep-token' ) ) {
 95+ $stats['token'] = Linker::linkKnown(
 96+ SpecialPage::getTitleFor( 'Enroll', $course->getId() . '/' . $course->getField( 'token' ) ),
 97+ htmlspecialchars( $course->getField( 'token' ) )
 98+ );
 99+ }
 100+
 101+ return $stats;
 102+ }
 103+
 104+}
\ No newline at end of file
Property changes on: trunk/extensions/EducationProgram/actions/ViewCourseAction.php
___________________________________________________________________
Added: svn:eol-style
1105 + native
Index: trunk/extensions/EducationProgram/actions/EditOrgAction.php
@@ -0,0 +1,77 @@
 2+<?php
 3+
 4+class EditOrgAction extends EPEditAction {
 5+
 6+
 7+ public function getName() {
 8+ return 'editorg';
 9+ }
 10+
 11+ protected function getDescription() {
 12+ return wfMsg( 'editorg' );
 13+ }
 14+
 15+ protected function getItemClass() {
 16+ return 'EPOrg';
 17+ }
 18+
 19+ /**
 20+ * (non-PHPdoc)
 21+ * @see SpecialEPFormPage::getFormFields()
 22+ * @return array
 23+ */
 24+ protected function getFormFields() {
 25+ $fields = parent::getFormFields();
 26+
 27+ $fields['name'] = array (
 28+ 'type' => 'text',
 29+ 'label-message' => 'educationprogram-org-edit-name',
 30+ 'maxlength' => 255,
 31+ 'required' => true,
 32+ 'validation-callback' => function ( $value, array $alldata = null ) {
 33+ return strlen( $value ) < 2 ? wfMsg( 'educationprogram-org-invalid-name' ) : true;
 34+ } ,
 35+ );
 36+
 37+ $fields['city'] = array (
 38+ 'type' => 'text',
 39+ 'label-message' => 'educationprogram-org-edit-city',
 40+ 'required' => true,
 41+ 'validation-callback' => function ( $value, array $alldata = null ) {
 42+ return strlen( $value ) < 2 ? wfMsg( 'educationprogram-org-invalid-city' ) : true;
 43+ } ,
 44+ );
 45+
 46+ $fields['country'] = array (
 47+ 'type' => 'select',
 48+ 'label-message' => 'educationprogram-org-edit-country',
 49+ 'maxlength' => 255,
 50+ 'required' => true,
 51+ 'options' => EPUtils::getCountryOptions( $this->getLanguage()->getCode() ),
 52+ 'validation-callback' => array( $this, 'countryIsValid' ),
 53+ );
 54+
 55+ return $this->processFormFields( $fields );
 56+ }
 57+
 58+ /**
 59+ * Returns true if the country value is valid or an error message if it's not.
 60+ *
 61+ * @since 0.1
 62+ *
 63+ * @param string $value
 64+ * @param array $alldata
 65+ *
 66+ * @return string|true
 67+ */
 68+ public function countryIsValid( $value, array $alldata = null ) {
 69+ $countries = array_keys( CountryNames::getNames( $this->getLanguage()->getCode() ) );
 70+
 71+// if ( $this->isNew() ) {
 72+// array_unshift( $countries, '' );
 73+// }
 74+
 75+ return in_array( $value, $countries ) ? true : wfMsg( 'educationprogram-org-invalid-country' );
 76+ }
 77+
 78+}
\ No newline at end of file
Property changes on: trunk/extensions/EducationProgram/actions/EditOrgAction.php
___________________________________________________________________
Added: svn:eol-style
179 + native
Index: trunk/extensions/EducationProgram/actions/EPViewAction.php
@@ -0,0 +1,167 @@
 2+<?php
 3+
 4+abstract class EPViewAction extends FormlessAction {
 5+
 6+ public function onView() {
 7+
 8+ }
 9+
 10+ /**
 11+ * Show a message in an error box.
 12+ *
 13+ * @since 0.1
 14+ *
 15+ * @param Message $message
 16+ */
 17+ protected function showError( Message $message ) {
 18+ $this->getOutput()->addHTML(
 19+ '<p class="visualClear errorbox">' . $message->parse() . '</p>'
 20+ . '<hr style="display: block; clear: both; visibility: hidden;" />'
 21+ );
 22+ }
 23+
 24+ /**
 25+ * Show a message in a warning box.
 26+ *
 27+ * @since 0.1
 28+ *
 29+ * @param Message $message
 30+ */
 31+ protected function showWarning( Message $message ) {
 32+ $this->getOutput()->addHTML(
 33+ '<p class="visualClear warningbox">' . $message->parse() . '</p>'
 34+ . '<hr style="display: block; clear: both; visibility: hidden;" />'
 35+ );
 36+ }
 37+
 38+ /**
 39+ * Show a message in a success box.
 40+ *
 41+ * @since 0.1
 42+ *
 43+ * @param Message $message
 44+ */
 45+ protected function showSuccess( Message $message ) {
 46+ $this->getOutput()->addHTML(
 47+ '<div class="successbox"><strong><p>' . $message->parse() . '</p></strong></div>'
 48+ . '<hr style="display: block; clear: both; visibility: hidden;" />'
 49+ );
 50+ }
 51+
 52+ /**
 53+ * Adds a navigation menu with the provided links.
 54+ * Links should be provided in an array with:
 55+ * label => Title (object)
 56+ *
 57+ * @since 0.1
 58+ *
 59+ * @param array $items
 60+ */
 61+ protected function displayNavigation( array $items = array() ) {
 62+ $links = array();
 63+ $items = array_merge( $this->getDefaultNavigationItems(), $items );
 64+
 65+ foreach ( $items as $label => $data ) {
 66+ if ( is_array( $data ) ) {
 67+ $target = array_shift( $data );
 68+ $attribs = $data;
 69+ }
 70+ else {
 71+ $target = $data;
 72+ $attribs = array();
 73+ }
 74+
 75+ $links[] = Linker::linkKnown(
 76+ $target,
 77+ htmlspecialchars( $label ),
 78+ $attribs
 79+ );
 80+ }
 81+
 82+ $this->getOutput()->addHTML(
 83+ Html::rawElement( 'p', array(), $this->getLanguage()->pipeList( $links ) )
 84+ );
 85+ }
 86+
 87+ /**
 88+ * Returns the default nav items for @see displayNavigation.
 89+ *
 90+ * @since 0.1
 91+ *
 92+ * @return array
 93+ */
 94+ protected function getDefaultNavigationItems() {
 95+ $items = array(
 96+ wfMsg( 'ep-nav-orgs' ) => SpecialPage::getTitleFor( 'Institutions' ),
 97+ wfMsg( 'ep-nav-courses' ) => SpecialPage::getTitleFor( 'Courses' ),
 98+ );
 99+
 100+ $items[wfMsg( 'ep-nav-students' )] = SpecialPage::getTitleFor( 'Students' );
 101+
 102+ if ( EPStudent::has( array( 'user_id' => $this->getUser()->getId() ) ) ) {
 103+ $items[wfMsg( 'ep-nav-mycourses' )] = SpecialPage::getTitleFor( 'MyCourses' );
 104+ }
 105+
 106+ return $items;
 107+ }
 108+
 109+ /**
 110+ * Display the summary data.
 111+ *
 112+ * @since 0.1
 113+ *
 114+ * @param EPDBObject $item
 115+ * @param boolean $collapsed
 116+ * @param array $summaryData
 117+ */
 118+ protected function displaySummary( EPDBObject $item, $collapsed = false, array $summaryData = null ) {
 119+ $out = $this->getOutput();
 120+
 121+ $class = 'wikitable ep-summary mw-collapsible';
 122+
 123+ if ( $collapsed ) {
 124+ $class .= ' mw-collapsed';
 125+ }
 126+
 127+ $out->addHTML( Html::openElement( 'table', array( 'class' => $class ) ) );
 128+
 129+ $out->addHTML( '<tr>' . Html::element( 'th', array( 'colspan' => 2 ), wfMsg( 'ep-item-summary' ) ) . '</tr>' );
 130+
 131+ $summaryData = is_null( $summaryData ) ? $this->getSummaryData( $item ) : $summaryData;
 132+
 133+ foreach ( $summaryData as $stat => $value ) {
 134+ $out->addHTML( '<tr>' );
 135+
 136+ $out->addHTML( Html::element(
 137+ 'th',
 138+ array( 'class' => 'ep-summary-name' ),
 139+ wfMsg( strtolower( get_called_class() ) . '-summary-' . $stat )
 140+ ) );
 141+
 142+ $out->addHTML( Html::rawElement(
 143+ 'td',
 144+ array( 'class' => 'ep-summary-value' ),
 145+ $value
 146+ ) );
 147+
 148+ $out->addHTML( '</tr>' );
 149+ }
 150+
 151+ $out->addHTML( Html::closeElement( 'table' ) );
 152+ }
 153+
 154+ /**
 155+ * Gets the summary data.
 156+ * Returned values must be escaped.
 157+ *
 158+ * @since 0.1
 159+ *
 160+ * @param EPDBObject $item
 161+ *
 162+ * @return array
 163+ */
 164+ protected function getSummaryData( EPDBObject $item ) {
 165+ return array();
 166+ }
 167+
 168+}
\ No newline at end of file
Property changes on: trunk/extensions/EducationProgram/actions/EPViewAction.php
___________________________________________________________________
Added: svn:eol-style
1169 + native
Index: trunk/extensions/EducationProgram/actions/CourseHistoryAction.php
@@ -0,0 +1,18 @@
 2+<?php
 3+
 4+class CourseHistoryAction extends EPHistoryAction {
 5+
 6+
 7+ public function getName() {
 8+ return 'coursehistory';
 9+ }
 10+
 11+ protected function getDescription() {
 12+ return wfMsg( 'coursehistory' );
 13+ }
 14+
 15+ protected function getItemClass() {
 16+ return 'EPCourse';
 17+ }
 18+
 19+}
\ No newline at end of file
Property changes on: trunk/extensions/EducationProgram/actions/CourseHistoryAction.php
___________________________________________________________________
Added: svn:eol-style
120 + native
Index: trunk/extensions/EducationProgram/actions/ViewOrgAction.php
@@ -0,0 +1,96 @@
 2+<?php
 3+
 4+class ViewOrgAction extends EPViewAction {
 5+
 6+ public function getName() {
 7+ return 'vieworg';
 8+ }
 9+
 10+ protected function getDescription() {
 11+ return wfMsg( 'vieworg' );
 12+ }
 13+
 14+ /**
 15+ *
 16+ *
 17+ * @return String HTML
 18+ */
 19+ public function onView() {
 20+ $out = $this->getOutput();
 21+
 22+ $name = $this->getTitle()->getText();
 23+
 24+ $out->setPageTitle( wfMsgExt( 'ep-institution-title', 'parsemag', $name ) );
 25+
 26+ $org = EPOrg::get( $name );
 27+
 28+ if ( $org === false ) {
 29+ $this->displayNavigation();
 30+
 31+ if ( $this->getUser()->isAllowed( 'ep-org' ) ) {
 32+ $out->addWikiMsg( 'ep-institution-create', $name );
 33+ EPOrg::displayAddNewControl( $this->getContext(), array( 'name' => $name ) );
 34+ }
 35+ else {
 36+ $out->addWikiMsg( 'ep-institution-none', $name );
 37+ }
 38+ }
 39+ else {
 40+ $this->displayNavigation();
 41+
 42+ $this->displaySummary( $org );
 43+
 44+ $out->addHTML( Html::element( 'h2', array(), wfMsg( 'ep-institution-courses' ) ) );
 45+
 46+ EPCourse::displayPager( $this->getContext(), array( 'org_id' => $org->getId() ) );
 47+
 48+ if ( $this->getUser()->isAllowed( 'ep-course' ) ) {
 49+ $out->addHTML( Html::element( 'h2', array(), wfMsg( 'ep-institution-add-course' ) ) );
 50+
 51+ EPCourse::displayAddNewControl( $this->getContext(), array( 'org' => $org->getId() ) );
 52+ }
 53+ }
 54+
 55+ return '';
 56+ }
 57+
 58+ /**
 59+ * Gets the summary data.
 60+ *
 61+ * @since 0.1
 62+ *
 63+ * @param EPOrg $org
 64+ *
 65+ * @return array
 66+ */
 67+ protected function getSummaryData( EPDBObject $org ) {
 68+ $stats = array();
 69+
 70+ $stats['name'] = $org->getField( 'name' );
 71+ $stats['city'] = $org->getField( 'city' );
 72+
 73+ $countries = CountryNames::getNames( $this->getLanguage()->getCode() );
 74+ $stats['country'] = $countries[$org->getField( 'country' )];
 75+
 76+ $stats['status'] = wfMsgHtml( $org->getField( 'active' ) ? 'ep-institution-active' : 'ep-institution-inactive' );
 77+
 78+ $stats['courses'] = $this->getLanguage()->formatNum( $org->getField( 'courses' ) );
 79+ $stats['students'] = $this->getLanguage()->formatNum( $org->getField( 'students' ) );
 80+
 81+ foreach ( $stats as &$stat ) {
 82+ $stat = htmlspecialchars( $stat );
 83+ }
 84+
 85+ if ( $org->getField( 'courses' ) > 0 ) {
 86+ $stats['courses'] = Linker::linkKnown(
 87+ SpecialPage::getTitleFor( 'Courses' ),
 88+ $stats['courses'],
 89+ array(),
 90+ array( 'org_id' => $org->getId() )
 91+ );
 92+ }
 93+
 94+ return $stats;
 95+ }
 96+
 97+}
\ No newline at end of file
Property changes on: trunk/extensions/EducationProgram/actions/ViewOrgAction.php
___________________________________________________________________
Added: svn:eol-style
198 + native
Index: trunk/extensions/EducationProgram/actions/EPHistoryAction.php
@@ -0,0 +1,126 @@
 2+<?php
 3+
 4+abstract class EPHistoryAction extends FormlessAction {
 5+
 6+ protected abstract function getItemClass();
 7+
 8+ public function onView() {
 9+ $c = $this->getItemClass(); // Yeah, this is needed in PHP 5.3 >_>
 10+ $object = $c::get( $this->getTitle()->getText() );
 11+
 12+ if ( $object === false ) {
 13+ // TODO
 14+ }
 15+ else {
 16+ $this->displayRevisions( $object );
 17+ }
 18+
 19+ return '';
 20+ }
 21+
 22+ /**
 23+ * @see SpecialPage::getDescription
 24+ *
 25+ * @since 0.1
 26+ *
 27+ * @return string
 28+ */
 29+// public function getDescription() {
 30+// return wfMsgExt( 'special-' . strtolower( $this->getName() ), 'parsemag', $this->subPage );
 31+// }
 32+
 33+ /**
 34+ * Display a list with the passed revisions.
 35+ *
 36+ * @since 0.1
 37+ *
 38+ * @param EPDBObject $object
 39+ */
 40+ protected function displayRevisions( EPDBObject $object ) {
 41+ $conditions = array(
 42+ 'type' => get_class( $object ),
 43+ );
 44+
 45+ if ( $object->hasIdField() ) {
 46+ $conditions['object_id'] = $object->getId();
 47+ }
 48+
 49+ $action = htmlspecialchars( $GLOBALS['wgScript'] );
 50+
 51+ $request = $this->getRequest();
 52+ $out = $this->getOutput();
 53+
 54+ /**
 55+ * Add date selector to quickly get to a certain time
 56+ */
 57+ $year = $request->getInt( 'year' );
 58+ $month = $request->getInt( 'month' );
 59+ $tagFilter = $request->getVal( 'tagfilter' );
 60+ $tagSelector = ChangeTags::buildTagFilterSelector( $tagFilter );
 61+
 62+ /**
 63+ * Option to show only revisions that have been (partially) hidden via RevisionDelete
 64+ */
 65+ if ( $request->getBool( 'deleted' ) ) {
 66+ $conditions['deleted'] = true;
 67+ }
 68+
 69+ $checkDeleted = Xml::checkLabel( $this->msg( 'history-show-deleted' )->text(),
 70+ 'deleted', 'mw-show-deleted-only', $request->getBool( 'deleted' ) ) . "\n";
 71+
 72+ $out->addHTML(
 73+ "<form action=\"$action\" method=\"get\" id=\"mw-history-searchform\">" .
 74+ Xml::fieldset(
 75+ $this->msg( 'history-fieldset-title' )->text(),
 76+ false,
 77+ array( 'id' => 'mw-history-search' )
 78+ ) .
 79+ Html::hidden( 'title', $this->getTitle()->getPrefixedDBKey() ) . "\n" .
 80+ Html::hidden( 'action', 'history' ) . "\n" .
 81+ Xml::dateMenu( $year, $month ) . '&#160;' .
 82+ ( $tagSelector ? ( implode( '&#160;', $tagSelector ) . '&#160;' ) : '' ) .
 83+ $checkDeleted .
 84+ Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . "\n" .
 85+ '</fieldset></form>'
 86+ );
 87+
 88+ $pager = new EPRevisionPager( $this->getContext(), $this->getItemClass(), $conditions );
 89+
 90+ if ( $pager->getNumRows() ) {
 91+ $out->addHTML(
 92+ $pager->getNavigationBar() .
 93+ $pager->getBody() .
 94+ $pager->getNavigationBar()
 95+ );
 96+ }
 97+ else {
 98+ // TODO
 99+ }
 100+
 101+// $revisions = EPRevision::select(
 102+// null,
 103+// $conditions
 104+// );
 105+//
 106+// if ( count( $revisions ) > 0 ) {
 107+// array_unshift( $revisions, EPRevision::newFromObject( $object ) );
 108+// $this->displayRevisionList( $revisions );
 109+// }
 110+// else {
 111+// // TODO
 112+// }
 113+ }
 114+
 115+ protected function displayRevisionList( array /* of EPRevision */ $revisions ) {
 116+ foreach ( $revisions as &$revision ) {
 117+ $revision = '<li>' . $this->getRevisionItem( $revision ) . '</li>';
 118+ }
 119+
 120+ $this->getOutput()->addHTML( '<ul>' . implode( '', $revisions ) . '</ul>' );
 121+ }
 122+
 123+ protected function getRevisionItem( EPRevision $revision ) {
 124+ return $revision->getField( 'time' ) . json_encode( $revision->getField( 'data' ) ); // TODO
 125+ }
 126+
 127+}
\ No newline at end of file
Property changes on: trunk/extensions/EducationProgram/actions/EPHistoryAction.php
___________________________________________________________________
Added: svn:eol-style
1128 + native
Index: trunk/extensions/EducationProgram/actions/EditCourseAction.php
@@ -0,0 +1,162 @@
 2+<?php
 3+
 4+class EditCourseAction extends EPEditAction {
 5+
 6+
 7+ public function getName() {
 8+ return 'editcourse';
 9+ }
 10+
 11+ protected function getDescription() {
 12+ return wfMsg( 'editcourse' );
 13+ }
 14+
 15+ public function onView() {
 16+ $this->getOutput()->addModules( array( 'ep.datepicker', 'ep.combobox' ) );
 17+
 18+ return parent::onView();
 19+ }
 20+
 21+ protected function getItemClass() {
 22+ return 'EPCourse';
 23+ }
 24+
 25+ /**
 26+ * (non-PHPdoc)
 27+ * @see SpecialEPFormPage::getFormFields()
 28+ * @return array
 29+ */
 30+ protected function getFormFields() {
 31+ $fields = parent::getFormFields();
 32+
 33+ $orgOptions = EPOrg::getOrgOptions();
 34+
 35+ $fields['name'] = array (
 36+ 'type' => 'text',
 37+ 'label-message' => 'ep-course-edit-name',
 38+ 'required' => true,
 39+ );
 40+
 41+ $fields['org_id'] = array (
 42+ 'type' => 'select',
 43+ 'label-message' => 'ep-course-edit-org',
 44+ 'required' => true,
 45+ 'options' => $orgOptions,
 46+ 'validation-callback' => function ( $value, array $alldata = null ) use ( $orgOptions ) {
 47+ return in_array( (int)$value, array_values( $orgOptions ) ) ? true : wfMsg( 'ep-course-invalid-org' );
 48+ },
 49+ );
 50+
 51+ $fields['token'] = array (
 52+ 'type' => 'text',
 53+ 'label-message' => 'ep-course-edit-token',
 54+ 'maxlength' => 255,
 55+ 'size' => 20,
 56+ 'validation-callback' => function ( $value, array $alldata = null ) {
 57+ $strLen = strlen( $value );
 58+ return ( $strLen !== 0 && $strLen < 2 ) ? wfMsgExt( 'ep-course-invalid-token', 'parsemag', 2 ) : true;
 59+ } ,
 60+ );
 61+
 62+ $fields['term'] = array (
 63+ 'type' => 'text',
 64+ 'label-message' => 'ep-course-edit-term',
 65+ 'required' => true,
 66+ );
 67+
 68+ $fields['start'] = array (
 69+ 'class' => 'EPHTMLDateField',
 70+ 'label-message' => 'ep-course-edit-start',
 71+ 'required' => true,
 72+ );
 73+
 74+ $fields['end'] = array (
 75+ 'class' => 'EPHTMLDateField',
 76+ 'label-message' => 'ep-course-edit-end',
 77+ 'required' => true,
 78+ );
 79+
 80+ $fieldFields = EPCourse::selectFields( 'field', array(), array( 'DISTINCT' ) );
 81+ $fieldFields = array_merge( array( '' => '' ), $fieldFields );
 82+ $fields['field'] = array (
 83+ 'class' => 'EPHTMLCombobox',
 84+ 'label-message' => 'ep-course-edit-field',
 85+ 'required' => true,
 86+ 'options' => array_combine( $fieldFields, $fieldFields ),
 87+ );
 88+
 89+ $levels = EPCourse::selectFields( 'level', array(), array( 'DISTINCT' ) );
 90+ $levels = array_merge( array( '' => '' ), $levels );
 91+ $fields['level'] = array (
 92+ 'class' => 'EPHTMLCombobox',
 93+ 'label-message' => 'ep-course-edit-level',
 94+ 'required' => true,
 95+ 'options' => array_combine( $levels, $levels ),
 96+ );
 97+
 98+ $langOptions = EPUtils::getLanguageOptions( $this->getLanguage()->getCode() );
 99+ $fields['lang'] = array (
 100+ 'type' => 'select',
 101+ 'label-message' => 'ep-course-edit-lang',
 102+ 'maxlength' => 255,
 103+ 'required' => true,
 104+ 'options' => $langOptions,
 105+ 'validation-callback' => function ( $value, array $alldata = null ) use ( $langOptions ) {
 106+ return in_array( $value, $langOptions ) ? true : wfMsg( 'ep-course-invalid-lang' );
 107+ }
 108+ );
 109+
 110+ $mcs = EPCourse::selectFields( 'mc', array(), array( 'DISTINCT' ) );
 111+ $mcs = array_merge( array( '' => '' ), $mcs );
 112+ $fields['mc'] = array (
 113+ 'class' => 'EPHTMLCombobox',
 114+ 'label-message' => 'ep-course-edit-mc',
 115+ 'required' => true,
 116+ 'options' => array_combine( $mcs, $mcs ),
 117+ );
 118+
 119+ $fields['description'] = array (
 120+ 'type' => 'textarea',
 121+ 'label-message' => 'ep-course-edit-description',
 122+ 'required' => true,
 123+ 'validation-callback' => function ( $value, array $alldata = null ) {
 124+ return strlen( $value ) < 10 ? wfMsgExt( 'ep-course-invalid-description', 'parsemag', 10 ) : true;
 125+ } ,
 126+ 'rows' => 10,
 127+ 'id' => 'wpTextbox1',
 128+ );
 129+
 130+ return $this->processFormFields( $fields );
 131+ }
 132+
 133+ /**
 134+ * (non-PHPdoc)
 135+ * @see SpecialEPFormPage::getNewData()
 136+ */
 137+ protected function getNewData() {
 138+ return array(
 139+ 'org_id' => $this->getRequest()->getVal( 'neworg' ),
 140+ 'name' => wfMsgExt(
 141+ 'ep-course-edit-name-format',
 142+ 'parsemag',
 143+ $this->getRequest()->getVal( 'newname' ),
 144+ $this->getRequest()->getVal( 'newterm' )
 145+ ),
 146+ 'term' => $this->getRequest()->getVal( 'newterm' ),
 147+ 'mc' => $this->getRequest()->getVal( 'newname' ),
 148+ );
 149+ }
 150+
 151+ /**
 152+ * (non-PHPdoc)
 153+ * @see SpecialEPFormPage::handleKnownField()
 154+ */
 155+ protected function handleKnownField( $name, $value ) {
 156+ if ( in_array( $name, array( 'end', 'start' ) ) ) {
 157+ $value = wfTimestamp( TS_MW, strtotime( $value ) );
 158+ }
 159+
 160+ return $value;
 161+ }
 162+
 163+}
\ No newline at end of file
Property changes on: trunk/extensions/EducationProgram/actions/EditCourseAction.php
___________________________________________________________________
Added: svn:eol-style
1164 + native
Index: trunk/extensions/EducationProgram/actions/OrgHistoryAction.php
@@ -0,0 +1,18 @@
 2+<?php
 3+
 4+class OrgHistoryAction extends EPHistoryAction {
 5+
 6+
 7+ public function getName() {
 8+ return 'orghistory';
 9+ }
 10+
 11+ protected function getDescription() {
 12+ return wfMsg( 'orghistory' );
 13+ }
 14+
 15+ protected function getItemClass() {
 16+ return 'EPOrg';
 17+ }
 18+
 19+}
\ No newline at end of file
Property changes on: trunk/extensions/EducationProgram/actions/OrgHistoryAction.php
___________________________________________________________________
Added: svn:eol-style
120 + native
Index: trunk/extensions/EducationProgram/actions/EPEditAction.php
@@ -0,0 +1,363 @@
 2+<?php
 3+
 4+abstract class EPEditAction extends FormlessAction {
 5+
 6+ /**
 7+ * Instance of the object being edited or created.
 8+ *
 9+ * @since 0.1
 10+ * @var EPDBObject|false
 11+ */
 12+ protected $item = false;
 13+
 14+ protected abstract function getItemClass();
 15+
 16+ public function onView() {
 17+ $this->getOutput()->addModules( 'ep.formpage' );
 18+
 19+ if ( $this->getRequest()->wasPosted() && $this->getUser()->matchEditToken( $this->getRequest()->getVal( 'wpEditToken' ) ) ) {
 20+ $this->showForm();
 21+ }
 22+ else {
 23+ $this->showContent();
 24+ }
 25+
 26+ return '';
 27+ }
 28+
 29+ /**
 30+ * @see SpecialPage::getDescription
 31+ *
 32+ * @since 0.1
 33+ *
 34+ * @return string
 35+ */
 36+// public function getDescription() {
 37+// $action = $this->isNew() ? 'add' : 'edit';
 38+// return wfMsg( 'special-' . strtolower( $this->getName() ) . '-' . $action );
 39+// }
 40+
 41+ /**
 42+ * Display the form and set the item field, or redirect the user.
 43+ *
 44+ * @since 0.1
 45+ */
 46+ protected function showContent() {
 47+ $c = $this->getItemClass(); // Yeah, this is needed in PHP 5.3 >_>
 48+
 49+ if ( $this->isNew() ) {
 50+ $data = $this->getNewData();
 51+
 52+ $object = $c::selectRow( null, $data );
 53+
 54+ if ( $object === false ) {
 55+ $object = new $c( $data, true );
 56+ }
 57+ else {
 58+ $this->showWarning( wfMessage( 'educationprogram-' . strtolower( $this->getName() ) . '-exists-already' ) );
 59+ }
 60+ }
 61+ else {
 62+ $object = $c::selectRow( null, $this->getTitleConditions() );
 63+ }
 64+
 65+ if ( $object === false ) {
 66+ $this->getOutput()->redirect( SpecialPage::getTitleFor( $c::getListPage() )->getLocalURL() );
 67+ }
 68+ else {
 69+// if ( !$this->isNew() ) {
 70+// $this->getOutput()->addHTML(
 71+// SpecialContestPage::getNavigation( $contest->getField( 'name' ), $this->getUser(), $this->getLanguage(), $this->getName() )
 72+// );
 73+// }
 74+
 75+ $this->item = $object;
 76+ $this->showForm();
 77+ }
 78+ }
 79+
 80+ /**
 81+ * Returns if the page should work in insertion mode rather then modification mode.
 82+ *
 83+ * @since 0.1
 84+ *
 85+ * @return boolean
 86+ */
 87+ protected function isNew() {
 88+ static $isNew = null;
 89+
 90+ if ( is_null( $isNew ) ) {
 91+ $isNew = $this->getRequest()->wasPosted() &&
 92+ ( $this->getRequest()->getCheck( 'isnew' ) || $this->getRequest()->getCheck( 'wpisnew' ) );
 93+ }
 94+
 95+ return $isNew;
 96+ }
 97+
 98+ /**
 99+ * Show the form.
 100+ *
 101+ * @since 0.1
 102+ */
 103+ protected function showForm() {
 104+ $form = $this->getForm();
 105+
 106+ if ( $this->getRequest()->wasPosted() && $this->getRequest()->getCheck( 'isnew' ) ) {
 107+ $form->prepareForm();
 108+ $form->displayForm( Status::newGood() );
 109+ }
 110+ else {
 111+ if ( $form->show() ) {
 112+ $this->onSuccess();
 113+ }
 114+ }
 115+ }
 116+
 117+ /**
 118+ * Returns the data to use as condition for selecting the object,
 119+ * or in case nothing matches the selection, the data to initialize
 120+ * it with. This is typically an identifier such as name or id.
 121+ *
 122+ * @since 0.1
 123+ *
 124+ * @return array
 125+ */
 126+ protected function getNewData() {
 127+ return array( 'name' => $this->getRequest()->getVal( 'newname' ) );
 128+ }
 129+
 130+ /**
 131+ * Get the query conditions to obtain the item based on the page title.
 132+ *
 133+ * @since 0.1
 134+ *
 135+ * @return array
 136+ */
 137+ protected function getTitleConditions() {
 138+ return array( 'name' => $this->getTitle()->getText() );
 139+ }
 140+
 141+ /**
 142+ * (non-PHPdoc)
 143+ * @see FormSpecialPage::getForm()
 144+ * @return HTMLForm|null
 145+ */
 146+ protected function getForm() {
 147+ $fields = $this->getFormFields();
 148+
 149+ if ( $this->isNew() ) {
 150+ $fields['isnew'] = array(
 151+ 'type' => 'hidden',
 152+ 'default' => 1,
 153+ );
 154+ }
 155+
 156+ if ( $this->getRequest()->getCheck( 'wpreturnto' ) ) {
 157+ $fields['returnto'] = array(
 158+ 'type' => 'hidden',
 159+ 'default' => $this->getRequest()->getText( 'wpreturnto' ),
 160+ );
 161+ }
 162+
 163+ $form = new HTMLForm( $fields, $this->getContext() );
 164+
 165+ $form->setSubmitCallback( array( $this, 'handleSubmission' ) );
 166+ $form->setSubmitText( wfMsg( 'educationprogram-org-submit' ) );
 167+ $form->setSubmitTooltip( 'ep-form-save' );
 168+
 169+ $action = $this->isNew() ? 'add' : 'edit';
 170+ $form->setWrapperLegend( $this->msg( strtolower( $this->getName() ) . '-' . $action . '-legend' ) );
 171+
 172+ $c = $this->getItemClass(); // Yeah, this is needed in PHP 5.3 >_>
 173+
 174+ $form->addButton(
 175+ 'cancelEdit',
 176+ wfMsg( 'cancel' ),
 177+ 'cancelEdit',
 178+ array(
 179+ 'target-url' => $this->getReturnToTitle()->getFullURL(),
 180+ )
 181+ );
 182+
 183+// $form->addButton(
 184+// 'deleteEdit',
 185+// wfMsg( 'delete' ),
 186+// 'deleteEdit'
 187+// );
 188+
 189+ return $form;
 190+ }
 191+
 192+ /**
 193+ * (non-PHPdoc)
 194+ * @see FormSpecialPage::getFormFields()
 195+ * @return array
 196+ */
 197+ protected function getFormFields() {
 198+ $fields = array();
 199+
 200+ $fields['id'] = array( 'type' => 'hidden' );
 201+
 202+ $req = $this->getRequest();
 203+
 204+ // This sort of sucks as well. Meh, HTMLForm is odd.
 205+ if ( $req->wasPosted()
 206+ && $this->getUser()->matchEditToken( $req->getVal( 'wpEditToken' ) )
 207+ && $req->getCheck( 'wpitem-id' ) ) {
 208+ $fields['id']['default'] = $req->getInt( 'wpitem-id' );
 209+ }
 210+
 211+ return $fields;
 212+ }
 213+
 214+ /**
 215+ * Populates the form fields with the data of the item
 216+ * and prefixes their names.
 217+ *
 218+ * @since 0.1
 219+ *
 220+ * @param array $fields
 221+ *
 222+ * @return array
 223+ */
 224+ protected function processFormFields( array $fields ) {
 225+ if ( $this->item !== false ) {
 226+ foreach ( $fields as $name => &$data ) {
 227+ if ( !array_key_exists( 'default', $data ) ) {
 228+ $data['default'] = $this->getDefaultFromItem( $this->item, $name );
 229+ }
 230+ }
 231+ }
 232+
 233+ $mappedFields = array();
 234+
 235+ foreach ( $fields as $name => $field ) {
 236+ if ( $this->getRequest()->getCheck( 'isnew' ) ) {
 237+ // HTML form is being a huge pain in running the validation on post,
 238+ // so just remove it if when not appropriate.
 239+ unset( $field['validation-callback'] );
 240+ unset( $field['required'] );
 241+ }
 242+
 243+ $mappedFields['item-' . $name] = $field;
 244+ }
 245+
 246+ return $mappedFields;
 247+ }
 248+
 249+ /**
 250+ * Gets the default value for a field from the item.
 251+ *
 252+ * @since 0.1
 253+ *
 254+ * @param EPDBObject $item
 255+ * @param string $name
 256+ *
 257+ * @return mixed
 258+ */
 259+ protected function getDefaultFromItem( EPDBObject $item, $name ) {
 260+ return $item->getField( $name );
 261+ }
 262+
 263+ /**
 264+ * Gets called after the form is saved.
 265+ *
 266+ * @since 0.1
 267+ */
 268+ public function onSuccess() {
 269+ $this->getOutput()->redirect( $this->getReturnToTitle( true )->getLocalURL() );
 270+ }
 271+
 272+ protected function getReturnToTitle( $newToItem = false ) {
 273+ if ( $this->getRequest()->getCheck( 'wpreturnto' ) ) {
 274+ return Title::newFromText( $this->getRequest()->getText( 'wpreturnto' ) );
 275+ }
 276+ elseif ( $newToItem && $this->isNew() ) {
 277+ $c = $this->getItemClass(); // Yeah, this is needed in PHP 5.3 >_>
 278+ return $c::getTitleFor( $this->getRequest()->getText( 'wpitem-' . $c::getIdentifierField() ) );
 279+ }
 280+ else {
 281+ return $this->getTitle();
 282+ }
 283+ }
 284+
 285+ /**
 286+ * Process the form. At this point we know that the user passes all the criteria in
 287+ * userCanExecute().
 288+ *
 289+ * @param array $data
 290+ *
 291+ * @return Bool|Array
 292+ */
 293+ public function handleSubmission( array $data ) {
 294+ $fields = array();
 295+ $unknownValues = array();
 296+
 297+ $c = $this->getItemClass(); // Yeah, this is needed in PHP 5.3 >_>
 298+
 299+ foreach ( $data as $name => $value ) {
 300+ $matches = array();
 301+
 302+ if ( preg_match( '/item-(.+)/', $name, $matches ) ) {
 303+ if ( $matches[1] === 'id' && ( $value === '' || $value === '0' ) ) {
 304+ $value = null;
 305+ }
 306+
 307+ if ( $c::canHasField( $matches[1] ) ) {
 308+ $fields[$matches[1]] = $value;
 309+ }
 310+ else {
 311+ $unknownValues[$matches[1]] = $value;
 312+ }
 313+ }
 314+ }
 315+
 316+ $keys = array_keys( $fields );
 317+ $fields = array_combine( $keys, array_map( array( $this, 'handleKnownField' ), $keys, $fields ) );
 318+
 319+ /* EPDBObject */ $item = new $c( $fields, is_null( $fields['id'] ) );
 320+
 321+ foreach ( $unknownValues as $name => $value ) {
 322+ $this->handleUnknownField( $item, $name, $value );
 323+ }
 324+
 325+ $success = $item->writeToDB();
 326+
 327+ if ( $success ) {
 328+ return true;
 329+ }
 330+ else {
 331+ return array(); // TODO
 332+ }
 333+ }
 334+
 335+ /**
 336+ * Gets called for evey unknown submitted value, so they can be dealt with if needed.
 337+ *$title = SpecialPage::getTitleFor( $this->itemPage, $this->subPage )->getLocalURL();
 338+ * @since 0.1
 339+ *
 340+ * @param EPDBObject $item
 341+ * @param string $name
 342+ * @param string $value This is a string, since it comes from request data, but might be a number or other type.
 343+ */
 344+ protected function handleUnknownField( EPDBObject $item, $name, $value ) {
 345+ // Override to use.
 346+ }
 347+
 348+ /**
 349+ * Gets called for evey known submitted value, so they can be dealt with if needed.
 350+ *
 351+ * @since 0.1
 352+ *
 353+ * @param string $name
 354+ * @param string $value This is a string, since it comes from request data, but might be a number or other type.
 355+ *
 356+ * @return mixed The new value
 357+ */
 358+ protected function handleKnownField( $name, $value ) {
 359+ // Override to use.
 360+ return $value;
 361+ }
 362+
 363+
 364+}
\ No newline at end of file
Property changes on: trunk/extensions/EducationProgram/actions/EPEditAction.php
___________________________________________________________________
Added: svn:eol-style
1365 + native
Index: trunk/extensions/EducationProgram/specials/SpecialEnroll.php
@@ -47,16 +47,18 @@
4848
4949 $args = explode( '/', $this->subPage, 2 );
5050
51 - if ( !ctype_digit( $args[0] ) ) {
52 - $this->showWarning( wfMessage( $args[0] === '' ? 'ep-enroll-no-id' : 'ep-enroll-invalid-id' ) );
 51+ if ( $args[0] === '' ) {
 52+ $this->showWarning( 'ep-enroll-no-id' );
5353 }
5454 else {
55 - $course = EPCourse::selectRow( null, array( 'id' => $args[0] ) );
 55+ $course = EPCourse::get( $args[0] );
5656
5757 if ( $course === false ) {
5858 $this->showWarning( wfMessage( 'ep-enroll-invalid-id' ) );
5959 }
6060 elseif ( $course->getStatus() === 'current' ) {
 61+ $this->setPageTitle( $course );
 62+
6163 $token = '';
6264 $tokenIsValid = $course->getField( 'token' ) === '';
6365
@@ -84,6 +86,8 @@
8587 }
8688 }
8789 else {
 90+ $this->setPageTitle( $course );
 91+
8892 $this->showWarning( wfMessage( 'ep-enroll-course-' . $course->getStatus() ) );
8993 }
9094 }
@@ -100,8 +104,6 @@
101105 protected function showEnrollmentView( EPCourse $course ) {
102106 $this->course = $course;
103107
104 - $this->setPageTitle( $course );
105 -
106108 if ( $this->getUser()->isLoggedIn() ) {
107109 if ( $this->getUser()->isAllowed( 'ep-enroll' ) ) {
108110 $user = $this->getUser();
Index: trunk/extensions/EducationProgram/includes/EPOrgPager.php
@@ -61,10 +61,7 @@
6262 public function getFormattedValue( $name, $value ) {
6363 switch ( $name ) {
6464 case 'name':
65 - $value = Linker::linkKnown(
66 - SpecialPage::getTitleFor( 'Institution', $value ),
67 - htmlspecialchars( $value )
68 - );
 65+ $value = EPOrg::getLinkFor( $value );
6966 break;
7067 case 'country':
7168 $countries = array_flip( EPUtils::getCountryOptions( $this->getLanguage()->getCode() ) );
@@ -149,7 +146,7 @@
150147 'edit',
151148 wfMsgHtml( 'edit' ),
152149 array(),
153 - array( 'wpreturnto' => $this->getTitle()->getText() )
 150+ array( 'wpreturnto' => $this->getTitle()->getFullText() )
154151 );
155152
156153 $links[] = $this->getDeletionLink(
Index: trunk/extensions/EducationProgram/includes/EPRevisionPager.php
@@ -27,24 +27,16 @@
2828 protected $className;
2929
3030 /**
31 - * @since 0.1
32 - * @var string
33 - */
34 - protected $itemPage;
35 -
36 - /**
3731 * Constructor.
3832 *
3933 * @param IContextSource $context
4034 * @param string $className
41 - * @param string $itemPage
4235 * @param array $conds
4336 */
44 - public function __construct( IContextSource $context, $className, $itemPage, array $conds = array() ) {
 37+ public function __construct( IContextSource $context, $className, array $conds = array() ) {
4538 $this->conds = $conds;
4639 $this->context = $context;
4740 $this->className = $className;
48 - $this->itemPage = $itemPage;
4941
5042 $this->mDefaultDirection = true;
5143
@@ -141,14 +133,11 @@
142134
143135 $html = '';
144136
145 - $html .= Html::element(
146 - 'a',
147 - array(
148 - 'href' => SpecialPage::getTitleFor( $this->itemPage, $object->getIdentifier() )->getLocalURL( array(
149 - 'revid' => $revision->getId(),
150 - ) ),
151 - ),
152 - $this->getLanguage()->timeanddate( $revision->getField( 'time' ) )
 137+ $html .= $object->getLink(
 138+ 'view',
 139+ $this->getLanguage()->timeanddate( $revision->getField( 'time' ) ),
 140+ array(),
 141+ array( 'revid' => $revision->getId() )
153142 );
154143
155144 return '<li>' . $html . '</li>';
Index: trunk/extensions/EducationProgram/includes/EPCoursePager.php
@@ -184,7 +184,7 @@
185185 'edit',
186186 wfMsgHtml( 'edit' ),
187187 array(),
188 - array( 'wpreturnto' => $this->getTitle()->getText() )
 188+ array( 'wpreturnto' => $this->getTitle()->getFullText() )
189189 );
190190
191191 $links[] = $this->getDeletionLink(
Index: trunk/extensions/EducationProgram/includes/EPPageObject.php
@@ -15,22 +15,27 @@
1616
1717 protected static $info = array(
1818 'EPCourse' => array(
19 - 'pages' => array(
20 - 'view' => 'Course',
21 - 'edit' => 'EditCourse',
22 - 'history' => 'CourseHistory',
 19+ 'ns' => EP_NS_COURSE,
 20+ 'actions' => array(
 21+ 'view' => false,
 22+ 'edit' => 'ep-course',
 23+ 'history' => false,
 24+ 'enroll' => 'ep-enroll',
2325 ),
2426 'edit-right' => 'ep-course',
2527 'identifier' => 'name',
 28+ 'list' => 'Courses',
2629 ),
2730 'EPOrg' => array(
28 - 'pages' => array(
29 - 'view' => 'Institution',
30 - 'edit' => 'EditInstitution',
31 - 'history' => 'InstitutionHistory',
 31+ 'ns' => EP_NS_INSTITUTION,
 32+ 'actions' => array(
 33+ 'view' => false,
 34+ 'edit' => 'ep-org',
 35+ 'history' => false,
3236 ),
3337 'edit-right' => 'ep-org',
3438 'identifier' => 'name',
 39+ 'list' => 'Institutions',
3540 ),
3641 );
3742
@@ -46,34 +51,53 @@
4752 return self::$info[get_called_class()]['edit-right'];
4853 }
4954
50 - public static function getTitleText( $action = 'view' ) {
51 - return self::$info[get_called_class()]['pages'][$action];
 55+ public function getTitle() {
 56+ return Title::newFromText(
 57+ $this->getIdentifier(),
 58+ self::$info[get_called_class()]['ns']
 59+ );
5260 }
5361
54 - public function getTitle( $action = 'view' ) {
55 - return SpecialPage::getTitleFor( self::getTitleText( $action ), $this->getIdentifier() );
56 - }
57 -
5862 public function getLink( $action = 'view', $html = null, $customAttribs = array(), $query = array() ) {
59 - return Linker::link(
60 - self::getTitle( $action ),
61 - is_null( $html ) ? htmlspecialchars( $this->getIdentifier() ) : $html,
 63+ return self::getLinkFor(
 64+ $this->getIdentifier(),
 65+ $action,
 66+ $html,
6267 $customAttribs,
6368 $query
6469 );
6570 }
6671
67 - public static function getTitleFor( $identifierValue, $action = 'view' ) {
68 - return SpecialPage::getTitleFor( self::getTitleText( $action ), $identifierValue );
 72+ public static function getTitleFor( $identifierValue ) {
 73+ return Title::newFromText(
 74+ $identifierValue,
 75+ self::$info[get_called_class()]['ns']
 76+ );
6977 }
7078
7179 public static function getLinkFor( $identifierValue, $action = 'view', $html = null, $customAttribs = array(), $query = array() ) {
72 - return Linker::link(
 80+ if ( $action !== 'view' ) {
 81+ $query['action'] = $action;
 82+ }
 83+
 84+ return Linker::linkKnown( // Linker has no hook that allows us to figure out if the page actually exists :(
7385 self::getTitleFor( $identifierValue, $action ),
7486 is_null( $html ) ? htmlspecialchars( $identifierValue ) : $html,
7587 $customAttribs,
7688 $query
7789 );
7890 }
 91+
 92+ public static function hasIdentifier( $identifier ) {
 93+ return static::has( array( static::getIdentifierField() => $identifier ) );
 94+ }
 95+
 96+ public static function get( $identifier, $fields = null ) {
 97+ return static::selectRow( $fields, array( static::getIdentifierField() => $identifier ) );
 98+ }
 99+
 100+ public static function getListPage() {
 101+ return self::$info[get_called_class()]['list'];
 102+ }
79103
80104 }
\ No newline at end of file
Index: trunk/extensions/EducationProgram/EducationProgram.i18n.php
@@ -27,6 +27,7 @@
2828 // Tabs
2929 'ep-tab-view' => 'Read',
3030 'ep-tab-edit' => 'Edit',
 31+ 'ep-tab-create' => 'Create',
3132 'ep-tab-history' => 'View history',
3233 'ep-tab-enroll' => 'Enroll',
3334
@@ -278,12 +279,12 @@
279280 'ep-institution-none' => 'There is no institution with name "$1". See [[Special:Institution|here]] for a list of institutions.',
280281 'ep-institution-create' => 'There is no institution with name "$1" yet, but you can create it.',
281282 'ep-institution-title' => 'Institution: $1',
282 - 'specialinstitution-summary-name' => 'Name',
283 - 'specialinstitution-summary-city' => 'City',
284 - 'specialinstitution-summary-country' => 'Country',
285 - 'specialinstitution-summary-status' => 'Status',
286 - 'specialinstitution-summary-courses' => 'Course count',
287 - 'specialinstitution-summary-students' => 'Student count',
 283+ 'vieworgaction-summary-name' => 'Name',
 284+ 'vieworgaction-summary-city' => 'City',
 285+ 'vieworgaction-summary-country' => 'Country',
 286+ 'vieworgaction-summary-status' => 'Status',
 287+ 'vieworgaction-summary-courses' => 'Course count',
 288+ 'vieworgaction-summary-students' => 'Student count',
288289 'ep-institution-nav-edit' => 'Edit this institution',
289290 'ep-institution-add-course' => 'Add a course',
290291 'ep-institution-inactive' => 'Inactive',
@@ -295,14 +296,14 @@
296297 'ep-course-students' => 'Students',
297298 'ep-course-none' => 'There is no course with id "$1". See [[Special:Courses|here]] for a list of courses.',
298299 'ep-course-create' => 'There is no course with id "$1", but you can create a new one.',
299 - 'specialcourse-summary-org' => 'Institution',
300 - 'specialcourse-summary-term' => 'Term',
301 - 'specialcourse-summary-start' => 'Start',
302 - 'specialcourse-summary-end' => 'End',
303 - 'specialcourse-summary-students' => 'Student count',
304 - 'specialcourse-summary-status' => 'Status',
 300+ 'viewcourseaction-summary-org' => 'Institution',
 301+ 'viewcourseaction-summary-term' => 'Term',
 302+ 'viewcourseaction-summary-start' => 'Start',
 303+ 'viewcourseaction-summary-end' => 'End',
 304+ 'viewcourseaction-summary-students' => 'Student count',
 305+ 'viewcourseaction-summary-status' => 'Status',
305306 'ep-course-description' => 'description',
306 - 'specialcourse-summary-token' => 'Enrollment token',
 307+ 'viewcourseaction-summary-token' => 'Enrollment token',
307308 'ep-course-nav-edit' => 'Edit this course',
308309
309310 // Special:Ambassador
Index: trunk/extensions/EducationProgram/EducationProgram.hooks.php
@@ -149,6 +149,63 @@
150150 }
151151
152152 /**
 153+ * Called to determine the class to handle the article rendering, based on title.
 154+ * @see https://www.mediawiki.org/wiki/Manual:Hooks/ArticleFromTitle
 155+ *
 156+ * @since 0.1
 157+ *
 158+ * @param Title $title
 159+ * @param Article|null $article
 160+ *
 161+ * @return true
 162+ */
 163+ public static function onArticleFromTitle( Title &$title, &$article ) {
 164+ if ( $title->getNamespace() == EP_NS_COURSE ) {
 165+ $article = new CoursePage( $title );
 166+ }
 167+ elseif ( $title->getNamespace() == EP_NS_INSTITUTION ) {
 168+ $article = new OrgPage( $title );
 169+ }
 170+
 171+ return true;
 172+ }
 173+
 174+ /**
 175+ * For extensions adding their own namespaces or altering the defaults.
 176+ * @see https://www.mediawiki.org/wiki/Manual:Hooks/CanonicalNamespaces
 177+ *
 178+ * @since 0.1
 179+ *
 180+ * @param array $list
 181+ *
 182+ * @return true
 183+ */
 184+ public static function onCanonicalNamespaces( array &$list ) {
 185+ $list[EP_NS_COURSE] = 'Course';
 186+ $list[EP_NS_INSTITUTION] = 'Institution';
 187+ $list[EP_NS_COURSE_TALK] = 'Course_talk';
 188+ $list[EP_NS_INSTITUTION_TALK] = 'Institution_talk';
 189+ return true;
 190+ }
 191+
 192+ /**
 193+ * Alter the structured navigation links in SkinTemplates.
 194+ * @see https://www.mediawiki.org/wiki/Manual:Hooks/SkinTemplateNavigation
 195+ *
 196+ * @since 0.1
 197+ *
 198+ * @param SkinTemplate $sktemplate
 199+ * @param array $links
 200+ *
 201+ * @return true
 202+ */
 203+ public static function onPageTabs( SkinTemplate &$sktemplate, array &$links ) {
 204+ self::displayTabs( $sktemplate, $links, $sktemplate->getTitle() );
 205+
 206+ return true;
 207+ }
 208+
 209+ /**
153210 * Called on special pages after the special tab is added but before variants have been added.
154211 * @see https://www.mediawiki.org/wiki/Manual:Hooks/SkinTemplateNavigation::SpecialPage
155212 *
@@ -160,106 +217,68 @@
161218 * @return true
162219 */
163220 public static function onSpecialPageTabs( SkinTemplate &$sktemplate, array &$links ) {
164 - $viewLinks = $links['views'];
165 -
166 - // The Title getBaseText and getSubpageText methods only do what we want when
167 - // the special pages NS is in teh list of NS with subpages.
168221 $textParts = SpecialPageFactory::resolveAlias( $sktemplate->getTitle()->getText() );
169 - $baseText = $textParts[0];
170 -
171 - if ( is_null( $textParts[1] ) ) {
172 - return true;
 222+
 223+ if ( $textParts[0] === 'Enroll' ) {
 224+ self::displayTabs( $sktemplate, $links, EPCourse::getTitleFor( $textParts[1] ) );
173225 }
174226
175 - $specials = array(
176 - array(
177 - 'view' => 'Institution',
178 - 'edit' => 'EditInstitution',
179 - 'history' => 'InstitutionHistory',
180 - ),
181 - array(
182 - 'view' => 'Course',
183 - 'edit' => 'EditCourse',
184 - 'history' => 'CourseHistory',
185 - 'enroll' => 'Enroll',
186 - ),
 227+ return true;
 228+ }
 229+
 230+ protected static function displayTabs( SkinTemplate &$sktemplate, array &$links, Title $title ) {
 231+ $classes = array(
 232+ EP_NS_INSTITUTION => 'EPOrg',
 233+ EP_NS_COURSE => 'EPCourse',
187234 );
188 -
189 - $editRights = array(
190 - 'EditInstitution' => 'ep-org',
191 - 'EditCourse' => 'ep-course',
192 - );
193 -
194 - $classes = array(
195 - 'Institution' => 'EPOrg',
196 - 'Course' => 'EPCourse',
197 - );
198 -
199 - $specialSet = false;
200 - $type = false;
201 -
202 - foreach ( $specials as $set ) {
203 - if ( in_array( $baseText, $set ) ) {
204 - $specialSet = $set;
205 - $flipped = array_flip( $set );
206 - $type = $flipped[$baseText];
207 - break;
208 - }
209 - }
210 -
211 - // TODO: messages
212 - if ( $specialSet !== false ) {
213 - $canonicalSet = $specialSet;
214 -
215 - foreach ( $specialSet as &$special ) {
216 - $special = SpecialPageFactory::getLocalNameFor( $special );
217 - }
218 -
219 - $identifier = 'name';
220 - $exists = $classes[$canonicalSet['view']]::has( array( $identifier => $textParts[1] ) );
221 -
222 - $viewLinks['view'] = array(
223 - 'class' => $type === 'view' ? 'selected' : false,
 235+
 236+ if ( array_key_exists( $title->getNamespace(), $classes ) ) {
 237+ // array_intersect_key( $links['views'], array_flip( array( 'view', 'edit', 'history' ) ) );
 238+ $links['views'] = array();
 239+ $links['actions'] = array();
 240+
 241+ $user = $sktemplate->getUser();
 242+ $class = $classes[$title->getNamespace()];
 243+ $exists = $class::hasIdentifier( $title->getText() );
 244+ $type = $sktemplate->getRequest()->getText( 'action' );
 245+ $isSpecial = $sktemplate->getTitle()->isSpecialPage();
 246+
 247+ $links['views']['view'] = array(
 248+ 'class' => ( !$isSpecial && $type === '' ) ? 'selected' : false,
224249 'text' => wfMsg( 'ep-tab-view' ),
225 - 'href' => SpecialPage::getTitleFor( $specialSet['view'], $textParts[1] )->getLocalUrl()
 250+ 'href' => $title->getLocalUrl()
226251 );
227 -
 252+
 253+ if ( $user->isAllowed( $class::getEditRight() ) ) {
 254+ $links['views']['edit'] = array(
 255+ 'class' => $type === 'edit' ? 'selected' : false,
 256+ 'text' => wfMsg( $exists ? 'ep-tab-edit' : 'ep-tab-create' ),
 257+ 'href' => $title->getLocalUrl( array( 'action' => 'edit' ) )
 258+ );
 259+ }
 260+
228261 if ( $exists ) {
229 - if ( $sktemplate->getUser()->isAllowed( $editRights[$canonicalSet['edit']] ) ) {
230 - $viewLinks['edit'] = array(
231 - 'class' => $type === 'edit' ? 'selected' : false,
232 - 'text' => wfMsg( 'ep-tab-edit' ),
233 - 'href' => SpecialPage::getTitleFor( $specialSet['edit'], $textParts[1] )->getLocalUrl()
234 - );
235 - }
236 -
237 - $viewLinks['history'] = array(
 262+ $links['views']['history'] = array(
238263 'class' => $type === 'history' ? 'selected' : false,
239264 'text' => wfMsg( 'ep-tab-history' ),
240 - 'href' => SpecialPage::getTitleFor( $specialSet['history'], $textParts[1] )->getLocalUrl()
 265+ 'href' => $title->getLocalUrl( array( 'action' => 'history' ) )
241266 );
242 -
243 - if ( $canonicalSet['view'] === 'Course' ) {
244 - $user = $sktemplate->getUser();
245 -
 267+
 268+ if ( $title->getNamespace() === EP_NS_COURSE ) {
246269 if ( $user->isAllowed( 'ep-enroll' ) ) {
247270 $student = EPStudent::newFromUser( $user );
248271
249 - if ( $student === false || !$student->hasCourse( array( 'id' => $textParts[1] ) ) ) {
250 - $viewLinks['enroll'] = array(
251 - 'class' => $type === 'enroll' ? 'selected' : false,
 272+ if ( $student === false || !$student->hasCourse( array( 'name' => $title->getText() ) ) ) {
 273+ $links['views']['enroll'] = array(
 274+ 'class' => $isSpecial ? 'selected' : false,
252275 'text' => wfMsg( 'ep-tab-enroll' ),
253 - 'href' => SpecialPage::getTitleFor( 'Enroll', $textParts[1] )->getLocalUrl()
 276+ 'href' => SpecialPage::getTitleFor( 'Enroll', $title->getText() )->getLocalURL()
254277 );
255278 }
256279 }
257280 }
258281 }
259 - }
260 -
261 - $links['views'] = $viewLinks;
262 -
263 - return true;
 282+ }
264283 }
265 -
 284+
266285 }

Follow-up revisions

RevisionCommit summaryAuthorDate
r110233folow up to r110231; kill obsolete special pagesjeroendedauw11:51, 29 January 2012

Comments

#Comment by Nikerabbit (talk | contribs)   05:51, 30 January 2012

Oh boy my eyes are still crossed. I read "orcs and curses".

#Comment by Jeroen De Dauw (talk | contribs)   11:05, 30 January 2012

I want to see the foundation fund writing an extension to do that :p

Status & tagging log