1<?php
2/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4include_once "./Services/Xml/classes/class.ilXmlWriter.php";
5include_once "./Modules/Exercise/classes/class.ilExAssignment.php";
6
7/**
8 * XML writer class
9 *
10 * Class to simplify manual writing of xml documents.
11 * It only supports writing xml sequentially, because the xml document
12 * is saved in a string with no additional structure information.
13 * The author is responsible for well-formedness and validity
14 * of the xml document.
15 *
16 * @author Roland Küstermann <Roland@kuestermann.com>
17 * @version $Id: class.ilExerciseXMLWriter.php,v 1.3 2005/11/04 12:50:24 smeyer Exp $
18 *
19 * @ingroup ModulesExercise
20 */
21class ilExerciseXMLWriter extends ilXmlWriter
22{
23    public static $CONTENT_ATTACH_NO = 0;
24    public static $CONTENT_ATTACH_ENCODED = 1;
25    public static $CONTENT_ATTACH_ZLIB_ENCODED = 2;
26    public static $CONTENT_ATTACH_GZIP_ENCODED = 3;
27
28    public static $STATUS_NOT_GRADED = "NOT_GRADED";
29    public static $STATUS_PASSED = "PASSED";
30    public static $STATUS_FAILED = "FAILED";
31    /**
32     * if true, file contents will be attached as base64
33     *
34     * @var boolean
35     */
36    public $attachFileContents;
37
38    /**
39     * if true, members will be attach to xml
40     *
41     * @var boolean
42     */
43    public $attachMembers;
44
45    /**
46     * Exercise Object
47     *
48     * @var ilObjExercise
49     */
50    public $exercise;
51
52    /**
53     * constructor
54     * @param	string	xml version
55     * @param	string	output encoding
56     * @param	string	input encoding
57     * @access	public
58     */
59    public function __construct()
60    {
61        // @todo: needs to be revised for multiple assignments per exercise
62        //die ("Needs revision for ILIAS 4.1");
63        parent::__construct();
64        $this->attachFileContents = ilExerciseXMLWriter::$CONTENT_ATTACH_NO;
65    }
66
67    /**
68     *
69     * set exercise object
70     * @param ilObjExercise $exercise
71     */
72
73    public function setExercise($exercise)
74    {
75        $this->exercise = $exercise;
76    }
77
78    /**
79     * set attachment content mode
80     *
81     * @param int $attachFileContents
82     * @throws  ilExerciseException if mode is not supported
83     */
84    public function setAttachFileContents($attachFileContents)
85    {
86        if ($attachFileContents == ilExerciseXMLWriter::$CONTENT_ATTACH_GZIP_ENCODED && !function_exists("gzencode")) {
87            throw new ilExerciseException("Inflating with gzip is not supported", ilExerciseException::$ID_DEFLATE_METHOD_MISMATCH);
88        }
89        if ($attachFileContents == ilExerciseXMLWriter::$CONTENT_ATTACH_ZLIB_ENCODED && !function_exists("gzcompress")) {
90            throw new ilExerciseException("Inflating with zlib (compress/uncompress) is not supported", ilExerciseException::$ID_DEFLATE_METHOD_MISMATCH);
91        }
92
93        $this->attachFileContents = $attachFileContents;
94    }
95
96    public function start()
97    {
98        $this->__buildHeader();
99
100        $attribs = array("obj_id" => "il_" . IL_INST_ID . "_exc_" . $this->exercise->getId() );
101
102        if ($this->exercise->getOwner()) {
103            $attribs ["owner"] = "il_" . IL_INST_ID . "_usr_" . $this->exercise->getOwner();
104        }
105
106        $this->xmlStartTag("Exercise", $attribs);
107
108        //todo: create new dtd for new assignment structure
109        $this->xmlElement("Title", null, $this->exercise->getTitle());
110        $this->xmlElement("Description", null, $this->exercise->getDescription());
111        //$this->xmlElement("Instruction",  null,$this->exercise->getInstruction());
112        //$this->xmlElement("DueDate",  null,$this->exercise->getTimestamp());
113
114
115        //todo: as a workaround use first assignment for compatibility with old exercise dtd
116        $assignments = ilExAssignment::getAssignmentDataOfExercise($this->exercise->getId());
117
118        if (count($assignments) > 0) {
119            foreach ($assignments as $assignment) {
120                $this->xmlStartTag("Assignment");
121                $this->xmlElement("Instruction", null, $assignment ["instruction"]);
122                $this->xmlElement("DueDate", null, $assignment ["deadline"]);
123
124                $this->handleAssignmentFiles($this->exercise->getId(), $assignment ["id"]);
125                if ($this->attachMembers) {
126                    $this->handleAssignmentMembers($this->exercise->getId(), $assignment ["id"]);
127                }
128                $this->xmlEndTag("Assignment");
129            }
130        }
131
132
133        $this->xmlEndTag("Exercise");
134        $this->__buildFooter();
135
136        return true;
137    }
138
139    public function getXML()
140    {
141        return $this->xmlDumpMem(false);
142    }
143
144    public function __buildHeader()
145    {
146        $this->xmlSetDtdDef("<!DOCTYPE Exercise PUBLIC \"-//ILIAS//DTD ExerciseAdministration//EN\" \"" . ILIAS_HTTP_PATH . "/xml/ilias_exercise_4_4.dtd\">");
147        $this->xmlSetGenCmt("Exercise Object");
148        $this->xmlHeader();
149
150        return true;
151    }
152
153    public function __buildFooter()
154    {
155    }
156
157    /**
158     * write access to property attchMarkings
159     *
160     * @param boolean $value
161     */
162    public function setAttachMembers($value)
163    {
164        $this->attachMembers = $value ? true : false;
165    }
166
167    /**
168     * attach marking tag to member for given assignment
169     *
170     * @param int $user_id
171     * @param int $assignment_id
172     */
173    private function attachMarking($user_id, $assignment_id)
174    {
175        $ass = new ilExAssignment($assignment_id);
176
177        $amark = $ass->getMemberStatus($user_id)->getMark();
178        $astatus = $ass->getMemberStatus($user_id)->getStatus();
179        $acomment = $ass->getMemberStatus($user_id)->getComment();
180        $anotice = $ass->getMemberStatus($user_id)->getNotice();
181
182
183        if ($astatus == "notgraded") {
184            $status = ilExerciseXMLWriter::$STATUS_NOT_GRADED;
185        } elseif ($astatus == "failed") {
186            $status = ilExerciseXMLWriter::$STATUS_FAILED;
187        } else {
188            $status = ilExerciseXMLWriter::$STATUS_PASSED;
189        }
190
191        $this->xmlStartTag("Marking", array("status" => $status ));
192        $this->xmlElement("Mark", null, $amark);
193        $this->xmlElement("Notice", null, $anotice);
194        $this->xmlElement("Comment", null, $acomment);
195        $this->xmlEndTag("Marking");
196    }
197
198    private function handleAssignmentFiles($ex_id, $as_id)
199    {
200        $this->xmlStartTag("Files");
201        include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
202        $storage = new ilFSStorageExercise($ex_id, $as_id);
203        $files = $storage->getFiles();
204
205        if (count($files)) {
206            foreach ($files as $file) {
207                $this->xmlStartTag("File", array("size" => $file ["size"] ));
208                $this->xmlElement("Filename", null, $file ["name"]);
209                if ($this->attachFileContents) {
210                    $filename = $file ["fullpath"];
211                    if (@is_file($filename)) {
212                        $content = @file_get_contents($filename);
213                        $attribs = array("mode" => "PLAIN" );
214                        if ($this->attachFileContents == ilExerciseXMLWriter::$CONTENT_ATTACH_ZLIB_ENCODED) {
215                            $attribs = array("mode" => "ZLIB" );
216                            $content = gzcompress($content, 9);
217                        } elseif ($this->attachFileContents == ilExerciseXMLWriter::$CONTENT_ATTACH_GZIP_ENCODED) {
218                            $attribs = array("mode" => "GZIP" );
219                            $content = gzencode($content, 9);
220                        }
221                        $content = base64_encode($content);
222                        $this->xmlElement("Content", $attribs, $content);
223                    }
224                }
225                $this->xmlEndTag("File");
226            }
227        }
228        $this->xmlEndTag("Files");
229    }
230
231    /**
232     * create xml for files per assignment
233     *
234     * @param integer $ex_id exercise id
235     * @param array $assignments assignment id
236     */
237    private function handleAssignmentMembers($ex_id, $assignment_id)
238    {
239        $this->xmlStartTag("Members");
240        include_once("./Modules/Exercise/classes/class.ilExerciseMembers.php");
241        $members = ilExerciseMembers::_getMembers($ex_id);
242        if (count($members)) {
243            foreach ($members as $member_id) {
244                $this->xmlStartTag("Member", array("usr_id" => "il_" . IL_INST_ID . "_usr_" . $member_id  ));
245
246                $name = ilObjUser::_lookupName($member_id);
247
248                $this->xmlElement("Firstname", array(), $name['firstname']);
249                $this->xmlElement("Lastname", array(), $name['lastname']);
250                $this->xmlElement("Login", array(), $name['login']);
251                $this->attachMarking($member_id, $assignment_id);
252                $this->xmlEndTag("Member");
253            }
254        }
255        $this->xmlEndTag("Members");
256    }
257}
258