aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan-Hendrik Willms <tleilax+studip@gmail.com>2022-11-24 10:29:24 +0000
committerJan-Hendrik Willms <tleilax+studip@gmail.com>2022-11-24 10:29:24 +0000
commit7dddea8ccca601bf2da28960f2e27a223fe60ea6 (patch)
treeb34ee92f9a4e0e4c1f7e4dcf5f15b396f9097d6f
parent1231022837beceedef376e4bb8084ff38fbc7d93 (diff)
rework aux lock rules, use sorm model, deprecate old class and let name and description be translatable, fixes #1791
Closes #1791 Merge request studip/studip!1177
-rw-r--r--app/controllers/admin/courses.php8
-rw-r--r--app/controllers/admin/specification.php106
-rw-r--r--app/controllers/authenticated_controller.php21
-rw-r--r--app/controllers/consultation/consultation_controller.php12
-rw-r--r--app/controllers/course/members.php3
-rw-r--r--app/controllers/course/overview.php26
-rw-r--r--app/views/admin/courses/aux-select.php12
-rw-r--r--app/views/admin/courses/aux_preselect.php21
-rw-r--r--app/views/admin/specification/_field.php28
-rw-r--r--app/views/admin/specification/edit.php129
-rw-r--r--app/views/admin/specification/index.php75
-rw-r--r--app/views/course/members/additional_input.php54
-rw-r--r--db/migrations/5.3.9_convert_aux_lock_rules_json_fields.php56
-rw-r--r--lib/classes/AuxLockRules.class.php3
-rw-r--r--lib/classes/Markup.class.php2
-rw-r--r--lib/classes/StudipArrayObject.class.php8
-rw-r--r--lib/classes/WidgetContainer.php5
-rw-r--r--lib/models/AuxLockRule.php133
-rw-r--r--lib/models/DatafieldEntryModel.class.php82
-rw-r--r--templates/i18n/input.php10
20 files changed, 481 insertions, 313 deletions
diff --git a/app/controllers/admin/courses.php b/app/controllers/admin/courses.php
index e832628..7e78aae 100644
--- a/app/controllers/admin/courses.php
+++ b/app/controllers/admin/courses.php
@@ -372,13 +372,7 @@ class Admin_CoursesController extends AuthenticatedController
]],
LockRule::findAllByType('sem')
));
- $this->aux_lock_rules = array_merge(
- [[
- 'name' => '--' . _("keine Zusatzangaben") . '--',
- 'lock_id' => 'none'
- ]],
- AuxLockRules::getAllLockRules()
- );
+ $this->aux_lock_rules = AuxLockRule::findBySQL('1 ORDER BY name');
//build the sidebar:
diff --git a/app/controllers/admin/specification.php b/app/controllers/admin/specification.php
index 977ec18..819d59b 100644
--- a/app/controllers/admin/specification.php
+++ b/app/controllers/admin/specification.php
@@ -17,6 +17,8 @@
*/
class Admin_SpecificationController extends AuthenticatedController
{
+ protected $_autobind = true;
+
/**
* Common tasks for all actions.
*/
@@ -41,25 +43,39 @@ class Admin_SpecificationController extends AuthenticatedController
*/
public function index_action()
{
- $this->allrules = AuxLockRules::getAllLockRules();
+ $this->rules = AuxLockRule::findBySQL('1 ORDER BY name');
+
+ Sidebar::Get()->addWidget(new ActionsWidget())->addLink(
+ _('Neue Regel anlegen'),
+ $this->editURL(),
+ Icon::create('add')
+ );
}
/**
* Edit or create a rule
- *
- * @param string $edit_id
+ * @property AuxLockRule $rule
*/
- public function edit_action($id = null)
+ public function edit_action(AuxLockRule $rule = null)
{
- //get data
- $user_field = 'user';
- $semdata_field = 'usersemdata';
- $this->semFields = AuxLockRules::getSemFields();
- $this->entries_user = DataField::getDataFields($user_field);
- $this->entries_semdata = DataField::getDataFields($semdata_field);
- $this->rule = is_null($id) ? false : AuxLockRules::getLockRuleByID($id);
-
- if ($GLOBALS['perm']->have_perm('root') && count($this->entries_semdata) == 0) {
+ $rule->name = Request::i18n('name', $rule->name);
+ $rule->description = Request::i18n('description', $rule->description);
+ $rule->attributes = Request::optionArray('fields') ?: $rule->attributes;
+ $rule->sorting = Request::getArray('order') ?: $rule->sorting;
+
+ if ($GLOBALS['perm']->have_perm('root')) {
+ Sidebar::Get()->addWidget(new ActionsWidget())->addLink(
+ _('Datenfelder bearbeiten'),
+ URLHelper::getURL('dispatch.php/admin/datafields'),
+ Icon::create('edit')
+ );
+ }
+
+ $this->semFields = $this->getSemFields();
+ $this->entries_user = DataField::getDataFields('user');
+ $this->entries_semdata = DataField::getDataFields('usersemdata');
+
+ if ($GLOBALS['perm']->have_perm('root') && count($this->entries_semdata) === 0) {
PageLayout::postWarning(sprintf(
_('Sie müssen zuerst im Bereich %sDatenfelder%s in der Kategorie '
. '<em>Datenfelder für Personenzusatzangaben in Veranstaltungen</em> '
@@ -74,51 +90,63 @@ class Admin_SpecificationController extends AuthenticatedController
* Store or edit Rule
* @param string $id
*/
- public function store_action($id = '')
+ public function store_action(AuxLockRule $rule = null)
{
- CSRFProtection::verifyRequest();
+ CSRFProtection::verifyUnsafeRequest();
$errors = [];
- if (!Request::get('rulename')) {
+ if (!trim(Request::get('name'))) {
$errors[] = _('Bitte geben Sie der Regel mindestens einen Namen!');
}
- if (!AuxLockRules::checkLockRule(Request::getArray('fields'))) {
+
+ if (!AuxLockRule::validateFields(Request::optionArray('fields'))) {
$errors[] = _('Bitte wählen Sie mindestens ein Feld aus der Kategorie "Zusatzinformationen" aus!');
}
- if (empty($errors)) {
- if (!$id) {
- //new
- AuxLockRules::createLockRule(Request::get('rulename'), Request::get('description'), Request::getArray('fields'), Request::getArray('order'));
- } else {
- //edit
- AuxLockRules::updateLockRule($id, Request::get('rulename'), Request::get('description'), Request::getArray('fields'), Request::getArray('order'));
- }
- PageLayout::postSuccess(sprintf(
- _('Die Regel "%s" wurde erfolgreich gespeichert!'),
- htmlReady(Request::get('rulename'))
- ));
- } else {
+ if ($errors) {
PageLayout::postError(_('Ihre Eingaben sind ungültig.'), $errors);
- }
+ $this->keepRequest();
+ $this->redirect($this->editURL($rule));
+ } else {
+ $rule->name = Request::i18n('name');
+ $rule->description = Studip\Markup::purifyHtml(Request::i18n('description'));
+ $rule->attributes = Request::optionArray('fields') ?? [];
+ $rule->sorting = Request::getArray('order') ?? [];
- $this->redirect('admin/specification');
+ if ($rule->store()) {
+ PageLayout::postSuccess(sprintf(
+ _('Die Regel "%s" wurde erfolgreich gespeichert!'),
+ htmlReady($rule->name)
+ ));
+ }
+ $this->redirect('admin/specification');
+ }
}
/**
* Delete a rule, using a modal dialog
- *
- * @param string $rule_id
*/
- public function delete_action($rule_id)
+ public function delete_action(AuxLockRule $rule)
{
CSRFProtection::verifyUnsafeRequest();
- if (AuxLockRules::deleteLockRule($rule_id)) {
- PageLayout::postSuccess(_('Die Regel wurde erfolgreich gelöscht!'));
- } else {
+
+ $result = $rule->delete();
+ if ($result === false) {
PageLayout::postError(_('Es können nur nicht verwendete Regeln gelöscht werden!'));
+ } elseif ($result > 0) {
+ PageLayout::postSuccess(_('Die Regel wurde erfolgreich gelöscht!'));
}
- $this->redirect('admin/specification');
+ $this->redirect($this->indexURL());
+ }
+
+ private function getSemFields(): array
+ {
+ return [
+ 'vasemester' => _('Semester'),
+ 'vanr' => _('Veranstaltungsnummer'),
+ 'vatitle' => _('Veranstaltungstitel'),
+ 'vadozent' => _('Dozent'),
+ ];
}
}
diff --git a/app/controllers/authenticated_controller.php b/app/controllers/authenticated_controller.php
index f50d478..e051ffa 100644
--- a/app/controllers/authenticated_controller.php
+++ b/app/controllers/authenticated_controller.php
@@ -1,8 +1,4 @@
<?php
-# Lifter007: TODO
-# Lifter003: TODO
-# Lifter010: TODO
-
/*
* Copyright (C) 2009 - Marcus Lunzenauer <mlunzena@uos.de>
*
@@ -16,4 +12,21 @@ class AuthenticatedController extends StudipController
{
protected $with_session = true; //we do need to have a session for this controller
protected $allow_nobody = false; //nobody is not allowed and always gets a login-screen
+
+ public function before_filter(&$action, &$args)
+ {
+ parent::before_filter($action, $args);
+
+ // Restore request if present
+ if (isset($this->flash['request'])) {
+ foreach ($this->flash['request'] as $key => $value) {
+ Request::set($key, $value);
+ }
+ }
+ }
+
+ protected function keepRequest()
+ {
+ $this->flash['request'] = Request::getInstance()->getIterator()->getArrayCopy();
+ }
}
diff --git a/app/controllers/consultation/consultation_controller.php b/app/controllers/consultation/consultation_controller.php
index eba81ff..dc7fd6e 100644
--- a/app/controllers/consultation/consultation_controller.php
+++ b/app/controllers/consultation/consultation_controller.php
@@ -26,13 +26,6 @@ abstract class ConsultationController extends AuthenticatedController
URLHelper::addLinkParam('cid', $this->range->id);
}
- // Restore request if present
- if (isset($this->flash['request'])) {
- foreach ($this->flash['request'] as $key => $value) {
- Request::set($key, $value);
- }
- }
-
// This defines the function to display a note. Not really a partial,
// not a controller method. This has no real place...
$this->displayNote = function ($what, $length = 40, $position = 'above') {
@@ -72,11 +65,6 @@ abstract class ConsultationController extends AuthenticatedController
return $this->range->getConfiguration()->CONSULTATION_TAB_TITLE;
}
- protected function keepRequest()
- {
- $this->flash['request'] = Request::getInstance()->getIterator()->getArrayCopy();
- }
-
/**
* @param $block_id
*
diff --git a/app/controllers/course/members.php b/app/controllers/course/members.php
index 16c59a3..ad7d6da 100644
--- a/app/controllers/course/members.php
+++ b/app/controllers/course/members.php
@@ -1330,6 +1330,9 @@ class Course_MembersController extends AuthenticatedController
$course = Course::findCurrent();
$member = $course->members->findOneBy('user_id', $GLOBALS['user']->id);
$this->datafields = $member ? $course->aux->getMemberData($member) : [];
+
+ $this->editable = false;
+
// We need aux data in the view
$this->aux = $course->aux;
diff --git a/app/controllers/course/overview.php b/app/controllers/course/overview.php
index 0994d54..96e7f5a 100644
--- a/app/controllers/course/overview.php
+++ b/app/controllers/course/overview.php
@@ -87,24 +87,14 @@ class Course_OverviewController extends AuthenticatedController
$this->show_dozenten = $show_dozenten;
// Check lock rules
- if (!$GLOBALS["perm"]->have_studip_perm('dozent', $this->course_id)) {
- $rule = AuxLockRules::getLockRuleBySemId($this->course_id);
- if (isset($rule)) {
- $show = false;
- foreach ((array) $rule['attributes'] as $val) {
- if ($val == 1) {
- // Es gibt also Zusatzangaben. Nun noch überprüfen ob der Nutzer diese Angaben schon gemacht hat...
- $count = DataField::countBySql("LEFT JOIN datafields_entries USING (datafield_id) WHERE object_type = ? AND sec_range_id = ? AND range_id = ?",
- ['usersemdata', $this->course_id, $GLOBALS['user']->id]
- );
- if (!$count) {
- $show = true;
- }
- break;
- }
- }
-
- if ($show) {
+ if (!$GLOBALS['perm']->have_studip_perm('dozent', $this->course_id)) {
+ $rule = AuxLockRule::findOneByCourse($this->course);
+ if ($rule && count($rule->attributes) > 0) {
+ $count = DataField::countBySql("LEFT JOIN datafields_entries USING (datafield_id) WHERE object_type = ? AND sec_range_id = ? AND range_id = ?",
+ ['usersemdata', $this->course_id, $GLOBALS['user']->id]
+ );
+
+ if ($count === 0) {
PageLayout::postInfo(
_("Sie haben noch nicht die für diese Veranstaltung benötigten Zusatzinformationen eingetragen."),
[
diff --git a/app/views/admin/courses/aux-select.php b/app/views/admin/courses/aux-select.php
index 1786598..950120e 100644
--- a/app/views/admin/courses/aux-select.php
+++ b/app/views/admin/courses/aux-select.php
@@ -1,13 +1,17 @@
<?php
/**
* @var Course $course
- * @var array $aux_lock_rules
+ * @var AuxLockRule[] $aux_lock_rules
+ * @var array $values
*/
?>
<select name="lock_sem[<?= htmlReady($course->id) ?>]" style="max-width: 200px">
-<? foreach ($aux_lock_rules as $id => $rule) : ?>
- <option value="<?= $id ?>" <?= $values['aux_lock_rule'] == $id ? 'selected' : '' ?>>
- <?= htmlReady($rule['name']) ?>
+ <option value="none">
+ --<?= _('keine Zusatzangaben') ?>--
+ </option>
+<? foreach ($aux_lock_rules as $rule) : ?>
+ <option value="<?= htmlReady($rule->id) ?>" <? if ($values['aux_lock_rule'] === $rule->id) echo 'selected'; ?>>
+ <?= htmlReady($rule->name) ?>
</option>
<? endforeach ?>
</select>
diff --git a/app/views/admin/courses/aux_preselect.php b/app/views/admin/courses/aux_preselect.php
index e44e378..73a2036 100644
--- a/app/views/admin/courses/aux_preselect.php
+++ b/app/views/admin/courses/aux_preselect.php
@@ -1,21 +1,24 @@
<?php
/**
* @var array $values
- * @var array $aux_lock_rules
+ * @var AuxLockRule[] $aux_lock_rules
*/
?>
<label><?= _('Für alle Veranstaltungen') ?>
<select name="lock_sem_all" style="max-width: 200px">
- <? foreach ($aux_lock_rules as $id => $rule) : ?>
- <option value="<?= $id ?>"
- <?= ($values['aux_lock_rule'] == $id) ? 'selected' : '' ?>>
- <?= htmlReady($rule["name"]) ?>
- </option>
- <? endforeach ?>
+ <option value="none">
+ --<?= _('keine Zusatzangaben') ?>--
+ </option>
+ <? foreach ($aux_lock_rules as $rule) : ?>
+ <option value="<?= htmlReady($rule->id) ?>"
+ <? if ($values['aux_lock_rule'] === $rule->id) echo 'selected'; ?>>
+ <?= htmlReady($rule->name) ?>
+ </option>
+ <? endforeach ?>
</select>
</label>
<label>
-<input type="checkbox" value="1" name="aux_all_forced">
-<?=_("Erzwungen")?>
+ <input type="checkbox" value="1" name="aux_all_forced">
+ <?=_('Erzwungen')?>
</label>
<?= \Studip\Button::createAccept(_('Speichern'), 'all'); ?>
diff --git a/app/views/admin/specification/_field.php b/app/views/admin/specification/_field.php
index 05ea09f..3d2703b 100644
--- a/app/views/admin/specification/_field.php
+++ b/app/views/admin/specification/_field.php
@@ -2,40 +2,36 @@
/**
* @var string $name
* @var string $id
- * @var array $rule
+ * @var AuxLockRule $rule
*/
-$fields = Request::getArray('fields');
-$order = Request::getArray('order');
?>
<section>
- <? if (!empty($required)) : ?>
+<? if (!empty($required)) : ?>
<span class="required">
<?= htmlReady($name) ?>
</span>
- <? else : ?>
+<? else: ?>
<?= htmlReady($name) ?>
- <? endif ?>
-
+<? endif ?>
<div class="hgroup">
<label class="col-2">
<?= _('Sortierung') ?>
- <input id="order_<?= $id ?>" min="0" type="number" size="3" name="order[<?= $id ?>]"
- value="<?= (int)(($order && isset($order[$id])) ? $order[$id] : @$rule['order'][$id]) ?>">
- <input type="hidden" name="fields[<?= $id ?>]" value="0">
+ <input id="order_<?= htmlReady($id) ?>" min="0" type="number" size="3" name="order[<?= htmlReady($id) ?>]"
+ value="<?= ($rule->sorting[$id] ?? 0) ?>">
</label>
<label class="col-2">
<input type="checkbox"
- name="fields[<?= $id ?>]"
- value="1"
- <?= (($fields && isset($fields[$id])) ? $fields[$id] : @$rule['attributes'][$id]) ? 'checked="checked"' : '' ?>>
+ name="fields[]"
+ value="<?= htmlReady($id) ?>"
+ <? if ($rule->attributes->contains($id)) echo 'checked'; ?>>
<?= _('Aktivieren') ?>
</label>
+ <? if (!empty($institution)) : ?>
<label class="col-1">
- <? if (!empty($institution)) : ?>
- <?= htmlReady($institution->name)?>
- <? endif; ?>
+ <?= htmlReady($institution->name )?>
</label>
+ <? endif; ?>
</div>
</section>
diff --git a/app/views/admin/specification/edit.php b/app/views/admin/specification/edit.php
index 30bee49..452c39b 100644
--- a/app/views/admin/specification/edit.php
+++ b/app/views/admin/specification/edit.php
@@ -3,95 +3,86 @@
/**
* @var Admin_SpecificationController $controller
- * @var AuxLockRules $rule
+ * @var AuxLockRule $rule
* @var array $semFields
* @var DataField[] $entries_semdata
* @var DataField[] $entries_user
*/
use Studip\Button, Studip\LinkButton;
?>
-<? if (isset($flash['error'])) : ?>
- <?= MessageBox::error($flash['error'], $flash['error_detail']) ?>
-<? elseif (isset($flash['info'])): ?>
- <?= MessageBox::info($flash['info']) ?>
-<? endif ?>
-
-<form action="<?= $controller->url_for('admin/specification/store' . ($rule ? '/' . $rule['lock_id'] : '')) ?>"
- method="post" class="default">
+<form action="<?= $controller->store($rule) ?>" method="post" class="default">
<?= CSRFProtection::tokenTag() ?>
<fieldset>
<legend>
- <? if ($rule) : ?>
- <?= sprintf(_('Regel "%s" editieren'), htmlReady($rule['name'])) ?>
- <? else : ?>
- <?= _('Eine neue Regel definieren') ?>
- <? endif ?>
+ <? if ($rule->isNew()) : ?>
+ <?= _('Eine neue Regel definieren') ?>
+ <? else : ?>
+ <?= sprintf(_('Regel "%s" editieren'), htmlReady($rule['name'])) ?>
+ <? endif ?>
</legend>
<label>
<span class="required">
- <?= _('Name der Regel:') ?>
+ <?= _('Name der Regel') ?>
</span>
- <input type="text" name="rulename" value="<?= htmlReady(Request::get('rulename', $rule ? $rule['name'] : '')) ?>"
- required="required">
+ <?= I18N::input('name', $rule->name, [
+ 'required' => '',
+ ]) ?>
</label>
<label>
<?= _('Beschreibung') ?>
- <textarea cols="60" rows="5"
- name="description"><?= htmlReady(Request::get('description', $rule ? $rule['description'] : '')) ?></textarea>
+ <?= I18N::textarea('description', $rule->description, [
+ 'class' => 'wysiwyg',
+ ]) ?>
</label>
</fieldset>
- <? if (count($entries_semdata) > 0) : ?>
- <fieldset>
- <legend>
- <?= _('Zusatzinformationen') ?>
- </legend>
- <? foreach ($entries_semdata as $id => $entry) : ?>
- <?= $this->render_partial('admin/specification/_field', array_merge(
- compact('rule'),
- ['id' => $entry->datafield_id, 'name' => $entry->name],
- ['required' => true, 'institution' => $entry->institution]
- )) ?>
- <? endforeach ?>
- </fieldset>
- <? endif ?>
- <? if (count($semFields) > 0) : ?>
- <fieldset>
- <legend>
- <?= _('Veranstaltungsinformationen') ?>
- </legend>
- <? foreach ($semFields as $id => $name) : ?>
- <?= $this->render_partial('admin/specification/_field', compact('rule', 'id', 'name')) ?>
- <? endforeach ?>
- </fieldset>
- <? endif ?>
+<? if (count($entries_semdata) > 0) : ?>
+ <fieldset>
+ <legend>
+ <?= _('Zusatzinformationen') ?>
+ </legend>
+ <? foreach ($entries_semdata as $id => $entry) : ?>
+ <?= $this->render_partial('admin/specification/_field', [
+ 'rule' => $rule,
+ 'id' => $entry->datafield_id,
+ 'name' => $entry->name,
+ 'required' => true,
+ 'institution' => $entry->institution,
+ ]) ?>
+ <? endforeach ?>
+ </fieldset>
+<? endif ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Veranstaltungsinformationen') ?>
+ </legend>
+ <? foreach ($semFields as $id => $name) : ?>
+ <?= $this->render_partial('admin/specification/_field', compact('rule', 'id', 'name')) ?>
+ <? endforeach ?>
+ </fieldset>
+
+<? if (count($entries_user) > 0) : ?>
+ <fieldset>
+ <legend>
+ <?= _('Personenbezogene Informationen') ?>
+ </legend>
+ <? foreach ($entries_user as $id => $entry) : ?>
+ <?= $this->render_partial('admin/specification/_field', [
+ 'rule' => $rule,
+ 'id' => $entry->datafield_id,
+ 'name' => $entry->name,
+ ]) ?>
+ <? endforeach ?>
+ </fieldset>
+<? endif ?>
- <? if (count($entries_user) > 0) : ?>
- <fieldset>
- <legend>
- <?= _('Personenbezogene Informationen') ?>
- </legend>
- <? foreach ($entries_user as $id => $entry) : ?>
- <?= $this->render_partial('admin/specification/_field',
- array_merge(compact('rule'), ['id' => $entry->datafield_id, 'name' => $entry->name])) ?>
- <? endforeach ?>
- </fieldset>
- <? endif ?>
<footer>
- <? if ($rule) : ?>
- <?= Button::createAccept(_('Übernehmen'), 'uebernehmen', ['title' => _('Änderungen übernehmen')]) ?>
- <? else : ?>
- <?= Button::createAccept(_('Erstellen'), 'erstellen', ['title' => _('Neue Regel erstellen')]) ?>
- <? endif ?>
- <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/specification'), ['title' => _('Zurück zur Übersicht')]) ?>
+ <? if ($rule->isNew()) : ?>
+ <?= Button::createAccept(_('Erstellen'), 'erstellen', ['title' => _('Neue Regel erstellen')]) ?>
+ <? else : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'uebernehmen', ['title' => _('Änderungen übernehmen')]) ?>
+ <? endif ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->indexURL(), ['title' => _('Zurück zur Übersicht')]) ?>
</footer>
</form>
-
-<?
-$sidebar = Sidebar::Get();
-if ($GLOBALS['perm']->have_perm('root')) {
- $actions = new ActionsWidget();
- $actions->addLink(_('Datenfelder bearbeiten'), URLHelper::getLink('dispatch.php/admin/datafields'), Icon::create('add', 'clickable'));
- $sidebar->addWidget($actions);
-}
-?>
diff --git a/app/views/admin/specification/index.php b/app/views/admin/specification/index.php
index b2b42ea..4538b6a 100644
--- a/app/views/admin/specification/index.php
+++ b/app/views/admin/specification/index.php
@@ -1,62 +1,63 @@
<?php
/**
* @var Admin_SpecificationController $controller
- * @var AuxLockRules[] $allrules
+ * @var AuxLockRule[] $rules
*/
?>
<form method="post" class="default">
<?= CSRFProtection::tokenTag() ?>
- <table class="default">
+ <table class="default <? if (count($rules) > 0) echo 'sortable-table'; ?>" data-sortlist="[[0, 0]]">
<caption>
<?= _('Verwaltung von Zusatzangaben') ?>
</caption>
<colgroup>
- <col style="width: 45%">
- <col style="width: 45%">
- <col style="width: 10%">
+ <col style="width: 40%">
+ <col>
+ <col style="width: 10ex">
+ <col style="width: 8ex">
</colgroup>
<thead>
<tr>
- <th><?= _('Name') ?></th>
- <th><?= _('Beschreibung') ?></th>
- <th><?= _('Aktionen') ?></th>
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="text"><?= _('Beschreibung') ?></th>
+ <th data-sort="htmldata">
+ <abbr title="<?= _('Anzahl der zugeordneten Veranstaltungen') ?>">#</abbr>
+ </th>
+ <th class="actions" data-sort="false"><?= _('Aktionen') ?></th>
</tr>
</thead>
<tbody>
- <? if (!empty($allrules)): ?>
- <? foreach ($allrules as $index => $rule) : ?>
- <tr>
- <td>
- <?= htmlReady($rule['name']) ?>
- </td>
- <td>
- <?= htmlReady($rule['description']) ?>
- </td>
- <td class="actions">
- <a href="<?=$controller->url_for('admin/specification/edit/'.$rule['lock_id']) ?>" style="vertical-align: bottom">
- <?= Icon::create('edit', 'clickable', ['title' => _('Regel bearbeiten')])->asImg() ?>
- </a>
- <?=Icon::create('trash', 'clickable', tooltip2(_('Regel löschen')))->asInput([
- 'formaction' => $controller->url_for('admin/specification/delete/' . $rule['lock_id']),
- 'data-confirm' => sprintf(_('Wollen Sie die Regel "%s" wirklich löschen?'), $rule['name']),
- 'style' => 'vertical-align: bottom'
- ])?>
- </td>
- </tr>
- <? endforeach ?>
- <? else : ?>
+ <? if (count($rules) === 0): ?>
<tr>
- <td colspan="3" style="text-align: center">
+ <td colspan="4" style="text-align: center">
<?= _('Es wurden noch keine Zusatzangaben definiert.') ?>
</td>
</tr>
<? endif ?>
+ <? foreach ($rules as $index => $rule) : ?>
+ <tr>
+ <td><?= htmlReady($rule->name) ?></td>
+ <td><?= htmlReady(Studip\Markup::removeHtml($rule->description)) ?></td>
+ <td data-sort-value="<?= count($rule->courses) ?>">
+ <?= number_format(count($rule->courses), 0, ',', '.') ?>
+ </td>
+ <td class="actions">
+ <a href="<?= $controller->edit($rule) ?>">
+ <?= Icon::create('edit')->asImg(['title' => _('Regel bearbeiten')]) ?>
+ </a>
+ <? if (count($rule->courses) > 0): ?>
+ <?= Icon::create('trash', Icon::ROLE_INACTIVE)->asImg(
+ tooltip2(_('Die Regel kann nicht gelöscht werden, da sie noch verwendet wird.'))
+ ) ?>
+ <? else: ?>
+ <?= Icon::create('trash')->asInput(tooltip2(_('Regel löschen')) + [
+ 'formaction' => $controller->deleteURL($rule),
+ 'data-confirm' => sprintf(_('Wollen Sie die Regel "%s" wirklich löschen?'), $rule->name),
+ ]) ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach ?>
</tbody>
</table>
</form>
-<?
-
-$sidebar = Sidebar::Get();
-$actions = new ActionsWidget();
-$actions->addLink(_('Neue Regel anlegen'), $controller->url_for('admin/specification/edit'), Icon::create('add', 'clickable'));
-$sidebar->addWidget($actions);
diff --git a/app/views/course/members/additional_input.php b/app/views/course/members/additional_input.php
index 89df041..50fd3b0 100644
--- a/app/views/course/members/additional_input.php
+++ b/app/views/course/members/additional_input.php
@@ -1,30 +1,38 @@
+<?php
+/**
+ * @var DataFieldEntryModel[] $datafields
+ * @var AuxLockRule $aux
+ * @var bool $editable
+ */
+$editable = false;
+?>
<form class="default" method="post">
- <? if ($datafields) : ?>
- <fieldset>
- <legend>
- <?= htmlReady($aux->name) ?>
- </legend>
+<? if ($datafields) : ?>
+ <fieldset>
+ <legend>
+ <?= htmlReady($aux->name) ?>
+ </legend>
- <p><?= formatReady($aux->description) ?></p>
+ <p><?= formatReady($aux->description) ?></p>
- <? foreach ($datafields as $field): ?>
- <? if ($field->getTypedDatafield()->isVisible()): ?>
- <? if ($field->getTypedDatafield()->isEditable()) : ?>
- <? $editable = true; ?>
- <? endif ?>
- <?= $field->getTypedDatafield()->getHTML('aux'); ?>
- <? endif; ?>
- <? endforeach; ?>
- </fieldset>
+ <? foreach ($datafields as $field): ?>
+ <? if ($field->getTypedDatafield()->isVisible()): ?>
+ <? if ($field->getTypedDatafield()->isEditable()) : ?>
+ <? $editable = true; ?>
+ <? endif ?>
+ <?= $field->getTypedDatafield()->getHTML('aux'); ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ </fieldset>
- <? if ($editable): ?>
- <footer>
- <?= \Studip\Button::create(_('Speichern'), 'save') ?>
- </footer>
- <? else: ?>
- <?= MessageBox::info(_('Keine einstellbaren Zusatzdaten vorhanden')) ?>
- <? endif; ?>
- <? else : ?>
+ <? if ($editable): ?>
+ <footer>
+ <?= Studip\Button::create(_('Speichern'), 'save') ?>
+ </footer>
+ <? else: ?>
<?= MessageBox::info(_('Keine einstellbaren Zusatzdaten vorhanden')) ?>
<? endif; ?>
+<? else : ?>
+ <?= MessageBox::info(_('Keine einstellbaren Zusatzdaten vorhanden')) ?>
+<? endif; ?>
</form>
diff --git a/db/migrations/5.3.9_convert_aux_lock_rules_json_fields.php b/db/migrations/5.3.9_convert_aux_lock_rules_json_fields.php
new file mode 100644
index 0000000..56b1c2b
--- /dev/null
+++ b/db/migrations/5.3.9_convert_aux_lock_rules_json_fields.php
@@ -0,0 +1,56 @@
+<?php
+final class ConvertAuxLockRulesJsonFields extends Migration
+{
+ public function description()
+ {
+ return parent::description(); // TODO: Change the autogenerated stub
+ }
+
+ protected function up()
+ {
+ $query = "SELECT `lock_id`, `attributes`, `sorting` FROM `aux_lock_rules`";
+ $rows = DBManager::get()->fetchAll($query);
+
+ $query = "UPDATE `aux_lock_rules`
+ SET `attributes` = :attributes,
+ `sorting` = :sorting
+ WHERE `lock_id` = :id";
+ $statement = DBManager::get()->prepare($query);
+
+ foreach ($rows as $row) {
+ $attributes = json_decode($row['attributes'], true) ?: [];
+ $attributes = array_filter($attributes);
+ $attributes = array_keys($attributes);
+
+ $sorting = json_decode($row['sorting'], true) ?: [];
+ $sorting = array_filter($sorting, function ($id) use ($attributes) {
+ return in_array($id, $attributes);
+ }, ARRAY_FILTER_USE_KEY);
+
+ $statement->bindValue(':id', $row['lock_id']);
+ $statement->bindValue(':attributes', json_encode($attributes));
+ $statement->bindValue(':sorting', json_encode($sorting));
+ $statement->execute();
+ }
+ }
+
+ protected function down()
+ {
+ $query = "SELECT `lock_id`, `attributes` FROM `aux_lock_rules`";
+ $rows = DBManager::get()->fetchAll($query);
+
+ $query = "UPDATE `aux_lock_rules`
+ SET `attributes` = :attributes
+ WHERE `lock_id` = :id";
+ $statement = DBManager::get()->prepare($query);
+
+ foreach ($rows as $row) {
+ $attributes = json_decode($row['attributes'], true) ?: [];
+ $attributes = array_fill_keys($attributes, '1');
+
+ $statement->bindValue(':id', $row['lock_id']);
+ $statement->bindValue(':attributes', json_encode($attributes));
+ $statement->execute();
+ }
+ }
+}
diff --git a/lib/classes/AuxLockRules.class.php b/lib/classes/AuxLockRules.class.php
index 6a6dfd9..4d06ca2 100644
--- a/lib/classes/AuxLockRules.class.php
+++ b/lib/classes/AuxLockRules.class.php
@@ -23,6 +23,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+/**
+ * @deprecated since Stud.IP 5.3
+ */
class AuxLockRules
{
diff --git a/lib/classes/Markup.class.php b/lib/classes/Markup.class.php
index af298be..0f5a5c8 100644
--- a/lib/classes/Markup.class.php
+++ b/lib/classes/Markup.class.php
@@ -233,7 +233,7 @@ class Markup
* Create HTML purifier instance with Stud.IP-specific configuration.
*
* @param boolean $autoformat Apply the AutoFormat rules
- * @return HTMLPurifier A new instance of the HTML purifier.
+ * @return \HTMLPurifier A new instance of the HTML purifier.
*/
private static function createPurifier($autoformat)
{
diff --git a/lib/classes/StudipArrayObject.class.php b/lib/classes/StudipArrayObject.class.php
index bb5444c..f025ffb 100644
--- a/lib/classes/StudipArrayObject.class.php
+++ b/lib/classes/StudipArrayObject.class.php
@@ -436,4 +436,12 @@ class StudipArrayObject implements IteratorAggregate, ArrayAccess, Serializable,
throw new InvalidArgumentException("{$key} is a protected property, use a different key");
}
}
+
+ /**
+ * Returns whether the given value is in the underlying array.
+ */
+ public function contains($value): bool
+ {
+ return in_array($value, $this->storage);
+ }
}
diff --git a/lib/classes/WidgetContainer.php b/lib/classes/WidgetContainer.php
index b4aaa8c..108477a 100644
--- a/lib/classes/WidgetContainer.php
+++ b/lib/classes/WidgetContainer.php
@@ -46,10 +46,11 @@ abstract class WidgetContainer
/**
* Add a widget to the container.
*
- * @param Widget $widget The actual widget
+ * @template W of Widget
+ * @param W $widget The actual widget
* @param String $index Optional index/name of the widget, defaults to
* class name without "widget"
- * @return Widget The added widget to allow for easier handling
+ * @return W The added widget to allow for easier handling
*/
public function addWidget(Widget $widget, $index = null)
{
diff --git a/lib/models/AuxLockRule.php b/lib/models/AuxLockRule.php
index d0686a9..4bf8e8b 100644
--- a/lib/models/AuxLockRule.php
+++ b/lib/models/AuxLockRule.php
@@ -13,31 +13,75 @@
* @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
* @category Stud.IP
* @since 3.0
+ *
* @property string lock_id database column
* @property string id alias column for lock_id
* @property string name database column
* @property string description database column
- * @property string attributes database column
- * @property string sorting database column
+ * @property JSONArrayObject attributes database column
+ * @property JSONArrayObject sorting database column
* @property array datafields computed column
* @property string order computed column
- * @property Course course belongs_to Course
+ * @property Course[]|SimpleORMapCollection courses has_and_belongs_to_many Courses
*/
class AuxLockRule extends SimpleORMap
{
protected static function configure($config = [])
{
$config['db_table'] = 'aux_lock_rules';
- $config['belongs_to']['course'] = [
- 'class_name' => Course::class,
- 'foreign_key' => 'lock_id',
- 'assoc_foreign_key' => 'aux_lock_rule',
+
+ $config['has_many'] = [
+ 'courses' => [
+ 'class_name' => Course::class,
+ 'foreign_key' => 'lock_id',
+ 'assoc_foreign_key' => 'aux_lock_rule',
+ ],
+ ];
+
+ $config['additional_fields'] = [
+ 'datafields' => true
+ ];
+
+ $config['serialized_fields'] = [
+ 'attributes' => JSONArrayObject::class,
+ 'sorting' => JSONArrayObject::class,
];
- $config['additional_fields']['datafields'] = true;
- $config['additional_fields']['order'] = true;
+
+ $config['i18n_fields'] = [
+ 'name' => true,
+ 'description' => true,
+ ];
+
+ $config['registered_callbacks'] = [
+ 'before_store' => [
+ function (AuxLockRule $rule) {
+ $rule->sorting = array_filter($rule->sorting->getArrayCopy(), function ($id) use ($rule) {
+ return $rule->attributes->contains($id);
+ }, ARRAY_FILTER_USE_KEY);
+ },
+ ],
+ 'before_delete' => [
+ function (AuxLockRule $rule) {
+ return count($rule->courses) === 0;
+ },
+ ]
+ ];
+
parent::configure($config);
}
+ public static function findOneByCourse(Course $course): ?AuxLockRule
+ {
+ return self::findOneByCourseId($course->id);
+ }
+
+ public static function findOneByCourseId(string $course_id): ?AuxLockRule
+ {
+ $condition = "JOIN seminare ON lock_id = aux_lock_rule
+ WHERE Seminar_id = ?";
+ return self::findOneBySQL($condition, [$course_id]);
+ }
+
/**
* Cache to avoid loading datafields for a user more than once
*/
@@ -50,8 +94,8 @@ class AuxLockRule extends SimpleORMap
*/
public function getDatafields()
{
- $attributes = json_decode($this->attributes, true) ?: [];
- $sorting = json_decode($this->sorting, true) ?: [];
+ $attributes = $this->attributes->getArrayCopy();
+ $sorting = $this->sorting->getArrayCopy();
foreach ($attributes as $key => $attr) {
if (!$attr) {
@@ -64,11 +108,8 @@ class AuxLockRule extends SimpleORMap
/**
* Updates a datafield of a courseMember by the given data
- *
- * @param object $member
- * @param object $data
*/
- public function updateMember($member, $data)
+ public function updateMember(CourseMember $member, array $data)
{
foreach ($data as $key => $value) {
$datafield = current($this->getDatafield($member, $key));
@@ -88,23 +129,22 @@ class AuxLockRule extends SimpleORMap
*/
public function getCourseData($course = null, $display_only = false)
{
-
// set course
if (!$course) {
$course = $this->course;
}
$mapping = [
- 'vadozent' => join(', ', $course->members->findBy('status', 'dozent')->getUserFullname()),
+ 'vadozent' => join(', ', $course->members->findBy('status', 'dozent')->getUserFullname()),
'vasemester' => $course->start_semester->name,
- 'vatitle' => $course->name,
- 'vanr' => $course->VeranstaltungsNummer,
+ 'vatitle' => $course->name,
+ 'vanr' => $course->veranstaltungsnummer,
];
$head_mapping = [
- 'vadozent' => _('Dozenten'),
+ 'vadozent' => _('Dozenten'),
'vasemester' => _('Semester'),
- 'vatitle' => _('Veranstaltungstitel'),
- 'vanr' => _('Veranstaltungsnummer'),
+ 'vatitle' => _('Veranstaltungstitel'),
+ 'vanr' => _('Veranstaltungsnummer'),
];
// start collecting entries
@@ -145,38 +185,44 @@ class AuxLockRule extends SimpleORMap
return $result;
}
- public function getMemberData($member)
+ public function getMemberData(CourseMember $member)
{
$datafields = SimpleCollection::createFromArray(DatafieldEntryModel::findByModel($member));
$result = [];
- foreach (array_keys($this->datafields) as $field) {
+ foreach ($this->attributes as $field) {
// since we have no only datafields we have to filter!
- if ($new = $datafields->findOneBy('datafield_id', $field)) {
+ $new = $datafields->findOneBy('datafield_id', $field);
+ if ($new) {
$result[] = $new;
}
}
+
+ usort($result, function (DatafieldEntryModel $a, DatafieldEntryModel $b) {
+ $a_order = $this->sorting[$a->datafield_id] ?? 0;
+ $b_order = $this->sorting[$b->datafield_id] ?? 0;
+ return $a_order - $b_order;
+ });
+
return $result;
}
/**
* Caching for the datafields
- * @param type $member
- * @param type $fieldID
- * @return null
*/
- private function getDatafield($member, $fieldID)
+ private function getDatafield(CourseMember $member, $field_id): ?array
{
- if (mb_strlen($fieldID) == 32) {
- if (!array_key_exists($fieldID, $this->datafieldCache)) {
- $this->datafieldCache[$fieldID] = DataField::find($fieldID);
+ if (mb_strlen($field_id) === 32) {
+ if (!array_key_exists($field_id, $this->datafieldCache)) {
+ $this->datafieldCache[$field_id] = DataField::find($field_id);
}
- if (isset($this->datafieldCache[$fieldID])) {
- if ($this->datafieldCache[$fieldID]->object_type == 'usersemdata') {
- $field = current(DatafieldEntryModel::findByModel($member, $fieldID));
+ if (isset($this->datafieldCache[$field_id])) {
+ $field = null;
+ if ($this->datafieldCache[$field_id]->object_type === 'usersemdata') {
+ $field = current(DatafieldEntryModel::findByModel($member, $field_id));
}
- if ($this->datafieldCache[$fieldID]->object_type == 'user') {
- $field = current(DatafieldEntryModel::findByModel(User::find($member->user_id), $fieldID));
+ if ($this->datafieldCache[$field_id]->object_type === 'user') {
+ $field = current(DatafieldEntryModel::findByModel(User::find($member->user_id), $field_id));
}
if ($field) {
$range_id = $field->sec_range_id ? [$field->range_id, $field->sec_range_id] : $field->range_id;
@@ -185,6 +231,19 @@ class AuxLockRule extends SimpleORMap
}
}
}
+
+ return null;
}
+ public static function validateFields(array $fields): bool
+ {
+ $entries = DataField::getDataFields('usersemdata');
+ foreach ($entries as $entry) {
+ if (in_array($entry->id, $fields)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
diff --git a/lib/models/DatafieldEntryModel.class.php b/lib/models/DatafieldEntryModel.class.php
index fa7a878..882b37e 100644
--- a/lib/models/DatafieldEntryModel.class.php
+++ b/lib/models/DatafieldEntryModel.class.php
@@ -48,37 +48,44 @@ class DatafieldEntryModel extends SimpleORMap implements PrivacyObject
*/
public static function findByModel(SimpleORMap $model, $datafield_id = null)
{
- $mask = ["user" => 1, "autor" => 2, "tutor" => 4, "dozent" => 8, "admin" => 16, "root" => 32];
+ $mask = [
+ 'user' => 1,
+ 'autor' => 2,
+ 'tutor' => 4,
+ 'dozent' => 8,
+ 'admin' => 16,
+ 'root' => 32,
+ ];
$sec_range_id = null;
- if (is_a($model, "Course")) {
+ if ($model instanceof Course) {
$params[':institution_ids'] = $model->institutes->pluck('institut_id');
$object_class = SeminarCategories::GetByTypeId($model->status)->id;
$object_type = 'sem';
- $range_id = $model->getId();
- } elseif(is_a($model, "Institute")) {
- $params[':institution_ids'] = [$model->Institut_id];
+ $range_id = $model->id;
+ } elseif ($model instanceof Institute) {
+ $params[':institution_ids'] = [$model->id];
$object_class = $model->type;
$object_type = 'inst';
- $range_id = $model->getId();
- } elseif(is_a($model, "User")) {
+ $range_id = $model->id;
+ } elseif ($model instanceof User) {
$params[':institution_ids'] = $model->institute_memberships->pluck('institut_id');
$object_class = $mask[$model->perms];
$object_type = 'user';
- $range_id = $model->getId();
- } elseif(is_a($model, "CourseMember")) {
+ $range_id = $model->id;
+ } elseif($model instanceof CourseMember) {
$params[':institution_ids'] = $model->course->institutes->pluck('institut_id');
$object_class = $mask[$model->status];
$object_type = 'usersemdata';
$range_id = $model->user_id;
$sec_range_id = $model->seminar_id;
- } elseif(is_a($model, "InstituteMember")) {
+ } elseif($model instanceof InstituteMember) {
$params[':institution_ids'] = [$model->institut_id];
$object_class = $mask[$model->inst_perms];
$object_type = 'userinstrole';
$range_id = $model->user_id;
$sec_range_id = $model->institut_id;
- } elseif (is_a($model, 'ModulDeskriptor')) {
+ } elseif ($model instanceof ModulDeskriptor) {
$params[':institution_ids'] = '';
if (!empty($model->modul->responsible_institute->institut_id)) {
$params[':institution_ids'] = [$model->modul->responsible_institute->institut_id];
@@ -86,7 +93,7 @@ class DatafieldEntryModel extends SimpleORMap implements PrivacyObject
$object_class = $model->getVariant();
$object_type = 'moduldeskriptor';
$range_id = $model->deskriptor_id;
- } elseif (is_a($model, 'ModulteilDeskriptor')) {
+ } elseif ($model instanceof ModulteilDeskriptor) {
$params[':institution_ids'] = [$model->modulteil->modul->responsible_institute->institut_id];
$object_class = $model->getVariant();
$object_type = 'modulteildeskriptor';
@@ -106,46 +113,50 @@ class DatafieldEntryModel extends SimpleORMap implements PrivacyObject
$object_class = $model->getVariant();
$object_type = 'studycourse';
$range_id = $model->studiengang_id;
- }
-
- if (!$object_type) {
+ } else {
throw new InvalidArgumentException('Wrong type of model: ' . get_class($model));
}
- $one_datafield = '';
+
+ $query = "SELECT a.*, b.*, a.datafield_id, b.datafield_id AS isset_content
+ FROM datafields a
+ LEFT JOIN datafields_entries b
+ ON (a.datafield_id=b.datafield_id AND range_id = :range_id AND sec_range_id = :sec_range_id)
+ WHERE object_type = :object_type
+ AND (lang IS NULL OR lang = '')
+ AND (a.institut_id IS NULL OR a.institut_id IN (:institution_ids))";
+
if ($datafield_id !== null) {
- $one_datafield = ' AND a.datafield_id = ' . DBManager::get()->quote($datafield_id);
- } else {
- $one_datafield = '';
+ $query .= ' AND a.datafield_id = :one_datafield_id';
+ $params[':one_datafield_id'] = $datafield_id;
}
- $query = "SELECT a.*, b.*,a.datafield_id,b.datafield_id as isset_content ";
- $query .= "FROM datafields a LEFT JOIN datafields_entries b ON (a.datafield_id=b.datafield_id AND range_id = :range_id AND sec_range_id = :sec_range_id) ";
- $query .= "WHERE object_type = :object_type AND (ISNULL(lang) OR lang = '') AND (a.institut_id IS NULL OR a.institut_id IN (:institution_ids))";
-
if ($object_type === 'studycourse') {
- $query .= "AND (LOCATE(:object_class, object_class) OR LOCATE('all', object_class)) $one_datafield ORDER BY priority";
+ $query .= " AND (LOCATE(:object_class, object_class) OR LOCATE('all', object_class)) ORDER BY priority";
$params = array_merge($params,[
- ':range_id' => (string) $range_id,
+ ':range_id' => (string) $range_id,
':sec_range_id' => (string) $sec_range_id,
- ':object_type' => $object_type,
- ':object_class' => (string) $object_class]);
+ ':object_type' => $object_type,
+ ':object_class' => (string) $object_class,
+ ]);
} elseif ($object_type === 'moduldeskriptor'
|| $object_type === 'modulteildeskriptor') {
// find datafields by language (string)
- $query .= "AND (LOCATE(:object_class, object_class) OR object_class IS NULL) $one_datafield ORDER BY priority";
+ $query .= " AND (LOCATE(:object_class, object_class) OR object_class IS NULL) ORDER BY priority";
$params = array_merge($params,[
- ':range_id' => (string) $range_id,
+ ':range_id' => (string) $range_id,
':sec_range_id' => (string) $sec_range_id,
- ':object_type' => $object_type,
- ':object_class' => (string) $object_class]);
+ ':object_type' => $object_type,
+ ':object_class' => (string) $object_class,
+ ]);
} else {
// find datafields by perms or status (int)
- $query .= "AND ((object_class & :object_class) OR object_class IS NULL) $one_datafield ORDER BY priority";
+ $query .= " AND ((object_class & :object_class) OR object_class IS NULL) ORDER BY priority";
$params = array_merge($params, [
- ':range_id' => (string) $range_id,
+ ':range_id' => (string) $range_id,
':sec_range_id' => (string) $sec_range_id,
- ':object_type' => $object_type,
- ':object_class' => (int) $object_class]);
+ ':object_type' => $object_type,
+ ':object_class' => (int) $object_class,
+ ]);
}
$st = DBManager::get()->prepare($query);
@@ -181,6 +192,7 @@ class DatafieldEntryModel extends SimpleORMap implements PrivacyObject
}
return $ret;
}
+
public function setContentLanguage($language)
{
if (!Config::get()->CONTENT_LANGUAGES[$language]) {
diff --git a/templates/i18n/input.php b/templates/i18n/input.php
index 9c9a456..3ab92a5 100644
--- a/templates/i18n/input.php
+++ b/templates/i18n/input.php
@@ -1,3 +1,13 @@
+<?php
+/**
+ * @var array $languages
+ * @var array $attributes
+ * @var string $base_lang
+ * @var string $name
+ * @var I18NString $value
+ *
+ */
+?>
<? foreach ($languages as $locale => $lang): ?>
<?
$attr = $attributes;