| Index: trunk/extensions/EducationProgram/sql/AddExtraFields.sql |
| — | — | @@ -5,10 +5,12 @@ |
| 6 | 6 | |
| 7 | 7 | ALTER TABLE /*_*/ep_orgs ADD COLUMN org_courses SMALLINT unsigned NOT NULL; |
| 8 | 8 | ALTER TABLE /*_*/ep_orgs ADD COLUMN org_mentors SMALLINT unsigned NOT NULL; |
| | 9 | +ALTER TABLE /*_*/ep_orgs ADD COLUMN org_terms SMALLINT unsigned NOT NULL; |
| 9 | 10 | ALTER TABLE /*_*/ep_orgs ADD COLUMN org_students INT unsigned NOT NULL; |
| 10 | 11 | |
| 11 | 12 | CREATE INDEX /*i*/ep_org_courses ON /*_*/ep_orgs (org_courses); |
| 12 | 13 | CREATE INDEX /*i*/ep_org_mentors ON /*_*/ep_orgs (org_mentors); |
| | 14 | +CREATE INDEX /*i*/ep_org_terms ON /*_*/ep_orgs (org_terms); |
| 13 | 15 | CREATE INDEX /*i*/ep_org_students ON /*_*/ep_orgs (org_students); |
| 14 | 16 | |
| 15 | 17 | ALTER TABLE /*_*/ep_courses ADD COLUMN course_lang VARCHAR(10) NOT NULL; |
| Index: trunk/extensions/EducationProgram/sql/EducationProgram.sql |
| — | — | @@ -11,11 +11,13 @@ |
| 12 | 12 | org_country VARCHAR(255) NOT NULL, -- Name of the country where the org is located |
| 13 | 13 | |
| 14 | 14 | org_courses SMALLINT unsigned NOT NULL, -- Amount of courses |
| | 15 | + org_terms SMALLINT unsigned NOT NULL, -- Amount of terms |
| 15 | 16 | org_mentors SMALLINT unsigned NOT NULL, -- Amount of mentors |
| 16 | 17 | org_students INT unsigned NOT NULL -- Amount of students |
| 17 | 18 | ) /*$wgDBTableOptions*/; |
| 18 | 19 | |
| 19 | 20 | CREATE UNIQUE INDEX /*i*/ep_org_name ON /*_*/ep_orgs (org_name); |
| | 21 | +CREATE INDEX /*i*/ep_org_terms ON /*_*/ep_orgs (org_terms); |
| 20 | 22 | CREATE INDEX /*i*/ep_org_courses ON /*_*/ep_orgs (org_courses); |
| 21 | 23 | CREATE INDEX /*i*/ep_org_mentors ON /*_*/ep_orgs (org_mentors); |
| 22 | 24 | CREATE INDEX /*i*/ep_org_students ON /*_*/ep_orgs (org_students); |
| Index: trunk/extensions/EducationProgram/includes/EPOrgPager.php |
| — | — | @@ -32,6 +32,10 @@ |
| 33 | 33 | 'name', |
| 34 | 34 | 'city', |
| 35 | 35 | 'country', |
| | 36 | + 'courses', |
| | 37 | + 'terms', |
| | 38 | + 'mentors', |
| | 39 | + 'students', |
| 36 | 40 | ); |
| 37 | 41 | } |
| 38 | 42 | |
| — | — | @@ -65,8 +69,11 @@ |
| 66 | 70 | break; |
| 67 | 71 | case 'country': |
| 68 | 72 | $countries = array_flip( efEpGetCountryOptions( $this->getLanguage()->getCode() ) ); |
| 69 | | - $value = $countries[$value]; |
| | 73 | + $value = htmlspecialchars( $countries[$value] ); |
| 70 | 74 | break; |
| | 75 | + case 'courses': case 'mentors': case 'students': case 'terms': |
| | 76 | + $value = htmlspecialchars( $this->getLanguage()->formatNum( $value ) ); |
| | 77 | + break; |
| 71 | 78 | } |
| 72 | 79 | |
| 73 | 80 | return $value; |
| — | — | @@ -81,6 +88,11 @@ |
| 82 | 89 | 'name', |
| 83 | 90 | 'city', |
| 84 | 91 | 'country', |
| | 92 | + 'courses', |
| | 93 | + 'mentors', |
| | 94 | + 'students', |
| | 95 | + 'terms', |
| | 96 | + 'terms', |
| 85 | 97 | ); |
| 86 | 98 | } |
| 87 | 99 | |
| Index: trunk/extensions/EducationProgram/includes/EPStudent.php |
| — | — | @@ -32,6 +32,11 @@ |
| 33 | 33 | return array( |
| 34 | 34 | 'id' => 'id', |
| 35 | 35 | 'user_id' => 'id', |
| | 36 | + |
| | 37 | + 'first_enroll' => 'str', // TS_MW |
| | 38 | + |
| | 39 | + 'last_active' => 'str', // TS_MW |
| | 40 | + 'active_enroll' => 'bool', |
| 36 | 41 | ); |
| 37 | 42 | } |
| 38 | 43 | |
| Index: trunk/extensions/EducationProgram/includes/EPOrg.php |
| — | — | @@ -43,6 +43,11 @@ |
| 44 | 44 | 'name' => 'str', |
| 45 | 45 | 'city' => 'str', |
| 46 | 46 | 'country' => 'str', |
| | 47 | + |
| | 48 | + 'courses' => 'int', |
| | 49 | + 'terms' => 'int', |
| | 50 | + 'mentors' => 'int', |
| | 51 | + 'students' => 'int', |
| 47 | 52 | ); |
| 48 | 53 | } |
| 49 | 54 | |
| — | — | @@ -55,8 +60,62 @@ |
| 56 | 61 | 'name' => '', |
| 57 | 62 | 'city' => '', |
| 58 | 63 | 'country' => '', |
| | 64 | + |
| | 65 | + 'courses' => 0, |
| | 66 | + 'terms' => 0, |
| | 67 | + 'mentors' => 0, |
| | 68 | + 'students' => 0, |
| 59 | 69 | ); |
| 60 | 70 | } |
| | 71 | + |
| | 72 | + /** |
| | 73 | + * (non-PHPdoc) |
| | 74 | + * @see EPDBObject::loadSummaryFields() |
| | 75 | + */ |
| | 76 | + public function loadSummaryFields( $summaryFields = null ) { |
| | 77 | + if ( is_null( $summaryFields ) ) { |
| | 78 | + $summaryFields = array( 'courses', 'terms', 'mentors', 'students' ); |
| | 79 | + } |
| | 80 | + else { |
| | 81 | + $summaryFields = (array)$summaryFields; |
| | 82 | + } |
| | 83 | + |
| | 84 | + $fields = array(); |
| | 85 | + |
| | 86 | + if ( in_array( 'courses', $summaryFields ) ) { |
| | 87 | + $fields['courses'] = EPCourse::count( array( 'org_id' => $this->getId() ) ); |
| | 88 | + } |
| | 89 | + |
| | 90 | + if ( in_array( 'terms', $summaryFields ) ) { |
| | 91 | + $fields['terms'] = EPTerm::count( array( 'org_id' => $this->getId() ) ); |
| | 92 | + } |
| | 93 | + |
| | 94 | + $dbr = wfGetDB( DB_SLAVE ); |
| | 95 | + |
| | 96 | + if ( in_array( 'mentors', $summaryFields ) ) { |
| | 97 | + $fields['mentors'] = $dbr->select( |
| | 98 | + 'ep_mentors_per_org', |
| | 99 | + 'COUNT(*) AS rowcount', |
| | 100 | + array( 'mpo_org_id' => $this->getId() ) |
| | 101 | + ); |
| | 102 | + |
| | 103 | + $fields['mentors'] = $fields['mentors']->rowcount; |
| | 104 | + } |
| | 105 | + |
| | 106 | + if ( in_array( 'students', $summaryFields ) ) { |
| | 107 | + $termIds = EPTerm::selectFields( 'id', array( 'org_id' => $this->getId() ) ); |
| | 108 | + |
| | 109 | + $fields['students'] = $dbr->select( |
| | 110 | + 'ep_students_per_term', |
| | 111 | + 'COUNT(*) AS rowcount', |
| | 112 | + array( 'spt_term_id' => $termIds ) |
| | 113 | + ); |
| | 114 | + |
| | 115 | + $fields['students'] = $fields['students']->rowcount; |
| | 116 | + } |
| | 117 | + |
| | 118 | + $this->setFields( $fields ); |
| | 119 | + } |
| 61 | 120 | |
| 62 | 121 | /** |
| 63 | 122 | * (non-PHPdoc) |
| Index: trunk/extensions/EducationProgram/includes/EPTerm.php |
| — | — | @@ -74,6 +74,8 @@ |
| 75 | 75 | $this->setField( 'org_id', $this->getCourse( 'org_id' )->getField( 'org_id' ) ); |
| 76 | 76 | } |
| 77 | 77 | |
| | 78 | + EPOrg::updateSummaryFields( 'terms', array( 'id' => $this->getField( 'org_id' ) ) ); |
| | 79 | + |
| 78 | 80 | return parent::insertIntoDB(); |
| 79 | 81 | } |
| 80 | 82 | |
| — | — | @@ -83,15 +85,38 @@ |
| 84 | 86 | */ |
| 85 | 87 | public function removeFromDB() { |
| 86 | 88 | $id = $this->getId(); |
| | 89 | + $this->loadFields( array( 'org_id' ) ); |
| | 90 | + $orgId = $this->getField( 'org_id', false ); |
| 87 | 91 | |
| 88 | 92 | $success = parent::removeFromDB(); |
| 89 | 93 | |
| 90 | 94 | if ( $success ) { |
| 91 | 95 | $success = wfGetDB( DB_MASTER )->delete( 'ep_students_per_term', array( 'spt_term_id' => $id ) ) && $success; |
| 92 | 96 | } |
| 93 | | - |
| | 97 | + |
| | 98 | + if ( $orgId !== false ) { |
| | 99 | + EPOrg::updateSummaryFields( array( 'terms', 'students' ), array( 'id' => $orgId ) ); |
| | 100 | + } |
| | 101 | + |
| 94 | 102 | return $success; |
| 95 | 103 | } |
| | 104 | + |
| | 105 | + /** |
| | 106 | + * (non-PHPdoc) |
| | 107 | + * @see EPDBObject::updateInDB() |
| | 108 | + */ |
| | 109 | + protected function updateInDB() { |
| | 110 | + $oldOrgId = $this->hasField( 'org_id' ) ? self::selectFieldsRow( 'org_id', array( 'id' => $this->getId() ) ) : false; |
| | 111 | + |
| | 112 | + $success = parent::updateInDB(); |
| | 113 | + |
| | 114 | + if ( $success && $oldOrgId !== false && $oldOrgId !== $this->getField( 'org_id' ) ) { |
| | 115 | + $conds = array( 'id' => array( $oldOrgId, $this->getField( 'org_id' ) ) ); |
| | 116 | + EPOrg::updateSummaryFields( array( 'terms', 'students' ), $conds ); |
| | 117 | + } |
| | 118 | + |
| | 119 | + return $success; |
| | 120 | + } |
| 96 | 121 | |
| 97 | 122 | /** |
| 98 | 123 | * Returns the course associated with this term. |
| Index: trunk/extensions/EducationProgram/includes/EPDBObject.php |
| — | — | @@ -168,13 +168,16 @@ |
| 169 | 169 | * @since 0.1 |
| 170 | 170 | * |
| 171 | 171 | * @param string $name |
| | 172 | + * @param mixed $default |
| 172 | 173 | * |
| 173 | 174 | * @throws MWException |
| 174 | 175 | * @return mixed |
| 175 | 176 | */ |
| 176 | | - public function getField( $name ) { |
| | 177 | + public function getField( $name, $default = null ) { |
| 177 | 178 | if ( $this->hasField( $name ) ) { |
| 178 | 179 | return $this->fields[$name]; |
| | 180 | + } elseif ( !is_null( $default ) ) { |
| | 181 | + return $default; |
| 179 | 182 | } else { |
| 180 | 183 | throw new MWException( 'Attempted to get not-set field ' . $name ); |
| 181 | 184 | } |
| — | — | @@ -343,6 +346,7 @@ |
| 344 | 347 | |
| 345 | 348 | /** |
| 346 | 349 | * Updates the object in the database. |
| | 350 | + * TODO: log and store old rev |
| 347 | 351 | * |
| 348 | 352 | * @since 0.1 |
| 349 | 353 | * |
| — | — | @@ -361,6 +365,7 @@ |
| 362 | 366 | |
| 363 | 367 | /** |
| 364 | 368 | * Inserts the object into the database. |
| | 369 | + * TODO: log |
| 365 | 370 | * |
| 366 | 371 | * @since 0.1 |
| 367 | 372 | * |
| — | — | @@ -383,6 +388,7 @@ |
| 384 | 389 | |
| 385 | 390 | /** |
| 386 | 391 | * Removes the object from the database. |
| | 392 | + * TODO: log and store rev |
| 387 | 393 | * |
| 388 | 394 | * @since 0.1 |
| 389 | 395 | * |
| — | — | @@ -1066,4 +1072,34 @@ |
| 1067 | 1073 | return $params; |
| 1068 | 1074 | } |
| 1069 | 1075 | |
| | 1076 | + /** |
| | 1077 | + * Computes and updates the values of the summary fields. |
| | 1078 | + * |
| | 1079 | + * @since 0.1 |
| | 1080 | + * |
| | 1081 | + * @param array|string|null $summaryFields |
| | 1082 | + */ |
| | 1083 | + public function loadSummaryFields( $summaryFields = null ) { |
| | 1084 | + |
| | 1085 | + } |
| | 1086 | + |
| | 1087 | + /** |
| | 1088 | + * Computes the values of the summary fields of the objects matching the provided conditions. |
| | 1089 | + * |
| | 1090 | + * @since 0.1 |
| | 1091 | + * |
| | 1092 | + * @param array|string|null $summaryFields |
| | 1093 | + * @param array $conditions |
| | 1094 | + */ |
| | 1095 | + public static function updateSummaryFields( $summaryFields = null, array $conditions = array() ) { |
| | 1096 | + self::setReadDb( DB_MASTER ); |
| | 1097 | + |
| | 1098 | + foreach ( self::select( 'id', $conditions ) as /* EPDBObject */ $item ) { |
| | 1099 | + $item->loadSummaryFields( $summaryFields ); |
| | 1100 | + $item->writeToDB(); |
| | 1101 | + } |
| | 1102 | + |
| | 1103 | + self::setReadDb( DB_SLAVE ); |
| | 1104 | + } |
| | 1105 | + |
| 1070 | 1106 | } |
| Index: trunk/extensions/EducationProgram/includes/EPPager.php |
| — | — | @@ -492,7 +492,8 @@ |
| 493 | 493 | |
| 494 | 494 | /** |
| 495 | 495 | * Similar to TablePager::formatValue, but passes along the name of the field without prefix. |
| 496 | | - * |
| | 496 | + * Returned values need to be escaped! |
| | 497 | + * |
| 497 | 498 | * @since 0.1 |
| 498 | 499 | * |
| 499 | 500 | * @param string $name |
| Index: trunk/extensions/EducationProgram/includes/EPCourse.php |
| — | — | @@ -36,6 +36,9 @@ |
| 37 | 37 | |
| 38 | 38 | 'name' => 'str', |
| 39 | 39 | 'description' => 'str', |
| | 40 | + 'lang' => 'str', |
| | 41 | + |
| | 42 | + 'students' => 'int', |
| 40 | 43 | ); |
| 41 | 44 | } |
| 42 | 45 | |
| Index: trunk/extensions/EducationProgram/EducationProgram.i18n.php |
| — | — | @@ -128,6 +128,10 @@ |
| 129 | 129 | 'eporgpager-header-city' => 'City', |
| 130 | 130 | 'eporgpager-header-country' => 'Country', |
| 131 | 131 | 'eporgpager-filter-country' => 'Country', |
| | 132 | + 'eporgpager-header-courses' => 'Courses', |
| | 133 | + 'eporgpager-header-mentors' => 'Ambassadors', |
| | 134 | + 'eporgpager-header-students' => 'Students', |
| | 135 | + 'eporgpager-header-terms' => 'Terms', |
| 132 | 136 | |
| 133 | 137 | // Institution pager |
| 134 | 138 | 'epcoursepager-header-name' => 'Name', |
| Index: trunk/extensions/EducationProgram/api/ApiDeleteEducation.php |
| — | — | @@ -24,7 +24,7 @@ |
| 25 | 25 | protected static $typeMap = array( |
| 26 | 26 | 'org' => 'EPOrg', |
| 27 | 27 | 'course' => 'EPCourse', |
| 28 | | - 'trem' => 'EPTerm', |
| | 28 | + 'term' => 'EPTerm', |
| 29 | 29 | 'student' => 'EPStudent', |
| 30 | 30 | 'mentor' => 'EPMentor', |
| 31 | 31 | ); |