r106673 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r106672‎ | r106673 | r106674 >
Date:19:07, 19 December 2011
Author:jeroendedauw
Status:deferred
Tags:educationprogram 
Comment:
work on special:editCourse and added support for joins to the dbobject class
Modified paths:
  • /trunk/extensions/EducationProgram/EducationProgram.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPDBObject.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPMentor.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPOrg.php (modified) (history)
  • /trunk/extensions/EducationProgram/specials/SpecialEditCourse.php (modified) (history)
  • /trunk/extensions/EducationProgram/specials/SpecialEditInstitution.php (modified) (history)

Diff [purge]

Index: trunk/extensions/EducationProgram/specials/SpecialEditInstitution.php
@@ -48,8 +48,6 @@
4949 },
5050 );
5151
52 - $countries = efEpGetCountries();
53 -
5452 $fields['country'] = array (
5553 'type' => 'select',
5654 'label-message' => 'educationprogram-org-edit-country',
Index: trunk/extensions/EducationProgram/specials/SpecialEditCourse.php
@@ -1 +1,69 @@
22 <?php
 3+
 4+/**
 5+ * Adittion and modification interface for courses.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SpecialEditCourse.php
 10+ * @ingroup EducationProgram
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+class SpecialEditCourse extends SpecialEPFormPage {
 16+
 17+ /**
 18+ * Constructor.
 19+ *
 20+ * @since 0.1
 21+ */
 22+ public function __construct() {
 23+ parent::__construct( 'EditCourse', 'epmentor', 'EPCourse', 'Courses' );
 24+ }
 25+
 26+ /**
 27+ * (non-PHPdoc)
 28+ * @see SpecialEPFormPage::getFormFields()
 29+ * @return array
 30+ */
 31+ protected function getFormFields() {
 32+ $fields = parent::getFormFields();
 33+
 34+ $fields['name'] = array (
 35+ 'type' => 'text',
 36+ 'label-message' => 'ep-course-edit-name',
 37+ 'required' => true,
 38+ 'validation-callback' => function ( $value, array $alldata = null ) {
 39+ return strlen( $value ) < 5 ? wfMsg( 'ep-course-invalid-name' ) : true;
 40+ },
 41+ );
 42+
 43+ $orgOptions = EPOrg::getOrgOptions( EPOrg::getEditableOrgs( $this->getUser() ) );
 44+
 45+ $fields['org'] = array (
 46+ 'type' => 'select',
 47+ 'label-message' => 'ep-course-edit-org',
 48+ 'required' => true,
 49+ 'options' => $orgOptions,
 50+ 'validation-callback' => function ( $value, array $alldata = null ) {
 51+ return strlen( $value ) < 10 ? wfMsg( 'ep-course-invalid-description' ) : true;
 52+ },
 53+ 'default' => array_shift( $orgOptions )
 54+ );
 55+
 56+ $fields['description'] = array (
 57+ 'type' => 'textarea',
 58+ 'label-message' => 'ep-course-edit-description',
 59+ 'required' => true,
 60+ 'validation-callback' => function ( $value, array $alldata = null ) {
 61+ return strlen( $value ) < 10 ? wfMsg( 'ep-course-invalid-description' ) : true;
 62+ },
 63+ 'default' => '',
 64+ 'rows' => 5
 65+ );
 66+
 67+ return $this->processFormFields( $fields );
 68+ }
 69+
 70+}
Index: trunk/extensions/EducationProgram/includes/EPMentor.php
@@ -59,7 +59,12 @@
6060 * @return array of EPOrg
6161 */
6262 public function getOrgs( array $fields = null ) {
63 - return array(); // TODO
 63+ return EPOrg::select(
 64+ $fields,
 65+ array( array( 'ep_mentors_per_org', 'mentor_id' ), $this->getId() ),
 66+ array(),
 67+ array( 'orgs' => array( 'INNER JOIN', array( array( array( 'ep_mentors_per_org', 'org_id' ), array( 'orgs', 'id' ) ) ) ) )
 68+ );
6469 }
6570
6671 /**
Index: trunk/extensions/EducationProgram/includes/EPOrg.php
@@ -59,5 +59,46 @@
6060 'country' => '',
6161 );
6262 }
 63+
 64+ public static function getOrgOptions( array /* EPOrg */ $orgs ) {
 65+ $options = array();
 66+
 67+ foreach ( $orgs as /* EPOrg */ $org ) {
 68+ $options[$org->getField( 'name' )] = $org->getId();
 69+ }
 70+
 71+ return $options;
 72+ }
 73+
 74+ /**
 75+ * Returns the list of orgs that the specified user can edit.
 76+ *
 77+ * @since 0.1
 78+ *
 79+ * @param User|int $user
 80+ * @param array|null $fields
 81+ *
 82+ * @return array of EPOrg
 83+ */
 84+ public static function getEditableOrgs( $user, array $fields = null ) {
 85+ if ( is_int( $user ) ) {
 86+ $userId = $user;
 87+ $user = User::newFromId( $user );
 88+ }
 89+ else {
 90+ $userId = $user->getId();
 91+ }
 92+
 93+ if ( $user->isAllowed( 'epadmin' ) ) {
 94+ return self::select( $fields );
 95+ }
 96+ elseif ( $user->isAllowed( 'epmentor' ) ) {
 97+ $mentor = EPMentor::selectRow( 'id', array( 'user_id' => $userId ) );
 98+ return $mentor === false ? array() : $mentor->getOrgs( $fields );
 99+ }
 100+ else {
 101+ return array();
 102+ }
 103+ }
