Merge branch 'MDL-24255' of git://github.com/timhunt/moodle
authorSam Hemelryk <sam@moodle.com>
Mon, 20 Jun 2011 07:51:59 +0000 (15:51 +0800)
committerSam Hemelryk <sam@moodle.com>
Mon, 20 Jun 2011 07:51:59 +0000 (15:51 +0800)
20 files changed:
backup/cc/includes/constants.php
backup/moodle2/restore_stepslib.php
lang/en/question.php
lib/db/services.php
mod/quiz/index.php
mod/quiz/lang/en/quiz.php
mod/quiz/locallib.php
mod/quiz/renderer.php
mod/quiz/review.php
mod/quiz/reviewquestion.php
question/behaviour/adaptive/behaviour.php
question/behaviour/adaptive/lang/en/qbehaviour_adaptive.php
question/behaviour/immediatefeedback/behaviour.php
question/behaviour/immediatefeedback/lang/en/qbehaviour_immediatefeedback.php
question/type/calculated/edit_calculated_form.php
question/type/calculatedsimple/edit_calculatedsimple_form.php
question/type/multianswer/edit_multianswer_form.php
question/type/multianswer/lang/en/qtype_multianswer.php
user/externallib.php
version.php

index 84d08c0..58925d1 100644 (file)
@@ -92,5 +92,3 @@ define('MOODLE_QUIZ_MULTIPLE_RESPONSE', 'multichoice');
 define('MOODLE_QUIZ_MACHT', 'match');
 define('MOODLE_QUIZ_ESSAY', 'essay');
 define('MOODLE_QUIZ_SHORTANSWER', 'shortanswer');
-
-?>
index 2904c9e..e87a292 100644 (file)
@@ -1,4 +1,3 @@
-
 <?php
 
 // This file is part of Moodle - http://moodle.org/
index 50392bd..dbde0c3 100644 (file)
@@ -62,6 +62,7 @@ $string['categorycurrent'] = 'Current category';
 $string['categorycurrentuse'] = 'Use this category';
 $string['categorydoesnotexist'] = 'This category does not exist';
 $string['categoryinfo'] = 'Category info';
+$string['categorymove'] = 'The category \'{$a->name}\' contains {$a->count} questions (some of them may be old, hidden, questions that are still in use in some existing quizzes). Please choose another category to move them to.';
 $string['categorymoveto'] = 'Save in category';
 $string['categorynamecantbeblank'] = 'The category name cannot be blank.';
 $string['clicktoflag'] = 'Click to flag this question';
index 37cb7c1..53c1309 100644 (file)
@@ -129,6 +129,15 @@ $functions = array(
         'capabilities'=> 'moodle/user:viewdetails, moodle/user:viewhiddendetails, moodle/course:useremail, moodle/user:update',
     ),
 
+    'moodle_user_get_course_participants_by_id' => array(
+        'classname'   => 'moodle_user_external',
+        'methodname'  => 'get_course_participants_by_id',
+        'classpath'   => 'user/externallib.php',
+        'description' => 'Get course user profiles by id.',
+        'type'        => 'read',
+        'capabilities'=> 'moodle/user:viewdetails, moodle/user:viewhiddendetails, moodle/course:useremail, moodle/user:update, moodle/site:accessallgroups',
+    ),
+
     'moodle_user_delete_users' => array(
         'classname'   => 'moodle_user_external',
         'methodname'  => 'delete_users',
@@ -248,6 +257,7 @@ $services = array(
             'moodle_user_get_users_by_id',
             'moodle_webservice_get_siteinfo',
             'moodle_notes_create_notes',
+            'moodle_user_get_course_participants_by_id',
             'moodle_message_send_messages'),
         'enabled' => 0,
         'restrictedusers' => 0,
index 794d24c..926fa2e 100644 (file)
@@ -177,7 +177,7 @@ foreach ($quizzes as $quiz) {
                 $grade = get_string('outofshort', 'quiz', $a);
             }
             if ($alloptions->overallfeedback) {
-                $feedback = quiz_feedback_for_grade($grades[$quiz->id], $quiz, $context, $cm);
+                $feedback = quiz_feedback_for_grade($grades[$quiz->id], $quiz, $context);
             }
         }
         $data[] = $grade;
index cd81944..1158506 100644 (file)
@@ -141,8 +141,6 @@ $string['categories'] = 'Categories';
 $string['category'] = 'Category';
 $string['categoryadded'] = 'The category \'{$a}\' was added';
 $string['categorydeleted'] = 'The category \'{$a}\' was deleted';
-$string['categorymove'] = 'The category \'{$a->name}\' contains {$a->count} questions (some of them may be old, hidden, questions that are still in use in some existing quizzes).<br />Please choose another category to move them to.';
-$string['categorymoveto'] = 'Move them to this category';
 $string['categorynoedit'] = 'You do not have editing privileges in the category \'{$a}\'.';
 $string['categoryupdated'] = 'The category was successfully updated';
 $string['close'] = 'Close window';
