Index: trunk/extensions/EducationProgram/specials/SpecialEditInstitution.php |
— | — | @@ -23,283 +23,36 @@ |
24 | 24 | } |
25 | 25 | |
26 | 26 | /** |
27 | | - * Attempt to get the contest to be edited or create the one to be added. |
28 | | - * If this works, show the form, if not, redirect to special:contests. |
29 | | - * |
30 | | - * @since 0.1 |
31 | | - */ |
32 | | - protected function showContent() { |
33 | | - if ( $this->isNew() ) { |
34 | | - $conditions = array( 'name' => $this->getRequest()->getVal( 'neworg' ) ); |
35 | | - |
36 | | - $contest = Contest::s()->selectRow( null, $conditions ); |
37 | | - |
38 | | - if ( $contest === false ) { |
39 | | - $contest = new Contest( $conditions, true ); |
40 | | - } |
41 | | - else { |
42 | | - $this->showWarning( 'contest-edit-exists-already' ); |
43 | | - } |
44 | | - } |
45 | | - else { |
46 | | - $contest = Contest::s()->selectRow( null, array( 'name' => $this->subPage ) ); |
47 | | - } |
48 | | - |
49 | | - if ( $contest === false ) { |
50 | | - $this->getOutput()->redirect( SpecialPage::getTitleFor( 'Contests' )->getLocalURL() ); |
51 | | - } |
52 | | - else { |
53 | | - if ( !$this->isNew() ) { |
54 | | - $this->getOutput()->addHTML( |
55 | | - SpecialContestPage::getNavigation( $contest->getField( 'name' ), $this->getUser(), $this->getLanguage(), $this->getName() ) |
56 | | - ); |
57 | | - } |
58 | | - |
59 | | - $this->contest = $contest; |
60 | | - $this->showForm(); |
61 | | - $this->getOutput()->addModules( 'contest.special.editcontest' ); |
62 | | - } |
63 | | - } |
64 | | - |
65 | | - /** |
66 | 27 | * (non-PHPdoc) |
67 | | - * @see FormSpecialPage::getFormFields() |
| 28 | + * @see SpecialEPFormPage::getFormFields() |
68 | 29 | * @return array |
69 | 30 | */ |
70 | 31 | protected function getFormFields() { |
| 32 | + $fields = parent::getFormFields(); |
71 | 33 | |
72 | | - /** |
73 | | - * @var $contest Contest |
74 | | - */ |
75 | | - $contest = $this->contest; |
76 | | - |
77 | | - $fields = array(); |
78 | | - |
79 | | - $fields['id'] = array ( 'type' => 'hidden' ); |
80 | | - |
81 | 34 | $fields['name'] = array ( |
82 | 35 | 'type' => 'text', |
83 | | - 'label-message' => 'contest-edit-name', |
84 | | - 'id' => 'contest-name-field', |
| 36 | + 'label-message' => 'educationprogram-org-edit-name', |
| 37 | + 'id' => 'org-name-field', |
85 | 38 | ); |
86 | 39 | |
87 | | - $fields['status'] = array ( |
88 | | - 'type' => 'radio', |
89 | | - 'label-message' => 'contest-edit-status', |
90 | | - 'options' => Contest::getStatusMessages( true ) |
91 | | - ); |
92 | | - |
93 | | - $fields['intro'] = array ( |
94 | | - 'type' => 'text', |
95 | | - 'label-message' => 'contest-edit-intro', |
96 | | - ); |
97 | | - |
98 | | - $fields['opportunities'] = array ( |
99 | | - 'type' => 'text', |
100 | | - 'label-message' => 'contest-edit-opportunities', |
101 | | - ); |
102 | | - |
103 | | - $fields['rules_page'] = array ( |
104 | | - 'type' => 'text', |
105 | | - 'label-message' => 'contest-edit-rulespage', |
106 | | - ); |
107 | | - |
108 | | - $fields['help'] = array ( |
109 | | - 'type' => 'text', |
110 | | - 'label-message' => 'contest-edit-help', |
111 | | - ); |
112 | | - |
113 | | - $fields['signup_email'] = array ( |
114 | | - 'type' => 'text', |
115 | | - 'label-message' => 'contest-edit-signup', |
116 | | - ); |
117 | | - |
118 | | - $fields['reminder_email'] = array ( |
119 | | - 'type' => 'text', |
120 | | - 'label-message' => 'contest-edit-reminder', |
121 | | - ); |
122 | | - |
123 | | - $fields['end'] = array ( |
124 | | - 'type' => 'text', |
125 | | - 'label-message' => 'contest-edit-end', |
126 | | - 'id' => 'contest-edit-end', |
127 | | - 'size' => 15 |
128 | | - ); |
129 | | - |
130 | | - if ( $contest !== false ) { |
131 | | - foreach ( $fields as $name => $data ) { |
132 | | - $default = $contest->getField( $name ); |
133 | | - |
134 | | - if ( $name == 'end' ) { |
135 | | - $default = wfTimestamp( TS_DB, $default ); |
136 | | - } |
137 | | - |
138 | | - $fields[$name]['default'] = $default; |
139 | | - } |
140 | | - } |
141 | | - |
142 | | - $mappedFields = array(); |
143 | | - |
144 | | - foreach ( $fields as $name => $field ) { |
145 | | - $mappedFields['contest-' . $name] = $field; |
146 | | - } |
147 | | - |
148 | | - if ( $contest !== false ) { |
149 | | - foreach ( $contest->getChallenges() as /* ContestChallenge */ $challenge ) { |
150 | | - $mappedFields[] = array( |
151 | | - 'class' => 'ContestChallengeField', |
152 | | - 'options' => $challenge->toArray() |
153 | | - ); |
154 | | - } |
155 | | - } |
156 | | - |
157 | | - $mappedFields['delete-challenges'] = array ( 'type' => 'hidden', 'id' => 'delete-challenges' ); |
158 | | - |
159 | | - return $mappedFields; |
| 40 | + return $this->processFormFields( $fields ); |
160 | 41 | } |
161 | | - |
| 42 | + |
162 | 43 | /** |
163 | | - * Process the form. At this point we know that the user passes all the criteria in |
164 | | - * userCanExecute(), and if the data array contains 'Username', etc, then Username |
165 | | - * resets are allowed. |
166 | | - * |
167 | | - * @param array $data |
168 | | - * |
169 | | - * @return Bool|Array |
| 44 | + * (non-PHPdoc) |
| 45 | + * @see SpecialEPFormPage::getListPage() |
170 | 46 | */ |
171 | | - public function onSubmit( array $data ) { |
172 | | - $fields = array(); |
173 | | - |
174 | | - foreach ( $data as $name => $value ) { |
175 | | - $matches = array(); |
176 | | - |
177 | | - if ( preg_match( '/contest-(.+)/', $name, $matches ) ) { |
178 | | - if ( $matches[1] == 'end' ) { |
179 | | - $value = wfTimestamp( TS_MW, strtotime( $value ) ); |
180 | | - } |
181 | | - |
182 | | - $fields[$matches[1]] = $value; |
183 | | - } |
184 | | - } |
185 | | - |
186 | | - // If no ID is set, this means it's a new contest, so set the ID to null for an insert. |
187 | | - // However, the user can have hot the back button after creation of a new contest, |
188 | | - // re-submitting the form. In this case, get the ID of the already existing item for an update. |
189 | | - if ( !array_key_exists( 'id', $fields ) || $fields['id'] === '' ) { |
190 | | - $contest = Contest::s()->selectRow( 'id', array( 'name' => $fields['name'] ) ); |
191 | | - $fields['id'] = $contest === false ? null : $contest->getField( 'id' ); |
192 | | - } |
193 | | - |
194 | | - $contest = new Contest( $fields, is_null( $fields['id'] ) ); |
195 | | - |
196 | | - $contest->setChallenges( $this->getSubmittedChallenges() ); |
197 | | - $success = $contest->writeAllToDB(); |
198 | | - |
199 | | - $success = $this->removeDeletedChallenges( $data['delete-challenges'] ) && $success; |
200 | | - |
201 | | - if ( $success ) { |
202 | | - return true; |
203 | | - } |
204 | | - else { |
205 | | - return array(); // TODO |
206 | | - } |
| 47 | + protected function getListPage() { |
| 48 | + return 'Institutions'; |
207 | 49 | } |
208 | | - |
| 50 | + |
209 | 51 | /** |
210 | | - * The UI keeps track of 'removed' challenges by storing them into a |
211 | | - * hidden HTML input, pipe-separated. On submission, this method |
212 | | - * takes this string and actually deletes them. |
213 | | - * |
214 | | - * @since 0.1 |
215 | | - * |
216 | | - * @param string $idString |
217 | | - * |
218 | | - * @return boolean Success indicator |
| 52 | + * (non-PHPdoc) |
| 53 | + * @see SpecialEPFormPage::getListPage() |
219 | 54 | */ |
220 | | - protected function removeDeletedChallenges( $idString ) { |
221 | | - if ( $idString == '' ) { |
222 | | - return true; |
223 | | - } |
224 | | - |
225 | | - if ( !ContestSettings::get( 'contestDeletionEnabled' ) ) { |
226 | | - // Shouldn't get here (UI should prevent it) |
227 | | - throw new MWException( 'Contest deletion is disabled', 'contestdeletiondisabled' ); |
228 | | - } |
229 | | - |
230 | | - return ContestChallenge::s()->delete( array( 'id' => explode( '|', $idString ) ) ); |
| 55 | + protected function getObjectClassName() { |
| 56 | + return 'EPOrg'; |
231 | 57 | } |
232 | 58 | |
233 | | - /** |
234 | | - * Finds the submitted challanges and returns them as a list of |
235 | | - * ContestChallenge objects. |
236 | | - * |
237 | | - * @since 0.1 |
238 | | - * |
239 | | - * @return array of ContestChallenge |
240 | | - */ |
241 | | - protected function getSubmittedChallenges() { |
242 | | - $challenges = array(); |
243 | | - |
244 | | - foreach ( $this->getrequest()->getValues() as $name => $value ) { |
245 | | - $matches = array(); |
246 | | - |
247 | | - if ( preg_match( '/contest-challenge-(\d+)/', $name, $matches ) ) { |
248 | | - $challenges[] = $this->getSubmittedChallenge( $matches[1] ); |
249 | | - } elseif ( preg_match( '/contest-challenge-new-(\d+)/', $name, $matches ) ) { |
250 | | - $challenges[] = $this->getSubmittedChallenge( $matches[1], true ); |
251 | | - } |
252 | | - } |
253 | | - |
254 | | - return $challenges; |
255 | | - } |
256 | | - |
257 | | - /** |
258 | | - * Create and return a contest challenge object from the submitted data. |
259 | | - * |
260 | | - * @since 0.1 |
261 | | - * |
262 | | - * @param integer|null $challengeId |
263 | | - * |
264 | | - * @return ContestChallenge |
265 | | - */ |
266 | | - protected function getSubmittedChallenge( $challengeId, $isNewChallenge = false ) { |
267 | | - if ( $isNewChallenge ) { |
268 | | - $challengeDbId = null; |
269 | | - $challengeId = "new-$challengeId"; |
270 | | - } else { |
271 | | - $challengeDbId = $challengeId; |
272 | | - } |
273 | | - |
274 | | - $request = $this->getRequest(); |
275 | | - |
276 | | - return new ContestChallenge( array( |
277 | | - 'id' => $challengeDbId, |
278 | | - 'text' => $request->getText( "challenge-text-$challengeId" ), |
279 | | - 'title' => $request->getText( "contest-challenge-$challengeId" ), |
280 | | - 'oneline' => $request->getText( "challenge-oneline-$challengeId" ), |
281 | | - ) ); |
282 | | - } |
283 | | - |
284 | | - /** |
285 | | - * Gets called after the form is saved. |
286 | | - * Enter description here ... |
287 | | - */ |
288 | | - public function onSuccess() { |
289 | | - $this->getOutput()->redirect( SpecialPage::getTitleFor( 'Institutions' )->getLocalURL() ); |
290 | | - } |
291 | | - |
292 | | - /** |
293 | | - * Show a message in a warning box. |
294 | | - * |
295 | | - * @since 0.1 |
296 | | - * |
297 | | - * @param string $message |
298 | | - */ |
299 | | - protected function showWarning( $message ) { |
300 | | - $this->getOutput()->addHTML( |
301 | | - '<p class="visualClear warningbox">' . wfMsgExt( $message, 'parseinline' ) . '</p>' |
302 | | - . '<hr style="display: block; clear: both; visibility: hidden;" />' |
303 | | - ); |
304 | | - } |
305 | | - |
306 | 59 | } |
Index: trunk/extensions/EducationProgram/specials/SpecialEPFormPage.php |
— | — | @@ -20,9 +20,35 @@ |
21 | 21 | * @since 0.1 |
22 | 22 | * @var string |
23 | 23 | */ |
24 | | - public $subPage; |
| 24 | + protected $subPage; |
25 | 25 | |
26 | 26 | /** |
| 27 | + * Instance of the object being edited or created. |
| 28 | + * |
| 29 | + * @since 0.1 |
| 30 | + * @var EPDBObject|false |
| 31 | + */ |
| 32 | + protected $item; |
| 33 | + |
| 34 | + /** |
| 35 | + * Returns the name of the EPDBObject deriving class this page edits or creates. |
| 36 | + * |
| 37 | + * @since 0.1 |
| 38 | + * |
| 39 | + * @return string |
| 40 | + */ |
| 41 | + protected abstract function getObjectClassName(); |
| 42 | + |
| 43 | + /** |
| 44 | + * Gets the name of the list page corresponding to this edit page. |
| 45 | + * |
| 46 | + * @since 0.1 |
| 47 | + * |
| 48 | + * @return string |
| 49 | + */ |
| 50 | + protected abstract function getListPage(); |
| 51 | + |
| 52 | + /** |
27 | 53 | * @see SpecialPage::getDescription |
28 | 54 | * |
29 | 55 | * @since 0.1 |
— | — | @@ -70,8 +96,11 @@ |
71 | 97 | } |
72 | 98 | |
73 | 99 | /** |
| 100 | + * Returns if the page should work in insertion mode rather then modification mode. |
74 | 101 | * |
75 | | - * Enter description here ... |
| 102 | + * @since 0.1 |
| 103 | + * |
| 104 | + * @return boolean |
76 | 105 | */ |
77 | 106 | protected function isNew() { |
78 | 107 | return $this->getRequest()->wasPosted() && $this->getUser()->matchEditToken( $this->getRequest()->getVal( 'wpEditToken' ) ); |
— | — | @@ -89,7 +118,60 @@ |
90 | 119 | $this->onSuccess(); |
91 | 120 | } |
92 | 121 | } |
| 122 | + |
| 123 | + /** |
| 124 | + * Returns the data to use as condition for selecting the object, |
| 125 | + * or in case nothing matches the selection, the data to initialize |
| 126 | + * it with. This is typically an identifier such as name or id. |
| 127 | + * |
| 128 | + * @since 0.1 |
| 129 | + * |
| 130 | + * @return array |
| 131 | + */ |
| 132 | + protected function getNewData() { |
| 133 | + return array( 'name' => $this->getRequest()->getVal( 'newname' ) ); |
| 134 | + } |
| 135 | + |
| 136 | + /** |
| 137 | + * Attempt to get the contest to be edited or create the one to be added. |
| 138 | + * If this works, show the form, if not, redirect to special:contests. |
| 139 | + * |
| 140 | + * @since 0.1 |
| 141 | + */ |
| 142 | + protected function showContent() { |
| 143 | + $c = $this->getObjectClassName(); |
| 144 | + |
| 145 | + if ( $this->isNew() ) { |
| 146 | + $data = $this->getNewData(); |
93 | 147 | |
| 148 | + $object = $c::selectRow( null, $data ); |
| 149 | + |
| 150 | + if ( $object === false ) { |
| 151 | + $object = new Contest( $data, true ); |
| 152 | + } |
| 153 | + else { |
| 154 | + $this->showWarning( 'educationprogram-' . strtolower( $this->getName() ) . '-exists-already' ); |
| 155 | + } |
| 156 | + } |
| 157 | + else { |
| 158 | + $object = $c::selectRow( null, array( 'name' => $this->subPage ) ); |
| 159 | + } |
| 160 | + |
| 161 | + if ( $object === false ) { |
| 162 | + $this->getOutput()->redirect( SpecialPage::getTitleFor( $this->getListPage() )->getLocalURL() ); |
| 163 | + } |
| 164 | + else { |
| 165 | +// if ( !$this->isNew() ) { |
| 166 | +// $this->getOutput()->addHTML( |
| 167 | +// SpecialContestPage::getNavigation( $contest->getField( 'name' ), $this->getUser(), $this->getLanguage(), $this->getName() ) |
| 168 | +// ); |
| 169 | +// } |
| 170 | + |
| 171 | + $this->item = $object; |
| 172 | + $this->showForm(); |
| 173 | + } |
| 174 | + } |
| 175 | + |
94 | 176 | /** |
95 | 177 | * (non-PHPdoc) |
96 | 178 | * @see FormSpecialPage::getForm() |
— | — | @@ -103,7 +185,7 @@ |
104 | 186 | wfMsg( 'cancel' ), |
105 | 187 | 'cancelEdit', |
106 | 188 | array( |
107 | | - 'target-url' => SpecialPage::getTitleFor( 'Contests' )->getFullURL() |
| 189 | + 'target-url' => SpecialPage::getTitleFor( $this->getListPage() )->getFullURL() |
108 | 190 | ) |
109 | 191 | ); |
110 | 192 | |
— | — | @@ -115,8 +197,46 @@ |
116 | 198 | |
117 | 199 | return $form; |
118 | 200 | } |
| 201 | + |
| 202 | + /** |
| 203 | + * (non-PHPdoc) |
| 204 | + * @see FormSpecialPage::getFormFields() |
| 205 | + * @return array |
| 206 | + */ |
| 207 | + protected function getFormFields() { |
| 208 | + $fields = array(); |
119 | 209 | |
| 210 | + $fields['id'] = array ( 'type' => 'hidden' ); |
| 211 | + |
| 212 | + return $fields; |
| 213 | + } |
| 214 | + |
120 | 215 | /** |
| 216 | + * Populates the form fields with the data of the item |
| 217 | + * and prefixes their names. |
| 218 | + * |
| 219 | + * @since 0.1 |
| 220 | + * |
| 221 | + * @param array $fields |
| 222 | + */ |
| 223 | + protected function processFormFields( array $fields ) { |
| 224 | + if ( $this->item !== false ) { |
| 225 | + foreach ( $fields as $name => $data ) { |
| 226 | + $default = $this->item->getField( $name ); |
| 227 | + $fields[$name]['default'] = $default; |
| 228 | + } |
| 229 | + } |
| 230 | + |
| 231 | + $mappedFields = array(); |
| 232 | + |
| 233 | + foreach ( $fields as $name => $field ) { |
| 234 | + $mappedFields['item-' . $name] = $field; |
| 235 | + } |
| 236 | + |
| 237 | + return $mappedFields; |
| 238 | + } |
| 239 | + |
| 240 | + /** |
121 | 241 | * Show a message in a warning box. |
122 | 242 | * |
123 | 243 | * @since 0.1 |
— | — | @@ -131,5 +251,47 @@ |
132 | 252 | . '<hr style="display: block; clear: both; visibility: hidden;" />' |
133 | 253 | ); |
134 | 254 | } |
| 255 | + |
| 256 | + /** |
| 257 | + * Gets called after the form is saved. |
| 258 | + * |
| 259 | + * @since 0.1 |
| 260 | + */ |
| 261 | + public function onSuccess() { |
| 262 | + $this->getOutput()->redirect( SpecialPage::getTitleFor( $this->getListPage() )->getLocalURL() ); |
| 263 | + } |
| 264 | + |
| 265 | + /** |
| 266 | + * Process the form. At this point we know that the user passes all the criteria in |
| 267 | + * userCanExecute(), and if the data array contains 'Username', etc, then Username |
| 268 | + * resets are allowed. |
| 269 | + * |
| 270 | + * @param array $data |
| 271 | + * |
| 272 | + * @return Bool|Array |
| 273 | + */ |
| 274 | + public function onSubmit( array $data ) { |
| 275 | + $fields = array(); |
135 | 276 | |
| 277 | + foreach ( $data as $name => $value ) { |
| 278 | + $matches = array(); |
| 279 | + |
| 280 | + if ( preg_match( '/item-(.+)/', $name, $matches ) ) { |
| 281 | + $fields[$matches[1]] = $value; |
| 282 | + } |
| 283 | + } |
| 284 | + |
| 285 | + $c = $this->getObjectClassName(); |
| 286 | + $item = new $c( $fields, is_null( $fields['id'] ) ); |
| 287 | + |
| 288 | + $success = $item->writeAllToDB(); |
| 289 | + |
| 290 | + if ( $success ) { |
| 291 | + return true; |
| 292 | + } |
| 293 | + else { |
| 294 | + return array(); // TODO |
| 295 | + } |
| 296 | + } |
| 297 | + |
136 | 298 | } |