/srv/www/bgphoenics2.invorbereitung.de/ilias/Core/TwigComponents/Classes/Components/Favourites.php
<?php
namespace SeminarCatalog\Core\TwigComponents\Components;
use SeminarCatalog\Core\Object\Manager\ObjectManager;
use SeminarCatalog\Core\Seminar\Model\Seminar;
use SeminarCatalog\Core\TwigComponents\Base\TwigComponent;
use SeminarCatalog\Core\User\Model\CurrentUser;
class Favourites extends TwigComponent
{
protected Seminar $seminar;
public function getContext(): array
{
$favouriteList = ObjectManager::get(CurrentUser::class)->getFavouritesIdList();
return [
'id' => uniqid(),
'seminar' => $this->seminar,
'favouriteList' => $favouriteList,
];
}
}
Arguments
"Class "SeminarCatalog\Core\TwigComponents\Base\TwigComponent" not found"
/srv/www/bgphoenics2.invorbereitung.de/ilias/vendor/composer/ClassLoader.php
/**
* @return void
*/
private static function initializeIncludeClosure()
{
if (self::$includeFile !== null) {
return;
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
*/
self::$includeFile = \Closure::bind(static function($file) {
include $file;
}, null, null);
}
}
/srv/www/bgphoenics2.invorbereitung.de/ilias/vendor/composer/ClassLoader.php
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
$includeFile = self::$includeFile;
$includeFile($file);
return true;
}
return null;
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
Arguments
"/srv/www/bgphoenics2.invorbereitung.de/ilias/vendor/composer/../../Core/TwigComponents/Classes/Components/Favourites.php"
[internal]
Arguments
"SeminarCatalog\Core\TwigComponents\Components\Favourites"
/srv/www/bgphoenics2.invorbereitung.de/ilias/Core/Object/Classes/Manager/ObjectManager.php
*/
class ObjectManager implements ObjectManagerInterface
{
/**
* @var array<class-string,Callable> $factories
*/
protected static array $factories = [];
/**
* @var array<class-string,ObjectFactoryInterface> $factories
*/
protected static array $factoriesInstance = [];
protected static bool $testMode = false;
public static function has(string $className) : bool {
$className = self::mapClass($className);
return class_exists($className) || interface_exists($className);
}
/**
* @template Type
* @param class-string<Type> $className
* @param list<mixed> $constructorArguments
* @return Type
*/
public static function get(string $className, array $constructorArguments = []) {
$className = self::mapClass($className);
$instance = self::getInstanceVariable($className, $constructorArguments);
if (method_exists($instance, '__inject')) {
self::injectDependencies($instance);
}
return $instance;
}
Arguments
"SeminarCatalog\Core\TwigComponents\Components\Favourites"
/srv/www/bgphoenics2.invorbereitung.de/ilias/classes/Service/Wrapper/TwigTemplate.php
public function renderBlock($name, array $context, array $blocks = [], $useBlocks = true): string
{
$template = $this->base->renderBlock($name, $context, $blocks, $useBlocks);
return $this->parseSemiTags($template);
}
private function parseSemiTags(string $template): string
{
// modifier 's' makes, that the dot also matches newlines
if (preg_match_all('/<xsem:(\S+)[^>]*>(.*?)<\/xsem:\1>/s', $template, $matches)) {
for ($i = 0; $i < count($matches[0]); $i++) {
$componentName = $matches[1][$i];
$content = $matches[2][$i] ?? "";
$completeTag = $matches[0][$i];
$componentName = str_replace(':', '\\', $componentName);
$class = '\SeminarCatalog\Core\TwigComponents\Components\\' . $componentName;
if (!ObjectManager::has($class)) {
continue;
}
$component = ObjectManager::get($class, [ $this->twig->getGlobals()['controller'] ]);
if (!$component instanceof TwigComponent) {
continue;
}
$arguments = $this->parseArguments($completeTag);
$frontendArguments = [];
foreach ($arguments as $argument) {
$key = $argument['key'];
$value = $argument['value'];
if (is_string($value) && str_starts_with($value, '_context_pass_')) {
$contextKey = substr($value, 14);
$value = $this->twig->getPassContext()[$contextKey];
}
$property = UtilityService::kebabToCamelCase($key);
if (property_exists($component, $property)) {
$setter = 'set' . ucfirst($property);
Arguments
"SeminarCatalog\Core\TwigComponents\Components\Favourites"
/srv/www/bgphoenics2.invorbereitung.de/ilias/classes/Service/Wrapper/TwigTemplate.php
public function getDebugInfo(): array
{
return $this->base->getDebugInfo();
}
public function getSourceContext(): Source
{
return $this->base->getSourceContext();
}
protected function doDisplay(array $context, array $blocks = []): Traversable|array
{
return $this->base->doDisplay($context, $blocks);
}
public function render(array $context = []): string
{
$template = $this->base->render($context);
return $this->parseSemiTags($template);
}
public function renderBlock($name, array $context, array $blocks = [], $useBlocks = true): string
{
$template = $this->base->renderBlock($name, $context, $blocks, $useBlocks);
return $this->parseSemiTags($template);
}
private function parseSemiTags(string $template): string
{
// modifier 's' makes, that the dot also matches newlines
if (preg_match_all('/<xsem:(\S+)[^>]*>(.*?)<\/xsem:\1>/s', $template, $matches)) {
for ($i = 0; $i < count($matches[0]); $i++) {
$componentName = $matches[1][$i];
$content = $matches[2][$i] ?? "";
$completeTag = $matches[0][$i];
$componentName = str_replace(':', '\\', $componentName);
$class = '\SeminarCatalog\Core\TwigComponents\Components\\' . $componentName;
Arguments
"""
<style>\n
.tab-notice-danger {\n
color: var(--il-danger-color);\n
}\n
\n
.tab-notice-warning {\n
color: var(--warning-color);\n
}\n
div.il_HeaderInner {\n
/*Removes ilias header, since we render an semi header*/\n
display: none !important;\n
}\n
\n
#xsem.backend #xsemTopArea #xsemTopWrapper #xsemTabs .nav.nav-tabs > li#xsemMenuDropdownToggler div.xsem-menu-dropdown-menu {\n
padding: 10px;\n
}\n
\n
#xsem.backend #xsemTopArea #xsemTopWrapper #xsemTabs .nav.nav-tabs > li#xsemMenuDropdownToggler div.xsem-menu-dropdown-menu {\n
display: none;\n
}\n
#xsem.backend #xsemTopArea #xsemTopWrapper #xsemTabs .nav.nav-tabs > li#xsemMenuDropdownToggler.show div.xsem-menu-dropdown-menu,\n
#xsem.backend #xsemTopArea #xsemTopWrapper #xsemTabs .nav.nav-tabs > li#xsemMenuDropdownToggler.open div.xsem-menu-dropdown-menu {\n
display: flex;\n
}\n
\n
#xsem.backend #xsemTopArea #xsemTopWrapper #xsemTabs .nav.nav-tabs > li#xsemMenuDropdownToggler.active a {\n
background-color: #fff;\n
color: var(--main-color) !important;\n
}\n
\n
#xsem.backend #xsemTopArea #xsemTopWrapper #xsemTabs .nav.nav-tabs > li#xsemMenuDropdownToggler.active a span.caret {\n
color: var(--main-color) !important;\n
}\n
\n
#xsem.backend #xsemTopArea #xsemTopWrapper #xsemTabs .nav.nav-tabs > li#xsemMenuDropdownToggler div.xsem-menu-dropdown-menu .dropdown-item {\n
color: var(--darkblue) !important;\n
display: block;\n
}\n
\n
#xsem.backend #xsemTopArea #xsemTopWrapper #xsemTabs .nav.nav-tabs > li#xsemMenuDropdownToggler div.xsem-menu-dropdown-menu .dropdown-item:not(:first-child) {\n
margin-top: 10px;\n
}\n
\n
#xsem.backend #xsemTopArea #xsemTopWrapper #xsemTabs .nav.nav-tabs > li#xsemMenuDropdownToggler div.xsem-menu-dropdown-menu .dropdown-item.active {\n
font-weight: bold;\n
}\n
</style>\n
<svg width="20px" height="20px" viewBox="0 -0.5 33 33" display="none">\n
<g id="Vivid.JS" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="scale(1)">\n
<g id="Vivid-Icons" transform="translate(-903.000000, -411.000000)" fill="currentColor">\n
<g id="Icons" transform="translate(37.000000, 169.000000)">\n
<g id="star" transform="translate(858.000000, 234.000000)">\n
<g transform="translate(7.000000, 8.000000)" id="Shape">\n
<polygon\n
points="27.865 31.83 17.615 26.209 7.462 32.009 9.553 20.362 0.99 12.335 12.532 10.758 17.394 0 22.436 10.672 34 12.047 25.574 20.22">\n
</polygon>\n
</g>\n
</g>\n
</g>\n
</g>\n
</g>\n
</svg>\n
<div id="xsemTopArea" class="">\n
<nav aria-label="Brotkrumen" class="breadcrumb_wrapper xsem-breadcrumbs" data-a="showCart"\n
data-c="SeminarCatalog__Core__Cart__Controller__CartController">\n
<div class="breadcrumb">\n
<span class="crumb">\n
<a href="/warenkorb.html">Warenkorb</a>\n
</span>\n
</div>\n
</nav>\n
\n
<div id="xsemTopWrapper" class="xsemHeaderNoTabs">\n
<div id="xsemHeadline">\n
<div class="headline">\n
<h1>\n
Warenkorb\n
\n
</h1>\n
\n
\n
</div>\n
<div class="headerContent">\n
</div>\n
</div>\n
\n
</div>\n
\n
</div>\n
\n
<div id="xsemAlerts">\n
\n
\n
\n
\n
</div>\n
\n
\n
\n
<div class="modal fade" id="xsem_header_object_modified_confirm_modal" tabindex="-1" role="dialog">\n
<div class="modal-dialog modal-lg" role="document">\n
<div class="modal-content">\n
<div class="modal-header">\n
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>\n
<h4 class="modal-title">\n
Der Datensatz wurde geändert.\n
</h4>\n
</div>\n
<div class="modal-body">\n
<p>Dieser Datensatz wurde zwischenzeitlich zuletzt von <span id="xsem_header_object_modified_confirm_modal_user">N/A</span> vor <span id="xsem_header_object_modified_confirm_modal_time">N/A</span> geändert.</p>\n
<p>Es könnten wichtige Änderungen verloren gehen, möchten Sie trotzdem Ihre Änderungen übernehmen?</p>\n
</div>\n
<div class="modal-footer">\n
<button type="button" class="btn btn-default" data-dismiss="modal">Abbrechen</button>\n
<a type="button" class="btn btn-primary" id="xsem_header_object_modified_confirm_modal_btn">Bestätigen</a>\n
</div>\n
</div>\n
</div>\n
</div>\n
\n
<script type="text/javascript">\n
\n
const tabContainer = document.getElementById('xsemTabs');\n
let realDropdownMenuBtnWidth = false;\n
const dropdownMenuBtnWidthThreshold = 3;\n
// Predicted width of dropdown btn, only for initialization, will be replaced later by automatic detection.\n
let dropdownMenuBtnWidth = 99 + dropdownMenuBtnWidthThreshold;\n
const dropdownMenuBtnLabel = "Mehr...";\n
let previousWidth = 0;\n
if (tabContainer) {\n
previousWidth = tabContainer.getBoundingClientRect().width;\n
}\n
\n
/**\n
* Ensures that all tabs in the navigation bar are in one row only. Overflowing tabs are moved to a dropdown menu.\n
*\n
* Dynamically adjusts the contents of the dropdown based on the width of the navigation bar.\n
* @author Justin Jansen <jjansen@databay.de>\n
* @param init\n
*/\n
function handleTabDropdown(init = false) {\n
const availableWidth = tabContainer.getBoundingClientRect().width;\n
// Important because ilias triggers several size changes due to the grid system\n
if (!init && availableWidth === previousWidth) {\n
return;\n
}\n
previousWidth = availableWidth;\n
\n
const tabList = tabContainer.querySelector('#xsemTabs .nav-tabs');\n
const tabs = Array.from(tabList.children);\n
let tabsToMove = [];\n
tabsToMove = getTabsOverceedWidth(tabs, availableWidth, tabsToMove);\n
const dropdownMenu = document.createElement('div');\n
dropdownMenu.classList.add('xsem-menu-dropdown-menu', 'dropdown-menu');\n
\n
// Remove tabs from tab list and add them to dropdown menu\n
let isDropTabActive = false;\n
tabsToMove.forEach(tab => {\n
const tabLink = tab.querySelector('a');\n
if (tabLink) {\n
const dropdownTab = tabLink.cloneNode(true);\n
dropdownTab.classList.add('dropdown-item');\n
if (tab.classList.contains('active')) {\n
isDropTabActive = true;\n
dropdownTab.classList.add('active');\n
}\n
dropdownMenu.appendChild(dropdownTab);\n
}\n
});\n
\n
const dropdownBtn = document.getElementById('xsemMenuDropdownToggler');\n
if (dropdownBtn) {\n
dropdownBtn.remove()\n
}\n
\n
if (tabsToMove.length > 0) {\n
const dropdownBtn = document.createElement('li');\n
dropdownBtn.classList.add('dropdown', 'pull-right');\n
if (isDropTabActive) {\n
dropdownBtn.classList.add('active');\n
}\n
dropdownBtn.id = 'xsemMenuDropdownToggler';\n
dropdownBtn.innerHTML = `\n
<a href="#" class="dropdown-toggle" data-toggle="dropdown">` + dropdownMenuBtnLabel + ` <span class="caret"></span></a>\n
`;\n
dropdownBtn.appendChild(dropdownMenu);\n
tabList.appendChild(dropdownBtn);\n
if (!realDropdownMenuBtnWidth) {\n
getWidthOfDropdownBtn()\n
}\n
}\n
}\n
\n
/**\n
* Returns all tabs that exceed the specified available width.\n
*\n
* Uses a recursive solution to add only tabs that actually go over the available width without a dropdown button.\n
* @author Justin Jansen <jjansen@databay.de>\n
* @param tabs\n
* @param availableWidth\n
* @param overflowingTabs\n
* @param initMove\n
* @returns {*}\n
*/\n
function getTabsOverceedWidth(tabs, availableWidth, overflowingTabs, initMove = false) {\n
let totalWidth = 0;\n
\n
for (const tab of tabs) {\n
totalWidth += getFullWidthOfTab(tab);\n
\n
if (tab.classList.contains('dropdown') || tab.classList.contains('xsem-menu-back-btn')) {\n
continue; // Skip certain tabs\n
}\n
\n
if (totalWidth >= availableWidth) {\n
if (!initMove) {\n
return getTabsOverceedWidth(tabs, availableWidth - dropdownMenuBtnWidth, overflowingTabs, true);\n
}\n
overflowingTabs.push(tab);\n
tab.style.display = 'none';\n
} else {\n
tab.style.display = 'inherit';\n
const index = overflowingTabs.indexOf(tab);\n
if (index > -1) {\n
overflowingTabs.splice(index, 1);\n
}\n
}\n
}\n
\n
return overflowingTabs;\n
}\n
\n
/**\n
* Fetches the complete width of the dropdown menu button, if any, and uses it for further calculations.\n
*\n
* An accurate solution if the button has a different size than originally intended (e.g. 90px) due to overriding styling.\n
* The size is needed to give the dropdown menu button always enough space in the same row of the navigation bar and when the tabs have to disappear.\n
* @author Justin Jansen <jjansen@databay.de>\n
* @returns {number}\n
*/\n
function getWidthOfDropdownBtn() {\n
const dropdownBtn = document.getElementById('xsemMenuDropdownToggler');\n
\n
if (dropdownBtn) {\n
realDropdownMenuBtnWidth = true;\n
dropdownMenuBtnWidth = getFullWidthOfTab(dropdownBtn) + dropdownMenuBtnWidthThreshold;\n
}\n
}\n
\n
/**\n
* Returns the complete width of the given element with margin, padding, border and offsetWidth included.\n
* @author Justin Jansen <jjansen@databay.de>\n
* @param element\n
* @returns {number}\n
*/\n
function getFullWidthOfTab(element) {\n
const styles = getComputedStyle(element);\n
\n
const isHidden = styles.display === 'none';\n
\n
if (isHidden) {\n
element.style.display = 'block';\n
}\n
\n
// Get values of padding, border, and margin\n
const paddingLeft = parseFloat(styles.paddingLeft);\n
const paddingRight = parseFloat(styles.paddingRight);\n
const borderLeft = parseFloat(styles.borderLeftWidth);\n
const borderRight = parseFloat(styles.borderRightWidth);\n
const marginLeft = parseFloat(styles.marginLeft);\n
const marginRight = parseFloat(styles.marginRight);\n
\n
const fullWidth =\n
element.offsetWidth +\n
marginLeft + marginRight +\n
paddingLeft + paddingRight +\n
borderLeft + borderRight;\n
\n
if (isHidden) {\n
element.style.display = 'none';\n
}\n
\n
return fullWidth;\n
}\n
\n
if (tabContainer) {\n
$(function() {\n
// Important because ilias triggers several size changes due to the grid system\n
handleTabDropdown(true);\n
// change debounce delay higher, it gets triggered to often\n
const resizeObserver = new ResizeObserver(debounce(handleTabDropdown, 1));\n
resizeObserver.observe(tabContainer);\n
});\n
}\n
\n
const fetchLastModifiedUrl = document.querySelector('[name="xsem-header-object-url"]')?.value;\n
\n
\n
\n
\n
\n
// add an event listener on every form submit and call fetchLastModified, then check with the data if the lastModifiedTime is bigger then modifiedTimestamp\n
function submitForm(event) {\n
setFormValidation(event.target, true);\n
event.submitter.click();\n
}\n
\n
function getCurrentLastModifiedTime() {\n
let modifiedTimestamp = 0;\n
const changeDate = document.querySelector('input[name="xsem-header-object-change-date"]');\n
if (changeDate) {\n
modifiedTimestamp = Number(changeDate.value);\n
}\n
return modifiedTimestamp;\n
}\n
\n
let modifiedTimestamp = getCurrentLastModifiedTime();\n
// if yes then show a confirm dialog if the user wants to leave the page\n
if (modifiedTimestamp > 0) {\n
document.addEventListener('submit', function (event) {\n
\n
const isValidated = isFormValidated(event.target);\n
if (isValidated) {\n
return;\n
}\n
\n
event.preventDefault();\n
fetchLastObjectModified(fetchLastModifiedUrl)\n
.then(data => {\n
\n
// if the fetch failed, just submit the form\n
if (!data.success) {\n
submitForm(event);\n
return;\n
}\n
let modifiedTimestamp = getCurrentLastModifiedTime();\n
const lastModifiedTime = Number(data.lastModifiedTime);\n
\n
if (lastModifiedTime > modifiedTimestamp) {\n
initModal(event, data.lastModifiedBy, data.formattedLastModified);\n
} else {\n
submitForm(event);\n
}\n
});\n
});\n
}\n
\n
const initModal = (event, lastModifiedBy, formattedLastModified) => {\n
const modal = document.getElementById('xsem_header_object_modified_confirm_modal');\n
modal.querySelector('#xsem_header_object_modified_confirm_modal_user').innerText = lastModifiedBy;\n
modal.querySelector('#xsem_header_object_modified_confirm_modal_time').innerText = formattedLastModified;\n
const submitModalBtn = document.getElementById('xsem_header_object_modified_confirm_modal_btn');\n
submitModalBtn.addEventListener('click', function () {\n
submitForm(event);\n
})\n
$('#xsem_header_object_modified_confirm_modal').modal('show');\n
}\n
\n
const setFormValidation = (form, isValidated) => {\n
form.setAttribute('data-xsem-header-object-form-is-validate', isValidated ? '1' : '0');\n
}\n
\n
const isFormValidated = (form) => {\n
const value = form.getAttribute('data-xsem-header-object-form-is-validate',)\n
\n
return value === '1';\n
}\n
</script>\n
\n
\n
\n
\n
\n
<div class="cart">\n
\n
<form id="cartForm" action="/kasse.html" method="post" class="submitOnChange">\n
\n
\n
\n
\n
<div class="cart-row-item mb-l " data-seminar-id="32" data-seminar-type="seminar">\n
<div class="cart-col-item cart-event-block">\n
<style>\n
\t.xsem-related-bundles-event-btn {\n
\t\tpadding: 3px 10px !important;\n
\t\ttext-transform: uppercase !important;\n
\t\tfont-weight: 500 !important;\n
\t}\n
</style>\n
\n
\t<div class="card card-event card-sections card-bordered favourite-wrapper ">\n
\t\t<xsem:Favourites seminar="_context_pass_0" favouriteList="_context_pass_1"></xsem:Favourites>\n
\t\t<section class="card-header">\n
\t\t\t\t\t\t<div class="row">\n
\t\t\t\t<div class="col-xs-12 col-sm-6">\n
\t\t\t\t\t<h5 class="card-column-headline">Kurstermin</h5>\n
\t\t\t\t\t 07. - 10.09.2025\n
\t\t\t\t\t\t\t\t\t\t\t<xsem:EditPencil\n
\t\t\t\t\t\t\t\tobject="_context_pass_2"\n
\t\t\t\t\t\t\t\tlink="/seminarverwaltung/kurse/gefaehrdungsbeurteilungen-32/termine/gefaehrdungsbeurteilungen-07.--10.09.2025-32/bearbeiten.html?parentObject=Seminar"\n
\t\t\t\t\t\t\t\ttarget="editEvent"\n
\t\t\t\t\t\t>\n
\t\t\t\t\t\t</xsem:EditPencil>\n
\t\t\t\t\t\t\t\t\t</div>\n
\t\t\t\t<div class="col-xs-6 col-sm-3">\n
\t\t\t\t\t<h5 class="card-column-headline">Kurssprache</h5>\n
\t\t\t\t\t <span class="nowrap">Deutsch <img src="./Customizing/global/plugins/Services/UIComponent/UserInterfaceHook/SeminarCatalog/Resources//img/flags/de.png" alt="Kurssprache: Deutsch"></span>\t\t\t\t</div>\n
\t\t\t\t<div class="col-xs-6 col-sm-3">\n
\t\t\t\t\t\t\t\t\t\t\t<h5 class="card-column-headline">Kurs-Nr.</h5>\n
\t\t\t\t\t\t1870 / GB\n
\t\t\t\t\t\t\t\t\t</div>\n
\t\t\t</div>\n
\t\t</section>\n
\t\t<section class="card-body">\n
\t\t\t<div class="row">\n
\t\t\t\t<div class="col-xs-12 col-sm-6">\n
\t\t\t\t\t\t\t\t\t\t\t<h5 class="card-column-headline">Kurs</h5>\n
\t\t\t\t\t\n
\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div class="card-title">\n
\t\t\t\t\t\t\t\n
\t\t<a href="/kursangebot/kurs/gefaehrdungsbeurteilungen-32.html"\n
\t\t \t\t title="Kursdetails anzeigen"\n
\t\t class=""\t\t>\n
Gefährdungsbeurteilungen\n
\t\t\t\t\t</a>\n
<xsem:EditPencil\n
\t\tobject="_context_pass_3"\n
\t\tlink="/seminarverwaltung/kurse/gefaehrdungsbeurteilungen-32/termine/gefaehrdungsbeurteilungen-07.--10.09.2025-32/bearbeiten.html?parentObject=Seminar"\n
\t\ttarget="editEvent"\n
>\n
</xsem:EditPencil>\n
\t\t\t\t\t</div>\n
\n
\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n
\n
\t\t\t\t<div class="col-xs-6 col-sm-3">\n
\t\t\t\t\t\t\t\t\t\t\t<h5 class="card-column-headline">Kursort</h5>\n
\t\t\t\t\t\t<xsem:FormatEventLocation event="_context_pass_4" cityOnly></xsem:FormatEventLocation>\n
\t\t\t\t\t\t\t\t\t</div>\n
\n
\t\t\t\t <div class="col-xs-6 col-sm-3 online-event-pricecontainer">\n
\t\t\t\t\t \t\t\t\t\t\t \t\t\t\t\t\t\t \t\t\t\t\t\t\t\t <h5 class="card-column-headline">Kursgebühr</h5>\n
\t\t\t\t\t\t\t\t \t<div class="price-block">\n
\t\t\t\t\t\t<p class="pb-best-price">\n
\t\t\t\t\t\t\t<span class="pb-price">100,- EUR</span>\n
\t\t\t\t<br><span class="pb-vat">\n
\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n
\t\t\t\t \t\t</p>\n
\n
\t\t\t\t\t\t\t</div>\n
\t\t\t\t\t\t\t \t\t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t </div>\n
\t\t\t</div>\n
\n
\t\t\t\t\t</section>\n
\t\t\t\t\t\t\t\t\t<section class="card-footer ce-accordion closed">\n
\t\t\t\t\t<div class="ce-info">\n
<div id="event-detail-row-32" class="row">\n
<div class="col-sm-12 col-md-6 mb-l">\n
<div class="info-table">\n
<div class="table-row wide">\n
<div class="label-column">Kursort:</div>\n
<div class="info-column">\n
<div class="location">\n
\n
<p>\n
<b>Berufsgenossenschaftliche Bildungsstätte</b>\n
</p>\n
\n
<div class="address-row info-table info-table-small">\n
<div class="table-row">\n
<div class="icon-column">\n
<span class="glyphicon glyphicon-map-marker"\n
title="Anschrift"></span>\n
</div>\n
<div class="info-column">\n
Feldstraße 8,\n
08547 Jößnitz </div>\n
</div>\n
</div>\n
</div>\n
</div>\n
</div>\n
</div>\n
\n
\n
\n
</div>\n
\n
<div class="col-sm-12 col-md-6 mb-l">\n
\n
<div class="map">\n
<div class="event-details-map mb-m">\n
<!-- OPENSTREETMAPS START -->\n
<div id="maploc5-68b862625ff1d"\n
class="mapBlock mt-m mb-m"\n
style="height: 200px; width: 100%"\n
data-mapdata='{"id":"loc5-68b862625ff1d","searchText":"Feldstra\u00dfe 8 08547 J\u00f6\u00dfnitz ","description":"Berufsgenossenschaftliche Bildungsst\u00e4tte<br>Feldstra\u00dfe 8<br>08547 J\u00f6\u00dfnitz<br>"}'\n
data-longitude="12.1425478"\n
data-latitude="50.5489161">\n
</div>\n
<!-- OPENSTREETMAPS END -->\n
</div>\n
<div id="navloc5-68b862625ff1d" class="mapNavigation text-right mb-m">\n
<a class="btn btn-primary mapNavigationLink"\n
id="navLinkloc5-68b862625ff1d"\n
target="_blank"\n
href="https://www.google.de/maps/dir//Feldstraße 8 08547 Jößnitz ">\n
Routenplaner\n
</a>\n
</div>\n
</div>\n
\n
</div>\n
</div>\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
<div class="row">\n
<div class="col-sm-12 col-md-6 mb-l">\n
<div class="info-table">\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
</div>\n
\n
</div>\n
</div>\n
\n
</div>\n
\n
<div id="cancellation-info32">\n
<div style="padding-top:30px;">\n
\n
</div>\n
</div>\n
<style>\n
#xsem #cancellation-info32 {\n
display: none;\n
}\n
</style>\n
\t\t\t\t\t<div class="ce-accordion-header">\n
\t\t\t\t\t\t<button id="btnOpenAccordion32">Weitere Informationen</button>\n
\t\t\t\t\t</div>\n
\t\t\t\t</section>\n
\t\t\t\t\t\t</div>\n
\n
</div>\n
<div class="cart-col-amount">\n
<div class="cart-price price-block">\n
<span class="cart-label">Preis je Teilnehmer</span>\n
\t<div class="price-block">\n
\t\t\t\t\t\t<p class="pb-best-price">\n
\t\t\t\t\t\t\t<span class="pb-price">100,- EUR</span>\n
\t\t\t\t<br><span class="pb-vat">\n
\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n
\t\t\t\t \t\t</p>\n
\n
\t\t\t\t\t\t\t</div>\n
</div>\n
<div class="cart-amount">\n
<span class="cart-label">Anzahl Teilnehmer</span>\n
<div class="form-group">\n
<input type="number"\n
min="0"\n
max="250"\n
id="cartNumberParticipants57"\n
name="numberParticipants[57]"\n
class="form-control cartNumberParticipants"\n
value="1">\n
</div>\n
<button id="updateItem57"\n
type="submit"\n
name="cmd[change]"\n
class="btn btn-primary"\n
title="Aktualisieren"><span class="glyphicon glyphicon-refresh"></span>\n
</button>\n
<button id="removeItem57"\n
type="submit"\n
name="cmd[delete]"\n
class="btn btn-primary remove"\n
title="Entfernen"><span class="glyphicon glyphicon-trash"></span>\n
</button>\n
<script type="text/javascript">\n
$('#removeItem57').on('click', function () {\n
$('#cartNumberParticipants57').val(0);\n
$(this).closest('form').submit();\n
if (typeof GARemoveFromCart57 === "function") {\n
GARemoveFromCart57();\n
}\n
});\n
\n
$('#updateItem57').on('click', function (e) {\n
if (typeof GAUpdateCart57 === "function") {\n
GAUpdateCart57();\n
}\n
});\n
//$('form.submitOnChange input').on('keyup', function() {\n
// $.post($(this).closest('form').attr('action'), $(this).closest('form').serialize())\n
//});\n
</script>\n
\n
\n
\n
\n
\n
\n
\n
</div>\n
</div>\n
</div>\n
\n
<div class="cart-row-total">\n
<div class="cart-col-coupon">\n
</div>\n
<div class="cart-col-total price-block">\n
\n
<div class="pb-total">\n
<span class="cart-label">Gesamtsumme</span>\n
100,- EUR<br>\n
<span class="pb-vat">\n
mehrwertsteuerfrei<br>\n
\n
</span>\n
</div>\n
\n
</div>\n
</div>\n
\n
<div class="row cart-submit">\n
<div class="col-sm-6">\n
<a class="btn btn-primary" href="/kursangebot.html">\n
Weitere Kurse buchen\n
</a>\n
</div>\n
<div class="col-sm-6 text-right">\n
<button id="bookingButton" name="cmd[book]" class="btn btn-primary" type="submit">\n
Zur Kasse\n
</button>\n
</div>\n
</div>\n
</form>\n
\n
<div class="clear"></div>\n
</div>\n
\n
\n
<style>\n
#xsem {\n
[data-seminar-type="conference"] .cart-event-block .card {\n
margin-bottom: 0 !important;\n
border: 0 !important;\n
min-height: 0 !important\n
}\n
\n
[data-seminar-type="conference"] .cart-amount{\n
padding-bottom: 0 !important;\n
}\n
}\n
</style>\n
<style>\n
.booking-blocked {\n
border-color:red;\n
}\n
</style>\n
\n
\n
<script type="text/javascript">\n
$(document).ready(function () {\n
$(".cartNumberParticipants").each(function () {\n
if ($(this).val() > $(this).data("max-participants") || $(this).val() < 0) {\n
$(this).popover("show");\n
$(this).data("has-popover", 1);\n
}\n
});\n
});\n
\n
\n
$(".cartNumberParticipants").on("click", function () {\n
if ($(this).data("max-participants")) {\n
if ($(this).val() > $(this).data("max-participants") || $(this).val() < 0) {\n
$(this).popover("show");\n
$(this).data("has-popover", 1);\n
} else {\n
$(this).popover("hide");\n
$(this).data("has-popover", 0);\n
}\n
}\n
});\n
$(".cartNumberParticipants").on("keyup", function () {\n
if ($(this).data("max-participants")) {\n
if ($(this).val() > $(this).data("max-participants") || $(this).val() < 0) {\n
$(this).popover("show");\n
$(this).data("has-popover", 1);\n
} else {\n
$(this).popover("hide");\n
$(this).data("has-popover", 0);\n
}\n
}\n
});\n
\n
$("#bookingButton").on("click", function () {\n
var saveFlag = true;\n
$(".cartNumberParticipants").each(function () {\n
if ($(this).data("has-popover") == 1) {\n
saveFlag = false;\n
}\n
});\n
\n
if (saveFlag) {\n
//$("#cartForm").submit();\n
return true;\n
}\n
\n
return false;\n
});\n
</script>\n
\n
<style>\n
#xsem .cart-row-item,\n
#xsem .cart-row-total {\n
display: flex;\n
flex-direction: row;\n
flex-wrap: nowrap;\n
justify-content: space-between;\n
align-items: stretch;\n
align-content: stretch;\n
gap: 0;\n
}\n
#xsem .cart-col-item {\n
flex-grow: 3;\n
flex-basis: 75%;\n
padding-right: 20px;\n
}\n
#xsem .cart-col-amount {\n
flex-grow: 1;\n
flex-basis: 25%;\n
padding: 0 20px;\n
}\n
#xsem .cart-col-coupon {\n
flex-grow: 3;\n
flex-basis: 75%;\n
padding: 0 20px;\n
}\n
#xsem .cart-col-total {\n
flex-grow: 1;\n
flex-basis: 25%;\n
padding: 0 20px;\n
}\n
\n
#xsem .cart-col-total .cart-price {\n
display: inline-block;\n
text-align: left;\n
}\n
</style>\n
"""
/srv/www/bgphoenics2.invorbereitung.de/ilias/vendor/twig/twig/src/TemplateWrapper.php
/**
* @return iterable<scalar|\Stringable|null>
*/
public function stream(array $context = []): iterable
{
yield from $this->template->yield($context);
}
/**
* @return iterable<scalar|\Stringable|null>
*/
public function streamBlock(string $name, array $context = []): iterable
{
yield from $this->template->yieldBlock($name, $context);
}
public function render(array $context = []): string
{
return $this->template->render($context);
}
/**
* @return void
*/
public function display(array $context = [])
{
// using func_get_args() allows to not expose the blocks argument
// as it should only be used by internal code
$this->template->display($context, \func_get_args()[1] ?? []);
}
public function hasBlock(string $name, array $context = []): bool
{
return $this->template->hasBlock($name, $context);
}
/**
* @return string[] An array of defined template block names
*/
Arguments
array:6 [
"newItem" => SeminarCatalog\Core\Order\Model\Item {#2714}
"isEmptyCart" => false
"currentOrder" => SeminarCatalog\Core\Order\Model\Order {#2461}
"validationResult" => SeminarCatalog\Validator\ValidationResult {#3262}
"couponDiscounts" => []
"orderItemsReserved" => null
]
/srv/www/bgphoenics2.invorbereitung.de/ilias/Core/Cart/Classes/Controller/CartController.php
if (isset($_GET['newItemId'])) {
if ($item->getId() === (int)StringUtility::fromMixed($_GET['newItemId'])) {
$newItem = $item;
}
}
}
$couponDiscounts = $this->couponService->getDiscountsList($this->currentOrder);
}
if ($this->configurationService->get('maintenance_mode') == 1) {
NoticeService::send(
"error",
LanguageService::translate("booking_info_bookings_temporarily_not_possible")
);
}
return $template->render(
[
'newItem' => $newItem,
'isEmptyCart' => $isEmptyCart,
'currentOrder' => $this->currentOrder,
'validationResult' => $this->validationResult,
'couponDiscounts' => $couponDiscounts,
"orderItemsReserved" => isset($_GET['orderItemsReserved']) ? explode(",",
urldecode($_GET['orderItemsReserved'])) : null,
]
);
}
/**
* @access isAnybody
* @return RedirectControllerResult|string
* @throws \Exception
*/
public function submitCartAction()
{
if (!($this->currentOrder instanceof Order)) {
Arguments
array:6 [
"newItem" => SeminarCatalog\Core\Order\Model\Item {#2714}
"isEmptyCart" => false
"currentOrder" => SeminarCatalog\Core\Order\Model\Order {#2461}
"validationResult" => SeminarCatalog\Validator\ValidationResult {#3262}
"couponDiscounts" => []
"orderItemsReserved" => null
]
/srv/www/bgphoenics2.invorbereitung.de/ilias/classes/Controller/BaseController.php
$this,
'handleParameters',
$_GET
);
$this->handleParameters(...$params);
}
if (method_exists($this, 'initializeAction')) {
$params = ClassService::convertGetValuesToMethodParameterValues(
$this,
'initializeAction',
$_GET
);
$this->initializeAction(...$params);
}
$cmd = $cmd . 'Action';
$params = ClassService::convertGetValuesToMethodParameterValues($this, $cmd, $_GET);
$html = $this->$cmd(...$params);
global $tpl;
if ($tpl) {
if ($this->getPageTitle() != '') {
$tpl->setTitle($this->getPageTitle());
} else {
// This is a bad idea because it will break the page title in the repository
$tpl->setTitle(LanguageService::translate('default_page_header'));
}
if ($this->getPageIcon() != '') {
$tpl->setTitleIcon($this->getPageIcon());
}
}
return $html;
}
throw new AuthenticationException(get_class($this), $cmd);
/srv/www/bgphoenics2.invorbereitung.de/ilias/classes/SeminarCatalogKernel.php
$router = ObjectManager::get(\SeminarCatalog\Core\Routing\Service\CoreRouter::class);
try {
if ($request->getRequestUri()) {
if (strpos($request->getRequestUri(), '/index.php?') === 0) {
throw new ResourceNotFoundException('URLs starting with /index.php? are not allowed');
}
}
$match = $router->match($request);
$router->resolveMatch($match);
$controller = $match[$configurationService->getControllerGetParameterName()];
$request->query->add($match);
$controller = UtilityService::prepareClassNameFromUrl($controller);
$controller = self::checkAccessAndGetControllerInstance(
$controller,
$configurationService
);
$response = $controller->handleCmd($request);
} catch(NoConfigurationException|ResourceNotFoundException $e) {
// Fallback to legacy Routing
$controller = $request->get($configurationService->getControllerGetParameterName());
if ($controller == "") {
throw new \Exception("No route found");
}
$controller = UtilityService::prepareClassNameFromUrl($controller);
$controller = self::checkAccessAndGetControllerInstance(
$controller,
$configurationService
);
$response = $controller->handleCmd();
}
return $this->handleControllerResponse($response, $request, $controller);
} catch(\Throwable $e) {
Arguments
Symfony\Component\HttpFoundation\Request {#543
+attributes: Symfony\Component\HttpFoundation\ParameterBag {#533}
+request: Symfony\Component\HttpFoundation\InputBag {#531}
+query: Symfony\Component\HttpFoundation\InputBag {#532}
+server: Symfony\Component\HttpFoundation\ServerBag {#536}
+files: Symfony\Component\HttpFoundation\FileBag {#535}
+cookies: Symfony\Component\HttpFoundation\InputBag {#534}
+headers: Symfony\Component\HttpFoundation\HeaderBag {#537}
#content: null
#languages: null
#charsets: null
#encodings: null
#acceptableContentTypes: null
#pathInfo: "/warenkorb.html"
#requestUri: "/warenkorb.html?newItemId=57"
#baseUrl: ""
#basePath: null
#method: "GET"
#format: null
#session: null
#locale: null
#defaultLocale: "en"
-preferredFormat: null
-isHostValid: true
-isForwardedValid: true
-isSafeContentPreferred: null
-isIisRewrite: false
basePath: ""
format: "html"
}
/srv/www/bgphoenics2.invorbereitung.de/ilias/index.php
use SeminarCatalog\Rest\Utility\ControllerResultInterface;
use Symfony\Component\HttpFoundation\Request;
require_once __DIR__ . '/classes/SeminarCatalogKernel.php';
error_reporting(error_reporting() & ~E_NOTICE);
ini_set('display_errors', 1);
apcu_clear_cache();
$whoops = new \Whoops\Run;
$whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
$whoops->register();
define("standalone2",true);
define("DEVMODE",true);
$kernel = new \SeminarCatalogKernel();
$kernel->boot();
$response = $kernel->handleRequest(ObjectManager::get(Request::class));
if ($response instanceof \Symfony\Component\HttpFoundation\Response || $response instanceof ControllerResultInterface) {
$response->send();
} else {
if (is_string($response)) {
echo $response;
} else {
throw new \Exception('Invalid response type given. Only Response|String is valid.');
}
}
// http://localhost:32768/?scontroller=SeminarCatalog__Core__Catalog__Controller__CatalogController&saction=catalog
Arguments
Symfony\Component\HttpFoundation\Request {#543
+attributes: Symfony\Component\HttpFoundation\ParameterBag {#533}
+request: Symfony\Component\HttpFoundation\InputBag {#531}
+query: Symfony\Component\HttpFoundation\InputBag {#532}
+server: Symfony\Component\HttpFoundation\ServerBag {#536}
+files: Symfony\Component\HttpFoundation\FileBag {#535}
+cookies: Symfony\Component\HttpFoundation\InputBag {#534}
+headers: Symfony\Component\HttpFoundation\HeaderBag {#537}
#content: null
#languages: null
#charsets: null
#encodings: null
#acceptableContentTypes: null
#pathInfo: "/warenkorb.html"
#requestUri: "/warenkorb.html?newItemId=57"
#baseUrl: ""
#basePath: null
#method: "GET"
#format: null
#session: null
#locale: null
#defaultLocale: "en"
-preferredFormat: null
-isHostValid: true
-isForwardedValid: true
-isSafeContentPreferred: null
-isIisRewrite: false
basePath: ""
format: "html"
}