r107619 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r107618‎ | r107619 | r107620 >
Date:02:00, 30 December 2011
Author:jeroendedauw
Status:deferred
Tags:educationprogram 
Comment:
added multi item action thing to pagers and work on enrollment flow
Modified paths:
  • /trunk/extensions/EducationProgram/EducationProgram.i18n.php (modified) (history)
  • /trunk/extensions/EducationProgram/EducationProgram.php (modified) (history)
  • /trunk/extensions/EducationProgram/api/ApiDeleteEducation.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPDBObject.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPPager.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPStudent.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPTerm.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPTermPager.php (modified) (history)
  • /trunk/extensions/EducationProgram/resources/ep.api.js (modified) (history)
  • /trunk/extensions/EducationProgram/resources/ep.pager.css (added) (history)
  • /trunk/extensions/EducationProgram/resources/ep.pager.js (modified) (history)
  • /trunk/extensions/EducationProgram/specials/SpecialEPFormPage.php (modified) (history)
  • /trunk/extensions/EducationProgram/specials/SpecialEnroll.php (modified) (history)

Diff [purge]

Index: trunk/extensions/EducationProgram/specials/SpecialEnroll.php
@@ -14,6 +14,12 @@
1515 class SpecialEnroll extends SpecialEPPage {
1616
1717 /**
 18+ * @since 0.1
 19+ * @var EPTerm
 20+ */
 21+ protected $term;
 22+
 23+ /**
1824 * Constructor.
1925 *
2026 * @since 0.1
@@ -51,9 +57,13 @@
5258 $this->showWarning( wfMessage( 'ep-enroll-invalid-token' ) );
5359 }
5460 else {
 61+ $this->term = $term;
 62+
 63+ $this->setPageTitle( $term );
 64+
5565 if ( $this->getUser()->isLoggedIn() ) {
5666 if ( $this->getUser()->isAllowed( 'epstudent' ) ) {
57 - $this->showEntrollmentForm( $term );
 67+ $this->showEnrollmentForm( $term );
5868 }
5969 else {
6070 $this->showWarning( wfMessage( 'ep-enroll-not-allowed' ) );
@@ -64,10 +74,25 @@
6575 }
6676 }
6777 }
68 -
6978 }
7079
7180 /**
 81+ *
 82+ *
 83+ * @since 0.1
 84+ *
 85+ * @param EPTerm $term
 86+ */
 87+ protected function setPageTitle( EPTerm $term ) {
 88+ $this->getOutput()->setPageTitle( wfMsgExt(
 89+ 'ep-enroll-title',
 90+ 'parsemag',
 91+ $term->getCourse( 'name' )->getField( 'name' ),
 92+ $term->getOrg( 'name' )->getField( 'name' )
 93+ ) );
 94+ }
 95+
 96+ /**
7297 *
7398 *
7499 * @param EPTerm $term
@@ -78,18 +103,22 @@
79104 $out = $this->getOutput();
80105
81106 $out->addWikiMsg( 'ep-enroll-login-first' );
82 -
 107+
 108+ $out->addHTML( '<ul><li>' );
 109+
83110 $out->addHTML( Linker::linkKnown(
84 - SpecialPage::getTitleFor( 'UserLogin' ),
 111+ SpecialPage::getTitleFor( 'Userlogin' ),
85112 wfMsgHtml( 'ep-enroll-login-and-entroll' ),
86113 array(),
87114 array(
88115 'returnto' => $this->getTitle( $this->subPage )->getFullText()
89116 )
90117 ) );
91 -
 118+
 119+ $out->addHTML( '</li><li>' );
 120+
92121 $out->addHTML( Linker::linkKnown(
93 - SpecialPage::getTitleFor( 'UserLogin' ),
 122+ SpecialPage::getTitleFor( 'Userlogin' ),
94123 wfMsgHtml( 'ep-enroll-signup-and-entroll' ),
95124 array(),
96125 array(
@@ -97,6 +126,8 @@
98127 'type' => 'signup'
99128 )
100129 ) );
 130+
 131+ $out->addHTML( '</li></ul>' );
101132 }
102133
103134 /**
@@ -106,8 +137,80 @@
107138 *
108139 * @param EPTerm $term
109140 */
110 - protected function showEntrollmentForm( EPTerm $term ) {
111 -
 141+ protected function showEnrollmentForm( EPTerm $term ) {
 142+ $form = new HTMLForm( $this->getFormFields(), $this->getContext() );
 143+
 144+ $form->setSubmitCallback( array( $this, 'handleSubmission' ) );
 145+ $form->setSubmitText( wfMsg( 'educationprogram-org-submit' ) );
 146+ $form->setWrapperLegend( $this->msg( 'ep-enroll-legend' ) );
 147+
 148+ if ( $form->show() ) {
 149+ $this->onSuccess();
 150+ }
112151 }
113152
 153+ /**
 154+ *
 155+ *
 156+ * @since 0.1
 157+ *
 158+ * @return array
 159+ */
 160+ protected function getFormFields() {
 161+ $fields = array();
 162+
 163+ $fields['enroll'] = array(
 164+ 'type' => 'hidden',
 165+ 'default' => 1
 166+ );
 167+
 168+ return $fields;
 169+ }
 170+
 171+ /**
 172+ * Process the form. At this point we know that the user passes all the criteria in
 173+ * userCanExecute().
 174+ *
 175+ * @param array $data
 176+ *
 177+ * @return Bool|Array
 178+ */
 179+ public function handleSubmission( array $data ) {
 180+ $student = EPStudent::newFromUser( $this->getUser(), array( 'id' ) );
 181+
 182+ if ( $student === false ) {
 183+ $student = new EPStudent( array( 'user_id' => $this->getUser()->getId() ), true );
 184+ }
 185+
 186+ $fields = array(); // TODO
 187+
 188+ $student->setFields( $fields );
 189+
 190+ $success = $student->writeToDB();
 191+
 192+ if ( $success ) {//q($this->term);
 193+ $success = $student->associateWithTerms( array( $this->term ) ) && $success;
 194+ }
 195+
 196+ if ( $success ) {
 197+ return true;
 198+ }
 199+ else {
 200+ return array(); // TODO
 201+ }
 202+ }
 203+
 204+ /**
 205+ * Gets called after the form is saved.
 206+ *
 207+ * @since 0.1
 208+ */
 209+ public function onSuccess() {
 210+ $this->getOutput()->redirect(
 211+ SpecialPage::getTitleFor( 'MyCourses' )->getLocalURL( array(
 212+ 'enrolled' => 1
 213+ ) )
 214+ );
 215+ }
 216+
114217 }
Index: trunk/extensions/EducationProgram/specials/SpecialEPFormPage.php
@@ -304,8 +304,7 @@
305305
306306 /**
307307 * Process the form. At this point we know that the user passes all the criteria in
308 - * userCanExecute(), and if the data array contains 'Username', etc, then Username
309 - * resets are allowed.
 308+ * userCanExecute().
310309 *
311310 * @param array $data
312311 *
Index: trunk/extensions/EducationProgram/includes/EPStudent.php
@@ -40,5 +40,36 @@
4141 public static function newFromUser( User $user, $fields = null ) {
4242 return self::selectRow( $fields, array( 'user_id' => $user->getId() ) );
4343 }
 44+
 45+ /**
 46+ * Associate the student with the provided terms.
 47+ *
 48+ * @since 0.1
 49+ *
 50+ * @param array $terms
 51+ *
 52+ * @return bool
 53+ */
 54+ public function associateWithTerms( array /* of EPTerm */ $terms ) {
 55+ $dbw = wfGetDB( DB_MASTER );
 56+
 57+ $success = true;
 58+
 59+ $dbw->begin();
 60+
 61+ foreach ( $terms as /* EPTerm */ $term ) {
 62+ $success = $dbw->insert(
 63+ 'ep_students_per_term',
 64+ array(
 65+ 'spt_student_id' => $this->getId(),
 66+ 'spt_term_id' => $term->getId(),
 67+ )
 68+ ) && $success;
 69+ }
 70+
 71+ $dbw->commit();
 72+
 73+ return $success;
 74+ }
4475
4576 }
Index: trunk/extensions/EducationProgram/includes/EPTermPager.php
@@ -151,5 +151,15 @@
152152
153153 return $links;
154154 }
 155+
 156+ /**
 157+ * (non-PHPdoc)
 158+ * @see EPPager::getMultipleItemActions()
 159+ */
 160+ protected function getMultipleItemActions() {
 161+ $actions = parent::getMultipleItemActions();
155162
 163+ return $actions;
 164+ }
 165+
