Index: openacs-4/packages/imsld/imsld.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/imsld/imsld.info,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/imsld/imsld.info 26 Jul 2005 08:05:35 -0000 1.1 @@ -0,0 +1,24 @@ + + + + + Imsld + Imslds + f + f + + + Jose Pablo Escobedo Del Cid + IMS LD integration with dotLRN. + 2005-07-07 + This package is the implementation of IMS LD in dotLRN. The course admin can create a sequence of activities for the students, as well as decide who does what, when and using what resources. + + + + + + + + + + Index: openacs-4/packages/imsld/tcl/imsld-parse-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/imsld/tcl/imsld-parse-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/imsld/tcl/imsld-parse-procs.tcl 26 Jul 2005 08:05:35 -0000 1.1 @@ -0,0 +1,682 @@ +# /packages/imsld/tcl/imsld-parse-procs.tcl + +ad_library { + Procedures in the imsld namespace for parsing xml files. + + @creation-date Jul 2005 + @author jopez@inv.it.uc3m.es + @cvs-id $Id: imsld-parse-procs.tcl,v 1.1 2005/07/26 08:05:35 josee Exp $ +} + +namespace eval imsld {} +namespace eval imsld::parse {} + +ad_proc -public imsld::parse::find_manifest { + -dir + -file_name +} { + Taken from the one with the same name in the LORS package. + Find the manifest file (or other file) that contains + the ims ld. + if it finds it, then it returns the file location. Otherwise it + returns 0 + + @param tmp_dir Temporary directory where the course is located + @param file Manifest file +} { + if { [file exist $dir/$file_name] } { + return "$dir/$file_name" + } else { + return 0 + } +} + +ad_proc -public imsld::parse::is_imsld { + -tree:required +} { + Checks it the given tree has the IMS LD extension and if the IMS LD comes in the organization. + + Returns a list (pair of values): 1 + OK if succeeded, 0 + error message otherwise. + + @param tree XML tree to analyze. +} { + + # Check the manifest attribute + set man_attribute [$tree hasAttribute xmlns:imsld] + + # Check manifest organizations + set organizations [$tree child all organizations] + + if { [llength $organizations] == 1 } { + + set imsld [$organizations child all imsld:learning-design] + + if { [llength $imsld] > 1 } { + # There are more than one imsld in the organization, not supported + return [list 0 "<#_ The manifest has more than one imsld:learning design. Right now this is not supported, sorry. #>"] + } + + } else { + # There are more than one organizations, or there is none. None of those cases supported, aborting + return [list 0 "<#_ The manifest doesn't contain any organizations or there are more than one. None of those cases are supported in this version, sorry. #>"] + } + + # After validating the cases above, we can say that this seems a well formed IMS LD + return [list 1 "<#_ OK #>"] +} + +ad_proc -public imsld::parse::expand_file { + -upload_file:required + -tmpfile:required + {-dest_dir_base "imsld"} +} { + Taken from the one with the same name in the LORS package. + Extracts the contents of the file and puts them in the folder + indicated by dest_dir. If empty, it will generate a tmp_dir for the extraction. + + Returns the name of the directory where the files where extracted. + + @param upload_file Path of the file to be extracted + @param tmpfile Temporary file name + @option dest_dir_base Destination directory where the files will be extracted +} { + + # Generate a random directory name + if { [catch {set tmp_dir [file join [file dirname $tmpfile] [ns_mktemp "$dest_dir_base-XXXXXX"]]} errmsg] } { + form set_error upload_file_form upload_file "<#_ There was an error generating the tmp_dir to unzip the file. #> $errmsg" + return -code error "IMSLD::imsld::parse::expand_file: Error generating tmp directory: $errmsg" + } + + # Create a temporary directory + if { [catch {file mkdir $tmp_dir} errmsg] } { + form set_error upload_file_form upload_file "<#_ There was an error creating the tmp_dir to unzip the file. #> $errmsg" + return -code error "IMSLD::imsld::parse::expand_file: Error creating tmp directory: $errmsg" + } + + set upload_file [string trim [string tolower $upload_file]] + + if {[regexp {(.tar.gz|.tgz)$} $upload_file]} { + set type tgz + } elseif {[regexp {.tar.z$} $upload_file]} { + set type tgZ + } elseif {[regexp {.tar$} $upload_file]} { + set type tar + } elseif {[regexp {(.tar.bz2|.tbz2)$} $upload_file]} { + set type tbz2 + } elseif {[regexp {.zip$} $upload_file]} { + set type zip + } else { + set type "<#_ Uknown type #>" + } + + switch $type { + tar { + set error_p [catch {exec tar --directory $tmp_dir -xvf $tmpfile} errmsg] + } + tgZ { + set error_p [catch {exec tar --directory $tmp_dir -xZvf $tmpfile} errmsg] + } + tgz { + set error_p [catch {exec tar --directory $tmp_dir -xzvf $tmpfile} errmsg] + } + tbz2 { + set error_p [catch {exec tar --directory $tmp_dir -xjvf $tmpfile} errmsg] + } + zip { + set error_p [catch {exec unzip -d $tmp_dir $tmpfile} errmsg] + + ## According to man unzip: + # unzip exit status: + # + # 0 normal; no errors or warnings + # detected. + + # 1 one or more warning errors were encountered, but process- + # ing completed successfully anyway. This includes zip- + # files where one or more files was skipped due to unsup- + # ported compression method or encryption with an unknown + # password. + + # Therefor it if it is 1, then it concluded successfully + # but with warnings, so we switch it back to 0 + + if { $error_p == 1 } { + set error_p 0 + } + } + default { + set error_p 1 + set errmsg "<#_ Could not determine whit what program uncompress the file $upload_file has. Aborting #>" + } + } + + if { $error_p } { + imsld::parse::remove_dir -dir $tmp_dir + ns_log Notice "IMSLD::imsld::parse::expand_file: extract type $type failed $errmsg" + return -code error "IMSLD::imsld::parse::expand_file: extract type $type failed $errmsg" + } + return $tmp_dir +} + +ad_proc -public imsld::parse::get_title { + -tree +} { + Gets the title of the given doc. If the title is not found (because it's optional), the identifier (which is mandatory) is returned. + + @param doc XML document to analyze. +} { + set title_list [$tree child all title] + if { [llength $title_list] } { + return [imsld::parse::get_element -tree $title_list]] + } else { + return [imsld::parse::get_attribute -tree $tree -attr_name identifier] + } +} + +ad_proc -public imsld::parse::get_element { + -tree + {-attr_name ""} +} { + Taken from the one with the same name in the LORS package. + Datatype Element extractor + + @param tree Node + @param att Attribute + +} { + if { ![empty_string_p $attr_name] } { + return [list "{[$tree text]} {[imsld::parse::get_attribute -tree $tree -attr_name $attr_name]}"] + } else { + return [list [$tree text]] + } +} + +ad_proc -public imsld::parse::get_attribute { + -tree + -attr_name +} { + Taken from the one with the same name in the LORS package. + Gets attributes for an specific element. Returns the attribute value if fond, emtpy string otherwise + + @param tree Document + @param attr_name Attribute we want to fetch +} { + if { [$tree hasAttribute $attr_name] == 1 } { + $tree getAttribute $attr_name + } else { + return "" + } +} + +ad_proc -public imsld::parse::validate_multiplicity { + -tree + -multiplicity + -element_name + -equal:boolean + -greather_than:boolean + -lower_than:boolean +} { + Validates the multiplicity of a given tree. It throws an error if the multiplicity is greather or equal than, lowher or equal than or not equal to the number especified in the multiplicity param. + + Only one vaidation can be done at the same time, and by default, equal is pefrormed. + + @param tree Document + @param multiplicity Number of times the element can be repeated + @param element_name Name of the element we are validating (in order to display a possible error message) + @option equal If passed, the number of roots of the tree must be equal to multiplicity + @option greather_than If passed, the number of roots of the tree must be greather or equal than multiplicity + @option lower_than If passed, the number of roots of the tree must be lower or equal than multiplicity +} { + if { [expr $equal_p + $greather_than_p + $lower_than_p] > 1 } { + return -code error "IMSLD:imsld::parse::validate_multiplicity: <#_ More than one validation tried at the same time#>" + } + if { ![expr $equal_p + $greather_than_p + $lower_than_p] } { + set equal_p 1 + } + + if { $equal_p } { + if { [llength $tree] != $multiplicity } { + ad_return_error "<#_ Error parsing file #>" "<#_ There must be exactly $multiplicity $element_name and there are [llength $tree]. This is not supported, sorry. #>" + ad_script_abort + } + } elseif { $greather_than_p } { + if { [llength $tree] < $multiplicity } { + ad_return_error "<#_ Error parsing file #>" "<#_ There can't be less than $multiplicity $element_name and there are [llength $tree]. This is not supported, sorry. #>" + ad_script_abort + } + } else { + if { [llength $tree] > $multiplicity } { + ad_return_error "<#_ Error parsing file #>" "<#_ There can't greather than $multiplicity $element_name and there are [llength $tree]. This is not supported, sorry. #>" + ad_script_abort + } + } +} + +ad_proc -public imsld::parse::remove_dir { + -dir:required +} { + Deletes the given directory. + For instance, the tmp_dir used to extract the files and parse them. + + Returns 1 when succeded, 0 otherwise + + @param dir directory to be deleted. +} { + if { [file exist $dir] } { + if { [catch {exec rm -rf $dir} errmsg] } { + return -code error "IMSLD:imsld::parse::remove_dir: <#_ There was an error trying to delete the dir $dir. #> $errmsg" + } + } + + return 1 +} + +ad_proc -public imsld::parse::tcl_boolean { + -bool:required +} { + Convets a boolean string to its corresponding boolean value 0 or 1. + + @param bool The boolean value to convert +} { + set result "" + set value [string tolower $bool] + + switch $bool { + 0 - + f - + n - + no - + false { + set result 0 + } + 1 - + t - + y - + yes - + true { + set result 1 + } + default { + set result 0 + ns_log error "Invalid option in imsld::parse::tcl_boolean - $bool" + } + } + return $result +} + +ad_proc -public imsld::parse::parse_and_create_imsld { + -xmlfile:required + -imsld_id:optional +} { + Parse a XML IMS LD file. + + Returns the new imsld_id created if there was no errors. Otherwise it returns 0. + + @param xmlfile The file to parse. This file must be compliant with the IMS LD spec + @option imsld_id The imsld_id of the new ims-ld +} { + + # Parser + # XML => DOM document + dom parse [::tDOM::xmlReadFile $xmlfile] document + + # DOM document => DOM root + $document documentElement root + set organizations [$manifest child all organizations] + + # IMS-LD + set imsld [$organizations child all imsld:learning-design] + set imsld_title [imsld::parse::get_title -tree $imsld] + set imsld_level [imsld::parse::get_attribute -tree $imsld -attr_name level] + set imsld_level [expr { [empty_string_p $imsld_level] ? "null" : [string tolower $imsld_level] }] + set imsld_version [imsld::parse::get_attribute -tree $imsld -attr_name version] + set imsld_sequence_used [imsld::parse::get_attribute -tree $imsld -attr_name sequence-used] + set imsld_sequence_p [expr { [empty_string_p $imsld_sequence_used] ? 0 : [imsld::parse::tcl_boolean -bool $imsld_sequence_used] }] + + # IMS-LD: Learning Objectives (which is an imsld_item that can have a text resource associated.) + set learning_objectives [$imsld child all imsld:learning-objectives] + imsld::parse::validate_multiplicity -tree $learning_objectives -multiplicity 1 -element_name learning-objectives -lower_than + + + # Components + set components [$imsld child all imsld:components] + imsld::parse::validate_multiplicity -tree $components -multiplicity 1 -element_name components -equal + + # Components: Roles + set roles [$components child all imsld:roles] + set learners [$roles child all imsld:learner] + set staff [$roles child all imsld:staff] + + # Componetns: Activities + set activities [$components child all imsld:activities] + if { [llength $activities] } { + set learning_activities [$activities child all imsld:learning-activity] + set support_activities [$activities child all imsld:support-activity] + set activity_structures [$activities child all imsld:activity-structure] + } + + # Method + set methods [$imsld child all imsld:method] + imsld::parse::validate_multiplicity -tree $methods -multiplicity 1 -element_name methods -equal + + # Method: Play + set plays [$methods child all imsld:play] + imsld::parse::validate_multiplicity -tree $plays -multiplicity 1 -element_name plays -equal + + # Method: Acts + set acts [$plays child all imsld:act] + imsld::parse::validate_multiplicity -tree $acts -multiplicity 0 -element_name acts -greather_than + + + + + set questestinteropNodes [$root selectNodes {/questestinterop}] + foreach questestinterop $questestinteropNodes { + # Looks for assessments + set assessmentNodes [$questestinterop selectNodes {assessment}] + if { [llength $assessmentNodes] > 0 } { + # There are assessments + foreach assessment $assessmentNodes { + set as_assessments__title [$assessment getAttribute {title} {Assessment}] + #get assessment's children: section, (qticomment, duration, qtimetadata, objectives, assessmentcontrol, + #rubric, presentation_material, outcomes_processing, assessproc_extension, assessfeedback, + #selection_ordering, reference, sectionref) + set nodesList [$assessment childNodes] + set as_assessments__definition "" + set as_assessments__instructions "" + set as_assessments__duration "" + #for each assessment's child + foreach node $nodesList { + set nodeName [$node nodeName] + #as_assessmentsx.description = or + if {$nodeName == "qticomment"} { + set definitionNodes [$assessment selectNodes {qticomment}] + if {[llength $definitionNodes] != 0} { + set definition [lindex $definitionNodes 0] + set as_assessments__definition [as::qti::mattext_gethtml $definition] + } + } elseif {$nodeName == "objectives"} { + set definitionNodes [$assessment selectNodes {objectives/material/mattext}] + if {[llength $definitionNodes] != 0} { + set definition [lindex $definitionNodes 0] + set as_assessments__definition [as::qti::mattext_gethtml $definition] + } + #as_assessments.instructions = + } elseif {$nodeName == "rubric"} { + set instructionNodes [$assessment selectNodes {rubric/material/mattext}] + if {[llength $instructionNodes] != 0} { + set instruction [lindex $instructionNodes 0] + set as_assessments__instructions [as::qti::mattext_gethtml $instruction] + } + #as_assessments.time_for_response = + } elseif {$nodeName == "duration"} { + set durationNodes [$assessment selectNodes {duration/text()}] + if {[llength $durationNodes] != 0} { + set duration [lindex $durationNodes 0] + set as_assessments__duration [$duration nodeValue] + } + } + } + set qtimetadataNodes [$assessment selectNodes {qtimetadata}] + set as_assessments__run_mode "" + set as_assessments__anonymous_p f + set as_assessments__secure_access_p f + set as_assessments__reuse_responses_p f + set as_assessments__show_item_name_p f + set as_assessments__consent_page "" + set as_assessments__return_url "" + set as_assessments__start_time "" + set as_assessments__end_time "" + set as_assessments__number_tries "" + set as_assessments__wait_between_tries "" + set as_assessments__ip_mask "" + set as_assessments__show_feedback "none" + set as_assessments__section_navigation "default path" + + set itemfeedbacknodes [$root selectNodes {/questestinterop/assessment/section/item/itemfeedback}] + if { [llength $itemfeedbacknodes] >0} { + set as_assessments__show_feedback "all" + } + set resprocessNodes [$root selectNodes {/questestinterop/assessment/section/item/resprocessing}] + set as_assessments__survey_p {f} + if { [llength $resprocessNodes] == 0 } { + set as_assessments__survey_p {t} + #if it's a survey don't show feedback + set as_assessments__show_feedback "none" + } + + if {[llength $qtimetadataNodes] > 0} { + #nodes qtimetadatafield + set qtimetadatafieldNodes [$qtimetadataNodes selectNodes {qtimetadatafield}] + foreach qtimetadatafieldnode $qtimetadatafieldNodes { + set label [$qtimetadatafieldnode selectNodes {fieldlabel/text()}] + set label [$label nodeValue] + set value [$qtimetadatafieldnode selectNodes {fieldentry/text()}] + set value [$value nodeValue] + + switch -exact -- $label { + run_mode { + set as_assessments__run_mode $value + } + anonymous_p { + set as_assessments__anonymous_p $value + } + secure_access_p { + set as_assessments__secure_access_p $value + } + reuse_responses_p { + set as_assessments__reuse_responses_p $value + } + show_item_name_p { + set as_assessments__show_item_name_p $value + } + consent_page { + set as_assessments__consent_page $value + } + start_time { + set as_assessments__start_time $value + } + end_time { + set as_assessments__end_time $value + } + number_tries { + set as_assessments__number_tries $value + } + wait_between_tries { + set as_assessments__wait_between_tries $value + } + ip_mask { + set as_assessments__ip_mask $value + } + show_feedback { + set as_assessments__show_feedback $value + } + section_navigation { + set as_assessments__section_navigation $value + } + } + + } + } + + # Insert assessment in the CR (and as_assessments table) getting the revision_id (assessment_id) + set as_assessments__assessment_id [as::assessment::new \ + -title $as_assessments__title \ + -description $as_assessments__definition \ + -instructions $as_assessments__instructions \ + -run_mode $as_assessments__run_mode \ + -anonymous_p $as_assessments__anonymous_p \ + -secure_access_p $as_assessments__secure_access_p \ + -reuse_responses_p $as_assessments__reuse_responses_p \ + -show_item_name_p $as_assessments__show_item_name_p \ + -consent_page $as_assessments__consent_page \ + -return_url $as_assessments__return_url \ + -start_time $as_assessments__start_time \ + -end_time $as_assessments__end_time \ + -number_tries $as_assessments__number_tries \ + -wait_between_tries $as_assessments__wait_between_tries \ + -time_for_response $as_assessments__duration \ + -ip_mask $as_assessments__ip_mask \ + -show_feedback $as_assessments__show_feedback \ + -section_navigation $as_assessments__section_navigation \ + -survey_p $as_assessments__survey_p ] + + # Section + set sectionNodes [$assessment selectNodes {section}] + set as_assessment_section_map__sort_order 0 + foreach section $sectionNodes { + set as_sections__title [$section getAttribute {title} {Section}] + #get section's children (qticomment, duration, qtimetadata, objectives, sectioncontrol, + #sectionprecondition, sectionpostcondition, rubric, presentation_material, outcomes_processing, + #sectionproc_extension, sectionfeedback, selection_ordering, reference, itemref, item, sectionref, + #section) + set nodesList [$section childNodes] + set as_sections__definition "" + set as_sections__instructions "" + set as_sections__duration "" + set as_sections__sectionfeedback "" + #for each section's child + foreach node $nodesList { + set nodeName [$node nodeName] + #as_sectionsx.description = or + if {$nodeName == "qticomment"} { + set definitionNodes [$section selectNodes {qticomment}] + if {[llength $definitionNodes] != 0} { + set definition [lindex $definitionNodes 0] + set as_sections__definition [as::qti::mattext_gethtml $definition] + } + } elseif {$nodeName == "objectives"} { + set definitionNodes [$section selectNodes {objectives/material/mattext}] + if {[llength $definitionNodes] != 0} { + set definition [lindex $definitionNodes 0] + set as_sections__definition [as::qti::mattext_gethtml $definition] + } + #as_sections.max_time_to_complete = + } elseif {$nodeName == "duration"} { + set section_durationNodes [$section selectNodes {duration/text()}] + if {[llength $section_durationNodes] != 0} { + set section_duration [lindex $section_durationNodes 0] + set as_sections__duration [$section_duration nodeValue] + } + #as_sections.instructions = + } elseif {$nodeName == "rubric"} { + set section_instructionNodes [$section selectNodes {rubric/material/mattext}] + if {[llength $section_instructionNodes] != 0} { + set section_instruction [lindex $section_instructionNodes 0] + set as_sections__instructions [as::qti::mattext_gethtml $section_instruction] + } + #as_sections.feedback_text = + } elseif {$nodeName == "sectionfeedback"} { + set sectionfeedbackNodes [$section selectNodes {sectionfeedback/material/mattext}] + if {[llength $sectionfeedbackNodes] != 0} { + set sectionfeedback [lindex $sectionfeedbackNodes 0] + set as_sections__sectionfeedback [as::qti::mattext_gethtml $sectionfeedback] + } + } + } + + set qtimetadataNodes [$section selectNodes {qtimetadata}] + set as_sections__num_items "" + set as_sections__points "" + set asdt__display_type none + set asdt__s_num_items "" + set asdt__adp_chunk "" + set asdt__branched_p f + set asdt__back_button_p t + set asdt__submit_answer_p f + set asdt__sort_order_type order_of_entry + + if {[llength $qtimetadataNodes] > 0} { + #nodes qtimetadatafield + set qtimetadatafieldNodes [$qtimetadataNodes selectNodes {qtimetadatafield}] + foreach qtimetadatafieldnode $qtimetadatafieldNodes { + set label [$qtimetadatafieldnode selectNodes {fieldlabel/text()}] + set label [$label nodeValue] + set value [$qtimetadatafieldnode selectNodes {fieldentry/text()}] + set value [$value nodeValue] + + switch -exact -- $label { + num_items { + set as_sections__num_items $value + } + points { + set as_sections__points $value + } + display_type { + set asdt__display_type $value + } + s_num_items { + set asdt__s_num_items $value + } + adp_chunk { + set asdt__adp_chunk $value + } + branched_p { + set asdt__branched_p $value + } + back_button_p { + set asdt__back_button_p $value + } + submit_answer_p { + set asdt__submit_answer_p $value + } + sort_order_type { + set asdt__sort_order_type $value + } + } + } + } + + #section display type + set display_type_id [as::section_display::new \ + -title $asdt__display_type \ + -num_items $asdt__s_num_items \ + -adp_chunk $asdt__adp_chunk \ + -branched_p $asdt__branched_p \ + -back_button_p $asdt__back_button_p \ + -submit_answer_p $asdt__submit_answer_p \ + -sort_order_type $asdt__sort_order_type] + # Insert section in the CR (and in the as_sections table) getting the revision_id (section_id) + set section_id [as::section::new \ + -title $as_sections__title \ + -description $as_sections__definition \ + -instructions $as_sections__instructions \ + -feedback_text $as_sections__sectionfeedback \ + -max_time_to_complete $as_sections__duration \ + -num_items $as_sections__num_items \ + -points $as_sections__points \ + -display_type_id $display_type_id] + + # Relation between as_sections and as_assessments + db_dml as_assessment_section_map_insert {} + incr as_assessment_section_map__sort_order + set as_item_section_map__sort_order 0 + # Process the items + set as_items [as::qti::parse_item $section [file dirname $xmlfile]] + # Relation between as_items and as_sections + foreach as_item_list $as_items { + array set as_item $as_item_list + set as_item_id $as_item(as_item_id) + set as_item__duration $as_item(duration) + set as_item__points $as_item(points) + db_dml as_item_section_map_insert {} + incr as_item_section_map__sort_order + } + + #get points from a section + db_0or1row get_section_points {} + #update as_assessment_section_map with section points + db_dml update_as_assessment_section_map {} + } + } + } else { + # Just items (no assessments) + as::qti::parse_item $questestinterop [file dirname $xmlfile]] + } + } + return $as_assessments__assessment_id +} + + + + Index: openacs-4/packages/imsld/www/admin/imsld-new-2.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/imsld/www/admin/imsld-new-2.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/imsld/www/admin/imsld-new-2.adp 26 Jul 2005 08:05:35 -0000 1.1 @@ -0,0 +1,13 @@ + + @page_title;noquote@ + @context;noquote@ + + + No information found in the imsmanifest.xml file. Nothing to do. + +Pleas, confirm the information you are uploading +
+ +
+ +
Index: openacs-4/packages/imsld/www/admin/imsld-new-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/imsld/www/admin/imsld-new-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/imsld/www/admin/imsld-new-2.tcl 26 Jul 2005 08:05:35 -0000 1.1 @@ -0,0 +1,121 @@ +# /packages/imsld/www/admin/imsld-new-2.tcl + +ad_page_contract { + + Pre parse the IMS LD ZIP file and requests confirmation from the user. + + @author jopez@inv.it.uc3m.es + @creation-date jul 2005 +} { + upload_file:trim + upload_file.tmpfile:tmpfile + return_url +} -properties { + upload_file + context:onevalue +} + +set package_id [ad_conn package_id] +permission::require_permission -object_id $package_id -privilege create + +set page_title "<#_ Confirm: New IMS-LD #>" +set context [list [list "<#_ New IMS-LD #>" "new-imsld"] [list "<#_ Confirm: New IMS-LD #>"]] + +set user_id [ad_conn user_id] +set imsld_id [db_nextval acs_object_id_seq] + +# expand file +set tmp_dir [imsld::parse::expand_file -upload_file $upload_file -tmpfile ${upload_file.tmpfile} -dest_dir_base imsld-${imsld_id}] + +# search for manifest file +set manifest [imsld::parse::find_manifest -dir $tmp_dir -file_name "imsmanifest.xml"] + +# see if the file actually is where it suppose to be. Othewise abort +if {$manifest == 0} { + imsld::parse::remove_dir -dir $tmp_dir + ad_return_error "<#_ No imsmanifest.xml found #>" "<#_ No imsmanifest.xml was found in the compressed file. Aborting. #>" + ad_script_abort +} + +# open the imsmanifest.xml file +dom parse [::tDOM::xmlReadFile $manifest] doc +set manifest [$doc documentElement] + +# Pair of values, success_p + explanation +set is_imsld_list [imsld::parse::is_imsld -tree $manifest] + +if { [lindex $is_imsld_list 0] } { + + multirow create imsld_info element_name info + + template::list::create \ + -name imsld_info \ + -multirow imsld_info \ + -no_data "<#_ No information found in the manifest file #>" \ + -elements { + element_name { + label "" + html {valign top style "background-color: #e0e0e0; font-weight: bold;"} + } + info { + label "" + html {valign top style "background-color: #f0f0f0; font-weight: bold;"} + } + + } + + # Get the info from the manifest + set organizations [$manifest child all organizations] + multirow append imsld_info "<#_ Number of Organizations: #>" [llength $organizations] + set imsld [$organizations child all imsld:learning-design] + multirow append imsld_info "<#_ Number of IMD LDs #>" [llength $imsld] + set imsld_title [imsld::parse::get_title -tree $imsld] + set imsld_level [imsld::parse::get_attribute -tree $imsld -attr_name level] + set imsld_level [expr { [empty_string_p $imsld_level] ? "<#_ Not defined #>" : $imsld_level }] + multirow append imsld_info "<#_ IMD LD Title #>" [llength $imsld] + multirow append imsld_info "<#_ IMD LD Level #>" "$imsld_level" + + # Components + set components [$imsld child all imsld:components] + imsld::parse::validate_multiplicity -tree $components -multiplicity 1 -element_name components -equal + + set roles [$components child all imsld:roles] + set learners [llength [$roles child all imsld:learner]] + set staff [llength [$roles child all imsld:staff]] + multirow append imsld_info "<#_ Total Roles #>" [expr $learners + $staff] + multirow append imsld_info "<#_ Learners Roles #>" $learners + multirow append imsld_info "<#_ Staff Roels #>" $staff + + set activities [$components child all imsld:activities] + if { [llength $activities] } { + set learning_activities [llength [$activities child all imsld:learning-activity]] + set support_activities [llength [$activities child all imsld:support-activity]] + set activity_structures [llength [$activities child all imsld:activity-structure]] + multirow append imsld_info "<#_ Total Activities #>" [expr $learning_activities + $support_activities + $activity_structures] + multirow append imsld_info "<#_ Learning Activities #>" $learning_activities + multirow append imsld_info "<#_ Support Activities #>" $support_activities + multirow append imsld_info "<#_ Activity Structures #>" $activity_structures + } + + # Methods + set methods [$imsld child all imsld:method] + imsld::parse::validate_multiplicity -tree $methods -multiplicity 1 -element_name methods -equal + + set plays [$methods child all imsld:play] + imsld::parse::validate_multiplicity -tree $plays -multiplicity 1 -element_name plays -equal + + set acts [$plays child all imsld:act] + imsld::parse::validate_multiplicity -tree $acts -multiplicity 0 -element_name acts -greather_than + multirow append imsld_info "<#_ Acts #>" [llength $acts] + +} else { + # Not valid (or supported?) IMS LD + ad_return_error "<#_ No IMS LD #>" "Couldn't determine if this is a well formed IMS-LD: [lindex $is_imsld_list 1]" + ad_script_abort +} + +ad_form -name imsld_upload -cancel_url $return_url -action imsld-new-3 -html { enctype multipart/form-data } -form { + imsld_id:key + + {tmp_dir:text {widget hidden} {value $tmp_dir}} +} Index: openacs-4/packages/imsld/www/admin/imsld-new-3.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/imsld/www/admin/Attic/imsld-new-3.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/imsld/www/admin/imsld-new-3.tcl 26 Jul 2005 08:05:35 -0000 1.1 @@ -0,0 +1,43 @@ +# /packages/imsld/www/admin/imsld-new-3.tcl + +ad_page_contract { + + Parse and create the imsld in the database. + + @author jopez@inv.it.uc3m.es + @creation-date jul 2005 +} { + tmp_dir + imsld_id:integer,notnull + return_url +} -properties { + context:onevalue +} + +set package_id [ad_conn package_id] +permission::require_permission -object_id $package_id -privilege create + +set page_title "<#_ Creating new IMS-LD... #>" +set context [list [list "<#_ New IMS-LD #>" "new-imsld"] [list "<#_ Creaginting new IMS-LD #>"]] + +set user_id [ad_conn user_id] + +# Display progress bar +ad_progress_bar_begin \ + -title "<#_ Uploading IMS LD #>" \ + -message_1 "<#_ Uploading and processing your course, please wait... #>" \ + -message_2 "<#_ We will continue automatically when processing is complete. #>" + + +# Atempting to create the new IMS LD. +# The proc imsld::parse::parse_and_create_imsldl return a pair of values (success_p and a message) +set create_ismld_atempt_list [imsld::parse::parse_and_create_imsld -xmlfile $tmp_dir/imsmanifest.xml -imsld_id $imsld_id] + +set success_p [lindex $create_ismld_atempt_list 0] +set message [lindex $create_ismld_atempt_list 1] + +if { $success_p } { + # Hats off! +} else { + # Error +} \ No newline at end of file Index: openacs-4/packages/imsld/www/admin/imsld-new.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/imsld/www/admin/imsld-new.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/imsld/www/admin/imsld-new.adp 26 Jul 2005 08:05:35 -0000 1.1 @@ -0,0 +1,5 @@ + + @page_title;noquote@ + @context;noquote@ + +

Index: openacs-4/packages/imsld/www/admin/imsld-new.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/imsld/www/admin/imsld-new.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/imsld/www/admin/imsld-new.tcl 26 Jul 2005 08:05:35 -0000 1.1 @@ -0,0 +1,30 @@ +ad_page_contract { + + Presents a form to upload a IMS LD ZIP file. + + @author jopez@inv.it.uc3m.es + @creation-date jul 2005 +} { + {return_url "index"} +} -properties { + upload_file + context:onevalue +} + +set package_id [ad_conn package_id] +permission::require_permission -object_id $package_id -privilege create + +set page_title "<#_ New IMS-LD #>" +set context [list "<#_ New IMS-LD #>"] + +set user_id [ad_conn user_id] + +# form to upload an IMS LD ZIP file + +ad_form -name upload_file_form -html {enctype multipart/form-data} -cancel_url $return_url -action imsld-new-2 -form { + imsld_id:key + {upload_file:file {label "<#_ IMS-LD ZIP File #>"}} + {return_url:text {widget hidden} {value $return_url}} +} + +