From 5e4964cef121f35e93e85c1e2101e55b8077935d Mon Sep 17 00:00:00 2001
From: David Siegfried <david.siegfried@uni-vechta.de>
Date: Tue, 5 Nov 2024 09:48:54 +0000
Subject: [PATCH] prevent php-warnings, fixes #4823

Closes #4823

Merge request studip/studip!3608
---
 app/controllers/admin/courseplanning.php              |  2 +-
 app/controllers/admin/courses.php                     |  2 +-
 app/controllers/blubber.php                           |  4 +---
 app/controllers/course/contentmodules.php             |  2 +-
 app/controllers/course/forum/index.php                |  4 ++--
 app/controllers/course/statusgroups.php               |  7 +++++--
 app/controllers/course/study_areas.php                |  2 +-
 app/controllers/course/studygroup.php                 |  3 +++
 app/controllers/settings/privacy.php                  |  6 ++----
 app/controllers/tour.php                              |  2 +-
 app/views/consultation/admin/cancel_slots.php         |  2 +-
 app/views/course/forum/index/index.php                |  4 ++--
 app/views/course/timesrooms/editStack.php             |  2 +-
 app/views/files_dashboard/_search_tr.php              |  2 +-
 app/views/resources/room_request/decline.php          |  2 +-
 lib/classes/coursewizardsteps/BasicDataWizardStep.php |  8 ++++----
 lib/models/BlubberThread.php                          |  6 +++++-
 lib/models/File.php                                   |  4 ++--
 lib/models/OERHostOERSI.php                           |  8 ++++----
 lib/models/SeminarCycleDate.php                       | 11 ++++++-----
 lib/models/resources/ResourceRequest.php              |  8 ++++----
 public/sendfile.php                                   |  2 +-
 templates/courseware/block_types/document.php         |  4 ++--
 templates/dates/seminar_html_roomplanning.php         |  2 +-
 24 files changed, 53 insertions(+), 46 deletions(-)