156166 }
Index: trunk/extensions/EducationProgram/includes/EPTerm.php
@@ -144,7 +144,8 @@
145145 $pager->getFilterControl() .
146146 $pager->getNavigationBar() .
147147 $pager->getBody() .
148 - $pager->getNavigationBar()
 148+ $pager->getNavigationBar() .
 149+ $pager->getMultipleItemControl()
149150 );
150151 }
151152 else {
Index: trunk/extensions/EducationProgram/includes/EPDBObject.php
@@ -580,7 +580,7 @@
581581 *
582582 * Field names can also be provdied as an array with as first element a table name, such as
583583 * $conditions = array(
584 - * array( array( 'tablename', 'fieldname' ), $value ),
 584+ * array( array( 'tablename', 'fieldname' ), $value ),
585585 * );
586586 *
587587 * @since 0.1
Index: trunk/extensions/EducationProgram/includes/EPPager.php
@@ -138,7 +138,20 @@
139139 $fields = $this->getFieldNames();
140140
141141 foreach ( $this->getFieldNames() as $field => $name ) {
142 - if ( $field === 0 ) {
 142+ if ( $field === '_select' ) {
 143+ $value = Html::element(
 144+ 'input',
 145+ array(
 146+ 'type' => 'checkbox',
 147+ 'value' => $this->currentObject->getId(),
 148+ 'id' => 'select-' . $this->getInstanceNumber() . '-' . $this->currentObject->getId(),
 149+ 'name' => 'epitemsselected',
 150+ 'class' => 'ep-select-item',
 151+ 'data-pager-id' => $this->getInstanceNumber(),
 152+ )
 153+ );
 154+ }
 155+ elseif ( $field === '_controls' ) {
143156 $value = $this->getLanguage()->pipeList( $this->getControlLinks( $this->currentObject ) );
144157 }
145158 else {
@@ -183,12 +196,88 @@
184197 } );
185198
186199 $fields = $this->getFieldNameList( $fields );
187 - $fields[0] = ''; // This is a hack to get an extra colum for the control links.
188200
 201+ if ( $this->hasMultipleItemControl() ) {
 202+ // This is a hack to get an extra colum for select all control.
 203+ $fields = array_merge( array( '_select' => '' ), $fields );
 204+ }
 205+
 206+ $fields['_controls'] = ''; // This is a hack to get an extra colum for the control links.
 207+
189208 return $fields;
190209 }
191210
192211 /**
 212+ * Returns HTML for the multiple item control.
 213+ * With actions comming from @see getMultipleItemActions.
 214+ *
 215+ * @since 0.1
 216+ *
 217+ * @return string
 218+ */
 219+ public function getMultipleItemControl() {
 220+ if ( !$this->hasMultipleItemControl() ) {
 221+ return '';
 222+ }
 223+
 224+ $controls = array();
 225+
 226+ foreach ( $this->getMultipleItemActions() as $label => $attribs ) {
 227+ if ( array_key_exists( 'class', $attribs ) ) {
 228+ $attribs['class'] .= ' ep-pager-items-action';
 229+ }
 230+ else {
 231+ $attribs['class'] = 'ep-pager-items-action';
 232+ }
 233+
 234+ $attribs['data-pager-id'] = $this->getInstanceNumber();
 235+
 236+ $controls[] = Html::element(
 237+ 'button',
 238+ $attribs,
 239+ $label
 240+ );
 241+ }
 242+
 243+ return
 244+ '<fieldset>' .
 245+ '<legend>' . wfMsgHtml( 'ep-pager-withselected' ) . '</legend>' .
 246+ implode( '', $controls ) .
 247+ '</fieldset>';
 248+ }
 249+
 250+ /**
 251+ * Return the multiple item actions the current user can do.
 252+ * Override in deriving classes to add actions.
 253+ *
 254+ * @since 0.1
 255+ *
 256+ * @return array
 257+ */
 258+ protected function getMultipleItemActions() {
 259+ $actions = array();
 260+
 261+ if ( $this->getUser()->isAllowed( 'epadmin' ) ) {
 262+ $actions[wfMsg( 'ep-pager-delete-selected' )] = array(
 263+ 'class' => 'ep-pager-delete-selected',
 264+ 'data-type' => ApiDeleteEducation::getTypeForClassName( $this->className )
 265+ );
 266+ }
 267+
 268+ return $actions;
 269+ }
 270+
 271+ /**
 272+ *
 273+ * @since 0.1
 274+ *
 275+ * @return boolean
 276+ */
 277+ protected function hasMultipleItemControl() {
 278+ return count( $this->getMultipleItemActions() ) > 0;
 279+ }
 280+
 281+ /**
193282 * Returns the fields to display.
194283 * Similar to @see getFieldNames, but fields should not be prefixed, and
195284 * non-relevant fields will be removed.
@@ -262,8 +351,9 @@
263352 $headers = array();
264353 $c = $this->className;
265354
266 - foreach ( $fields as $fieldName ) {
267 - $headers[$c::getPrefixedField( $fieldName )] = $this->getMsg( 'header-' . $fieldName );
 355+ foreach ( $fields as $fieldName => $fieldLabel ) {
 356+ $message = $fieldLabel === '' ? '' : $this->getMsg( 'header-' . $fieldLabel );
 357+ $headers[$c::getPrefixedField( $fieldLabel )] = $message;
268358 }
269359
270360 return $headers;
@@ -465,4 +555,79 @@
466556 );
467557 }
468558
 559+ /**
 560+ * (non-PHPdoc)
 561+ * @see TablePager::getStartBody()
 562+ *
 563+ * Mostly just a copy of parent class function.
 564+ * Allows for having a checlbox in the selection column header.
 565+ * Would obviously be better if parent class supported doing this nicer.
 566+ */
 567+ function getStartBody() {
 568+ global $wgStylePath;
 569+ $tableClass = htmlspecialchars( $this->getTableClass() );
 570+ $sortClass = htmlspecialchars( $this->getSortHeaderClass() );
 571+
 572+ $s = "<table style='border:1;' class=\"mw-datatable $tableClass\"><thead><tr>\n";
 573+ $fields = $this->getFieldNames();
 574+
 575+ # Make table header
 576+ foreach ( $fields as $field => $name ) {
 577+ if ( $field === '_select' ) {
 578+ $s .= '<th>' . Html::element( 'input', array(
 579+ 'type' => 'checkbox',
 580+ 'name' => 'ep-pager-select-all-' . $this->getInstanceNumber(),
 581+ 'id' => 'ep-pager-select-all-' . $this->getInstanceNumber(),
 582+ 'class' => 'ep-pager-select-all',
 583+ ) ) . "</th>\n";
 584+ }
 585+ elseif ( strval( $name ) == '' ) {
 586+ $s .= "<th>&#160;</th>\n";
 587+ } elseif ( $this->isFieldSortable( $field ) ) {
 588+ $query = array( 'sort' => $field, 'limit' => $this->mLimit );
 589+ if ( $field == $this->mSort ) {
 590+ # This is the sorted column
 591+ # Prepare a link that goes in the other sort order
 592+ if ( $this->mDefaultDirection ) {
 593+ # Descending
 594+ $image = 'Arr_d.png';
 595+ $query['asc'] = '1';
 596+ $query['desc'] = '';
 597+ $alt = htmlspecialchars( wfMsg( 'descending_abbrev' ) );
 598+ } else {
 599+ # Ascending
 600+ $image = 'Arr_u.png';
 601+ $query['asc'] = '';
 602+ $query['desc'] = '1';
 603+ $alt = htmlspecialchars( wfMsg( 'ascending_abbrev' ) );
 604+ }
 605+ $image = htmlspecialchars( "$wgStylePath/common/images/$image" );
 606+ $link = $this->makeLink(
 607+ "<img width=\"12\" height=\"12\" alt=\"$alt\" src=\"$image\" />" .
 608+ htmlspecialchars( $name ), $query );
 609+ $s .= "<th class=\"$sortClass\">$link</th>\n";
 610+ } else {
 611+ $s .= '<th>' . $this->makeLink( htmlspecialchars( $name ), $query ) . "</th>\n";
 612+ }
 613+ }
 614+ else {
 615+ $s .= '<th>' . htmlspecialchars( $name ) . "</th>\n";
 616+ }
 617+ }
 618+ $s .= "</tr></thead><tbody>\n";
 619+ return $s;
 620+ }
 621+
 622+ protected $instanceNumber = null;
 623+
 624+ protected function getInstanceNumber() {
 625+ static $instanceCount = 0;
 626+
 627+ if ( is_null( $this->instanceNumber ) ) {
 628+ $this->instanceNumber = $instanceCount++;
 629+ }
 630+
 631+ return $this->instanceNumber;
 632+ }
 633+
469634 }
Index: trunk/extensions/EducationProgram/EducationProgram.i18n.php
@@ -97,6 +97,8 @@
9898 'ep-pager-showonly' => 'Show only items with',
9999 'ep-pager-clear' => 'Clear filters',
100100 'ep-pager-go' => 'Go',
 101+ 'ep-pager-withselected' => 'With selected',
 102+ 'ep-pager-delete-selected' => 'Delete',
