From 1231022837beceedef376e4bb8084ff38fbc7d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michaela=20Br=C3=BCckner?= <brueckner@data-quest.de> Date: Thu, 24 Nov 2022 10:00:25 +0000 Subject: [PATCH] Resolve "Visuelle Kennzeichnung von barrierefreien Dateien in den Dateibereichen", closes #1540 Closes #1540 Merge request studip/studip!1027 --- .../admin/accessibility_info_text.php | 33 +++++++++++++ app/controllers/file.php | 19 +++++++- .../admin/accessibility_info_text/index.php | 19 ++++++++ app/views/file/_file_aside.php | 6 +++ app/views/file/_terms_of_use_select.php | 3 ++ app/views/file/edit.php | 12 ++++- app/views/file/edit_license.php | 29 ++++++++--- ....3.8_add_accessibility_field_for_files.php | 48 +++++++++++++++++++ lib/filesystem/FileType.php | 6 ++- lib/filesystem/FilesystemVueDataManager.php | 1 + lib/filesystem/StandardFile.php | 4 ++ lib/filesystem/UnknownFileType.php | 8 ++++ lib/models/FileRef.php | 9 ++++ lib/navigation/AdminNavigation.php | 8 ++++ .../images/icons/black/accessibility.svg | 1 + resources/vue/components/FilesTable.vue | 11 ++++- 16 files changed, 205 insertions(+), 12 deletions(-) create mode 100644 app/controllers/admin/accessibility_info_text.php create mode 100644 app/views/admin/accessibility_info_text/index.php create mode 100644 db/migrations/5.3.8_add_accessibility_field_for_files.php create mode 100644 public/assets/images/icons/black/accessibility.svg diff --git a/app/controllers/admin/accessibility_info_text.php b/app/controllers/admin/accessibility_info_text.php new file mode 100644 index 00000000000..9a1828bcc73 --- /dev/null +++ b/app/controllers/admin/accessibility_info_text.php @@ -0,0 +1,33 @@ +<?php +/** + * accessibility_info_text.php - controller class for administrating additional information text to accessible files + * in file upload/edit dialogs + * + * @author Michaela Brückner <brueckner@data-quest.de> + * @license GPL2 or any later version + * @category Stud.IP + * @package admin + * @since 5.3 + */ +class Admin_AccessibilityInfoTextController extends AuthenticatedController +{ + public function before_filter(&$action, &$args) + { + parent::before_filter($action, $args); + $GLOBALS['perm']->check('root'); + PageLayout::setTitle(_('Infotext zu barrierefreien Dateien')); + Navigation::activateItem('/admin/locations/accessibility_info_text'); + } + + public function index_action() + { + } + + public function edit_action() + { + CSRFProtection::verifyUnsafeRequest(); + Config::get()->store('ACCESSIBILITY_INFO_TEXT', Request::i18n('accessbility_info_text')); + PageLayout::postSuccess(_('Die Einstellungen wurden gespeichert.')); + $this->relocate('admin/accessibility_info_text/index'); + } +} diff --git a/app/controllers/file.php b/app/controllers/file.php index f418109d352..b1ed35a0b8d 100644 --- a/app/controllers/file.php +++ b/app/controllers/file.php @@ -378,6 +378,8 @@ class FileController extends AuthenticatedController $force_save = Request::submitted('force_save'); $this->name = trim(Request::get('name')); $this->description = Request::get('description'); + $this->store_accessibility_flag($file_ref_id); + $this->content_terms_of_use_id = Request::get('content_terms_of_use_id'); //Check if the FileRef is unmodified: @@ -1541,6 +1543,12 @@ class FileController extends AuthenticatedController if (Request::isPost()) { CSRFProtection::verifyUnsafeRequest(); + + if (count($file_ref_ids) === 1) { + // store flag if file is an accessible file + $this->store_accessibility_flag($file_ref_ids[0]); + } + if (($folder_id == 'bulk') && !Request::submitted('accept')) { $file_ref_ids = Request::getArray('ids'); $this->file_refs = FileRef::findMany($file_ref_ids); @@ -1662,8 +1670,8 @@ class FileController extends AuthenticatedController PageLayout::setTitle(sprintf( ngettext( - 'Lizenz auswählen', - 'Lizenz auswählen: %s Dateien', + 'Zusatzangaben und Lizenz wählen', + 'Zusatzangaben und Lizenz auswählen: %s Dateien', count($this->file_refs) ), count($this->file_refs) @@ -2159,4 +2167,11 @@ class FileController extends AuthenticatedController } return [$folder_size, $folder_file_amount]; } + + private function store_accessibility_flag($file_ref_id) + { + $file_ref = FileRef::find($file_ref_id); + $file_ref->file['is_accessible'] = Request::get('is_accessible'); + $file_ref->file->store(); + } } diff --git a/app/views/admin/accessibility_info_text/index.php b/app/views/admin/accessibility_info_text/index.php new file mode 100644 index 00000000000..c236099ccbe --- /dev/null +++ b/app/views/admin/accessibility_info_text/index.php @@ -0,0 +1,19 @@ +<form class="default a11y-settings" action="<?= $controller->url_for('admin/accessibility_info_text/edit') ?>" method="post"> + <?= CSRFProtection::tokenTag() ?> + + <fieldset> + <legend><?= _('Infotext zu barrierefreien Dateien') ?></legend> + <section> + <label for="accessbility_info_text"> + <?= _('Die angegebene Information wird im Datei-Hochladen-Dialog unter der Checkbox angezeigt.') ?> + </label> + <?= I18N::textarea('accessbility_info_text', Config::get()->ACCESSIBILITY_INFO_TEXT, + ['class' => 'add_toolbar wysiwyg', 'data-editor' => 'toolbar=small']) ?> + </section> + </fieldset> + + <footer data-dialog-button> + <?= CSRFProtection::tokenTag() ?> + <?= Studip\Button::createAccept(_('Speichern'), 'store') ?> + </footer> +</form> diff --git a/app/views/file/_file_aside.php b/app/views/file/_file_aside.php index 47f33f38e29..e626f324f4e 100644 --- a/app/views/file/_file_aside.php +++ b/app/views/file/_file_aside.php @@ -36,6 +36,12 @@ <? endif ?> </td> </tr> + <tr> + <td><?= _('Barrierefrei') ?></td> + <td> + <?= $file->getAccessibility() ? _('ja') : _('nein') ?> + </td> + </tr> <? $content_terms_of_use = $file->getTermsOfUse() ?> diff --git a/app/views/file/_terms_of_use_select.php b/app/views/file/_terms_of_use_select.php index c1dd994e95e..59cb5079b20 100644 --- a/app/views/file/_terms_of_use_select.php +++ b/app/views/file/_terms_of_use_select.php @@ -4,6 +4,8 @@ if (!$selected_terms_of_use_id) { } ?> <? if ($content_terms_of_use_entries) : ?> +<fieldset> + <legend><?= _('Lizenzauswahl') ?></legend> <div style="margin-bottom: 1ex;"> <?= _('Bereitgestellte Dateien können heruntergeladen und ggf. weiterverbreitet werden. Dabei ist das Urheberrecht sowohl beim Hochladen der Datei als auch bei der Nutzung @@ -47,4 +49,5 @@ if (!$selected_terms_of_use_id) { <? endif ?> <? endforeach ?> </fieldset> +</fieldset> <? endif; ?> diff --git a/app/views/file/edit.php b/app/views/file/edit.php index 737d2414b6e..3e36abb312a 100644 --- a/app/views/file/edit.php +++ b/app/views/file/edit.php @@ -7,8 +7,7 @@ <?= CSRFProtection::tokenTag() ?> <fieldset> - <legend><?= _('Datei bearbeiten') ?></legend> - + <legend><?= _('Zusatzangaben') ?></legend> <label> <?= _('Name') ?> <input id="edit_file_name" type="text" name="name" @@ -20,6 +19,15 @@ </label> </fieldset> + <fieldset> + <legend><?= _('Barrierefreiheit') ?></legend> + <label> + <input type="checkbox" name="is_accessible" value="1" <?= $file->getAccessibility() ? "checked" : "" ?>> + <?= _('Diese Datei ist barrierefrei.') ?> + </label> + <?= formatReady((string)Config::get()->ACCESSIBILITY_INFO_TEXT ?: '') ?> + </fieldset> + <?= $this->render_partial('file/_terms_of_use_select.php', [ 'content_terms_of_use_entries' => $content_terms_of_use_entries, 'selected_terms_of_use_id' => $content_terms_of_use->id, diff --git a/app/views/file/edit_license.php b/app/views/file/edit_license.php index ebd5ff01de4..ddd031d153c 100644 --- a/app/views/file/edit_license.php +++ b/app/views/file/edit_license.php @@ -5,21 +5,38 @@ <input type="hidden" name="file_refs[]" value="<?= htmlReady($file_ref->id) ?>"> <? endforeach ?> + <? if ($show_description_field): ?> + <fieldset> + <legend><?= _('Zusatzangaben') ?></legend> <label> - <?= _('Beschreibung') ?> + <b><?= _('Beschreibung') ?></b> <textarea name="description" placeholder="<?= _('Optionale Beschreibung') ?>"></textarea> </label> + </fieldset> + <? endif ?> - <?= $this->render_partial('file/_terms_of_use_select.php', [ - 'content_terms_of_use_entries' => $licenses, - 'selected_terms_of_use_id' => $file_ref->content_terms_of_use_id - ]) ?> + + <? if (count($file_refs) === 1) : ?> + <fieldset> + <legend><?= _('Barrierefreiheit') ?></legend> + <label> + <input type="checkbox" name="is_accessible" value="1"> + <?= _('Diese Datei ist barrierefrei.') ?> + </label> + <?= formatReady((string)Config::get()->ACCESSIBILITY_INFO_TEXT ?: '') ?> + </fieldset> + <? endif ?> + + <?= $this->render_partial('file/_terms_of_use_select.php', [ + 'content_terms_of_use_entries' => $licenses, + 'selected_terms_of_use_id' => $file_ref->content_terms_of_use_id + ]) ?> <footer data-dialog-button> <?= Studip\Button::createAccept(_('Speichern')) ?> <?= Studip\LinkButton::createCancel( - _('Lizenzauswahl abbrechen'), + _('Abbrechen'), $controller->url_for((in_array($folder->range_type, ['course', 'institute']) ? $folder->range_type . '/' : '') . 'files/index/' . $folder->id) ) ?> </footer> diff --git a/db/migrations/5.3.8_add_accessibility_field_for_files.php b/db/migrations/5.3.8_add_accessibility_field_for_files.php new file mode 100644 index 00000000000..e9ee2475f96 --- /dev/null +++ b/db/migrations/5.3.8_add_accessibility_field_for_files.php @@ -0,0 +1,48 @@ +<?php + + +class AddAccessibilityFieldForFiles extends Migration +{ + public function description() + { + return 'Add field is_accessible to file table; creates config for accessibility info text'; + } + + public function up() + { + $db = DBManager::get(); + + $db->exec( + "ALTER TABLE `files` + ADD `is_accessible` TINYINT(1) NULL AFTER `author_name`" + ); + + + $query = 'INSERT INTO `config` (`field`, `value`, `type`, `section`, `range`, `description`, `mkdate`, `chdate`) + VALUES (:name, :value, :type, :section, :range, :description, UNIX_TIMESTAMP(), UNIX_TIMESTAMP())'; + $statement = DBManager::get()->prepare($query); + $statement->execute([ + 'name' => 'ACCESSIBILITY_INFO_TEXT', + 'value' => '', + 'type' => 'i18n', + 'section' => 'accessibility', + 'range' => 'global', + 'description' => 'Diese Konfiguration bitte unter Admin -> Standort -> Infotext zu barrierefreien Dateien anpassen!' + ]); + + } + + public function down() + { + $db = DBManager::get(); + + $db->exec( + "ALTER TABLE `files` DROP `is_accessible`" + ); + + $query = "DELETE `config`, `config_values` + FROM `config` LEFT JOIN `config_values` USING (`field`) + WHERE `field` = 'ACCESSIBILITY_INFO_TEXT'"; + DBManager::get()->exec($query); + } +} diff --git a/lib/filesystem/FileType.php b/lib/filesystem/FileType.php index 003ee856a9a..5a53896fdc9 100644 --- a/lib/filesystem/FileType.php +++ b/lib/filesystem/FileType.php @@ -35,13 +35,17 @@ interface FileType */ public function getUserName(); + /** + * Returns if a file is accessible or not. + * @return bool + */ + public function getAccessibility(): bool; /** * @returns The User object representing the author. */ public function getUser(); - /** * Returns the size of the file in bytes. If this is null, the file doesn't exist * physically - is probably only a weblink or a request for libraries. diff --git a/lib/filesystem/FilesystemVueDataManager.php b/lib/filesystem/FilesystemVueDataManager.php index 0714356f721..06ea27313c2 100644 --- a/lib/filesystem/FilesystemVueDataManager.php +++ b/lib/filesystem/FilesystemVueDataManager.php @@ -44,6 +44,7 @@ class FilesystemVueDataManager 'actions' => $actionMenu ? (is_string($actionMenu) ? $actionMenu : $actionMenu->render()) : "", 'new' => isset($last_visitdate) && $file->getLastChangeDate() > $last_visitdate && $file->getUserId() !== $GLOBALS['user']->id, 'isEditable' => $file->isEditable(), + 'isAccessible' => $file->getAccessibility(), ]; } diff --git a/lib/filesystem/StandardFile.php b/lib/filesystem/StandardFile.php index 5a4271ab5ff..c11541066be 100644 --- a/lib/filesystem/StandardFile.php +++ b/lib/filesystem/StandardFile.php @@ -174,6 +174,10 @@ class StandardFile implements FileType, ArrayAccess, StandardFileInterface return $this->fileref['author_name']; } + public function getAccessibility(): bool + { + return (bool) $this->fileref['is_accessible']; + } public function getUser() { diff --git a/lib/filesystem/UnknownFileType.php b/lib/filesystem/UnknownFileType.php index effe75178de..15c2b92e13f 100644 --- a/lib/filesystem/UnknownFileType.php +++ b/lib/filesystem/UnknownFileType.php @@ -284,4 +284,12 @@ class UnknownFileType implements FileType, ArrayAccess { return ''; } + + /** + * @inheritDoc + */ + public function getAccessibility() : bool + { + return false; + } } diff --git a/lib/models/FileRef.php b/lib/models/FileRef.php index 48c64dc6150..9cc24388141 100644 --- a/lib/models/FileRef.php +++ b/lib/models/FileRef.php @@ -60,6 +60,7 @@ class FileRef extends SimpleORMap implements PrivacyObject, FeedbackRange $config['additional_fields']['download_url']['set'] = 'setDownloadURL'; $config['additional_fields']['download_url']['get'] = 'getDownloadURL'; $config['additional_fields']['author_name']['get'] = 'getAuthorName'; + $config['additional_fields']['is_accessible']['get'] = 'getAccessibility'; $config['additional_fields']['is_link']['get'] = 'isLink'; $config['additional_fields']['foldertype']['set'] = 'setFolderType'; $config['additional_fields']['foldertype']['get'] = 'getFolderType'; @@ -189,6 +190,14 @@ class FileRef extends SimpleORMap implements PrivacyObject, FeedbackRange return $this->file->author_name; } + /** + * Returns true if the file is accessible + */ + public function getAccessibility() : bool + { + return (bool) $this->file->is_accessible; + } + /** * This method increments the download counter of the FileRef. * diff --git a/lib/navigation/AdminNavigation.php b/lib/navigation/AdminNavigation.php index 2bb24189e00..b45859c59c7 100644 --- a/lib/navigation/AdminNavigation.php +++ b/lib/navigation/AdminNavigation.php @@ -153,6 +153,14 @@ class AdminNavigation extends Navigation ); } + $navigation->addSubNavigation( + 'accessibility_info_text', + new Navigation( + _('Infotext zu barrierefreien Dateien'), + 'dispatch.php/admin/accessibility_info_text/index' + ) + ); + } $this->addSubNavigation('locations', $navigation); diff --git a/public/assets/images/icons/black/accessibility.svg b/public/assets/images/icons/black/accessibility.svg new file mode 100644 index 00000000000..2c1f0fe03eb --- /dev/null +++ b/public/assets/images/icons/black/accessibility.svg @@ -0,0 +1 @@ +<svg viewBox="0 0 54 54" xmlns="http://www.w3.org/2000/svg"><g fill="#000000"><path d="m27 8c10.5 0 19 8.5 19 19s-8.5 19-19 19-19-8.6-19-19 8.5-19 19-19m0-5c-13.3 0-24 10.7-24 24s10.7 24 24 24 24-10.7 24-24-10.7-24-24-24z"/><circle cx="27" cy="15" r="4"/><path d="m38.2 19.1c-.6-.9-1.7-1.1-2.7-.8l-5.8 2.1c-.8.4-1.8.6-2.7.6h-.2c-.9 0-1.9-.2-2.8-.5l-5.8-2.1c-1-.4-2.1-.1-2.7.8-.8 1.2-.2 2.8 1.1 3.3l7.4 2.7c.3.1.5.4.5.7v3.7c0 .3-.1.6-.2.9l-4.5 7.9c-.5.9-.4 2.1.3 2.8 1.1 1 2.7.7 3.4-.5l3.5-6.1 3.6 6.2c.6 1 1.9 1.4 3 .8 1-.6 1.4-2 .8-3.1l-4.6-7.9c-.2-.3-.2-.6-.2-.9v-3.8c0-.3.2-.6.5-.7l7.2-2.6c1.2-.6 1.8-2.2.9-3.5z"/></g></svg> diff --git a/resources/vue/components/FilesTable.vue b/resources/vue/components/FilesTable.vue index 875b07635bb..c694a024f6f 100644 --- a/resources/vue/components/FilesTable.vue +++ b/resources/vue/components/FilesTable.vue @@ -180,8 +180,15 @@ data-lightbox="gallery"></a> </td> <td :class="{'filter-match': valueMatchesFilter(file.name)}"> + <a :href="file.details_url" data-dialog> <span v-html="highlightString(file.name)"></span> + <studip-icon v-if="file.isAccessible" + shape="accessibility" + role="info" + size="16" + style="vertical-align: text-bottom" + :title="$gettext('Diese Datei ist barrierefrei.')"></studip-icon> </a> <studip-icon v-if="file.restrictedTermsOfUse" @@ -189,7 +196,9 @@ role="info" size="16" :title="$gettext('Das Herunterladen dieser Datei ist nur eingeschränkt möglich.')"></studip-icon> + </td> + <td :data-sort-value="file.size" class="responsive-hidden"> <studip-file-size v-if="file.size !== null" :size="parseInt(file.size, 10)"></studip-file-size> @@ -388,7 +397,7 @@ export default { }, computed: { numberOfColumns () { - return 7 + return 8 + (this.showdownloads ? 1 : 0) + Object.keys(this.topfolder.additionalColumns).length; }, -- GitLab