Overview

Packages

  • ClipIt
    • clipit
      • api
    • urjc
      • backend
  • Elgg
    • Core
      • Access
      • Authentication
      • Cache
      • Caches
      • Core
      • DataMode
        • Site
      • DataModel
        • Annotations
        • Entities
        • Extender
        • File
        • Importable
        • Loggable
        • Notable
        • Object
        • User
      • DataStorage
      • Exception
      • Exceptions
        • Stub
      • FileStore
        • Disk
      • Groups
      • Helpers
      • HMAC
      • Memcache
      • Metadata
      • Navigation
      • ODD
      • Output
      • Plugins
        • Settings
      • Sessions
      • SocialModel
        • Friendable
        • Locatable
      • WebServicesAPI
      • Widgets
      • XML
      • XMLRPC
    • Exceptions
      • Stub
  • None
  • PHP

Classes

  • ClipitActivity
  • ClipitChat
  • ClipitComment
  • ClipitEvent
  • ClipitExample
  • ClipitFile
  • ClipitGroup
  • ClipitLA
  • ClipitLabel
  • ClipitPerformanceItem
  • ClipitPerformanceRating
  • ClipitPost
  • ClipitQuiz
  • ClipitQuizQuestion
  • ClipitQuizResult
  • ClipitRating
  • ClipitRemoteTrickyTopic
  • ClipitRemoteVideo
  • ClipitResource
  • ClipitSite
  • ClipitStoryboard
  • ClipitTag
  • ClipitTagRating
  • ClipitTask
  • ClipitTrickyTopic
  • ClipitUser
  • ClipitVideo
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * ClipIt - JuxtaLearn Web Space
  4:  * PHP version:     >= 5.2
  5:  * Creation date:   2013-10-10
  6:  * Last update:     $Date$
  7:  * @author          Pablo LlinĂ¡s Arnaiz <pebs74@gmail.com>, URJC JuxtaLearn Team
  8:  * @version         $Version$
  9:  * @link            http://www.juxtalearn.eu
 10:  * @license         GNU Affero General Public License v3
 11:  * @package         ClipIt
 12:  * @subpackage      clipit_api
 13:  */
 14: 
 15: /**
 16:  * A collection of Quiz Questions, with a link to a Tricky Topic, links to the Tricky Topic Tool Quiz answering and
 17:  * score review URLs, and Author name.
 18:  */
 19: class ClipitQuiz extends UBItem {
 20:     /**
 21:      * @const string Elgg entity SUBTYPE for this class
 22:      */
 23:     const SUBTYPE = "ClipitQuiz";
 24:     const REL_QUIZ_TRICKYTOPIC = "ClipitQuiz-ClipitTrickyTopic";
 25:     const REL_QUIZ_QUIZQUESTION = "ClipitQuiz-ClipitQuizQuestion";
 26:     const REL_QUIZ_USER = "ClipitQuiz-ClipitUser";
 27:     const VIEW_MODE_LIST = "list";
 28:     const VIEW_MODE_PAGED = "paged";
 29:     const TARGET_CLIPIT = "clipit";
 30:     const TARGET_LARGEDISPLAY = "large_display";
 31:     /**
 32:      * @var string Target interface for Quiz display (e.g.: "clipit", "large display"...)
 33:      */
 34:     public $target = "";
 35:     /**
 36:      * @var bool Specifies whether the Quiz can be reused by other teachers (optional, default = false)
 37:      */
 38:     public $public = false;
 39:     /**
 40:      * @var array Array of ClipitQuizQuestion ids (int) included in this Quiz (optional)
 41:      */
 42:     public $quiz_question_array = array();
 43:     /**
 44:      * @var int Id of tricky topic used for this Quiz (optional)
 45:      */
 46:     public $tricky_topic = 0;
 47:     /**
 48:      * @var string
 49:      */
 50:     public $view_mode = "";
 51:     /**
 52:      * @var int $max_time  Maximum time in seconds to perform the quiz since it's opened by a student (0 = unlimited)
 53:      */
 54:     public $max_time = 0;
 55:     /**
 56:      * Loads object parameters stored in Elgg
 57:      *
 58:      * @param ElggEntity $elgg_entity Elgg Object to load parameters from.
 59:      */
 60:     protected function copy_from_elgg($elgg_entity) {
 61:         parent::copy_from_elgg($elgg_entity);
 62:         $this->quiz_question_array = static::get_quiz_questions($this->id);
 63:         $this->public = (bool)$elgg_entity->get("public");
 64:         $this->tricky_topic = (int)static::get_tricky_topic($this->id);
 65:         $this->target = (string)$elgg_entity->get("target");
 66:         $this->view_mode = (string)$elgg_entity->get("view_mode");
 67:         $this->max_time = (int)$elgg_entity->get("max_time");
 68:     }
 69: 
 70:     /**
 71:      * Copy $this object parameters into an Elgg entity.
 72:      *
 73:      * @param ElggEntity $elgg_entity Elgg object instance to save $this to
 74:      */
 75:     protected function copy_to_elgg($elgg_entity) {
 76:         parent::copy_to_elgg($elgg_entity);
 77:         $elgg_entity->set("public", (bool)$this->public);
 78:         $elgg_entity->set("target", (string)$this->target);
 79:         if((string)$this->view_mode == ""){
 80:             $elgg_entity->set("view_mode", static::VIEW_MODE_LIST);
 81:         }else{
 82:             $elgg_entity->set("view_mode", (string)$this->view_mode);
 83:         }
 84:         $elgg_entity->set("max_time", (int)$this->max_time);
 85:     }
 86: 
 87:     /**
 88:      * Saves this instance to the system.
 89:      * @param  bool $double_save if $double_save is true, this object is saved twice to ensure that all properties are updated properly. E.g. the time created property can only beset on ElggObjects during an update. Defaults to false!
 90:      * @return bool|int Returns the Id of the saved instance, or false if error
 91:      */
 92:     protected function save($double_save=false) {
 93:         parent::save($double_save);
 94:         static::set_tricky_topic($this->id, (int)$this->tricky_topic);
 95:         static::set_quiz_questions($this->id, $this->quiz_question_array);
 96:         return $this->id;
 97:     }
 98: 
 99:     /**
100:      * Clones a ClipitQuiz, including the contained ClipitQuizQuestions
101:      *
102:      * @param int $id ID of Quiz to clone
103:      * @param bool $linked Whether the clone will be linked to the parent object
104:      * @param bool $keep_owner Selects whether the clone will keep the parent item's owner (default: no)
105:      * @return bool|int ID of new cloned object
106:      * @throws InvalidParameterException if error
107:      */
108:     static function create_clone($id, $linked = true, $keep_owner = false) {
109:         $prop_value_array = static::get_properties($id);
110:         if($keep_owner === false){
111:             $prop_value_array["owner_id"] = elgg_get_logged_in_user_guid();
112:         }
113:         $quiz_question_array = $prop_value_array["quiz_question_array"];
114:         if(!empty($quiz_question_array)){
115:             $new_quiz_question_array = array();
116:             foreach($quiz_question_array as $quiz_question_id){
117:                 $new_quiz_question_array[] = ClipitQuizQuestion::create_clone($quiz_question_id);
118:             }
119:             $prop_value_array["quiz_question_array"] = $new_quiz_question_array;
120:         }
121:         $clone_id = static::create($prop_value_array);
122:         if($linked) {
123:             static::link_parent_clone($id, $clone_id);
124:         }
125:         return $clone_id;
126:     }
127: 
128:     /**
129:      * Sets values to specified properties of an Item
130:      *
131:      * @param int   $id               Id of Item to set property values
132:      * @param array $prop_value_array Array of property=>value pairs to set into the Item
133:      *
134:      * @return int|bool Returns Id of Item if correct, or false if error
135:      * @throws InvalidParameterException
136:      */
137:     static function set_properties($id, $prop_value_array) {
138:         $new_prop_value_array = array();
139:         foreach($prop_value_array as $prop => $value) {
140:             if($prop == "public") {
141:                 if($value == "true") {
142:                     $new_prop_value_array["public"] = true;
143:                 } elseif($value == "false") {
144:                     $new_prop_value_array["public"] = false;
145:                 } else {
146:                     $new_prop_value_array["public"] = (bool)$value;
147:                 }
148:             } else {
149:                 $new_prop_value_array[$prop] = $value;
150:             }
151:         }
152:         return parent::set_properties($id, $new_prop_value_array);
153:     }
154: 
155:     static function get_task($id){
156:         $task_array = UBCollection::get_items((int)$id, ClipitTask::REL_TASK_QUIZ, true);
157:         if(empty($task_array)){
158:             return 0;
159:         }
160:         return (int)array_pop($task_array);
161:     }
162: 
163:     static function get_tricky_topic($id) {
164:         $ret_array = UBCollection::get_items($id, static::REL_QUIZ_TRICKYTOPIC);
165:         if(!empty($ret_array)){
166:             return array_pop($ret_array);
167:         }
168:         return 0;
169:     }
170: 
171:     static function set_tricky_topic($id, $tricky_topic) {
172:         return UBCollection::set_items($id, array($tricky_topic), static::REL_QUIZ_TRICKYTOPIC);
173:     }
174: 
175:     static function get_from_tricky_topic($tricky_topic_id) {
176:         $id_array = UBCollection::get_items($tricky_topic_id, static::REL_QUIZ_TRICKYTOPIC, true);
177:         $quiz_array = array();
178:         foreach($id_array as $quiz_id) {
179:             $quiz_array[] = new static($quiz_id);
180:         }
181:         return $quiz_array;
182:     }
183: 
184:     static function set_quiz_as_finished($id, $user_id){
185:         $start_timestamp = (int)static::get_quiz_start($id, $user_id);
186:         if(empty($start_timestamp)) {
187:             return null;
188:         }
189:         $prop_value_array = static::get_properties($id, array("max_time"));
190:         $max_time = (int)$prop_value_array["max_time"];
191:         $new_start_timestamp = (int)$start_timestamp - $max_time;
192:         return UBCollection::set_timestamp($id, $user_id, static::REL_QUIZ_USER, $new_start_timestamp);
193:     }
194: 
195:     static function set_quiz_start($id, $user_id){
196:         return UBCollection::add_items($id, array($user_id), static::REL_QUIZ_USER);
197:     }
198: 
199:     static function remove_quiz_start($id, $user_array){
200:         return UBCollection::remove_items($id, $user_array, static::REL_QUIZ_USER);
201:     }
202: 
203:     /**
204:      * @param $id
205:      * @param $user_id
206:      * @return int|null
207:      */
208:     static function get_quiz_start($id, $user_id){
209:         return UBCollection::get_timestamp($id, $user_id, static::REL_QUIZ_USER);
210:     }
211: 
212:     /**
213:      * Returns whether a user has finished a Quiz
214:      *
215:      * @param int $id The Quiz ID
216:      * @param int $user_id The User ID
217:      * @return bool 'true' if yes, 'false' if no
218:      */
219:     static function has_finished_quiz($id, $user_id){
220:         // check if quiz has been started, and if max_time is over
221:         $start_time = (int)static::get_quiz_start($id, $user_id);
222:         if(empty($start_time)){
223:             return false;
224:         }
225:         // If task has ended, quiz is finished
226:         $task_id = static::get_task($id);
227:         if(ClipitTask::get_status($task_id) !== ClipitTask::STATUS_ACTIVE){
228:             return true;
229:         }
230:         $prop_value_array = (array)static::get_properties($id, array("max_time"));
231:         $max_time = (int)$prop_value_array["max_time"];
232:         if($max_time == 0){
233:             return false;
234:         }
235:         $current_time = (int)time();
236:         if($start_time + $max_time <= $current_time){
237:             return true;
238:         }
239:         // else, quiz is still ongoing
240:         return false;
241:     }
242: 
243:     static function questions_answered_by_user($id, $user_id){
244:         if(empty($id) || empty($user_id)){
245:             return null;
246:         }
247:         $quiz = new static($id);
248:         $answered_questions = 0;
249:         $user_results = ClipitQuizResult::get_by_owner(array($user_id));
250:         $user_results = $user_results[$user_id];
251:         if(empty($user_results)){
252:             return $answered_questions;
253:         }
254:         foreach($user_results as $result){
255:             if(array_search($result->quiz_question, $quiz->quiz_question_array) !== false){
256:                 $answered_questions++;
257:             }
258:         }
259:         return $answered_questions;
260:     }
261: 
262:     /**
263:      * Returns the average results by Question for a Quiz for a User, normalized from 0 to 1.
264:      *
265:      * @param int $id Quiz ID
266:      * @param int $user_id User ID
267:      * @return array Array of question_id=>$result, where the result is a float from 0 to 1. Empty array if the user has not
268:      * finished the Quiz.
269:      */
270:     static function get_user_results_by_question($id, $user_id){
271:         $result_array = array();
272:         if(!static::has_finished_quiz($id, $user_id)){
273:             return $result_array;
274:         }
275:         $quiz_question_array = static::get_quiz_questions($id);
276:         if(empty($quiz_question_array)){
277:             return $result_array;
278:         }
279:         foreach($quiz_question_array as $quiz_question_id){
280:             $quiz_question = new ClipitQuizQuestion($quiz_question_id);
281:             $quiz_result = ClipitQuizResult::get_from_question_user($quiz_question_id, $user_id);
282:                 if(!empty($quiz_result)) {
283:                     if ($quiz_result->correct) {
284:                         $result_array[$quiz_question->id]=1;
285:                     } else {
286:                         $result_array[$quiz_question->id]=0;
287:                     }
288:                 }
289:         }
290:         return $result_array;
291:     }
292: 
293:     /**
294:      * Returns the average results by Question for a Quiz among a Group. Students who have not finished the Quiz will not
295:      * be counted.
296:      *
297:      * @param int $id Quiz ID
298:      * @param int $group_id Group ID
299:      *
300:      * @return array Array of $question_id=>$result, where the result is a float from 0 to 1. Empty array if none of the
301:      * students in the group have answered the Quiz.
302:      */
303:     static function get_group_results_by_question($id, $group_id){
304:         $group = new ClipitGroup($group_id);
305:         $user_results = array();
306:         foreach($group->user_array as $user_id){
307:             $user_results[$user_id] = static::get_user_results_by_question($id, $user_id);
308:         }
309:         $group_results = array();
310:         $user_count = 0;
311:         foreach($user_results as $user=>$results){
312:             if(empty($results)){
313:                 continue;
314:             }
315:             $user_count++;
316:             foreach($results as $question_id=>$result){
317:                 if(!isset($group_results[$question_id])){
318:                     $group_results[$question_id] = (float)0.0;
319:                 }
320:                 $group_results[$question_id] += $result;
321:             }
322:         }
323:         foreach($group_results as $question_id=>$result){
324:             $group_results[$question_id] = (float)$result/$user_count;
325:         }
326:         return $group_results;
327:     }
328: 
329: 
330:     /**
331:      * Returns the average results by Tag for a Quiz for a User, normalized from 0 to 1.
332:      *
333:      * @param int $id Quiz ID
334:      * @param int $user_id User ID
335:      * @return array Array of tag_id=>$result, where the result is a float from 0 to 1. Empty array if the user has not
336:      * finished the Quiz.
337:      */
338:     static function get_user_results_by_tag($id, $user_id){
339:         $result_array = array();
340:         if(!static::has_finished_quiz($id, $user_id)){
341:             return $result_array;
342:         }
343:         $tag_count_array = array();
344:         $quiz_question_array = static::get_quiz_questions($id);
345:         if(empty($quiz_question_array)){
346:             return $result_array;
347:         }
348:         foreach($quiz_question_array as $quiz_question_id){
349:             $quiz_question = new ClipitQuizQuestion($quiz_question_id);
350:             $quiz_result = ClipitQuizResult::get_from_question_user($quiz_question_id, $user_id);
351:             foreach($quiz_question->tag_array as $tag_id){
352:                 if(!isset($tag_count_array[$tag_id])){
353:                     $tag_count_array[$tag_id] = (int)1;
354:                     $result_array[$tag_id] = (int)0;
355:                 } else {
356:                     $tag_count_array[$tag_id]++;
357:                 }
358:                 if(!empty($quiz_result)) {
359:                     if ($quiz_result->correct) {
360:                         $result_array[$tag_id]++;
361:                     }
362:                 }
363:             }
364:         }
365:         // transform to [0..1] scale
366:         foreach($result_array as $tag_id=>$correct_answers){
367:             $result_array[$tag_id] = (float)$correct_answers/$tag_count_array[$tag_id];
368:         }
369:         ksort($result_array);
370:         return $result_array;
371:     }
372: 
373:     /**
374:      * Returns the average results by Tag for a Quiz among a Group. Students who have not finished the Quiz will not
375:      * be counted.
376:      *
377:      * @param int $id Quiz ID
378:      * @param int $group_id Group ID
379:      *
380:      * @return array Array of $tag_id=>$result, where the result is a float from 0 to 1. Empty array if none of the
381:      * students in the group have answered the Quiz.
382:      */
383:     static function get_group_results_by_tag($id, $group_id){
384:         $group = new ClipitGroup($group_id);
385:         $user_results = array();
386:         foreach($group->user_array as $user_id){
387:             $user_results[$user_id] = static::get_user_results_by_tag($id, $user_id);
388:         }
389:         $group_results = array();
390:         $user_count = 0;
391:         foreach($user_results as $user=>$results){
392:             if(empty($results)){
393:                 continue;
394:             }
395:             $user_count++;
396:             foreach($results as $tag_id=>$result){
397:                 if(!isset($group_results[$tag_id])){
398:                     $group_results[$tag_id] = (float)0.0;
399:                 }
400:                 $group_results[$tag_id] += $result;
401:             }
402:         }
403:         foreach($group_results as $tag_id=>$result){
404:             $group_results[$tag_id] = (float)$result/$user_count;
405:         }
406:         ksort($group_results);
407:         return $group_results;
408:     }
409: 
410:     /**
411:      * Returns the average results by Tag for a Quiz among all the results. Results from students who have not finished
412:      * the Quiz will not be counted.
413:      *
414:      * @param int $id Quiz ID
415:      * @return array Array of $tag_id=>$result where the result is a float from 0 to 1. Empty array of there are no
416:      * results for the Quiz.
417:      */
418:     static function get_quiz_results_by_tag($id){
419:         $task_id = static::get_task($id);
420:         $activity_id = ClipitTask::get_activity($task_id);
421:         $user_array = ClipitActivity::get_students($activity_id);
422:         $user_results = array();
423:         foreach($user_array as $user_id){
424:             $user_results[$user_id] = static::get_user_results_by_tag($id, $user_id);
425:         }
426:         $quiz_results = array();
427:         $user_count = 0;
428:         foreach($user_results as $user=>$results){
429:             if(empty($results)){
430:                 continue;
431:             }
432:             $user_count++;
433:             foreach($results as $tag_id=>$result){
434:                 if(!isset($quiz_results[$tag_id])){
435:                     $quiz_results[$tag_id] = (float)0.0;
436:                 }
437:                 $quiz_results[$tag_id] += $result;
438:             }
439:         }
440:         foreach($quiz_results as $tag_id=>$result){
441:             $quiz_results[$tag_id] = (float)$result/$user_count;
442:         }
443:         ksort($quiz_results);
444:         return $quiz_results;
445:     }
446: 
447:     static function evaluate_results($id){
448:         $quiz_questions = static::get_quiz_questions($id);
449:         foreach($quiz_questions as $quiz_question) {
450:             ClipitQuizQuestion::evaluate_results($quiz_question);
451:         }
452:         return true;
453:     }
454: 
455:     /**
456:      * Adds Quiz Questions to a Quiz.
457:      *
458:      * @param int   $id             Id from Quiz to add Questions to
459:      * @param array $question_array Array of Questions to add
460:      *
461:      * @return bool Returns true if success, false if error
462:      */
463:     static function add_quiz_questions($id, $question_array) {
464:         return UBCollection::add_items($id, $question_array, static::REL_QUIZ_QUIZQUESTION, true);
465:     }
466: 
467:     /**
468:      * Sets Quiz Questions to a Quiz.
469:      *
470:      * @param int   $id             Id from Quiz to set Questions to
471:      * @param array $question_array Array of Questions to set
472:      *
473:      * @return bool Returns true if success, false if error
474:      */
475:     static function set_quiz_questions($id, $question_array) {
476:         return UBCollection::set_items($id, $question_array, static::REL_QUIZ_QUIZQUESTION, true);
477:     }
478: 
479:     /**
480:      * Remove Quiz Questions from a Quiz.
481:      *
482:      * @param int   $id             Id from Quiz to remove Questions from
483:      * @param array $question_array Array of Questions to remove
484:      *
485:      * @return bool Returns true if success, false if error
486:      */
487:     static function remove_quiz_questions($id, $question_array) {
488:         return UBCollection::remove_items($id, $question_array, static::REL_QUIZ_QUIZQUESTION);
489:     }
490: 
491:     /**
492:      * Get an array of Quiz Questions included in a Quiz.
493:      *
494:      * @param int $id The Id of the Quiz to get questions from
495:      *
496:      * @return array|bool Returns an array of ClipitQuizQuestion IDs, or false if error
497:      */
498:     static function get_quiz_questions($id) {
499:         return UBCollection::get_items($id, static::REL_QUIZ_QUIZQUESTION);
500:     }
501: 
502:     static function export_to_excel($id){
503:         $quiz = static::get_by_id(array($id));
504:         if(empty($quiz)){
505:             return null;
506:         }
507:         $quiz = array_pop($quiz);
508:         $task_id = ClipitQuiz::get_task($id);
509:         $activity_id = ClipitTask::get_activity($task_id);
510:         $user_ids = ClipitActivity::get_students($activity_id);
511:         $quiz_question_array = ClipitQuizQuestion::get_by_id(ClipitQuiz::get_quiz_questions($id));
512: 
513:         // New Excel object
514:         $php_excel = new PHPExcel();
515: 
516:         // Set document properties
517:         $php_excel->getProperties()->setCreator("ClipIt")
518:             ->setTitle("ClipIt export of Quiz " . $quiz->name)
519:             ->setKeywords("clipit export quiz");
520: 
521:         // Set Scores sheet properties
522:         $sheet_0 = $php_excel->getSheet(0);
523:         $sheet_0->setTitle("Scores");
524:         $sheet_0->getDefaultStyle()->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_RIGHT);
525:         $sheet_0->getDefaultStyle()->getAlignment()->setWrapText(true);
526:         $sheet_0->getDefaultRowDimension()->setRowHeight(-1);
527:         $sheet_0->getDefaultColumnDimension()->setWidth(30);
528: 
529: 
530: 
531:         // Quiz info title row
532:         $col_0 = 0; $row_0 = 1;
533:         $sheet_0->getStyle($row_0)->getFont()->setBold(true);
534:         $sheet_0->setCellValueByColumnAndRow($col_0++, $row_0, "QUIZ NAME");
535:         $sheet_0->setCellValueByColumnAndRow($col_0++, $row_0, "TRICKY TOPIC");
536:         $sheet_0->setCellValueByColumnAndRow($col_0++, $row_0, "MAX TIME (mins)");
537: 
538:         // Quiz info
539:         $col_0=0; $row_0++;
540:         $sheet_0->setCellValueByColumnAndRow($col_0++, $row_0, $quiz->name);
541:         $tricky_topic = ClipitTrickyTopic::get_by_id(array($quiz->tricky_topic));
542:         if(!empty($tricky_topic)) {
543:             $tricky_topic = array_pop($tricky_topic);
544:             $sheet_0->setCellValueByColumnAndRow($col_0++, $row_0, $tricky_topic->name);
545:         } else{
546:             $col_0++;
547:         }
548:         $sheet_0->setCellValueByColumnAndRow($col_0++, $row_0, ((int)$quiz->max_time)/60);
549: 
550:         // Student Scores title row
551:         $col_0 = 0; $row_0 += 2;
552:         $sheet_0->getStyle($row_0)->getFont()->setBold(true);
553:         $sheet_0->setCellValueByColumnAndRow($col_0++, $row_0, "STUDENT NAME");
554:         $sheet_0->setCellValueByColumnAndRow($col_0++, $row_0, "CORRECT ANSWERS");
555:         $sheet_0->setCellValueByColumnAndRow($col_0++, $row_0, "SCORE");
556: 
557:         // Student Scores
558:         $col_0 = 0; $row_0++;
559:         foreach($user_ids as $user_id){
560:             $pv_array = ClipitUser::get_properties($user_id, array("name"));
561:             $user_names[$user_id] = $pv_array["name"];
562:             $sheet_0->setCellValueByColumnAndRow($col_0++, $row_0, $pv_array["name"]);
563:             $results_by_question = ClipitQuiz::get_user_results_by_question($id, $user_id);
564:             $total_correct = 0;
565:             foreach($results_by_question as $question_id => $result){
566:                 $total_correct += (int)$result;
567:             }
568:             $sheet_0->setCellValueByColumnAndRow($col_0++, $row_0, $total_correct." out of ".count($quiz->quiz_question_array));
569:             $percentage = (float)($total_correct / count($quiz->quiz_question_array) * 100.0);
570:             $percentage = round($percentage, 2);
571:             $sheet_0->setCellValueByColumnAndRow($col_0++, $row_0, $percentage."%");
572:             $col_0 = 0; $row_0++;
573:         }
574: 
575:         // Set Answers sheet properties
576:         $sheet_1 = $php_excel->createSheet(1);
577:         $sheet_1->setTitle("Answers");
578:         $sheet_1->getDefaultStyle()->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_RIGHT);
579:         $sheet_1->getDefaultStyle()->getAlignment()->setWrapText(true);
580:         $sheet_1->getDefaultRowDimension()->setRowHeight(-1);
581:         $sheet_1->getDefaultColumnDimension()->setWidth(30);
582: 
583:         // Quiz Questions header
584:         $col_1 = 0; $row_1 = 1;
585:         $sheet_1->getColumnDimension('A')->setWidth(30);
586:         $sheet_1->getStyleByColumnAndRow($col_1, $row_1)->getFont()->setBold(true);
587:         $sheet_1->setCellValueByColumnAndRow($col_1, $row_1++, "QUESTION NUMBER");
588:         $sheet_1->getStyleByColumnAndRow($col_1, $row_1)->getFont()->setBold(true);
589:         $sheet_1->setCellValueByColumnAndRow($col_1, $row_1++, "QUESTION TITLE");
590:         $sheet_1->getStyleByColumnAndRow($col_1, $row_1)->getFont()->setBold(true);
591:         $sheet_1->setCellValueByColumnAndRow($col_1, $row_1++, "CORRECT ANSWER(S)");
592:         $sheet_1->getStyleByColumnAndRow($col_1, $row_1)->getFont()->setBold(true);
593:         $sheet_1->setCellValueByColumnAndRow($col_1, $row_1++, "STUDENT NAME");
594: 
595:         /// Quiz Questions
596:         $col_1 = 1; $row_1 = 1;
597:         foreach($quiz_question_array as $quiz_question){
598:             $sheet_1->setCellValueByColumnAndRow($col_1, $row_1++, (int)$quiz_question->order);
599:             $sheet_1->setCellValueByColumnAndRow($col_1, $row_1++, (string)$quiz_question->name);
600:             $correct_answer = "";
601:             switch($quiz_question->option_type){
602:                 case ClipitQuizQuestion::TYPE_SELECT_MULTI:
603:                 case ClipitQuizQuestion::TYPE_SELECT_ONE:
604:                     $i = 0;
605:                     $multi = false;
606:                     $num_options = count($quiz_question->option_array);
607:                     while($i < $num_options){
608:                         if($quiz_question->validation_array[$i]){
609:                             if($multi) {
610:                                 $correct_answer = $correct_answer."\n ";
611:                             } else{
612:                                 $multi = true;
613:                             }
614:                             $correct_answer = $correct_answer.$quiz_question->option_array[$i];
615:                         }
616:                         $i++;
617:                     }
618:                     break;
619:                 case ClipitQuizQuestion::TYPE_TRUE_FALSE:
620:                     if($quiz_question->validation_array[0]){
621:                         $correct_answer = "TRUE";
622:                     } elseif($quiz_question->validation_array[1]){
623:                         $correct_answer = "FALSE";
624:                     }
625:                     break;
626:                 case ClipitQuizQuestion::TYPE_NUMBER:
627:                     $correct_answer = $quiz_question->validation_array[0];
628:                     break;
629:                 default:
630:                     $correct_answer = ("<ERROR>");
631:             }
632:             $fill_color = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_GREEN);
633:             $sheet_1->getStyleByColumnAndRow($col_1, $row_1)->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
634:             $sheet_1->getStyleByColumnAndRow($col_1, $row_1)->getFill()->setStartColor($fill_color);
635:             $sheet_1->setCellValueByColumnAndRow($col_1, $row_1++, (string)$correct_answer);
636:             $sheet_1->setCellValueByColumnAndRow($col_1, $row_1, "STUDENT ANSWER");
637:             $sheet_1->getStyleByColumnAndRow($col_1, $row_1)->getFont()->setBold(true);
638:             $col_1++; $row_1 = 1;
639:         }
640: 
641:         // Student Names
642:         $col_1 = 0; $row_1 = 5;
643:         foreach($user_ids as $user_id){
644:             $sheet_1->setCellValueByColumnAndRow($col_1, $row_1++, $user_names[$user_id]);
645:         }
646: 
647:         // Student Answers
648:         $col_1 = 1; $row_1 = 5;
649:         foreach($user_ids as $user_id){
650:             foreach($quiz_question_array as $quiz_question){
651:                 $quiz_result = ClipitQuizResult::get_from_question_user($quiz_question->id, $user_id);
652:                 if(empty($quiz_result)){
653:                     $sheet_1->setCellValueByColumnAndRow($col_1, $row_1, "<not answered>");
654:                     $col_1++;
655:                     continue;
656:                 }
657:                 $answer = "";
658:                 switch($quiz_question->option_type){
659:                     case ClipitQuizQuestion::TYPE_SELECT_MULTI:
660:                     case ClipitQuizQuestion::TYPE_SELECT_ONE:
661:                         $i = 0;
662:                         $multi = false;
663:                         $num_options = count($quiz_question->option_array);
664:                         while($i < $num_options){
665:                             if($quiz_result->answer[$i]){
666:                                 if($multi) {
667:                                     $answer = $answer."\n ";
668:                                 } else{
669:                                     $multi = true;
670:                                 }
671:                                 $answer = $answer.$quiz_question->option_array[$i];
672:                             }
673:                             $i++;
674:                         }
675:                         break;
676:                     case ClipitQuizQuestion::TYPE_TRUE_FALSE:
677:                         if($quiz_result->answer[0]){
678:                             $answer = "TRUE";
679:                         } elseif($quiz_result->answer[1]){
680:                             $answer = "FALSE";
681:                         }
682:                         break;
683:                     case ClipitQuizQuestion::TYPE_NUMBER:
684:                         $answer = $quiz_result->answer;
685:                         break;
686:                     default:
687:                         $answer = ("<ERROR>");
688:                 }
689:                 $sheet_1->setCellValueByColumnAndRow($col_1, $row_1, (string)$answer);
690:                 if($quiz_result->correct){
691:                     $fill_color = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_GREEN);
692:                 } else{
693:                     $fill_color = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_RED);
694:                 }
695:                 $sheet_1->getStyleByColumnAndRow($col_1, $row_1)->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
696:                 $sheet_1->getStyleByColumnAndRow($col_1, $row_1)->getFill()->setStartColor($fill_color);
697:                 $col_1++;
698:             }
699:             $col_1 = 1; $row_1++;
700:         }
701: 
702:         // Write to file
703:         $php_excel->setActiveSheetIndex(0);
704:         $date_obj = new DateTime();
705:         $timestamp = $date_obj->getTimestamp();
706:         $objWriter = PHPExcel_IOFactory::createWriter($php_excel, 'Excel2007');
707:         $filename = (string)"/tmp/".$timestamp."_quiz_export.xlsx";
708:         $objWriter->save($filename);
709:         return $filename;
710:     }
711: }
API documentation generated by ApiGen 2.8.0