* @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 * @category Stud.IP * @since 2.4 */ require_once 'lib/messaging.inc.php'; require_once 'lib/object.inc.php'; require_once 'lib/statusgruppe.inc.php'; require_once 'lib/user_visible.inc.php'; class ProfileController extends AuthenticatedController { public function before_filter(&$action, &$args) { parent::before_filter($action, $args); Navigation::activateItem('/profile/index'); URLHelper::addLinkParam('username', Request::username('username')); PageLayout::setHelpKeyword('Basis.Homepage'); // current logged in user $this->user = User::findCurrent(); // perms of current logged in user $this->perm = $GLOBALS['perm']; // current selected user $this->current_user = User::findByUsername(Request::username( 'username', $this->user ? $this->user->username : null )); // set the page title depending on user selection if ( isset($this->user, $this->current_user) && $this->current_user->id === $this->user->id && !$this->current_user->locked ) { PageLayout::setTitle(_('Mein Profil')); UserConfig::get($this->user->id)->store('PROFILE_LAST_VISIT', time()); } elseif ( !empty($this->current_user->id) && ( $this->perm->have_perm('root') || ( !$this->current_user->locked && get_visibility_by_id($this->current_user->id) ) ) ) { PageLayout::setTitle(_('Profil von') . ' ' . $this->current_user->getFullName()); object_add_view($this->current_user->id); } else { PageLayout::setTitle(_('Profil')); $action = 'not_available'; } } /** * Entry point of the controller that displays all the information of the selected or current user * @return void */ public function index_action() { // Template Index_Box for render-partials $layout = $GLOBALS['template_factory']->open('shared/content_box'); $this->shared_box = $layout; // if he has not yet stored into user_info, he comes in with no values if ($this->current_user->mkdate === null) { $this->current_user->store(); } if (Config::get()->NEWS_RSS_EXPORT_ENABLE) { $news_author_id = StudipNews::GetRssIdFromUserId($this->current_user->user_id); if ($news_author_id) { PageLayout::addHeadElement('link', [ 'rel' => 'alternate', 'type' => 'application/rss+xml', 'title' => 'RSS', 'href' => 'rss.php?id=' . $news_author_id, ]); } } // GetScroreList if (Config::get()->SCORE_ENABLE) { if ($this->current_user->user_id === $GLOBALS['user']->id || $this->current_user->score) { $this->score = Score::GetMyScore($this->current_user); $this->score_title = Score::getTitel($this->score, $this->current_user->geschlecht); } } // Additional user information $this->public_email = get_visible_email($this->current_user->user_id); $this->motto = $this->getVisibilityValue('motto'); $this->private_nr = $this->getVisibilityValue('privatnr', 'private_phone'); $this->private_cell = $this->getVisibilityValue('privatcell', 'private_cell'); $this->privadr = $this->getVisibilityValue('privadr', 'privadr'); $this->homepage = $this->getVisibilityValue('Home', 'homepage'); // skype informations $this->skype_name = ''; if (Config::get()->ENABLE_SKYPE_INFO && Visibility::verify('skype_name', $this->current_user->user_id)) { $this->skype_name = UserConfig::get($this->current_user->user_id)->SKYPE_NAME; } // get generic datafield entries $this->shortDatafields = $this->getShortDatafields(); $this->longDatafields = $this->getLongDatafields(); // get working station of an user (institutes) $this->institutes = $this->getInstitutInformation(); // get studying informations of an user $this->study_institutes = []; if ($this->current_user->perms !== 'dozent') { if (count($this->current_user->institute_memberships) > 0 && Visibility::verify('studying', $this->current_user->user_id)) { $study_institutes = $this->current_user->institute_memberships->filter(function ($a) { return $a->inst_perms === 'user'; }); $this->study_institutes = $study_institutes; } } $show_admin = ($this->perm->have_perm('autor') && $this->user->user_id == $this->current_user->user_id) || (Deputy::isEditActivated() && Deputy::isDeputy($this->user->user_id, $this->current_user->user_id, true)); if (Visibility::verify('news', $this->current_user->user_id) || $show_admin) { $response = $this->relayWithRedirect('news/display/' . $this->current_user->user_id); $this->news = $response->body; } // calendar if ( Config::get()->CALENDAR_ENABLE && !in_array($this->current_user->perms, ['admin', 'root']) && Visibility::verify('termine', $this->current_user->user_id) ) { $start = time(); $end = strtotime('+1 week 23:59:59'); $response = $this->relay('calendar/contentbox/display/' . $this->current_user->user_id . '/' . ($end - $start)); $this->dates = $response->body; } // include and show votes and tests if (Config::get()->VOTE_ENABLE && Visibility::verify('votes', $this->current_user->user_id)) { $response = $this->relay('questionnaire/widget/' . $this->current_user->user_id . "/user"); $this->questionnaires = $response->body; } // Hier werden Lebenslauf, Hobbys, Publikationen und Schwerpunkte ausgegeben: $ausgabe_felder = [ 'lebenslauf' => _('Lebenslauf'), 'hobby' => _('Hobbys'), 'publi' => _('Publikationen'), 'schwerp' => _('Schwerpunkte'), ]; $ausgabe_inhalt = []; foreach ($ausgabe_felder as $key => $value) { if (Visibility::verify($key, $this->current_user->user_id)) { $ausgabe_inhalt[$value] = $this->current_user[$key]; } } $this->ausgabe_inhalt = array_filter($ausgabe_inhalt, function ($item) { return (string)$item; }); //public folders $folders = Folder::findBySQL("range_type='user' AND range_id = ? AND folder_type = 'PublicFolder'", [$this->current_user->user_id]); $public_files = []; $public_folders =[]; foreach ($folders as $folder) { $one_public_folder = $folder->getTypedFolder(); if ($one_public_folder->viewable) { //We don't need to fetch all files recursively, //since we have collected all public folders above already. $folder_file_refs = $one_public_folder->getFiles(); foreach ($folder_file_refs as $file_ref) { if ($one_public_folder->isFileDownloadable($file_ref->id, $GLOBALS['user']->id)) { $public_files[$file_ref->id] = $file_ref; } } $public_folders[$one_public_folder->id] = $one_public_folder; } } if (count($public_files)) { $this->public_files = $public_files; $this->public_folders = $public_folders; } // Anzeige der Seminare, falls User = dozent if ($this->current_user['perms'] == 'dozent') { $this->seminare = array_filter($this->getTeacherSeminars()); } // Hompageplugins $homepageplugins = PluginEngine::getPlugins(HomepagePlugin::class); $render = ''; $layout = $GLOBALS['template_factory']->open('shared/content_box'); foreach ($homepageplugins as $homepageplugin) { if ($homepageplugin->isActivated($this->current_user->user_id, 'user')) { // get homepageplugin tempaltes $template = $homepageplugin->getHomepageTemplate($this->current_user->user_id); // create output of the plugins if (!empty($template)) { $render .= $template->render(layout: $layout); } $layout->clear_attributes(); } } $this->hompage_plugin = $render; // get categories $category = Kategorie::findByUserId($this->current_user->user_id); foreach ($category as $cat) { $head = $cat->name; $body = $cat->content; $vis_text = ''; if ($this->user->user_id == $this->current_user->user_id) { $vis_text .= ' (' . Visibility::getStateDescription('kat_' . $cat->kategorie_id) . ')'; } if (Visibility::verify('kat_' . $cat->kategorie_id, $this->current_user->user_id)) { $categories[$cat->kategorie_id]['head'] = $head; $categories[$cat->kategorie_id]['zusatz'] = $vis_text; $categories[$cat->kategorie_id]['content'] = $body; } } if (!empty($categories)) { $this->categories = array_filter($categories, function ($item) { return !empty($item['content']); }); } $sidebar = Sidebar::Get(); //The profile avatar, profile visits and profile score //shall be visible in the sidebar. Therefore we must construct //a generic WidgetElement object and its HTML in here. $kings = []; if (Config::Get()->SCORE_ENABLE) { if ($this->current_user->user_id === $GLOBALS['user']->id || $this->current_user->score) { $kings = $this->current_user->getStudipKingIcon(); } } $avatar_widget = new TemplateWidget( $this->current_user->getFullName(), $this->get_template_factory()->open('profile/widget-avatar.php'), [ 'avatar' => Avatar::getAvatar($this->current_user->user_id), 'kings' => $kings, 'views' => object_return_views($this->current_user->user_id), 'score' => $this->score, 'score_title' => $this->score_title, 'current_user' => $this->current_user->user_id ] ); $avatar_widget->setTitle($this->current_user->getFullName()); $sidebar->addWidget($avatar_widget); $actions = new ActionsWidget(); //If a user visits the profile of another user //we add a few more actions to the sidebar: if ($this->current_user->username != $this->user->username) { if ($GLOBALS['perm']->have_perm('root')) { $actions->addLink( _('Dieses Konto bearbeiten'), $this->url_for('admin/user/edit/' . $this->current_user->user_id), Icon::create('edit', attributes: tooltip2(_('Dieses Konto bearbeiten'))) ); } if (!$this->user->isFriendOf($this->current_user)) { $actions->addLink( _('Zu den Kontakten hinzufügen'), $this->url_for('profile/add_buddy?username=' . $this->current_user->username), Icon::create('add', attributes: tooltip2(_('Zu den Kontakten hinzufügen'))), ['data-confirm' => _('Wollen Sie die Person wirklich als Kontakt hinzufügen?')] )->asButton(); } else { $actions->addLink( _('Von den Kontakten entfernen'), $this->url_for('profile/remove_buddy', ['username' => $this->current_user->username]), Icon::create('trash', attributes: tooltip2(_('Zu den Kontakten hinzufügen'))), ['data-confirm' => _('Wollen Sie die Person wirklich von den Kontakten entfernen?')] )->asButton(); } $actions->addLink( _('Nachricht schreiben'), $this->url_for('messages/write', ['rec_uname' => $this->current_user->username]), Icon::create('mail', attributes: tooltip2(_('Nachricht an Nutzer verschicken'))) )->asDialog('size="50%"'); if (class_exists('Blubber')) { $actions->addLink( _('Anblubbern'), URLHelper::getURL('dispatch.php/blubber/write_to/'.$this->current_user->user_id), Icon::create('blubber'), ['title' => _('Blubber diesen Nutzer an')] )->asDialog(); } } $actions->addLink( _('vCard herunterladen'), $this->url_for('contact/vcard', ['user[]' => $this->current_user->username]), Icon::create('vcard', attributes: tooltip2(_('vCard herunterladen'))) ); $sidebar->addWidget($actions); $privacy = new LinksWidget(); $privacy->setTitle(_('Datenschutz')); if (Privacy::isVisible($this->current_user->user_id)) { $privacy->addLink( _('Anzeige Personendaten'), $this->url_for('privacy/landing/' . $this->current_user->user_id), Icon::create('log') )->asDialog('size=medium'); $privacy->addLink( _('Personendaten drucken'), $this->url_for('privacy/print/' . $this->current_user->user_id), Icon::create('print'), ['class' => 'print_action', 'target' => '_blank'] ); $privacy->addLink( _('Export Personendaten als CSV'), $this->url_for('privacy/export/' . $this->current_user->user_id), Icon::create('file-text') ); $privacy->addLink( _('Export Personendaten als XML'), $this->url_for('privacy/xml/' . $this->current_user->user_id), Icon::create('file-text') ); $privacy->addLink( _('Export persönlicher Dateien als ZIP'), $this->url_for('privacy/filesexport/' . $this->current_user->user_id), Icon::create('file-archive') ); } elseif ($this->current_user->username === $this->user->username && Config::get()->PRIVACY_CONTACT) { $privacy->addLink( _('Datenschutzauskunft anfordern'), $this->url_for('privacy/askfor/' . $this->current_user->user_id), Icon::create('mail') )->asDialog('size=auto'); } $sidebar->addWidget($privacy); $info_widget = new SidebarWidget(); $info_widget->setTitle(_('Informationen')); if (!get_visibility_by_id($this->current_user->user_id)) { if ($this->current_user->user_id !== $this->user->user_id) { $string = _('(Dieser Nutzer ist unsichtbar.)'); } else { $string = _('(Sie sind unsichtbar. Deshalb können nur Sie diese Seite sehen.)'); } $info_widget->addElement( new WidgetElement('' . $string . '') ); } if ($GLOBALS['perm']->have_perm('root') && $this->current_user['locked']) { $info_widget->addElement( new WidgetElement('' . _('BENUTZER IST GESPERRT!') . '') ); } if ($this->current_user->auth_plugin === null) { $info_widget->addElement( new WidgetElement('' . _('vorläufiger Benutzer') . '') ); } if (count($info_widget->getElements())) { $sidebar->addWidget($info_widget); } if ($this->motto) { $motto_widget = new SidebarWidget(); $motto_widget->setTitle(_('Motto')); $motto_widget->addElement(new WidgetElement(htmlReady($this->motto))); $sidebar->addWidget($motto_widget); } } /** * Action for a selection, where the user not exists * * @return void */ public function not_available_action() { Navigation::getItem('/profile')->setActive(false); } /** * Adds the user identified by the variable username to the current user's * contacts. */ public function add_buddy_action() { CSRFProtection::verifyUnsafeRequest(); $username = Request::username('username'); $user = User::findByUsername($username); $current = User::findCurrent(); $current->contacts[] = $user; $current->store(); PageLayout::postSuccess(_('Der Nutzer wurde zu Ihren Kontakten hinzugefügt.')); $this->redirect('profile/index?username=' . $username); } /** * Removes the user identified by the variable username from the current * user's contacts. */ public function remove_buddy_action() { CSRFProtection::verifyUnsafeRequest(); $username = Request::username('username'); $current = User::findCurrent(); $contact = Contact::find([$current->id, User::findByUsername($username)->id]); if ($contact && $contact->delete()) { PageLayout::postSuccess(_('Der Kontakt wurde entfernt.')); } $this->redirect('profile/index?username=' . $username); } /** * Returns user-institutes * @return mixed */ private function getInstitutInformation() { $institutes = $this->current_user->institute_memberships->filter(function ($member) { return $member->inst_perms !== 'user' && $member->visible; }); $institutes = $institutes->orderBy('priority asc'); $institutes = $institutes->toArray(); foreach ($institutes as $id => $institute) { $entries = DataFieldEntry::getDataFieldEntries([ $this->current_user->user_id, $institute['institut_id'], ]); foreach ($entries as $entry) { $view = $entry->isVisible(null, false); $show_star = false; if (!$view && $entry->isVisible()) { $view = true; $show_star = true; } if (trim($entry->getValue()) && $view) { $institutes[$id]['datafield'][] = [ 'name' => $entry->getName(), 'value' => $entry->getDisplayValue(), 'show_star' => $show_star, ]; } } $groups = GetAllStatusgruppen( $institute['institut_id'], $this->current_user->user_id ); $default_entries = $entries; $data = get_role_data_recursive( $groups, $this->current_user->user_id, $default_entries ); $institutes[$id]['role'] = $data; } return $institutes; } public function extern_action(ExternalUser $external_user) { PageLayout::setTitle(sprintf(_('Profil von %s'), $external_user['name'])); $this->user = $external_user; } /** * Collect user datafield informations * * @return array */ private function getDatafields(): array { $short_datafields = []; $long_datafields = []; foreach (DataFieldEntry::getDataFieldEntries($this->current_user->user_id, 'user') as $entry) { if ($entry->isVisible() && $entry->getDisplayValue() && Visibility::verify($entry->getID(), $this->current_user->user_id)) { if ($entry instanceof DataFieldTextareaEntry) { $long_datafields[] = $entry; } else { $short_datafields[] = $entry; } } } return [ 'long' => $long_datafields, 'short' => $short_datafields, ]; } /** * Filter long datafiels from the datafields * * @return array */ private function getLongDatafields(): array { $datafields = $this->getDatafields(); $array = []; if (!empty($datafields)) { foreach ($datafields['long'] as $entry) { $array[(string)$entry->getName()] = [ 'content' => $entry->getDisplayValue(), 'visible' => '(' . $entry->getPermsDescription() . ')', ]; } } return $array; } /** * Filter short datafiels from the datafields * * @return array */ private function getShortDatafields(): array { $shortDatafields = $this->getDatafields(); $array = []; if (!empty($shortDatafields)) { foreach ($shortDatafields['short'] as $entry) { $array[(string)$entry->getName()] = [ 'content' => $entry->getDisplayValue(), 'visible' => '(' . $entry->getPermsDescription() . ')', ]; } } return $array; } /** * Creates an array with all seminars * * @return array */ private function getTeacherSeminars(): array { $courses = []; $semester = []; $next_semester = Semester::findNext(); $current_semester = Semester::findCurrent(); $previous_semester = Semester::findPrevious(); if ($next_semester) { $semester[$next_semester->id] = $next_semester; } if ($current_semester) { $semester[$current_semester->id] = $current_semester; } if ($previous_semester) { $semester[$previous_semester->id] = $previous_semester; } $field = 'name'; if (Config::get()->IMPORTANT_SEMNUMBER) { $field = "veranstaltungsnummer,{$field}"; } $allcourses = new SimpleCollection( Course::findBySQL( "INNER JOIN seminar_user USING(Seminar_id) WHERE user_id=? AND seminar_user.status='dozent' AND seminare.visible=1", [ $this->current_user->id ] ) ); foreach (array_filter($semester) as $one) { $courses[(string) $one->name] = $allcourses->filter(function ($c) use ($one) { if (Config::get()->HIDE_STUDYGROUPS_FROM_PROFILE && $c->isStudygroup()) { return false; } if (!$c->isOpenEnded()) { return $c->isInSemester($one); } elseif ($one->isCurrent()) { return $c; } return false; })->orderBy($field); if (!$courses[(string) $one->name]->count()) { unset($courses[(string) $one->name]); } } return $courses; } /** * Get the homepagevisibilities * * @return array */ private function getHomepageVisibilities(): array { $visibilities = get_local_visibility_by_id( $this->current_user ? $this->current_user->id : null, 'homepage' ); if (is_array(json_decode($visibilities, true))) { return json_decode($visibilities, true); } return []; } /** * Returns the visibility value */ private function getVisibilityValue(string $param, string $visibility = ''): mixed { if (Visibility::verify($visibility ?: $param, $this->current_user->user_id)) { return $this->current_user->$param; } return false; } }