63104
64105 }
Index: trunk/extensions/EducationProgram/includes/EPDBObject.php
@@ -47,7 +47,13 @@
4848 * @return string
4949 */
5050 public static function getDBTable() {
51 - throw new MWException( 'Class did not implement getDBTable' );
 51+ global $egEPDBObjects;
 52+ if ( array_key_exists( __CLASS__, $egEPDBObjects ) ) {
 53+ return $egEPDBObjects[__CLASS__]['table'];
 54+ }
 55+ else {
 56+ throw new MWException( 'Class "' . __CLASS__ . '" not found in $egEPDBObjects' );
 57+ }
5258 }
5359
5460 /**
@@ -59,7 +65,13 @@
6066 * @return string
6167 */
6268 protected static function getFieldPrefix() {
63 - throw new MWException( 'Class did not implement getFieldPrefix' );
 69+ global $egEPDBObjects;
 70+ if ( array_key_exists( __CLASS__, $egEPDBObjects ) ) {
 71+ return $egEPDBObjects[__CLASS__]['prefix'];
 72+ }
 73+ else {
 74+ throw new MWException( 'Class "' . __CLASS__ . '" not found in $egEPDBObjects' );
 75+ }
6476 }
6577
6678 /**
@@ -515,11 +527,9 @@
516528 *
517529 * @return array
518530 */
519 - public static function getPrefixedFields( $fields ) {
520 - $fields = (array)$fields;
521 -
 531+ public static function getPrefixedFields( array $fields ) {
522532 foreach ( $fields as &$field ) {
523 - $field = static::getFieldPrefix() . $field;
 533+ $field = static::getPrefixedField( $field );
524534 }
525535
526536 return $fields;
@@ -527,21 +537,51 @@
528538
529539 /**
530540 * Takes in a field and returns an it's prefixed version, ready for db usage.
 541+ * If the field needs to be prefixed for another table, provide an array in the form
 542+ * array( 'tablename', 'fieldname' )
 543+ * Where table name is registered in $egEPDBObjects.
531544 *
532545 * @since 0.1
533546 *
534 - * @param string $field
 547+ * @param string|array $field
535548 *
536549 * @return string
 550+ * @throws MWException
537551 */
538552 public static function getPrefixedField( $field ) {
539 - return static::getFieldPrefix() . $field;
 553+ static $prefixes = false;
 554+
 555+ if ( $prefixes === false ) {
 556+ foreach ( $GLOBALS['egEPDBObjects'] as $classOrIndex => $object ) {
 557+ $prefixes[$object['table']] = $object['prefix'];
 558+ }
 559+ }
 560+
 561+ if ( is_array( $field ) && count( $field ) > 1 ) {
 562+ if ( array_key_exists( $field[0], $prefixes ) ) {
 563+ $prefix = $prefixes[$field[0]];
 564+ $field = $field[1];
 565+ }
 566+ else {
 567+ throw new MWException( 'Tried to prefix field with unknown table "' . $field[0] . '"' );
 568+ }
 569+ }
 570+ else {
 571+ $prefix = static::getFieldPrefix();
 572+ }
 573+
 574+ return $prefix . $field;
540575 }
541576
542577 /**
543578 * Takes in an associative array with field names as keys and
544579 * their values as value. The field names are prefixed with the
545580 * db field prefix.
 581+ *
 582+ * Field names can also be provdied as an array with as first element a table name, such as
 583+ * $conditions = array(
 584+ * array( array( 'tablename', 'fieldname' ), $value ),
 585+ * );
546586 *
547587 * @since 0.1
548588 *
@@ -553,7 +593,12 @@
554594 $prefixedValues = array();
555595
556596 foreach ( $values as $field => $value ) {
557 - $prefixedValues[static::getFieldPrefix() . $field] = $value;
 597+ if ( is_integer( $field ) ) {
 598+ $field = $value[0];
 599+ $value = $value[1];
 600+ }
 601+
 602+ $prefixedValues[static::getPrefixedField( $field )] = $value;
558603 }
559604
560605 return $prefixedValues;
@@ -682,18 +727,24 @@
683728 * @param array|string|null $fields
684729 * @param array $conditions
685730 * @param array $options
 731+ * @param array $joinConds
686732 *
687733 * @return array of self
688734 */
689 - public static function select( $fields = null, array $conditions = array(), array $options = array() ) {
 735+ public static function select( $fields = null, array $conditions = array(), array $options = array(), array $joinConds = array() ) {
690736 if ( is_null( $fields ) ) {
691737 $fields = array_keys( static::getFieldTypes() );
692738 }
693739
 740+ $tables = array( static::getDBTable() );
 741+ $joinConds = static::getProcessedJoinConds( $joinConds, $tables );
 742+
694743 $result = static::rawSelect(
695744 static::getPrefixedFields( $fields ),
696745 static::getPrefixedValues( $conditions ),
697 - $options
 746+ $options,
 747+ $joinConds,
 748+ $tables
698749 );
699750
700751 $objects = array();
@@ -704,6 +755,42 @@
705756
706757 return $objects;
707758 }
 759+
 760+ /**
 761+ * Process the join conditions. This includes prefixing table and field names,
 762+ * and adding of needed tables.
 763+ *
 764+ * @since 0.1
 765+ *
 766+ * @param array $joinConds Join conditions without prefixes and fields in array rather then string with equals sign.
 767+ * @param array $tables List of tables to which the extra needed ones get added.
 768+ *
 769+ * @return array Join conditions ready to be fed to MediaWikis native select function.
 770+ */
 771+ protected static function getProcessedJoinConds( array $joinConds, array &$tables ) {
 772+ $conds = array();
 773+
 774+ foreach ( $joinConds as $table => $joinCond ) {
 775+ if ( !in_array( $table, $tables ) ) {
 776+ $tables[] = $table;
 777+ }
 778+
 779+ $cond = array( $joinCond[0], array() );
 780+
 781+ foreach ( $joinCond[1] as $joinCondPart ) {
 782+ $parts = array(
 783+ static::getPrefixedField( $joinCondPart[0] ),
 784+ static::getPrefixedField( $joinCondPart[1] ),
 785+ );
 786+
 787+ $cond[1][] = implode( '=', $parts );
 788+ }
 789+
 790+ $conds = $cond;
 791+ }
 792+
 793+ return $conds;
 794+ }
708795
709796 /**
710797 * Selects the the specified fields of the first matching record.
@@ -769,18 +856,24 @@
770857 * @param array|null $fields
771858 * @param array $conditions
772859 * @param array $options
 860+ * @param array $joinConds
773861 *
774862 * @return ResultWrapper
775863 */
776 - public static function rawSelect( $fields = null, array $conditions = array(), array $options = array() ) {
 864+ public static function rawSelect( $fields = null, array $conditions = array(), array $options = array(), array $joinConds = array(), array $tables = null ) {
 865+ if ( is_null( $tables ) ) {
 866+ $tables = static::getDBTable();
 867+ }
 868+
777869 $dbr = wfGetDB( static::getReadDb() );
778870
779871 return $dbr->select(
780 - static::getDBTable(),
 872+ $tables,
781873 $fields,
782874 count( $conditions ) == 0 ? '' : $conditions,
783875 __METHOD__,
784 - $options
 876+ $options,
 877+ $joinConds
785878 );
786879 }
787880
Index: trunk/extensions/EducationProgram/EducationProgram.php
@@ -106,6 +106,16 @@
107107 $wgSpecialPageGroups['EditInstitution'] = 'education';
108108 $wgSpecialPageGroups['EditTerm'] = 'education';
109109
 110+// DB object classes
 111+$egEPDBObjects = array();
 112+$egEPDBObjects['EPOrg'] = array( 'table' => 'ep_orgs', 'prefix' => 'org_' );
 113+$egEPDBObjects['EPCourse'] = array( 'table' => 'ep_courses', 'prefix' => 'course_' );
 114+$egEPDBObjects['EPTerm'] = array( 'table' => 'ep_terms', 'prefix' => 'term_' );
 115+$egEPDBObjects['EPMentor'] = array( 'table' => 'ep_mentors', 'prefix' => 'mentor_' );
 116+$egEPDBObjects['EPStudent'] = array( 'table' => 'ep_students', 'prefix' => 'student_' );
 117+$egEPDBObjects[] = array( 'table' => 'ep_students_per_term', 'prefix' => 'spt_' );
 118+$egEPDBObjects[] = array( 'table' => 'ep_mentors_per_org', 'prefix' => 'mpo_' );
 119+
110120 // API
111121
112122

Follow-up revisions

RevisionCommit summaryAuthorDate
r106678Follow up to r106673; added messagesjeroendedauw19:56, 19 December 2011
r106680Follow up to r106673; rem dead code and fix obtaining of caller class name, w...jeroendedauw20:08, 19 December 2011

Status & tagging log