1<?php
2/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4include_once("./Services/Table/classes/class.ilTable2GUI.php");
5include_once  './Services/Search/classes/class.ilSearchSettings.php';
6require_once('./Services/Repository/classes/class.ilObjectPlugin.php');
7
8/**
9* TableGUI class for learning progress
10*
11* @author Jörg Lützenkirchen <luetzenkirchen@leifos.com>
12* @version $Id$
13*
14* @ingroup ServicesTracking
15*/
16class ilLPTableBaseGUI extends ilTable2GUI
17{
18    protected $filter; // array
19    protected $anonymized; // [bool]
20
21    public function __construct($a_parent_obj, $a_parent_cmd = "", $a_template_context = "")
22    {
23        parent::__construct($a_parent_obj, $a_parent_cmd, $a_template_context);
24
25        // country names
26        $this->lng->loadLanguageModule("meta");
27
28        include_once("./Services/Object/classes/class.ilObjectLP.php");
29
30        $this->anonymized = (bool) !ilObjUserTracking::_enabledUserRelatedData();
31        if (!$this->anonymized && $this->obj_id) {
32            include_once "Services/Object/classes/class.ilObjectLP.php";
33            $olp = ilObjectLP::getInstance($this->obj_id);
34            $this->anonymized = $olp->isAnonymized();
35        }
36    }
37
38    public function executeCommand()
39    {
40        global $DIC;
41
42        $ilCtrl = $DIC['ilCtrl'];
43        $lng = $DIC['lng'];
44
45        $this->determineSelectedFilters();
46
47        if (!$ilCtrl->getNextClass($this)) {
48            $to_hide = false;
49
50            switch ($ilCtrl->getCmd()) {
51                case "applyFilter":
52                    $this->resetOffset();
53                    $this->writeFilterToSession();
54                    break;
55
56                case "resetFilter":
57                    $this->resetOffset();
58                    $this->resetFilter();
59                    break;
60
61                case "hideSelected":
62                    $to_hide = $_POST["item_id"];
63                    break;
64
65                case "hide":
66                    $to_hide = array((int) $_GET["hide"]);
67                    break;
68
69                case "mailselectedusers":
70                    if (!sizeof($_POST["uid"])) {
71                        ilUtil::sendFailure($lng->txt("no_checkbox"), true);
72                    } else {
73                        $this->sendMail($_POST["uid"], $this->parent_obj, $this->parent_cmd);
74                    }
75                    break;
76
77                case 'addToClipboard':
78                    if (!sizeof($_POST['uid'])) {
79                        ilUtil::sendFailure($lng->txt('no_checkbox'), true);
80                    } else {
81                        $this->addToClipboard();
82                    }
83                    break;
84
85                // page selector
86                default:
87                    $this->determineOffsetAndOrder();
88                    $this->storeNavParameter();
89                    break;
90            }
91
92            if ($to_hide) {
93                $obj = $this->getFilterItemByPostVar("hide");
94                $value = array_unique(array_merge((array) $obj->getValue(), $to_hide));
95                $obj->setValue($value);
96                $obj->writeToSession();
97            }
98
99            if (isset($_REQUEST["tbltplcrt"])) {
100                $ilCtrl->setParameter($this->parent_obj, "tbltplcrt", $_REQUEST["tbltplcrt"]);
101            }
102            if (isset($_REQUEST["tbltpldel"])) {
103                $ilCtrl->setParameter($this->parent_obj, "tbltpldel", $_REQUEST["tbltpldel"]);
104            }
105
106            $ilCtrl->redirect($this->parent_obj, $this->parent_cmd);
107        } else {
108            // e.g. repository selector
109            return parent::executeCommand();
110        }
111    }
112
113    protected function sendMail(array $a_user_ids, $a_parent_obj, $a_parent_cmd)
114    {
115        // see ilObjCourseGUI::sendMailToSelectedUsersObject()
116
117        require_once 'Services/Mail/classes/class.ilMailFormCall.php';
118
119        $rcps = array();
120        foreach ($a_user_ids as $usr_id) {
121            $rcps[] = ilObjUser::_lookupLogin($usr_id);
122        }
123
124        $template = array();
125        $sig = null;
126
127        // repository-object-specific
128        $ref_id = (int) $_REQUEST["ref_id"];
129        if ($ref_id) {
130            $obj_lp = ilObjectLP::getInstance(ilObject::_lookupObjectId($ref_id));
131            $tmpl_id = $obj_lp->getMailTemplateId();
132
133            if ($tmpl_id) {
134                $template = array(
135                    ilMailFormCall::CONTEXT_KEY => $tmpl_id,
136                    'ref_id' => $ref_id,
137                    'ts' => time()
138                );
139            } else {
140                include_once './Services/Link/classes/class.ilLink.php';
141                $sig = ilLink::_getLink($ref_id);
142                $sig = rawurlencode(base64_encode($sig));
143            }
144        }
145
146        ilUtil::redirect(
147            ilMailFormCall::getRedirectTarget(
148                $a_parent_obj,
149                $a_parent_cmd,
150                array(),
151                array(
152                    'type' => 'new',
153                    'rcp_to' => implode(',', $rcps),
154                    'sig' => $sig
155                ),
156                $template
157            )
158        );
159    }
160
161    /**
162     * Search objects that match current filters
163     *
164     * @param array	$filter
165     * @param string	$permission
166     * @param array preset obj_ids
167     * @param bool check lp activation
168     * @return	array
169     */
170    protected function searchObjects(array $filter, $permission, array $preset_obj_ids = null, $a_check_lp_activation = true)
171    {
172        global $DIC;
173
174        $ilObjDataCache = $DIC['ilObjDataCache'];
175
176        include_once './Services/Search/classes/class.ilQueryParser.php';
177
178        $query_parser = new ilQueryParser($filter["query"]);
179        $query_parser->setMinWordLength(0);
180        $query_parser->setCombination(QP_COMBINATION_AND);
181        $query_parser->parse();
182        if (!$query_parser->validate()) {
183            ilLoggerFactory::getLogger('trac')->notice($query_parser->getMessage());
184            // echo $query_parser->getMessage();
185            return false;
186        }
187
188        if ($filter["type"] == "lres") {
189            $filter["type"] = array('lm','sahs','htlm');
190        } else {
191            $filter["type"] = array($filter["type"]);
192        }
193
194        include_once 'Services/Search/classes/Like/class.ilLikeObjectSearch.php';
195        $object_search = new ilLikeObjectSearch($query_parser);
196        $object_search->setFilter($filter["type"]);
197        if ($preset_obj_ids) {
198            $object_search->setIdFilter($preset_obj_ids);
199        }
200        $res = &$object_search->performSearch();
201
202        if ($permission) {
203            $res->setRequiredPermission($permission);
204        }
205
206        $res->setMaxHits(1000);
207
208        if ($a_check_lp_activation) {
209            $res->addObserver($this, "searchFilterListener");
210        }
211
212        if (!$this->filter["area"]) {
213            $res->filter(ROOT_FOLDER_ID, false);
214        } else {
215            $res->filter($this->filter["area"], false);
216        }
217
218        $objects = array();
219        foreach ($res->getResults() as $obj_data) {
220            $objects[$obj_data['obj_id']][] = $obj_data['ref_id'];
221        }
222
223        // Check if search max hits is reached
224        if ($res->isLimitReached()) {
225            $this->lng->loadLanguageModule("search");
226            ilUtil::sendFailure(sprintf($this->lng->txt("search_limit_reached"), 1000));
227        }
228
229        return $objects ? $objects : array();
230    }
231
232    /**
233     * Listener for SearchResultFilter
234     * Checks wheather the object is hidden and mode is not LP_MODE_DEACTIVATED
235     * @access public
236     */
237    public function searchFilterListener($a_ref_id, $a_data)
238    {
239        if (is_array($this->filter["hide"]) && in_array($a_data["obj_id"], $this->filter["hide"])) {
240            return false;
241        }
242        $olp = ilObjectLP::getInstance($a_data["obj_id"]);
243        if (get_class($olp) != "ilObjectLP" && // #13654 - LP could be unsupported
244            !$olp->isActive()) {
245            return false;
246        }
247        return true;
248    }
249
250    /**
251     * Init filter
252     *
253     * @param bool $a_split_learning_resources
254     */
255    public function initBaseFilter($a_split_learning_resources = false, $a_include_no_status_filter = true)
256    {
257        global $DIC;
258
259        $lng = $DIC['lng'];
260        $ilObjDataCache = $DIC['ilObjDataCache'];
261
262        $this->setDisableFilterHiding(true);
263
264        // object type selection
265        include_once("./Services/Form/classes/class.ilSelectInputGUI.php");
266        $si = new ilSelectInputGUI($this->lng->txt("obj_type"), "type");
267        $si->setOptions($this->getPossibleTypes($a_split_learning_resources));
268        $this->addFilterItem($si);
269        $si->readFromSession();
270        if (!$si->getValue()) {
271            $si->setValue("crs");
272        }
273        $this->filter["type"] = $si->getValue();
274
275        // hidden items
276        include_once("./Services/Form/classes/class.ilMultiSelectInputGUI.php");
277        $msi = new ilMultiSelectInputGUI($lng->txt("trac_filter_hidden"), "hide");
278        $this->addFilterItem($msi);
279        $msi->readFromSession();
280        $this->filter["hide"] = $msi->getValue();
281        if ($this->filter["hide"]) {
282            // create options from current value
283            $types = $this->getCurrentFilter(true);
284            $type = $types["type"];
285            $options = array();
286            if ($type == 'lres') {
287                $type = array('lm','sahs','htlm');
288            } else {
289                $type = array($type);
290            }
291            foreach ($this->filter["hide"] as $obj_id) {
292                if (in_array($ilObjDataCache->lookupType($obj_id), $type)) {
293                    $options[$obj_id] = $ilObjDataCache->lookupTitle($obj_id);
294                }
295            }
296            $msi->setOptions($options);
297        }
298
299        // title/description
300        include_once("./Services/Form/classes/class.ilTextInputGUI.php");
301        $ti = new ilTextInputGUI($lng->txt("trac_title_description"), "query");
302        $ti->setMaxLength(64);
303        $ti->setSize(20);
304        $this->addFilterItem($ti);
305        $ti->readFromSession();
306        $this->filter["query"] = $ti->getValue();
307
308        // repository area selection
309        include_once("./Services/Form/classes/class.ilRepositorySelectorInputGUI.php");
310        $rs = new ilRepositorySelectorInputGUI($lng->txt("trac_filter_area"), "area");
311        $rs->setSelectText($lng->txt("trac_select_area"));
312        $this->addFilterItem($rs);
313        $rs->readFromSession();
314        $this->filter["area"] = $rs->getValue();
315
316        // hide "not started yet"
317        if ($a_include_no_status_filter) {
318            include_once("./Services/Form/classes/class.ilCheckboxInputGUI.php");
319            $cb = new ilCheckboxInputGUI($lng->txt("trac_filter_has_status"), "status");
320            $this->addFilterItem($cb);
321            $cb->readFromSession();
322            $this->filter["status"] = $cb->getChecked();
323        }
324    }
325
326    /**
327     * Build path with deep-link
328     *
329     * @param	array	$ref_ids
330     * @return	array
331     */
332    protected function buildPath($ref_ids)
333    {
334        global $DIC;
335
336        $tree = $DIC['tree'];
337        $ilCtrl = $DIC['ilCtrl'];
338
339        include_once './Services/Link/classes/class.ilLink.php';
340
341        if (!count($ref_ids)) {
342            return false;
343        }
344        foreach ($ref_ids as $ref_id) {
345            $path = "...";
346            $counter = 0;
347            $path_full = $tree->getPathFull($ref_id);
348            foreach ($path_full as $data) {
349                if (++$counter < (count($path_full) - 1)) {
350                    continue;
351                }
352                $path .= " &raquo; ";
353                if ($ref_id != $data['ref_id']) {
354                    $path .= $data['title'];
355                } else {
356                    $path .= ('<a target="_top" href="' .
357                              ilLink::_getLink($data['ref_id'], $data['type']) . '">' .
358                              $data['title'] . '</a>');
359                }
360            }
361
362            $result[$ref_id] = $path;
363        }
364        return $result;
365    }
366
367    /**
368     * Get possible subtypes
369     *
370     * @param bool $a_split_learning_resources
371     * @param bool $a_include_digilib
372     * @param bool $a_allow_undefined_lp
373     */
374    protected function getPossibleTypes($a_split_learning_resources = false, $a_include_digilib = false, $a_allow_undefined_lp = false)
375    {
376        global $DIC;
377
378        $lng = $DIC['lng'];
379        $ilPluginAdmin = $DIC['ilPluginAdmin'];
380
381        $options = array();
382
383        if ($a_split_learning_resources) {
384            $options['lm'] = $lng->txt('objs_lm');
385            $options['sahs'] = $lng->txt('objs_sahs');
386            $options['htlm'] = $lng->txt('objs_htlm');
387        } else {
388            $options['lres'] = $lng->txt('obj_lrss');
389        }
390
391        $options['crs'] = $lng->txt('objs_crs');
392        $options['grp'] = $lng->txt('objs_grp');
393        $options['exc'] = $lng->txt('objs_exc');
394        $options['file'] = $lng->txt('objs_file');
395        $options['mcst'] = $lng->txt('objs_mcst');
396        $options['svy'] = $lng->txt('objs_svy');
397        $options['tst'] = $lng->txt('objs_tst');
398        $options['prg'] = $lng->txt('objs_prg');
399        $options['iass'] = $lng->txt('objs_iass');
400        $options['copa'] = $lng->txt('objs_copa');
401        $options['lso'] = $lng->txt('objs_lso');
402
403        if ($a_allow_undefined_lp) {
404            $options["webr"] = $lng->txt("objs_webr");
405            $options["wiki"] = $lng->txt("objs_wiki");
406            $options["blog"] = $lng->txt("objs_blog");
407            $options["prtf"] = $lng->txt("objs_prtf");
408            $options["prtt"] = $lng->txt("objs_prtt");
409        }
410
411        // repository plugins (currently only active)
412        include_once 'Services/Repository/classes/class.ilRepositoryObjectPluginSlot.php';
413        $pl_names = $ilPluginAdmin->getActivePluginsForSlot(IL_COMP_SERVICE, "Repository", "robj");
414        foreach ($pl_names as $pl) {
415            $pl_id = $ilPluginAdmin->getId(IL_COMP_SERVICE, "Repository", "robj", $pl);
416            if (ilRepositoryObjectPluginSlot::isTypePluginWithLP($pl_id)) {
417                $options[$pl_id] = ilObjectPlugin::lookupTxtById($pl_id, "objs_" . $pl_id);
418            }
419        }
420
421        asort($options);
422        return $options;
423    }
424
425    protected function parseValue($id, $value, $type)
426    {
427        global $DIC;
428
429        $lng = $DIC['lng'];
430
431        // get rid of aggregation
432        $pos = strrpos($id, "_");
433        if ($pos !== false) {
434            $function = strtoupper(substr($id, $pos + 1));
435            if (in_array($function, array("MIN", "MAX", "SUM", "AVG", "COUNT"))) {
436                $id = substr($id, 0, $pos);
437            }
438        }
439
440        if (trim($value) == "" && $id != "status") {
441            if ($id == "title" &&
442                get_class($this) != "ilTrObjectUsersPropsTableGUI" &&
443                get_class($this) != "ilTrMatrixTableGUI") {
444                return "--" . $lng->txt("none") . "--";
445            }
446            return " ";
447        }
448
449        switch ($id) {
450            case "first_access":
451            case "create_date":
452            case 'status_changed':
453                $value = ilDatePresentation::formatDate(new ilDateTime($value, IL_CAL_DATETIME));
454                break;
455
456            case "last_access":
457                $value = ilDatePresentation::formatDate(new ilDateTime($value, IL_CAL_UNIX));
458                break;
459
460            case "birthday":
461                $value = ilDatePresentation::formatDate(new ilDate($value, IL_CAL_DATE));
462                break;
463
464            case "spent_seconds":
465                if (!ilObjectLP::supportsSpentSeconds($type)) {
466                    $value = "-";
467                } else {
468                    $value = ilDatePresentation::secondsToString($value, ($value < 3600 ? true : false)); // #14858
469                }
470                break;
471
472            case "percentage":
473                if (false /* $this->isPercentageAvailable() */) {
474                    $value = "-";
475                } else {
476                    $value = $value . "%";
477                }
478                break;
479
480            case "mark":
481                if (!ilObjectLP::supportsMark($type)) {
482                    $value = "-";
483                }
484                break;
485
486            case "gender":
487                $value = $lng->txt("gender_" . $value);
488                break;
489
490            case "status":
491                include_once("./Services/Tracking/classes/class.ilLearningProgressBaseGUI.php");
492                $path = ilLearningProgressBaseGUI::_getImagePathForStatus($value);
493                $text = ilLearningProgressBaseGUI::_getStatusText($value);
494                $value = ilUtil::img($path, $text);
495                break;
496
497            case "language":
498                $lng->loadLanguageModule("meta");
499                $value = $lng->txt("meta_l_" . $value);
500                break;
501
502            case "sel_country":
503                $value = $lng->txt("meta_c_" . $value);
504                break;
505        }
506
507        return $value;
508    }
509
510    public function getCurrentFilter($as_query = false)
511    {
512        $result = array();
513        foreach ((array) $this->filter as $id => $value) {
514            $item = $this->getFilterItemByPostVar($id);
515            switch ($id) {
516                case "title":
517                case "country":
518                case "gender":
519                case "city":
520                case "language":
521                case "login":
522                case "firstname":
523                case "lastname":
524                case "mark":
525                case "u_comment":
526                case "institution":
527                case "department":
528                case "title":
529                case "street":
530                case "zipcode":
531                case "email":
532                case "matriculation":
533                case "sel_country":
534                case "query":
535                case "type":
536                case "area":
537                    if ($value) {
538                        $result[$id] = $value;
539                    }
540                    break;
541
542                case "status":
543                    if ($value !== false) {
544                        $result[$id] = $value;
545                    }
546                    break;
547
548                case "user_total":
549                case "read_count":
550                case "percentage":
551                case "hide":
552                case "spent_seconds":
553                    if (is_array($value) && implode("", $value)) {
554                        $result[$id] = $value;
555                    }
556                    break;
557
558                 case "registration":
559                 case "create_date":
560                 case "first_access":
561                 case "last_access":
562                 case 'status_changed':
563                     if ($value) {
564                         if ($value["from"]) {
565                             $result[$id]["from"] = $value["from"]->get(IL_CAL_DATETIME);
566                         }
567                         if ($value["to"]) {
568                             $result[$id]["to"] = $value["to"]->get(IL_CAL_DATETIME);
569                         }
570                     }
571                     break;
572
573                 case "birthday":
574                     if ($value) {
575                         if ($value["from"]) {
576                             $result[$id]["from"] = $value["from"]->get(IL_CAL_DATETIME);
577                             $result[$id]["from"] = substr($result[$id]["from"], 0, -8) . "00:00:00";
578                         }
579                         if ($value["to"]) {
580                             $result[$id]["to"] = $value["to"]->get(IL_CAL_DATETIME);
581                             $result[$id]["to"] = substr($result[$id]["to"], 0, -8) . "23:59:59";
582                         }
583                     }
584                     break;
585          }
586        }
587
588        return $result;
589    }
590
591    protected function isPercentageAvailable($a_obj_id)
592    {
593        // :TODO:
594        $olp = ilObjectLP::getInstance($a_obj_id);
595        $mode = $olp->getCurrentMode();
596        if (in_array($mode, array(ilLPObjSettings::LP_MODE_TLT,
597            ilLPObjSettings::LP_MODE_VISITS,
598            ilLPObjSettings::LP_MODE_SCORM,
599            ilLPObjSettings::LP_MODE_VISITED_PAGES,
600            ilLPObjSettings::LP_MODE_TEST_PASSED))) {
601            return true;
602        }
603        return false;
604    }
605
606    protected function parseTitle($a_obj_id, $action, $a_user_id = false)
607    {
608        global $DIC;
609
610        $lng = $DIC['lng'];
611        $ilObjDataCache = $DIC['ilObjDataCache'];
612        $ilUser = $DIC['ilUser'];
613
614        $user = "";
615        if ($a_user_id) {
616            if ($a_user_id != $ilUser->getId()) {
617                $a_user = ilObjectFactory::getInstanceByObjId($a_user_id);
618            } else {
619                $a_user = $ilUser;
620            }
621            $user .= ", " . $a_user->getFullName(); // " [".$a_user->getLogin()."]";
622        }
623
624        if ($a_obj_id != ROOT_FOLDER_ID) {
625            $this->setTitle($lng->txt($action) . ": " . $ilObjDataCache->lookupTitle($a_obj_id) . $user);
626
627            $olp = ilObjectLP::getInstance($a_obj_id);
628            $this->setDescription($this->lng->txt('trac_mode') . ": " . $olp->getModeText($olp->getCurrentMode()));
629        } else {
630            $this->setTitle($lng->txt($action));
631        }
632    }
633
634    /**
635     * Build export meta data
636     *
637     * @return array
638     */
639    protected function getExportMeta()
640    {
641        global $DIC;
642
643        $lng = $DIC['lng'];
644        $ilObjDataCache = $DIC['ilObjDataCache'];
645        $ilUser = $DIC['ilUser'];
646        $ilClientIniFile = $DIC['ilClientIniFile'];
647
648        /* see spec
649            Name of installation
650            Name of the course
651            Permalink to course
652            Owner of course object
653            Date of report generation
654            Reporting period
655            Name of person who generated the report.
656        */
657
658        ilDatePresentation::setUseRelativeDates(false);
659        include_once './Services/Link/classes/class.ilLink.php';
660
661        $data = array();
662        $data[$lng->txt("trac_name_of_installation")] = $ilClientIniFile->readVariable('client', 'name');
663
664        if ($this->obj_id) {
665            $data[$lng->txt("trac_object_name")] = $ilObjDataCache->lookupTitle($this->obj_id);
666            if ($this->ref_id) {
667                $data[$lng->txt("trac_object_link")] = ilLink::_getLink($this->ref_id, ilObject::_lookupType($this->obj_id));
668            }
669            $data[$lng->txt("trac_object_owner")] = ilObjUser::_lookupFullname(ilObject::_lookupOwner($this->obj_id));
670        }
671
672        $data[$lng->txt("trac_report_date")] = ilDatePresentation::formatDate(new ilDateTime(time(), IL_CAL_UNIX));
673        $data[$lng->txt("trac_report_owner")] = $ilUser->getFullName();
674
675        return $data;
676    }
677
678    protected function fillMetaExcel(ilExcel $a_excel, &$a_row)
679    {
680        foreach ($this->getExportMeta() as $caption => $value) {
681            $a_excel->setCell($a_row, 0, $caption);
682            $a_excel->setCell($a_row, 1, $value);
683            $a_row++;
684        }
685        $a_row++;
686    }
687
688    protected function fillMetaCSV($a_csv)
689    {
690        foreach ($this->getExportMeta() as $caption => $value) {
691            $a_csv->addColumn(strip_tags($caption));
692            $a_csv->addColumn(strip_tags($value));
693            $a_csv->addRow();
694        }
695        $a_csv->addRow();
696    }
697
698    protected function showTimingsWarning($a_ref_id, $a_user_id)
699    {
700        $timing_cache = ilTimingCache::getInstanceByRefId($a_ref_id);
701        if ($timing_cache->isWarningRequired($a_user_id)) {
702            $timings = ilTimingCache::_getTimings($a_ref_id);
703            if ($timings['item']['changeable'] && $timings['user'][$a_user_id]['end']) {
704                $end = $timings['user'][$a_user_id]['end'];
705            } elseif ($timings['item']['suggestion_end']) {
706                $end = $timings['item']['suggestion_end'];
707            } else {
708                $end = true;
709            }
710            return $end;
711        }
712    }
713
714    protected function formatSeconds($seconds, $a_shorten_zero = false)
715    {
716        $seconds = ((int) $seconds > 0) ? $seconds : 0;
717        if ($a_shorten_zero && !$seconds) {
718            return "-";
719        }
720
721        $hours = floor($seconds / 3600);
722        $rest = $seconds % 3600;
723
724        $minutes = floor($rest / 60);
725        $rest = $rest % 60;
726
727        if ($rest) {
728            $minutes++;
729        }
730
731        return sprintf("%dh%02dm", $hours, $minutes);
732    }
733
734    protected function anonymizeValue($a_value, $a_force_number = false)
735    {
736        // currently inactive
737        return $a_value;
738
739        if (is_numeric($a_value)) {
740            $threshold = 3;
741            $a_value = (int) $a_value;
742            if ($a_value <= $threshold) {
743                if (!$a_force_number) {
744                    return "0-" . $threshold;
745                } else {
746                    return $threshold;
747                }
748            }
749        }
750        return $a_value;
751    }
752
753    protected function buildValueScale($a_max_value, $a_anonymize = false, $a_format_seconds = false)
754    {
755        $step = 0;
756        if ($a_max_value) {
757            $step = $a_max_value / 10;
758            $base = ceil(log($step, 10));
759            $fac = ceil($step / pow(10, ($base - 1)));
760            $step = pow(10, $base - 1) * $fac;
761        }
762        if ($step <= 1) {
763            $step = 1;
764        }
765        $ticks = range(0, $a_max_value + $step, $step);
766
767        $value_ticks = array(0 => 0);
768        foreach ($ticks as $tick) {
769            $value = $tvalue = $tick;
770            if ($a_anonymize) {
771                $value = $this->anonymizeValue($value, true);
772                $tvalue = $this->anonymizeValue($tvalue);
773            }
774            if ($a_format_seconds) {
775                $tvalue = $this->formatSeconds($value);
776            }
777            $value_ticks[$value] = $tvalue;
778        }
779
780        return $value_ticks;
781    }
782
783    protected function getMonthsFilter($a_short = false)
784    {
785        global $DIC;
786
787        $lng = $DIC['lng'];
788
789        $options = array();
790        for ($loop = 0; $loop < 10; $loop++) {
791            $year = date("Y") - $loop;
792            $options[$year] = $year;
793            for ($loop2 = 12; $loop2 > 0; $loop2--) {
794                $month = str_pad($loop2, 2, "0", STR_PAD_LEFT);
795                if ($year . $month <= date("Ym")) {
796                    if (!$a_short) {
797                        $caption = $year . " / " . $lng->txt("month_" . $month . "_long");
798                    } else {
799                        $caption = $year . "/" . $month;
800                    }
801                    $options[$year . "-" . $month] = $caption;
802                }
803            }
804        }
805        return $options;
806    }
807
808    protected function getMonthsYear($a_year = null, $a_short = false)
809    {
810        global $DIC;
811
812        $lng = $DIC['lng'];
813
814        if (!$a_year) {
815            $a_year = date("Y");
816        }
817
818        $all = array();
819        for ($loop = 1; $loop < 13; $loop++) {
820            $month = str_pad($loop, 2, "0", STR_PAD_LEFT);
821            if ($a_year . "-" . $month <= date("Y-m")) {
822                if (!$a_short) {
823                    $caption = $lng->txt("month_" . $month . "_long");
824                } else {
825                    $caption = $lng->txt("month_" . $month . "_short");
826                }
827                $all[$a_year . "-" . $month] = $caption;
828            }
829        }
830        return $all;
831    }
832
833    protected function getSelectableUserColumns($a_in_course = false, $a_in_group = false)
834    {
835        global $DIC;
836
837        $lng = $DIC['lng'];
838        $ilSetting = $DIC['ilSetting'];
839
840        $cols = $privacy_fields = array();
841
842        include_once("./Services/User/classes/class.ilUserProfile.php");
843        $up = new ilUserProfile();
844        $up->skipGroup("preferences");
845        $up->skipGroup("settings");
846        $up->skipGroup("interests");
847        $ufs = $up->getStandardFields();
848
849        // default fields
850        $cols["login"] = array(
851            "txt" => $lng->txt("login"),
852            "default" => true);
853
854        if (!$this->anonymized) {
855            $cols["firstname"] = array(
856                "txt" => $lng->txt("firstname"),
857                "default" => true);
858            $cols["lastname"] = array(
859                "txt" => $lng->txt("lastname"),
860                "default" => true);
861        }
862
863        // show only if extended data was activated in lp settings
864        include_once 'Services/Tracking/classes/class.ilObjUserTracking.php';
865        $tracking = new ilObjUserTracking();
866        if ($tracking->hasExtendedData(ilObjUserTracking::EXTENDED_DATA_LAST_ACCESS)) {
867            $cols["first_access"] = array(
868                "txt" => $lng->txt("trac_first_access"),
869                "default" => true);
870            $cols["last_access"] = array(
871                "txt" => $lng->txt("trac_last_access"),
872                "default" => true);
873        }
874        if ($tracking->hasExtendedData(ilObjUserTracking::EXTENDED_DATA_READ_COUNT)) {
875            $cols["read_count"] = array(
876                "txt" => $lng->txt("trac_read_count"),
877                "default" => true);
878        }
879        if ($tracking->hasExtendedData(ilObjUserTracking::EXTENDED_DATA_SPENT_SECONDS) &&
880            ilObjectLP::supportsSpentSeconds($this->type)) {
881            $cols["spent_seconds"] = array(
882                "txt" => $lng->txt("trac_spent_seconds"),
883                "default" => true);
884        }
885
886        if ($this->isPercentageAvailable($this->obj_id)) {
887            $cols["percentage"] = array(
888                "txt" => $lng->txt("trac_percentage"),
889                "default" => true);
890        }
891
892        // do not show status if learning progress is deactivated
893        $olp = ilObjectLP::getInstance($this->obj_id);
894        if ($olp->isActive()) {
895            $cols["status"] = array(
896                "txt" => $lng->txt("trac_status"),
897                "default" => true);
898
899            $cols['status_changed'] = array(
900                'txt' => $lng->txt('trac_status_changed'),
901                'default' => false);
902        }
903
904        if (ilObjectLP::supportsMark($this->type)) {
905            $cols["mark"] = array(
906                "txt" => $lng->txt("trac_mark"),
907                "default" => true);
908        }
909
910        $cols["u_comment"] = array(
911            "txt" => $lng->txt("trac_comment"),
912            "default" => false);
913
914        $cols["create_date"] = array(
915            "txt" => $lng->txt("create_date"),
916            "default" => false);
917        $cols["language"] = array(
918            "txt" => $lng->txt("language"),
919            "default" => false);
920
921        // add user data only if object is [part of] course
922        if (!$this->anonymized &&
923            ($a_in_course || $a_in_group)) {
924            // only show if export permission is granted
925            include_once('Services/PrivacySecurity/classes/class.ilPrivacySettings.php');
926            if (ilPrivacySettings::_getInstance()->checkExportAccess($this->ref_id)) {
927                // other user profile fields
928                foreach ($ufs as $f => $fd) {
929                    if (!isset($cols[$f]) && $f != "username" && !$fd["lists_hide"]) {
930                        if ($a_in_course &&
931                            !($fd["course_export_fix_value"] || $ilSetting->get("usr_settings_course_export_" . $f))) {
932                            continue;
933                        }
934                        if ($a_in_group &&
935                            !($fd["group_export_fix_value"] || $ilSetting->get("usr_settings_group_export_" . $f))) {
936                            continue;
937                        }
938
939                        $cols[$f] = array(
940                            "txt" => $lng->txt($f),
941                            "default" => false);
942
943                        $privacy_fields[] = $f;
944                    }
945                }
946
947                // additional defined user data fields
948                include_once './Services/User/classes/class.ilUserDefinedFields.php';
949                $user_defined_fields = ilUserDefinedFields::_getInstance();
950                if ($a_in_course) {
951                    $user_defined_fields = $user_defined_fields->getCourseExportableFields();
952                } else {
953                    $user_defined_fields = $user_defined_fields->getGroupExportableFields();
954                }
955                foreach ($user_defined_fields as $definition) {
956                    if ($definition["field_type"] != UDF_TYPE_WYSIWYG) {
957                        $f = "udf_" . $definition["field_id"];
958                        $cols[$f] = array(
959                                "txt" => $definition["field_name"],
960                                "default" => false);
961
962                        $privacy_fields[] = $f;
963                    }
964                }
965            }
966        }
967
968        return array($cols, $privacy_fields);
969    }
970
971    /**
972     * Add selected users to clipboard
973     */
974    protected function addToClipboard()
975    {
976        $users = (array) $_POST['uid'];
977        include_once './Services/User/classes/class.ilUserClipboard.php';
978        $clip = ilUserClipboard::getInstance($GLOBALS['DIC']['ilUser']->getId());
979        $clip->add($users);
980        $clip->save();
981
982        $GLOBALS['DIC']['lng']->loadLanguageModule('user');
983        ilUtil::sendSuccess($this->lng->txt('clipboard_user_added'), true);
984    }
985}
986