101103
102104 // Org pager
103105 'eporgpager-header-name' => 'Name',
@@ -155,6 +157,8 @@
156158 // ep.pager
157159 'ep-pager-confirm-delete' => 'Are you sure you want to delete this item?',
158160 'ep-pager-delete-fail' => 'Could not delete this item.',
 161+ 'ep-pager-confirm-delete-selected' => 'Are you sure you want to delete the selected items?',
 162+ 'ep-pager-delete-selected-fail' => 'Could not delete the selected items.',
159163
160164 // Special:Institution
161165 'ep-institution-none' => 'There is no institution with name "$1". See [[Special:Institution|here]] for a list of institutions.',
@@ -191,6 +195,7 @@
192196 'ep-term-nav-edit' => 'Edit this term',
193197
194198 // Special:Enroll
 199+ 'ep-enroll-title' => 'Enroll for $1 at $2',
195200 'ep-enroll-login-first' => 'Before you can enroll in this course, you need to login.',
196201 'ep-enroll-login-and-entroll' => 'Login with an existing account & enroll',
197202 'ep-enroll-signup-and-entroll' => 'Create a new account & enroll',
@@ -199,6 +204,7 @@
200205 'ep-enroll-no-id' => 'You need to specify a term to enroll for. A list of existing terms can be found [[Special:Terms|here]].',
201206 'ep-enroll-no-token' => 'You need to provide the token needed to enroll for this term.',
202207 'ep-enroll-invalid-token' => 'The token you provided is invalid.',
 208+ 'ep-enroll-legend' => 'Enroll',
