dokeos-learnpath
[ class tree: dokeos-learnpath ] [ index: dokeos-learnpath ] [ all elements ]

Source for file learnpathItem.class.php

Documentation is available at learnpathItem.class.php

  1. <?php //$id:$
  2. /**
  3.  * This file contains the lp_item class, that inherits from the learnpath class
  4.  * @package    dokeos.learnpath
  5.  * @author    Yannick Warnier <ywarnier@beeznest.org>
  6.  * @license    GNU/GPL - See Dokeos license directory for details
  7.  */
  8. /**
  9.  * lp_item defines items belonging to a learnpath. Each item has a name, a score, a use time and additional
  10.  * information that enables tracking a user's progress in a learning path
  11.  * @package    dokeos.learnpath
  12.  */
  13.     var $attempt_id//also called "objectives" SCORM-wise
  14.     var $children = array()//contains the ids of children items
  15.     var $condition//if this item has a special condition embedded
  16.     var $current_score;
  17.     var $current_start_time;
  18.     var $current_stop_time;
  19.     var $current_data = '';
  20.     var $db_id;
  21.     var $db_item_view_id = '';
  22.     var $description = '';
  23.     var $file;
  24.     //at the moment, interactions are just an array of arrays with a structure of 8 text fields
  25.     //id(0), type(1), time(2), weighting(3),correct_responses(4),student_response(5),result(6),latency(7)
  26.     var $interactions = array();
  27.     var $interactions_count = 0;
  28.     var $objectives = array();
  29.     var $objectives_count = 0;
  30.     var $launch_data = '';
  31.     var $lesson_location = '';
  32.     var $level = 0;
  33.     //var $location; //only set this for SCORM?
  34.     var $lp_id;
  35.     var $max_score;
  36.     var $mastery_score;
  37.     var $min_score;
  38.     var $max_time_allowed = '';
  39.     var $name;
  40.     var $next;
  41.     var $parent;
  42.     var $path;
  43.     var $possible_status = array('not attempted','incomplete','completed','passed','failed','browsed');
  44.     var $prereq_string = '';
  45.     var $prereq_alert = '';
  46.     var $prereqs = array();
  47.     var $previous;
  48.     var $prevent_reinit = 1;
  49.     var $ref;
  50.     var $save_on_close = true;
  51.     var $status;
  52.     var $title;
  53.     var $type// this attribute can contain chapter|link|student_publication|module|quiz|document|forum|thread
  54.     var $view_id;
  55.     
  56.     var $debug = 0//logging param
  57.     /**
  58.      * Class constructor. Prepares the learnpath_item for later launch
  59.      * 
  60.      * Don't forget to use set_lp_view() if applicable after creating the item.
  61.      * Setting an lp_view will finalise the item_view data collection
  62.      * @param    integer    Learnpath item ID
  63.      * @param    integer    User ID
  64.      * @return    boolean    True on success, false on failure
  65.      */
  66.     function learnpathItem($db_id$user_id{
  67.         //get items table
  68.         if($this->debug>0){error_log('New LP - In learnpathItem constructor: '.$db_id.','.$user_id,0);}
  69.         $items_table Database::get_course_table('lp_item');
  70.         $id = (int) $db_id;
  71.         $sql "SELECT * FROM $items_table WHERE id = $id";
  72.         //error_log('New LP - Creating item object from DB: '.$sql,0);
  73.         $res @api_sql_query($sql);
  74.         if(Database::num_rows($res)<1)
  75.         {
  76.             $this->error "Could not find given learnpath item in learnpath_item table";
  77.             //error_log('New LP - '.$this->error,0);
  78.             return false;
  79.         }
  80.         $row Database::fetch_array($res);
  81.         $this->lp_id     = $row['lp_id'];
  82.         $this->max_score = $row['max_score'];
  83.         $this->min_score = $row['min_score'];
  84.         $this->name      = $row['title'];
  85.         $this->type      = $row['item_type'];
  86.         $this->ref         = $row['ref'];
  87.         $this->title     = $row['title'];
  88.         $this->description = $row['description'];
  89.         $this->path         = $row['path'];
  90.         $this->mastery_score = $row['mastery_score'];
  91.         $this->parent     = $row['parent_item_id'];
  92.         $this->next         = $row['next_item_id'];
  93.         $this->previous     = $row['previous_item_id'];
  94.         $this->display_order $row['display_order'];
  95.         $this->prereq_string = $row['prerequisite'];
  96.         $this->max_time_allowed = $row['max_time_allowed'];
  97.         if(isset($row['launch_data'])){
  98.             $this->launch_data = $row['launch_data'];
  99.         }
  100.         $this->save_on_close = true;
  101.         $this->db_id = $id;
  102.         
  103.         //error_log('New LP - End of learnpathItem constructor for item '.$id,0);
  104.         return true;
  105.     }
  106.     /**
  107.      * Adds a child to the current item
  108.      */
  109.     function add_child($item)
  110.     {
  111.         if($this->debug>0){error_log('New LP - In learnpathItem::add_child()',0);}
  112.         if(!empty($item))
  113.         {
  114.             //do not check in DB as we expect the call to come from the learnpath class which should
  115.             //be aware of any fake
  116.             $this->children[$item;
  117.         }
  118.     }
  119.     /**
  120.      * Adds an interaction to the current item
  121.      * @param    int        Index (order ID) of the interaction inside this item
  122.      * @param    array    Array of parameters: id(0), type(1), time(2), weighting(3),correct_responses(4),student_response(5),result(6),latency(7)
  123.      * @result    void
  124.      */
  125.     function add_interaction($index,$params)
  126.     {
  127.         $this->interactions[$index$params;
  128.         //take the current maximum index to generate the interactions_count
  129.         if(($index+1)>$this->interactions_count){
  130.             $this->interactions_count = $index+1;
  131.         }
  132.         /*
  133.         if(is_array($this->interactions[$index]) && count($this->interactions[$index])>0){
  134.             $this->interactions[$index] = $params;
  135.             return false;
  136.         }else{
  137.             if(count($params)==8){//we rely on the calling script to provide parameters in the right order
  138.                 $this->interactions[$index] = $params;
  139.                 return true;
  140.             }else{
  141.                 return false;
  142.             }
  143.         }
  144.         */
  145.     }
  146.     /**
  147.      * Adds an objective to the current item
  148.      * @param    array    Array of parameters: id(0), status(1), score_raw(2), score_max(3), score_min(4)
  149.      * @result    void
  150.      */
  151.     function add_objective($index,$params)
  152.     {
  153.         if(empty($params[0])){return null;}
  154.         $this->objectives[$index$params;
  155.         //take the current maximum index to generate the objectives_count
  156.         if((count($this->objectives)+1)>$this->objectives_count){
  157.             $this->objectives_count = (count($this->objectives)+1);
  158.         }
  159.     }
  160.     
  161.     /**
  162.      * Closes/stops the item viewing. Finalises runtime values. If required, save to DB.
  163.      * @return    boolean    True on success, false otherwise
  164.      */
  165.     function close()
  166.     {
  167.         if($this->debug>0){error_log('New LP - In learnpathItem::close()',0);}
  168.            $this->current_stop_time = time();
  169.            $type $this->get_type();
  170.         if($type != 'sco'){
  171.             if($type == TOOL_QUIZ or $type == TOOL_HOTPOTATOES)
  172.             {
  173.                 $this->get_status(true,true);//update status (second option forces the update)        
  174.             }
  175.             else
  176.             {
  177.                 $this->status = $this->possible_status[2];
  178.             }
  179.         }
  180.         if($this->save_on_close)
  181.         {
  182.             $this->save();
  183.         }    
  184.         return true;
  185.     }
  186.     /**
  187.      * Deletes all traces of this item in the database
  188.      * @return    boolean    true. Doesn't check for errors yet.
  189.      */
  190.     function delete()
  191.     {
  192.         if($this->debug>0){error_log('New LP - In learnpath_item::delete() for item '.$this->db_id,0);}
  193.         $lp_item_view Database::get_course_table('lp_item_view');
  194.         $lp_item Database::get_course_table('lp_item');
  195.         $sql_del_view "DELETE FROM $lp_item_view WHERE item_id = ".$this->db_id;
  196.         //error_log('New LP - Deleting from lp_item_view: '.$sql_del_view,0);
  197.         $res_del_view api_sql_query($sql_del_view);
  198.         $sql_del_item "DELETE FROM $lp_item WHERE id = ".$this->db_id;
  199.         //error_log('New LP - Deleting from lp_item: '.$sql_del_view,0);
  200.         $res_del_item api_sql_query($sql_del_item);
  201.         return true;
  202.     }
  203.     /**
  204.      * Drops a child from the children array
  205.      * @param    string index of child item to drop
  206.      * @return     void 
  207.      */
  208.     function drop_child($item)
  209.     {
  210.         if($this->debug>0){error_log('New LP - In learnpathItem::drop_child()',0);}
  211.         if(!empty($item))
  212.         {
  213.             foreach($this->children as $index => $child)
  214.             {
  215.                 if($child == $item){
  216.                     $this->children[$indexnull;
  217.                 }
  218.             }
  219.         }
  220.     }
  221.     /**
  222.      * Gets the current attempt_id for this user on this item
  223.      * @return    integer    The attempt_id for this item view by this user, or 1 if none defined
  224.      */
  225.     function get_attempt_id()
  226.     {
  227.         if($this->debug>0){error_log('New LP - In learnpathItem::get_attempt_id() on item '.$this->db_id,0);}
  228.         $res 1;
  229.         if(!empty($this->attempt_id))
  230.         {
  231.             $res $this->attempt_id;
  232.         }
  233.         if($this->debug>0){error_log('New LP - End of learnpathItem::get_attempt_id() on item '.$this->db_id.' - Returning '.$res,0);}
  234.         return $res;
  235.     }
  236.     /**
  237.      * Gets a list of the item's children
  238.      * @return    array    Array of children items IDs
  239.      */
  240.     function get_children()
  241.     {
  242.         if($this->debug>0){error_log('New LP - In learnpathItem::get_children()',0);}
  243.         $list array();
  244.         foreach($this->children as $child){
  245.             if(!empty($child))
  246.             {
  247.                 //error_log('New LP - Found '.$child,0);
  248.                 $list[$child;
  249.             }
  250.         }
  251.         return $list;
  252.     }
  253.     /**
  254.      * Gets the core_exit value from the database
  255.      */
  256.     function get_core_exit()
  257.     {
  258.         return $this->core_exit;
  259.     }
  260.     /**
  261.      * Gets the credit information (rather scorm-stuff) based on current status and reinit
  262.      * autorization. Credit tells the sco(content) if Dokeos will record the data it is sent (credit) or not (no-credit)
  263.      * @return    string    'credit' or 'no-credit'. Defaults to 'credit' because if we don't know enough about this item, it's probably because it was never used before.
  264.      */
  265.     function get_credit(){
  266.         if(!empty($this->debug&& $this->debug>1){error_log('New LP - In learnpathItem::get_credit()',0);}
  267.         $credit 'credit';
  268.         //now check the value of prevent_reinit (if it's 0, return credit as the default was)
  269.         if($this->get_prevent_reinit(!= 0)//if prevent_reinit == 1 (or more)
  270.             //if status is not attempted or incomplete, credit anyway. Otherwise:
  271.             //check the status in the database rather than in the object, as checking in the object
  272.             //would always return "no-credit" when we want to set it to completed
  273.             $status $this->get_status(true);
  274.             if(!empty($this->debug&& $this->debug>2){error_log('New LP - In learnpathItem::get_credit() - get_prevent_reinit!=0 and status is '.$status,0);}            
  275.             if($status != $this->possible_status[0AND $status != $this->possible_status[1]){
  276.                 $credit 'no-credit';
  277.             }
  278.         }
  279.         return $credit;
  280.     }
  281.     /**
  282.      * Gets the current start time property
  283.      * @return    integer    Current start time, or current time if none
  284.      */
  285.     function get_current_start_time()
  286.     {
  287.         if($this->debug>0){error_log('New LP - In learnpathItem::get_current_start_time()',0);}
  288.         if(empty($this->current_start_time))
  289.         {
  290.             return time();
  291.         }else{
  292.             return $this->current_start_time;
  293.         }
  294.     }
  295.     /**
  296.      * Gets the item's description
  297.      * @return    string    Description
  298.      */
  299.     function get_description(){
  300.         if($this->debug>0){error_log('New LP - In learnpathItem::get_description()',0);}
  301.         if(empty($this->description)){return '';}
  302.         return $this->description;
  303.     }
  304.     /**
  305.      * Gets the file path from the course's root directory, no matter what tool it is from.
  306.      * @return    string    The file path, or an empty string if there is no file attached, or '-1' if the file must be replaced by an error page
  307.      */
  308.     function get_file_path($path_to_scorm_dir=''){
  309.         if($this->debug>0){error_log('New LP - In learnpathItem::get_file_path()',0);}
  310.         $path $this->get_path();
  311.            $type $this->get_type();
  312.         if(empty($path))
  313.         {
  314.             if($type == 'dokeos_chapter' OR $type=='chapter' OR $type == 'dir')
  315.             {
  316.                 return '';
  317.             }
  318.             else
  319.             {
  320.                 return '-1';
  321.             }
  322.         }elseif($path == strval(intval($path))){
  323.             //the path is numeric, so it is a reference to a Dokeos object
  324.             switch($type)
  325.             {
  326.                 case 'dokeos_chapter':
  327.                 case 'dir':
  328.                 case 'chapter':
  329.                     return '';
  330.                 case TOOL_DOCUMENT:
  331.                     $table_doc Database::get_course_table(TABLE_DOCUMENT);
  332.                     $sql 'SELECT path FROM '.$table_doc.' WHERE id = '.$path;
  333.                     $res api_sql_query($sql,__FILE__,__LINE__);
  334.                     $row Database::fetch_array($res);
  335.                     $real_path 'document'.$row['path'];
  336.                     return $real_path;
  337.                 case TOOL_STUDENTPUBLICATION:
  338.                 case TOOL_QUIZ:
  339.                 case TOOL_FORUM:
  340.                 case TOOL_THREAD:
  341.                 case TOOL_LINK:
  342.                 default:
  343.                     return '-1';
  344.             }
  345.         }else{
  346.             if(!empty($path_to_scorm_dir))
  347.             {
  348.                 $path $path_to_scorm_dir.$path;
  349.             }
  350.             return $path;
  351.         }
  352.     }
  353.     /**
  354.      * Gets the DB ID
  355.      * @return    integer    Database ID for the current item
  356.      */
  357.     function get_id(){
  358.         if($this->debug>1){error_log('New LP - In learnpathItem::get_id()',0);}
  359.         if(!empty($this->db_id))
  360.         {
  361.             return $this->db_id;
  362.         }
  363.         //TODO check this return value is valid for children classes (SCORM?)
  364.         return 0;
  365.     }
  366.     /**
  367.      * Gets the current count of interactions recorded in the database
  368.      * @return    int    The current number of interactions recorder
  369.      */
  370.     function get_interactions_count()
  371.     {
  372.         if($this->debug>1){error_log('New LP - In learnpathItem::get_interactions_count()',0);}
  373.         $res 0;
  374.         if(!empty($this->interactions_count)){
  375.             $res $this->interactions_count;
  376.         }
  377.         return $res;
  378.     }
  379.     /**
  380.      * Gets the current count of objectives recorded in the database
  381.      * @return    int    The current number of objectives recorder
  382.      */
  383.     function get_objectives_count()
  384.     {
  385.         if($this->debug>1){error_log('New LP - In learnpathItem::get_objectives_count()',0);}
  386.         $res 0;
  387.         if(!empty($this->objectives_count)){
  388.             $res $this->objectives_count;
  389.         }
  390.         return $res;
  391.     }
  392.     /**
  393.      * Gets the launch_data field found in imsmanifests (this is SCORM- or AICC-related, really)
  394.      * @return    string    Launch data as found in imsmanifest and stored in Dokeos (read only). Defaults to ''.
  395.      */
  396.     function get_launch_data(){
  397.         if($this->debug>0){error_log('New LP - In learnpathItem::get_launch_data()',0);}
  398.         if(!empty($this->launch_data)){
  399.             return $this->launch_data;
  400.         }
  401.         return '';
  402.     }
  403.     /**
  404.      * Gets the lesson location
  405.      * @return string    lesson location as recorded by the SCORM and AICC elements. Defaults to ''
  406.      */
  407.     function get_lesson_location(){
  408.         if($this->debug>0){error_log('New LP - In learnpathItem::get_lesson_location()',0);}
  409.         if(!empty($this->lesson_location)){return $this->lesson_location;}else{return '';}
  410.     }
  411.     /**
  412.      * Gets the lesson_mode (scorm feature, but might be used by aicc as well as dokeos paths)
  413.      * 
  414.      * The "browse" mode is not supported yet (because there is no such way of seeing a sco in Dokeos)
  415.      * @return    string    'browse','normal' or 'review'. Defaults to 'normal'
  416.      */
  417.     function get_lesson_mode(){
  418.         $mode 'normal';
  419.         if($this->get_prevent_reinit(!= 0)//if prevent_reinit == 0
  420.             $my_status $this->get_status();
  421.             if($my_status != $this->possible_status[0AND $my_status != $this->possible_status[1]){    
  422.                 $mode 'review';
  423.             }
  424.         }
  425.         return $mode;
  426.     }
  427.     /**
  428.      * Gets the depth level
  429.      * @return int    Level. Defaults to 0
  430.      */
  431.     function get_level(){
  432.         if($this->debug>0){error_log('New LP - In learnpathItem::get_level()',0);}
  433.         if(empty($this->level)){return 0;}
  434.         return $this->level;
  435.     }
  436.     /**
  437.      * Gets the mastery score
  438.      */
  439.     function get_mastery_score()
  440.     {
  441.         if($this->debug>0){error_log('New LP - In learnpathItem::get_mastery_score()',0);}
  442.         if(isset($this->mastery_score)){return $this->mastery_score;}else{return -1;}                
  443.     }
  444.     /**
  445.      * Gets the maximum (score)
  446.      * @return    int    Maximum score. Defaults to 100 if nothing else is defined
  447.      */
  448.     function get_max(){
  449.         if($this->debug>0){error_log('New LP - In learnpathItem::get_max()',0);}
  450.         if($this->type == 'sco')
  451.         {
  452.             if(!empty($this->view_max_scoreand $this->view_max_score>0)
  453.             {
  454.                 return $this->view_max_score;
  455.             }
  456.             elseif($this->view_max_score === '')
  457.             {
  458.                 return $this->view_max_score;
  459.             }
  460.             else
  461.             {
  462.                 if(!empty($this->max_score)){return $this->max_score;}else{return 100;}
  463.             }
  464.         }
  465.         else
  466.         {
  467.             if(!empty($this->max_score)){return $this->max_score;}else{return 100;}
  468.         }
  469.     }
  470.     /**
  471.      * Gets the maximum time allowed for this user in this attempt on this item
  472.      * @return    string    Time string in SCORM format (HH:MM:SS or HH:MM:SS.SS or HHHH:MM:SS.SS)
  473.      */
  474.     function get_max_time_allowed()
  475.     {
  476.         if($this->debug>0){error_log('New LP - In learnpathItem::get_max_time_allowed()',0);}
  477.         if(!empty($this->max_time_allowed)){return $this->max_time_allowed;}else{return '';}        
  478.     }
  479.     /**
  480.      * Gets the minimum (score)
  481.      * @return int    Minimum score. Defaults to 0
  482.      */
  483.     function get_min(){
  484.         if($this->debug>0){error_log('New LP - In learnpathItem::get_min()',0);}
  485.         if(!empty($this->min_score)){return $this->min_score;}else{return 0;}
  486.     }
  487.     /**
  488.      * Gets the parent ID
  489.      * @return    int    Parent ID. Defaults to null
  490.      */
  491.     function get_parent(){
  492.         if($this->debug>0){error_log('New LP - In learnpathItem::get_parent()',0);}
  493.         if(!empty($this->parent))
  494.         {
  495.             return $this->parent;
  496.         }
  497.         //TODO check this return value is valid for children classes (SCORM?)
  498.         return null;
  499.     }
  500.     /**
  501.      * Gets the path attribute.
  502.      * @return    string    Path. Defaults to ''
  503.      */
  504.     function get_path(){
  505.         if($this->debug>0){error_log('New LP - In learnpathItem::get_path()',0);}
  506.         if(empty($this->path)){return '';}
  507.         return $this->path;
  508.     }
  509.     /**
  510.      * Gets the prerequisites string
  511.      * @return    string    Empty string or prerequisites string if defined. Defaults to
  512.      */
  513.     function get_prereq_string()
  514.     {
  515.         if($this->debug>0){error_log('New LP - In learnpathItem::get_prereq_string()',0);}
  516.         if(!empty($this->prereq_string))
  517.         {
  518.             return $this->prereq_string;
  519.         }else{
  520.             return '';
  521.         }
  522.     }
  523.     /**
  524.      * Gets the prevent_reinit attribute value (and sets it if not set already)
  525.      * @return    int    1 or 0 (defaults to 1)
  526.      */
  527.     function get_prevent_reinit(){
  528.         if($this->debug>2){error_log('New LP - In learnpathItem::get_prevent_reinit()',0);}
  529.         if(!isset($this->prevent_reinit)){
  530.             if(!empty($this->lp_id)){
  531.                 $db Database::get_course_table('lp');
  532.                    $sql "SELECT * FROM $db WHERE id = ".$this->lp_id;
  533.                 $res @api_sql_query($sql);
  534.                 if(Database::num_rows($res)<1)
  535.                 {
  536.                     $this->error "Could not find parent learnpath in learnpath table";
  537.                     if($this->debug>2){error_log('New LP - End of learnpathItem::get_prevent_reinit() - Returning false',0);}
  538.                     return false;
  539.                 }else{
  540.                     $row Database::fetch_array($res);
  541.                     $this->prevent_reinit = $row['prevent_reinit']
  542.                 }
  543.             }else{
  544.                 $this->prevent_reinit = 1;//prevent reinit is always 1 by default - see learnpath.class.php
  545.             }
  546.         }
  547.         if($this->debug>2){error_log('New LP - End of learnpathItem::get_prevent_reinit() - Returned '.$this->prevent_reinit,0);}
  548.         return $this->prevent_reinit;
  549.     }
  550.     /**
  551.      * Gets the item's reference column
  552.      * @return string    The item's reference field (generally used for SCORM identifiers)
  553.      */
  554.     function get_ref()
  555.     {
  556.         return $this->ref;
  557.     }
  558.     /**
  559.      * Gets the list of included resources as a list of absolute or relative paths of
  560.      * resources included in the current item. This allows for a better SCORM export.
  561.      * The list will generally include pictures, flash objects, java applets, or any other
  562.      * stuff included in the source of the current item. The current item is expected
  563.      * to be an HTML file. If it is not, then the function will return and empty list.
  564.      * @param    string    type (one of the Dokeos tools) - optional (otherwise takes the current item's type)
  565.      * @param    string    path (absolute file path) - optional (otherwise takes the current item's path)
  566.      * @param    int        level of recursivity we're in
  567.      * @return    array    List of file paths. An additional field containing 'local' or 'remote' helps determine if the file should be copied into the zip or just linked
  568.      */
  569.     function get_resources_from_source($type=null,$abs_path=null$recursivity=1)
  570.     {
  571.         $max 5;
  572.         if($recursivity $max)
  573.         {
  574.             return array();
  575.         }
  576.         if(!isset($type))
  577.         {
  578.             $type $this->get_type();
  579.         }
  580.         if(!isset($abs_path))
  581.         {
  582.             $path $this->get_file_path();
  583.                $abs_path api_get_path(SYS_COURSE_PATH).api_get_course_path().'/'.$path;
  584.                //echo "Abs path coming from item : ".$abs_path."<br/>\n";
  585.         }
  586.         /*
  587.         else
  588.         {
  589.             echo "Abs path coming from param: ".$abs_path."<br/>\n";
  590.         }
  591.         */
  592.         //error_log(str_repeat(' ',$recursivity).'Analyse file '.$abs_path,0);
  593.         $files_list array();
  594.         $type $this->get_type();
  595.         switch($type)
  596.         {
  597.             case TOOL_DOCUMENT 
  598.             case TOOL_QUIZ:
  599.             case 'sco':
  600.                 //get the document and, if HTML, open it
  601.                 
  602.                 if(is_file($abs_path))
  603.                 {
  604.                     //for now, read the whole file in one go (that's gonna be a problem when the file is too big)
  605.                     $info pathinfo($abs_path);
  606.                     $ext $info['extension'];
  607.                     switch(strtolower($ext))
  608.                     {
  609.                         case 'html':
  610.                         case 'htm':
  611.                         case 'shtml':
  612.                         case 'css':
  613.                              $wanted_attributes array('src','url','@import','href','value');
  614.                             //parse it for included resources
  615.                             $file_content file_get_contents($abs_path);
  616.                             //get an array of attributes from the HTML source
  617.                             $attributes learnpathItem::parse_HTML_attributes($file_content,$wanted_attributes);
  618.                             //look at 'src' attributes in this file
  619.                             foreach($wanted_attributes as $attr)
  620.                             {
  621.                                 if(isset($attributes[$attr]))
  622.                                 {
  623.                                     //find which kind of path these are (local or remote)
  624.                                     $sources $attributes[$attr];
  625.                                     
  626.                                     foreach($sources as $source)
  627.                                     {
  628.                                         //skip what is obviously not a resource
  629.                                         if(strpos($source,"+this.")) continue//javascript code - will still work unaltered
  630.                                         if(strpos($source,'.')=== falsecontinue//no dot, should not be an external file anyway
  631.                                         if(strpos($source,'mailto:')) continue//mailto link
  632.                                         if(strpos($source,';'&& !strpos($source,'&amp;')) continue//avoid code - that should help
  633.                                         
  634.                                         if($attr == 'value')
  635.                                         {
  636.                                             if(strpos($source 'mp3file'))
  637.                                             {
  638.                                                 $files_list[array(substr($source0strpos($source '.swf')+4),'local','abs');
  639.                                                 $mp3file substr($source strpos($source 'mp3file=')+8);
  640.                                                 if(substr($mp3file,0,1== '/')
  641.                                                     $files_list[array($mp3file,'local','abs');
  642.                                                 else
  643.                                                     $files_list[array($mp3file,'local','rel');
  644.                                             }
  645.                                             elseif(strpos($source'flv=')===0)
  646.                                             {
  647.                                                 $source substr($source4);
  648.                                                 if(strpos($source'&')>0)
  649.                                                 {
  650.                                                     $source substr($source,0,strpos($source'&'));
  651.                                                 }
  652.                                                 if(strpos($source,'://')>0)
  653.                                                 {
  654.                                                     if(strpos($source,api_get_path(WEB_PATH))!==false)
  655.                                                     {
  656.                                                         //we found the current portal url
  657.                                                         $files_list[array($source,'local','url');
  658.                                                     }
  659.                                                     else
  660.                                                     {
  661.                                                         //we didn't find any trace of current portal
  662.                                                         $files_list[array($source,'remote','url');
  663.                                                     }
  664.                                                 }
  665.                                                 else
  666.                                                 {
  667.                                                     $files_list[array($source,'local','abs');
  668.                                                 }
  669.                                                 continue//skipping anything else to avoid two entries (while the others can have sub-files in their url, flv's can't)
  670.                                             }
  671.                                         }
  672.                                         if(strpos($source,'://'0)
  673.                                         {
  674.                                             
  675.                                             //cut at '?' in a URL with params
  676.                                             if(strpos($source,'?')>0)
  677.                                             {
  678.                                                 $second_part substr($source,strpos($source,'?'));
  679.                                                 if(strpos($second_part,'://')>0)
  680.                                                 {//if the second part of the url contains a url too, treat the second one before cutting
  681.  
  682.                                                     $pos1 strpos($second_part,'=');
  683.                                                     $pos2 strpos($second_part,'&');
  684.                                                     $second_part substr($second_part,$pos1+1,$pos2-($pos1+1));
  685.                                                     if(strpos($second_part,api_get_path(WEB_PATH))!==false)
  686.                                                     {
  687.                                                         //we found the current portal url
  688.                                                         $files_list[array($second_part,'local','url');
  689.                                                         $in_files_list[learnpathItem::get_resources_from_source(TOOL_DOCUMENT,$second_part,$recursivity+1);
  690.                                                         if(count($in_files_list)>0)
  691.                                                         {
  692.                                                             $files_list array_merge($files_list,$in_files_list);
  693.                                                         }
  694.                                                     }
  695.                                                     else
  696.                                                     {
  697.                                                         //we didn't find any trace of current portal
  698.                                                         $files_list[array($second_part,'remote','url');
  699.                                                     }
  700.                                                 }
  701.                                                 elseif(strpos($second_part,'=')>0)
  702.                                                 {
  703.                                                     if(substr($second_part,0,1=== '/')
  704.                                                     {    //link starts with a /, making it absolute (relative to DocumentRoot)
  705.                                                         $files_list[array($second_part,'local','abs');
  706.                                                         $in_files_list[learnpathItem::get_resources_from_source(TOOL_DOCUMENT,$second_part,$recursivity+1)
  707.                                                         if(count($in_files_list)>0)
  708.                                                         {
  709.                                                             $files_list array_merge($files_list,$in_files_list);
  710.                                                         
  711.                                                     }
  712.                                                     elseif(strstr($second_part,'..'=== 0)
  713.                                                     {    //link is relative but going back in the hierarchy
  714.                                                         $files_list[array($second_part,'local','rel');
  715.                                                         $dir dirname($abs_path);
  716.                                                         $new_abs_path realpath($dir.'/'.$second_part);
  717.                                                         $in_files_list[learnpathItem::get_resources_from_source(TOOL_DOCUMENT,$new_abs_path,$recursivity+1)
  718.                                                         if(count($in_files_list)>0)
  719.                                                         {
  720.                                                             $files_list array_merge($files_list,$in_files_list);
  721.                                                         
  722.                                                     }
  723.                                                     else
  724.                                                     {    //no starting '/', making it relative to current document's path
  725.                                                         if(substr($second_part,0,2== './')
  726.                                                         {
  727.                                                             $second_part substr($second_part,2);
  728.                                                         }
  729.                                                         $files_list[array($second_part,'local','rel');
  730.                                                         $dir dirname($abs_path);
  731.                                                         $new_abs_path realpath($dir.'/'.$second_part);
  732.                                                         $in_files_list[learnpathItem::get_resources_from_source(TOOL_DOCUMENT,$new_abs_path,$recursivity+1)
  733.                                                         if(count($in_files_list)>0)
  734.                                                         {
  735.                                                             $files_list array_merge($files_list,$in_files_list);
  736.                                                         
  737.                                                     }
  738.                                                     
  739.                                                 }
  740.                                                 //leave that second part behind now
  741.                                                 $source substr($source,0,strpos($source,'?'));
  742.                                                 if(strpos($source,'://'0)
  743.                                                 {
  744.                                                     if(strpos($source,api_get_path(WEB_PATH))!==false)
  745.                                                     {
  746.                                                         //we found the current portal url
  747.                                                         $files_list[array($source,'local','url');
  748.                                                         $in_files_list[learnpathItem::get_resources_from_source(TOOL_DOCUMENT,$source,$recursivity+1);
  749.                                                         if(count($in_files_list)>0)
  750.                                                         {
  751.                                                             $files_list array_merge($files_list,$in_files_list);
  752.                                                         
  753.                                                     }
  754.                                                     else
  755.                                                     {
  756.                                                         //we didn't find any trace of current portal
  757.                                                         $files_list[array($source,'remote','url');
  758.                                                     }
  759.                                                 }
  760.                                                 else
  761.                                                 {
  762.                                                     //no protocol found, make link local
  763.                                                     if(substr($source,0,1=== '/')
  764.                                                     {    //link starts with a /, making it absolute (relative to DocumentRoot)
  765.                                                         $files_list[array($source,'local','abs');
  766.                                                         $in_files_list[learnpathItem::get_resources_from_source(TOOL_DOCUMENT,$source,$recursivity+1)
  767.                                                         if(count($in_files_list)>0)
  768.                                                         {
  769.                                                             $files_list array_merge($files_list,$in_files_list);
  770.                                                         
  771.                                                     }
  772.                                                     elseif(strstr($source,'..'=== 0)
  773.                                                     {    //link is relative but going back in the hierarchy
  774.                                                         $files_list[array($source,'local','rel');
  775.                                                         $dir dirname($abs_path);
  776.                                                         $new_abs_path realpath($dir.'/'.$source);
  777.                                                         $in_files_list[learnpathItem::get_resources_from_source(TOOL_DOCUMENT,$new_abs_path,$recursivity+1)
  778.                                                         if(count($in_files_list)>0)
  779.                                                         {
  780.                                                             $files_list array_merge($files_list,$in_files_list);
  781.                                                         
  782.                                                     }
  783.                                                     else
  784.                                                     {    //no starting '/', making it relative to current document's path
  785.                                                         if(substr($source,0,2== './')
  786.                                                         {
  787.                                                             $source substr($source,2);
  788.                                                         }
  789.                                                         $files_list[array($source,'local','rel');
  790.                                                         $dir dirname($abs_path);
  791.                                                         $new_abs_path realpath($dir.'/'.$source);
  792.                                                         $in_files_list[learnpathItem::get_resources_from_source(TOOL_DOCUMENT,$new_abs_path,$recursivity+1)
  793.                                                         if(count($in_files_list)>0)
  794.                                                         {
  795.                                                             $files_list array_merge($files_list,$in_files_list);
  796.                                                         
  797.                                                     }
  798.                                                 }
  799.                                             }
  800.                                             //found some protocol there
  801.                                             if(strpos($source,api_get_path(WEB_PATH))!==false)
  802.                                             {
  803.                                                 //we found the current portal url
  804.                                                 $files_list[array($source,'local','url');
  805.                                                 $in_files_list[learnpathItem::get_resources_from_source(TOOL_DOCUMENT,$source,$recursivity+1);
  806.                                                 if(count($in_files_list)>0)
  807.                                                 {
  808.                                                     $files_list array_merge($files_list,$in_files_list);
  809.                                                 
  810.                                             }
  811.                                             else
  812.                                             {
  813.                                                 //we didn't find any trace of current portal
  814.                                                 $files_list[array($source,'remote','url');
  815.                                             }
  816.                                         }
  817.                                         else
  818.                                         {
  819.                                             //no protocol found, make link local
  820.                                             if(substr($source,0,1=== '/')
  821.                                             {    //link starts with a /, making it absolute (relative to DocumentRoot)
  822.                                                 $files_list[array($source,'local','abs');
  823.                                                 $in_files_list[learnpathItem::get_resources_from_source(TOOL_DOCUMENT,$source,$recursivity+1)
  824.                                                 if(count($in_files_list)>0)
  825.                                                 {
  826.                                                     $files_list array_merge($files_list,$in_files_list);
  827.                                                 
  828.                                             }
  829.                                             elseif(strstr($source,'..'=== 0)
  830.                                             {    //link is relative but going back in the hierarchy
  831.                                                 $files_list[array($source,'local','rel');
  832.                                                 $dir dirname($abs_path);
  833.                                                 $new_abs_path realpath($dir.'/'.$source);
  834.                                                 $in_files_list[learnpathItem::get_resources_from_source(TOOL_DOCUMENT,$new_abs_path,$recursivity+1)
  835.                                                 if(count($in_files_list)>0)
  836.                                                 {
  837.                                                     $files_list array_merge($files_list,$in_files_list);
  838.                                                 
  839.                                             }
  840.                                             else
  841.                                             {    //no starting '/', making it relative to current document's path
  842.                                                 if(substr($source,0,2== './')
  843.                                                 {
  844.                                                     $source substr($source,2);
  845.                                                 }
  846.                                                 $files_list[array($source,'local','rel');
  847.                                                 $dir dirname($abs_path);
  848.                                                 $new_abs_path realpath($dir.'/'.$source);
  849.                                                 $in_files_list[learnpathItem::get_resources_from_source(TOOL_DOCUMENT,$new_abs_path,$recursivity+1)
  850.                                                 if(count($in_files_list)>0)
  851.                                                 {
  852.                                                     $files_list array_merge($files_list,$in_files_list);
  853.                                                 
  854.                                             }
  855.                                         }
  856.                                     }
  857.                                 }
  858.                             }
  859.                             break;
  860.                         default:
  861.                             break;
  862.                     }
  863.                     
  864.                 }
  865.                 else
  866.                 {
  867.                     //the file could not be found
  868.                     return false;
  869.                 }
  870.                 break;
  871.             default//ignore
  872.                 break;
  873.         }
  874.         //error_log(str_repeat(' ',$recursivity),'found files '.print_r($files_list,true),0);
  875.         //return $files_list;
  876.         $checked_files_list array();
  877.         $checked_array_list array();
  878.         foreach($files_list as $idx => $file)
  879.         {
  880.             if(!empty($file[0]))
  881.             {
  882.                 if(!in_array($file[0],$checked_files_list))
  883.                 {
  884.                     $checked_files_list[$files_list[$idx][0];
  885.                     $checked_array_list[$files_list[$idx];
  886.                 }
  887.             }
  888.         }
  889.         return $checked_array_list;
  890.     }
  891.     /**
  892.      * Gets the score
  893.      * @return    float    The current score or 0 if no score set yet
  894.      */
  895.     function get_score(){
  896.         if($this->debug>0){error_log('New LP - In learnpathItem::get_score()',0);}
  897.         $res 0;
  898.         if(!empty($this->current_score))
  899.         {
  900.             $res $this->current_score;
  901.         }
  902.         if($this->debug>1){error_log('New LP - Out of learnpathItem::get_score() - returning '.$res,0);}
  903.         return $res;
  904.     }
  905.     /**
  906.      * Gets the item status
  907.      * @param    boolean    Do or don't check into the database for the latest value. Optional. Default is true
  908.      * @param    boolean    Do or don't update the local attribute value with what's been found in DB
  909.      * @return    string    Current status or 'Nnot attempted' if no status set yet
  910.      */
  911.     function get_status($check_db=true,$update_local=false)
  912.     {
  913.         if($this->debug>0){error_log('New LP - In learnpathItem::get_status() on item '.$this->db_id,0);}
  914.         if($check_db)
  915.         {
  916.             if($this->debug>2){error_log('New LP - In learnpathItem::get_status(): checking db',0);}
  917.             $table Database::get_course_table('lp_item_view');
  918.             $sql "SELECT * FROM $table WHERE id = '".$this->db_item_view_id."' AND view_count = '".$this->get_attempt_id()."'";
  919.             if($this->debug>2){error_log('New LP - In learnpathItem::get_status() - Checking DB: '.$sql,0);}
  920.             $res api_sql_query($sql);
  921.             if(Database::num_rows($res)==1){
  922.                 $row Database::fetch_array($res);
  923.                 if($update_local==true){
  924.                     $this->set_status($row['status']);
  925.                 }
  926.                 if($this->debug>2){error_log('New LP - In learnpathItem::get_status() - Returning db value '.$row['status'],0);}
  927.                 return $row['status'];
  928.             }
  929.         }
  930.         else
  931.         {
  932.             if($this->debug>2){error_log('New LP - In learnpathItem::get_status() - in get_status: using attrib',0);}
  933.             if(!empty($this->status))
  934.             {
  935.                 if($this->debug>2){error_log('New LP - In learnpathItem::get_status() - Returning attrib: '.$this->status,0);}
  936.                 return $this->status;
  937.             }
  938.         }
  939.            if($this->debug>2){error_log('New LP - In learnpathItem::get_status() - Returning default '.$this->possible_status[0],0);}
  940.         return $this->possible_status[0];
  941.     }
  942.     /**
  943.      * Gets the suspend data
  944.      */
  945.     function get_suspend_data()
  946.     {
  947.         if($this->debug>0){error_log('New LP - In learnpathItem::get_suspend_data()',0);}
  948.         //TODO : improve cleaning of breaklines ... it works but is it really a beautiful way to do it ?
  949.         if(!empty($this->current_data)){return str_replace(array("\r","\n"),array('\r','\n'),$this->current_data);}else{return '';}
  950.     }
  951.     /**
  952.      * Gets the total time spent on this item view so far
  953.      * @param    string    Origin of the request. If coming from PHP, send formatted as xxhxx'xx", otherwise use scorm format 00:00:00
  954.      * @param    integer    Given time is a default time to return formatted
  955.      */
  956.     function get_scorm_time($origin='php',$given_time=null){
  957.         //if($this->debug>0){error_log('New LP - In learnpathItem::get_scorm_time()',0);}
  958.         $h get_lang('h');
  959.         if(!isset($given_time)){
  960.             if(!empty($this->current_start_time&& is_object($this)){
  961.                 if(!empty($this->current_stop_time)){
  962.                     $time $this->current_stop_time - $this->current_start_time;
  963.                 }else{
  964.                     $time time($this->current_start_time;
  965.                 }
  966.             }else{
  967.                 if($origin == 'js'){
  968.                     return '00:00:00';
  969.                 }else{
  970.                     return '00'.$h.'00\'00"';
  971.                 }
  972.             }
  973.         }else{
  974.             $time $given_time;
  975.         }
  976.         $hours $time/3600;
  977.         $mins  ($time%3600)/60;
  978.         $secs  ($time%60);
  979.           if($origin == 'js'){
  980.             $scorm_time trim(sprintf("%4d:%02d:%02d",$hours,$mins,$secs));
  981.           }else{
  982.             $scorm_time trim(sprintf("%4d$h%02d'%02d\"",$hours,$mins,$secs));
  983.           }
  984.         return $scorm_time;
  985.     }
  986.     /**
  987.      * Returns the item's title
  988.      * @return    string    Title
  989.      */
  990.     function get_title(){
  991.         if($this->debug>0){error_log('New LP - In learnpathItem::get_title()',0);}
  992.         if(empty($this->title)){return '';}
  993.         return $this->title;
  994.     }
  995.     /**
  996.      * Returns the total time used to see that item
  997.      * @return    integer    Total time
  998.      */
  999.     function get_total_time(){
  1000.         if($this->debug>0){error_log('New LP - In learnpathItem::get_total_time()',0);}
  1001.         if($this->current_start_time == 0)//shouldn't be necessary thanks to the open() method
  1002.             $this->current_start_time = time();
  1003.         }
  1004.         $time $this->current_stop_time - $this->current_start_time;
  1005.         if($time 0){
  1006.             return 0;
  1007.         }else{
  1008.         if($this->debug>2){error_log('New LP - In learnpathItem::get_total_time() - Current stop time = '.$this->current_stop_time.', current start time = '.$this->current_start_time.' Returning '.$time,0);}
  1009.             return $time;
  1010.         }
  1011.     }
  1012.     /**
  1013.      * Gets the item type
  1014.      * @return    string    The item type (can be doc, dir, sco, asset)
  1015.      */
  1016.     function get_type()
  1017.     {
  1018.         $res 'asset';
  1019.         if($this->debug>0){error_log('New LP - In learnpathItem::get_type() on item '.$this->db_id,0);}
  1020.         if(!empty($this->type))
  1021.         {
  1022.             //error_log('In item::get_type() - returning '.$this->type,0);
  1023.             $res $this->type;
  1024.         }
  1025.         if($this->debug>2){error_log('New LP - In learnpathItem::get_type() - Returning '.$res.' for item '.$this->db_id,0);}
  1026.         return $res;        
  1027.     }
  1028.     /**
  1029.      * Gets the view count for this item
  1030.      */
  1031.     function get_view_count(){
  1032.         if($this->debug>0){error_log('New LP - In learnpathItem::get_view_count()',0);}
  1033.         if(!empty($this->attempt_id)){
  1034.             return $this->attempt_id;
  1035.         }else{
  1036.             return 0;
  1037.         }
  1038.     }
  1039.     /**
  1040.      * Tells if an item is done ('completed','passed','succeeded') or not
  1041.      * @return    bool    True if the item is done ('completed','passed','succeeded'), false otherwise
  1042.      */
  1043.     function is_done(){
  1044.            if($this->status_is(array('completed','passed','succeeded'))){
  1045.                if($this->debug>2){error_log('New LP - In learnpath::is_done() - Item '.$this->get_id().' is complete',0);}
  1046.                return true;
  1047.            }else{
  1048.                if($this->debug>2){error_log('New LP - In learnpath::is_done() - Item '.$this->get_id().' is not complete',0);}
  1049.                return false;
  1050.            }
  1051.     }
  1052.     /**
  1053.      * Tells if a restart is allowed (take it from $this->prevent_reinit and $this->status)
  1054.      * @return    integer    -1 if retaking the sco another time for credit is not allowed,
  1055.      *                       0 if it is not allowed but the item has to be finished
  1056.      *                       1 if it is allowed. Defaults to 1
  1057.      */
  1058.     function is_restart_allowed()
  1059.     {
  1060.         if($this->debug>2){error_log('New LP - In learnpathItem::is_restart_allowed()',0);}
  1061.         $restart 1;
  1062.         $mystatus $this->get_status(true);
  1063.         if($this->get_prevent_reinit(0)//if prevent_reinit == 1 (or more)
  1064.             //if status is not attempted or incomplete, authorize retaking (of the same) anyway. Otherwise:
  1065.             if($mystatus != $this->possible_status[0AND $mystatus != $this->possible_status[1]){
  1066.                 $restart = -1;
  1067.             }else{
  1068.                 $restart 0;
  1069.             }
  1070.         }else{
  1071.             if($mystatus == $this->possible_status[0OR $mystatus == $this->possible_status[1]){
  1072.                 $restart = -1;
  1073.             }
  1074.         }
  1075.         if($this->debug>2){error_log('New LP - End of learnpathItem::is_restart_allowed() - Returning '.$restart,0);}
  1076.         return $restart;
  1077.     }
  1078.     /**
  1079.      * Opens/launches the item. Initialises runtime values.
  1080.      * @return    boolean    True on success, false on failure.
  1081.      */
  1082.     function open($allow_new_attempt=false){
  1083.         if($this->debug>0){error_log('New LP - In learnpathItem::open()',0);}
  1084.         if($this->prevent_reinit == 0)
  1085.         {
  1086.             $this->current_score = 0;
  1087.             $this->current_start_time = time();
  1088.             //In this case, as we are opening the item, what is important to us
  1089.             //is the database status, in order to know if this item has already
  1090.             //been used in the past (rather than just loaded and modified by
  1091.             //some javascript but not written in the database).
  1092.             //If the database status is different from 'not attempted', we can
  1093.             //consider this item has already been used, and as such we can
  1094.             //open a new attempt. Otherwise, we'll just reuse the current
  1095.             //attempt, which is generally created the first time the item is
  1096.             //loaded (for example as part of the table of contents)
  1097.             $stat $this->get_status(true);
  1098.             if($allow_new_attempt && isset($stat&& ($stat != $this->possible_status[0]))
  1099.             {
  1100.                 $this->attempt_id = $this->attempt_id + 1//open a new attempt
  1101.             }
  1102.             $this->status = $this->possible_status[1];
  1103.         }
  1104.         else
  1105.         {
  1106.             if($this->current_start_time == 0)
  1107.             //small exception for start time, to avoid amazing values
  1108.                 $this->current_start_time = time();
  1109.             }
  1110.             //error_log('New LP - reinit blocked by setting',0);
  1111.         }
  1112.     }
  1113.     /**
  1114.      * Outputs the item contents
  1115.      * @return    string    HTML file (displayable in an <iframe>) or empty string if no path defined
  1116.      */
  1117.     function output()
  1118.     {
  1119.         if($this->debug>0){error_log('New LP - In learnpathItem::output()',0);}
  1120.         if(!empty($this->pathand is_file($this->path))
  1121.         {
  1122.             $output '';
  1123.             $output .= file_get_contents($this->path);
  1124.             return $output;
  1125.         }
  1126.         return '';
  1127.     }
  1128.     /**
  1129.      * Parses the prerequisites string with the AICC logic language
  1130.      * @param    string    The prerequisites string as it figures in imsmanifest.xml
  1131.      * @param    Array    Array of items in the current learnpath object. Although we're in the learnpathItem object, it's necessary to have a list of all items to be able to check the current item's prerequisites
  1132.      * @param    Array    List of references (the "ref" column in the lp_item table) that are strings used in the expression of prerequisites.
  1133.      * @param    integer    The user ID. In some cases like Dokeos quizzes, it's necessary to have the user ID to query other tables (like the results of quizzes)
  1134.      * @return    boolean    True if the list of prerequisites given is entirely satisfied, false otherwise
  1135.      */
  1136.     function parse_prereq($prereqs_string$items$refs_list,$user_id){
  1137.         if($this->debug>0){error_log('New LP - In learnpathItem::parse_prereq() for learnpath '.$this->lp_id.' with string '.$prereqs_string,0);}
  1138.         //deal with &, |, ~, =, <>, {}, ,, X*, () in reverse order
  1139.         $this->prereq_alert = '';
  1140.         // First parse all parenthesis by using a sequential loop (looking for less-inclusives first)
  1141.         if($prereqs_string == '_true_'){return true;}
  1142.         if($prereqs_string == '_false_'){        
  1143.             if(empty($this->prereq_alert)){
  1144.                 $this->prereq_alert = get_lang('_prereq_not_complete');
  1145.             }
  1146.             return false;
  1147.         }        
  1148.         while(strpos($prereqs_string,'(')!==false){
  1149.             //remove any () set and replace with its value
  1150.             $matches array();
  1151.             $res preg_match_all('/(\(([^\(\)]*)\))/',$prereqs_string,$matches);
  1152.             if($res){
  1153.                 foreach($matches[2as $id=>$match){
  1154.                     $str_res $this->parse_prereq($match,$items,$refs_list,$user_id);
  1155.                     if($str_res){
  1156.                         $prereqs_string str_replace($matches[1][$id],'_true_',$prereqs_string);
  1157.                     }else{
  1158.                         $prereqs_string str_replace($matches[1][$id],'_false_',$prereqs_string);
  1159.                     }
  1160.                 }
  1161.             }
  1162.         }
  1163.         
  1164.         //parenthesis removed, now look for ORs as it is the lesser-priority binary operator (= always uses one text operand)
  1165.         if(strpos($prereqs_string,"|")===false){
  1166.             if($this->debug>1){error_log('New LP - Didnt find any OR, looking for AND',0);}
  1167.             if(strpos($prereqs_string,"&")!==false){
  1168.                 $list split("&",$prereqs_string);
  1169.                 if(count($list)>1){
  1170.                     $andstatus true;
  1171.                     foreach($list as $condition){
  1172.                         $andstatus $andstatus && $this->parse_prereq($condition,$items,$refs_list,$user_id);
  1173.                         if($andstatus==false){
  1174.                             if($this->debug>1){error_log('New LP - One condition in AND was false, short-circuit',0);}
  1175.                             break;                            
  1176.                         }
  1177.                     }
  1178.                     if(empty($this->prereq_alert&& !$andstatus){
  1179.                         $this->prereq_alert = get_lang('_prereq_not_complete');
  1180.                     }
  1181.                     return $andstatus;
  1182.                 }else{
  1183.                     if(isset($items[$refs_list[$list[0]]])){
  1184.                         $status $items[$refs_list[$list[0]]]->get_status(true);
  1185.                         $returnstatus (($status == $this->possible_status[2]OR ($status == $this->possible_status[3]));
  1186.                         if(empty($this->prereq_alert&& !$returnstatus){
  1187.                             $this->prereq_alert = get_lang('_prereq_not_complete');
  1188.                         }
  1189.                         return $returnstatus;
  1190.                     }
  1191.                     $this->prereq_alert = get_lang('_prereq_not_complete');
  1192.                     return false;
  1193.                 }
  1194.             }else{
  1195.                 
  1196.                 //no ORs found, now look for ANDs
  1197.                 
  1198.                 if($this->debug>1){error_log('New LP - Didnt find any AND, looking for =',0);}                
  1199.                 if(strpos($prereqs_string,"=")!==false){
  1200.                     if($this->debug>1){error_log('New LP - Found =, looking into it',0);}
  1201.                     //we assume '=' signs only appear when there's nothing else around
  1202.                     $params split('=',$prereqs_string);
  1203.                     if(count($params== 2){
  1204.                         //right number of operands
  1205.                         if(isset($items[$refs_list[$params[0]]])){
  1206.                             $status $items[$refs_list[$params[0]]]->get_status(true);
  1207.                             $returnstatus ($status == $params[1]);
  1208.                             if(empty($this->prereq_alert&& !$returnstatus){
  1209.                                 $this->prereq_alert = get_lang('_prereq_not_complete');
  1210.                             }
  1211.                             return $returnstatus;
  1212.                         }
  1213.                         $this->prereq_alert = get_lang('_prereq_not_complete');
  1214.                         return false;
  1215.                     }
  1216.                 }else{
  1217.                 
  1218.                     //No ANDs found, look for <>
  1219.                 
  1220.                     if($this->debug>1){error_log('New LP - Didnt find any =, looking for <>',0);}                
  1221.                     if(strpos($prereqs_string,"<>")!==false){
  1222.                         if($this->debug>1){error_log('New LP - Found <>, looking into it',0);}
  1223.                         //we assume '<>' signs only appear when there's nothing else around
  1224.                         $params split('<>',$prereqs_string);
  1225.                         if(count($params== 2){
  1226.                             //right number of operands
  1227.                             if(isset($items[$refs_list[$params[0]]])){
  1228.                                 $status $items[$refs_list[$params[0]]]->get_status(true);
  1229.                                 $returnstatus =  ($status != $params[1]);
  1230.                                 if(empty($this->prereq_alert&& !$returnstatus){
  1231.                                     $this->prereq_alert = get_lang('_prereq_not_complete');
  1232.                                 }
  1233.                                 return $returnstatus;
  1234.                             }
  1235.                             $this->prereq_alert = get_lang('_prereq_not_complete');
  1236.                             return false;
  1237.                         }
  1238.                     }else{
  1239.                         
  1240.                         //No <> found, look for ~ (unary)
  1241.                         
  1242.                         if($this->debug>1){error_log('New LP - Didnt find any =, looking for ~',0);}
  1243.                         //only remains: ~ and X*{}
  1244.                         if(strpos($prereqs_string,"~")!==false){
  1245.                             //found NOT
  1246.                             if($this->debug>1){error_log('New LP - Found ~, looking into it',0);}
  1247.                             $list array();
  1248.                             $myres preg_match('/~([^(\d+\*)\{]*)/',$prereqs_string,$list);
  1249.                             if($myres){
  1250.                                 $returnstatus !$this->parse_prereq($list[1],$items,$refs_list,$user_id);
  1251.                                 if(empty($this->prereq_alert&& !$returnstatus){
  1252.                                     $this->prereq_alert = get_lang('_prereq_not_complete');
  1253.                                 }
  1254.                                 return $returnstatus;
  1255.                             }else{
  1256.                                 //strange...
  1257.                                 if($this->debug>1){error_log('New LP - Found ~ but strange string: '.$prereqs_string,0);}
  1258.                             }
  1259.                         }else{
  1260.                             
  1261.                             //Finally, look for sets/groups
  1262.                             
  1263.                             if($this->debug>1){error_log('New LP - Didnt find any ~, looking for groups',0);}                
  1264.                             //only groups here
  1265.                             $groups array();
  1266.                             $groups_there preg_match_all('/((\d+\*)?\{([^\}]+)\}+)/',$prereqs_string,$groups);
  1267.                             if($groups_there){
  1268.                                 foreach($groups[1as $gr//only take the results that correspond to the big brackets-enclosed condition
  1269.                                 {
  1270.                                     if($this->debug>1){error_log('New LP - Dealing with group '.$gr,0);}
  1271.                                     $multi array();
  1272.                                     $mycond false;
  1273.                                     if(preg_match('/(\d+)\*\{([^\}]+)\}/',$gr,$multi)){
  1274.                                         if($this->debug>1){error_log('New LP - Found multiplier '.$multi[0],0);}
  1275.                                         $count $multi[1];
  1276.                                         $list split(',',$multi[2]);
  1277.                                         $mytrue 0;
  1278.                                         foreach($list as $cond){
  1279.                                             if(isset($items[$refs_list[$cond]])){
  1280.                                                 $status $items[$refs_list[$cond]]->get_status(true);
  1281.                                                 if (($status == $this->possible_status[2]OR ($status == $this->possible_status[3])){
  1282.                                                     $mytrue ++;
  1283.                                                     if($this->debug>1){error_log('New LP - Found true item, counting.. ('.($mytrue).')',0);}
  1284.                                                 }
  1285.                                             }else{
  1286.                                                 if($this->debug>1){error_log('New LP - item '.$cond.' does not exist in items list',0);}
  1287.                                             }
  1288.                                         }
  1289.                                         if($mytrue >= $count){
  1290.                                             if($this->debug>1){error_log('New LP - Got enough true results, return true',0);}
  1291.                                             $mycond true;
  1292.                                         }else{
  1293.                                             if($this->debug>1){error_log('New LP - Not enough true results',0);}
  1294.                                         }
  1295.                                     }
  1296.                                     else{
  1297.                                         if($this->debug>1){error_log('New LP - No multiplier',0);}
  1298.                                         $list split(',',$gr);
  1299.                                         $mycond true;
  1300.                                         foreach($list as $cond){
  1301.                                             if(isset($items[$refs_list[$cond]])){
  1302.                                                 $status $items[$refs_list[$cond]]->get_status(true);
  1303.                                                 if (($status == $this->possible_status[2]OR ($status == $this->possible_status[3])){
  1304.                                                     $mycond true;
  1305.                                                     if($this->debug>1){error_log('New LP - Found true item',0);}                                                
  1306.                                                 }else{
  1307.                                                     if($this->debug>1){error_log('New LP - Found false item, the set is not true, return false',0);}                                                
  1308.                                                     $mycond false;
  1309.                                                     break;
  1310.                                                 }
  1311.                                             }else{
  1312.                                                 if($this->debug>1){error_log('New LP - item '.$cond.' does not exist in items list',0);}
  1313.                                                 if($this->debug>1){error_log('New LP - Found false item, the set is not true, return false',0);}                                    
  1314.                                                 $mycond false;
  1315.                                                 break;
  1316.                                             }
  1317.                                         }
  1318.                                     }
  1319.                                     if(!$mycond && empty($this->prereq_alert)){
  1320.                                         $this->prereq_alert = get_lang('_prereq_not_complete');
  1321.                                     }
  1322.                                     return $mycond;
  1323.                                 }
  1324.                             }else{
  1325.                                 
  1326.                                 //Nothing found there either. Now return the value of the corresponding resource completion status
  1327.                                 
  1328.                                 if($this->debug>1){error_log('New LP - Didnt find any group, returning value for '.$prereqs_string,0);}
  1329.                                 if(isset($items[$refs_list[$prereqs_string]])){                                    
  1330.                                     if($items[$refs_list[$prereqs_string]]->type == 'quiz')
  1331.                                     {
  1332.                                         $sql 'SELECT exe_result, exe_weighting
  1333.                                                 FROM '.Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES).'
  1334.                                                 WHERE exe_exo_id = '.$items[$refs_list[$prereqs_string]]->path.
  1335.                                                 AND exe_user_id = '.$user_id.
  1336.                                                 ORDER BY exe_date DESC
  1337.                                                 LIMIT 0, 1';
  1338.                                         $rs_quiz api_sql_query($sql__FILE____LINE__);
  1339.                                         if($quiz Database :: fetch_array($rs_quiz))
  1340.                                         {
  1341.                                             if($quiz['exe_result'>= $items[$refs_list[$prereqs_string]]->get_mastery_score())
  1342.                                             {
  1343.                                                 $returnstatus true;
  1344.                                             }
  1345.                                             else
  1346.                                             {
  1347.                                                 $this->prereq_alert = get_lang('_prereq_not_complete');
  1348.                                                 $returnstatus false;
  1349.                                             }
  1350.                                         }
  1351.                                         else
  1352.                                         {
  1353.                                             $this->prereq_alert = get_lang('_prereq_not_complete');
  1354.                                             $returnstatus false;
  1355.                                         }
  1356.                                         return $returnstatus;
  1357.                                     }
  1358.                                     else
  1359.                                     {
  1360.                                         $status $items[$refs_list[$prereqs_string]]->get_status(true);
  1361.                                         $returnstatus (($status == $this->possible_status[2]OR ($status == $this->possible_status[3]));
  1362.                                         if(!$returnstatus && empty($this->prereq_alert)){
  1363.                                             $this->prereq_alert = get_lang('_prereq_not_complete');
  1364.                                         }
  1365.                                         if(!$returnstatus){
  1366.                                             if($this->debug>1){error_log('New LP - Prerequisite '.$prereqs_string.' not complete',0);}
  1367.                                         }else{
  1368.                                             if($this->debug>1){error_log('New LP - Prerequisite '.$prereqs_string.' complete',0);}
  1369.                                         }
  1370.                                         return $returnstatus;
  1371.                                     }
  1372.                                 }else{
  1373.                                     if($this->debug>1){error_log('New LP - Could not find '.$prereqs_string.' in '.print_r($refs_list,true),0);}
  1374.                                 }
  1375.                             }
  1376.                         }
  1377.                     }
  1378.                 }
  1379.             }
  1380.         }else{
  1381.             $list split("\|",$prereqs_string);
  1382.             if(count($list)>1){
  1383.                 if($this->debug>1){error_log('New LP - Found OR, looking into it',0);}
  1384.                 $orstatus false;
  1385.                 foreach($list as $condition){
  1386.                     if($this->debug>1){error_log('New LP - Found OR, adding it ('.$condition.')',0);}
  1387.                     $orstatus $orstatus || $this->parse_prereq($condition,$items,$refs_list,$user_id);
  1388.                     if($orstatus == true){
  1389.                         //shortcircuit OR
  1390.                         if($this->debug>1){error_log('New LP - One condition in OR was true, short-circuit',0);}
  1391.                         break;
  1392.                     }
  1393.                 }
  1394.                 if(!$orstatus && empty($this->prereq_alert)){
  1395.                     $this->prereq_alert = get_lang('_prereq_not_complete');
  1396.                 }
  1397.                 return $orstatus;
  1398.             }else{
  1399.                 if($this->debug>1){error_log('New LP - OR was found but only one elem present !?',0);}
  1400.                 if(isset($items[$refs_list[$list[0]]])){
  1401.                     $status $items[$refs_list[$list[0]]]->get_status(true);
  1402.                     $returnstatus (($status == 'completed'OR ($status == 'passed'));
  1403.                     if(!$returnstatus && empty($this->prereq_alert)){
  1404.                         $this->prereq_alert = get_lang('_prereq_not_complete');
  1405.                     }
  1406.                     return $returnstatus;
  1407.                 }
  1408.             }
  1409.         }
  1410.         if(empty($this->prereq_alert)){
  1411.             $this->prereq_alert = get_lang('_prereq_not_complete');
  1412.         }
  1413.         if($this->debug>1){error_log('New LP - End of parse_prereq. Error code is now '.$this->prereq_alert,0);}
  1414.         return false;
  1415.     }
  1416.     /**
  1417.      * Parses the HTML attributes given as string.
  1418.      * 
  1419.      * @param    string  HTML attribute string
  1420.      * @param     array     List of attributes that we want to get back
  1421.      * @return   array   An associative array of attributes
  1422.      * @author Based on a function from the HTML_Common2 PEAR module
  1423.      */
  1424.     function parse_HTML_attributes($attrString,$wanted=array())
  1425.     {
  1426.         $attributes array();
  1427.         $regs array();
  1428.         $reduced false;
  1429.         if(count($wanted)>0)
  1430.         {
  1431.             $reduced true;
  1432.         }
  1433.         try {
  1434.             
  1435.            //Find all occurences of something that looks like a URL
  1436.            // The structure of this regexp is:
  1437.            // (find protocol) then 
  1438.            // (optionally find some kind of space 1 or more times) then
  1439.            // find (either an equal sign or a bracket) followed by an optional space
  1440.            // followed by some text without quotes (between quotes itself or not)
  1441.            // then possible closing brackets if we were in the opening bracket case
  1442.            // OR something like @import() 
  1443.             $res preg_match_all(
  1444.                 '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]*))' .
  1445. //                '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]|[^\x00-\x7F])*)' . -> seems to be taking too much
  1446. //                '/(((([A-Za-z_:])([^\x00-\x7F])*)' . -> takes only last letter of parameter name 
  1447.                 '([ \n\t\r]+)?(' .
  1448. //                  '(=([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+))' . -> doesn't restrict close enough to the url itself
  1449.                   '(=([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+))' .
  1450.                   '|' .
  1451. //                  '(\(([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)\))' . -> doesn't restrict close enough to the url itself
  1452.                   '(\(([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+)\))' .
  1453.                 '))' .
  1454.                 '|' .
  1455. //                '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))?/', -> takes a lot (like 100's of thousands of empty possibilities) 
  1456.                 '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))/'
  1457.                 $attrString
  1458.                 $regs
  1459.            );
  1460.  
  1461.         catch (Exception $e{
  1462.             error_log('Caught exception: '$e->getMessage(),0;
  1463.         }
  1464.         if ($res{
  1465.             for ($i 0$i count($regs[1])$i++{
  1466.                 $name  trim($regs[3][$i]);
  1467.                 $check trim($regs[0][$i]);
  1468.                 $value trim($regs[10][$i]);
  1469.                 if(empty($valueand !empty($regs[13][$i]))
  1470.                 {
  1471.                     $value $regs[13][$i];
  1472.                 }
  1473.                 if(empty($name&& !empty($regs[16][$i]))
  1474.                 {
  1475.                     $name '@import';
  1476.                     $value trim($regs[16][$i]);
  1477.                 }
  1478.                 if(!empty($name))
  1479.                 {     
  1480.                     if(!$reduced OR in_array(strtolower($name),$wanted))
  1481.                     {
  1482.                         if ($name == $check{
  1483.                             $attributes[strtolower($name)][strtolower($name);
  1484.                         else {
  1485.                             if (!empty($value&& ($value[0== '\'' || $value[0== '"')) {
  1486.                                 $value substr($value1-1);
  1487.                             }
  1488.                             $attributes[strtolower($name)][$value;
  1489.                         }
  1490.                     }
  1491.                 }
  1492.             }
  1493.         }else{
  1494.             error_log('preg_match did not find anything',0);
  1495.         }
  1496.         return $attributes;
  1497.     }
  1498.     /**
  1499.      * Reinits all local values as the learnpath is restarted
  1500.      * @return    boolean    True on success, false otherwise
  1501.      */
  1502.     function restart()
  1503.     {
  1504.         if($this->debug>0){error_log('New LP - In learnpathItem::restart()',0);}
  1505.         $this->save();
  1506.         $allowed $this->is_restart_allowed();
  1507.         if($allowed === -1){
  1508.             //nothing allowed, do nothing
  1509.         }elseif($allowed === 1){
  1510.             //restart as new attempt is allowed, record a new attempt
  1511.             $this->attempt_id = $this->attempt_id + 1//simply reuse the previous attempt_id
  1512.             $this->current_score = 0;
  1513.             $this->current_start_time = 0;
  1514.             $this->current_stop_time = 0;
  1515.             $this->current_data = '';
  1516.             $this->status = $this->possible_status[0];
  1517.             $this->interactions_count = 0;
  1518.             $this->interactions = array();
  1519.             $this->objectives_count = 0;
  1520.             $this->objectives = array();
  1521.             $this->lesson_location = '';
  1522.             $this->write_to_db();
  1523.         }else
  1524.             //restart current element is allowed (because it's not finished yet), 
  1525.             // reinit current
  1526.             $this->current_score = 0;
  1527.             $this->current_start_time = 0;
  1528.             $this->current_stop_time = 0;
  1529.             $this->current_data = '';
  1530.             $this->status = $this->possible_status[0];            
  1531.         }
  1532.         return true;
  1533.     }
  1534.     /**
  1535.      * Saves data in the database
  1536.      * @param    boolean    Save from URL params (1) or from object attributes (0)
  1537.      * @param    boolean    The results of a check on prerequisites for this item. True if prerequisites are completed, false otherwise. Defaults to false. Only used if not sco or au
  1538.      * @return    boolean    True on success, false on failure
  1539.      */
  1540.     function save($from_outside=true,$prereqs_complete=false)
  1541.     {
  1542.         if($this->debug>0){error_log('New LP - In learnpathItem::save()',0);}
  1543.  
  1544.         //$item_view_table = Database::get_course_table(COURSEID,LEARNPATH_ITEM_VIEW_TABLE);
  1545.          $item_id $this->get_id();
  1546.          //first check if parameters passed via GET can be saved here
  1547.          //in case it's a SCORM, we should get:
  1548.         if($this->type == 'sco' || $this->type== 'au'){
  1549.             $s $this->get_status(true);
  1550.             if($this->prevent_reinit == AND
  1551.                 $s != $this->possible_status[0AND $s != $this->possible_status[1]){
  1552.                 if($this->debug>1){error_log('New LP - In learnpathItem::save() - save reinit blocked by setting',0);}
  1553.                 //do nothing because the status has already been set. Don't allow it to change.
  1554.                 //TODO check there isn't a special circumstance where this should be saved
  1555.             }else{
  1556.               if($this->debug>1){error_log('New LP - In learnpathItem::save() - SCORM save request received',0);}
  1557.               //get all new settings from the URL
  1558.                 if($from_outside==true){
  1559.                   if($this->debug>1){error_log('New LP - In learnpathItem::save() - Getting item data from outside',0);}
  1560.                    foreach($_GET as $param => $value)
  1561.                    {
  1562.                      $value Database::escape_string($value);
  1563.                      switch($param){
  1564.                          case 'score':
  1565.                                $this->set_score($value);
  1566.                                if($this->debug>2){error_log('New LP - In learnpathItem::save() - setting score to '.$value,0);}
  1567.                              break;
  1568.                          case 'max':
  1569.                              $this->set_max_score($value);
  1570.                                if($this->debug>2){error_log('New LP - In learnpathItem::save() - setting view_max_score to '.$value,0);}
  1571.                              break;
  1572.                          case 'min':
  1573.                              $this->min_score = $value;
  1574.                                if($this->debug>2){error_log('New LP - In learnpathItem::save() - setting min_score to '.$value,0);}
  1575.                              break;
  1576.                          case 'lesson_status':
  1577.                              if(!empty($value)){
  1578.                                  $this->set_status($value)
  1579.                                    if($this->debug>2){error_log('New LP - In learnpathItem::save() - setting status to '.$value,0);}
  1580.                              }
  1581.                              break;
  1582.                          case 'time':
  1583.                              $this->set_time($value);
  1584.                                if($this->debug>2){error_log('New LP - In learnpathItem::save() - setting time to '.$value,0);}
  1585.                              break;
  1586.                          case 'suspend_data':
  1587.                              $this->current_data = $value;
  1588.                              if($this->debug>2){error_log('New LP - In learnpathItem::save() - setting suspend_data to '.$value,0);}
  1589.                              break;
  1590.                          case 'lesson_location':
  1591.                              $this->set_lesson_location($value);
  1592.                              if($this->debug>2){error_log('New LP - In learnpathItem::save() - setting lesson_location to '.$value,0);}
  1593.                              break;
  1594.                          case 'core_exit':
  1595.                              $this->set_core_exit($value);
  1596.                              if($this->debug>2){error_log('New LP - In learnpathItem::save() - setting core_exit to '.$value,0);}
  1597.                              break;
  1598.                          case 'interactions':
  1599.                              //$interactions = unserialize($value);
  1600.                              //foreach($interactions as $interaction){
  1601.                              //    ;
  1602.                              //}
  1603.                              break;
  1604.                          case 'objectives':
  1605.                              break;
  1606.                          //case 'maxtimeallowed':
  1607.                          //    $this->set_max_time_allowed($value);
  1608.                          //    break;
  1609.                          /*
  1610.                          case 'objectives._count':
  1611.                              $this->attempt_id = $value;
  1612.                              break;
  1613.                          */
  1614.                          default:
  1615.                              //ignore
  1616.                              break;
  1617.                      }
  1618.                    }
  1619.                 }else{
  1620.                     if($this->debug>1){error_log('New LP - In learnpathItem::save() - Using inside item status',0);}
  1621.                     //do nothing, just let the local attributes be used
  1622.                 }
  1623.             }
  1624.         }else//if not SCO, such messages should not be expected
  1625.             $type strtolower($this->type);
  1626.             switch($type){
  1627.                 case 'asset':
  1628.                      if($prereqs_complete)
  1629.                      {
  1630.                          $this->set_status($this->possible_status[2]);
  1631.                      }
  1632.                      break;
  1633.                  case TOOL_HOTPOTATOES:
  1634.                  case TOOL_QUIZ:
  1635.                 default:
  1636.                      //for now, everything that is not sco and not asset is set to
  1637.                      //completed when saved
  1638.                      if($prereqs_complete)
  1639.                      {
  1640.                          $this->set_status($this->possible_status[2]);
  1641.                      }                 
  1642.                 break;
  1643.              }
  1644.         }
  1645.         //$time = $this->time
  1646.         if($this->debug>1){error_log('New LP - End of learnpathItem::save() - Calling write_to_db()',0);}
  1647.         return $this->write_to_db();
  1648.     }
  1649.     /**
  1650.      * Sets the number of attempt_id to a given value
  1651.      * @param    integer    The given value to set attempt_id to
  1652.      * @return    boolean    TRUE on success, FALSE otherwise
  1653.      */
  1654.     function set_attempt_id($num)
  1655.     {
  1656.         if($this->debug>0){error_log('New LP - In learnpathItem::set_attempt_id()',0);}
  1657.          if($num == strval(intval($num)) && $num>=0){
  1658.              $this->attempt_id = $num;
  1659.              return true;
  1660.          }
  1661.          return false;
  1662.     }
  1663.     /**
  1664.      * Sets the core_exit value to the one given
  1665.      */
  1666.     function set_core_exit($value)
  1667.     {
  1668.         switch($value){
  1669.             case '':
  1670.                 $this->core_exit '';
  1671.                 break;
  1672.             case 'suspend':
  1673.                 $this->core_exit 'suspend';
  1674.                 break;
  1675.             default:
  1676.                 $this->core_exit 'none';
  1677.                 break;
  1678.         }
  1679.         return true;
  1680.     }
  1681.     /**
  1682.      * Sets the item's description
  1683.      * @param    string    Description
  1684.      */
  1685.     function set_description($string=''){
  1686.         if($this->debug>0){error_log('New LP - In learnpathItem::set_description()',0);}
  1687.         if(!empty($string)){$this->description = $string;}
  1688.     }
  1689.     /**
  1690.      * Sets the lesson_location value
  1691.      * @param    string    lesson_location as provided by the SCO
  1692.      * @return    boolean    True on success, false otherwise
  1693.      */
  1694.     function set_lesson_location($location)
  1695.     {
  1696.            if($this->debug>0){error_log('New LP - In learnpathItem::set_lesson_location()',0);}
  1697.         if(isset($location)){
  1698.                $this->lesson_location = Database::escape_string($location);
  1699.               return true;
  1700.           }
  1701.          return false;
  1702.     }
  1703.     /**
  1704.      * Sets the item's depth level in the LP tree (0 is at root)
  1705.      * @param    integer    Level
  1706.      */
  1707.     function set_level($int=0){
  1708.         if($this->debug>0){error_log('New LP - In learnpathItem::set_level('.$int.')',0);}
  1709.         if(!empty($intAND $int == strval(intval($int))){$this->level = $int;}
  1710.     }
  1711.     /**
  1712.      * Sets the lp_view id this item view is registered to
  1713.      * @param    integer    lp_view DB ID
  1714.      * @todo //todo insert into lp_item_view if lp_view not exists
  1715.      */
  1716.     function set_lp_view($lp_view_id)
  1717.     {
  1718.         if($this->debug>0){error_log('New LP - In learnpathItem::set_lp_view('.$lp_view_id.')',0);}
  1719.         if(!empty($lp_view_idand $lp_view_id intval(strval($lp_view_id)))
  1720.          {
  1721.              $this->view_id = $lp_view_id;
  1722.              $item_view_table Database::get_course_table('lp_item_view');
  1723.              //get the lp_item_view with the highest view_count
  1724.              $sql "SELECT * FROM $item_view_table WHERE lp_item_id = ".$this->get_id()." " .
  1725.                      " AND lp_view_id = ".$lp_view_id." ORDER BY view_count DESC";
  1726.              if($this->debug>2){error_log('New LP - In learnpathItem::set_lp_view() - Querying lp_item_view: '.$sql,0);}
  1727.              $res api_sql_query($sql,__FILE__,__LINE__);
  1728.              if(Database::num_rows($res)>0){
  1729.                  $row Database::fetch_array($res);
  1730.                  $this->db_item_view_id  = $row['id'];
  1731.                  $this->attempt_id         = $row['view_count'];
  1732.                 $this->current_score    = $row['score'];
  1733.                 $this->current_data        = $row['suspend_data'];
  1734.                 $this->view_max_score     $row['max_score'];
  1735.                 //$this->view_min_score     = $row['min_score'];
  1736.                 $this->status            = $row['status'];
  1737.                 $this->current_start_time    = $row['start_time'];
  1738.                 $this->current_stop_time     = $this->current_start_time + $row['total_time']
  1739.                 $this->lesson_location  = $row['lesson_location'];
  1740.                 $this->core_exit        $row['core_exit'];
  1741.                  if($this->debug>2){error_log('New LP - In learnpathItem::set_lp_view() - Updated item object with database values',0);}
  1742.  
  1743.                  //now get the number of interactions for this little guy
  1744.                  $item_view_interaction_table Database::get_course_table('lp_iv_interaction');
  1745.                  $sql "SELECT * FROM $item_view_interaction_table WHERE lp_iv_id = '".$this->db_item_view_id."'"
  1746.                 $res api_sql_query($sql,__FILE__,__LINE__);
  1747.                 if($res !== false){
  1748.                     $this->interactions_count = Database::num_rows($res);
  1749.                 }else{
  1750.                     $this->interactions_count = 0;
  1751.                 }
  1752.                  //now get the number of objectives for this little guy
  1753.                  $item_view_objective_table Database::get_course_table('lp_iv_objective');
  1754.                  $sql "SELECT * FROM $item_view_objective_table WHERE lp_iv_id = '".$this->db_item_view_id."'"
  1755.                 $res api_sql_query($sql,__FILE__,__LINE__);
  1756.                 if($res !== false){
  1757.                     $this->objectives_count = Database::num_rows($res);
  1758.                 }else{
  1759.                     $this->objectives_count = 0;
  1760.                 }
  1761.              }
  1762.          }
  1763.         //end
  1764.         if($this->debug>2){error_log('New LP - End of learnpathItem::set_lp_view()',0);}
  1765.     }
  1766.     /**
  1767.      * Sets the path
  1768.      * @param    string    Path
  1769.      */
  1770.     function set_path($string=''){
  1771.         if($this->debug>0){error_log('New LP - In learnpathItem::set_path()',0);}
  1772.         if(!empty($string)){$this->path = $string;}
  1773.     }
  1774.     /**
  1775.      * Sets the prevent_reinit attribute. This is based on the LP value and is set at creation time for
  1776.      * each learnpathItem. It is a (bad?) way of avoiding a reference to the LP when saving an item.
  1777.      * @param    integer    1 for "prevent", 0 for "don't prevent" saving freshened values (new "not attempted" status etc)
  1778.      */
  1779.     function set_prevent_reinit($prevent){
  1780.         if($this->debug>0){error_log('New LP - In learnpathItem::set_prevent_reinit()',0);}
  1781.         if($prevent){
  1782.             $this->prevent_reinit = 1;
  1783.         }else{
  1784.             $this->prevent_reinit = 0;
  1785.         }
  1786.     }
  1787.     /**
  1788.      * Sets the score value. If the mastery_score is set and the score reaches
  1789.      * it, then set the status to 'passed'.
  1790.      * @param    float    Score
  1791.      * @return    boolean    True on success, false otherwise
  1792.      */
  1793.     function set_score($score)
  1794.     {
  1795.            if($this->debug>0){error_log('New LP - In learnpathItem::set_score('.$score.')',0);}
  1796.            if(($this->max_score<=|| $score <= $this->max_score&& ($score >= $this->min_score))
  1797.            {
  1798.                $this->current_score = $score;
  1799.                $master $this->get_mastery_score();
  1800.                $current_status $this->get_status(false);
  1801.                //if mastery_score is set AND the current score reaches the mastery score AND the current status is different from 'completed', then set it to 'passed'
  1802.                if($master != -&& $this->current_score >= $master && $current_status != $this->possible_status[2])
  1803.                {
  1804.                    $this->set_status($this->possible_status[3]);
  1805.                }
  1806.                elseif($master != -&& $this->current_score<$master)
  1807.                {
  1808.                    $this->set_status($this->possible_status[4]);
  1809.                }
  1810.               return true;
  1811.           }
  1812.          return false;
  1813.     }
  1814.     /**
  1815.      * Sets the maximum score for this item
  1816.      * @param    int        Maximum score - must be a decimal or an empty string
  1817.      * @return    boolean    True on success, false on error
  1818.      */
  1819.     function set_max_score($score)
  1820.     {
  1821.            if($this->debug>0){error_log('New LP - In learnpathItem::set_max_score('.$score.')',0);}
  1822.          if(is_int($scoreor $score == '')
  1823.          {
  1824.              $this->view_max_score Database::escape_string($score);
  1825.              if($this->debug>1){error_log('New LP - In learnpathItem::set_max_score() - Updated object score of item '.$this->db_id.' to '.$this->view_max_score,0);}
  1826.              return true;
  1827.          }
  1828.          return false;
  1829.     }
  1830.     /**
  1831.      * Sets the status for this item
  1832.      * @param    string    Status - must be one of the values defined in $this->possible_status
  1833.      * @return    boolean    True on success, false on error
  1834.      */
  1835.     function set_status($status)
  1836.     {
  1837.            if($this->debug>0){error_log('New LP - In learnpathItem::set_status('.$status.')',0);}
  1838.          $found false;
  1839.          foreach($this->possible_status  as $possible){
  1840.              if(preg_match('/^'.$possible.'$/i',$status)){
  1841.                  $found true;
  1842.              }
  1843.          }
  1844.          //if(in_array($status,$this->possible_status))
  1845.          if($found)
  1846.          {
  1847.              $this->status = Database::escape_string($status);
  1848.              if($this->debug>1){error_log('New LP - In learnpathItem::set_status() - Updated object status of item '.$this->db_id.' to '.$this->status,0);}
  1849.              return true;
  1850.          }
  1851.          //error_log('New LP - '.$status.' was not in the possible status',0);
  1852.          $this->status = $this->possible_status[0];
  1853.          return false;
  1854.     }
  1855.     /**
  1856.      * Sets the item viewing time in a usable form, given that SCORM packages often give it as 00:00:00.0000
  1857.      * @param    string    Time as given by SCORM
  1858.      */
  1859.     function set_time($scorm_time,$format='scorm')
  1860.     {
  1861.            if($this->debug>0){error_log('New LP - In learnpathItem::set_time('.$scorm_time.')',0);}
  1862.          if($scorm_time == and ($this->type!='sco'and $this->current_start_time!=0){
  1863.              $my_time time($this->current_start_time;
  1864.              if($my_time 0){
  1865.                  $this->update_time($my_time);
  1866.                  if($this->debug>0){error_log('New LP - In learnpathItem::set_time('.$scorm_time.') - found asset - set time to '.$my_time,0);}
  1867.              }
  1868.          }else{
  1869.              if($format == 'scorm'){
  1870.                  $res array();
  1871.                  if(preg_match('/^(\d{1,4}):(\d{2}):(\d{2})(\.\d{1,4})?/',$scorm_time,$res)){
  1872.                      $time time();
  1873.                     $hour $res[1];
  1874.                     $min $res[2];
  1875.                     $sec $res[3];
  1876.                     //getting total number of seconds spent
  1877.                      $total_sec $hour*3600 $min*60 $sec;
  1878.                      $this->update_time($total_sec);
  1879.                  }
  1880.              }elseif($format == 'int'){
  1881.                  $this->update_time($scorm_time);
  1882.              }
  1883.          }
  1884.     }
  1885.     /**
  1886.      * Sets the item's title
  1887.      * @param    string    Title
  1888.      */
  1889.     function set_title($string=''){
  1890.            if($this->debug>0){error_log('New LP - In learnpathItem::set_title()',0);}
  1891.         if(!empty($string)){$this->title = $string;}
  1892.     }
  1893.     /**
  1894.      * Sets the item's type
  1895.      * @param    string    Type
  1896.      */
  1897.     function set_type($string=''){
  1898.            if($this->debug>0){error_log('New LP - In learnpathItem::set_type()',0);}
  1899.         if(!empty($string)){$this->type = $string;}
  1900.     }
  1901.     /**
  1902.      * Checks if the current status is part of the list of status given
  1903.      * @param    strings_array    An array of status to check for. If the current status is one of the strings, return true
  1904.      * @return    boolean            True if the status was one of the given strings, false otherwise
  1905.      */
  1906.     function status_is($list=array())
  1907.     {
  1908.            if($this->debug>1){error_log('New LP - In learnpathItem::status_is('.print_r($list,true).') on item '.$this->db_id,0);}
  1909.         $mystatus $this->get_status(true);
  1910.         if(empty($mystatus)){
  1911.             return false;
  1912.         }
  1913.         $found false;
  1914.         foreach($list as $status)
  1915.         {
  1916.             if(preg_match('/^'.$status.'$/i',$mystatus))
  1917.             {
  1918.                 if($this->debug>2){error_log('New LP - learnpathItem::status_is() - Found status '.$status.' corresponding to current status',0);}
  1919.                 $found true;
  1920.                 return $found;
  1921.             }
  1922.         }
  1923.         if($this->debug>2){error_log('New LP - learnpathItem::status_is() - Status '.$mystatus.' did not match request',0);}
  1924.         return $found;
  1925.     }
  1926.     /**
  1927.      * Updates the time info according to the given session_time
  1928.      * @param    integer    Time in seconds
  1929.      *  //TODO @TODO make this method better by allowing better/multiple time slices
  1930.      */
  1931.     function update_time($total_sec=0){
  1932.            if($this->debug>0){error_log('New LP - In learnpathItem::update_time('.$total_sec.')',0);}
  1933.         if($total_sec>=0){
  1934.              //getting start time from finish time. The only problem in the calculation is it might be
  1935.              //modified by the scripts processing time
  1936.              $now time();
  1937.              $start $now-$total_sec;
  1938.             $this->current_start_time = $start;
  1939.             $this->current_stop_time  = $now;
  1940.              /*if(empty($this->current_start_time)){
  1941.                  $this->current_start_time = $start;
  1942.                  $this->current_stop_time  = $now;
  1943.              }else{
  1944.                  //if($this->current_stop_time != $this->current_start_time){
  1945.                      //if the stop time has already been set before to something else
  1946.                      //than the start time, add the given time to what's already been
  1947.                      //recorder.
  1948.                      //This is the SCORM way of doing things, because the time comes from
  1949.                      //core.session_time, not core.total_time
  1950.                  // UPDATE: adding time to previous time is only done on SCORM's finish()
  1951.                  // call, not normally, so for now ignore this section
  1952.                  //    $this->current_stop_time = $this->current_stop_time + $stop;
  1953.                  //    error_log('New LP - Adding '.$stop.' seconds - now '.$this->current_stop_time,0);
  1954.                  //}else{
  1955.                      //if no previous stop time set, use the one just calculated now from
  1956.                      //start time
  1957.                      //$this->current_start_time = $start;
  1958.                      //$this->current_stop_time  = $now;
  1959.                      //error_log('New LP - Setting '.$stop.' seconds - now '.$this->current_stop_time,0);
  1960.                  //}
  1961.              }*/
  1962.         }
  1963.     }
  1964.     /**
  1965.      * Write objectives to DB. This method is separate from write_to_db() because otherwise
  1966.      * objectives are lost as a side effect to AJAX and session concurrent access
  1967.      * @return    boolean        True or false on error
  1968.      */
  1969.     function write_objectives_to_db()
  1970.     {
  1971.            if($this->debug>0){error_log('New LP - In learnpathItem::write_objectives_to_db()',0);}
  1972.          if(is_array($this->objectives&& count($this->objectives)>0){
  1973.              //save objectives
  1974.              $tbl Database::get_course_table('lp_item_view');
  1975.              $sql "SELECT id FROM $tbl .
  1976.                      "WHERE lp_item_id = ".$this->db_id." " .
  1977.                      "AND   lp_view_id = ".$this->view_id." " .
  1978.                      "AND   view_count = ".$this->attempt_id;
  1979.              $res api_sql_query($sql,__FILE__,__LINE__);
  1980.              if(Database::num_rows($res)>0){
  1981.                  $row Database::fetch_array($res);
  1982.                  $lp_iv_id $row[0];
  1983.                  if($this->debug>2){error_log('New LP - In learnpathItem::write_to_db() - Got item_view_id '.$lp_iv_id.', now checking objectives ',0);}
  1984.                  foreach($this->objectives as $index => $objective){
  1985.                      $iva_table Database::get_course_table('lp_iv_objective');
  1986.                      $iva_sql "SELECT id FROM $iva_table .
  1987.                              "WHERE lp_iv_id = $lp_iv_id .
  1988.                              //"AND order_id = $index";
  1989.                             //also check for the objective ID as it must be unique for this SCO view
  1990.                              "AND objective_id = '".$objective[0]."'";
  1991.                      $iva_res api_sql_query($iva_sql,__FILE__,__LINE__);
  1992.                     //id(0), type(1), time(2), weighting(3),correct_responses(4),student_response(5),result(6),latency(7)
  1993.                      if(Database::num_rows($iva_res)>0){
  1994.                          //update (or don't)
  1995.                          $iva_row Database::fetch_array($iva_res);
  1996.                          $iva_id $iva_row[0];
  1997.                          $ivau_sql "UPDATE $iva_table .
  1998.                              "SET objective_id = '".$objective[0]."'," .
  1999.                              "status = '".$objective[1]."'," .
  2000.                              "score_raw = '".$objective[2]."'," .
  2001.                              "score_min = '".$objective[4]."'," .
  2002.                              "score_max = '".$objective[3]."' " .
  2003.                              "WHERE id = $iva_id";
  2004.                          $ivau_res api_sql_query($ivau_sql,__FILE__,__LINE__);
  2005.                          //error_log($ivau_sql,0);
  2006.                      }else{
  2007.                          //insert new one
  2008.                          $ivai_sql "INSERT INTO $iva_table .
  2009.                                  "(lp_iv_id, order_id, objective_id, status, score_raw, score_min, score_max )" .
  2010.                                  "VALUES" .
  2011.                                  "(".$lp_iv_id.", ".$index.",'".$objective[0]."','".$objective[1]."'," .
  2012.                                  "'".$objective[2]."','".$objective[4]."','".$objective[3]."')";
  2013.                          $ivai_res api_sql_query($ivai_sql,__FILE__,__LINE__);
  2014.                          //error_log($ivai_sql);
  2015.                      }
  2016.                  }
  2017.              }
  2018.          }
  2019.          else
  2020.          {
  2021.              //error_log('no objective to save: '.print_r($this->objectives,1));
  2022.          }
  2023.     }
  2024.     /**
  2025.      * Writes the current data to the database
  2026.      * @return    boolean    Query result
  2027.      */
  2028.      function write_to_db()
  2029.      {
  2030.            if($this->debug>0){error_log('New LP - In learnpathItem::write_to_db()',0);}
  2031.            $mode $this->get_lesson_mode();
  2032.            $credit $this->get_credit();
  2033.            if(($this->type == 'sco'&& ($credit == 'no-credit' OR $mode == 'review' OR $mode == 'browse'))
  2034.            {
  2035.                //this info shouldn't be saved as the credit or lesson mode info prevent it
  2036.                if($this->debug>1){error_log('New LP - In learnpathItem::write_to_db() - credit('.$credit.') or lesson_mode('.$mode.') prevent recording!',0);}
  2037.            }else{
  2038.           //check the row exists
  2039.              $item_view_table Database::get_course_table('lp_item_view');
  2040.              $check "SELECT * FROM $item_view_table .
  2041.                      "WHERE lp_item_id = ".$this->db_id" " .
  2042.                      "AND   lp_view_id = ".$this->view_id" ".
  2043.                      "AND   view_count = ".$this->get_attempt_id();
  2044.              if($this->debug>2){error_log('New LP - In learnpathItem::write_to_db() - Querying item_view: '.$check,0);}
  2045.              $check_res api_sql_query($check);
  2046.              //depending on what we want (really), we'll update or insert a new row
  2047.              //now save into DB
  2048.              $res 0;
  2049.              if(Database::num_rows($check_res)<1){
  2050.                  $sql "INSERT INTO $item_view_table .
  2051.                          "(total_time, " .
  2052.                          "start_time, " .
  2053.                          "score, " .
  2054.                          "status, " .
  2055.                          "max_score, ".
  2056.                          "lp_item_id, " .
  2057.                          "lp_view_id, " .
  2058.                          "view_count, " .
  2059.                          "suspend_data, " .
  2060.                          //"max_time_allowed," .
  2061.                          "lesson_location)" .
  2062.                          "VALUES" .
  2063.                          "(".$this->get_total_time()."," .
  2064.                          "".$this->current_start_time."," .
  2065.                          "".$this->get_score()."," .
  2066.                          "'".$this->get_status(false)."'," .
  2067.                          "'".$this->get_max()."'," .
  2068.                          "".$this->db_id."," .
  2069.                          "".$this->view_id."," .
  2070.                          "".$this->get_attempt_id()."," .
  2071.                          "'".Database::escape_string($this->current_data)."'," .
  2072.                          //"'".$this->get_max_time_allowed()."'," .
  2073.                          "'".$this->lesson_location."')";
  2074.                  if($this->debug>2){error_log('New LP - In learnpathItem::write_to_db() - Inserting into item_view: '.$sql,0);}
  2075.                  $res api_sql_query($sql,__FILE__,__LINE__);
  2076.                  $this->db_item_view_id = Database::get_last_insert_id();
  2077.              }else{
  2078.                  $sql '';
  2079.                  if($this->type=='hotpotatoes')
  2080.                  {    //make an exception for HotPotatoes, don't update the score
  2081.                      //because it has been saved outside of this tool
  2082.                      $sql "UPDATE $item_view_table .
  2083.                              "SET total_time = ".$this->get_total_time().", " .
  2084.                              " start_time = ".$this->get_current_start_time().", " .
  2085.                              " score = ".$this->get_score().", " .
  2086.                              " status = '".$this->get_status(false)."'," .
  2087.                              " max_score = '".$this->get_max()."'," .
  2088.                              " suspend_data = '".Database::escape_string($this->current_data)."'," .
  2089.                              " lesson_location = '".$this->lesson_location."' " .
  2090.                              "WHERE lp_item_id = ".$this->db_id." " .
  2091.                              "AND lp_view_id = ".$this->view_id." " .
  2092.                              "AND view_count = ".$this->attempt_id;
  2093.                  }
  2094.                  else
  2095.                  {    //for all other content types...
  2096.                      $sql "UPDATE $item_view_table .
  2097.                              "SET total_time = ".$this->get_total_time().", " .
  2098.                              " start_time = ".$this->get_current_start_time().", " .
  2099.                              " score = ".$this->get_score().", " .
  2100.                              " status = '".$this->get_status(false)."'," .
  2101.                              " max_score = '".$this->get_max()."'," .
  2102.                              " suspend_data = '".Database::escape_string($this->current_data)."'," .
  2103.                              //" max_time_allowed = '".$this->get_max_time_allowed()."'," .
  2104.                              " lesson_location = '".$this->lesson_location."' " .
  2105.                              "WHERE lp_item_id = ".$this->db_id." " .
  2106.                              "AND lp_view_id = ".$this->view_id." " .
  2107.                              "AND view_count = ".$this->attempt_id;
  2108.                  }
  2109.                  if($this->debug>2){error_log('New LP - In learnpathItem::write_to_db() - Updating item_view: '.$sql,0);}
  2110.                  $res api_sql_query($sql,__FILE__,__LINE__);
  2111.              }
  2112.              //if(!$res)
  2113.              //{
  2114.              //    $this->error = 'Could not update item_view table...'.mysql_error();
  2115.              //}
  2116.              if(is_array($this->interactions&& count($this->interactions)>0){
  2117.                  //save interactions
  2118.                  $tbl Database::get_course_table('lp_item_view');
  2119.                  $sql "SELECT id FROM $tbl .
  2120.                          "WHERE lp_item_id = ".$this->db_id." " .
  2121.                          "AND   lp_view_id = ".$this->view_id." " .
  2122.                          "AND   view_count = ".$this->attempt_id;
  2123.                  $res api_sql_query($sql,__FILE__,__LINE__);
  2124.                  if(Database::num_rows($res)>0){
  2125.                      $row Database::fetch_array($res);
  2126.                      $lp_iv_id $row[0];
  2127.                      if($this->debug>2){error_log('New LP - In learnpathItem::write_to_db() - Got item_view_id '.$lp_iv_id.', now checking interactions ',0);}
  2128.                      foreach($this->interactions as $index => $interaction){
  2129.                          $correct_resp '';
  2130.                          if(is_array($interaction[4]&& !empty($interaction[4][0]) ){
  2131.                              foreach($interaction[4as $resp){
  2132.                                  $correct_resp .= $resp.',';
  2133.                              }
  2134.                              $correct_resp substr($correct_resp,0,strlen($correct_resp)-1);
  2135.                          }
  2136.                          $iva_table Database::get_course_table('lp_iv_interaction');
  2137.                          $iva_sql "SELECT id FROM $iva_table .
  2138.                                  "WHERE lp_iv_id = $lp_iv_id .
  2139. //                                 "AND order_id = $index";
  2140.                                 //also check for the interaction ID as it must be unique for this SCO view
  2141.                                  "AND (order_id = $index .
  2142.                                  "OR interaction_id = '".$interaction[0]."')";
  2143.                          $iva_res api_sql_query($iva_sql,__FILE__,__LINE__);
  2144.                         //id(0), type(1), time(2), weighting(3),correct_responses(4),student_response(5),result(6),latency(7)
  2145.                          if(Database::num_rows($iva_res)>0){
  2146.                              //update (or don't)
  2147.                              $iva_row Database::fetch_array($iva_res);
  2148.                              $iva_id $iva_row[0];
  2149.                              $ivau_sql "UPDATE $iva_table .
  2150.                                  "SET interaction_id = '".$interaction[0]."'," .
  2151.                                  "interaction_type = '".$interaction[1]."'," .
  2152.                                  "weighting = '".$interaction[3]."'," .
  2153.                                  "completion_time = '".$interaction[2]."'," .
  2154.                                  "correct_responses = '".$correct_resp."'," .
  2155.                                  "student_response = '".$interaction[5]."'," .
  2156.                                  "result = '".$interaction[6]."'," .
  2157.                                  "latency = '".$interaction[7]."'" .
  2158.                                  "WHERE id = $iva_id";
  2159.                              $ivau_res api_sql_query($ivau_sql,__FILE__,__LINE__);
  2160.                          }else{
  2161.                              //insert new one
  2162.                              $ivai_sql "INSERT INTO $iva_table .
  2163.                                      "(order_id, lp_iv_id, interaction_id, interaction_type, " .
  2164.                                      "weighting, completion_time, correct_responses, " .
  2165.                                      "student_response, result, latency)" .
  2166.                                      "VALUES" .
  2167.                                      "(".$index.",".$lp_iv_id.",'".$interaction[0]."','".$interaction[1]."'," .
  2168.                                      "'".$interaction[3]."','".$interaction[2]."','".$correct_resp."'," .
  2169.                                      "'".$interaction[5]."','".$interaction[6]."','".$interaction[7]."'" .
  2170.                                      ")";
  2171.                              $ivai_res api_sql_query($ivai_sql,__FILE__,__LINE__);
  2172.                          }
  2173.                      }
  2174.                  }
  2175.              }
  2176.            }
  2177.         if($this->debug>2){error_log('New LP - End of learnpathItem::write_to_db()',0);}
  2178.          return true;
  2179.      }
  2180. }
  2181. ?>

Documentation generated on Thu, 12 Jun 2008 13:58:13 -0500 by phpDocumentor 1.4.1