1<?php
2/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4
5/**
6* Class ilObjUserFolder
7*
8* @author Stefan Meyer <meyer@leifos.com>
9* @version $Id$
10*
11* @extends ilObject
12*/
13
14require_once "./Services/Object/classes/class.ilObject.php";
15
16define('USER_FOLDER_ID', 7);
17
18class ilObjUserFolder extends ilObject
19{
20    /**
21    * Constructor
22    * @access	public
23    * @param	integer	reference_id or object_id
24    * @param	boolean	treat the id as reference_id (true) or object_id (false)
25    */
26    public function __construct($a_id, $a_call_by_reference = true)
27    {
28        $this->type = "usrf";
29        parent::__construct($a_id, $a_call_by_reference);
30    }
31
32
33    /**
34    * delete userfolder and all related data
35    * DISABLED
36    * @access	public
37    * @return	boolean	true if all object data were removed; false if only a references were removed
38    */
39    public function delete()
40    {
41        // DISABLED
42        return false;
43
44        // always call parent delete function first!!
45        if (!parent::delete()) {
46            return false;
47        }
48        // put here userfolder specific stuff
49
50        // always call parent delete function at the end!!
51        return true;
52    }
53
54
55    public function getExportFilename($a_mode = "userfolder_export_excel_x86")
56    {
57        $filename = "";
58        //$settings = $this->ilias->getAllSettings();
59        //$this->inst_id = $settings["inst_id"];
60        $inst_id = IL_INST_ID;
61
62        $date = time();
63
64        switch ($a_mode) {
65            case "userfolder_export_excel_x86":
66                $filename = $date . "__" . $inst_id . "__xls_usrf";
67                break;
68            case "userfolder_export_csv":
69                $filename = $date . "__" . $inst_id . "__csv_usrf.csv";
70                break;
71            case "userfolder_export_xml":
72                $filename = $date . "__" . $inst_id . "__xml_usrf.xml";
73                break;
74        }
75        return $filename;
76    }
77
78
79    /**
80    * Get the location of the export directory for the user accounts
81    *
82    * Get the location of the export directory for the user accounts
83    *
84    * @access	public
85    */
86    public function getExportDirectory()
87    {
88        $export_dir = ilUtil::getDataDir() . "/usrf_data/export";
89
90        return $export_dir;
91    }
92
93    /**
94    * Get a list of the already exported files in the export directory
95    *
96    * Get a list of the already exported files in the export directory
97    *
98    * @return array A list of file names
99    * @access	public
100    */
101    public function getExportFiles()
102    {
103        $dir = $this->getExportDirectory();
104
105        // quit if export dir not available
106        if (!@is_dir($dir) or
107            !is_writeable($dir)) {
108            return array();
109        }
110
111        // open directory
112        $dir = dir($dir);
113
114        // initialize array
115        $file = array();
116
117        // get files and save the in the array
118        while ($entry = $dir->read()) {
119            if ($entry != "." and
120                $entry != ".." and
121                preg_match("/^[0-9]{10}_{2}[0-9]+_{2}([a-z0-9]{3})_usrf\.[a-z]{1,4}\$/", $entry, $matches)) {
122                $filearray["filename"] = $entry;
123                $filearray["filesize"] = filesize($this->getExportDirectory() . "/" . $entry);
124                array_push($file, $filearray);
125            }
126        }
127
128        // close import directory
129        $dir->close();
130
131        // sort files
132        sort($file);
133        reset($file);
134
135        return $file;
136    }
137
138    public function escapeXML($value)
139    {
140        $value = str_replace("&", "&amp;", $value);
141        $value = str_replace("<", "&lt;", $value);
142        $value = str_replace(">", "&gt;", $value);
143        return $value;
144    }
145
146    public function createXMLExport(&$settings, &$data, $filename)
147    {
148        include_once './Services/User/classes/class.ilUserDefinedData.php';
149        include_once './Services/User/classes/class.ilObjUser.php';
150
151        global $DIC;
152
153        $rbacreview = $DIC['rbacreview'];
154        global $DIC;
155
156        $ilDB = $DIC['ilDB'];
157        global $DIC;
158
159        $log = $DIC['log'];
160
161        $file = fopen($filename, "w");
162
163        if (is_array($data)) {
164            include_once './Services/User/classes/class.ilUserXMLWriter.php';
165
166            $xmlWriter = new ilUserXMLWriter();
167            $xmlWriter->setObjects($data);
168            $xmlWriter->setSettings($settings);
169            $xmlWriter->setAttachRoles(true);
170
171            if ($xmlWriter->start()) {
172                fwrite($file, $xmlWriter->getXML());
173            }
174        }
175    }
176
177
178    /**
179     * Get all exportable user defined fields
180     */
181    public function getUserDefinedExportFields()
182    {
183        include_once './Services/User/classes/class.ilUserDefinedFields.php';
184        $udf_obj = &ilUserDefinedFields::_getInstance();
185
186        $udf_ex_fields = array();
187        foreach ($udf_obj->getDefinitions() as $definition) {
188            if ($definition["export"] != false) {
189                $udf_ex_fields[] = array("name" => $definition["field_name"],
190                    "id" => $definition["field_id"]);
191            }
192        }
193
194        return $udf_ex_fields;
195    }
196
197    public function createCSVExport(&$settings, &$data, $filename)
198    {
199
200        // header
201        $headerrow = array();
202        $udf_ex_fields = $this->getUserDefinedExportFields();
203        foreach ($settings as $value) {	// standard fields
204            array_push($headerrow, $this->lng->txt($value));
205        }
206        foreach ($udf_ex_fields as $f) {	// custom fields
207            array_push($headerrow, $f["name"]);
208        }
209
210        $separator = ";";
211        $file = fopen($filename, "w");
212        $formattedrow = &ilUtil::processCSVRow($headerrow, true, $separator);
213        fwrite($file, join($separator, $formattedrow) . "\n");
214        foreach ($data as $row) {
215            $csvrow = array();
216            foreach ($settings as $header) {	// standard fields
217                // multi-text
218                if (is_array($row[$header])) {
219                    $row[$header] = implode(", ", $row[$header]);
220                }
221
222                array_push($csvrow, $row[$header]);
223            }
224
225            // custom fields
226            reset($udf_ex_fields);
227            if (count($udf_ex_fields) > 0) {
228                include_once("./Services/User/classes/class.ilUserDefinedData.php");
229                $udf = new ilUserDefinedData($row["usr_id"]);
230                foreach ($udf_ex_fields as $f) {	// custom fields
231                    array_push($csvrow, $udf->get("f_" . $f["id"]));
232                }
233            }
234
235            $formattedrow = &ilUtil::processCSVRow($csvrow, true, $separator);
236            fwrite($file, join($separator, $formattedrow) . "\n");
237        }
238        fclose($file);
239    }
240
241    public function createExcelExport(&$settings, &$data, $filename)
242    {
243        include_once "./Services/Excel/classes/class.ilExcel.php";
244        $worksheet = new ilExcel();
245        $worksheet->addSheet($this->lng->txt("users"));
246
247        $row = 1;
248        $col = 0;
249
250        $udf_ex_fields = $this->getUserDefinedExportFields();
251
252        // title row
253        foreach ($settings as $value) {	// standard fields
254            if ($value == 'ext_account') {
255                $value = 'user_ext_account';
256            }
257            $worksheet->setCell($row, $col, $this->lng->txt($value));
258            $col++;
259        }
260        foreach ($udf_ex_fields as $f) {	// custom fields
261            $worksheet->setCell($row, $col, $f["name"]);
262            $col++;
263        }
264        $worksheet->setBold("A1:" . $worksheet->getColumnCoord($col - 1) . "1");
265
266        $this->lng->loadLanguageModule("meta");
267        foreach ($data as $index => $rowdata) {
268            $row++;
269            $col = 0;
270
271            // standard fields
272            foreach ($settings as $fieldname) {
273                $value = $rowdata[$fieldname];
274                switch ($fieldname) {
275                    case "language":
276                        $worksheet->setCell($row, $col, $this->lng->txt("meta_l_" . $value));
277                        break;
278                    case "time_limit_from":
279                    case "time_limit_until":
280                        $value = $value
281                            ? new ilDateTime($value, IL_CAL_UNIX)
282                            : null;
283                        $worksheet->setCell($row, $col, $value);
284                        break;
285                    case "last_login":
286                    case "last_update":
287                    case "create_date":
288                    case "approve_date":
289                    case "agree_date":
290                        $value = $value
291                            ? new ilDateTime($value, IL_CAL_DATETIME)
292                            : null;
293                        $worksheet->setCell($row, $col, $value);
294                        break;
295
296                    case "interests_general":
297                    case "interests_help_offered":
298                    case "interests_help_looking":
299                        if (is_array($value) && sizeof($value)) {
300                            $value = implode(", ", $value);
301                        } else {
302                            $value = null;
303                        }
304                        // fallthrough
305
306                        // no break
307                    default:
308                        $worksheet->setCell($row, $col, $value);
309                        break;
310                }
311                $col++;
312            }
313
314            // custom fields
315            reset($udf_ex_fields);
316            if (count($udf_ex_fields) > 0) {
317                include_once("./Services/User/classes/class.ilUserDefinedData.php");
318                $udf = new ilUserDefinedData($rowdata["usr_id"]);
319                foreach ($udf_ex_fields as $f) {	// custom fields
320                    $worksheet->setCell($row, $col, $udf->get("f_" . $f["id"]));
321                    $col++;
322                }
323            }
324        }
325
326        $worksheet->writeToFile($filename);
327    }
328
329    /**
330     * getExport Settings
331     *
332     * @return array of exportable fields
333     */
334    public static function getExportSettings()
335    {
336        global $DIC;
337
338        $ilDB = $DIC['ilDB'];
339
340        $db_settings = array();
341
342        include_once("./Services/User/classes/class.ilUserProfile.php");
343        $up = new ilUserProfile();
344        $up->skipField("roles");
345        $profile_fields = $up->getStandardFields();
346
347        /*$profile_fields =& ilObjUserFolder::getProfileFields();
348        $profile_fields[] = "preferences";*/
349
350        $query = "SELECT * FROM settings WHERE " .
351            $ilDB->like("keyword", "text", '%usr_settings_export_%');
352        $result = $ilDB->query($query);
353        while ($row = $result->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
354            if ($row["value"] == "1") {
355                if (preg_match("/usr_settings_export_(.*)/", $row["keyword"], $setting)) {
356                    array_push($db_settings, $setting[1]);
357                }
358            }
359        }
360        $export_settings = array();
361        foreach ($profile_fields as $key => $value) {
362            if (in_array($key, $db_settings)) {
363                if (strcmp($key, "password") == 0) {
364                    // we do not support password export with ILIAS >= 4.5.x
365                    continue;
366                } else {
367                    array_push($export_settings, $key);
368                }
369            }
370        }
371        array_push($export_settings, "usr_id");
372        array_push($export_settings, "login");
373        array_push($export_settings, "last_login");
374        array_push($export_settings, "last_update");
375        array_push($export_settings, "create_date");
376        array_push($export_settings, "time_limit_owner");
377        array_push($export_settings, "time_limit_unlimited");
378        array_push($export_settings, "time_limit_from");
379        array_push($export_settings, "time_limit_until");
380        array_push($export_settings, "time_limit_message");
381        array_push($export_settings, "active");
382        array_push($export_settings, "approve_date");
383        array_push($export_settings, "agree_date");
384        array_push($export_settings, "client_ip");
385        array_push($export_settings, "auth_mode");
386        array_push($export_settings, "ext_account");
387        array_push($export_settings, "feedhash");
388        return $export_settings;
389    }
390
391    /**
392    * build xml export file
393    */
394    public function buildExportFile($a_mode = "userfolder_export_excel_x86", $user_data_filter = false)
395    {
396        global $DIC;
397
398        $ilBench = $DIC['ilBench'];
399        global $DIC;
400
401        $log = $DIC['log'];
402        global $DIC;
403
404        $ilDB = $DIC['ilDB'];
405        global $DIC;
406
407        $ilias = $DIC['ilias'];
408        global $DIC;
409
410        $lng = $DIC['lng'];
411
412        //get Log File
413        $expDir = $this->getExportDirectory();
414        //$expLog = &$log;
415        //$expLog->delete();
416        //$expLog->setLogFormat("");
417        //$expLog->write(date("[y-m-d H:i:s] ")."Start export of user data");
418
419        // create export directory if needed
420        $this->createExportDirectory();
421
422        //get data
423        //$expLog->write(date("[y-m-d H:i:s] ")."User data export: build an array of all user data entries");
424        $settings = &$this->getExportSettings();
425
426        // user languages
427        $query = "SELECT * FROM usr_pref WHERE keyword = " . $ilDB->quote('language', 'text');
428        $res = $ilDB->query($query);
429        $languages = array();
430        while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
431            $languages[$row['usr_id']] = $row['value'];
432        }
433
434        // multi-text
435        $multi = array();
436        $set = $ilDB->query("SELECT * FROM usr_data_multi");
437        while ($row = $ilDB->fetchAssoc($set)) {
438            if (!is_array($user_data_filter) ||
439                in_array($row["usr_id"], $user_data_filter)) {
440                $multi[$row["usr_id"]][$row["field_id"]][] = $row["value"];
441            }
442        }
443
444        $data = array();
445        $query = "SELECT usr_data.* FROM usr_data  " .
446            " ORDER BY usr_data.lastname, usr_data.firstname";
447        $result = $ilDB->query($query);
448        while ($row = $ilDB->fetchAssoc($result)) {
449            if (isset($languages[$row['usr_id']])) {
450                $row['language'] = $languages[$row['usr_id']];
451            } else {
452                $row['language'] = $lng->getDefaultLanguage();
453            }
454
455            if (isset($multi[$row["usr_id"]])) {
456                $row = array_merge($row, $multi[$row["usr_id"]]);
457            }
458
459            if (is_array($user_data_filter)) {
460                if (in_array($row["usr_id"], $user_data_filter)) {
461                    array_push($data, $row);
462                }
463            } else {
464                array_push($data, $row);
465            }
466        }
467        //$expLog->write(date("[y-m-d H:i:s] ")."User data export: build an array of all user data entries");
468
469        $fullname = $expDir . "/" . $this->getExportFilename($a_mode);
470        switch ($a_mode) {
471            case "userfolder_export_excel_x86":
472                $this->createExcelExport($settings, $data, $fullname);
473                break;
474            case "userfolder_export_csv":
475                $this->createCSVExport($settings, $data, $fullname);
476                break;
477            case "userfolder_export_xml":
478                $this->createXMLExport($settings, $data, $fullname);
479                break;
480        }
481        //$expLog->write(date("[y-m-d H:i:s] ")."Finished export of user data");
482
483        return $fullname;
484    }
485
486
487    /**
488    * creates data directory for export files
489    * (data_dir/usrf_data/export, depending on data
490    * directory that is set in ILIAS setup/ini)
491    */
492    public function createExportDirectory()
493    {
494        if (!@is_dir($this->getExportDirectory())) {
495            $usrf_data_dir = ilUtil::getDataDir() . "/usrf_data";
496            ilUtil::makeDir($usrf_data_dir);
497            if (!is_writable($usrf_data_dir)) {
498                $this->ilias->raiseError("Userfolder data directory (" . $usrf_data_dir
499                    . ") not writeable.", $this->ilias->error_obj->MESSAGE);
500            }
501
502            // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
503            $export_dir = $usrf_data_dir . "/export";
504            ilUtil::makeDir($export_dir);
505            if (!@is_dir($export_dir)) {
506                $this->ilias->raiseError("Creation of Userfolder Export Directory failed.", $this->ilias->error_obj->MESSAGE);
507            }
508        }
509    }
510
511
512    /**
513     * Get profile fields (DEPRECATED, use ilUserProfile() instead)
514     *
515     * @return array of fieldnames
516     */
517    public static function &getProfileFields()
518    {
519        include_once("./Services/User/classes/class.ilUserProfile.php");
520        $up = new ilUserProfile();
521        $up->skipField("username");
522        $up->skipField("roles");
523        $up->skipGroup("preferences");
524        $fds = $up->getStandardFields();
525        foreach ($fds as $k => $f) {
526            $profile_fields[] = $k;
527        }
528
529        return $profile_fields;
530    }
531
532    public static function _writeNewAccountMail($a_lang, $a_subject, $a_sal_g, $a_sal_f, $a_sal_m, $a_body)
533    {
534        global $DIC;
535
536        $ilDB = $DIC['ilDB'];
537
538        if (self::_lookupNewAccountMail($a_lang)) {
539            $values = array(
540                'subject' => array('text',$a_subject),
541                'body' => array('clob',$a_body),
542                'sal_g' => array('text',$a_sal_g),
543                'sal_f' => array('text',$a_sal_f),
544                'sal_m' => array('text',$a_sal_m)
545                );
546            $ilDB->update(
547                'mail_template',
548                $values,
549                array('lang' => array('text',$a_lang), 'type' => array('text','nacc'))
550            );
551        } else {
552            $values = array(
553                'subject' => array('text',$a_subject),
554                'body' => array('clob',$a_body),
555                'sal_g' => array('text',$a_sal_g),
556                'sal_f' => array('text',$a_sal_f),
557                'sal_m' => array('text',$a_sal_m),
558                'lang' => array('text',$a_lang),
559                'type' => array('text','nacc')
560                );
561            $ilDB->insert('mail_template', $values);
562        }
563    }
564
565    /**
566     * Update account mail attachment
567     * @param $a_lang
568     * @param $a_tmp_name
569     * @param $a_name
570     * @throws ilFileUtilsException
571     */
572    public static function _updateAccountMailAttachment($a_lang, $a_tmp_name, $a_name)
573    {
574        global $DIC;
575
576        $ilDB = $DIC['ilDB'];
577
578        include_once "Services/User/classes/class.ilFSStorageUserFolder.php";
579        $fs = new ilFSStorageUserFolder(USER_FOLDER_ID);
580        $fs->create();
581        $path = $fs->getAbsolutePath() . "/";
582
583        ilUtil::moveUploadedFile($a_tmp_name, $a_lang, $path . $a_lang);
584
585        $ilDB->update(
586            'mail_template',
587            array('att_file' => array('text', $a_name)),
588            array('lang' => array('text',$a_lang), 'type' => array('text','nacc'))
589        );
590    }
591
592    /**
593     * Delete account mail attachment
594     * @param $a_lang
595     */
596    public static function _deleteAccountMailAttachment($a_lang)
597    {
598        global $DIC;
599
600        $ilDB = $DIC['ilDB'];
601
602        include_once "Services/User/classes/class.ilFSStorageUserFolder.php";
603        $fs = new ilFSStorageUserFolder(USER_FOLDER_ID);
604        $path = $fs->getAbsolutePath() . "/";
605
606        if (file_exists($path . $a_lang)) {
607            unlink($path . $a_lang);
608        }
609
610        $ilDB->update(
611            'mail_template',
612            array('att_file' => array('text', '')),
613            array('lang' => array('text',$a_lang), 'type' => array('text','nacc'))
614        );
615    }
616
617    public static function _lookupNewAccountMail($a_lang)
618    {
619        global $DIC;
620
621        $ilDB = $DIC['ilDB'];
622
623        $set = $ilDB->query("SELECT * FROM mail_template " .
624            " WHERE type='nacc' AND lang = " . $ilDB->quote($a_lang, 'text'));
625
626        if ($rec = $set->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
627            return $rec;
628        }
629        return array();
630    }
631
632    /**
633     * Update user folder assignment
634     * Typically called after deleting a category with local user accounts.
635     * These users will be assigned to the global user folder.
636     *
637     * @access public
638     * @static
639     *
640     * @param int old_id
641     * @param int new id
642     */
643    public static function _updateUserFolderAssignment($a_old_id, $a_new_id)
644    {
645        global $DIC;
646
647        $ilDB = $DIC['ilDB'];
648
649        $query = "UPDATE usr_data SET time_limit_owner = " . $ilDB->quote($a_new_id, "integer") . " " .
650            "WHERE time_limit_owner = " . $ilDB->quote($a_old_id, "integer") . " ";
651        $ilDB->manipulate($query);
652
653        return true;
654    }
655} // END class.ilObjUserFolder
656