diff --git a/app/controllers/admin/courseplanning.php b/app/controllers/admin/courseplanning.php
index be411338668..81e90a5687b 100644
--- a/app/controllers/admin/courseplanning.php
+++ b/app/controllers/admin/courseplanning.php
@@ -84,7 +84,7 @@ class Admin_CourseplanningController extends AuthenticatedController
         foreach ($this->events as $event) {
             $start_date_time = explode('T', $event['start']);
             $time_elements = explode(':', $start_date_time[1]);
-            if (!$event['conform'] || $time_elements[0] % 2) {
+            if (empty($event['conform']) || $time_elements[0] % 2) {
                 Sidebar::get()->getWidget('actions')->addLink(
                     _('Veranstaltungen außerhalb des Rasters'),
                     $this->nonconformURL(),
diff --git a/app/controllers/admin/courses.php b/app/controllers/admin/courses.php
index b85f682e7cc..9e9423dcfad 100644
--- a/app/controllers/admin/courses.php
+++ b/app/controllers/admin/courses.php
@@ -1188,7 +1188,7 @@ class Admin_CoursesController extends AuthenticatedController
                     $course = Course::find($course_id);
 
                     if ($course->isOpenEnded() || $course->end_semester->visible) {
-                        $visibility = $visibilites[$course_id] ?: 0;
+                        $visibility = $visibilites[$course_id] ?? 0;
 
                         if ($course->visible == $visibility) {
                             continue;
diff --git a/app/controllers/blubber.php b/app/controllers/blubber.php
index d206a4ad075..8ede39ee478 100644
--- a/app/controllers/blubber.php
+++ b/app/controllers/blubber.php
@@ -270,8 +270,6 @@ class BlubberController extends AuthenticatedController
 
         $output = [];
         foreach ($_FILES as $file) {
-            $file_ref = null; //is also filled below
-
             if ($file['size']) {
                 $document['user_id'] = $GLOBALS['user']->id;
                 $success = false;
@@ -354,7 +352,7 @@ class BlubberController extends AuthenticatedController
                     if ($type) {
                         $output['inserts'][] = "[{$type}]{$url}";
                     } else {
-                        $output['inserts'][] = "[{$file_ref['name']}]{$url}";
+                        $output['inserts'][] = "[{$file['name']}]{$url}";
                     }
                 }
             }
diff --git a/app/controllers/course/contentmodules.php b/app/controllers/course/contentmodules.php
index c3d2269a8b6..7fbb487a5e8 100644
--- a/app/controllers/course/contentmodules.php
+++ b/app/controllers/course/contentmodules.php
@@ -259,7 +259,7 @@ class Course_ContentmodulesController extends AuthenticatedController
         }
         if (isset($this->metadata['screenshots'])) {
             foreach ($this->metadata['screenshots']['pictures'] as $picture) {
-                $title  = $picture['title'];
+                $title  = $picture['title'] ?? '';
                 $source = "{$this->plugin->getPluginURL()}/{$this->metadata['screenshots']['path']}/{$picture['source']}";
                 $this->screenshots[] = compact('title', 'source');
             }
diff --git a/app/controllers/course/forum/index.php b/app/controllers/course/forum/index.php
index d3be08ebe79..01d60c0cd0c 100644
--- a/app/controllers/course/forum/index.php
+++ b/app/controllers/course/forum/index.php
@@ -199,8 +199,8 @@ class Course_Forum_IndexController extends ForumController
         $this->visitdate = ForumVisit::getLastVisit($this->getId());
 
         $list = ForumEntry::getList('newest', $this->topic_id);
-        $this->postings          = $list['list'];
-        $this->number_of_entries = $list['count'];
+        $this->postings          = $list['list'] ?? [];
+        $this->number_of_entries = $list['count'] ?? 0;
         $this->show_full_path    = true;
 
         if (empty($this->postings)) {
diff --git a/app/controllers/course/statusgroups.php b/app/controllers/course/statusgroups.php
index dc282ff4f3f..a274aeaa04d 100644
--- a/app/controllers/course/statusgroups.php
+++ b/app/controllers/course/statusgroups.php
@@ -571,7 +571,10 @@ class Course_StatusgroupsController extends AuthenticatedController
                 $endtime = 0;
             }
         }
-        $position = Statusgruppen::find($group_id)->position;
+        $position = 1;
+        if (Statusgruppen::exists($group_id)) {
+            $position = Statusgruppen::find($group_id)->position;
+        }
         $selfassign = Request::int('selfassign', 0);
         // Exclusive entry makes sense only when selfassign is set in general.
         if ($selfassign !== 0) {
@@ -1443,7 +1446,7 @@ class Course_StatusgroupsController extends AuthenticatedController
                 } catch (Exception $e) {
                     $errors[] = $e->getMessage();
                 }
-            
+
             },
             array_column($members, 'user_id')
         );
diff --git a/app/controllers/course/study_areas.php b/app/controllers/course/study_areas.php
index 8a4df73c19a..df546e72991 100644
--- a/app/controllers/course/study_areas.php
+++ b/app/controllers/course/study_areas.php
@@ -141,7 +141,7 @@ class Course_StudyAreasController extends AuthenticatedController
             }
         }
 
-        if (!$msg) {
+        if (empty($msg)) {
             PageLayout::postSuccess(_('Die Studienbereichszuordnung wurde übernommen.'));
         } else {
             PageLayout::postError($msg);
diff --git a/app/controllers/course/studygroup.php b/app/controllers/course/studygroup.php
index a8d5f49867d..4582225d6ac 100644
--- a/app/controllers/course/studygroup.php
+++ b/app/controllers/course/studygroup.php
@@ -290,6 +290,9 @@ class Course_StudygroupController extends AuthenticatedController
     public function members_action()
     {
         $sem = Context::get();
+        if (!$sem) {
+            throw new CheckObjectException(_('Sie haben kein Objekt gewählt.'));
+        }
         $id = $sem->id;
 
         PageLayout::setTitle(Context::getHeaderLine() . ' - ' . _('Teilnehmende'));
diff --git a/app/controllers/settings/privacy.php b/app/controllers/settings/privacy.php
index 8d63ad84108..d62f3a839e1 100644
--- a/app/controllers/settings/privacy.php
+++ b/app/controllers/settings/privacy.php
@@ -119,10 +119,8 @@ class Settings_PrivacyController extends Settings_SettingsController
                 'name'       => $entry['name'],
                 'visibility' => $new_visibility,
             ];
-            if ($entry['extern']) {
-                $new_data[$key]['extern'] = true;
-            }
-            $new_data[$key]['category'] = $entry['category'];
+            $new_data[$key]['extern'] = !empty($entry['extern']);
+            $new_data[$key]['category'] = $entry['category'] ?? '';
 
             $db_result[$key] = $new_visibility;
         }
diff --git a/app/controllers/tour.php b/app/controllers/tour.php
index 46052b5ad8b..e507c4bddca 100644
--- a/app/controllers/tour.php
+++ b/app/controllers/tour.php
@@ -64,7 +64,7 @@ class TourController extends AuthenticatedController
         }
 
         $this->user_visit = new HelpTourUser([$tour_id, $GLOBALS['user']->user_id]);
-        if ($this->user_visit->step_nr > 1 && !$_SESSION['active_tour']['step_nr'] && $this->tour->type === 'tour') {
+        if ($this->user_visit->step_nr > 1 && empty($_SESSION['active_tour']['step_nr']) && $this->tour->type === 'tour') {
             $data['last_run']      = sprintf(_('Wollen Sie die Tour "%s" an der letzten Position fortsetzen?'), $this->tour->name);
             $data['last_run_step'] = $this->user_visit->step_nr;
             $data['last_run_href'] = URLHelper::getURL($this->tour->steps[$this->user_visit->step_nr - 1]->route, null, true);
diff --git a/app/views/consultation/admin/cancel_slots.php b/app/views/consultation/admin/cancel_slots.php
index f1263a8b8d4..0e7067a5fd1 100644
--- a/app/views/consultation/admin/cancel_slots.php
+++ b/app/views/consultation/admin/cancel_slots.php
@@ -52,7 +52,7 @@
     <? endif; ?>
         <?= Studip\LinkButton::createCancel(
             _('Abbrechen'),
-            $controller->indexURL($page ?? null, "#block-{$block->id}")
+            $controller->indexURL($page ?? null, isset($block) ?"#block-{$block->id}" : '')
         ) ?>
     </footer>
 </form>
diff --git a/app/views/course/forum/index/index.php b/app/views/course/forum/index/index.php
index d14c840635e..183978319ee 100644
--- a/app/views/course/forum/index/index.php
+++ b/app/views/course/forum/index/index.php
@@ -130,7 +130,7 @@ $pagechooser = null;
 <?= $this->render_partial('course/forum/index/_breadcrumb') ?>
 
 <!-- Seitenwähler (bei Bedarf) am oberen Rand anzeigen -->
-<? if ($number_of_entries > ForumEntry::POSTINGS_PER_PAGE) : ?>
+<? if (!empty($number_of_entries) && $number_of_entries > ForumEntry::POSTINGS_PER_PAGE) : ?>
 <div data-type="page_chooser" id="page-chooser">
     <? if (!isset($constraint) || $constraint['depth'] > 0) : ?>
     <?= $pagechooser = $GLOBALS['template_factory']->render('shared/pagechooser', [
@@ -150,7 +150,7 @@ $pagechooser = null;
     <?= $this->render_partial('course/forum/messages') ?>
 </div>
 
-<? if ($no_entries) : ?>
+<? if (!empty($no_entries)) : ?>
     <?= MessageBox::info(_('In dieser Ansicht befinden sich zur Zeit keine Beiträge.')) ?>
 <? endif ?>
 
diff --git a/app/views/course/timesrooms/editStack.php b/app/views/course/timesrooms/editStack.php
index cd4df4013f4..11695fcf2ab 100644
--- a/app/views/course/timesrooms/editStack.php
+++ b/app/views/course/timesrooms/editStack.php
@@ -14,7 +14,7 @@
  * @var string[] $selected_lecturer_ids
  */
 ?>
-<form method="post" action="<?= $controller->url_for('course/timesrooms/saveStack/' . $cycle_id, $linkAttributes) ?>"
+<form method="post" action="<?= $controller->link_for('course/timesrooms/saveStack/' . $cycle_id, $linkAttributes ?? []) ?>"
       class="default collapsable" data-dialog="size=big">
     <?= CSRFProtection::tokenTag()?>
     <input type="hidden" name="method" value="edit">
diff --git a/app/views/files_dashboard/_search_tr.php b/app/views/files_dashboard/_search_tr.php
index 60c56711c2f..62546da0d83 100644
--- a/app/views/files_dashboard/_search_tr.php
+++ b/app/views/files_dashboard/_search_tr.php
@@ -65,7 +65,7 @@
             <? elseif ($searchResult['folder']->range_type === 'message') : ?>
                 <?= _('Nachrichtenanhang') ?>:
                 <?= $controller->markPhrase($searchResult['folder']->message->subject, $query->getQuery()) ?>
-            <? elseif ($searchResult['folder']->range_type === 'user') : ?>
+            <? elseif ($searchResult['folder']->user && $searchResult['folder']->range_type === 'user') : ?>
                 <?= _('Öffentlicher Dateibereich') ?>:
                 <?= $controller->markPhrase($searchResult['folder']->user->getFullName('full_rev_username'), $query->getQuery()) ?>
             <? endif ?>
diff --git a/app/views/resources/room_request/decline.php b/app/views/resources/room_request/decline.php
index 2c02126bc83..d49a206c3e1 100644
--- a/app/views/resources/room_request/decline.php
+++ b/app/views/resources/room_request/decline.php
@@ -25,7 +25,7 @@
         <? if (!$delete_mode): ?>
             <fieldset>
                 <legend><?= _('Kommentar zur Ablehnung der Anfrage') ?></legend>
-                <textarea name="reply_comment"><?= $reply_comment ?></textarea>
+                <textarea name="reply_comment"><?= htmlReady($reply_comment ?? '') ?></textarea>
             </fieldset>
         <? endif ?>
     <? endif ?>
diff --git a/lib/classes/coursewizardsteps/BasicDataWizardStep.php b/lib/classes/coursewizardsteps/BasicDataWizardStep.php
index 49446114ac0..8f7a96c0be2 100644
--- a/lib/classes/coursewizardsteps/BasicDataWizardStep.php
+++ b/lib/classes/coursewizardsteps/BasicDataWizardStep.php
@@ -350,7 +350,7 @@ class BasicDataWizardStep implements CourseWizardStep
         $values = $values[__CLASS__];
         $ok = true;
         $errors = [];
-        if (!trim($values['name'])) {
+        if (empty($values['name'])) {
             $errors[] = _('Bitte geben Sie den Namen der Veranstaltung an.');
         }
         if (isset($values['number']) && $values['number'] != '') {
@@ -362,7 +362,7 @@ class BasicDataWizardStep implements CourseWizardStep
         if (empty($values['lecturers'])) {
             $errors[] = sprintf(
                 _('Bitte tragen Sie mindestens eine Person als %s ein.'),
-                htmlReady(get_title_for_status('dozent', 1, $values['coursetype']))
+                htmlReady(get_title_for_status('dozent', 1, $values['coursetype'] ?? null))
             );
         }
         if (empty($values['lecturers'][$GLOBALS['user']->id]) && !$GLOBALS['perm']->have_perm('admin')) {
@@ -370,13 +370,13 @@ class BasicDataWizardStep implements CourseWizardStep
                 if (empty($values['deputies'][$GLOBALS['user']->id])) {
                     $errors[] = sprintf(
                         _('Sie selbst müssen entweder als %s oder als Vertretung eingetragen sein.'),
-                        htmlReady(get_title_for_status('dozent', 1, $values['coursetype']))
+                        htmlReady(get_title_for_status('dozent', 1, $values['coursetype'] ?? null))
                     );
                 }
             } else {
                 $errors[] = sprintf(
                     _('Sie müssen selbst als %s eingetragen sein.'),
-                    htmlReady(get_title_for_status('dozent', 1, $values['coursetype']))
+                    htmlReady(get_title_for_status('dozent', 1, $values['coursetype'] ?? null))
                 );
             }
         }
diff --git a/lib/models/BlubberThread.php b/lib/models/BlubberThread.php
index 6753cfb8bed..4c3b5851dc4 100644
--- a/lib/models/BlubberThread.php
+++ b/lib/models/BlubberThread.php
@@ -432,7 +432,11 @@ class BlubberThread extends SimpleORMap implements PrivacyObject
             if ($this['content']) {
                 return mb_substr((string) Course::find($this['context_id'])->name . ': ' . $this['content'], 0, 50) . ' ...';
             } else {
-                return (string) (Course::find($this['context_id'])->name ?? _('unbekannt'));
+                if ($course = Course::find($this['context_id'])) {
+                    return (string) $course->name;
+                } else {
+                    return _('unbekannt');
+                }
             }
         }
 
diff --git a/lib/models/File.php b/lib/models/File.php
index 6cd0151e0a6..603a2282557 100644
--- a/lib/models/File.php
+++ b/lib/models/File.php
@@ -87,7 +87,7 @@ class File extends SimpleORMap
      */
     public function deleteDataFile()
     {
-        return @unlink($this->getPath());
+        return file_exists($this->getPath()) && unlink($this->getPath());
     }
 
     /**
@@ -107,7 +107,7 @@ class File extends SimpleORMap
             if (!@move_uploaded_file($path_to_file, $newpath)) {
                 return false;
             }
-        } else if (!@copy($path_to_file, $newpath)) {
+        } else if (!file_exists($path_to_file) || !@copy($path_to_file, $newpath)) {
             return false;
         }
         $this->size = filesize($newpath);
diff --git a/lib/models/OERHostOERSI.php b/lib/models/OERHostOERSI.php
index f2b07b8ae2e..92a3a838626 100644
--- a/lib/models/OERHostOERSI.php
+++ b/lib/models/OERHostOERSI.php
@@ -77,7 +77,7 @@ class OERHostOERSI extends OERHost
                     $material['uri'] = $material_data['_source']['id'];
                     $material['source_url'] = $material_data['_source']['id'];
                     $material['content_type'] = $material_data['_source']['encoding'][0]['encodingFormat'] ?? '';
-                    $material['license_identifier'] = $this->getLicenseID($material_data['_source']['license']['id']) ?: '';
+                    $material['license_identifier'] = !empty($material_data['_source']['license']['id']) ? $this->getLicenseID($material_data['_source']['license']['id']): '';
                     if (!$material['category']) {
                         $material['category'] = $material->autoDetectCategory();
                     }
@@ -151,7 +151,7 @@ class OERHostOERSI extends OERHost
                 $data['uri'] = $output['encoding'][0]['contentUrl'] ?? '';
                 $data['source_url'] = $output['id'];
                 $data['content_type'] = $output['encoding'][0]['encodingFormat'] ?? '';
-                $data['license_identifier'] = $this->getLicenseID($output['license']['id']) ?: '';
+                $data['license_identifier'] = !empty($output['license']['id']) ? $this->getLicenseID($output['license']['id']) : '';
                 if (empty($data['category'])) {
                     $data['category'] = $material->autoDetectCategory();
                 }
@@ -178,7 +178,7 @@ class OERHostOERSI extends OERHost
     /**
      * Tries to match the CC-license URL from OERSI to an spdx-identifier, which is used in Stud.IP
      * @param $license : an URL
-     * @return string|null
+     * @return string
      */
     protected function getLicenseID($license)
     {
@@ -189,7 +189,7 @@ class OERHostOERSI extends OERHost
                 return $spdx_id;
             }
         }
-        return null;
+        return '';
     }
 
     public function isReviewable()
diff --git a/lib/models/SeminarCycleDate.php b/lib/models/SeminarCycleDate.php
index 69396324657..9a922e99360 100644
--- a/lib/models/SeminarCycleDate.php
+++ b/lib/models/SeminarCycleDate.php
@@ -507,11 +507,12 @@ class SeminarCycleDate extends SimpleORMap
         if (!parent::store()) {
             return false;
         }
-
-        if ($this->start_time != $old_cycle->start_time
-                || $this->end_time != $old_cycle->end_time
-                || $old_cycle->weekday != $this->weekday )
-        {
+        $update_count = 0;
+        if (
+            $this->start_time != $old_cycle->start_time
+            || $this->end_time != $old_cycle->end_time
+            || $old_cycle->weekday != $this->weekday
+        ) {
             $update_count = $this->updateExistingDates($old_cycle);
         }
 
diff --git a/lib/models/resources/ResourceRequest.php b/lib/models/resources/ResourceRequest.php
index 8d3bcbaaf0e..88bf1197edc 100644
--- a/lib/models/resources/ResourceRequest.php
+++ b/lib/models/resources/ResourceRequest.php
@@ -1030,8 +1030,8 @@ class ResourceRequest extends SimpleORMap implements PrivacyObject, Studip\Calen
                 }
                 $interval['range']                                 = 'CourseDate';
                 $interval['range_id']                              = $date->id;
-                $interval['booked_room']                           = $date->room_booking->resource_id;
-                $interval['booking_id']                            = $date->room_booking->id;
+                $interval['booked_room']                           = $date->room_booking->resource_id ?? null;
+                $interval['booking_id']                            = $date->room_booking->id ?? null;
                 $time_intervals[$this->metadate_id]['intervals'][] = $interval;
             }
             return $time_intervals;
@@ -1094,8 +1094,8 @@ class ResourceRequest extends SimpleORMap implements PrivacyObject, Studip\Calen
                     }
                     $interval['range']                 = 'CourseDate';
                     $interval['range_id']              = $date->id;
-                    $interval['booked_room']           = $date->room_booking->resource_id;
-                    $interval['booking_id']            = $date->room_booking->id;
+                    $interval['booked_room']           = $date->room_booking->resource_id ?? null;
+                    $interval['booking_id']            = $date->room_booking->id ?? null;
                     $time_intervals['']['intervals'][] = $interval;
                 }
 
