Documentation is available at tgcSimplePollAdmin.php
1 <?php
2 /**
3 * tgcSimplePollAdmin is a class to administrate the tgcSimplePoll voting script
4 *
5 * $Id: tgcSimplePollAdmin.php,v 1.3 2004/07/25 18:34:55 luckec Exp $
6 *
7 * @package tgcSimplePoll
8 * @version 2.0.0
9 * @author Carsten Lucke <carsten@tool-garage.de>
10 * @copyright Carsten Lucke <carsten@tool-garage.de>
11 * @link http://www.tool-garage.de
12 */
13
14 /**
15 * main configfile
16 */
17 require_once './config/config.php';
18
19 /**
20 * tgcSimplePoll baseclass
21 */
22 require_once SP_INCLUDEDIR . '/tgcSimplePoll_common.php';
23
24 /**
25 * requires PEAR::DB
26 */
27 require_once SP_INCLUDEDIR . '/pear/DB.php';
28
29 /**
30 * uses patTemplate - a powerful and easy to use template-engine
31 *
32 * @link http://www.php-tools.de
33 */
34 require_once SP_INCLUDEDIR . '/patTemplate.php';
35
36 /**
37 * uses patUser for user-authentication
38 *
39 * @link http://www.php-tools.de
40 */
41 require_once SP_INCLUDEDIR . '/patUser.php';
42
43 /**
44 * patForms
45 *
46 * @link http://www.php-tools.de
47 */
48 require_once SP_INCLUDEDIR . '/patForms.php';
49
50 /**
51 * patErrorManager for patForms
52 *
53 * @link http://www.php-tools.de
54 */
55 require_once SP_INCLUDEDIR . '/patErrorManager.php';
56
57
58 /**
59 * maximum login attempts (0 for unlimited)
60 *
61 * @access public
62 */
63 define('SP_ADMIN_MAXLOGINATTEMPTS', 3);
64
65 /**
66 * update of question too insecure
67 *
68 * @access public
69 */
70 define('SP_ADMIN_UPDATEQUESTION_TOO_INSECURE', 10);
71
72
73 /**
74 * tgcSimplePollAdmin is a class to administrate the tgcSimplePoll voting script
75 *
76 * With tgcSimplePoll you can easily include a survey on your website.
77 * You can manage your polls in an admin-area which is password protected.
78 * Changing the layout is much easier now, as tgcSimplePoll uses a template-engine (patTemplate from <{@link http://www.php-tools.de}>).
79 *
80 * tgcSimplePoll requires PHP >= 4.1.0
81 *
82 * @package tgcSimplePoll
83 * @access public
84 * @version 2.0.0
85 * @author Carsten Lucke <carsten@tool-garage.de>
86 * @link http://www.tool-garage.de
87 */
88 class tgcSimplePollAdmin extends tgcSimplePoll_common
89 {
90 /**
91 * user object (patUser)
92 *
93 * @access private
94 * @var object
95 * @link http://www.php-tools.de <www.php-tools.de>
96 */
97 var $_user = null;
98
99 /**
100 * add question form elements
101 *
102 * @access private
103 * @var array
104 */
105 var $_addQuestionElements = array();
106
107 /**
108 * changePasswd form elements
109 *
110 * @access private
111 * @var array
112 */
113 var $_changePasswdElements = array();
114
115
116 /**
117 * Constructor
118 *
119 * Initializes the admin-area
120 *
121 * This parameter is an associative array containing the settings you desire.
122 * If you don't want to build an own skin set the skinDir and
123 * take 'tg/default' or sth. else as skin
124 *
125 * <pre>
126 * Following options are possible:
127 *
128 * 'language' => the language file, that shall be used - default language is English
129 * 'skin' => skin-name as string (if no skin is specified the default-skin will be used)
130 * 'useSessions' => use sessions for user authentication
131 * </pre>
132 *
133 * @access public
134 * @param array $settings settings array
135 */
136 function tgcSimplePollAdmin($settings = array())
137 {
138 if (isset($settings['skin'])) {
139 $this->_skin = $settings['skin'];
140 }
141 if (isset($settings['useSessions'])) {
142 $this->_useSessions = $settings['useSessions'];
143 }
144 if (isset($settings['language'])) {
145 $this->_lang = $settings['language'];
146 }
147
148 // init template-engine
149 $this->_tmpl = &new patTemplate('html');
150 $this->_tmpl->setBasedir(SP_SKINDIR . '/' . $this->_skin);
151 $this->_tmpl->addGlobalVar('SP_SKINDIR', SP_SKINDIR . '/' . $this->_skin);
152 $this->_tmpl->setOption('translationFolder', SP_DATADIR);
153 $this->_tmpl->setOption('lang', $this->_lang);
154
155 // init dbc
156 $dbc = &DB::connect(SP_DB_DSN);
157 if (PEAR::isError($dbc)) {
158 return $dbc;
159 }
160 $dbc->setFetchMode(DB_FETCHMODE_ASSOC);
161 $this->_dbc = &$dbc;
162
163 // init patUser
164 $this->_user = &new patUser($this->_useSessions);
165 $this->_user->setAuthDbc($this->_dbc);
166 $this->_user->setTemplate($this->_tmpl);
167 $this->_user->setAuthTable(SP_DB_TABLEPREFIX . 'admin');
168 $authfields = array(
169 'primary' => 'uId',
170 'passwd' => 'password',
171 'username' => 'username'
172 );
173 $this->_user->setAuthFields($authfields);
174 $this->_user->setCryptFunction('md5');
175 $this->_user->setRealm('tgcSimplePoll admin-area');
176 if (SP_ADMIN_MAXLOGINATTEMPTS) {
177 $this->_user->setMaxLoginAttempts(SP_ADMIN_MAXLOGINATTEMPTS);
178 }
179
180 // build dispatcher
181 $this->_dispatcher = $_SERVER['PHP_SELF'];
182 if ($this->_useSessions) {
183 $this->_dispatcher .= sprintf('?%s', SID);
184 }
185 $this->_tmpl->addGlobalVar('SP_DISPATCHER', $this->_dispatcher);
186
187 if (isset($_GET['spSite'])) {
188 $this->_site = $_GET['spSite'];
189 }
190 }
191
192
193 /**
194 * displays the admin-area
195 *
196 * returns a string containing markup-data for the admin-area, after the user has been identified as admin
197 *
198 * @access public
199 * @return string markup-data for the admin-area
200 */
201 function run()
202 {
203 if (isset($_POST['password']) && isset($_POST['username'])) {
204 $this->_user->authenticate(array('password' => $_POST['password'], 'username' => $_POST['username']));
205 }
206
207 // check if user has authenticated
208 if (! $this->_user->isAuthenticated()) {
209 $this->_user->requireAuthentication();
210 }
211
212 switch ($this->_site) {
213 case 'addQuestion':
214 $this->_siteAddQuestion();
215 break;
216 case 'qDetail':
217 $this->_siteQuestionDetail();
218 break;
219 case 'qChange':
220 $this->_siteQuestionChange();
221 break;
222 case 'modQuestion':
223 $this->_siteModifyQuestion();
224 break;
225 case 'qReset':
226 $this->_siteQuestionReset();
227 break;
228 case 'qDelete':
229 $this->_siteQuestionDelete();
230 break;
231 case 'changePass':
232 $this->_changeLoginData();
233 break;
234 default:
235 $this->_siteOverview();
236 break;
237 }
238 return $this->_tmpl->getParsedTemplate('page');
239 }
240
241 /**
242 * Shows the admin overview site
243 *
244 * @access private
245 */
246 function _siteOverview()
247 {
248 $this->_tmpl->readTemplatesFromFile('admin.tmpl');
249 $this->_tmpl->addVar('inputform', 'FORM_ACTION', $this->_dispatcher . '&spSite=addQuestion');
250
251 // build needed form elements
252 $this->_buildAddQuestionElements();
253 // new question input form
254 $this->_tmpl->addVar('inputform', 'FORM_QUESTION', $this->_addQuestionElements['question']->serialize());
255 for ($i = 0; $i < count($this->_addQuestionElements['options']); $i++) {
256 $this->_tmpl->addVar('inputform_option', 'FORM_OPTION', $this->_addQuestionElements['options'][$i]->serialize());
257 $this->_tmpl->addVar('inputform_option', 'FORM_OPTION_NO', $i + 1);
258 $this->_tmpl->parseTemplate('inputform_option', 'a');
259 }
260
261 // available questions
262 $questions = $this->_getQuestionsFromDB();
263 if (! empty($questions)) {
264 foreach($questions as $id => $question) {
265 $this->_tmpl->addVar('available_questions', 'QUESTIONS_AVAILABLE', 'yes');
266 $this->_tmpl->addVar('question_list', 'QUESTION_DETAIL_URL', sprintf('%s&spSite=qDetail&spQId=%d', $this->_dispatcher, $id));
267 $this->_tmpl->addVar('question_list', 'QUESTION', $question);
268 $this->_tmpl->parseTemplate('available_questions', 'a');
269 $this->_tmpl->clearTemplate('question_list');
270 }
271 }
272
273 // change login-data form
274 $this->_buildChangeLoginFormElements();
275 $this->_tmpl->addVar('changePass', 'FORM_ACTION', $this->_dispatcher . '&spSite=changePass');
276 $this->_tmpl->addVar('changePass', 'FORM_USERNAME', $this->_changePasswdElements['username']->serialize());
277 $this->_tmpl->addVar('changePass', 'FORM_PASSWD', $this->_changePasswdElements['password']->serialize());
278 }
279
280 /**
281 * Builds the form-elements used to add new questions
282 *
283 * @access private
284 */
285 function _buildAddQuestionElements()
286 {
287 $attributes = array(
288 'required' => 'yes',
289 'display' => 'yes',
290 'edit' => 'yes',
291 'accesskey' => 'q',
292 'maxlength' => '255',
293 'minlength' => '1',
294 'title' => 'Poll-Question'
295 );
296 $this->_addQuestionElements['question'] = &patForms::createElement('spQuestion', 'String', $attributes);
297 $this->_addQuestionElements['options'] = array();
298 $attributes = array(
299 'required' => 'no',
300 'display' => 'yes',
301 'edit' => 'yes',
302 'maxlength' => '255',
303 'minlength' => '1',
304 'title' => 'Poll-Option #1'
305 );
306 $this->_addQuestionElements['options'][] = &patForms::createElement('spOptions[]', 'String', $attributes);
307 $attributes['required'] = 'no';
308 for ($i = 2; $i <= 10; $i++) {
309 $attributes['title'] = 'Poll-Option #' . $i;
310 $this->_addQuestionElements['options'][] = &patForms::createElement('spOptions[]', 'String', $attributes);
311 }
312 }
313
314 /**
315 * Builds the form-elements used to change the admin-login
316 *
317 * @access private
318 */
319 function _buildChangeLoginFormElements()
320 {
321 $attributes = array(
322 'required' => 'yes',
323 'display' => 'yes',
324 'edit' => 'yes',
325 'accesskey' => 'u',
326 'maxlength' => '20',
327 'minlength' => '1',
328 'title' => 'Admin-Username'
329 );
330 $this->_changePasswdElements['username'] = &patForms::createElement('spUsername', 'String', $attributes);
331 $attributes = array(
332 'required' => 'yes',
333 'display' => 'yes',
334 'edit' => 'yes',
335 'accesskey' => 'p',
336 'minlength' => '1',
337 'title' => 'Admin-Password',
338 'type' => 'password'
339 );
340 $this->_changePasswdElements['password'] = &patForms::createElement('spPassword', 'String', $attributes);
341 }
342
343 /**
344 * Shows the site with detailed information abaout a question
345 *
346 * @access private
347 * @param int $qId questionId
348 */
349 function _siteQuestionDetail($qId = null)
350 {
351 if (is_null($qId)) {
352 if (! isset($_GET['spQId']) || empty($_GET['spQId'])) {
353 $this->_siteOverview();
354 $this->_tmpl->setAttribute('errors', 'visibility', 'visible');
355 $this->_tmpl->addVar('errorEntry', 'ERRORMESSAGE', 'No question-details found!');
356 return true;
357 }
358
359 $qId = $_GET['spQId'];
360 }
361
362 $this->_tmpl->addGlobalVar('QUESTION_ID', $qId);
363 $result = $this->_getVoteResults($qId);
364 if (PEAR::isError($result) || empty($result)) {
365 $this->_siteOverview();
366 $this->_tmpl->setAttribute('errors', 'visibility', 'visible');
367 $this->_tmpl->addVar('errorEntry', 'ERRORMESSAGE', 'No question-details found!');
368 return true;
369 }
370 $overallVotes = $this->_getOverallVotes($qId);
371 if (PEAR::isError($overallVotes)) {
372 $this->_siteOverview();
373 $this->_tmpl->setAttribute('errors', 'visibility', 'visible');
374 $this->_tmpl->addVar('errorEntry', 'ERRORMESSAGE', 'DB-Error while retrieving question-data!');
375 return true;
376 }
377 $cnt = count($result);
378 for ($i = 0; $i < $cnt; $i++) {
379 if (! isset($question)) {
380 $question = $result[$i]['question'];
381 }
382 $result[$i]['percent'] = $overallVotes == 0 ? 0 : number_format(($result[$i]['votes'] / $overallVotes) * 100, 2, ',', '.');
383 $result[$i]['bar_width'] = $result[$i]['percent'] * 2;
384 }
385 $this->_tmpl->readTemplatesFromFile('admin_qdetail.tmpl');
386 $this->_tmpl->addRows('qDetail_options', $result);
387 $this->_tmpl->addVar('qDetail', 'QUESTION', $question);
388 $this->_tmpl->addVar('qDetail', 'VOTES_TOTAL', $overallVotes);
389
390 $this->_tmpl->addVar('qIncludeCode', 'QUESTION_ID', $qId);
391 $this->_tmpl->addVar('qIncludeCode', 'LANGUAGE', $this->_lang);
392 $code = highlight_string($this->_tmpl->getParsedTemplate('qIncludeCode'), true);
393 $this->_tmpl->addVar('qDetail', 'CODE', $code);
394 }
395
396 /**
397 * Adds a question to db
398 *
399 * @access private
400 */
401 function _siteAddQuestion()
402 {
403 // build needed form elements
404 $this->_buildAddQuestionElements();
405
406 $validationErrors = array();
407 $elementsValues = array();
408 $elementsValues['options'] = array();
409
410 // validate question element
411 $this->_addQuestionElements['question']->setSubmitted(true);
412 if (! $this->_addQuestionElements['question']->validate()) {
413 $errors = $this->_addQuestionElements['question']->getValidationErrors();
414 $errors['elTitle'] = $this->_addQuestionElements['question']->getAttribute('title');
415 array_push($validationErrors, $errors);
416 } else {
417 $elementsValues['question'] = $this->_addQuestionElements['question']->getValue();
418 }
419
420 // validate option elements
421 for ($i = 0; $i < count($this->_addQuestionElements['options']); $i++) {
422 $this->_addQuestionElements['options'][$i]->setSubmitted(true);
423 // validate element
424 if (! $this->_addQuestionElements['options'][$i]->validate()) {
425 $errors = $this->_addQuestionElements['options'][$i]->getValidationErrors();
426 $errors['elTitle'] = $this->_addQuestionElements['options'][$i]->getAttribute('title');
427 array_push($validationErrors, $errors);
428 continue;
429 }
430 // store valid value
431 array_push($elementsValues['options'], $this->_addQuestionElements['options'][$i]->getValue());
432 }
433
434 // print errors
435 if (! empty($validationErrors)) {
436 $this->_siteOverview();
437 $this->_tmpl->setAttribute('validationErrors', 'visibility', 'visible');
438
439 foreach ($validationErrors as $elErrors) {
440 $elTitle = $elErrors['elTitle'];
441 unset($elErrors['elTitle']);
442 foreach ($elErrors as $error) {
443 $this->_tmpl->addVar('validationErrorsEntry', 'ELEMENT_TITLE', $elTitle);
444 $this->_tmpl->addVar('validationErrorsEntry', 'ERRORMESSAGE', $error['message']);
445 $this->_tmpl->parseTemplate('validationErrorsEntry', 'a');
446 }
447 }
448 return true;
449 }
450
451 // no errors - add question
452 $question = $_POST['spQuestion'];
453 $options = $_POST['spOptions'];
454 $cnt = count($options);
455 for ($i = 0; $i < $cnt; $i++) {
456 if (empty($options[$i])) {
457 unset($options[$i]);
458 }
459 }
460 $qId = $this->_saveQuestion($question, $options);
461 if (PEAR::isError($qId)) {
462 $this->_siteOverview();
463 $this->_tmpl->setAttribute('errors', 'visibility', 'visible');
464 $this->_tmpl->addVar('errorEntry', 'ERRORMESSAGE', 'Could not add question!');
465 return true;
466 }
467
468 $this->_siteQuestionDetail($qId);
469 return true;
470 }
471
472 /**
473 * Modifies a question in db
474 *
475 * @access private
476 * @param int $qId questionId
477 */
478 function _siteModifyQuestion()
479 {
480 if (! isset($_GET['spQId']) || empty($_GET['spQId'])) {
481 $this->_siteOverview();
482 $this->_tmpl->setAttribute('errors', 'visibility', 'visible');
483 $this->_tmpl->addVar('errorEntry', 'ERRORMESSAGE', 'No question-id found - unable to show requested site!');
484 return true;
485 }
486 $qId = $_GET['spQId'];
487
488 // build needed form elements
489 $this->_buildAddQuestionElements();
490
491 $validationErrors = array();
492 $elementsValues = array();
493 $elementsValues['options'] = array();
494
495 // validate question element
496 $this->_addQuestionElements['question']->setSubmitted(true);
497 if (! $this->_addQuestionElements['question']->validate()) {
498 $errors = $this->_addQuestionElements['question']->getValidationErrors();
499 $errors['elTitle'] = $this->_addQuestionElements['question']->getAttribute('title');
500 array_push($validationErrors, $errors);
501 } else {
502 $elementsValues['question'] = $this->_addQuestionElements['question']->getValue();
503 }
504
505 // validate option elements
506 for ($i = 0; $i < count($this->_addQuestionElements['options']); $i++) {
507 $this->_addQuestionElements['options'][$i]->setSubmitted(true);
508 // validate element
509 if (! $this->_addQuestionElements['options'][$i]->validate()) {
510 $errors = $this->_addQuestionElements['options'][$i]->getValidationErrors();
511 $errors['elTitle'] = $this->_addQuestionElements['options'][$i]->getAttribute('title');
512 array_push($validationErrors, $errors);
513 continue;
514 }
515 // store valid value
516 array_push($elementsValues['options'], $this->_addQuestionElements['options'][$i]->getValue());
517 }
518
519 // print errors
520 if (! empty($validationErrors)) {
521 $this->_siteOverview();
522 $this->_tmpl->setAttribute('validationErrors', 'visibility', 'visible');
523
524 foreach ($validationErrors as $elErrors) {
525 $elTitle = $elErrors['elTitle'];
526 unset($elErrors['elTitle']);
527 foreach ($elErrors as $error) {
528 $this->_tmpl->addVar('validationErrorsEntry', 'ELEMENT_TITLE', $elTitle);
529 $this->_tmpl->addVar('validationErrorsEntry', 'ERRORMESSAGE', $error['message']);
530 $this->_tmpl->parseTemplate('validationErrorsEntry', 'a');
531 }
532 }
533 return true;
534 }
535
536 // no errors -> modify db-data
537 $question = $_POST['spQuestion'];
538 $options = $_POST['spOptions'];
539 $cnt = count($options);
540 for ($i = 0; $i < $cnt; $i++) {
541 if (empty($options[$i])) {
542 unset($options[$i]);
543 }
544 }
545 // delete question and options
546 $result = $this->_updateQuestion($qId, $question, $options);
547 if (PEAR::isError($result)) {
548 $this->_siteOverview();
549 $this->_tmpl->setAttribute('errors', 'visibility', 'visible');
550 $this->_tmpl->addVar('errorEntry', 'ERRORMESSAGE', 'Could not modify question!');
551 return true;
552 }
553
554 $this->_siteQuestionDetail($qId);
555 return true;
556 }
557
558 /**
559 * Resets a question - All votes are deleted
560 *
561 * @access private
562 */
563 function _siteQuestionReset()
564 {
565 if (! isset($_GET['spQId']) || empty($_GET['spQId'])) {
566 $this->_siteOverview();
567 $this->_tmpl->setAttribute('errors', 'visibility', 'visible');
568 $this->_tmpl->addVar('errorEntry', 'ERRORMESSAGE', 'No question-id found - unable to show requested site!');
569 return true;
570 }
571 $qId = $_GET['spQId'];
572 $result = $this->_deleteVotes($qId);
573 if (PEAR::isError($result)) {
574 $this->_siteOverview();
575 $this->_tmpl->setAttribute('errors', 'visibility', 'visible');
576 $this->_tmpl->addVar('errorEntry', 'ERRORMESSAGE', 'DB-error while trying to reset question! Try again.');
577 return true;
578 }
579
580 $this->_siteQuestionDetail($qId);
581 }
582
583 /**
584 * Deletes a question and its options
585 *
586 * @access private
587 */
588 function _siteQuestionDelete()
589 {
590 if (! isset($_GET['spQId']) || empty($_GET['spQId'])) {
591 $this->_siteOverview();
592 $this->_tmpl->setAttribute('errors', 'visibility', 'visible');
593 $this->_tmpl->addVar('errorEntry', 'ERRORMESSAGE', 'No question-id found - unable to show requested site!');
594 return true;
595 }
596 $qId = $_GET['spQId'];
597 $result = $this->_deleteQuestion($qId);
598 if (PEAR::isError($result)) {
599 $this->_siteOverview();
600 $this->_tmpl->setAttribute('errors', 'visibility', 'visible');
601 $this->_tmpl->addVar('errorEntry', 'ERRORMESSAGE', 'DB-error while trying to delete question! Try again.');
602 return true;
603 }
604
605 $this->_siteOverview();
606 }
607
608 /**
609 * Shows a site that allows changing the question and its options
610 *
611 * @access private
612 */
613 function _siteQuestionChange()
614 {
615 if (! isset($_GET['spQId']) || empty($_GET['spQId'])) {
616 $this->_siteOverview();
617 $this->_tmpl->setAttribute('errors', 'visibility', 'visible');
618 $this->_tmpl->addVar('errorEntry', 'ERRORMESSAGE', 'No question-id found - unable to show requested site!');
619 return true;
620 }
621 $qId = $_GET['spQId'];
622
623 // create form and set values
624 $question = $this->_getQuestionFromDB($qId);
625 $options = $this->_getOptionsFromDB($qId);
626 if (PEAR::isError($question) || PEAR::isError($options)) {
627 $this->_siteOverview();
628 $this->_tmpl->setAttribute('errors', 'visibility', 'visible');
629 $this->_tmpl->addVar('errorEntry', 'ERRORMESSAGE', 'DB-error while loading site to change question! Try again.');
630 return true;
631 }
632
633 $this->_tmpl->addGlobalVar('QUESTION_ID', $qId);
634
635 // build needed form elements
636 $this->_buildAddQuestionElements();
637
638 $this->_tmpl->readTemplatesFromFile('admin_qchange.tmpl');
639 $this->_tmpl->addVar('qChange', 'FORM_ACTION', $this->_dispatcher . '&spSite=modQuestion&spQId=' . $qId);
640 $this->_tmpl->addVar('qChange', 'QUESTION_ID', $qId);
641
642 // set form-element values
643 $this->_addQuestionElements['question']->setValue($question);
644 $this->_tmpl->addVar('qChange', 'FORM_QUESTION', $this->_addQuestionElements['question']->serialize());
645 for ($i = 0; $i < count($this->_addQuestionElements['options']); $i++) {
646 if (isset($options[$i + 1])) {
647 $this->_addQuestionElements['options'][$i]->setValue($options[$i + 1]);
648 }
649 $this->_tmpl->addVar('qOption', 'FORM_OPTION', $this->_addQuestionElements['options'][$i]->serialize());
650 $this->_tmpl->addVar('qOption', 'FORM_OPTION_NO', $i + 1);
651 $this->_tmpl->parseTemplate('qOption', 'a');
652 }
653 }
654
655 /**
656 * Changes the login-data
657 *
658 * @access private
659 */
660 function _changeLoginData()
661 {
662 // build needed form elements
663 $this->_buildChangeLoginFormElements();
664
665 $validationErrors = array();
666 $elementsValues = array();
667
668 // validate elements
669 $this->_changePasswdElements['username']->setSubmitted(true);
670 if (! $this->_changePasswdElements['username']->validate()) {
671 $errors = $this->_changePasswdElements['username']->getValidationErrors();
672 $errors['elTitle'] = $this->_changePasswdElements['username']->getAttribute('title');
673 array_push($validationErrors, $errors);
674 } else {
675 $elementsValues['username'] = $this->_changePasswdElements['username']->getValue();
676 }
677
678 $this->_changePasswdElements['password']->setSubmitted(true);
679 if (! $this->_changePasswdElements['password']->validate()) {
680 $errors = $this->_changePasswdElements['password']->getValidationErrors();
681 $errors['elTitle'] = $this->_changePasswdElements['password']->getAttribute('title');
682 array_push($validationErrors, $errors);
683 } else {
684 $elementsValues['password'] = $this->_changePasswdElements['password']->getValue();
685 }
686
687 // print errors
688 if (! empty($validationErrors)) {
689 $this->_siteOverview();
690 $this->_tmpl->setAttribute('validationErrors', 'visibility', 'visible');
691
692 foreach ($validationErrors as $elErrors) {
693 $elTitle = $elErrors['elTitle'];
694 unset($elErrors['elTitle']);
695 foreach ($elErrors as $error) {
696 $this->_tmpl->addVar('validationErrorsEntry', 'ELEMENT_TITLE', $elTitle);
697 $this->_tmpl->addVar('validationErrorsEntry', 'ERRORMESSAGE', $error['message']);
698 $this->_tmpl->parseTemplate('validationErrorsEntry', 'a');
699 }
700 }
701 return true;
702 }
703
704 // no errors -> change login-data
705 $this->_user->modifyUser(array('username' => $elementsValues['username'], 'password' => $elementsValues['password']));
706 $this->_siteOverview();
707 $this->_tmpl->setAttribute('information', 'visibility', 'visible');
708 $this->_tmpl->addVar('infoEntry', 'MESSAGE', 'Login data successfully changed!');
709 return true;
710 }
711
712 /**
713 * Delete a certain question and its options from DB
714 *
715 * @access private
716 * @param int $qId question-id
717 * @return boolean true on success, otherwise a PEAR_Error object
718 * @throws object PEAR_Error
719 */
720 function _deleteQuestion($qId)
721 {
722 $query = sprintf('DELETE FROM %squestions WHERE qId=%d', SP_DB_TABLEPREFIX, $qId);
723 $result = $this->_dbc->query($query);
724 if (PEAR::isError($result)) {
725 return $result;
726 }
727
728 $result = $this->_deleteOptions($qId);
729 if (PEAR::isError($result)) {
730 return $result;
731 }
732
733 $result = $this->_deleteVotes($qId);
734 if (PEAR::isError($result)) {
735 return $result;
736 }
737 return true;
738 }
739
740 /**
741 * Deletes options of a certain question from DB
742 *
743 * @access private
744 * @param int $qId question-id
745 * @return boolean true on success, otherwise a PEAR_Error object
746 * @throws object PEAR_Error
747 */
748 function _deleteOptions($qId)
749 {
750 $query = sprintf('DELETE FROM %soptions WHERE qId=%d', SP_DB_TABLEPREFIX, $qId);
751 $result = $this->_dbc->query($query);
752 if (PEAR::isError($result)) {
753 return $result;
754 }
755 return true;
756 }
757
758 /**
759 * Updates a certain question and its options
760 *
761 * @access private
762 * @param int $qId questionId
763 * @param string $question question
764 * @param array $options options
765 * @return boolean true on success, otherwise a PEAR_Error object
766 * @throws object PEAR_Error
767 */
768 function _updateQuestion($qId, $question, $options)
769 {
770 // update question
771 $query = sprintf('UPDATE %squestions SET question = %s WHERE qId = %d', SP_DB_TABLEPREFIX, $this->_dbc->quote($question), $qId);
772 $result = $this->_dbc->query($query);
773 if (PEAR::isError($result)) {
774 return $result;
775 }
776 // backup current options
777 $optionsBak = $this->_getOptionsFromDB($qId);
778 if (PEAR::isError($optionsBak)) {
779 return PEAR::raiseError('Unable to update question because of unstable database', SP_ADMIN_UPDATEQUESTION_TOO_INSECURE);
780 }
781 $result = $this->_deleteOptions($qId);
782 if (PEAR::isError($result)) {
783 return $result;
784 }
785 $result = $this->_saveOptions($qId, $options);
786 if (PEAR::isError($result)) {
787 return $this->_saveOptions($qId, $optionsBak);
788 }
789 // clean up overfluent votes in case the number of options has reduced
790 $diff = count($optionsBak) - count($options);
791 if ($diff > 0) {
792 for ($i = count($options) + 1; $i < count($options) + 1 + $diff; $i++) {
793 $result = $this->_deleteVotes($qId, $i);
794 if (PEAR::isError($result)) {
795 return $result;
796 }
797 }
798 }
799 return true;
800 }
801
802 /**
803 * Deletes votes for the given question-id (and option-id if given)
804 *
805 * @access private
806 * @param int $qId question-id
807 * @param int $oId option-id
808 * @return boolean true on success, otherwise a PEAR_Error object
809 * @throws object PEAR_Error
810 */
811 function _deleteVotes($qId, $oId = null)
812 {
813 $query = sprintf('DELETE FROM %svotes WHERE qId = %d', SP_DB_TABLEPREFIX, $qId);
814 if (! is_null($oId)) {
815 $query .= sprintf(' AND oId = %d', $oId);
816 }
817 $result = $this->_dbc->query($query);
818 if (PEAR::isError($result)) {
819 return $result;
820 }
821 return true;
822 }
823
824 /**
825 * Save a question and its options to DB
826 *
827 * @access private
828 * @param string $question question
829 * @param array $options options
830 * @return int question-id on success, else PEAR_Error object
831 * @throws object PEAR_Error
832 */
833 function _saveQuestion($question, $options)
834 {
835 $qId = $this->_dbc->nextId(SP_DB_TABLEPREFIX . 'questions');
836 $query = sprintf('INSERT INTO %squestions (qId, question) VALUES (%d, %s)',
837 SP_DB_TABLEPREFIX, $qId, $this->_dbc->quote($question));
838 $result = $this->_dbc->query($query);
839 if (PEAR::isError($result)) {
840 return $result;
841 }
842 $result = $this->_saveOptions($qId, $options);
843 if (PEAR::isError($result)) {
844 return $result;
845 }
846 return $qId;
847 }
848
849 /**
850 * Saves an array of options to DB
851 *
852 * @access private
853 * @param int $qId questionId
854 * @param array $options options
855 * @return boolean true on success, otherwise a PEAR_Error object
856 * @throws object PEAR_Error
857 */
858 function _saveOptions($qId, $options)
859 {
860 // make sure $options starts from zero
861 $options = array_values($options);
862
863 foreach ($options as $index => $option) {
864 $result = $this->_saveOption($qId, $index + 1, $option);
865 if (PEAR::isError($result)) {
866 $this->_deleteQuestion($qId);
867 return $result;
868 }
869 }
870 return true;
871 }
872
873 /**
874 * Saves an option to DB
875 *
876 * @access private
877 * @param int $qId questionId
878 * @param int $oId optionId
879 * @param string $option option text
880 * @return boolean true on success, otherwise a PEAR_Error object
881 * @throws object PEAR_Error
882 */
883 function _saveOption($qId, $oId, $option)
884 {
885 $query = sprintf('INSERT INTO %soptions (qId, oId, answer) VALUES(%d, %d, %s)',
886 SP_DB_TABLEPREFIX, $qId, $oId, $this->_dbc->quote($option));
887 $result = $this->_dbc->query($query);
888 if (PEAR::isError($result)) {
889 return $result;
890 }
891 return true;
892 }
893
894 /**
895 * Reads all available questions from db
896 *
897 * @access private
898 * @return array array with questionIds as key and questions as corresponding value
899 */
900 function _getQuestionsFromDB()
901 {
902 $questions = array();
903
904 $query = 'SELECT qId, question FROM ' . SP_DB_TABLEPREFIX . 'questions';
905 $result = $this->_dbc->query($query);
906 if (PEAR::isError($result)) {
907 return array();
908 }
909
910 while ($row = $result->fetchRow()) {
911 $questions[$row['qId']] = $row['question'];
912 }
913 return $questions;
914 }
915 }
916 ?>
Documentation generated on Fri, 19 Nov 2004 23:51:51 +0100 by phpDocumentor 1.2.3