index f9f57c9..04b7bbe 100644 (file)
@@ -634,7 +634,7 @@ function quiz_update_all_final_grades($quiz) {
                 MIN(attempt) AS firstattempt,
                 MAX(attempt) AS lastattempt
 
-            FROM {quiz_attempts iquiza}
+            FROM {quiz_attempts} iquiza
 
             WHERE
                 iquiza.timefinish <> 0 AND
index e957156..eee2959 100644 (file)
@@ -59,6 +59,49 @@ class mod_quiz_renderer extends plugin_renderer_base {
         return $output;
     }
 
+    /**
+     * Renders the review question pop-up.
+     *
+     * @param quiz_attempt $attemptobj an instance of quiz_attempt.
+     * @param int $slot which question to display.
+     * @param int $seq which step of the question attempt to show. null = latest.
+     * @param mod_quiz_display_options $displayoptions instance of mod_quiz_display_options.
+     * @param array $summarydata contains all table data
+     * @return $output containing html data.
+     */
+    public function review_question_page(quiz_attempt $attemptobj, $slot, $seq,
+            mod_quiz_display_options $displayoptions, $summarydata) {
+
+        $output = '';
+        $output .= $this->header();
+        $output .= $this->review_summary_table($summarydata, 0);
+
+        if (!is_null($seq)) {
+            $output .= $attemptobj->render_question_at_step($slot, $seq, true, $this->page->url);
+        } else {
+            $output .= $attemptobj->render_question($slot, true, $this->page->url);
+        }
+
+        $output .= $this->close_window_button();
+        $output .= $this->footer();
+        return $output;
+    }
+
+    /**
+     * Renders the review question pop-up.
+     *
+     * @param string $message Why the review is not allowed.
+     * @return string html to output.
+     */
+    public function review_question_not_allowed($message) {
+        $output = '';
+        $output .= $this->header();
+        $output .= $this->notification($message);
+        $output .= $this->close_window_button();
+        $output .= $this->footer();
+        return $output;
+    }
+
     /**
      * Filters the summarydata array.
      *
@@ -88,8 +131,7 @@ class mod_quiz_renderer extends plugin_renderer_base {
      * @param int $page contains the current page number
      */
     public function review_summary_table($summarydata, $page) {
-                                         $summarydata = $this->filter_summary_table($summarydata,
-                                         $page);
+        $summarydata = $this->filter_summary_table($summarydata, $page);
         if (empty($summarydata)) {
             return '';
         }
@@ -758,7 +800,7 @@ class mod_quiz_renderer extends plugin_renderer_base {
 
             if ($viewobj->feedbackcolumn && $attempt->timefinish > 0) {
                 if ($attemptoptions->overallfeedback) {
-                    $row[] = quiz_feedback_for_grade($attemptgrade, $quiz, $context, $cm);
+                    $row[] = quiz_feedback_for_grade($attemptgrade, $quiz, $context);
                 } else {
                     $row[] = '';
                 }
@@ -838,7 +880,7 @@ class mod_quiz_renderer extends plugin_renderer_base {
         if ($viewobj->feedbackcolumn) {
             $resultinfo .= $this->heading(get_string('overallfeedback', 'quiz'), 3, 'main');
             $resultinfo .= html_writer::tag('p',
-                    quiz_feedback_for_grade($viewobj->mygrade, $quiz, $context, $cm),
+                    quiz_feedback_for_grade($viewobj->mygrade, $quiz, $context),
                     array('class' => 'quizgradefeedback')).'\n';
         }
 
@@ -997,4 +1039,4 @@ class mod_quiz_view_object {
      * @var int $lastfinishedattempt contains a pointer to the last attempt in the attempts array.
      */
     public $lastfinishedattempt;
-}
\ No newline at end of file
+}
index 3f7b2b7..9d3c4ab 100644 (file)
@@ -135,9 +135,7 @@ if ($attempt->timefinish) {
     $timetaken = get_string('unfinished', 'quiz');
 }
 
-// Print summary table about the whole attempt.
-// First we assemble all the rows that are appopriate to the current situation in
-// an array, then later we only output the table if there are any rows to show.
+// Prepare summary informat about the whole attempt.
 $summarydata = array();
 if (!$attemptobj->get_quiz()->showuserpicture && $attemptobj->get_userid() != $USER->id) {
     // If showuserpicture is true, the picture is shown elsewhere, so don't repeat it.
index 583a18e..30560ba 100644 (file)
@@ -39,7 +39,6 @@ if ($seq !== 0) {
     $currenturl->param('step', $seq);
 }
 $PAGE->set_url($currenturl);
-$PAGE->set_pagelayout('popup');
 
 $attemptobj = quiz_attempt::create($attemptid);
 
@@ -47,21 +46,18 @@ $attemptobj = quiz_attempt::create($attemptid);
 require_login($attemptobj->get_courseid(), false, $attemptobj->get_cm());
 $attemptobj->check_review_capability();
 
-echo $OUTPUT->header();
+$PAGE->set_pagelayout('popup');
+$output = $PAGE->get_renderer('mod_quiz');
 
 // Check permissions.
 if ($attemptobj->is_own_attempt()) {
     if (!$attemptobj->is_finished()) {
-        echo $OUTPUT->notification(get_string('cannotreviewopen', 'quiz'));
-        echo $OUTPUT->close_window_button();
-        echo $OUTPUT->footer();
+        echo $output->review_question_not_allowed(get_string('cannotreviewopen', 'quiz'));
         die();
     } else if (!$options->responses) {
         $accessmanager = $attemptobj->get_access_manager(time());
-        echo $OUTPUT->notification($accessmanager->cannot_review_message(
-                $attemptobj->get_review_options()));
-        echo $OUTPUT->close_window_button();
-        echo $OUTPUT->footer();
+        echo $output->review_question_not_allowed(
+                $accessmanager->cannot_review_message($attemptobj->get_review_options()));
         die();
     }
 
@@ -69,44 +65,40 @@ if ($attemptobj->is_own_attempt()) {
     throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'noreviewattempt');
 }
 
+// Prepare summary informat about this question attempt.
+$summarydata = array();
+
 // Quiz name.
-$rows[] = '<tr><th scope="row" class="cell">' . get_string('modulename', 'quiz') .
-        '</th><td class="cell">' . format_string($attemptobj->get_quiz_name()) . '</td></tr>';
+$summarydata['quizname'] = array(
+    'title'   => get_string('modulename', 'quiz'),
+    'content' => format_string($attemptobj->get_quiz_name()),
+);
 
 // Question name.
-$rows[] = '<tr><th scope="row" class="cell">' . get_string('question', 'quiz') .
-        '</th><td class="cell">' . format_string(
-        $attemptobj->get_question_name($slot)) . '</td></tr>';
+$summarydata['questionname'] = array(
+    'title'   => get_string('question', 'quiz'),
+    'content' => $attemptobj->get_question_name($slot),
+);
 
 // Other attempts at the quiz.
 if ($attemptobj->has_capability('mod/quiz:viewreports')) {
     $attemptlist = $attemptobj->links_to_other_attempts($baseurl);
     if ($attemptlist) {
-        $rows[] = '<tr><th scope="row" class="cell">' . get_string('attempts', 'quiz') .
-                '</th><td class="cell">' . $attemptlist . '</td></tr>';
+        $summarydata['attemptlist'] = array(
+            'title'   => get_string('attempts', 'quiz'),
+            'content' => $attemptlist,
+        );
     }
 }
 
 // Timestamp of this action.
 $timestamp = $attemptobj->get_question_action_time($slot);
 if ($timestamp) {
-    $rows[] = '<tr><th scope="row" class="cell">' . get_string('completedon', 'quiz') .
-            '</th><td class="cell">' . userdate($timestamp) . '</td></tr>';
-}
-
-// Now output the summary table, if there are any rows to be shown.
-if (!empty($rows)) {
-    echo '<table class="generaltable generalbox quizreviewsummary"><tbody>', "\n";
-    echo implode("\n", $rows);
-    echo "\n</tbody></table>\n";
-}
-
-// Print the question in the requested state.
-if (!is_null($seq)) {
-    echo $attemptobj->render_question_at_step($slot, $seq, true, $currenturl);
-} else {
-    echo $attemptobj->render_question($slot, true, $currenturl);
+    $summarydata['timestamp'] = array(
+        'title'   => get_string('completedon', 'quiz'),
+        'content' => userdate($timestamp),
+    );
 }
 
-// Finish the page
-echo $OUTPUT->footer();
+echo $output->review_question_page($attemptobj, $slot, $seq,
+        $attemptobj->get_display_options(true), $summarydata);
index 7e8ad03..5bcee3b 100644 (file)
@@ -49,6 +49,22 @@ class qbehaviour_adaptive extends question_behaviour_with_save {
         return parent::get_expected_data();
     }
 
+    public function get_state_string($showcorrectness) {
+        $laststep = $this->qa->get_last_step();
+        if ($laststep->has_behaviour_var('_try')) {
+            $state = question_state::graded_state_for_fraction(
+                    $laststep->get_behaviour_var('_rawfraction'));
+            return $state->default_string(true);
+        }
+
+        $state = $this->qa->get_state();
+        if ($state == question_state::$todo) {
+            return get_string('notcomplete', 'qbehaviour_adaptive');
+        } else {
+            return parent::get_state_string($showcorrectness);
+        }
+    }
+
     public function get_right_answer_summary() {
         return $this->question->get_right_answer_summary();
     }
@@ -61,18 +77,6 @@ class qbehaviour_adaptive extends question_behaviour_with_save {
         }
     }
 
-    public function get_state_string($showcorrectness) {
-        $state = $this->qa->get_state();
-
-        $laststep = $this->qa->get_last_step();
-        if ($laststep->has_behaviour_var('_try')) {
-            $state = question_state::graded_state_for_fraction(
-                    $laststep->get_behaviour_var('_rawfraction'));
-        }
-
-        return $state->default_string($showcorrectness);
-    }
-
     public function process_action(question_attempt_pending_step $pendingstep) {
         if ($pendingstep->has_behaviour_var('comment')) {
             return $this->process_comment($pendingstep);
index 0bb96fa..ca97f54 100644 (file)
@@ -26,4 +26,5 @@
 $string['gradingdetails'] = 'Marks for this submission: {$a->raw}/{$a->max}.';
 $string['gradingdetailsadjustment'] = 'With previous penalties this gives <strong>{$a->cur}/{$a->max}</strong>.';
 $string['gradingdetailspenalty'] = 'This submission attracted a penalty of {$a}.';
+$string['notcomplete'] = 'Not complete';
 $string['pluginname'] = 'Adaptive mode';
index 21238e3..2e7bbe0 100644 (file)
@@ -59,6 +59,15 @@ class qbehaviour_immediatefeedback extends question_behaviour_with_save {
         return parent::get_expected_data();
     }
 
+    public function get_state_string($showcorrectness) {
+        $state = $this->qa->get_state();
+        if ($state == question_state::$todo) {
+            return get_string('notcomplete', 'qbehaviour_immediatefeedback');
+        } else {
+            return parent::get_state_string($showcorrectness);
+        }
+    }
+
     public function get_right_answer_summary() {
         return $this->question->get_right_answer_summary();
     }
index 6c4f023..84e3688 100644 (file)
@@ -23,4 +23,5 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+$string['notcomplete'] = 'Not complete';
 $string['pluginname'] = 'Immediate feedback';
index 194239e..ccab22d 100644 (file)
@@ -73,28 +73,15 @@ class qtype_calculated_edit_form extends qtype_numerical_edit_form {
 
     public function get_per_answer_fields($mform, $label, $gradeoptions,
             &$repeatedoptions, &$answersoption) {
-        $repeated = array();
-        $repeated[] = $mform->createElement('header', 'answerhdr', $label);
-        $repeated[] = $mform->createElement('text', 'answer',
-                get_string('answer', 'question'), array('size' => 50));
-        $repeated[] = $mform->createElement('select', 'fraction',
-                get_string('grade'), $gradeoptions);
-        $repeated[] = $mform->createElement('editor', 'feedback',
-                get_string('feedback', 'question'), null, $this->editoroptions);
-        $repeatedoptions['answer']['type'] = PARAM_RAW;
-        $repeatedoptions['fraction']['default'] = 0;
-        $answersoption = 'answers';
-
-        $mform->setType('answer', PARAM_NOTAGS);
+        $repeated = parent::get_per_answer_fields($mform, $label, $gradeoptions,
+                $repeatedoptions, $answersoption);
+
+        $repeated[1]->setLabel(get_string('correctanswerformula', 'qtype_calculated') . '=');
+        $repeatedoptions['tolerance']['default'] = 0.01;
 
         $addrepeated = array();
-        $addrepeated[] = $mform->createElement('text', 'tolerance',
-                get_string('tolerance', 'qtype_calculated'));
         $addrepeated[] = $mform->createElement('select', 'tolerancetype',
-                get_string('tolerancetype', 'qtype_numerical'),
-                $this->qtypeobj->tolerance_types());
-        $repeatedoptions['tolerance']['type'] = PARAM_NUMBER;
-        $repeatedoptions['tolerance']['default'] = 0.01;
+                get_string('tolerancetype', 'qtype_numerical'), $this->qtypeobj->tolerance_types());
 
         $addrepeated[] = $mform->createElement('select', 'correctanswerlength',
                 get_string('correctanswershows', 'qtype_calculated'), range(0, 9));
@@ -106,8 +93,9 @@ class qtype_calculated_edit_form extends qtype_numerical_edit_form {
         );
         $addrepeated[] = $mform->createElement('select', 'correctanswerformat',
                 get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
-        array_splice($repeated, 3, 0, $addrepeated);
-        $repeated[1]->setLabel(get_string('correctanswerformula', 'qtype_calculated') . ' = ');
+
+        array_splice($repeated, 4, 0, $addrepeated);
+
         return $repeated;
     }
 
index 13a53df..5ba6cd1 100644 (file)
@@ -286,34 +286,6 @@ class qtype_calculatedsimple_edit_form extends qtype_calculated_edit_form {
         parent::__construct($submiturl, $question, $category, $contexts, $formeditable);
     }
 
-    public function get_per_answer_fields($mform, $label, $gradeoptions,
-            &$repeatedoptions, &$answersoption) {
-        $repeated = parent::get_per_answer_fields($mform, $label, $gradeoptions,
-                $repeatedoptions, $answersoption);
-        $mform->setType('answer', PARAM_NOTAGS);
-        $addrepeated = array();
-        $addrepeated[] = $mform->createElement('text', 'tolerance',
-                get_string('tolerance', 'qtype_calculated'));
-        $repeatedoptions['tolerance']['type'] = PARAM_NUMBER;
-        $repeatedoptions['tolerance']['default'] = 0.01;
-        $addrepeated[] = $mform->createElement('select', 'tolerancetype',
-                get_string('tolerancetype', 'qtype_numerical'), $this->qtypeobj->tolerance_types());
-        $addrepeated[] = $mform->createElement('select', 'correctanswerlength',
-                get_string('correctanswershows', 'qtype_calculated'), range(0, 9));
-        $repeatedoptions['correctanswerlength']['default'] = 2;
-
-        $answerlengthformats = array(
-            '1' => get_string('decimalformat', 'qtype_numerical'),
-            '2' => get_string('significantfiguresformat', 'qtype_calculated')
-        );
-        $addrepeated[] = $mform->createElement('select', 'correctanswerformat',
-                get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
-        array_splice($repeated, 3, 0, $addrepeated);
-        $repeated[1]->setLabel(get_string('correctanswerformula', 'qtype_calculated').'=');
-
-        return $repeated;
-    }
-
     /**
      * Add question-type specific form fields.
      *
index 415ff62..34c0c4e 100644 (file)
@@ -141,8 +141,6 @@ class qtype_multianswer_edit_form extends question_edit_form {
                 get_string('decodeverifyquestiontext', 'qtype_multianswer'));
         $mform->registerNoSubmitButton('analyzequestion');
         if ($this->reload) {
-            $mform->addElement('html', '<div class="ablock clearfix">');
-            $mform->addElement('html', '<div class=" clearfix">');
             for ($sub = 1; $sub <= $countsubquestions; $sub++) {
 
                 $this->editas[$sub] = 'unknown type';
@@ -151,15 +149,16 @@ class qtype_multianswer_edit_form extends question_edit_form {
                 } else if (optional_param('sub_'.$sub."_".'qtype', '', PARAM_RAW) != '') {
                     $this->editas[$sub] = optional_param('sub_'.$sub."_".'qtype', '', PARAM_RAW);
                 }
+
                 $storemess = '';
                 if (isset($this->savedquestiondisplay->options->questions[$sub]->qtype) &&
                         $this->savedquestiondisplay->options->questions[$sub]->qtype !=
                                 $this->questiondisplay->options->questions[$sub]->qtype) {
                     $this->qtype_change = true;
-                    $storemess = "<font class=\"error\"> STORED QTYPE " .
-                            question_bank::get_qtype_name(
-                            $this->savedquestiondisplay->options->questions[$sub]->qtype).
-                            "</font >";
+                    $storemess = ' ' . html_writer::tag('span', get_string(
+                            'storedqtype', 'qtype_multianswer', question_bank::get_qtype_name(
+                                    $this->savedquestiondisplay->options->questions[$sub]->qtype)),
+                            array('class' => 'error'));
                 }
 
                 $mform->addElement('header', 'subhdr'.$sub, get_string('questionno', 'question',
@@ -167,8 +166,7 @@ class qtype_multianswer_edit_form extends question_edit_form {
                         $this->questiondisplay->options->questions[$sub]->qtype).$storemess);
 
                 $mform->addElement('static', 'sub_'.$sub."_".'questiontext',
-                        get_string('questiondefinition', 'qtype_multianswer'),
-                        array('cols' => 60, 'rows' => 3));
+                        get_string('questiondefinition', 'qtype_multianswer'));
 
                 if (isset ($this->questiondisplay->options->questions[$sub]->questiontext)) {
                     $mform->setDefault('sub_'.$sub."_".'questiontext',
@@ -187,13 +185,12 @@ class qtype_multianswer_edit_form extends question_edit_form {
 
                 if ($this->questiondisplay->options->questions[$sub]->qtype == 'multichoice') {
                     $mform->addElement('static', 'sub_'.$sub."_".'layout',
-                            get_string('layout', 'qtype_multianswer'),
-                            array('cols' => 60, 'rows' => 1));
+                            get_string('layout', 'qtype_multianswer'));
                 }
-                foreach ($this->questiondisplay->options->questions[$sub]->answer as $key => $ans) {
 
+                foreach ($this->questiondisplay->options->questions[$sub]->answer as $key => $ans) {
                     $mform->addElement('static', 'sub_'.$sub."_".'answer['.$key.']',
-                            get_string('answer', 'question'), array('cols' => 60, 'rows' => 1));
+                            get_string('answer', 'question'));
 
                     if ($this->questiondisplay->options->questions[$sub]->qtype == 'numerical' &&
                             $key == 0) {
@@ -207,9 +204,8 @@ class qtype_multianswer_edit_form extends question_edit_form {
                     $mform->addElement('static', 'sub_'.$sub."_".'feedback['.$key.']',
                             get_string('feedback', 'question'));
                 }
-
             }
-            $mform->addElement('html', '</div>');
+
             $this->negative_diff = $countsavedsubquestions - $countsubquestions;
             if (($this->negative_diff > 0) ||$this->qtype_change ||
                     ($this->used_in_quiz && $this->negative_diff != 0)) {
@@ -226,7 +222,6 @@ class qtype_multianswer_edit_form extends question_edit_form {
                         get_string('questiontypechanged', 'qtype_multianswer')."</strong>",
                         get_string('questiontypechangedcomment', 'qtype_multianswer'));
             }
-            $mform->addElement('html', '</div>');
         }
         if ($this->used_in_quiz) {
             if ($this->negative_diff < 0) {
index fffd3ce..2ce8564 100644 (file)
@@ -60,6 +60,7 @@ $string['questionsaveasedited'] = 'The question will be saved as edited';
 $string['questiontypechanged'] = 'Question type changed';
 $string['questiontypechangedcomment'] = 'At least one question type has been changed.<br \>Did you add, delete or move a question?<br \>Look ahead.';
 $string['questionusedinquiz'] = 'This question is used in {$a->nb_of_quiz} quiz(s), total attempt(s) : {$a->nb_of_attempts} ';
+$string['storedqtype'] = 'Stored question type {$a}';
 $string['subqresponse'] = 'part {$a->i}: {$a->response}';
 $string['unknownquestiontypeofsubquestion'] = 'Unknown question type: {$a->type} of question part # {$a->sub}';
 $string['warningquestionmodified'] = '<b>WARNING</b>';
index 8296b48..fdc28bd 100644 (file)
@@ -363,13 +363,21 @@ class moodle_user_external extends external_api {
         $params = self::validate_parameters(self::get_users_by_id_parameters(),
                 array('userids'=>$userids));
 
-        $userscontexts = get_context_instance(CONTEXT_USER, $params['userids']);
+        list($uselect, $ujoin) = context_instance_preload_sql('u.id', CONTEXT_USER, 'ctx');
+        list($sqluserids, $params) = $DB->get_in_or_equal($userids);
+        $usersql = "SELECT u.* $uselect
+                      FROM {user} u $ujoin
+                     WHERE u.id $sqluserids";
+        $users = $DB->get_recordset_sql($usersql, $params);
 
-        $users = user_get_users_by_id($params['userids']);
         $result = array();
         foreach ($users as $user) {
-
-            $context = $userscontexts[$user->id];
+            if (!empty($user->deleted)) {
+                continue;
+            }
+            context_instance_preload($user);
+            // cached
+            $context = get_context_instance(CONTEXT_USER, $user->id);
             $hasviewdetailscap = has_capability('moodle/user:viewdetails', $context);
             $hasuserupdatecap = has_capability('moodle/user:update', get_system_context());
 
@@ -377,197 +385,193 @@ class moodle_user_external extends external_api {
 
             $currentuser = ($user->id == $USER->id);
 
-            if (empty($user->deleted)) {
+            if (!$currentuser && !$hasviewdetailscap && !has_coursecontact_role($user->id)) {
+                throw new moodle_exception('usernotavailable', 'error');
+            }
 
-                if (!$currentuser && !$hasviewdetailscap && !has_coursecontact_role($user->id)) {
-                    throw new moodle_exception('usernotavailable', 'error');
-                }
+            $userarray = array();
 
-                $userarray = array();
+            //basic fields
+            $userarray['id'] = $user->id;
+            if ($isadmin) {
+                $userarray['username'] = $user->username;
+            }
+            if ($isadmin or has_capability('moodle/site:viewfullnames', $context)) {
+                $userarray['firstname'] = $user->firstname;
+                $userarray['lastname'] = $user->lastname;
+            }
+            $userarray['fullname'] = fullname($user);
+
+            //fields matching permissions from /user/editadvanced.php
+            if ($currentuser or $hasuserupdatecap) {
+                $userarray['auth'] = $user->auth;
+                $userarray['confirmed'] = $user->confirmed;
+                $userarray['idnumber'] = $user->idnumber;
+                $userarray['lang'] = $user->lang;
+                $userarray['theme'] = $user->theme;
+                $userarray['timezone'] = $user->timezone;
+                $userarray['mailformat'] = $user->mailformat;
+            }
 
-                //basic fields
-                $userarray['id'] = $user->id;
-                if ($isadmin) {
-                    $userarray['username'] = $user->username;
-                }
-                if ($isadmin or has_capability('moodle/site:viewfullnames', $context)) {
-                    $userarray['firstname'] = $user->firstname;
-                    $userarray['lastname'] = $user->lastname;
-                }
-                $userarray['fullname'] = fullname($user);
-
-                //fields matching permissions from /user/editadvanced.php
-                if ($currentuser or $hasuserupdatecap) {
-                    $userarray['auth'] = $user->auth;
-                    $userarray['confirmed'] = $user->confirmed;
-                    $userarray['idnumber'] = $user->idnumber;
-                    $userarray['lang'] = $user->lang;
-                    $userarray['theme'] = $user->theme;
-                    $userarray['timezone'] = $user->timezone;
-                    $userarray['mailformat'] = $user->mailformat;
+            //Custom fields (matching /user/profil/lib.php - profile_display_fields code logic)
+            $fields = $DB->get_recordset_sql("SELECT f.*
+                                                FROM {user_info_field} f
+                                                JOIN {user_info_category} c
+                                                     ON f.categoryid=c.id
+                                            ORDER BY c.sortorder ASC, f.sortorder ASC");
+            foreach ($fields as $field) {
+                require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
+                $newfield = 'profile_field_'.$field->datatype;
+                $formfield = new $newfield($field->id, $user->id);
+                if ($formfield->is_visible() and !$formfield->is_empty()) {
+                    $userarray['customfields'][] =
+                        array('name' => $formfield->field->name, 'value' => $formfield->data,
+                            'type' => $field->datatype, 'shortname' => $formfield->field->shortname);
                 }
+            }
+            $fields->close();
+
+            //image profiles urls (public, no permission required in fact)
+            $profileimageurl = moodle_url::make_pluginfile_url($context->id, 'user', 'icon', NULL, '/', 'f1');
+            $userarray['profileimageurl'] = $profileimageurl->out(false);
+            $profileimageurlsmall = moodle_url::make_pluginfile_url($context->id, 'user', 'icon', NULL, '/', 'f2');
+            $userarray['profileimageurlsmall'] = $profileimageurlsmall->out(false);
+
+            //hidden user field
+            if (has_capability('moodle/user:viewhiddendetails', $context)) {
+                $hiddenfields = array();
+            } else {
+                $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
+            }
 
-                //Custom fields (matching /user/profil/lib.php - profile_display_fields code logic)
-                $userarray['customfields'] = array();
-                if ($categories = $DB->get_records('user_info_category', null, 'sortorder ASC')) {
-                    foreach ($categories as $category) {
-                        if ($fields = $DB->get_records('user_info_field', array('categoryid'=>$category->id), 'sortorder ASC')) {
-                            foreach ($fields as $field) {
-                                require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
-                                $newfield = 'profile_field_'.$field->datatype;
-                                $formfield = new $newfield($field->id, $user->id);
-                                if ($formfield->is_visible() and !$formfield->is_empty()) {
-                                    $userarray['customfields'][] =
-                                        array('name' => $formfield->field->name, 'value' => $formfield->data,
-                                            'type' => $field->datatype, 'shortname' => $formfield->field->shortname);
-                                }
-                            }
-                        }
-                    }
+            if (isset($user->description) && (!isset($hiddenfields['description']) or $isadmin)) {
+                if (empty($CFG->profilesforenrolledusersonly) || $currentuser) {
+                    $user->description = file_rewrite_pluginfile_urls($user->description, 'pluginfile.php', $context->id, 'user', 'profile', null);
+                    $userarray['description'] = $user->description;
+                    $userarray['descriptionformat'] = $user->descriptionformat;
                 }
+            }
 
-                //image profiles urls (public, no permission required in fact)
-                $profileimageurl = moodle_url::make_pluginfile_url($context->id, 'user', 'icon', NULL, '/', 'f1');
-                $userarray['profileimageurl'] = $profileimageurl->out(false);
-                $profileimageurlsmall = moodle_url::make_pluginfile_url($context->id, 'user', 'icon', NULL, '/', 'f2');
-                $userarray['profileimageurlsmall'] = $profileimageurlsmall->out(false);
+            if ((! isset($hiddenfields['country']) or $isadmin) && $user->country) {
+                $userarray['country'] = $user->country;
+            }
 
-                //hidden user field
-                if (has_capability('moodle/user:viewhiddendetails', $context)) {
-                    $hiddenfields = array();
-                } else {
-                    $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
-                }
+            if ((! isset($hiddenfields['city']) or $isadmin) && $user->city) {
+                $userarray['city'] = $user->city;
+            }
 
-                if (isset($user->description) && (!isset($hiddenfields['description']) or $isadmin)) {
-                    if (empty($CFG->profilesforenrolledusersonly) || $currentuser) {
-                        $user->description = file_rewrite_pluginfile_urls($user->description, 'pluginfile.php', $context->id, 'user', 'profile', null);
-                        $userarray['description'] = $user->description;
-                        $userarray['descriptionformat'] = $user->descriptionformat;
-                    }
+            if (has_capability('moodle/user:viewhiddendetails', $context)) {
+                if ($user->address) {
+                    $userarray['address'] = $user->address;
                 }
-
-                if ((! isset($hiddenfields['country']) or $isadmin) && $user->country) {
-                    $userarray['country'] = $user->country;
+                if ($user->phone1) {
+                    $userarray['phone1'] = $user->phone1;
                 }
-
-                if ((! isset($hiddenfields['city']) or $isadmin) && $user->city) {
-                    $userarray['city'] = $user->city;
+                if ($user->phone2) {
+                    $userarray['phone2'] = $user->phone2;
                 }
+            }
 
-                if (has_capability('moodle/user:viewhiddendetails', $context)) {
-                    if ($user->address) {
-                        $userarray['address'] = $user->address;
-                    }
-                    if ($user->phone1) {
-                        $userarray['phone1'] = $user->phone1;
-                    }
-                    if ($user->phone2) {
-                        $userarray['phone2'] = $user->phone2;
-                    }
-                }
+            if ($currentuser
+              or $user->maildisplay == 1
+              or has_capability('moodle/course:useremail', $context)
+              or ($user->maildisplay == 2 and enrol_sharing_course($user, $USER))) {
+                $userarray['email'] = $user->email;;
+            }
 
-                if ($currentuser
-                  or $user->maildisplay == 1
-                  or has_capability('moodle/course:useremail', $context)
-                  or ($user->maildisplay == 2 and enrol_sharing_course($user, $USER))) {
-                    $userarray['email'] = $user->email;;
+            if ($user->url && (!isset($hiddenfields['webpage']) or $isadmin)) {
+                $url = $user->url;
+                if (strpos($user->url, '://') === false) {
+                    $url = 'http://'. $url;
                 }
+                $user->url = clean_param($user->url, PARAM_URL);
+                $userarray['url'] = $user->url;
+            }
 
-                if ($user->url && (!isset($hiddenfields['webpage']) or $isadmin)) {
-                    $url = $user->url;
-                    if (strpos($user->url, '://') === false) {
-                        $url = 'http://'. $url;
-                    }
-                    $user->url = clean_param($user->url, PARAM_URL);
-                    $userarray['url'] = $user->url;
-                }
+            if ($user->icq && (!isset($hiddenfields['icqnumber']) or $isadmin)) {
+                $userarray['icq'] = $user->icq;
+            }
 
-                if ($user->icq && (!isset($hiddenfields['icqnumber']) or $isadmin)) {
-                    $userarray['icq'] = $user->icq;
-                }
+            if ($user->skype && (!isset($hiddenfields['skypeid']) or $isadmin)) {
+                $userarray['skype'] = $user->skype;
+            }
+            if ($user->yahoo && (!isset($hiddenfields['yahooid']) or $isadmin)) {
+                $userarray['yahoo'] = $user->yahoo;
+            }
+            if ($user->aim && (!isset($hiddenfields['aimid']) or $isadmin)) {
+                $userarray['aim'] = $user->aim;
+            }
+            if ($user->msn && (!isset($hiddenfields['msnid']) or $isadmin)) {
+                $userarray['msn'] = $user->msn;
+            }
 
-                if ($user->skype && (!isset($hiddenfields['skypeid']) or $isadmin)) {
-                    $userarray['skype'] = $user->skype;
-                }
-                if ($user->yahoo && (!isset($hiddenfields['yahooid']) or $isadmin)) {
-                    $userarray['yahoo'] = $user->yahoo;
+            if ((!isset($hiddenfields['firstaccess'])) or $isadmin) {
+                if ($user->firstaccess) {
+                    $userarray['firstaccess'] = $user->firstaccess;
+                } else {
+                    $userarray['firstaccess'] = 0;
                 }
-                if ($user->aim && (!isset($hiddenfields['aimid']) or $isadmin)) {
-                    $userarray['aim'] = $user->aim;
+            }
+            if ((!isset($hiddenfields['lastaccess'])) or $isadmin) {
+                if ($user->lastaccess) {
+                    $userarray['lastaccess'] = $user->lastaccess;
+                } else {
+                    $userarray['lastaccess'] = 0;
                 }
-                if ($user->msn && (!isset($hiddenfields['msnid']) or $isadmin)) {
-                    $userarray['msn'] = $user->msn;
+            }
+            /// Printing tagged interests
+            if (!empty($CFG->usetags)) {
+                require_once($CFG->dirroot . '/tag/lib.php');
+                if ($interests = tag_get_tags_csv('user', $user->id, TAG_RETURN_TEXT) ) {
+                    $userarray['interests'] = $interests;
                 }
+            }
 
-                if ((!isset($hiddenfields['firstaccess'])) or $isadmin) {
-                    if ($user->firstaccess) {
-                        $userarray['firstaccess'] = $user->firstaccess;
-                    } else {
-                        $userarray['firstaccess'] = 0;
-                    }
-                }
-                if ((!isset($hiddenfields['lastaccess'])) or $isadmin) {
-                    if ($user->lastaccess) {
-                        $userarray['lastaccess'] = $user->lastaccess;
-                    } else {
-                        $userarray['lastaccess'] = 0;
-                    }
+            //Departement/Institution are not displayed on any profile, however you can get them from editing profile.
+            if ($isadmin or $currentuser) {
+                if ($user->institution) {
+                    $userarray['institution'] = $user->institution;
                 }
-                /// Printing tagged interests
-                if (!empty($CFG->usetags)) {
-                    require_once($CFG->dirroot . '/tag/lib.php');
-                    if ($interests = tag_get_tags_csv('user', $user->id, TAG_RETURN_TEXT) ) {
-                        $userarray['interests'] = $interests;
-                    }
-                }
-
-                //Departement/Institution are not displayed on any profile, however you can get them from editing profile.
-                if ($isadmin or $currentuser) {
-                    if ($user->institution) {
-                        $userarray['institution'] = $user->institution;
-                    }
-                    if (isset($user->department)) { //isset because it's ok to have department 0
-                        $userarray['department'] = $user->department;
-                    }
+                if (isset($user->department)) { //isset because it's ok to have department 0
+                    $userarray['department'] = $user->department;
                 }
+            }
 
-                //list of courses where the user is enrolled
-                $enrolledcourses = array();
-                if (!isset($hiddenfields['mycourses'])) {
-                    if ($mycourses = enrol_get_users_courses($user->id, true, NULL, 'visible DESC,sortorder ASC')) {
-                        $courselisting = '';
-                        foreach ($mycourses as $mycourse) {
-                            if ($mycourse->category) {
-                                if ($mycourse->visible == 0) {
-                                    $ccontext = get_context_instance(CONTEXT_COURSE, $mycourse->id);
-                                    if (!has_capability('moodle/course:viewhiddencourses', $ccontext)) {
-                                        continue;
-                                    }
+            //list of courses where the user is enrolled
+            $enrolledcourses = array();
+            if (!isset($hiddenfields['mycourses'])) {
+                if ($mycourses = enrol_get_users_courses($user->id, true, NULL, 'visible DESC,sortorder ASC')) {
+                    $courselisting = '';
+                    foreach ($mycourses as $mycourse) {
+                        if ($mycourse->category) {
+                            if ($mycourse->visible == 0) {
+                                $ccontext = get_context_instance(CONTEXT_COURSE, $mycourse->id);
+                                if (!has_capability('moodle/course:viewhiddencourses', $ccontext)) {
+                                    continue;
                                 }
-                                $enrolledcourse = array();
-                                $enrolledcourse['id'] = $mycourse->id;
-                                $enrolledcourse['fullname'] = $mycourse->fullname;
-                                $enrolledcourses[] = $enrolledcourse;
                             }
+                            $enrolledcourse = array();
+                            $enrolledcourse['id'] = $mycourse->id;
+                            $enrolledcourse['fullname'] = $mycourse->fullname;
+                            $enrolledcourses[] = $enrolledcourse;
                         }
-                        $userarray['enrolledcourses'] = $enrolledcourses;
                     }
-                }
-
-                //user preferences
-                if ($currentuser) {
-                    $preferences = array();
-                    $userpreferences = get_user_preferences();
-                     foreach($userpreferences as $prefname => $prefvalue) {
-                        $preferences[] = array('name' => $prefname, 'value' => $prefvalue);
-                     }
-                     $userarray['preferences'] = $preferences;
+                    $userarray['enrolledcourses'] = $enrolledcourses;
                 }
             }
 
+            //user preferences
+            if ($currentuser) {
+                $preferences = array();
+                $userpreferences = get_user_preferences();
+                 foreach($userpreferences as $prefname => $prefvalue) {
+                    $preferences[] = array('name' => $prefname, 'value' => $prefvalue);
+                 }
+                 $userarray['preferences'] = $preferences;
+            }
             $result[] = $userarray;
         }
+        $users->close();
 
         return $result;
     }
@@ -578,8 +582,8 @@ class moodle_user_external extends external_api {
      */
     public static function get_users_by_id_returns() {
         return new external_multiple_structure(
-                new external_single_structure(
-                        array(
+            new external_single_structure(
+                array(
                     'id'    => new external_value(PARAM_NUMBER, 'ID of the user'),
                     'username'    => new external_value(PARAM_RAW, 'Username policy is defined in Moodle security config', VALUE_OPTIONAL),
                     'firstname'   => new external_value(PARAM_NOTAGS, 'The first name(s) of the user', VALUE_OPTIONAL),
@@ -614,30 +618,342 @@ class moodle_user_external extends external_api {
                     'profileimageurlsmall' => new external_value(PARAM_URL, 'User image profile URL - small version'),
                     'profileimageurl' => new external_value(PARAM_URL, 'User image profile URL - big version'),
                     'customfields' => new external_multiple_structure(
-                                    new external_single_structure(
-                                            array(
-                                                'type'  => new external_value(PARAM_ALPHANUMEXT, 'The type of the custom field - text field, checkbox...'),
-                                                'value' => new external_value(PARAM_RAW, 'The value of the custom field'),
-                                                'name' => new external_value(PARAM_RAW, 'The name of the custom field'),
-                                                'shortname' => new external_value(PARAM_RAW, 'The shortname of the custom field - to be able to build the field class in the code'),
-                                            )
-                                    ), 'User custom fields (also known as user profil fields)', VALUE_OPTIONAL),
+                        new external_single_structure(
+                            array(
+                                'type'  => new external_value(PARAM_ALPHANUMEXT, 'The type of the custom field - text field, checkbox...'),
+                                'value' => new external_value(PARAM_RAW, 'The value of the custom field'),
+                                'name' => new external_value(PARAM_RAW, 'The name of the custom field'),
+                                'shortname' => new external_value(PARAM_RAW, 'The shortname of the custom field - to be able to build the field class in the code'),
+                            )
+                    ), 'User custom fields (also known as user profil fields)', VALUE_OPTIONAL),
                     'preferences' => new external_multiple_structure(
-                            new external_single_structure(
-                                    array(
-                                        'name'  => new external_value(PARAM_ALPHANUMEXT, 'The name of the preferences'),
-                                        'value' => new external_value(PARAM_RAW, 'The value of the custom field'),
-                                    )
-                            ), 'User preferences', VALUE_OPTIONAL),
+                        new external_single_structure(
+                            array(
+                                'name'  => new external_value(PARAM_ALPHANUMEXT, 'The name of the preferences'),
+                                'value' => new external_value(PARAM_RAW, 'The value of the custom field'),
+                            )
+                    ), 'User preferences', VALUE_OPTIONAL),
                     'enrolledcourses' => new external_multiple_structure(
-                            new external_single_structure(
-                                    array(
-                                        'id'  => new external_value(PARAM_INT, 'Id of the course'),
-                                        'fullname' => new external_value(PARAM_RAW, 'Fullname of the course')
-                                    )
-                            ), 'Courses where the user is enrolled - limited by which courses the user is able to see', VALUE_OPTIONAL)
+                        new external_single_structure(
+                            array(
+                                'id'  => new external_value(PARAM_INT, 'Id of the course'),
+                                'fullname' => new external_value(PARAM_RAW, 'Fullname of the course')
+                            )
+                    ), 'Courses where the user is enrolled - limited by which courses the user is able to see', VALUE_OPTIONAL)
+                )
+            )
+        );
+    }
+    /**
+     * Returns description of method parameters
+     * @return external_function_parameters
+     */
+    public static function get_course_participants_by_id_parameters() {
+        return new external_function_parameters(
+            array(
+                'userlist' => new external_multiple_structure(
+                    new external_single_structure(
+                        array(
+                            'userid'    => new external_value(PARAM_INT, 'userid'),
+                            'courseid'    => new external_value(PARAM_INT, 'courseid'),
                         )
+                    )
                 )
+            )
+        );
+    }
+
+    /**
+     * Get course participant's details
+     * @param array $userlist  array of user ids and according course ids
+     * @return array An array of arrays describing course participants
+     */
+    public static function get_course_participants_by_id($userlist) {
+        global $CFG, $USER, $DB;
+        require_once($CFG->dirroot . "/user/lib.php");
+        require_once($CFG->dirroot . "/user/profile/lib.php"); //custom field library
+        require_once($CFG->dirroot . "/lib/filelib.php");      // file handling on description and friends
+
+        $isadmin = is_siteadmin($USER);
+
+        $params = self::validate_parameters(self::get_course_participants_by_id_parameters(), array('userlist'=>$userlist));
+
+        $userids = array();
+        $courseids = array();
+        foreach ($params['userlist'] as $value) {
+            $userids[] = $value['userid'];
+            $courseids[$value['userid']] = $value['courseid'];
+        }
+
+        // cache all courses
+        $courses = array();
+        list($cselect, $cjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx');
+        list($sqlcourseids, $params) = $DB->get_in_or_equal(array_unique($courseids));
+        $coursesql = "SELECT c.* $uselect
+                        FROM {course} c $cjoin
+                       WHERE c.id $sqlcourseids";
+        $rs = $DB->get_recordset_sql($coursesql, $params);
+        foreach ($rs as $course) {
+            // adding course contexts to cache
+            context_instance_preload($course);
+            // cache courses
+            $courses[$course->id] = $course;
+        }
+        $rs->close();
+
+        list($uselect, $ujoin) = context_instance_preload_sql('u.id', CONTEXT_USER, 'ctx');
+        list($sqluserids, $params) = $DB->get_in_or_equal($userids);
+        $usersql = "SELECT u.* $uselect
+                      FROM {user} u $ujoin
+                     WHERE u.id $sqluserids";
+        $users = $DB->get_recordset_sql($usersql, $params);
+        $result = array();
+        foreach ($users as $user) {
+            if (!empty($user->deleted)) {
+                continue;
+            }
+            context_instance_preload($user);
+            $usercontext = get_context_instance(CONTEXT_USER, $user->id);
+            $course = $courses[$courseids[$user->id]];
+            $context = get_context_instance(CONTEXT_COURSE, $courseids[$user->id]);
+            $hasviewdetailscap = has_capability('moodle/user:viewdetails', $context) || has_capability('moodle/user:viewdetails', $usercontext);
+
+            self::validate_context($context);
+
+            $currentuser = ($user->id == $USER->id);
+
+            if (!$currentuser && !$hasviewdetailscap && !has_coursecontact_role($user->id)) {
+                throw new moodle_exception('usernotavailable', 'error');
+            }
+            $userarray = array();
+
+            //basic fields
+            $userarray['id'] = $user->id;
+            if ($isadmin) {
+                $userarray['username'] = $user->username;
+            }
+            if ($isadmin or has_capability('moodle/site:viewfullnames', $context)) {
+                $userarray['firstname'] = $user->firstname;
+                $userarray['lastname'] = $user->lastname;
+            }
+            $userarray['fullname'] = fullname($user);
+
+            //Custom fields (matching /user/profile/lib.php - profile_display_fields code logic)
+            $userarray['customfields'] = array();
+
+            $fields = $DB->get_recordset_sql("SELECT f.*
+                                                FROM {user_info_field} f
+                                                JOIN {user_info_category} c
+                                                     ON f.categoryid=c.id
+                                            ORDER BY c.sortorder ASC, f.sortorder ASC");
+            foreach ($fields as $field) {
+                require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
+                $newfield = 'profile_field_'.$field->datatype;
+                $formfield = new $newfield($field->id, $user->id);
+                if ($formfield->is_visible() and !$formfield->is_empty()) {
+                    $userarray['customfields'][] =
+                        array('name' => $formfield->field->name, 'value' => $formfield->data,
+                            'type' => $field->datatype, 'shortname' => $formfield->field->shortname);
+                }
+            }
+            $fields->close();
+
+            //image profiles urls (public, no permission required in fact)
+            $profileimageurl = moodle_url::make_pluginfile_url($usercontext->id, 'user', 'icon', NULL, '/', 'f1');
+            $userarray['profileimageurl'] = $profileimageurl->out(false);
+            $profileimageurlsmall = moodle_url::make_pluginfile_url($usercontext->id, 'user', 'icon', NULL, '/', 'f2');
+            $userarray['profileimageurlsmall'] = $profileimageurlsmall->out(false);
+
+            //hidden user field
+            if (has_capability('moodle/course:viewhiddenuserfields', $context)) {
+                $hiddenfields = array();
+            } else {
+                $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
+            }
+
+            if (isset($user->description) && (!isset($hiddenfields['description']) or $isadmin)) {
+                if (empty($CFG->profilesforenrolledusersonly) || $currentuser) {
+                    $user->description = file_rewrite_pluginfile_urls($user->description, 'pluginfile.php', $context->id, 'user', 'profile', null);
+                    $userarray['description'] = $user->description;
+                    $userarray['descriptionformat'] = $user->descriptionformat;
+                }
+            }
+
+            if ((! isset($hiddenfields['country']) or $isadmin) && $user->country) {
+                $userarray['country'] = $user->country;
+            }
+
+            if ((! isset($hiddenfields['city']) or $isadmin) && $user->city) {
+                $userarray['city'] = $user->city;
+            }
+
+            if (has_capability('moodle/course:viewhiddenuserfields', $context)) {
+                if ($user->address) {
+                    $userarray['address'] = $user->address;
+                }
+                if ($user->phone1) {
+                    $userarray['phone1'] = $user->phone1;
+                }
+                if ($user->phone2) {
+                    $userarray['phone2'] = $user->phone2;
+                }
+            }
+
+            if ($currentuser
+              or $user->maildisplay == 1
+              or has_capability('moodle/course:useremail', $context)
+              or ($user->maildisplay == 2 and enrol_sharing_course($user, $USER))) {
+                $userarray['email'] = $user->email;;
+            }
+
+            if ($user->url && (!isset($hiddenfields['webpage']) or $isadmin)) {
+                $url = $user->url;
+                if (strpos($user->url, '://') === false) {
+                    $url = 'http://'. $url;
+                }
+                $user->url = clean_param($user->url, PARAM_URL);
+                $userarray['url'] = $user->url;
+            }
+
+            if ($user->icq && (!isset($hiddenfields['icqnumber']) or $isadmin)) {
+                $userarray['icq'] = $user->icq;
+            }
+
+            if ($user->skype && (!isset($hiddenfields['skypeid']) or $isadmin)) {
+                $userarray['skype'] = $user->skype;
+            }
+            if ($user->yahoo && (!isset($hiddenfields['yahooid']) or $isadmin)) {
+                $userarray['yahoo'] = $user->yahoo;
+            }
+            if ($user->aim && (!isset($hiddenfields['aimid']) or $isadmin)) {
+                $userarray['aim'] = $user->aim;
+            }
+            if ($user->msn && (!isset($hiddenfields['msnid']) or $isadmin)) {
+                $userarray['msn'] = $user->msn;
+            }
+
+            if ((!isset($hiddenfields['firstaccess'])) or $isadmin) {
+                if ($user->firstaccess) {
+                    $userarray['firstaccess'] = $user->firstaccess;
+                } else {
+                    $userarray['firstaccess'] = 0;
+                }
+            }
+            if ((!isset($hiddenfields['lastaccess'])) or $isadmin) {
+                if ($user->lastaccess) {
+                    $userarray['lastaccess'] = $user->lastaccess;
+                } else {
+                    $userarray['lastaccess'] = 0;
+                }
+            }
+            /// Printing tagged interests
+            if (!empty($CFG->usetags)) {
+                require_once($CFG->dirroot . '/tag/lib.php');
+                if ($interests = tag_get_tags_csv('user', $user->id, TAG_RETURN_TEXT) ) {
+                    $userarray['interests'] = $interests;
+                }
+            }
+
+            //Departement/Institution are not displayed on any profile, however you can get them from editing profile.
+            if ($isadmin or $currentuser) {
+                if ($user->institution) {
+                    $userarray['institution'] = $user->institution;
+                }
+                if (isset($user->department)) { //isset because it's ok to have department 0
+                    $userarray['department'] = $user->department;
+                }
+            }
+
+            // not a big secret
+            $userarray['roles'] = array();
+            $roles = get_user_roles($context, $user->id, false);
+            foreach ($roles as $role) {
+                $userarray['roles'][] = array(
+                    'roleid'       => $role->roleid,
+                    'name'         => $role->name,
+                    'shortname'    => $role->shortname,
+                    'sortorder'    => $role->sortorder
+                );
+            }
+
+            // If groups are in use and enforced throughout the course, then make sure we can meet in at least one course level group
+            if (has_capability('moodle/site:accessallgroups', $context)) {
+                $usergroups = groups_get_all_groups($course->id, $user->id, $course->defaultgroupingid, 'g.id, g.name,g.description');
+                foreach ($usergroups as $group) {
+                    $group->description = file_rewrite_pluginfile_urls($group->description, 'pluginfile.php', $context->id, 'group', 'description', $group->id);
+                    $userarray['groups'][] = array('id'=>$group->id, 'name'=>$group->name, 'description'=>$group->description);
+                }
+            }
+            $result[] = $userarray;
+        }
+
+        $users->close();
+
+        return $result;
+    }
+
+    /**
+     * Returns description of method result value
+     * @return external_description
+     */
+    public static function get_course_participants_by_id_returns() {
+        return new external_multiple_structure(
+            new external_single_structure(
+                array(
+                    'id'    => new external_value(PARAM_NUMBER, 'ID of the user'),
+                    'username'    => new external_value(PARAM_RAW, 'Username policy is defined in Moodle security config', VALUE_OPTIONAL),
+                    'firstname'   => new external_value(PARAM_NOTAGS, 'The first name(s) of the user', VALUE_OPTIONAL),
+                    'lastname'    => new external_value(PARAM_NOTAGS, 'The family name of the user', VALUE_OPTIONAL),
+                    'fullname'    => new external_value(PARAM_NOTAGS, 'The fullname of the user'),
+                    'email'       => new external_value(PARAM_TEXT, 'An email address - allow email as root@localhost', VALUE_OPTIONAL),
+                    'address'     => new external_value(PARAM_MULTILANG, 'Postal address', VALUE_OPTIONAL),
+                    'phone1'      => new external_value(PARAM_NOTAGS, 'Phone 1', VALUE_OPTIONAL),
+                    'phone2'      => new external_value(PARAM_NOTAGS, 'Phone 2', VALUE_OPTIONAL),
+                    'icq'         => new external_value(PARAM_NOTAGS, 'icq number', VALUE_OPTIONAL),
+                    'skype'       => new external_value(PARAM_NOTAGS, 'skype id', VALUE_OPTIONAL),
+                    'yahoo'       => new external_value(PARAM_NOTAGS, 'yahoo id', VALUE_OPTIONAL),
+                    'aim'         => new external_value(PARAM_NOTAGS, 'aim id', VALUE_OPTIONAL),
+                    'msn'         => new external_value(PARAM_NOTAGS, 'msn number', VALUE_OPTIONAL),
+                    'department'  => new external_value(PARAM_TEXT, 'department', VALUE_OPTIONAL),
+                    'institution' => new external_value(PARAM_TEXT, 'institution', VALUE_OPTIONAL),
+                    'interests'   => new external_value(PARAM_TEXT, 'user interests (separated by commas)', VALUE_OPTIONAL),
+                    'firstaccess' => new external_value(PARAM_INT, 'first access to the site (0 if never)', VALUE_OPTIONAL),
+                    'lastaccess'  => new external_value(PARAM_INT, 'last access to the site (0 if never)', VALUE_OPTIONAL),
+                    'description' => new external_value(PARAM_RAW, 'User profile description', VALUE_OPTIONAL),
+                    'descriptionformat' => new external_value(PARAM_INT, 'User profile description format', VALUE_OPTIONAL),
+                    'city'        => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL),
+                    'url'         => new external_value(PARAM_URL, 'URL of the user', VALUE_OPTIONAL),
+                    'country'     => new external_value(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL),
+                    'profileimageurlsmall' => new external_value(PARAM_URL, 'User image profile URL - small version'),
+                    'profileimageurl' => new external_value(PARAM_URL, 'User image profile URL - big version'),
+                    'customfields' => new external_multiple_structure(
+                        new external_single_structure(
+                            array(
+                                'type'  => new external_value(PARAM_ALPHANUMEXT, 'The type of the custom field - text field, checkbox...'),
+                                'value' => new external_value(PARAM_RAW, 'The value of the custom field'),
+                                'name' => new external_value(PARAM_RAW, 'The name of the custom field'),
+                                'shortname' => new external_value(PARAM_RAW, 'The shortname of the custom field - to be able to build the field class in the code'),
+                            )
+                        ), 'User custom fields (also known as user profil fields)', VALUE_OPTIONAL),
+                    'groups' => new external_multiple_structure(
+                        new external_single_structure(
+                            array(
+                                'id'  => new external_value(PARAM_INT, 'group id'),
+                                'name' => new external_value(PARAM_RAW, 'group name'),
+                                'description' => new external_value(PARAM_RAW, 'group description'),
+                            )
+                        ), 'user groups', VALUE_OPTIONAL),
+                    'roles' => new external_multiple_structure(
+                        new external_single_structure(
+                            array(
+                                'roleid'       => new external_value(PARAM_INT, 'role id'),
+                                'name'         => new external_value(PARAM_RAW, 'role name'),
+                                'shortname'    => new external_value(PARAM_ALPHANUMEXT, 'role shortname'),
+                                'sortorder'    => new external_value(PARAM_INT, 'role sortorder')
+                            )
+                        ), 'user roles', VALUE_OPTIONAL),
+                )
+            )
         );
     }
 }
index 3716b2d..96a166b 100644 (file)
@@ -31,7 +31,7 @@ defined('MOODLE_INTERNAL') || die();
 
 
 
-$version  = 2011061700.01;              // YYYYMMDD      = weekly release date of this DEV branch
+$version  = 2011061700.02;              // YYYYMMDD      = weekly release date of this DEV branch
                                         //         RR    = release increments - 00 in DEV branches
                                         //           .XX = incremental changes