diff --git a/public/sendfile.php b/public/sendfile.php
index 03157b8ada1..571713ef08b 100644
--- a/public/sendfile.php
+++ b/public/sendfile.php
@@ -135,7 +135,7 @@ switch ($type) {
             //Get the file type:
             if ($file->hasFileAttached()) {
                 $path_file = $file->getPath();
-            } elseif ($file->hasURL()) {
+            } elseif ($file->hasURL() && !empty($file->metadata['url'])) {
                 $path_file = $file->metadata['url'];
             }
         } else {
diff --git a/templates/courseware/block_types/document.php b/templates/courseware/block_types/document.php
index d4391701e9c..76ef7686b3b 100644
--- a/templates/courseware/block_types/document.php
+++ b/templates/courseware/block_types/document.php
@@ -2,8 +2,8 @@
     <p style="font-weight: bold;"><?= _('Dokument') . ': ' ?></p>
     <p>
         <?= _('Titel') . ' => ' . htmlReady($payload['title']) ?>,
-        <? if ($files[0]): ?>
+        <? if (!empty($files[0])): ?>
             <?= _('Datei') . '=>' ?> <a href="<?= htmlReady($files[0]->getDownloadURL()) ?>"><?= htmlReady($files[0]->name) ?></a>
         <? endif; ?>
     </p>
-</div>
\ No newline at end of file
+</div>
diff --git a/templates/dates/seminar_html_roomplanning.php b/templates/dates/seminar_html_roomplanning.php
index b758f403a13..decc8c025d5 100644
--- a/templates/dates/seminar_html_roomplanning.php
+++ b/templates/dates/seminar_html_roomplanning.php
@@ -49,7 +49,7 @@ if (!empty($dates['regular']['turnus_data']) || !empty($dates['irregular'])) :
 
   if (isset($dates['irregular']) && is_array($dates['irregular'])):
     foreach ($dates['irregular'] as $date) :
-        if (empty($with_past_intervals) && $date->end_time < $now) {
+        if (empty($with_past_intervals) && $date['end_time'] < $now) {
             continue;
         }
         $irregular[] = $date;
-- 
GitLab