Skip to content
Snippets Groups Projects
Select Git revision
  • af2d1e28f110d6a12ed7e2923ca7fffc17ecd631
  • main default protected
  • studip-rector
  • ci-opt
  • course-members-export-as-word
  • data-vue-app
  • pipeline-improvements
  • webpack-optimizations
  • rector
  • icon-renewal
  • http-client-and-factories
  • jsonapi-atomic-operations
  • vueify-messages
  • tic-2341
  • 135-translatable-study-areas
  • extensible-sorm-action-parameters
  • sorm-configuration-trait
  • jsonapi-mvv-routes
  • docblocks-for-magic-methods
19 results

LogEvent.php

  • Forked from Stud.IP / Stud.IP
    3481 commits behind, 92 commits ahead of the upstream repository.
    Jan-Hendrik Willms's avatar
    Jan-Hendrik Willms authored and Jan-Hendrik Willms committed
    Closes #1619
    
    Merge request studip/studip!1047
    af2d1e28
    History
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    LogEvent.php 14.04 KiB
    <?php
    /**
     * LogEvent
     * model class for table log_events
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License as
     * published by the Free Software Foundation; either version 2 of
     * the License, or (at your option) any later version.
     *
     * @author      Peter Thienel <thienel@data-quest.de>
     * @copyright   2013 Stud.IP Core-Group
     * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
     * @category    Stud.IP
     * @since       3.0
     * @property string event_id database column
     * @property string id alias column for event_id
     * @property string user_id database column
     * @property string action_id database column
     * @property string affected_range_id database column
     * @property string coaffected_range_id database column
     * @property string info database column
     * @property string dbg_info database column
     * @property string mkdate database column
     * @property LogAction action belongs_to LogAction
     * @property User user belongs_to User
     */
    
    
    class LogEvent extends SimpleORMap implements PrivacyObject
    {
        protected static function configure($config = [])
        {
            $config['db_table'] = 'log_events';
    
            $config['belongs_to']['action'] = [
                'class_name' => LogAction::class,
                'foreign_key' => 'action_id',
            ];
            $config['belongs_to']['user'] = [
                'class_name' => User::class,
                'foreign_key' => 'user_id',
            ];
    
            parent::configure($config);
        }
    
        protected $formatted_text = '';
    
        /**
         * Returns the number of log events counted by actions as an array where
         * the ey is the action id and the value is the number of events for
         * this action.
         *
         * @return array Number of loge events for all actions
         */
        public static function countByActions()
        {
            $query = "SELECT action_id, COUNT(*) FROM log_events GROUP BY action_id";
            $statement = DBManager::get()->query($query);
            return $statement->fetchGrouped(PDO::FETCH_COLUMN);
        }
    
        /**
         * Deletes all expired events.
         *
         * @return int Number of deleted events.
         */
        public static function deleteExpired()
        {
            $sql = "DELETE log_events
                    FROM log_events
                    JOIN log_actions USING(action_id)
                    WHERE log_actions.expires > 0
                      AND log_events.mkdate + log_actions.expires < UNIX_TIMESTAMP()";
            return DBManager::get()->exec($sql);
        }
    
        /**
         * Returns the formatted log event. Fills the action template with data
         * of this event.
         *
         * @return string The formatted log event.
         */
        public function formatEvent()
        {
            $text = $this->formatObject();
            $patterns = [
                '/%affected/',
                '/%coaffected/',
                '/%info/',
                '/%dbg_info/'
            ];
            $replacements = [
                $this->affected_range_id,
                $this->coaffected_range_id,
                htmlReady($this->info),
                htmlReady($this->dbg_info)
            ];
            $replace_callbacks = [
                '/%sem\(%affected\)/',
                '/%sem\(%coaffected\)/',
                '/%studyarea\(%affected\)/',
                '/%studyarea\(%coaffected\)/',
                '/%res\(%affected\)/',
                '/%res\(%coaffected\)/',
                '/%inst\(%affected\)/',
                '/%inst\(%coaffected\)/',
                '/%user\(%affected\)/',
                '/%user\(%coaffected\)/',
                '/%user/',
                '/%singledate\(%affected\)/',
                '/%semester\(%coaffected\)/',
                '/%plugin\(%coaffected\)/',
                '/%group\(%coaffected\)/',
            ];
    
            $text = preg_replace_callback($replace_callbacks, [$this, 'formatCallback'], $text);
            return preg_replace($patterns, $replacements, $text);
        }
    
        /**
         * @param $m
         * @return string
         */
        protected function formatCallback($m)
        {
            $map = [
                'sem'  => 'Seminar',
                'res'  => 'Resource',
                'inst' => 'Institute',
                'user' => 'Username',
                'group' => 'Statusgruppe'
            ];
            $ret = '';
            if (preg_match_all('/%([a-z]+)/', $m[0], $found)) {
                if (isset($found[1][0])) {
                    $funcname = 'format' . (isset($map[$found[1][0]]) ? $map[$found[1][0]] : $found[1][0]);
                    if (isset($found[1][1])) {
                        $param = $found[1][1] . '_range_id';
                    } else {
                        $param = 'user_id';
                    }
                    if (is_callable([$this, $funcname])) {
                        $ret = call_user_func([$this, $funcname], $param);
                    }
                }
            }
            return $ret;
        }
    
        /**
         * Returns the name of the resource for the resource id found in the
         * given field or the resource id if the resource is unknown.
         *
         * @param string $field The name of the table field.
         * @return string The name of the resource or resource id.
         */
        protected function formatResource($field)
        {
            $resource = Resource::find($this->$field);
            if ($resource && $resource->name) {
                return sprintf(
                    '<a href="%s">%s</a>',
                    Resource::getLinkForAction('show', $resource->id),
                    htmlReady($resource->name)
                );
            }
            return $this->$field;
        }
    
        /**
         * Returns the name of the user with the id found in the given field.
         *
         * @param string $field The name of the table field.
         * @return string The name of the user.
         */
        protected function formatUsername($field)
        {
            return '<a href="' . URLHelper::getLink('dispatch.php/admin/user/edit/'
                    . $this->$field) . '">' . htmlReady(get_fullname($this->$field))
                    . '</a>';
        }
    
        /**
         * Returns the name of the seminar for the id found in the given
         * field or the id if the seminar is unknown.
         *
         * @param string $field The name of the table field.
         * @return string The name of seminar or the id.
         */
        protected function formatSeminar($field)
        {
            $course = Course::find($this->$field);
    
            if (!$course) {
                return $this->$field;
            }
            return sprintf('<a href="%s">%s %s (%s)</a>',
                           URLHelper::getLink('dispatch.php/course/details',
                                   ['sem_id' => $course->getId()]),
                           htmlReady($course->VeranstaltungsNummer),
                           htmlReady(my_substr($course->name, 0, 100)),
                           htmlReady($course->start_semester->name));
        }
    
        /**
         * Returns the name of the institute for the id found in the given
         * field or the id if the institute is unknown.
         *
         * @param string $field The name of the table field.
         * @return string The name of institute or the id.
         */
        protected function formatInstitute($field)
        {
            $institute = Institute::find($this->$field);
    
            if (!$institute) {
                return $this->$field;
            }
    
            return sprintf('<a href="%s">%s</a>',
                           URLHelper::getLink('dispatch.php/institute/overview',
                                   ['auswahl' => $institute->getId()]),
                           htmlReady(my_substr($institute->name, 0, 100)));
        }
    
        /**
         * Returns the name of the study area for the id found in the given
         * field or the id if the study area is unknown.
         *
         * @param string $field The name of the table field.
         * @return string The name of seminar or the id.
         */
        protected function formatStudyarea($field)
        {
            $study_area = StudipStudyArea::find($this->$field);
    
            if (!$study_area) {
                return $this->$field;
            }
    
            return '<em>' . htmlReady($study_area->getPath(' > ')) . '</em>';
        }
    
        /**
         * Returns the singledate for the id found in the given field.
         *
         * @param string $field The name of the table field.
         * @return string The singledate.
         */
        protected function formatSingledate($field) {
            $termin = new SingleDate($this->$field);
            return '<em>' . $termin->toString() . '</em>';
        }
    
        /**
         * Returns the name of the plugin for the id found in the given
         * field or the id if the plugin is unknown.
         *
         * @param string $field The name of the table field.
         * @return string The name of plugin or the id.
         */
        protected function formatPlugin($field) {
            $plugin_manager = PluginManager::getInstance();
            $plugin_info = $plugin_manager->getPluginInfoById($this->$field);
    
            return $plugin_info ? '<em>' . htmlReady($plugin_info['name']) . '</em>' : $this->$field;
        }
    
        /**
         * Returns the name of the semester for the id found in the given
         * field or the id if the seminar is unknown.
         *
         * @param string $field The name of the table field.
         * @return string The name of semester or the id.
         */
        protected function formatSemester($field) {
            $all_semester = Semester::findAllVisible(false);
            foreach ($all_semester as $val) {
                if ($val['beginn'] == $this->$field) {
                    return '<em>' . htmlReady($val['name']) . '</em>';
                }
            }
            return htmlReady($this->$field);
        }
    
        /**
         * Returns the name of the statusgroup for the id found in the given
         * field or the id if the group is unknown.
         *
         * @param string $field The name of the table field.
         * @return string The name of statusgruppe or the id.
         */
        protected function formatStatusgruppe($field)
        {
            $group = Statusgruppen::find($this->$field);
    
            if (!$group) {
                return $this->$field;
            }
            $course = Course::find($group->range_id);
            return sprintf(
                '<a href="%s">%s</a>',
                URLHelper::getLink('dispatch.php/course/statusgroups', [
                    'contentbox_open' => $group->getId()
                ]),
                htmlReady($group->name. ($course ? " (VA: ".$course->name.")" : ""))
            );
        }
    
        protected function formatObject()
        {
            if ($this->action) {
                switch ($this->action->type) {
                    case 'plugin':
                        $plugin_manager = PluginManager::getInstance();
                        $plugin_info = $plugin_manager->getPluginInfo($this->action->class);
                        $class_name = $plugin_info['class'];
                        $plugin = $plugin_manager->getPlugin($class_name);
                        if ($plugin instanceof Loggable) {
                            return $class_name::logFormat($this);
                        }
                        break;
                    case 'file':
                        if (file_exists($this->action->filename)) {
                            require_once $this->action->filename;
    
                            $class_name = $this->action->class;
                            if ($class_name && in_array(Loggable::class, class_implements($class_name))) {
                                return $class_name::logFormat($this);
                            }
                        }
                        break;
                    case 'core':
                        $class_name = $this->action->class;
                        if ($class_name && in_array(Loggable::class, class_implements($class_name))) {
                            return $class_name::logFormat($this);
                        }
                        break;
                }
            }
            return $this->action->info_template;
        }
    
        /**
         * Export available data of a given user into a storage object
         * (an instance of the StoredUserData class) for that user.
         *
         * @param StoredUserData $storage object to store data into
         */
        public static function exportUserData(StoredUserData $storage)
        {
            $user_id = $storage->user_id;
            $templates = [];
    
            $query = "SELECT *
                      FROM log_events
                      WHERE :user_id IN (user_id, affected_range_id, coaffected_range_id)";
            $log = DBManager::get()->fetchAll($query, [':user_id' => $user_id]);
    
            foreach ($log as $pos => $event) {
                if (!array_key_exists($event['action_id'], $templates)) {
                    $log_action = LogAction::find($event["action_id"]);
                    $templates[$event['action_id']] = $log_action->info_template;
                }
                $template = $templates[$event['action_id']];
                $log_event = LogEvent::find($event['event_id']);
    
                // anonymize
                $was_censored = false;
                if ($event['user_id'] && substr_count($template, '%user ') && $event['user_id'] !== $user_id) {
                    $event['user_id'] = preg_replace('/[^w]/', '#', $event['user_id']);
                    $log_event->user_id = $event['user_id'];
                    $was_censored = true;
                }
                if ($event['affected_range_id'] && substr_count($template, '%user(%affected)') && $event['affected_range_id'] !== $user_id) {
                    $event['affected_range_id'] = preg_replace('/[^w]/', '#', $event['affected_range_id']);
                    $log_event->affected_range_id = $event['affected_range_id'];
                    $was_censored = true;
                }
                if ($event['coaffected_range_id'] && substr_count($template, '%user(%coaffected)') && $event['coaffected_range_id'] !== $user_id) {
                    $event['coaffected_range_id'] = preg_replace('/[^w]/', '#', $event['coaffected_range_id']);
                    $log_event->coaffected_range_id = $event['coaffected_range_id'];
                    $was_censored = true;
                }
    
                //censore possible info
                if ($was_censored) {
                    if (!empty($event['info'])) {
                        $event['info'] = preg_replace('/[^w]/', '#', $event['info']);
                    }
                    if (!empty($event["dbg_info"])) {
                        $event['dbg_info'] = preg_replace('/[^w]/', '#', $event['dbg_info']);
                    }
                }
    
                $a['readable_entry'] = html_entity_decode(strip_tags(str_replace('<br>', PHP_EOL, $log_event->formatEvent())));
                $log[$pos]= array_merge($a, $event);
            }
    
            if ($log) {
                $storage->addTabularData(_('Logs'), 'log_events', $log);
            }
        }
    }