, Cornelis Kater , data-quest GmbH * @access public * @modulegroup functions * @module object.inc.php * @package studip_core */ //object.inc.php - Verwaltung von Objektoperationen //Copyright (C) 2004 Ralf Stockmann , Cornelis Kater , data-quest GmbH // This file is part of Stud.IP // object.inc.php // Funktionen fuer generische Objekt-Behandlungen (Stud.IP-Objekte/Module) // Copyright (C) 2004 Cornelis Kater , Suchi & Berg GmbH // +---------------------------------------------------------------------------+ // 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 any later version. // +---------------------------------------------------------------------------+ // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // +---------------------------------------------------------------------------+ function object_set_visit_module($plugin_id) { $plugin_id = object_type_to_id($plugin_id); if (object_get_visit(Context::getId(), $plugin_id, false, false) < object_get_visit(Context::getId(), 0, false, false)){ object_set_visit(Context::getId(), $plugin_id); } } /** * This function saves the actual time as last visitdate for the given object, user and type * * @param string the id of the object (i.e. seminar_id, news_id, vote_id) * @param string the type of visited object or module (i.e. news, documents, wiki - see /lib/classes/Modules.class.php for definitions) * @param string the user who visited the object - if not given, the actual user is used * */ function object_set_visit($object_id, $plugin_id, $user_id = '') { global $user; $plugin_id = object_type_to_id($plugin_id); if (!$user_id) { $user_id = $user->id; } $last_visit = object_get_visit($object_id, $plugin_id, FALSE, false , $user_id); if ($last_visit === false) { $last_visit = object_get_visit_threshold(); } $query = "INSERT INTO object_user_visits (object_id, user_id, plugin_id, visitdate, last_visitdate) VALUES (?, ?, ?, UNIX_TIMESTAMP(), ?) ON DUPLICATE KEY UPDATE visitdate=UNIX_TIMESTAMP(), last_visitdate=?"; $statement = DBManager::get()->prepare($query); $statement->execute([$object_id, $user_id, $plugin_id, $last_visit, $last_visit]); return object_get_visit($object_id, $plugin_id, FALSE, false, $user_id, true); } /** * This function gets the (last) visit time for an object or module. If no information is found, the last visit of the open-object can bes used * * @param string the id of the object (i.e. seminar_id, news_id, vote_id) * @param string the type of visited object or module (i.e. news, documents, wiki - see /lib/classes/Modules.class.php for definitions OR sem/inst, if the visit for the whole seminar was saved) * @param string the return-mode: 'last' for the last visit, other for actual-visit * @param string the user who visited the object - if not given, the actual user is used * @param string the id of an open-object (seminar or inst), to gather information for last visit from the visit of the whole open-object * @return int the timestamp of the last visit or FALSE * */ function object_get_visit($object_id, $plugin_id, $mode = "last", $open_object_id = '', $user_id = '', $refresh_cache = false) { global $user; static $cache; $plugin_id = object_type_to_id($plugin_id); if (!$user_id) { $user_id = $user->id; } if (!$open_object_id && $open_object_id !== false) { $open_object_id = $object_id; } if ($refresh_cache) { $cache[$object_id][$plugin_id][$user_id] = null; } if (isset($cache[$object_id][$plugin_id][$user_id])) { return $mode == 'last' ? $cache[$object_id][$plugin_id][$user_id]['last_visitdate'] : $cache[$object_id][$plugin_id][$user_id]['visitdate']; } $query = "SELECT visitdate, last_visitdate FROM object_user_visits WHERE object_id = ? AND user_id = ? AND plugin_id = ?"; $statement = DBManager::get()->prepare($query); $statement->execute([$object_id, $user_id, $plugin_id]); $temp = $statement->fetch(PDO::FETCH_ASSOC); if ($temp) { $cache[$object_id][$plugin_id][$user_id] = $temp; return $mode == 'last' ? $temp['last_visitdate'] : $temp['visitdate']; //no visitdate for the object or modul - we have to gather the information from the studip-object (seminar or institute) } elseif ($open_object_id) { $query = "SELECT visitdate, last_visitdate FROM object_user_visits WHERE object_id = ? AND user_id = ? AND plugin_id = 0"; $statement = DBManager::get()->prepare($query); $statement->execute([$open_object_id, $user_id]); $temp = $statement->fetch(PDO::FETCH_ASSOC); if ($temp) { return $mode == 'last' ? $temp['last_visitdate'] : $temp['visitdate']; } else { return object_get_visit_threshold(); } } else { return object_get_visit_threshold(); } } /** * This function gets the (last) visit time for an array of objects. * If no information is found, the last visit of the open-object can bes used * * @param array $object_ids The ids of the objects (i.e. seminar_id, news_id, vote_id) * @param string $type The type of visited objects or module (i.e. news, documents, wiki) * @param string|null $mode The return-mode: 'last' for the last visit, other for actual-visit; * pass null to get an array of visit date and last visit date * @param mixed $user_id User id to gather the data for, pass null for current user * @param array $additional_plugins Additional types to get data for. The returned array is then enlarged * by one dimension * @return array associate array with the object id as key and the according data as value * * @note This function will respect the visit threshold defined in NEW_INDICATOR_THRESHOLD config. */ function get_objects_visits(array $object_ids, $plugin_id, $mode = 'last', $user_id = null, $additional_plugins = []) { $plugin_id = object_type_to_id($plugin_id); // Combine types $plugin_ids = array_merge([$plugin_id], $additional_plugins); // Create result array with predefined values / defined threshold $threshold = object_get_visit_threshold(); $thresholds = array_combine($plugin_ids, array_fill( 0, count($plugin_ids), $mode === null ? ['last_visitdate' => null, 'visitdate' => null] : null )); $result = array_combine( $object_ids, array_fill(0, count($object_ids), $thresholds) ); // Read data from database $query = "SELECT `object_id`, `plugin_id`, `visitdate`, `last_visitdate` FROM `object_user_visits` WHERE `object_id` IN (:ids) AND `plugin_id` IN (:plugin_ids) AND `user_id` = :user_id"; $statement = DBManager::get()->prepare($query); $statement->bindValue(':ids', $object_ids); $statement->bindValue(':plugin_ids', $plugin_ids); $statement->bindValue(':user_id', $user_id ?? $GLOBALS['user']->id); $statement->execute(); $statement->setFetchMode(PDO::FETCH_ASSOC); // Spread data from database into result array foreach ($statement as $row) { if ($mode === null) { $return = [ 'visitdate' => max($threshold, (int) $row['visitdate']), 'last_visitdate' => max($threshold, (int) $row['last_visitdate']), ]; } elseif ($mode === 'last') { $return = max($threshold, (int) $row['last_visitdate']); } else { $return = max($threshold, (int) $row['visitdate']); } $result[$row['object_id']][$row['plugin_id']] = $return; } foreach ($result as $object_id => $plugins) { $seminar_data = $plugins[0]; if ($mode === null && !isset($seminar_data['visitdate'])) { $seminar_data = ['last_visitdate' => $threshold, 'visitdate' => $threshold]; $result[$object_id][0] = $seminar_data; } if ($mode !== null && !isset($seminar_data)) { $seminar_data = $threshold; $result[$object_id][0] = $seminar_data; } foreach ($plugins as $plugin_id => $data) { if ($plugin_id == 0) continue; if ($mode === null) { if (isset($data['visitdate']) || object_id_to_type($plugin_id)) { $result[$object_id][$plugin_id] = [ 'visitdate' => $data['visitdate'] ?? max($threshold, (int)$data['visitdate']), 'last_visitdate' => $data['last_visitdate'] ?? max($threshold, (int)$data['last_visitdate']) ]; } else { $result[$object_id][$plugin_id] = [ 'visitdate' => $data['visitdate'] ?? max($seminar_data['visitdate'], (int)$data['visitdate']), 'last_visitdate' => $data['last_visitdate'] ?? max($seminar_data['last_visitdate'], (int)$data['last_visitdate']) ]; } } elseif ($mode === 'last') { if (isset($data) || object_id_to_type($plugin_id)) { $result[$object_id][$plugin_id] = $data ?? max($threshold, (int)$data); } else { $result[$object_id][$plugin_id] = $data ?? max($seminar_data['last_visitdate'], (int)$data); } } else { if (isset($data) || object_id_to_type($plugin_id)) { $result[$object_id][$plugin_id] = $data ?? max($threshold, (int)$data); } else { $result[$object_id][$plugin_id] = $data ?? max($seminar_data['visitdate'], (int)$data); } } } } // Reduce array if not additional types were passed if (func_num_args() < 5) { // Unfortunately array_column() will dispose the array key $result = array_map(function ($row) use ($plugin_id) { return $row[$plugin_id]; }, $result); } return $result; } /** * This function gets the cutoff value for object visit dates as defined by the NEW_INDICATOR_THRESHOLD setting. * * @return int the timestamp of the oldest possible visit or 0 */ function object_get_visit_threshold() { $threshold = Config::get()->NEW_INDICATOR_THRESHOLD; return $threshold ? strtotime("-{$threshold} days 0:00:00") : 0; } function object_kill_visits($user_id, $object_ids = false) { if (!$user_id && !$object_ids) { return false; } $query = "DELETE FROM object_user_visits WHERE "; $parameters = []; if ($user_id) { $query .= "user_id = ?"; $parameters[] = $user_id; } else { $query .= "1"; } if ($object_ids) { if (!is_array($object_ids)) { $object_ids = [$object_ids]; } $query .= " AND object_id IN (?)"; $parameters[] = $object_ids; } $statement = DBManager::get()->prepare($query); $statement->execute($parameters); return $statement->rowCount(); } function object_add_view ($object_id) { $count_view = !in_array($object_id, $_SESSION['object_cache']); if (!$count_view) { return; } $_SESSION['object_cache'][] = $object_id; $query = "INSERT INTO object_views (object_id, views, chdate) VALUES (?, 1, UNIX_TIMESTAMP()) ON DUPLICATE KEY UPDATE views = views + 1, chdate = UNIX_TIMESTAMP()"; $statement = DBManager::get()->prepare($query); $statement->execute([$object_id]); $query = "SELECT views FROM object_views WHERE object_id = ?"; $statement = DBManager::get()->prepare($query); $statement->execute([$object_id]); return $statement->fetchColumn(); } function object_kill_views($object_id) { if (!empty($object_id)) { $query = "DELETE FROM object_views WHERE object_id IN (?)"; $statement = DBManager::get()->prepare($query); $statement->execute([$object_id]); return $statement->rowCount(); } else { return 0; } } function object_return_views ($object_id) { $query = "SELECT views FROM object_views WHERE object_id = ?"; $statement = DBManager::get()->prepare($query); $statement->execute([$object_id]); return $statement->fetchColumn() ?: 0; } /** * converts a ouv type to an id * @param $type string former used type of visited objects or module (i.e. news, documents, wiki) * @return ?int */ function object_type_to_id($type) { if (is_numeric($type)) { return $type; } $ouv_mapping = [ 'sem' => 0, 'inst'=> 0, 'basicdata' => 0, 'vote' => -1, 'news' => 'CoreOverview', 'documents' => 'CoreDocuments', 'schedule' => 'CoreSchedule', 'scm' => 'CoreScm', 'wiki' => 'CoreWiki', 'elearning_interface' => 'CoreElearningInterface', 'ilias_interface' => 'IliasInterfaceModule', 'participants' => 'CoreParticipants' ]; if (isset($ouv_mapping[$type])) { $id = $ouv_mapping[$type]; if (is_numeric($id)) { return $id; } $plugin = PluginEngine::getPlugin($id); if ($plugin) { return $plugin->getPluginId(); } } return null; } /** * converts a plugin id to old ouv type * @param $id int former used type of visited objects or module (i.e. news, documents, wiki) * @return string */ function object_id_to_type($id) { if (!is_numeric($id)) { return null; } $ouv_mapping = [ 'sem' => 0, 'inst'=> 0, 'basicdata' => 0, 'vote' => -1, 'news' => 'CoreOverview', 'documents' => 'CoreDocuments', 'schedule' => 'CoreSchedule', 'scm' => 'CoreScm', 'wiki' => 'CoreWiki', 'elearning_interface' => 'CoreElearningInterface', 'ilias_interface' => 'IliasInterfaceModule', 'participants' => 'CoreParticipants' ]; if (!in_array($id, [0, -1, -2])) { $plugin = PluginManager::getInstance()->getPluginInfoById($id); if ($plugin) { $search = $plugin['class']; } } else { $search = (int)$id; } if (isset($search)) { return array_search($search, $ouv_mapping, true) ?: null; } else { return null; } }