203209
204210 // Navigation links
205211 'ep-nav-orgs' => 'Institution list',
Index: trunk/extensions/EducationProgram/EducationProgram.php
@@ -182,12 +182,17 @@
183183 'scripts' => array(
184184 'ep.pager.js',
185185 ),
 186+ 'styles' => array(
 187+ 'ep.pager.css',
 188+ ),
186189 'dependencies' => array(
187190 'ep.api',
188191 ),
189192 'messages' => array(
190193 'ep-pager-confirm-delete',
191194 'ep-pager-delete-fail',
 195+ 'ep-pager-confirm-delete-selected',
 196+ 'ep-pager-delete-selected-fail',
192197 ),
193198 );
194199
Index: trunk/extensions/EducationProgram/api/ApiDeleteEducation.php
@@ -21,6 +21,16 @@
2222 'student' => 'EPStudent',
2323 'mentor' => 'EPMentor',
2424 );
 25+
 26+ public static function getTypeForClassName( $className ) {
 27+ static $map = null;
 28+
 29+ if ( is_null( $map ) ) {
 30+ $map = array_flip( self::$typeMap );
 31+ }
 32+
 33+ return $map[$className];
 34+ }
2535
2636 public function execute() {
2737 $params = $this->extractRequestParams();
Index: trunk/extensions/EducationProgram/resources/ep.api.js
@@ -14,8 +14,8 @@
1515 var requestArgs = {
1616 'action': 'deleteeducation',
1717 'format': 'json',
18 - 'token': mw.user.tokens.get( 'editToken' ),
19 - 'ids': data.id,
 18+ 'token': window.mw.user.tokens.get( 'editToken' ),
 19+ 'ids': data.ids.join( '|' ),
2020 'type': data.type
2121 };
2222
Index: trunk/extensions/EducationProgram/resources/ep.pager.css
@@ -0,0 +1,11 @@
 2+/**
 3+ * CSS for the Education Program MediaWiki extension.
 4+ * @see https://www.mediawiki.org/wiki/Extension:Education_Program
 5+ *
 6+ * @licence GNU GPL v3 or later
 7+ * @author Jeroen De Dauw <jeroendedauw at gmail dot com>
 8+ */
 9+
 10+td .TablePager_col__select {
 11+
 12+}
\ No newline at end of file
Index: trunk/extensions/EducationProgram/resources/ep.pager.js
@@ -24,7 +24,7 @@
2525 ep.api.remove(
2626 {
2727 'type': $this.attr( 'data-type' ),
28 - 'id': $this.attr( 'data-id' )
 28+ 'ids': [ $this.attr( 'data-id' ) ]
2929 },
3030 function( result ) {
3131 if ( result.success ) {
@@ -48,6 +48,47 @@
4949 }
5050 } );
5151
 52+ $( '.ep-pager-select-all' ).change( function() {
 53+ var a = $( this ).closest( 'table' ).find( 'input:checkbox' ).prop( 'checked', $( this ).is( ':checked' ) );
 54+ } );
 55+
 56+ $( '.ep-pager-delete-selected' ).click( function() {
 57+ var selectAllCheckbox = $( '#ep-pager-select-all-' + $( this ).attr( 'data-pager-id' ) );
 58+
 59+ var ids = [];
 60+
 61+ selectAllCheckbox.closest( 'table' ).find( 'input[type=checkbox]:checked' ).each( function( i, element ) {
 62+ ids.push( $( element ).val() );
 63+ } );
 64+
 65+ if ( ids.length < 1 || !confirm( mw.msg( 'ep-pager-confirm-delete-selected' ) ) ) {
 66+ return;
 67+ }
 68+
 69+ var pagerId = $( this ).attr( 'data-pager-id' );
 70+
 71+ ep.api.remove(
 72+ {
 73+ 'type': $( this ).attr( 'data-type' ),
 74+ 'ids': ids
 75+ },
 76+ function( result ) {
 77+ if ( result.success ) {
 78+ for ( i in ids ) {
 79+ if ( ids.hasOwnProperty( i ) ) {
 80+ console.log('#select-' + pagerId + '-' + ids[i]);
 81+ console.log($( '#select-' + pagerId + '-' + ids[i] ));
 82+ $( '#select-' + pagerId + '-' + ids[i] ).closest( 'tr' ).remove();
 83+ }
 84+ }
 85+ }
 86+ else {
 87+ alert( mw.msg( 'ep-pager-delete-selected-fail' ) ); // TODO
 88+ }
 89+ }
 90+ );
 91+ } );
 92+
5293 } );
5394
5495 })( window.jQuery, window.mediaWiki, window.educationProgram );
\ No newline at end of file

Status & tagging log