Select Git revision
ResponsiveHelper.php
Forked from
Stud.IP / Stud.IP
Source project has a limited visibility.
-
Jan-Hendrik Willms authored
Closes #1911 Merge request studip/studip!1255
Jan-Hendrik Willms authoredCloses #1911 Merge request studip/studip!1255
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ResponsiveHelper.php 10.05 KiB
<?php
/**
* ResponsiveHelper.php
*
* This class collects helper methods for Stud.IP's responsive design.
*
* @author Jan-Hendrik Willms <tleilax+studip@gmail.com>
* @license GPL2 or any later version
* @copyright Stud.IP core group
* @since Stud.IP 3.2
*/
class ResponsiveHelper
{
/**
* Returns the current navigation as an array.
*
* @return Array containing the navigation
*/
public static function getNavigationArray()
{
$navigation = [];
$activated = [];
$link_params = array_fill_keys(array_keys(URLHelper::getLinkParams()), null);
foreach (Navigation::getItem('/')->getSubNavigation() as $path => $nav) {
$image = $nav->getImage();
$forceVisibility = false;
/*
* Special treatment for "browse" navigation which is normally hidden
* when we are inside a course.
*/
if ($path === 'browse' && !$image) {
$image = Icon::create('seminar');
$forceVisibility = true;
}
/*
* Special treatment for "footer" navigation because
* the real footer is hidden in responsive view.
*/
if ($path === 'footer' && !$image) {
$image = Icon::create('info');
$nav->setTitle(_('Impressum & Information'));
$forceVisibility = true;
}
$image_src = $image ? $image->copyWithRole('info_alt')->asImagePath() : false;
$item = [
'icon' => $image_src ? self::getAssetsURL($image_src) : false,
'title' => (string) $nav->getTitle(),
'url' => URLHelper::getURL($nav->getURL(), $link_params, true),
'parent' => '/',
'path' => $path,
'visible' => $forceVisibility ? true : $nav->isVisible(true),
'active' => $nav->isActive()
];
if ($nav->isActive()) {
// course navigation is integrated in course sub-navigation items
if ($path === 'course') {
$activated[] = 'browse/my_courses/' . (Context::get()->getId());
} else {
$activated[] = $path;
}
}
if ($nav->getSubnavigation() && $path != 'start') {
$item['children'] = self::getChildren($nav, $path, $activated);
}
if ($path !== 'course') {
$navigation[$path] = $item;
}
}
return [$navigation, $activated];
}
/**
* Returns the navigation object required for the Vue.js component.
*
* The object will always contain the currently selected navigation path.
* Besides that, the object may contain the whole navigation and a hash
* for that navigation. If a hash is passed and it matches the currently
* genereated hash, the navigation and hash will be omitted from the
* response for performance reasons. We don't want to include the large
* navigation object in every response.
*
* @return array
*/
public static function getNavigationObject(string $stored_hash = null): array
{
[$navigation, $activated] = self::getNavigationArray();
$hash = md5(json_encode($navigation));
$response = compact('activated');
if ($stored_hash !== $hash) {
$response = array_merge($response, compact('navigation', 'hash'));
}
return $response;
}
/**
* Recursively build a navigation array from the subnavigation/children
* of a navigation object.
*
* @param Navigation $navigation The navigation object
* @param String $path Current path segment
* @param array $activated Activated items
* @param String|null $cid Optional context ID
* @return Array containing the children (+ grandchildren...)
*/
protected static function getChildren(Navigation $navigation, $path, &$activated = [], string $cid = null)
{
$children = [];
foreach ($navigation->getSubNavigation() as $subpath => $subnav) {
/*if (!$subnav->isVisible()) {
continue;
}*/
$originalSubpath = $subpath;
$subpath = "{$path}/{$subpath}";
$item = [
'title' => (string) $subnav->getTitle(),
'url' => URLHelper::getURL($subnav->getURL(), $cid ? ['cid' => $cid] : []),
'parent' => $path,
'path' => $subpath,
'visible' => $subnav->isVisible(),
'active' => $subnav->isActive()
];
if ($subnav->isActive()) {
// course navigation is integrated in course sub-navigation items
if ($path === 'course') {
$activated[] = 'browse/my_courses/' . Context::get()->getId() . '/' . $originalSubpath;
} else {
$activated[] = $subpath;
}
}
if ($subnav->getSubNavigation()) {
$item['children'] = self::getChildren($subnav, $subpath);
}
if ($subpath === 'browse/my_courses') {
$item['children'] = array_merge($item['children'] ?? [], static::getMyCoursesNavigation($activated));
}
$children[$subpath] = $item;
}
return $children;
}
/**
* Try to get a compressed version of the passed navigation url.
* The URL is processed is processed by URLHelper and the absolute uri
* of the Stud.IP installation is stripped from it afterwards.
*
* @param String $url The url to compress
* @return String containing the compressed url
*/
protected static function getURL($url, $params = [])
{
return str_replace($GLOBALS['ABSOLUTE_URI_STUDIP'], '', URLHelper::getURL($url, $params));
}
/**
* Try to get a compressed version of the passed assets url.
* The absolute uri of the Stud.IP installation is stripped from the url.
*
* @param String $url The assets url to compress
* @return String containing the compressed assets url
*/
protected static function getAssetsURL($url)
{
return str_replace($GLOBALS['ASSETS_URL'], '', $url);
}
/**
* Specialty for responsive navigation: build navigation items
* for my courses in current semester.
*
* @return array
*/
protected static function getMyCoursesNavigation($activated): array
{
if (!$GLOBALS['perm']->have_perm('admin')) {
$sem_data = Semester::getAllAsArray();
$currentIndex = -1;
foreach ($sem_data as $index => $semester) {
if (!empty($semester['current'])) {
$currentIndex = $index;
break;
}
}
$params = [
'deputies_enabled' => Config::get()->DEPUTIES_ENABLE
];
$courses = MyRealmModel::getCourses($currentIndex, $currentIndex, $params);
} else {
$courses = [];
}
$items = [];
$standardIcon = Icon::create('seminar', Icon::ROLE_INFO_ALT)->asImagePath();
// Add current course to list.
if (Context::get() && Context::isCourse()) {
$courses[] = Context::get();
}
foreach ($courses as $course) {
$avatar = CourseAvatar::getAvatar($course->id);
if ($avatar->is_customized()) {
$icon = $avatar->getURL(Avatar::SMALL);
} else {
$icon = $standardIcon;
}
$cnav = [
'icon' => $icon,
'title' => $course->getFullname(),
'url' => URLHelper::getURL('dispatch.php/course/details', ['cid' => $course->id]),
'parent' => 'browse/my_courses',
'path' => 'browse/my_courses/' . $course->id,
'visible' => true,
'active' => Course::findCurrent() ? Course::findCurrent()->id === $course->id : false,
'children' => []
];
foreach ($course->tools as $tool) {
if (Seminar_Perm::get()->have_studip_perm($tool->getVisibilityPermission(), $course->id)) {
$path = 'browse/my_courses/' . $course->id;
$studip_module = $tool->getStudipModule();
if ($studip_module instanceof StudipModule) {
$tool_nav = $studip_module->getTabNavigation($course->id) ?: [];
foreach ($tool_nav as $nav_name => $navigation) {
if ($nav_name && is_a($navigation, 'Navigation')) {
$cnav['children'][$path . '/' . $nav_name] = [
'icon' => $navigation->getImage() ? $navigation->getImage()->asImagePath() : '',
'title' => $tool->getDisplayname(),
'url' => URLHelper::getURL($navigation->getURL(), ['cid' => $course->id]),
'parent' => 'browse/my_courses/' . $course->id,
'path' => 'browse/my_courses/' . $course->id . '/' . $nav_name,
'visible' => true,
'active' => $navigation->isActive(),
'children' => static::getChildren(
$navigation,
'browse/my_courses/' . $course->id . '/' . $nav_name,
$activated,
$course->id
),
];
}
}
}
}
}
$items['browse/my_courses/' . $course->id] = $cnav;
}
return $items;
}
}