Compare commits

..

442 Commits

Author SHA1 Message Date
Paolo 9d6bcc7779 Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2026-04-27 13:23:19 +02:00
Paolo 64f23ea7eb Fixed application/phrases/dashboard.php 2026-04-27 13:22:49 +02:00
Paolo 86401dae8b Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2026-04-27 13:20:18 +02:00
Paolo 02a8797d4b Merge branch 'feature-13011/installation_on_multiple_servers' into merge-6237-13011 2026-04-27 13:19:42 +02:00
Paolo 2655cc0e34 Merge branch 'master' into feature-6237/Phrases_system_MkIII 2026-04-27 13:18:56 +02:00
Paolo 9b60f57d7a Merge branch 'master' into feature-13011/installation_on_multiple_servers 2026-04-27 13:14:15 +02:00
Andreas Österreicher 552faefa51 Merge branch 'feature-76108/microdegree_abschlussurkunde' 2026-04-27 08:55:08 +02:00
Harald Bamberger 954397f028 Merge branch 'feature-70376/Lohnguide' 2026-04-22 18:52:51 +02:00
Harald Bamberger 80faa61c91 Merge branch 'master' into feature-70376/Lohnguide 2026-04-22 18:46:57 +02:00
Werner Masik 961ede66a9 lohnguide db update changed 2026-04-22 18:40:22 +02:00
Andreas Österreicher 6fec8382b5 Merge branch 'feature-76554/Personalmeldung_alt_bei_Lehre_nicht_melderelevant_rausfiltern' 2026-04-22 09:15:23 +02:00
Andreas Österreicher 4eb076d115 Fixed Saving of Entwicklungsteam 2026-04-21 17:34:36 +02:00
Harald Bamberger 7427aa87ea Merge branch 'feature-76545/findAbgabenNewOrUpdatedSinceByAbgabedatumFixTimestampDateComparison' 2026-04-21 17:01:04 +02:00
Johann Hoffmann 85043e57db added missing parenthesis 2026-04-21 17:00:07 +02:00
Johann Hoffmann 5beddbccb4 changed the where clause to a simpler = CURRENT_DATE comparison -> works the same if the job runs daily and fetches updates of one day/date; has to be changed back in case we want to find updates in a range larger than 1 day in an interval larger than 1 day; 2026-04-21 14:18:45 +02:00
kindlm e2ae9b88c8 Merge remote-tracking branch 'origin/master' 2026-04-21 12:56:30 +02:00
kindlm ca3abf9154 Small Style-Fix in Testtool
To make headings stand out more clearly from the buttons
2026-04-21 12:56:02 +02:00
Alexei Karpenko f863c6d728 personalmeldung legacy system: melderelevant is checked for lehre, bugfix: lehre is correctly added if studiengang already has sws 2026-04-20 18:24:30 +02:00
Harald Bamberger 92a2053b42 Merge branch 'feature-40870/BUG_Studstatus_unpause_order_should_be_DESC' 2026-04-20 17:30:14 +02:00
kindlm 70602be54e SaveSort und Filter-Reset in RaumÜbersicht 2026-04-20 11:30:17 +02:00
kindlm dac71f597a Spalte Anmeldedatum in RT-Übersicht
Spalte Frage_ID in RT-Administration
JQuery und Tabelsorter aus Include in Service_Uebersicht
2026-04-20 11:24:59 +02:00
Johann Hoffmann 3a646ffe77 adapt AbgabeJob relevant queries so they compare with the pgsql date function CURRENT_DATE instead of NOW() to avoid the cutoff from uploads the happened "yesterday but more than 24 hours ago"; also added another "abgabedatum < CURRENT_DATE" condition, to avoid sending this exact case as updates 2 days in a row; 2026-04-20 11:06:06 +02:00
Harald Bamberger 98a10a2f55 Merge branch 'feature-69389/AbmeldungSTGL_Anzeige_mit_Studiengangskuerzel' 2026-04-17 12:37:49 +02:00
Harald Bamberger e48b94b858 studiengangskuerzel statt kurzbzlang 2026-04-17 12:35:55 +02:00
Andreas Österreicher 0ff29ba6af Merge branch 'epic-56039/LV-Evaluierung' 2026-04-16 13:22:40 +02:00
Harald Bamberger ba543448ae Merge branch 'bug-76260/StudVW_Messages_TinyMCE_Cursor_Jumping_TextInput' 2026-04-16 11:26:32 +02:00
Harald Bamberger f121f9b5a2 deactivate pagination - since potentially msg threads are not shown completely 2026-04-16 11:23:57 +02:00
Harald Bamberger 88b22f5490 revert to v-if to not render element when not necessary and use Vue.nextTick for dependent code 2026-04-15 17:02:58 +02:00
Harald Bamberger 4b7ee9abe1 Merge branch 'feature-70376/Lohnguide' 2026-04-15 15:52:12 +02:00
Cristina d499619cf3 Added phrase endedatumMussInZukunftLiegen 2026-04-15 13:39:06 +02:00
Cristina f489153ff3 Merge branch 'master' into epic-56039/LV-Evaluierung 2026-04-15 12:25:05 +02:00
Cristina 9b79a07fa2 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-04-15 12:24:44 +02:00
Harald Bamberger 6ce14a25d7 Merge branch 'master' into feature-70376/Lohnguide 2026-04-15 11:49:26 +02:00
Werner Masik c701d92779 fix db_update 2026-04-15 11:15:10 +02:00
Werner Masik 73e03ba901 Gehaltstyp Überstundenpauschale und Sachbezug PKW 2026-04-15 10:44:03 +02:00
ma0068 95a7797ae9 delete unused apicall for mode modal
add editor.setContent to function getReplyData
readd loadReplyData and use v-show for visibleDiv for mode inSamePage
2026-04-14 15:46:34 +02:00
ma0048 3ce3eff022 fehlendes mapping hinzugefuegt 2026-04-14 09:30:45 +02:00
Andreas Österreicher 3a91b12f31 Merge branch 'epic-56039/LV-Evaluierung' 2026-04-13 10:39:00 +02:00
ma0048 ea0a249612 micro degree abschlussdokumente hinzugefuegt 2026-04-13 09:14:27 +02:00
ma0068 843894405e changes for NewDiv
remove Watcher for formData Fields
add predefault settings for tabulator fields
add setContent for Editor
change text for closing window/tab
show alertSuccess for sending Message just in case of inSamePage
2026-04-10 13:03:24 +02:00
ma0068 8fddbc3a32 delete watcher for formData fields, add setContent for loading Vorlage 2026-04-10 09:15:34 +02:00
Harald Bamberger b2538075ee use STV_TAGS_ENABLED config when preparing sql statement for students list to query tags only if enabled 2026-04-07 10:35:06 +02:00
Werner Masik 5c463c0866 add vordienstzeit to lohnguide 2026-04-06 22:25:13 +02:00
Werner Masik 423bbd95a6 add vordienstzeit to lohnguide 2026-04-06 22:25:12 +02:00
Cristina 386cc779bf Merge branch 'master' into epic-56039/LV-Evaluierung 2026-04-02 15:49:20 +02:00
Cristina 08c6d58a50 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-04-02 14:24:39 +02:00
Cristina 3f53c5feba Added: method getKFLByUID to get Kompetenzfeldleitung by UID 2026-04-02 14:23:59 +02:00
Andreas Österreicher 2c057aad58 Updated Startup Dump to Final 3.3 Version 2026-04-01 13:00:50 +02:00
kindlm c2ce831bca Merge remote-tracking branch 'origin/master' 2026-03-26 11:43:59 +01:00
kindlm 21c1f13b28 Spalte "faktiv" (Foebis-Aktiv) im FAS 2026-03-26 11:43:20 +01:00
Andreas Österreicher e0079bb812 Merge branch 'feature-71665/mc4_vorlage' 2026-03-26 09:27:00 +01:00
Andreas Österreicher 966d1d10f6 Merge branch 'feature-71566/Studienordnung_Anpassungen_fuer_Programme_und_Lehrgaenge' 2026-03-26 09:05:31 +01:00
Andreas Österreicher 76936ad74f Merge branch 'feature-75703/BIS_Personalmeldung_Lehrgaenge' 2026-03-26 08:31:13 +01:00
Harald Bamberger 6fbb09eb6e group or clause 2026-03-25 16:32:43 +01:00
Harald Bamberger cfe1307018 Merge branch 'feature-68530/Dashboard_Cleanup_Admin' 2026-03-25 15:37:34 +01:00
Harald Bamberger 5139c3e44e use array_replace_recursive instead of array_merge_recursive to prevent two scalar values being merged to an array 2026-03-25 15:15:05 +01:00
Harald Bamberger 627a52e3d1 Merge branch 'master' into feature-70376/Lohnguide 2026-03-25 09:36:27 +01:00
chfhtw 1951cd6fa8 split/rename dashboard api factories 2026-03-24 16:08:02 +01:00
chfhtw e3093bdf3f get magic funktionen (Mitarbeiter, Student) as dashboard presets 2026-03-24 15:15:36 +01:00
chfhtw b11d8d056a get access rights from permissionlib 2026-03-24 15:15:12 +01:00
chfhtw 3a4015eced dashboard useroverwrite: remove doubles in other funktionen 2026-03-24 15:15:04 +01:00
chfhtw aeb5d40840 rename api endpoints 2026-03-24 15:14:39 +01:00
Alexei Karpenko 49c712a5b6 Personalmeldung sws: rounding to 2 decimals 2026-03-24 13:57:23 +01:00
Harald Bamberger 46817b846a fix e.g. long lines of underscores in cms content 2026-03-24 13:29:20 +01:00
Harald Bamberger 8c75608eaf add menu entry for Dashboard Admin 2026-03-24 13:21:50 +01:00
chfhtw 2720ed9ffb timezone from global object 2026-03-24 11:00:09 +01:00
Paolo d0513571f9 Merge branch 'feature-13011/installation_on_multiple_servers' into merge-6237-13011 2026-03-24 09:58:02 +01:00
Paolo 458dc1aaec Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2026-03-24 09:57:54 +01:00
Paolo 1f1d0a94e6 Merge branch 'master' into feature-6237/Phrases_system_MkIII 2026-03-24 09:57:37 +01:00
Paolo 944bc44a0e Merge branch 'master' into feature-13011/installation_on_multiple_servers 2026-03-24 09:50:48 +01:00
chfhtw 2fc392c084 refactor dashboards Preset->addWidgets to (single) Preset->addWidget 2026-03-23 16:05:22 +01:00
chfhtw ca630e94ae remove debug line 2026-03-23 15:46:13 +01:00
chfhtw 9cff50fa3b extract preset logic from dashboard admin api 2026-03-23 15:44:42 +01:00
chfhtw 3d7a6b1ad3 dashboard user api: empty -> check for false/null 2026-03-23 15:42:28 +01:00
chfhtw f15fd40636 dashboardlib bug: array <=> stdclass 2026-03-23 15:41:32 +01:00
chfhtw 054cf2f258 correct form validation & typo in api dashboard widget 2026-03-23 15:06:25 +01:00
chfhtw dc067a619b make widgets resizeable in dashboard admin 2026-03-23 14:07:31 +01:00
chfhtw 2a762fa4ab add renderers & timezone to dashboard admin for calendar widget 2026-03-23 13:22:30 +01:00
chfhtw ccade6ae0e rename dashboard admin controller and views 2026-03-23 11:47:28 +01:00
chfhtw 6971aed030 parsing happens in backend not frontend 2026-03-23 11:46:45 +01:00
chfhtw 60e556b2a8 wrong case 2026-03-23 11:33:45 +01:00
chfhtw 42fbbc5257 remove unused file 2026-03-23 11:28:31 +01:00
chfhtw d01dedb79c remove unused file 2026-03-23 11:23:01 +01:00
chfhtw 1972b461e7 replace controllers/dashboard/Config.php with controllers/api/frontend/v1/dashboard/User.php & controllers/api/frontend/v1/dashboard/DashboardAdmin.php 2026-03-23 11:21:15 +01:00
chfhtw e957926a4d replace controllers/dashboard/Widget.php with controllers/api/frontend/v1/dashboard/Widget.php 2026-03-23 10:57:43 +01:00
chfhtw bac2c13da3 viewData is mandatory so we dont need to load it if its not set 2026-03-23 10:44:39 +01:00
ma0068 b90c26412a DB update: new Organisationseinheittyp Programm 2026-03-20 13:06:16 +01:00
chfhtw 65c7ad2aac use correct error handling in FhcApi in case of success 2026-03-20 12:29:01 +01:00
chfhtw 126a2d3b7b add deepToRaw function to helpers/ObjectUtils 2026-03-20 11:23:35 +01:00
Harald Bamberger 60734f708e Merge branch 'master' into feature-68530/Dashboard_Cleanup_Admin 2026-03-19 16:20:06 +01:00
Harald Bamberger 9e6c15a10d Merge branch 'bug-76010/StudVW_Archivieren_Ausbildungsvertrag_Aufgenommene' 2026-03-19 15:41:44 +01:00
Harald Bamberger 14a8e2f001 Funktionen fett schreiben, die schon presets hinterlegt haben, demo aus views und Controller namen entfernen, preview hinzufuegen 2026-03-18 15:48:57 +01:00
ma0068 7603f8f12b Bugfix: use null instead of empty string, provide kuerzel 2026-03-18 14:32:09 +01:00
Harald Bamberger 059b13938e Merge branch 'master' into feature-70376/Lohnguide 2026-03-18 11:46:27 +01:00
Harald Bamberger a4f2502fe6 dashboard admin: funktionen sortieren, allgemein/general wieder hinzufuegen 2026-03-18 10:58:05 +01:00
Harald Bamberger 7c1762d467 Merge branch 'master' into feature-68530/Dashboard_Cleanup_Admin 2026-03-18 09:20:53 +01:00
Andreas Österreicher 96745525f1 Merge branch 'feature-71530/Error_beim_Archivieren_von_Diplomasupplement_STUDVW_Neu' 2026-03-16 11:28:56 +01:00
Andreas Österreicher 8d6e04ea77 Merge branch 'feature-61164/AbgabetoolQualityGates' 2026-03-16 11:09:52 +01:00
Andreas Österreicher d9e5acb52c Merge branch 'master' into feature-61164/AbgabetoolQualityGates 2026-03-16 11:08:44 +01:00
Johann Hoffmann 6ec32b0ca3 update tabulator persistence id 2026-03-16 11:05:48 +01:00
Johann Hoffmann 4778bb82c3 assistenz action buttons lefthand alignment & lower minwidth 2026-03-16 10:56:51 +01:00
Andreas Österreicher e20ff52f5b Merge branch 'feature-75417/pep_finetuning' 2026-03-16 09:08:10 +01:00
Andreas Österreicher df05af98d2 FHB - Markierung von Outgoing ohne Endedatum 2026-03-16 09:01:33 +01:00
Harald Bamberger 0764a597af do not allow foto editing in contract management 2026-03-12 15:18:26 +01:00
Harald Bamberger 8c36fe585a filter component add missing this 2026-03-12 15:09:46 +01:00
Johann Hoffmann 5ef1dccfc9 added missing phrase c4noZuordnungBetreuerStudent 2026-03-12 14:58:35 +01:00
Harald Bamberger d4b81da437 fix filter component also consider tabulator 6 selectableRows option to determine if tabulator has selector 2026-03-12 14:34:42 +01:00
Harald Bamberger b91efb6189 stv notizperson fix permission check to be able to add notes to prestudents that do not have an uid 2026-03-12 13:56:03 +01:00
Johann Hoffmann 6d28b8986d Merge remote-tracking branch 'origin/master' into feature-61164/AbgabetoolQualityGates
# Conflicts:
#	public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js
2026-03-12 09:47:54 +01:00
kindlm 40757322e7 Spalte "FGM" (Förder-Guthaben-Monate) bei Prestudentstatus einblendbar 2026-03-11 17:52:31 +01:00
Johann Hoffmann b43f1ec920 AbgabetoolAssistenz download latest uploaded file action button; UX changes Projektarbeit Tab Stv; fix stv form input bug after invalidation for selects; 2026-03-11 17:00:56 +01:00
Harald Bamberger 6cd4aebe8d stv projektarbeit projektbetreuer use correct ref 2026-03-11 14:54:06 +01:00
Andreas Österreicher 2b527bccd2 Merge branch 'feature-75873/Noteneingabe-Punkte' 2026-03-11 13:42:17 +01:00
Andreas Österreicher 41271711ec Merge branch 'bugfix-55630/Falsche-Nachpruefungsdaten-auf-Notenliste-bei-Wiederholern' into feature-75873/Noteneingabe-Punkte 2026-03-11 13:26:46 +01:00
Harald Bamberger 6287b6aef8 Merge branch 'feature-68296/Vue_Router_via_Extensions_erweitern_ma0080' 2026-03-11 13:19:02 +01:00
Harald Bamberger 3e9d960781 Merge branch 'master' into feature-68296/Vue_Router_via_Extensions_erweitern_ma0080 2026-03-11 12:52:18 +01:00
Alexei Karpenko c3d20bb181 Personalmeldung Lehrgaenge: distributed sws among Lehrgang types (Zertifikat, Master etc...) 2026-03-11 12:37:28 +01:00
Harald Bamberger 5ce0232890 fix bug in archiv tab 2026-03-11 11:50:09 +01:00
Harald Bamberger cf4ec12c00 Merge branch 'master' into feature-68296/Vue_Router_via_Extensions_erweitern_ma0080 2026-03-10 17:08:03 +01:00
Andreas Österreicher d35eca919f Merge branch 'hotfix-69228/DOCSBOX' 2026-03-10 13:53:58 +01:00
Harald Bamberger 61d133b2fd Merge branch 'master' into feature-68296/Vue_Router_via_Extensions_erweitern_ma0080 2026-03-10 12:14:35 +01:00
Andreas Österreicher 7cd438d188 Wenn Punkteeingabe aktiviert ist werden auch Punkte in der Excel Notenliste exportiert damit es beim Import von Spezialnoten (zb 18) nicht zu Problemen kommt 2026-03-10 11:47:24 +01:00
Harald Bamberger a733d9a861 Merge branch 'vv_und_studvw_2026_02_rc4_ma0080' 2026-03-10 11:37:34 +01:00
Harald Bamberger 33252de895 use ma0646 tabulator scroll fix on students/prestudents list 2026-03-10 11:11:40 +01:00
Harald Bamberger fb388346bf Merge branch 'master' into vv_und_studvw_2026_02_rc4_ma0080 2026-03-10 08:41:56 +01:00
Harald Bamberger 32a2e7708f remove bg color in stv and lvvw Tabs, detailsheader ajust foto buttons 2026-03-09 12:10:22 +01:00
Werner Masik 6b816def31 add lohnguide to vertragsbestandteil SQL 2026-03-05 15:34:51 +01:00
Werner Masik 5fbcf588ed fix vertragsbestandteil lohnguide 2026-03-05 14:29:56 +01:00
Harald Bamberger c40fdb2c4f getMessagesForTable laststatus only for filteredmessages 2026-03-05 11:35:57 +01:00
Harald Bamberger 47b5eecb9b Merge branch 'master' into vv_und_studvw_2026_02_rc4_ma0080 2026-03-04 18:57:13 +01:00
Harald Bamberger b7fd7e4298 Merge branch 'vv_und_studvw_2026_02_rc4' into vv_und_studvw_2026_02_rc4_ma0080 2026-03-04 17:53:53 +01:00
Harald Bamberger 1af334989e Merge branch 'feature-71601/drag_drop_aus_tabulator_heraus_ohne_vorheriges_selektieren' into vv_und_studvw_2026_02_rc4 2026-03-04 17:53:19 +01:00
Harald Bamberger 4f541495ad Merge branch 'feature-71610/verbandsbaum_togglen_ohne_select' into vv_und_studvw_2026_02_rc4 2026-03-04 17:25:32 +01:00
Harald Bamberger 35d83942c0 use primevue tabs in LVVerwaltung 2026-03-04 16:03:51 +01:00
Alexei Karpenko fc4e79c1f5 Personalmeldung: include Lehrgaenge in Lehre in legacy script 2026-03-04 11:12:58 +01:00
Werner Masik 41b2a6d1d4 added db migration for lohnguide 2026-03-04 10:53:30 +01:00
Harald Bamberger 1810bd40bd fix bug introduced in commit 043b1bcf11 send intern also using private email addresses 2026-03-04 09:39:58 +01:00
Harald Bamberger 5347cb1d63 add config STV_TAGS_ENABLED and use it to enable or disable tags in StudVw 2026-03-03 17:15:23 +01:00
Harald Bamberger 77731ed559 Merge branch 'feature-68767/FHC4_Studierendenverwaltung_Details_4spaltig_ma0080' into vv_und_studvw_2026_02_rc4_ma0080 2026-03-03 13:46:29 +01:00
Harald Bamberger 0283c6ca43 bg-color in details, padding-y tabs, messages align table and preview area 2026-03-03 12:24:34 +01:00
Werner Masik e054f1222b basic model and factory for lohnguide 2026-03-03 11:50:45 +01:00
Andreas Österreicher 8abb38123a Merge branch 'feature-70440/Change_var_dump_to_error_log_to_show_the_referring_script' 2026-03-03 11:41:16 +01:00
Andreas Österreicher d1928d4151 Merge branch 'bug-56209/is_valid_date_vs_isValidDate' 2026-03-03 11:29:29 +01:00
Andreas Österreicher bcd8f11f35 Fixed Merge Problem 2026-03-03 11:26:18 +01:00
Andreas Österreicher 5949527ee2 Merge branch 'master' into bug-56209/is_valid_date_vs_isValidDate 2026-03-03 11:07:18 +01:00
Johann Hoffmann 56a6aa993e getMitarbeiterProjektarbeiten safeguard in case a person without any assigned betreuungen opens the page for some reason to avoid nasty confusing sql error messages from querying with empty parameters 2026-03-03 10:52:12 +01:00
Andreas Österreicher ea19ba099e Merge branch 'bug-70950/Coodle_ICS_Organizer_falsch' 2026-03-03 10:44:55 +01:00
Johann Hoffmann db75cd2f62 also skip email loop/relevant abgaben loop when every occurance is filtered out to avoid empty notification emails; 2026-03-03 10:42:47 +01:00
Cristina c57eb1b8de Adapted method getLvLeitung: filter Dummy and allow only active Benutzer/Person 2026-03-02 11:00:05 +01:00
Harald Bamberger 28f4a38752 refactor helper function extendableApps to singleton helper class ExtendableAppsHelper and use it in FHC-Header and FHC-Footer, revert previous changes to other CI views 2026-02-27 16:50:50 +01:00
Andreas Österreicher 8495c74a7d Merge branch 'feature-61164/AbgabetoolQualityGates' 2026-02-27 10:48:35 +01:00
Harald Bamberger 43a37021a5 ensure extend_app js files from extensions are loaded directly before the apps js file 2026-02-27 09:24:47 +01:00
Johann Hoffmann abeb411742 betreuer email button config 2026-02-26 18:00:14 +01:00
Johann Hoffmann aa2334afe7 sammelmail button betreuer page; fix notenOpt retrieval in setDetailComponent for Betreuer when reopening detailView; $emit("paUpdated") after savingTermin/deletingTermin to update projektarbeit in overview table aswell; 2026-02-26 17:58:48 +01:00
Harald Bamberger 667a00d64b Merge branch 'master' into feature-68296/Vue_Router_via_Extensions_erweitern_ma0080 2026-02-26 16:05:32 +01:00
Harald Bamberger 4deed45f29 prepend extend_app js to customJSModules array, use FhcApps in Dashboard/Fhc App 2026-02-26 15:53:41 +01:00
Harald Bamberger 1ae072390e revert changes to add fhcApps property, not using path based syntax, to CI views include array 2026-02-26 15:27:52 +01:00
Andreas Österreicher 9eb2cb847d Merge branch 'feature-61164/AbgabetoolQualityGates' 2026-02-26 15:06:42 +01:00
Harald Bamberger 26fca87c75 refactor VueJs App magic into a helper function 2026-02-26 14:56:33 +01:00
ma0048 f3986688f2 selfoverview:
nur aktive kategorien anzeigen
uebersetzungen hinzugefuegt
2026-02-26 12:50:37 +01:00
Johann Hoffmann 859cb39a9d EmailJobs log & skip cases where no benutzer_uid email and no private email is available 2026-02-26 11:36:06 +01:00
Johann Hoffmann 4e2c3f7741 show qgate benotungsstatus of saved note, not currently selected note 2026-02-26 11:18:27 +01:00
ma0048 f1dbc6ab7d mc4 vorlage hinzugefuegt 2026-02-25 14:46:15 +01:00
Johann Hoffmann 325c84e6fe phrasen consistency "Short description of the submitted file" -> "Short description of the submitted document" + "Type of document submitted" 2026-02-25 13:31:00 +01:00
Johann Hoffmann 379880aef8 filter paabgabe uploads from newOrChanged job, since uploading a file still writes updateamum/updatevon fields -> compare student_uid with updatevon; when logging new paabgabe termine insert the whole paabgabe object into the logs, not just the result id; 2026-02-25 13:10:30 +01:00
Johann Hoffmann 16186bbee8 Merge branch 'master' into feature-61164/AbgabetoolQualityGates 2026-02-25 11:09:50 +01:00
Cristina d1015956d1 Merge branch 'master' into epic-56039/LV-Evaluierung 2026-02-25 10:54:29 +01:00
Cristina 726fce9fac Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-02-25 10:52:50 +01:00
Harald Bamberger ee0fa9f7d4 studvw reduce height of elements e.g:
- tabulator header filter
 - tabulator rows
 - form input and select
 - primevue autocomplete
 - primevue tabs
2026-02-24 17:23:50 +01:00
Harald Bamberger 7680a5c773 add bpk to api output if authuser has permission 2026-02-24 17:19:49 +01:00
Johann Hoffmann 1e827fffee additional erstbetreuer/zweitbetreuer name parts fetch & columns default invisible, columns next/prev termin header filter & custom sort func, list header filter for qgate 1/2 status assistenz & mitarbeiter, change all "Assessor" and "Assesor" phrasen to "Reviewer" 2026-02-24 15:58:44 +01:00
Harald Bamberger 0468b2b523 Merge branch 'master' into feature-68767/FHC4_Studierendenverwaltung_Details_4spaltig 2026-02-23 16:56:07 +01:00
Paolo d6108d816e Merge branch 'master' into hotfix-69228/DOCSBOX 2026-02-23 14:28:54 +01:00
Paolo f274b74ab1 Merge branch 'master' into feature-70440/Change_var_dump_to_error_log_to_show_the_referring_script 2026-02-23 14:25:40 +01:00
Paolo 029c51c2b2 Merge branch 'master' into bug-70950/Coodle_ICS_Organizer_falsch 2026-02-23 13:36:17 +01:00
Paolo 356a5fb51b Merge branch 'master' into bug-56209/is_valid_date_vs_isValidDate 2026-02-23 13:03:06 +01:00
Paolo 05b3040dd7 Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2026-02-23 12:23:54 +01:00
Paolo cd2941c904 Merge branch 'feature-13011/installation_on_multiple_servers' into merge-6237-13011 2026-02-23 12:23:45 +01:00
Paolo f1a7759a9d Merge branch 'master' into feature-6237/Phrases_system_MkIII 2026-02-23 12:23:06 +01:00
Paolo 9ea694bf9f Merge branch 'master' into feature-13011/installation_on_multiple_servers 2026-02-23 12:18:14 +01:00
Andreas Österreicher 9b114c5fb1 Merge branch 'feature-71344/LVEvaluierungZeitfenster' 2026-02-23 09:51:47 +01:00
Harald Bamberger 00fae2fa15 Merge branch 'master' into vv_und_studvw_2026_02_rc4 2026-02-23 09:28:54 +01:00
Johann Hoffmann 6c8eb9ac38 abgabetool dbupdate script check&insert new tbl_vorlage entry "PAANoSigAssSM" 2026-02-20 13:56:11 +01:00
Andreas Österreicher 2228b4d683 Sancho Header LV-Evaluierung 2026-02-20 13:29:01 +01:00
Johann Hoffmann 5558f6fc17 Signatur Sammelmail Job an Assistenz 2026-02-20 12:20:26 +01:00
kindlm 32fc029bd3 Merge remote-tracking branch 'origin/master' 2026-02-20 11:20:19 +01:00
kindlm f4e0516d89 Prüfung ob jede Fragen mindestens 2 Vorschläge hat auf Warning geändert
- Kleines Padding vor "Blättern"-Text
2026-02-20 11:20:09 +01:00
Harald Bamberger d98b7fd67a fix duplicates in lvplan for special groups 2026-02-19 18:34:27 +01:00
Johann Hoffmann 4b1a9fe892 avoid loading paabgaben a 2nd time for mitarbeiter; extracted getDateStyleClass from components; 2026-02-19 17:33:41 +01:00
ma0068 118dcbd252 remove testoutput 2026-02-19 15:45:34 +01:00
ma0068 d279f955a0 add emit-event for resetFilter 2026-02-19 15:12:38 +01:00
ma0068 1e8ec83965 add tileUid to StudentHeader, show Tiles only for selection of 1 student, just allow single selection of Mitarbeiter in MitarbeiterHeader 2026-02-19 11:57:28 +01:00
Harald Bamberger f2d49e02a7 Merge branch 'master' into vv_und_studvw_2026_02_rc4 2026-02-19 09:49:44 +01:00
Harald Bamberger 7169cb68a2 fix bug when sending multi messages introduced by loading time optimisation 2026-02-19 09:20:10 +01:00
Harald Bamberger f8da0b0915 Merge branch 'feature-69551/Einmeldeformular_als_VueJS_Component_fuer_LV-Evaluierung' 2026-02-19 07:46:15 +01:00
Alexei Karpenko f068b56083 PlausiIssueProducer: removed debugging output and die 2026-02-18 22:30:29 +01:00
Alexei Karpenko fa7a125727 Studierendenverwaltung archivieren: error message when no studentlehrverband found 2026-02-18 21:18:57 +01:00
Johann Hoffmann 4724008c2d betreuer page update table after adding serientermin qgate1/2 status prev/next; preserve scrollX/Y in betreuer/assistenz page 2026-02-18 14:32:57 +01:00
ma0068 34cd5d1a80 Filter List: only emit to updateURL if there is final dropdown result or change 2026-02-18 13:17:37 +01:00
Johann Hoffmann 6f28696556 getDateStyleClass evaluation also with precise luxon calculation on all pages; qgate12 status col, next/prev termin col on betreuer page; table persistence on mitarbeiter page; same rowheight on betreuer table as in assistenz to achieve similar UX; 2026-02-18 13:00:19 +01:00
Andreas Österreicher 6ec4737b22 Merge branch 'bug-71685/bewerbungstool_login_zugangscode' 2026-02-18 12:47:02 +01:00
Johann Hoffmann 328affa35c actually set deadline calculation to IANA timezone 'Europe/Vienna', so the code still works once Berlin moves to another timezone away from Austria. You never know. 2026-02-18 11:53:24 +01:00
ma0068 4b875bf019 also show filterActiveModule for HeaderFilters, change colour to red 2026-02-18 11:27:14 +01:00
Johann Hoffmann 90c845899f explicitely set deadline to end of day to achieve the desired "valid until 23:59" logic, instead of just moving the deadline by one day; endupload deadline is now optional by defining it as a "nachreichen möglich" aka non fixtermin; 2026-02-18 11:15:59 +01:00
Andreas Österreicher bb273d10bd Merge branch 'bug-71662/Bug_cancelVertrag_Berechtigungspruefung' 2026-02-18 10:50:59 +01:00
Johann Hoffmann a6daa7bf0c all abgabetool datepickers use date format via format="dd.MM.yyyy" instead of :format="formatDate" to enable text-input + autoapply; backend deadline datetime check for endupload; 2026-02-17 17:32:11 +01:00
ma0068 f0597e99e5 VV: update persistanceId 2026-02-17 16:51:56 +01:00
ma0048 1d8c4b7159 bug behoben, login wieder nur mit zugangscode moeglich 2026-02-17 16:49:09 +01:00
ma0068 f860fd3dc7 Studvw: update persistance_id for all tabs 2026-02-17 16:46:22 +01:00
Johann Hoffmann ee7254a964 assistenz preserve table state (selection, scroll) when adding serientermin; update isPastDate() function to luxon timezone safe logic; 2026-02-17 16:22:26 +01:00
ma0068 5ffd22c1f7 refactor last tabs from updateDefinition to setHeader variante 2026-02-17 16:11:43 +01:00
Alexei Karpenko c58674d133 Projektarbeiten cancelVertrag permission check bugfix (added array_column to get oes) 2026-02-17 15:15:30 +01:00
Harald Bamberger 006393704c Merge branch 'master' into vv_und_studvw_2026_02_rc4 2026-02-17 12:17:15 +01:00
Harald Bamberger 4825c75b5d revert changes made in commit b1a1cdf235 2026-02-17 12:11:37 +01:00
Harald Bamberger d82c186643 Merge branch 'master' into vv_und_studvw_2026_02_rc4 2026-02-17 11:23:18 +01:00
ma0048 2f51f18447 studierende in die gruppe ziehen ohne vorheriges selektieren 2026-02-17 11:16:44 +01:00
ma0048 5b34a226bd verbandsbaum nur toggeln und nicht automatisch selektieren 2026-02-17 11:09:54 +01:00
ma0068 1c69f3f654 VV: refactor Modal, change height of Table Unassigned Contracts 2026-02-17 10:31:45 +01:00
Harald Bamberger f6fd5ab678 Merge branch 'feature-71645/StudVw_MessageTab_Ladezeit' 2026-02-17 10:29:10 +01:00
Harald Bamberger 3d1aef617f add phrase error.opproject_does_not_exists in category kvp 2026-02-17 08:13:07 +01:00
Harald Bamberger e12b7e1ed5 add indexes for person_id to table msg_message and msg_recipient, ensure tabulator data request is made before requests of create msg components 2026-02-17 08:06:30 +01:00
ma0068 d9d3b1a245 VV: show Details und Status only if one Vertrag is selected 2026-02-17 07:58:03 +01:00
ma0068 ce27964df9 Detailheader VV and StudV: show - if no value for Tile 2026-02-16 16:46:46 +01:00
Harald Bamberger 0496eb7cc9 use union instead of or to avoid parallel seq scan 2026-02-16 15:56:40 +01:00
ma0068 556683574c Ignore typing inside editable elements for handling of keyboards event in function onKeydown 2026-02-16 15:44:01 +01:00
Harald Bamberger 962cbf4e78 join person table for sender and recipient instead of using subselect 2026-02-16 15:16:49 +01:00
Harald Bamberger 5415180b2c fetch count and paginated data in one query 2026-02-16 14:18:59 +01:00
ma0068 9d789d9a97 Tab Messages: remove unused computed statusText 2026-02-16 10:37:15 +01:00
ma0068 3d061df1d7 merge master into feature-68767/FHC4_Studierendenverwaltung_Details_4spaltig 2026-02-16 10:05:45 +01:00
Andreas Österreicher 827b6148a7 Merge branch 'feature-61164/AbgabetoolQualityGates' 2026-02-16 08:47:30 +01:00
Johann Hoffmann 3831f3c1d7 consistent use of :optionDisabled="getOptionDisabled" for paabgabetyp dropdowns in assistenz view 2026-02-16 03:41:30 +01:00
Johann Hoffmann 60294dd8f2 paBenotet evaluation fix 2026-02-16 03:22:39 +01:00
Harald Bamberger a9b343646e Merge branch 'master' into vv_und_studvw_2026_02_rc4 2026-02-13 10:49:09 +01:00
ma0068 fd35d20955 refactor VV: change handling of selections, allow only strg for multiselect in vetraegen and for adding unassignedVertraege 2026-02-13 09:24:36 +01:00
Paolo 34b00f8dd6 cis/public/coodle.php now produces the correct ORGANIZER:MAILTO: 2026-02-12 21:44:12 +01:00
ma0068 aec0e5227f get selection after reload of added or updated contract, remove selection, stati and details after delete 2026-02-12 15:09:51 +01:00
Paolo 990b8d281c Merge branch 'feature-13011/installation_on_multiple_servers' into merge-6237-13011 2026-02-09 12:36:12 +01:00
Paolo b2358c57d7 Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2026-02-09 12:35:59 +01:00
Paolo 6b7e061c87 Merge branch 'master' into feature-6237/Phrases_system_MkIII 2026-02-09 12:34:28 +01:00
Paolo 912896d4da Merge branch 'master' into feature-13011/installation_on_multiple_servers 2026-02-09 12:27:32 +01:00
ma0068 e13a7069dc Studverwaltung: refactor from Tabulator5 to 6, reformat some date entries 2026-02-06 13:18:09 +01:00
ma0068 1cd332115b Changes Vertragsverwaltung
- refactor from Tabulator 5 to Tabulator 6
- not reloading contract list after changes of Status or Detail to keep row selection
- Start reselection of current row
2026-02-06 10:38:29 +01:00
ma0068 0bf9d8fa8a Adaptions Detailheader: center Title and Values for Tiles, change size for mitarbeiterDetailHeader 2026-02-05 14:50:20 +01:00
ma0068 464f04b254 merge studvw_2026_02_rc4 in vv_und_studvw_2026_02_rc4 2026-02-05 11:57:03 +01:00
ma0068 2a63b99816 handle emit redirectToLeitung in parent 2026-02-05 11:50:43 +01:00
ma0068 2aca2cd6ab Custom Filter: change colour to green for filter symbol 2026-02-05 09:55:07 +01:00
ma0068 ee619004bd refactor tabulatorevents to avoid updateDefinitions (Tabs Betriebsmittel, Funktionen, Messages, Notizen, Abschlusspruefung, Anrechnungen, Aufnahmetermine, Dokumente, Kontakt, Lehrveranstaltungstermine, Mobility, Prestudent, Pruefungen) 2026-02-05 09:41:15 +01:00
ma0068 fc0fdc7909 Merge branch 'studvw_2026-02_rc4' of github.com:FH-Complete/FHC-Core into studvw_2026-02_rc4 2026-02-04 11:34:19 +01:00
ma0068 3053289146 Filter: change type filter Active, change position filter item, default values All Buchungstypen 2026-02-04 11:33:54 +01:00
Harald Bamberger f6b13c0bdf Merge branch 'master' into studvw_2026-02_rc4 2026-02-03 17:16:42 +01:00
ma0068 e0082db7c9 Tab Aufnahmetermine: add context self to computed properties and adapt name of 2 variables, Tab Lehrveranstaltungstermine: add space 2026-02-03 16:16:18 +01:00
ma0068 936858948b merge bug-71363/FHC4_Stvw_Refactor_TabulatorOptions_As_Computed into origin/studvw_2026-02_rc4 2026-02-03 14:15:58 +01:00
ma0068 18c949eed4 refactor tabulator options and events into computed section: Tabs Betriebsmittel, Abschlusspruefung, Anrechnungen, Aufnahmetermine, Kontakt, Prestudent, Status, bugfix Lehrveranstaltungstermine: sorter for Lektor as string 2026-02-03 13:57:30 +01:00
Harald Bamberger 82f0f3f5e3 Merge branch 'bug-71363/FHC4_Stvw_Refactor_TabulatorOptions_As_Computed_Part1' into studvw_2026-02_rc4 2026-02-03 13:39:59 +01:00
Harald Bamberger 8b9601502a Merge branch 'bug-71363/FHC4_Stvw_Refactor_TabulatorOptions_As_Computed' into studvw_2026-02_rc4 2026-02-03 13:38:28 +01:00
ma0068 888bb1c7c0 Merge branch 'master' into bug-71363/FHC4_Stvw_Refactor_TabulatorOptions_As_Computed_Part1 2026-02-03 13:26:04 +01:00
ma0068 372c932c47 Merge branch 'master' into bug-71363/FHC4_Stvw_Refactor_TabulatorOptions_As_Computed 2026-02-03 13:16:17 +01:00
Harald Bamberger 69749da331 Merge branch 'master' into feature-52533_62055/Vertragsverwaltung_mit_CoreComponent_DetailHeader 2026-02-03 11:46:19 +01:00
Harald Bamberger 0442a3da0a Merge branch 'bug-71363/FHC4_Stvw_Refactor_TabulatorOptions_As_Computed' into studvw_2026-02_rc4 2026-02-03 10:58:24 +01:00
Harald Bamberger 2492a4fc06 Merge branch 'bug-70848/FHC4_Studierendenverwaltung_Notiz_handleVisibleColumns_pp' into studvw_2026-02_rc4 2026-02-03 10:57:38 +01:00
Harald Bamberger 9ae9feb9ea Merge branch 'bug-69548/FHC4_Studierendenverwaltung_Aufnahmetermine_Gesamtnote_berechnen' into studvw_2026-02_rc4 2026-02-03 10:48:06 +01:00
Harald Bamberger a535fd85cd Merge branch 'feature-69516/studvw_verbandsbaum_zu_ausklappbar_machen' into studvw_2026-02_rc4 2026-02-03 10:47:31 +01:00
Harald Bamberger 269860252e Merge branch 'feature-69710/FHC4_Studierendenverwaltung/Filterverhalten_bei_Aenderungen' into studvw_2026-02_rc4 2026-02-03 10:46:57 +01:00
Harald Bamberger d0faba03a2 Merge branch 'feature-39571/Studierendenverwaltung_CoreNotizcontroller' into studvw_2026-02_rc4 2026-02-03 10:43:39 +01:00
ma0068 88a06194d4 Merge branch 'master' into bug-70848/FHC4_Studierendenverwaltung_Notiz_handleVisibleColumns_pp 2026-02-03 10:36:13 +01:00
ma0068 8c22a652fa merge master into bug-71363/FHC4_Stvw_Refactor_TabulatorOptions_As_Computed 2026-02-02 17:24:36 +01:00
ma0068 a70e25d0e8 Merge branch 'master' into feature-69516/studvw_verbandsbaum_zu_ausklappbar_machen 2026-02-02 16:48:02 +01:00
ma0068 e689531224 merge master into bug-69548/FHC4_Studierendenverwaltung_Aufnahmetermine_Gesamtnote_berechnen 2026-02-02 16:31:13 +01:00
ma0068 3ab1a002f0 Merge branch 'master' into feature-69710/FHC4_Studierendenverwaltung/Filterverhalten_bei_Aenderungen 2026-02-02 16:24:51 +01:00
ma0068 b9eaac18b0 merge Master into feature-39571/Studierendenverwaltung_CoreNotizcontroller 2026-02-02 16:21:47 +01:00
ma0068 b26df9ac21 Tab Kontakt: Bankaccount: move tabulator options to computed, fix bug height 2026-02-02 11:48:02 +01:00
ma0068 0539281adf Messages: move tabulator options and event to computed 2026-02-02 11:36:03 +01:00
ma0068 e01d814ae9 Tab Dokumente: move tabulator options and event to computed 2026-02-02 09:44:47 +01:00
ma0068 99ea6ad333 - moved tabulator options to computed
- removed unused change param
- added values to resetModal
2026-01-30 14:26:32 +01:00
ma0068 683626921b Tab Mobility: moved tabulator options to computed 2026-01-30 13:21:40 +01:00
ma0068 e3b630550a delete comment 2026-01-28 14:42:26 +01:00
ma0068 8903fa878c - more prominent view of Active Custom Filter
- one click filterreset
- fhc search bar: resetFilter with submit
2026-01-28 13:33:01 +01:00
ma0068 5dcf8bb854 add showVariables.showErledigt to tabulatorOptions 2026-01-26 15:11:00 +01:00
Harald Bamberger afc4544304 use showVariables properties directly in tabulatorOptions and tabulatorEvents moved to computed, so they are used only if user has not customized columns visibility in localstorage 2026-01-26 14:09:07 +01:00
ma0048 0a2afadb0a tagheaderfilter bug fix 2026-01-26 13:21:20 +01:00
Cristina 27a91de5f6 Added app lvevaluierung to system.tbl_app 2026-01-22 15:51:05 +01:00
Cristina 7ccc26c878 Added lvevaluierung phrasen for STGL Übersichtsseite 2026-01-22 15:41:25 +01:00
Cristina 9ebc847e8e Added lvevaluierung phrasen for Lektoren Übersichtsseite 2026-01-22 14:59:00 +01:00
Cristina 511b04c1f8 Merge branch 'master' into epic-56039/LV-Evaluierung 2026-01-21 18:01:55 +01:00
Cristina ec90d35e02 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-01-21 18:01:24 +01:00
Paolo d365f15744 Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2026-01-13 17:11:22 +01:00
Paolo 36823dac7d Merge branch 'feature-13011/installation_on_multiple_servers' into merge-6237-13011 2026-01-13 17:11:14 +01:00
Paolo a1142136b2 Merge branch 'master' into feature-6237/Phrases_system_MkIII 2026-01-13 17:08:02 +01:00
Paolo a0c41c95cd Merge branch 'master' into feature-13011/installation_on_multiple_servers 2026-01-13 16:47:08 +01:00
ma0068 4f104523ff - include directive primevue.tooltip
- refactor phrases to avoid timing problem with loading phrases of alert
2026-01-08 16:02:29 +01:00
Paolo 1ce362b66b Removed forgotten error_log 2026-01-07 15:54:59 +01:00
ma0068 02153e469f Dashboard Admin Cleanup
- refactoring Api: FHC-API controller for Edit/Update, widgets and presets
- delete dashboard with Prompt
- phrases
2025-12-19 11:39:31 +01:00
Paolo 47d4b2e2d4 Change var_dump_to_error_log to show the referring script -> tail -f /var/log/apache2/error.log | grep <user> can catch it 2025-12-18 13:20:08 +01:00
ma0068 f40f554c6b add logic for config FAS_REIHUNGSTEST_EXCLUDE_GEBIETE 2025-12-11 10:53:15 +01:00
ma0048 b4668aa6bc verbandsbaum zu/ausklappbar 2025-12-11 08:58:05 +01:00
ma0068 1176c8d6e4 - use studiengang_kz and studiengangkurzbz of studienordnung of persontRT
- add check for existing studiengang
- use studiengang_kz instead studiengangkurzbz for filter and background green
2025-12-10 09:49:00 +01:00
ma0068 43497b186d return empty array if there is no placementtest instead of error 2025-12-09 11:43:39 +01:00
ma0068 e78482e947 - refactor sum points
- create green row background for current RT
2025-12-05 12:31:02 +01:00
ma0048 96be1789b5 tag-formatter & helper hinzugefuegt 2025-11-27 09:45:57 +01:00
ma0068 38e8f91fdf add kurzbzlang to studentDropdown suggestion 2025-11-25 10:48:57 +01:00
Harald Bamberger 3730be991a Merge branch 'master' into feature-39571/Studierendenverwaltung_CoreNotizcontroller 2025-11-19 11:30:52 +01:00
Paolo 7868c33c3d Merge branch 'feature-13011/installation_on_multiple_servers' into merge-6237-13011 2025-11-13 09:55:40 +01:00
Paolo 3e303a6617 - ExtensionsLib->getInstalledExtensions returns only the extensions installed on the current server
- Better checks if no file has been uploaded
2025-11-13 09:53:06 +01:00
Paolo 0b6dc34220 If docsbox queue is slow, the DocsboxLib can stop checking the queued document status and raise an error 2025-11-10 15:41:01 +01:00
Paolo e774787d67 Merge branch 'feature-13011/installation_on_multiple_servers' into merge-6237-13011 2025-11-05 14:24:51 +01:00
Paolo c44bef3b19 Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2025-11-05 14:24:43 +01:00
Paolo 4c9476866d Merge branch 'master' into feature-6237/Phrases_system_MkIII 2025-11-05 14:23:59 +01:00
Paolo bd50a9a141 Merge branch 'master' into feature-13011/installation_on_multiple_servers 2025-11-05 14:23:45 +01:00
Paolo 481b221f89 Fixed Extensions Manager GUI 2025-11-05 14:23:09 +01:00
Paolo 4177c83c8e Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2025-11-03 16:33:16 +01:00
Paolo bc2fb32e3e Fixed phrases import from old system to the new one 2025-11-03 16:32:37 +01:00
Paolo 16ebbc324e Merge branch 'master' into feature-6237/Phrases_system_MkIII 2025-11-03 15:31:53 +01:00
Paolo abcc31b4e9 Merge branch 'master' into feature-13011/installation_on_multiple_servers 2025-11-03 15:31:37 +01:00
Paolo 50a14ccae8 Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2025-11-03 13:40:47 +01:00
Paolo 257b64a9a2 Fixed application/phrases/extensions.php 2025-11-03 13:40:32 +01:00
Paolo 0541596a91 Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2025-11-03 13:37:40 +01:00
Paolo b8aec21968 Added new phrases for the extensions manager into the PhrasesMkIII system 2025-11-03 13:37:01 +01:00
Paolo c438a2d6d8 Added phrases for the extensions manager into the new Phrases MkIII system 2025-11-03 13:35:27 +01:00
Paolo c2d6d01045 Merge branch 'feature-13011/installation_on_multiple_servers' into merge-6237-13011 2025-10-29 13:57:28 +01:00
Paolo 087930416f Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2025-10-29 13:53:12 +01:00
Paolo 18d2b72b30 Merge branch 'master' into feature-6237/Phrases_system_MkIII 2025-10-29 13:52:28 +01:00
Paolo 1cbd25b052 Merge branch 'master' into feature-13011/installation_on_multiple_servers 2025-10-29 13:52:09 +01:00
Paolo 48cd737bd9 - Added phrases for the Extension manager
- Fixed public/js/TableWidget.js
2025-10-29 13:50:05 +01:00
Paolo 819652f70b Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2025-10-28 13:41:58 +01:00
Paolo b72d20ff86 Fixed phrases files 2025-10-28 13:41:40 +01:00
ma0068 c78eef8af5 add validation for required props, refactor slots 2025-10-28 09:31:04 +01:00
ma0068 6a7de7417b student view: reload after delete or upload 2025-10-27 13:50:25 +01:00
ma0068 c12678ca5a buttons edit and delete foto: adapt for better visibility, add preview to upload 2025-10-27 13:43:59 +01:00
ma0068 84bfea0be9 make Prestudent.js and Details.js responsive 2025-10-24 11:18:19 +02:00
Paolo db09f357d1 Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2025-10-21 15:04:08 +02:00
Paolo 63810ccc81 Merge branch 'feature-13011/installation_on_multiple_servers' into merge-6237-13011 2025-10-21 15:03:59 +02:00
Paolo 33047797fd Merge branch 'master' into feature-13011/installation_on_multiple_servers 2025-10-21 13:12:21 +02:00
Paolo e32ce9a7ec Merge branch 'master' into feature-6237/Phrases_system_MkIII 2025-10-21 13:11:51 +02:00
ma0068 7755dc12d0 View Studierendenverwaltung
- add badge unruly
- add tileSlots for PersKz, MatrikelNr, person_id
- remove MatrikelNr and person_id from left side
- add attribut unruly to student object
2025-10-15 13:55:54 +02:00
ma0068 15a9379c6e use Slots for Core Detail Header: Tags, Issues, TileSlots 2025-10-14 15:45:11 +02:00
ma0068 40512edef0 add emit redirect to reload parent 2025-10-13 16:46:29 +02:00
ma0068 e9c039dad2 Refactor detailHeader component for PV21
- own css.file for fotouplad
- domain as prop
- refactor link to Leitung
- slots for issuetracking and tags
2025-10-13 16:07:51 +02:00
ma0068 c7f2b145bf add checkBerechtigungen for Notes person_id and notes prestudent_id 2025-10-10 14:15:40 +02:00
chfhtw 601c4367dc use fhcApps for CIS 2025-10-09 10:57:51 +02:00
chfhtw 70c230edce use fhcApps for LogsViewer/LogsViewer 2025-10-09 10:44:13 +02:00
chfhtw d294d17e37 use fhcApps for lehre/lvplanung/LvTemplates 2025-10-09 10:42:22 +02:00
chfhtw d88cc77a5c use fhcApps for Studstatus 2025-10-09 10:40:02 +02:00
chfhtw 61600e78b6 use fhcApps for Bismeldestichtag/Bismeldestichtag 2025-10-09 09:27:31 +02:00
chfhtw ea0b69d4c2 use fhcApps for ProfilUpdateRequest 2025-10-09 09:15:26 +02:00
chfhtw 0309c04ae0 use fhcApps for Cis/Documents 2025-10-09 08:46:09 +02:00
chfhtw 3c3e920573 use fhcApps for Studentenverwaltung 2025-10-09 08:43:12 +02:00
chfhtw d389cf87b8 delete MyLv->Info because app does not exist anymore and url is rerouted to MyLv->index 2025-10-09 08:42:29 +02:00
chfhtw 09864c5154 remove unused view that links to a non existing app 2025-10-09 08:41:58 +02:00
ma0068 204ae1a469 refactor prepareQuery, use and take into account config parameters, refactor autoSelectRows 2025-10-08 16:34:39 +02:00
chfhtw d2f21ba4e6 use fhcApps for LVVerwaltung 2025-10-08 14:45:12 +02:00
chfhtw 842dabc1e7 add fhcApps functionality to view template 2025-10-08 13:37:06 +02:00
chfhtw 67281c84ed FhcApps Library 2025-10-08 13:36:20 +02:00
ma0068 3a6c8dfd2d adapt event dataProcessed and method autoselect 2025-10-08 10:28:14 +02:00
ma0068 450789ed72 extend query getStudents, change zuordnung_type from uid to prestudent 2025-10-08 09:12:54 +02:00
ma0068 984d81edb6 add tag component to List.js, add column tags to table, add functionality add, delete and update 2025-10-06 16:37:17 +02:00
ma0068 e79bb607d9 add permission validation oe for lehreinheit 2025-10-03 10:23:25 +02:00
ma0068 890b50c830 add new api for notiz 2025-10-01 13:13:41 +02:00
ma0068 3664428467 add logic to edit and delete Personfoto 2025-09-30 10:50:01 +02:00
Harald Bamberger 845c75b775 Merge branch 'master' into feature-39571/Studierendenverwaltung_CoreNotizcontroller 2025-09-26 12:33:39 +02:00
ma0068 5326f961c6 DetailHeader: add uid to redirectToLeitung 2025-09-25 11:25:55 +02:00
Paolo e98e708283 Merge branch 'feature-13011/installation_on_multiple_servers' into merge-6237-13011 2025-09-22 11:57:15 +02:00
Paolo 513e9325e1 Merge branch 'feature-6237/Phrases_system_MkIII' into merge-6237-13011 2025-09-22 11:11:48 +02:00
Paolo 9c60ab7be2 Merge branch 'master' into feature-13011/installation_on_multiple_servers 2025-09-22 11:00:30 +02:00
Paolo b23eca2a63 Added new phrases 2025-09-22 10:56:46 +02:00
Paolo 0f82e73935 Fixed application/libraries/PhrasesLib.php->_appendPhraseToCategoryFile 2025-09-22 10:54:57 +02:00
Paolo 0c83bdfc68 Merge branch 'master' into feature-6237/Phrases_system_MkIII 2025-09-22 10:31:11 +02:00
Andreas Österreicher 9067f0e00a Merge branch 'master' into feature-52533_62055/Vertragsverwaltung_mit_CoreComponent_DetailHeader 2025-09-05 12:48:33 +02:00
Andreas Österreicher 4099d91a1b Vertragsverwaltung - Filter korrigiert fuer aktive und inaktive
Mitarbeiter
2025-09-05 12:45:39 +02:00
ma0068 1bb10ddeb1 refactor backend filter 2025-09-03 10:43:20 +02:00
ma0068 49e89f44be set default domain to fhcomplete.info 2025-09-02 20:37:20 +02:00
ma0068 e5cf417ac0 adapt headerFilter, remove frontend filter, add backend filter aktiv mitarbeiter 2025-09-02 20:29:23 +02:00
ma0068 ea85cce957 own controller detailHeader, bugfix loadDepartmentdata 2025-09-01 09:37:30 +02:00
Andreas Österreicher 703872adc9 Merge branch 'master' into feature-52533_62055/Vertragsverwaltung_mit_CoreComponent_DetailHeader 2025-08-20 11:14:40 +02:00
Harald Bamberger e2d6e5d9c8 Merge branch 'master' into feature-39571/Studierendenverwaltung_CoreNotizcontroller 2025-08-14 18:38:04 +02:00
ma0048 4a8868a709 verfasser nur noch readonly - wird im backend gesetzt 2025-07-21 15:29:57 +02:00
ma0068 10399db372 add handling comma in combination with titelpost 2025-07-14 09:42:41 +02:00
ma0068 179b50c798 fixed js-warnings
- Extraneous non-props attributes
 - duplicate html code
 - html template error
2025-07-10 14:27:54 +02:00
ma0068 ec1960e839 Bugfix: Delete Vertragsstatus if Betreuung 2025-07-10 13:33:54 +02:00
ma0068 a942423e84 remove unused code 2025-07-10 12:44:35 +02:00
ma0068 3ca49c5574 refactor function getHeader, get mitarbeiter_uid as prop instead of using function getMitarbeiterUid 2025-07-08 15:01:54 +02:00
ma0068 d1e35b1851 bugfix js error after sort: take out persistance for header filter 2025-07-03 12:14:00 +02:00
ma0068 46a10bd92e page handling
- entry in main navigation menu
- import navigation component
- remove space side menu
2025-07-03 11:14:20 +02:00
ma0068 b4d5e1c90a bugfix delete Vertragsdetails, add missing data updateamum, updatevon 2025-07-02 13:41:08 +02:00
ma0068 411b97fa14 reload Vertragsstatus if change of mitarbeiter 2025-07-02 11:54:32 +02:00
ma0068 56e8a34d68 readd Phrasen Vertragsverwaltung 2025-07-02 09:09:33 +02:00
ma0068 8c69bc1682 Headerfunctions in headerAPI auslagern 2025-06-11 15:28:19 +02:00
ma0068 2eef05e593 - refactore POST_Variablen with form_validation->set_data
- add phrase: Vertragsstatus bearbeiten
- filterActive: bugfix
2025-06-11 15:02:31 +02:00
ma0068 a56a804692 - fix error with Event 'multiActionPrintHonorarvertrag'
- Naming components Vertragsverwaltung, MitarbeiterHeader, CoreListMitarbeiter
- link to Vorgesetzter, show Vorgesetzter without postTitel
- Foto: if foto_sperre: show foto with lock
2025-06-11 13:46:23 +02:00
ma0068 a8f47fad45 copy Component DetailHeader into Vertragsverwaltung 2025-06-10 13:10:26 +02:00
ma0068 6f60d7c99e API Refactoring, some other minor fixes 2025-06-10 11:57:43 +02:00
ma0068 7d2da9e7f6 Merge master into feature-52533_62055/Vertragsverwaltung_mit_CoreComponent_DetailHeader 2025-06-06 11:46:31 +02:00
Harald Bamberger 8925692dd4 Merge branch 'master' into feature-39571/Studierendenverwaltung_CoreNotizcontroller 2025-05-21 17:03:58 +02:00
Cristina d4feee8914 Fixed wrong param causing wrong Notenliste for Wiederholer 2025-03-18 14:30:19 +01:00
Paolo bb476bb257 Merge branch 'master' into bug-56209/is_valid_date_vs_isValidDate 2025-03-12 11:54:50 +01:00
Paolo 7b74c36952 - Removed public method isValidDate from controller api/frontend/v1/studstatus/Unterbrechung
- Replaced callback_isValidDate with is_valid_date
- Removed global function isValidDate from helpers/hlp_common_helper
2025-02-27 12:09:30 +01:00
ma0068 31af28a7c4 Merge branch 'feature-52533/PV21_Karteireiter_Vertraege' of github.com:FH-Complete/FHC-Core into feature-52533/PV21_Karteireiter_Vertraege 2025-02-19 16:37:47 +01:00
ma0068 f3527dc8ff bugfix function getMitarbeiterUid 2025-02-19 16:37:30 +01:00
ma0068 660f9076ce delete commented out sections 2025-02-14 09:38:33 +01:00
ma0068 24682fb559 changeFormat Dates, use different select for MitarbeiterHeader before PV21, adapt condition for multiselect addon 2025-02-12 17:05:18 +01:00
ma0068 295e2aa3e5 adaptions styling 2025-01-22 11:17:09 +01:00
ma0068 0d0071e8bf refactoring and codesniff 2025-01-22 07:57:39 +01:00
ma0068 9c0baeacf2 Add Logic Permission and Phrases 2025-01-21 15:34:43 +01:00
ma0068 ffc99379ae Injection ADDON KU for Multiselect and Print Honorarvertrag 2025-01-20 15:25:06 +01:00
ma0068 35d8f0524d new page vertragsverwaltung with employee header and details components 2025-01-15 13:56:00 +01:00
ma0068 07e6146e50 Validations, Phrases, cleanup 2024-11-19 14:34:50 +01:00
ma0068 5751441424 filter offene Vertraege, validations insert, update Contract 2024-11-12 07:57:46 +01:00
ma0068 023fafde2c update reload functions, adapt delete contract, add watcher in unassignedList 2024-11-11 10:37:51 +01:00
ma0068 2d0285e31d add and update Lehrauftraege, logic sumup beträge 2024-11-08 13:29:19 +01:00
ma0068 9fd9c4e94d edit Status Contracts 2024-11-06 11:43:59 +01:00
ma0068 40baa7e08c update childcomponent vertragstati 2024-11-05 16:06:14 +01:00
ma0068 b1452698f8 Start View Karteireiter, Components Unassigned, Details and Stati 2024-11-04 12:54:34 +01:00
cgfhtw d542cf7720 s&d 2024-08-14 16:20:47 +02:00
Paolo e5f65ff442 - Added new public method syncFiles to application/controllers/system/phrases/CLI_Manager.php
- Added new constant CORE_PHRASES_LEGACY_CFG_FILE to application/libraries/PhrasesLib.php
- Added new public method syncFiles to application/libraries/PhrasesLib.php
- Added new private methods _appendPhraseToCategoryFile and _createPhraseToCategoryFile to application/libraries/PhrasesLib.php
2024-07-31 14:56:59 +02:00
ma0068 6e9ee7cf81 Notizcomponent: Api Controller for Notizzuordnungs_ids 2024-05-03 09:43:49 +02:00
Paolo 4944a13bfc Fixed JS & CSS includes for the Extensions manager 2023-04-06 12:21:17 +02:00
Paolo 5465f26c80 - Fixed deletion of the uidx_extensions_name_version index in the system DB update scripts
- Fixed creatation of uidx_extensions_name_version_server index in the system DB update scripts
2023-04-06 11:56:06 +02:00
Paolo e60335b635 Added new DB file system/dbupdate_3.4/13011_installation_on_multiple_servers.php 2023-04-05 14:33:27 +02:00
Paolo 5e799aa6e1 Moved DB changes from system/dbupdate_3.3.php to system/dbupdate_3.4/13011_installation_on_multiple_servers.php 2023-04-05 14:31:00 +02:00
Paolo c3fcd12bf9 Merge branch 'master' into feature-13011/installation_on_multiple_servers 2023-03-21 17:47:15 +01:00
Andreas Österreicher 16f6176d08 Extension Manager - Added missing Phrases 2022-04-13 19:01:16 +02:00
Paolo 158bf52f3b Updated new phrases application/phrases/ui.php 2022-04-13 14:31:21 +02:00
Paolo d75fd99a50 Merge branch 'master' into feature-6237/Phrases_system_MkIII 2022-04-13 14:26:21 +02:00
Paolo 7eceda4b3d Merge branch 'master' into feature-13011/installation_on_multiple_servers 2022-04-13 14:25:46 +02:00
Paolo 16d88d9f63 Controller system/extensions/Manager->toggleExtension now convert the enabled parameter from string to boolean 2022-04-13 14:21:19 +02:00
Paolo 0ccd4d1b88 Added missing phrases 2022-04-12 14:59:19 +02:00
Paolo c2addaf1a6 Merge branch 'master' into feature-6237/Phrases_system_MkIII 2022-04-12 11:01:31 +02:00
Paolo 9af36fc50c Merge branch 'master' into feature-13011/installation_on_multiple_servers 2022-04-12 10:38:01 +02:00
Paolo 4ea2772a8d Fixes to be compliant with PHPMD & PHPCS 2022-03-07 12:16:56 +01:00
Paolo 15f9762d01 - Fixed errors/violations noticed by PHPMD and PHPCS
- Removed parameter perform_sql from public method controllers/system/extensions/CLI_Manager->installExtension
- Added new public method controllers/system/extensions/CLI_Manager->installExtensionNoSQL
- Improved code quality in controllers/system/extensions/Manager->toggleExtension
- controllers/system/extensions/Manager->uploadExtension better check of
  HTTP POST parameter notPerformSql
- application/views/system/extensions/manager.php renamed checkbox
  performSql to notPerformSql
- application/views/system/extensions/tableWidget.php removed PHP close
  tag at the end of the file
- Improved code quality in application/widgets/TableWidget.php
- Removed private method _getColumnsNames from application/widgets/TableWidget.php
- Improved code quality in application/libraries/ExtensionsLib.php
- Added new private methods _getExtensionsPath and _getUploadPath to application/libraries/ExtensionsLib.php
- Changed application/libraries/ExtensionsLib->_toggleExtension to public method toggleExtension
- Removed private properties UPLOAD_PATH and EXTENSIONS_PATH from application/libraries/ExtensionsLib
- Added use imports in application/libraries/ExtensionsLib
- application/libraries/ExtensionsLib->installExtension changed parameters default values
2022-03-04 12:26:37 +01:00
Paolo 07e416c2f4 Replaced all the escaped umlaute with the corresponding character in the
phrases
2022-03-01 14:47:27 +01:00
Paolo d977cb8019 Removed var_dump from include/tw/vilesci_menu_main.inc.php 2022-02-02 11:54:15 +01:00
Paolo ab943729a6 Added new CLI controller to install phrases 2021-11-16 17:40:11 +01:00
Paolo d7b700f781 - Added new FilterWidget in the Administration menu for the phrases
- Extension installer is visible only for system/extensions
- Removed the old phrases editor from Vilesci
- system/checksystem.php does not call anymore system/phrasesupdate.php
- system/phrasesupdate.php has been removed
- Added new directory application/phrases
- application/phrases contains one file for each phrases category, and one file contains all the phrases for that category
- Added new controller system/phrases/Manager to install phrases in the core
- Added new constants CORE_PHRASES_DIRECTORY, INSERT_BY, APP, CATEGORY, PHRASE, SPRACHE, TEXT and DESCRIPTION to libraries/PhrasesLib
- libraries/PhrasesLib now loads EPrintfLib
- Removed public methods getPhraseByApp, getPhraseInhalt, delPhrasentext, savePhrase, getPhrasentextById, insertPhraseinhalt, getVorlagetextById and updatePhraseInhalt from libraries/PhrasesLib
- Renamed public method getJSON to toJSON in libraries/PhrasesLib
- Added new public methods installFromCore and installFrom to libraries/PhrasesLib
- Added new private methods _installPhrases and _addPhrases to libraries/PhrasesLib
2021-11-16 17:22:24 +01:00
Paolo 8bbc68ca75 Bufix: in case the file name contains not escaped / then it prints out
an error and quit the execution
2021-11-05 13:19:44 +01:00
Paolo e1c0d046cb HTML fixes views/system/extensions/manager.php 2021-09-28 09:11:18 +02:00
Paolo 023e0fc934 - Added new phrases fot the extension manager
- Renamed uploadExtension to installExtension in application/controllers/system/extensions/CLI_Manager.php
- Adapted controller system/extensions/Manager.php to use FHC_Controller functionalities
- Changed controller system/extensions/Manager->uploadExtension to get parameters from HTTP post and HTTP file
- Changed view system/extensions/manager.php to use templates/FHC-Header, ajaxlib, tablewidget, phrases and the CI upload library
- Added new column type array to application/widgets/TableWidget.php
- Added new type boolean to the public/js/AjaxLib.js result when checked by the hasData method
- Added new JS public/js/ExtensionsManager.js that contains the extensions manager JS
- Added new view system/extensions/tableWidget.php to display the extensions manager TableWidget
2021-09-27 12:45:55 +02:00
Paolo 063a3fa524 - Added missing column server_kurzbz to system/dbupdate_3.3.php column
check
- Changed the server column position in the extension manager view
- Removed public method getInstalledExtensions from application/models/system/Extensions_model.php
- Fixes, comments and indentations in application/libraries/ExtensionsLib.php
2021-09-15 18:08:08 +02:00
Paolo 22eae288cb Merge branch 'master' into feature-13011/installation_on_multiple_servers 2021-09-14 19:14:13 +02:00
Paolo 765edee509 Merge branch 'master' into feature-13011/installation_on_multiple_servers 2021-08-22 21:04:14 +02:00
ma0048 75647a5e24 tabs hinzugefuegt 2021-05-19 10:02:18 +02:00
ma0048 194979be6d aktivieren/deaktivieren nur auf dem jeweiligen server moeglich und bug fixed wenn server_kurz null ist 2021-05-19 09:58:44 +02:00
ma0048 43ff675b5e installation von extensions auf mehreren servern ermoeglicht 2021-05-05 13:37:19 +02:00
330 changed files with 83206 additions and 5082 deletions
@@ -0,0 +1,36 @@
<?php
$filterCmptArray = array(
"app" => 'core',
'datasetName' => 'vertragsverwaltung',
'query' => '
SELECT
uid,
person_id,
vorname,
nachname,
gebdatum,
vertragsarten,
unternehmen,
ids,
aktiv
FROM
(
SELECT
b.uid , p.person_id,
p.vorname, p.nachname,
gebdatum,
STRING_AGG(DISTINCT va.bezeichnung, \', \') AS Vertragsarten,
STRING_AGG(DISTINCT u.bezeichnung, \', \') AS Unternehmen,
STRING_AGG(d.dienstverhaeltnis_id::TEXT, \', \') AS ids,
b.aktiv
FROM
hr.tbl_dienstverhaeltnis d
JOIN public.tbl_benutzer b ON d.mitarbeiter_uid = b.uid
JOIN public.tbl_person p ON p.person_id = b.person_id
JOIN public.tbl_organisationseinheit u ON d.oe_kurzbz = u.oe_kurzbz
JOIN hr.tbl_vertragsart va ON d.vertragsart_kurzbz = va.vertragsart_kurzbz
GROUP BY b.uid, p.person_id, p.vorname, p.nachname, b.aktiv
) as vertragsdaten
',
'requiredPermissions' => 'vertrag/mitarbeiter'
);
+2
View File
@@ -41,3 +41,5 @@ $config['STG_MOODLE_LINK'] = 'https://moodle.technikum-wien.at/course/view.php?i
$config['ASSISTENZ_SAMMELMAIL_BUTTON_STUDENT'] = true;
$config['ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER'] = true;
$config['BETREUER_SAMMELMAIL_BUTTON_STUDENT'] = true;
+36 -3
View File
@@ -163,6 +163,13 @@ $config['navigation_header'] = array(
'expand' => true,
'sort' => 50,
'requiredPermissions' => 'lehre/gruppenmanager:r'
),
'vertragsverwaltung' => array(
'link' => site_url('vertragsverwaltung'),
'description' => 'Vertragsverwaltung',
'expand' => true,
'sort' => 51,
'requiredPermissions' => 'vertrag/mitarbeiter:r'
)
)
),
@@ -179,7 +186,7 @@ $config['navigation_header'] = array(
'description' => 'Extensions Manager',
'expand' => true,
'sort' => 10,
'requiredPermissions' => 'admin:r'
'requiredPermissions' => 'system/extensions:r'
),
'logsviewer' => array(
'link' => site_url('system/LogsViewer'),
@@ -192,7 +199,14 @@ $config['navigation_header'] = array(
'link' => site_url('system/jq/JobsQueueViewer'),
'description' => 'Jobs Queue Viewer',
'expand' => true,
'sort' => 20,
'sort' => 30,
'requiredPermissions' => 'system/developer:r'
),
'phrasesviewer' => array(
'link' => site_url('system/phrases/PhrasesViewer'),
'description' => 'Phrases viewer',
'expand' => true,
'sort' => 40,
'requiredPermissions' => 'system/developer:r'
),
'anrechnungen' => array(
@@ -201,7 +215,14 @@ $config['navigation_header'] = array(
'expand' => true,
'sort' => 30,
'requiredPermissions' => 'lehre/anrechnungszeitfenster:rw'
)
),
'dashboardadmin' => array(
'link' => site_url('dashboard/Admin'),
'description' => 'Dashboard Admin',
'expand' => true,
'sort' => 40,
'requiredPermissions' => 'dashboard/admin:r'
)
)
)
)
@@ -335,6 +356,18 @@ $config['navigation_menu']['system/issues/Issues/*'] = array(
'target' => '_blank',
'requiredPermissions' => array('admin:rw')
),
);
$config['navigation_menu']['vertragsverwaltung/*'] = array(
'vertragsverwaltung' => array(
'link' => site_url('vertragsverwaltung'),
'description' => 'Vertragsverwaltung',
'icon' => 'home',
'sort' => 100,
'target' => '_blank',
'requiredPermissions' => array('vertrag/mitarbeiter:r')
)
);
$config['navigation_menu']['apps'] = [
+13
View File
@@ -130,3 +130,16 @@ $config['students_tab_order'] = [
'combinePeople',
'archive',
];
$config['stv_prestudent_tags'] = [
'prioone' => ['readonly' => false],
'priotwo' => ['readonly' => true],
'hinweis' => ['readonly' => false],
'hinweis_assistenz' => ['readonly' => true],
'hinweis_kf' => ['readonly' => true],
'hinweis_lehrende' => ['readonly' => false],
'hinweis_stg_kf' => ['readonly' => true],
'finished_stg' => ['readonly' => true],
'finished_kf' => ['readonly' => true],
'inwork_kf' => ['readonly' => true],
];
-5
View File
@@ -33,9 +33,4 @@ class MyLv extends Auth_Controller
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'MyLv']);
}
public function Info($studien_semester,$lvid)
{
$this->load->view('Cis/LvInfo',['lvid'=> $lvid, 'studien_semester' => $studien_semester]);
}
}
@@ -28,7 +28,7 @@ class Studentenverwaltung extends Auth_Controller
'basis/prestudentstatus' => $this->permissionlib->isBerechtigt('basis/prestudentstatus'),
'assistenz_stgs' => $this->permissionlib->getSTG_isEntitledFor('assistenz'),
'admin' => $this->permissionlib->isBerechtigt('admin'),
'assistenz_schreibrechte' => $this->permissionlib->isBerechtigt('assistenz','suid'),
'assistenz_schreibrechte' => $this->permissionlib->isBerechtigt('assistenz', 'suid'),
'student/keine_studstatuspruefung' => $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung'),
'lehre/reihungstestAufsicht' => $this->permissionlib->isBerechtigt('lehre/reihungstestAufsicht'),
'system/change_outputformat' => $this->permissionlib->getOE_isEntitledFor('system/change_outputformat'),
@@ -43,3 +43,5 @@ class Studentenverwaltung extends Auth_Controller
]);
}
}
@@ -0,0 +1,30 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Vertragsverwaltung extends Auth_Controller
{
public function __construct()
{
$permissions = [];
$router = load_class('Router');
$permissions[$router->method] = ['vertrag/mitarbeiter:r'];
#$permissions[$router->method] = ['admin:rw'];
parent::__construct($permissions);
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
}
/**
* @return void
*/
public function _remap()
{
$this->load->view('Vertragsverwaltung', [
'permissions' => [
'vertragsverwaltung_schreibrechte' => $this->permissionlib->isBerechtigt('vertrag/mitarbeiter', 'suid')
]
]);
}
}
@@ -89,13 +89,15 @@ class Abgabe extends FHCAPI_Controller
$abgabetypenBetreuer = $this->config->item('ALLOWED_ABGABETYPEN_BETREUER');
$ASSISTENZ_SAMMELMAIL_BUTTON_STUDENT = $this->config->item('ASSISTENZ_SAMMELMAIL_BUTTON_STUDENT');
$ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER = $this->config->item('ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER');
$BETREUER_SAMMELMAIL_BUTTON_STUDENT = $this->config->item('BETREUER_SAMMELMAIL_BUTTON_STUDENT');
$ret = array(
'old_abgabe_beurteilung_link' => $old_abgabe_beurteilung_link,
'turnitin_link' => $turnitin_link,
'abgabetypenBetreuer' => $abgabetypenBetreuer,
'ASSISTENZ_SAMMELMAIL_BUTTON_STUDENT' => $ASSISTENZ_SAMMELMAIL_BUTTON_STUDENT,
'ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER' => $ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER
'ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER' => $ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER,
'BETREUER_SAMMELMAIL_BUTTON_STUDENT' => $BETREUER_SAMMELMAIL_BUTTON_STUDENT,
);
$this->terminateWithSuccess($ret);
@@ -373,6 +375,8 @@ class Abgabe extends FHCAPI_Controller
$this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general');
}
$this->checkPaabgabeDeadline($paabgabe_id);
$this->checkProjektarbeitForFinishedStatus($projektarbeit_id);
$zugeordnet = $this->checkZuordnung($projektarbeit_id, getAuthUID());
@@ -444,6 +448,36 @@ class Abgabe extends FHCAPI_Controller
}
}
// validate paabgabe deadline against servertime just in case a student spoofs their local clock and thus
// unlocks the upload ui
private function checkPaabgabeDeadline($paabgabe_id) {
$this->load->model('education/Paabgabe_model', 'PaabgabeModel');
$result = $this->PaabgabeModel->load($paabgabe_id);
$paabgabeArr = $this->getDataOrTerminateWithError($result, 'general');
if (count($paabgabeArr) > 0) {
$paabgabe = $paabgabeArr[0];
} else {
$this->terminateWithError($this->p->t('abgabetool', 'c4projektabgabeNichtGefunden'), 'general');
}
// in that case any submission date is fine
if($paabgabe->fixtermin === false) return;
$tz = new DateTimeZone('Europe/Berlin');
$now = new DateTimeImmutable('now', $tz);
$deadline = DateTimeImmutable::createFromFormat(
'Y-m-d H:i:s',
$paabgabe->datum . ' 23:59:59',
$tz
);
if($now >= $deadline) {
$this->terminateWithError($this->p->t('abgabetool', 'c4deadlineExceeded'));
}
}
/**
* tabulator tabledata fetch for abgabetool/mitarbeiter
@@ -473,6 +507,16 @@ class Abgabe extends FHCAPI_Controller
$projektarbeiten = $this->ProjektarbeitModel->getMitarbeiterProjektarbeiten(getAuthUID(), $showAllBool);
$mapFunc = function($projektarbeit) {
return $projektarbeit->projektarbeit_id;
};
$projektarbeiten_ids = array_map($mapFunc, $projektarbeiten->retval);
if(count($projektarbeiten_ids) > 0) {
$ret = $this->ProjektarbeitModel->getProjektarbeitenAbgabetermine($projektarbeiten_ids);
$projektabgaben = $this->getDataOrTerminateWithError($ret, 'general');
}
forEach($projektarbeiten->retval as $pa) {
$result = $this->ProjektarbeitModel->getProjektbetreuerAnrede($pa->betreuer_person_id);
@@ -489,6 +533,20 @@ class Abgabe extends FHCAPI_Controller
Events::trigger('projektbeurteilung_formular_link', $pa->betreuerart_kurzbz, APP_ROOT, $pa->projektarbeit_id, $pa->student_uid, $returnFunc);
$pa->beurteilungLinkNew = $newLink;
$pa->beurteilungLinkOld = $oldLink;
// has previously been retrieved via getStudentProjektabgaben but is fetched in advance to avoid having to reload abgaben
$projektarbeitIsCurrent = false;
$returnFunc = function ($result) use (&$projektarbeitIsCurrent) {
$projektarbeitIsCurrent = $result;
};
Events::trigger('projektarbeit_is_current', $pa->projektarbeit_id, $returnFunc);
$pa->isCurrent = $projektarbeitIsCurrent;
$filterFunc = function($projektabgabe) use ($pa) {
return $projektabgabe->projektarbeit_id == $pa->projektarbeit_id;
};
$pa->abgabetermine = array_values(array_filter($projektabgaben, $filterFunc));
}
@@ -544,7 +602,18 @@ class Abgabe extends FHCAPI_Controller
'insertamum' => date('Y-m-d H:i:s')
)
);
$this->logLib->logInfoDB(array('paabgabe created',$result, getAuthUID(), getAuthPersonId()));
$this->logLib->logInfoDB(array('paabgabe created',array(
'projektarbeit_id' => $projektarbeit_id,
'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz,
'fixtermin' => $fixtermin,
'datum' => $datum,
'kurzbz' => $kurzbz,
'note' => $note,
'beurteilungsnotiz' => $beurteilungsnotiz,
'upload_allowed' => $upload_allowed,
'insertvon' => getAuthUID(),
'insertamum' => date('Y-m-d H:i:s')
), getAuthUID(), getAuthPersonId()));
} else {
// load existing entry of paabgabe and check if note has changed to negativ, to avoid sending when
// only notiz has changed.
@@ -718,7 +787,16 @@ class Abgabe extends FHCAPI_Controller
$abgaben[]= getData($this->PaabgabeModel->load($dataAbgabe))[0];
}
$this->logLib->logInfoDB(array('serientermin angelegt',$res, getAuthUID(), getAuthPersonId()));
$this->logLib->logInfoDB(array('serientermin angelegt',array(
'projektarbeit_id' => $projektarbeit_id,
'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz,
'fixtermin' => $fixtermin,
'datum' => $datum,
'kurzbz' => $kurzbz,
'upload_allowed' => $upload_allowed,
'insertvon' => getAuthUID(),
'insertamum' => date('Y-m-d H:i:s')
), getAuthUID(), getAuthPersonId()));
$this->terminateWithSuccess($abgaben);
}
@@ -769,9 +847,10 @@ class Abgabe extends FHCAPI_Controller
private function getProjektbetreuerEmailByProjektarbeitID($projektarbeit_id) {
$this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel');
$result = $this->ProjektarbeitModel->getProjektbetreuerEmail($projektarbeit_id);
$email = $this->getDataOrTerminateWithError($result, 'general');
return $email[0]->uid ? $email[0]->uid.'@'.DOMAIN : $email[0]->private_email;
if(count($result->retval) > 0) {
$email = getData($result);
return $email[0]->uid ? $email[0]->uid.'@'.DOMAIN : $email[0]->private_email;
} else return '';
}
@@ -1167,7 +1246,7 @@ class Abgabe extends FHCAPI_Controller
$email = $this->getProjektbetreuerEmailByProjektarbeitID($projektarbeit_id);
if(!$email) $this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailBegutachter'), 'general');
if(!$email) $this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailBegutachterv2'), 'general');
$mailres = sendSanchoMail(
'ParbeitsbeurteilungEndupload',
@@ -1180,7 +1259,7 @@ class Abgabe extends FHCAPI_Controller
if(!$mailres)
{
$this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailBegutachter'), 'general');
$this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailBegutachterv2'), 'general');
}
// 2. Begutachter mail, wenn Endabgabe, mit Token wenn extern
@@ -1200,14 +1279,14 @@ class Abgabe extends FHCAPI_Controller
if (!$tokenGenRes)
{
$this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailZweitBegutachter'), 'general');
$this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailZweitBegutachterv2'), 'general');
}
$begutachterMitTokenRetval = getData($this->ProjektbetreuerModel->getZweitbegutachterWithToken($bperson_id, $projektarbeit_id, $studentUser->uid, $begutachter->person_id));
if (!$begutachterMitTokenRetval && count($begutachterMitTokenRetval) <= 0)
{
$this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailZweitBegutachter'), 'general');
$this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailZweitBegutachterv2'), 'general');
}
$begutachterMitToken = $begutachterMitTokenRetval[0];
@@ -1241,7 +1320,7 @@ class Abgabe extends FHCAPI_Controller
if (!$mailres)
{
$this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailBegutachter'), 'general');
$this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailBegutachterv2'), 'general');
}
}
@@ -208,7 +208,6 @@ class Documents extends FHCAPI_Controller
$this->load->model('system/Vorlage_model', 'VorlageModel');
$result = $this->VorlageModel->load($xsl);
$this->addMeta("ress", $result);
$vorlage = current($this->getDataOrTerminateWithError($result));
if (!$vorlage)
show_404();
@@ -221,7 +220,7 @@ class Documents extends FHCAPI_Controller
'gedruckt' => true,
'insertamum' => date('c'),
'insertvon' => getAuthUID(),
'uid' => $this->input->post_get('uid') ?: '',
'uid' => $this->input->post_get('uid') ?: null,
'archiv' => true,
'signiert' => !!$sign_user,
'stud_selfservice' => $vorlage->stud_selfservice
@@ -251,6 +250,9 @@ class Documents extends FHCAPI_Controller
'studiensemester_kurzbz' => $ss,
'student_uid' => $akteData['uid']
]);
if (!hasData($result)) $this->terminateWithError($this->p->t("stv", "error_noLehrverbandAssigned"));
$res = current($this->getDataOrTerminateWithError($result));
$studiengang_kz = $res->studiengang_kz;
@@ -332,6 +334,7 @@ class Documents extends FHCAPI_Controller
if ($prestudent_id) {
$this->load->model('crm/prestudent_model', 'PrestudentModel');
$this->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz', 'LEFT');
$this->PrestudentModel->addSelect('tbl_prestudent.*, UPPER(typ || kurzbz) AS kuerzel');
$result = $this->PrestudentModel->load($prestudent_id);
$prestudent = current($this->getDataOrTerminateWithError($result));
@@ -0,0 +1,121 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller operates between (interface) the JS (GUI) and the back-end
* Provides data to the ajax get calls about addresses
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Board extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'list' => 'dashboard/admin:r',
'create' => 'dashboard/admin:rw',
'update' => 'dashboard/admin:rw',
'delete' => 'dashboard/admin:rw'
]);
// Models
$this->load->model('dashboard/Dashboard_model', 'DashboardModel');
}
public function list()
{
$result = $this->DashboardModel->load();
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($result);
}
public function create()
{
$dashboard_kurzbz = $this->input->post('dashboard_kurzbz');
$result = $this->DashboardModel->insert([
'dashboard_kurzbz' => $dashboard_kurzbz
]);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function update()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('dashboard_id', 'Dashboard ID', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$dashboard_id = $this->input->post('dashboard_id');
$dashboard_kurzbz = $this->input->post('dashboard_kurzbz');
$beschreibung = $this->input->post('beschreibung');
$result = $this->DashboardModel->update([
'dashboard_id' => $dashboard_id
], [
'dashboard_kurzbz' => $dashboard_kurzbz,
'beschreibung' => $beschreibung
]);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($result);
}
public function delete()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('dashboard_id', 'Dashboard ID', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$dashboard_id = $this->input->post('dashboard_id');
//delete all presets
$this->load->model('dashboard/Dashboard_Preset_model', 'DashboardPresetModel');
$result = $this->DashboardPresetModel->delete([
'dashboard_id' => $dashboard_id
]);
$this->getDataOrTerminateWithError($result);
//delete all widgets
$this->load->model('dashboard/Dashboard_Widget_model', 'DashboardWidgetModel');
$result = $this->DashboardWidgetModel->delete([
'dashboard_id' => $dashboard_id
]);
$this->getDataOrTerminateWithError($result);
$result = $this->DashboardModel->delete($dashboard_id);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($result);
}
}
@@ -0,0 +1,200 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller operates between (interface) the JS (GUI) and the back-end
* Provides data to the ajax get calls about addresses
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Preset extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'list' => 'dashboard/admin:r',
'getBatch' => 'dashboard/admin:r',
'addWidget' => 'dashboard/admin:rw',
'removeWidget' => 'dashboard/admin:rw'
]);
// Load language phrases
$this->loadPhrases([
'ui'
]);
// Libraries
$this->load->library('dashboard/DashboardLib');
// Models
$this->load->model('ressource/Funktion_model', 'FunktionModel');
}
public function list($dashboard_kurzbz)
{
$sql = "
WITH
dashboard_presets AS (
SELECT
*
FROM
dashboard.tbl_dashboard_preset dp
JOIN
dashboard.tbl_dashboard d ON d.dashboard_id = dp.dashboard_id
WHERE
d.dashboard_kurzbz = {$this->db->escape($dashboard_kurzbz)}
),
general AS (
SELECT
'general' AS funktion_kurzbz,
'Allgemein' AS beschreibung
)
(
SELECT
f.funktion_kurzbz,
f.beschreibung,
COUNT(p.preset_id) AS has_preset
FROM
general f
LEFT JOIN
dashboard_presets p ON p.funktion_kurzbz IS NULL
GROUP BY
f.funktion_kurzbz, f.beschreibung
)
UNION ALL
(
SELECT
f.funktion_kurzbz,
f.beschreibung,
COUNT(p.preset_id) AS has_preset
FROM
public.tbl_funktion f
LEFT JOIN
dashboard_presets p ON p.funktion_kurzbz = f.funktion_kurzbz
GROUP BY
f.funktion_kurzbz, f.beschreibung
ORDER BY
f.beschreibung ASC
)
";
$result = $this->FunktionModel->execReadOnlyQuery($sql);
$funktionen = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($funktionen);
}
public function getBatch()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('db', 'Dashboard', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$db = $this->input->post('db');
$funktionen = $this->input->post('funktionen') ?: [];
$result = [];
foreach ($funktionen as $funktion) {
$conf = $this->dashboardlib->getPreset($db, $funktion);
if ($conf) {
$preset = json_decode($conf->preset, true);
if (!isset($preset[$funktion]) || !isset($preset[$funktion]['widgets']))
$result[$funktion] = [];
else
$result[$funktion] = $preset[$funktion]['widgets'];
} else {
$result[$funktion] = [];
}
}
return $this->terminateWithSuccess($result);
}
public function addWidget()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('dashboard', 'Dashboard', 'required');
$this->form_validation->set_rules('funktion_kurzbz', 'Funktion', 'required');
$this->form_validation->set_rules('widget[widget]', 'Widget', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$dashboard_kurzbz = $this->input->post('dashboard');
$funktion_kurzbz = $this->input->post('funktion_kurzbz');
$widget = $this->input->post('widget');
if (!isset($widget['widgetid']))
$widget['widgetid'] = $this->dashboardlib->generateWidgetId($dashboard_kurzbz);
$preset = $this->dashboardlib->getPresetOrCreateEmptyPreset($dashboard_kurzbz, $funktion_kurzbz);
$preset_decoded = json_decode($preset->preset, true);
$this->dashboardlib->addWidgetsToWidgets($preset_decoded, $dashboard_kurzbz, $funktion_kurzbz, [$widget]);
$preset->preset = json_encode($preset_decoded);
$result = $this->dashboardlib->insertOrUpdatePreset($preset);
$this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($widget['widgetid']);
}
public function removeWidget()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('db', 'Dashboard', 'required');
$this->form_validation->set_rules('funktion_kurzbz', 'Funktion', 'required');
$this->form_validation->set_rules('widgetid', 'Widget', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$dashboard_kurzbz = $this->input->post('db');
$funktion_kurzbz = $this->input->post('funktion_kurzbz');
$widgetid = $this->input->post('widgetid');
$preset = $this->dashboardlib->getPreset($dashboard_kurzbz, $funktion_kurzbz);
if (!$preset)
show_404();
$preset_decoded = json_decode($preset->preset, true);
if (!$this->dashboardlib->removeWidgetFromWidgets($preset_decoded, $funktion_kurzbz, $widgetid))
show_404();
$preset->preset = json_encode($preset_decoded);
$result = $this->dashboardlib->insertOrUpdatePreset($preset);
$this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(array('msg' => $this->p->t('dashboard', 'success_savePreset')));
}
}
@@ -0,0 +1,159 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller operates between (interface) the JS (GUI) and the back-end
* Provides data to the ajax get calls about the users dashboard
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class User extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'get' => 'dashboard/benutzer:r',
'addWidget' => 'dashboard/benutzer:rw',
'removeWidget' => 'dashboard/benutzer:rw'
]);
// Libraries
$this->load->library('dashboard/DashboardLib');
// Models
$this->load->model('ressource/Funktion_model', 'FunktionModel');
}
public function get($dashboard_kurzbz)
{
$dashboard = $this->dashboardlib->getDashboardByKurzbz($dashboard_kurzbz);
if (!$dashboard)
show_404();
$uid = $this->authlib->getAuthObj()->username;
/*$mergedconfig = $this->dashboardlib->getMergedConfig($dashboard->dashboard_id, $uid);
$this->terminateWithSuccess([
'general' => call_user_func_array(
'array_merge_recursive',
$mergedconfig
)
]);*/
$defaultconfig = $this->dashboardlib->getDefaultConfig($dashboard->dashboard_id);
$userconfig = $this->dashboardlib->getUserConfig($dashboard->dashboard_id, $uid);
$defaultconfig_squashed = $defaultconfig ? call_user_func_array('array_replace_recursive', $defaultconfig) : [];
$userconfig_squashed = $userconfig ? call_user_func_array('array_replace_recursive', $userconfig) : [];
$mergedconfig = array_replace_recursive($defaultconfig_squashed, $userconfig_squashed);
$this->terminateWithSuccess([
DashboardLib::SECTION_IF_FUNKTION_KURZBZ_IS_NULL => $mergedconfig
]);
}
public function addWidget()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('dashboard', 'Dashboard', 'required');
$this->form_validation->set_rules('widget[widget]', 'Widget', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$widget = $this->input->post('widget');
$dashboard_kurzbz = $this->input->post('dashboard');
$uid = $this->authlib->getAuthObj()->username;
if (!isset($widget['widgetid']))
$widget['widgetid'] = $this->dashboardlib->generateWidgetId($dashboard_kurzbz);
$override = $this->dashboardlib->getOverrideOrCreateEmptyOverride($dashboard_kurzbz, $uid);
$override_decoded = json_decode($override->override, true);
if (!isset($override_decoded['general']) || !is_array($override_decoded['general']))
$override_decoded['general'] = [];
if (!isset($override_decoded['general']['widgets']))
$override_decoded['general']['widgets'] = [];
$override_decoded['general']['widgets'][$widget['widgetid']] = $widget;
// NOTE(chris): remove doubles in other funktionen
foreach ($override_decoded as $funktion => $array) {
if ($funktion == 'general')
continue;
if (isset($array['widgets']) && isset($array['widgets'][$widget['widgetid']]))
unset($override_decoded[$funktion]['widgets'][$widget['widgetid']]);
}
$override->override = json_encode($override_decoded);
$result = $this->dashboardlib->insertOrUpdateOverride($override);
$this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($widget['widgetid']);
}
public function removeWidget()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('dashboard', 'Dashboard', 'required');
$this->form_validation->set_rules('widget', 'Widget', 'required');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$widget_id = $this->input->post('widget');
$dashboard_kurzbz = $this->input->post('dashboard');
$uid = $this->authlib->getAuthObj()->username;
$override = $this->dashboardlib->getOverride($dashboard_kurzbz, $uid);
if (!$override)
show_404();
$override_decoded = json_decode($override->override, true);
foreach (array_keys($override_decoded) as $k) {
if (!isset($override_decoded[$k]["widgets"])) {
unset($override_decoded[$k]);
continue;
}
if (isset($override_decoded[$k]["widgets"][$widget_id])) {
unset($override_decoded[$k]["widgets"][$widget_id]);
}
if (!$override_decoded[$k]["widgets"]) {
unset($override_decoded[$k]);
}
}
$override->override = json_encode($override_decoded);
$result = $this->dashboardlib->insertOrUpdateOverride($override);
$this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess();
}
}
@@ -0,0 +1,137 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller operates between (interface) the JS (GUI) and the back-end
* Provides data to the ajax get calls about the users dashboard
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Widget extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'get' => ['dashboard/benutzer:r', 'dashboard/admin:r'],
'list' => 'dashboard/admin:r',
'listAllowed' => ['dashboard/benutzer:rw', 'dashboard/admin:r'],
'setAllowed' => 'dashboard/admin:rw'
]);
// Libraries
$this->load->library('dashboard/DashboardLib');
// Models
$this->load->model('dashboard/Widget_model', 'WidgetModel');
}
public function get($id)
{
$result = $this->WidgetModel->load($id);
$widget = $this->getDataOrTerminateWithError($result);
if (!$widget)
return $this->terminateWithSuccess([
"widget_id" => 0,
"widget_kurzbz" => "notfound",
"arguments" => [
"className" => 'alert-danger',
"title" => 'Widget Not Found',
"msg" => 'The widget with the id ' . $id . ' could not be found'
],
"setup" => [
"name" => 'Widget Not Found',
"file" => absoluteJsImportUrl('public/js/components/DashboardWidget/Default.js'),
"width" => 1,
"height" => 1
]
]);
$widget = current($widget);
$widget->arguments = json_decode($widget->arguments);
$tmpsetup = json_decode($widget->setup);
$tmpsetup->file = absoluteJsImportUrl($tmpsetup->file);
$widget->setup = $tmpsetup;
$this->terminateWithSuccess($widget);
}
public function list($dashboard)
{
$result = $this->WidgetModel->getWithAllowedForDashboard($dashboard);
$widgets = $this->getDataOrTerminateWithError($result);
$widgets = array_map(function ($widget) {
$widget->arguments = json_decode($widget->arguments);
$tmpsetup = json_decode($widget->setup);
$tmpsetup->file = absoluteJsImportUrl($tmpsetup->file);
$widget->setup = $tmpsetup;
return $widget;
}, $widgets);
$this->terminateWithSuccess($widgets);
}
public function listAllowed($dashboard)
{
$result = $this->WidgetModel->getForDashboard($dashboard);
$widgets = $this->getDataOrTerminateWithError($result);
$widgets = array_map(function ($widget) {
$widget->arguments = json_decode($widget->arguments);
$tmpsetup = json_decode($widget->setup);
$tmpsetup->file = absoluteJsImportUrl($tmpsetup->file);
$widget->setup = $tmpsetup;
return $widget;
}, $widgets);
$this->terminateWithSuccess($widgets);
}
public function setAllowed()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('dashboard_id', 'Dashboard', 'required');
$this->form_validation->set_rules('widget_id', 'Widget', 'required');
$this->form_validation->set_rules('allowed', 'Allowed', 'is_bool');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
$data = [
'dashboard_id' => $this->input->post('dashboard_id'),
'widget_id' => $this->input->post('widget_id')
];
$this->load->model('dashboard/Dashboard_Widget_model', 'DashboardWidgetModel');
if ($this->input->post('allowed'))
$result = $this->DashboardWidgetModel->insert($data);
else
$result = $this->DashboardWidgetModel->delete($data);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
}
@@ -0,0 +1,53 @@
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class Detailheader extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'getHeader' => ['vertrag/mitarbeiter:r'],
'getPersonAbteilung' => ['vertrag/mitarbeiter:r'],
'getLeitungOrg' => ['vertrag/mitarbeiter:r'],
]);
}
public function getHeader($person_id)
{
$this->load->model('ressource/Mitarbeiter_model', 'Mitarbeitermodel');
$result = $this->Mitarbeitermodel->getHeader($person_id);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(current($data));
}
public function getPersonAbteilung($mitarbeiter_uid)
{
$this->load->model('ressource/Mitarbeiter_model', 'Mitarbeitermodel');
$result = $this->Mitarbeitermodel->getPersonAbteilung($mitarbeiter_uid);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(current($data));
}
public function getLeitungOrg($oekurzbz)
{
$this->load->model('ressource/Mitarbeiter_model', 'Mitarbeitermodel');
$result = $this->Mitarbeitermodel->getLeitungOrg($oekurzbz);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(current($data));
}
}
@@ -0,0 +1,237 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class Foto extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'uploadFoto' => ['admin:r', 'assistenz:r'],
'deleteFoto' => ['admin:r', 'assistenz:r'],
]);
//Load Models and Libraries
$this->load->model('person/Person_model', 'PersonModel');
$this->load->model("crm/Akte_model", "AkteModel");
$this->load->model('person/Fotostatusperson_model', 'FotostatusPersonModel');
$this->loadPhrases([
'ui',
'header'
]);
}
public function uploadFoto($person_id)
{
if(!$person_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person_id']), self::ERROR_TYPE_GENERAL);
}
$data = json_decode(file_get_contents("php://input"), true);
if (!empty($data['image']))
{
$base64 = $data['image'];
$resizedImage1 = $this->_resize($base64, 827, 1063);
if (is_null($resizedImage1))
return $this->terminateWithError($this->p->t('header', 'error_fotoupload'), self::ERROR_TYPE_GENERAL);
$akte = $this->AkteModel->loadWhere(array('person_id' => $person_id, 'dokument_kurzbz' => 'Lichtbil'));
$akteUpdateData = array(
'dokument_kurzbz' => 'Lichtbil',
'person_id' => $person_id,
'inhalt' => $resizedImage1,
'mimetype' => 'image/jpg',
'erstelltam' => date('c'),
'gedruckt' => false,
'titel' => 'Lichtbild_' . $person_id . '.jpg',
'bezeichnung' => 'Lichtbild gross',
'insertamum' => date('c'),
'insertvon' => getAuthUID(),
);
if (hasData($akte)) {
$akte_id = getData($akte)[0]->akte_id;
$akteUpdateData['updateamum'] = date('c');
$akteUpdateData['updatevon'] = getAuthUID();
$akteResult = $this->AkteModel->update(array('akte_id' => $akte_id), $akteUpdateData);
} else {
$akteResult = $this->AkteModel->insert($akteUpdateData);
}
if (isError($akteResult)) {
return $this->terminateWithError(getError($akteResult), self::ERROR_TYPE_GENERAL);
}
$resizedImage2 = $this->_resize($base64, 101, 130);
if (is_null($resizedImage2))
return $this->terminateWithError($this->p->t('header', 'error_fotoupload'), self::ERROR_TYPE_GENERAL);
$result = $this->_updateFoto($person_id, $resizedImage2);
if (!isError($result)) {
$this->FotostatusPersonModel->insert(array(
'person_id' => $person_id,
'fotostatus_kurzbz' => 'hochgeladen',
'datum' => date('Y-m-d'),
'updateamum' => date('c'),
'updatevon' => getAuthUID(),
'insertamum' => date('c'),
'insertvon' => getAuthUID(),
));
return $this->terminateWithSuccess($base64);
}
}
else
{
$this->terminateWithError($this->p->t('header', 'error_noPhoto'), self::ERROR_TYPE_GENERAL);
}
}
public function deleteFoto($person_id)
{
if(!$person_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person_id']), self::ERROR_TYPE_GENERAL);
}
$result = $this->_deleteFoto($person_id);
if (isError($result))
{
return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
return $this->terminateWithSuccess($result);
}
private function _resize($imageData, $maxwidth, $maxheight, $quality = 90)
{
$meta = getimagesize($imageData);
if (!$meta)
{
return null;
}
$src_width = $meta[0];
$src_height = $meta[1];
$mime = $meta['mime'];
switch ($mime) {
case 'image/jpeg':
case 'image/jpg':
$imagecreated = imagecreatefromjpeg($imageData);
break;
case 'image/png':
$imagecreated = imagecreatefrompng($imageData);
break;
case 'image/gif':
$imagecreated = imagecreatefromgif($imageData);
break;
default:
return null;
}
if (!$imagecreated)
{
return null;
}
$src_aspect_ratio = $src_width / $src_height;
$thu_aspect_ratio = $maxwidth / $maxheight;
if ($src_width <= $maxwidth && $src_height <= $maxheight)
{
$thu_width = $src_width;
$thu_height = $src_height;
}
elseif ($thu_aspect_ratio > $src_aspect_ratio)
{
$thu_width = (int) ($maxheight * $src_aspect_ratio);
$thu_height = $maxheight;
}
else
{
$thu_width = $maxwidth;
$thu_height = (int) ($maxwidth / $src_aspect_ratio);
}
$imageScaled = imagecreatetruecolor($thu_width, $thu_height);
if ($mime === 'image/png')
{
$background = imagecolorallocate($imageScaled , 0, 0, 0);
imagecolortransparent($imageScaled, $background);
imagealphablending($imageScaled, false);
imagesavealpha($imageScaled, true);
}
imagecopyresampled($imageScaled, $imagecreated, 0, 0, 0, 0, $thu_width, $thu_height, $src_width, $src_height);
if ($mime === "image/gif")
{
$background = imagecolorallocate($imageScaled, 0, 0, 0);
imagecolortransparent($imageScaled, $background);
}
if (!empty($imageScaled))
{
ob_start();
if ($mime == 'image/png')
imagepng($imageScaled, NULL);
else if ($mime === 'image/gif')
imagegif($imageScaled, NULL);
else
imagejpeg($imageScaled, NULL, $quality);
$resizedImageData = ob_get_contents();
ob_end_clean();
@imagedestroy($imagecreated);
@imagedestroy($imageScaled);
if (!empty($resizedImageData))
{
return base64_encode($resizedImageData);
}
return null;
}
return null;
}
private function _updateFoto($person_id, $foto)
{
$personJson['foto'] = $foto;
$result = $this->PersonModel->update($person_id, $personJson);
if (isError($result))
{
return error($result->msg, EXIT_ERROR);
}
return $result;
}
private function _deleteFoto($person_id)
{
$personJson['foto'] = null;
$result = $this->PersonModel->update($person_id, $personJson);
if (isError($result))
{
return error($result->msg, EXIT_ERROR);
}
return $result;
}
}
@@ -42,14 +42,22 @@ class Messages extends FHCAPI_Controller
]);
}
public function getMessages($id, $type_id, $size, $page)
public function getMessages($id, $type_id, $size=null, $page=null)
{
if($type_id != 'person_id'){
$id = $this->_getPersonId($id, $type_id);
}
$offset = $size * ($page - 1);
$limit = $size;
if(!(is_null($size) && is_null($page)))
{
$offset = $size * ($page - 1);
$limit = $size;
}
else
{
$offset = null;
$limit = null;
}
$result = $this->MessageModel->getMessagesForTable($id, $offset, $limit);
@@ -0,0 +1,44 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class NotizAnrechnung extends Notiz_Controller
{
public function __construct()
{
parent::__construct([
'isBerechtigt' => ['admin:r', 'assistenz:r'],
]);
//Load Models
$this->load->model('person/Notiz_model', 'NotizModel');
$this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel');
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
// Load language phrases
$this->loadPhrases([
'ui'
]);
}
public function isBerechtigt($id, $typeId)
{
if($typeId != "anrechnung_id")
{
$this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL);
}
//TODO define permission
if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid'))
{
$result = $this->p->t('lehre','error_keineSchreibrechte');
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess("berechtigt in überschreibender Funktion");
}
}
@@ -0,0 +1,43 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class NotizBestellung extends Notiz_Controller
{
public function __construct()
{
parent::__construct([
'isBerechtigt' => ['admin:r', 'assistenz:r'],
]);
//Load Models
$this->load->model('person/Notiz_model', 'NotizModel');
$this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel');
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
// Load language phrases
$this->loadPhrases([
'ui'
]);
}
public function isBerechtigt($id, $typeId)
{
if($typeId != "bestellung_id")
{
$this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL);
}
//TODO define permission
if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid'))
{
$result = $this->p->t('lehre','error_keineSchreibrechte');
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess("berechtigt in überschreibender Funktion");
}
}
@@ -17,5 +17,106 @@ class NotizLehreinheit extends Notiz_Controller
'getMitarbeiter' => ['admin:r', 'assistenz:r'],
'isBerechtigt' => ['admin:r', 'assistenz:r'],
]);
//Load Models
$this->load->model('person/Notiz_model', 'NotizModel');
$this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel');
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
//Permission checks for allowed Oes
$allowedOes = $this->permissionlib->getOE_isEntitledFor('assistenz') ?: [];
if ($this->router->method == 'addNewNotiz')
{
$json = $this->input->post('data');
$post_data = json_decode($json, true);
$lehreinheit_id = $post_data['id'];
if(!$lehreinheit_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Lehreinheit ID']), self::ERROR_TYPE_GENERAL);
}
$this->_checkAllowedOesFromLehreinheit($lehreinheit_id, $allowedOes);
}
if ($this->router->method == 'updateNotiz')
{
$json = $this->input->post('data');
$post_data = json_decode($json, true);
$notiz_id = $post_data['notiz_id'];
if(!$notiz_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Notiz ID']), self::ERROR_TYPE_GENERAL);
}
//get lehreinheit_id
$result = $this->NotizzuordnungModel->loadWhere(['notiz_id' => $notiz_id]);
$data = $this->getDataOrTerminateWithError($result);
$lehreinheit_id = current($data)->lehreinheit_id;
if(!$lehreinheit_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Lehreinheit ID']), self::ERROR_TYPE_GENERAL);
}
$this->_checkAllowedOesFromLehreinheit($lehreinheit_id, $allowedOes);
}
if ($this->router->method == 'deleteNotiz')
{
$notiz_id = $this->input->post('notiz_id');
$lehreinheit_id = $this->input->post('id');
if(!$notiz_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Notiz ID']), self::ERROR_TYPE_GENERAL);
}
if(!$lehreinheit_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Lehreinheit ID']), self::ERROR_TYPE_GENERAL);
}
$this->_checkAllowedOesFromLehreinheit($lehreinheit_id, $allowedOes);
}
// Load language phrases
$this->loadPhrases([
'ui'
]);
}
}
private function _checkAllowedOesFromLehreinheit($lehreinheit_id, $allowedOes)
{
//get oe from lehreinheit
$result = $this->LehreinheitModel->getOes($lehreinheit_id);
$data = $this->getDataOrTerminateWithError($result);
$oes = current($data);
if (!in_array($oes, $allowedOes))
{
return $this->terminateWithError($this->p->t('ui', 'error_keineBerechtigungStg') . " " . $oes, self::ERROR_TYPE_GENERAL);
}
}
public function isBerechtigt($id, $typeId)
{
if($typeId != "lehreinheit_id")
{
$this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL);
}
if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid'))
{
$result = $this->p->t('lehre','error_keineSchreibrechte');
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess("berechtigt in überschreibender Funktion");
}
}
@@ -0,0 +1,44 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class NotizMitarbeiter extends Notiz_Controller
{
public function __construct()
{
parent::__construct([
'isBerechtigt' => ['admin:r', 'assistenz:r'],
]);
//Load Models
$this->load->model('person/Notiz_model', 'NotizModel');
$this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel');
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
// Load language phrases
$this->loadPhrases([
'ui'
]);
}
public function isBerechtigt($id, $typeId)
{
if($typeId != "mitarbeiter_uid")
{
$this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL);
}
//TODO define permission
if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid'))
{
$result = $this->p->t('lehre','error_keineSchreibrechte');
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess("berechtigt in überschreibender Funktion");
}
}
@@ -20,33 +20,100 @@ class NotizPerson extends Notiz_Controller
'isBerechtigt' => ['admin:r', 'assistenz:r'],
'getCountNotes' => ['admin:r', 'assistenz:r'],
]);
//Load Models
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$this->load->model('crm/Student_model', 'StudentModel');
$this->load->model('crm/Prestudent_model', 'PrestudentModel');
//Permission checks for allowed Oes
if ($this->router->method == 'addNewNotiz')
{
$json = $this->input->post('data');
$post_data = json_decode($json, true);
$person_id = $post_data['id'];
$allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: [];
if(!$person_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID']), self::ERROR_TYPE_GENERAL);
}
$this->_checkIfBerechtigungForOnePrestudentExists($person_id, $allowedStgs);
}
if ( $this->router->method == 'updateNotiz')
{
$json = $this->input->post('data');
$post_data = json_decode($json, true);
$notiz_id = $post_data['notiz_id'];
if(!$notiz_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Notiz ID']), self::ERROR_TYPE_GENERAL);
}
//get person_id
$result = $this->NotizzuordnungModel->loadWhere(['notiz_id' => $notiz_id]);
$data = $this->getDataOrTerminateWithError($result);
$person_id = current($data)->person_id;
$allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: [];
$this->_checkIfBerechtigungForOnePrestudentExists($person_id, $allowedStgs);
}
if ($this->router->method == 'deleteNotiz' )
{
$notiz_id = $this->input->post('notiz_id');
$person_id = $this->input->post('id');
if(!$notiz_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Notiz ID']), self::ERROR_TYPE_GENERAL);
}
if(!$person_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'person ID']), self::ERROR_TYPE_GENERAL);
}
$allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: [];
$this->_checkIfBerechtigungForOnePrestudentExists($person_id, $allowedStgs);
}
}
public function isBerechtigt($id, $typeId)
{
if($typeId != "person_id")
{
return $this->terminateWithError($this->p->t('ui', 'error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL);
$this->terminateWithError($this->p->t('ui', 'error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL);
}
//TODO define permission
if (!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid'))
{
$result = $this->p->t('lehre', 'error_keineSchreibrechte');
return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
return $this->outputJsonSuccess(true);
$this->terminateWithSuccess("berechtigt in überschreibender Funktion");
}
public function loadDokumente()
//stv: if person has permission of one studiengang of person -> permission to add/update/delete Note
private function _checkIfBerechtigungForOnePrestudentExists($person_id, $allowedStgs)
{
$notiz_id = $this->input->post('notiz_id');
$result = $this->PrestudentModel->loadWhere(['person_id' => $person_id]);
$data = $this->getDataOrTerminateWithError($result);
// TODO(chris): make CI variant of endpoint
$this->NotizModel->addSelect($this->NotizModel->escape(base_url('content/notizdokdownload.php?id=')) . ' || campus.tbl_dms_version.dms_id AS preview');
return parent::loadDokumente();
$checkarray = [];
foreach ($data as $item)
{
if(in_array($item->studiengang_kz, $allowedStgs))
{
return true;
}
}
$this->terminateWithError($this->p->t('ui', 'error_keineBerechtigungStg'), self::ERROR_TYPE_GENERAL);
}
}
}
@@ -0,0 +1,117 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class NotizPrestudent extends Notiz_Controller
{
public function __construct()
{
parent::__construct([
'isBerechtigt' => ['admin:r', 'assistenz:r'],
]);
//Load Models
$this->load->model('person/Notiz_model', 'NotizModel');
$this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel');
$this->load->model('crm/Student_model', 'StudentModel');
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
// Load language phrases
$this->loadPhrases([
'ui'
]);
//Permission checks for Studiengangsarray
$allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: [];
if ($this->router->method == 'addNewNotiz')
{
$json = $this->input->post('data');
$post_data = json_decode($json, true);
$prestudent_id = $post_data['id'];
if(!$prestudent_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Lehreinheit ID']), self::ERROR_TYPE_GENERAL);
}
$this->_checkAllowedOesFromPrestudent($prestudent_id, $allowedStgs);
}
if ($this->router->method == 'updateNotiz')
{
$json = $this->input->post('data');
$post_data = json_decode($json, true);
$notiz_id = $post_data['notiz_id'];
if(!$notiz_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Notiz ID']), self::ERROR_TYPE_GENERAL);
}
//get prestudent_id
$result = $this->NotizzuordnungModel->loadWhere(['notiz_id' => $notiz_id]);
$data = $this->getDataOrTerminateWithError($result);
$prestudent_id = current($data)->prestudent_id;
if(!$prestudent_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Prestudent ID']), self::ERROR_TYPE_GENERAL);
}
$this->_checkAllowedOesFromPrestudent($prestudent_id, $allowedStgs);
}
if ($this->router->method == 'deleteNotiz')
{
$notiz_id = $this->input->post('notiz_id');
$prestudent_id = $this->input->post('id');
if(!$notiz_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Notiz ID']), self::ERROR_TYPE_GENERAL);
}
if(!$prestudent_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Prestudent ID']), self::ERROR_TYPE_GENERAL);
}
$this->_checkAllowedOesFromPrestudent($prestudent_id, $allowedStgs);
}
}
public function isBerechtigt($id, $typeId)
{
if($typeId != "prestudent_id")
{
$this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL);
}
if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid'))
{
$result = $this->p->t('lehre','error_keineSchreibrechte');
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess("berechtigt in überschreibender Funktion");
}
private function _checkAllowedOesFromPrestudent($prestudent_id, $allowedStgs)
{
$student_uid = $this->StudentModel->getUID($prestudent_id);
$result = $this->StudentModel->loadWhere(['student_uid' => $student_uid]);
$data = $this->getDataOrTerminateWithError($result);
$studiengang_kz = current($data)->studiengang_kz;
if (!in_array($studiengang_kz, $allowedStgs))
{
return $this->terminateWithError($this->p->t('ui', 'error_keineBerechtigungStg'), self::ERROR_TYPE_GENERAL);
}
}
}
@@ -0,0 +1,32 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class NotizProjekt extends Notiz_Controller
{
public function __construct()
{
parent::__construct([
'isBerechtigt' => ['admin:r', 'assistenz:r'],
]);
}
public function isBerechtigt($id, $typeId)
{
if($typeId != "projekt_kurzbz")
{
$this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL);
}
//TODO define permission
if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid'))
{
$result = $this->p->t('lehre','error_keineSchreibrechte');
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess("berechtigt in überschreibender Funktion");
}
}
@@ -0,0 +1,32 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class NotizProjektphase extends Notiz_Controller
{
public function __construct()
{
parent::__construct([
'isBerechtigt' => ['admin:r', 'assistenz:r'],
]);
}
public function isBerechtigt($id, $typeId)
{
if($typeId != "projektphase_id")
{
$this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL);
}
//TODO define permission
if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid'))
{
$result = $this->p->t('lehre','error_keineSchreibrechte');
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess("berechtigt in überschreibender Funktion");
}
}
@@ -0,0 +1,32 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class NotizProjekttask extends Notiz_Controller
{
public function __construct()
{
parent::__construct([
'isBerechtigt' => ['admin:r', 'assistenz:r'],
]);
}
public function isBerechtigt($id, $typeId)
{
if($typeId != "projekttask_id")
{
$this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL);
}
//TODO define permission
if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid'))
{
$result = $this->p->t('lehre','error_keineSchreibrechte');
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess("berechtigt in überschreibender Funktion");
}
}
@@ -127,9 +127,9 @@ class Unterbrechung extends FHCAPI_Controller
$this->form_validation->set_rules(
'datum_wiedereinstieg',
'Datum Wiedereinstieg',
'required|callback_isValidDate|callback_isDateInFuture',
'required|is_valid_date|callback_isDateInFuture',
[
'isValidDate' => $this->p->t('ui', 'error_invalid_date'),
'is_valid_date' => $this->p->t('ui', 'error_invalid_date'),
'isDateInFuture' => $this->p->t('ui', 'error_invalid_date')
]
);
@@ -209,18 +209,9 @@ class Unterbrechung extends FHCAPI_Controller
$this->terminateWithSuccess(getData($result));
}
public function isValidDate($date)
{
try {
new DateTime($date);
} catch (Exception $e) {
return false;
}
return true;
}
public function isDateInFuture($date)
{
return new DateTime() < new DateTime($date);
}
}
@@ -36,15 +36,44 @@ class Aufnahmetermine extends FHCAPI_Controller
// Load models
$this->load->model('crm/Reihungstest_model', 'ReihungstestModel');
$this->load->model('crm/RtPerson_model', 'RtPersonModel');
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
$this->load->model('organisation/Studienordnung_model', 'StudienordnungModel');
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
}
public function getAufnahmetermine($person_id)
{
$result = $this->ReihungstestModel->getReihungstestPerson($person_id);
$arrayRt = $this->getDataOrTerminateWithError($result);
$data = $this->getDataOrTerminateWithError($result);
foreach ($arrayRt as $item) {
//Studienplan
$result = $this->StudienplanModel->loadWhere([
'studienplan_id' => $item->studienplan_id
]);
$data = $this->getDataOrTerminateWithError($result);
$studienordnung_id_ber = current($data)->studienordnung_id;
$this->terminateWithSuccess($data);
//Studienordnung
$result = $this->StudienordnungModel->loadWhere([
'studienordnung_id' => $studienordnung_id_ber
]);
$data = $this->getDataOrTerminateWithError($result);
$studiengang_kz_ber = current($data)->studiengang_kz;
//Studiengang von studiengang_kz_ber
$result = $this->StudiengangModel->load($studiengang_kz_ber);
$data = $this->getDataOrTerminateWithError($result);
$studiengangkurzbzlang_ber = current($data)->kurzbzlang;
$typ_ber = current($data)->typ;
//add to Array
$item->studiengang_kz_ber = $studiengang_kz_ber;
$item->studiengangkurzbzlang_ber = $studiengangkurzbzlang_ber;
$item->studiengangtyp_ber = $typ_ber;
}
$this->terminateWithSuccess($arrayRt);
}
public function insertAufnahmetermin()
@@ -60,7 +89,6 @@ class Aufnahmetermine extends FHCAPI_Controller
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID']), self::ERROR_TYPE_GENERAL);
}
$rt_id = (isset($formData['rt_id']) && !empty($formData['rt_id'])) ? $formData['rt_id'] : null;
$anmeldedatum = (isset($formData['anmeldedatum']) && !empty($formData['anmeldedatum'])) ? $formData['anmeldedatum'] : null;
$teilgenommen = (isset($formData['teilgenommen']) && !empty($formData['teilgenommen'])) ? $formData['teilgenommen'] : false;
@@ -224,7 +252,11 @@ class Aufnahmetermine extends FHCAPI_Controller
)
);
$data = $this->getDataOrTerminateWithError($result);
//check if existing placementtest
if(!hasData($result))
$this->terminateWithSuccess([]);
else
$data = getData($result);
$studienplan_arr = [];
$include_ids = [];
@@ -233,12 +265,18 @@ class Aufnahmetermine extends FHCAPI_Controller
if($item->studienplan_id != null)
$studienplan_arr[] = $item->studienplan_id;
}
if(!hasData($studienplan_arr))
$this->terminateWithSuccess([]);
//get Placementtests Person
$person_id = $this->_getPersonId($prestudent_id);
$resultRt = $this->ReihungstestModel->getReihungstestPerson($person_id);
$dataRt = $this->getDataOrTerminateWithError($resultRt);
//check if existing placementtest
if(!hasData($result))
$this->terminateWithSuccess([]);
else
$dataRt = getData($resultRt);
foreach ($dataRt as $item)
{
@@ -354,6 +392,7 @@ class Aufnahmetermine extends FHCAPI_Controller
$person_id = $this->input->get('person_id');
$punkte = $this->input->get('punkte');
$reihungstest_id = $this->input->get('reihungstest_id');
$has_excluded_gebiete = $this->input->get('hasExcludedAreas');
if(!$reihungstest_id)
{
@@ -364,22 +403,27 @@ class Aufnahmetermine extends FHCAPI_Controller
$studiengang_kz = $this->input->get('studiengang_kz');
$this->load->model('testtool/Ablauf_model', 'AblaufModel');
$result = $this->AblaufModel->getAblaufGebieteAndGewichte($studiengang_kz);
$result = $this->AblaufModel->getAblaufGebieteAndGewichte($studiengang_kz, 1);
$data = $this->getDataOrTerminateWithError($result);
$weightedArray = [];
$basis_gebiet_id_arr = [];
$basis_gebiet_id_toString = '';
foreach ($data as $abl)
{
$weightedArray[$abl->gebiet_id] = $abl->gewicht;
$basis_gebiet_id_arr[]= $abl->gebiet_id;
}
$basis_gebiet_id_toString = implode(', ', $basis_gebiet_id_arr);
$result = $this->ReihungstestModel->getReihungstestErgebnisPerson($person_id, $punkte, $reihungstest_id, $weightedArray);
/* if (isError($result))
{
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}*/
$result = $this->ReihungstestModel->getReihungstestErgebnisPerson(
$person_id,
$punkte,
$reihungstest_id,
$weightedArray,
$has_excluded_gebiete,
$basis_gebiet_id_toString
);
$this->terminateWithSuccess($result);
}
@@ -200,7 +200,8 @@ class Config extends FHCAPI_Controller
'type' => 'select',
'values' => $buchungstyp_kurzbz_plus_all,
'value_key' => 'buchungstyp_kurzbz',
'label_key' => 'beschreibung'
'label_key' => 'beschreibung',
'default' => 'all'
],
'samestg' => [
'type' => 'bool',
@@ -226,7 +227,8 @@ class Config extends FHCAPI_Controller
'type' => 'select',
'values' => $buchungstyp_kurzbz_plus_all,
'value_key' => 'buchungstyp_kurzbz',
'label_key' => 'beschreibung'
'label_key' => 'beschreibung',
'default' => 'all'
],
'samestg' => [
'type' => 'bool',
@@ -753,6 +753,10 @@ class Dokumente extends FHCAPI_Controller
);
$data = $this->getDataOrTerminateWithError($result);
if(!(is_array($data) && count($data) > 0))
{
return null;
}
$student = current($data);
return $student->student_uid;
@@ -108,6 +108,10 @@ class Student extends FHCAPI_Controller
$this->PrestudentModel->addSelect('p.matr_nr');
$this->PrestudentModel->addSelect('p.anrede');
$this->PrestudentModel->addSelect('p.zugangscode');
if($this->permissionlib->isBerechtigt('student/bpk'))
{
$this->PrestudentModel->addSelect('p.bpk');
}
if (defined('ACTIVE_ADDONS') && strpos(ACTIVE_ADDONS, 'bewerbung') !== false) {
$this->PrestudentModel->addSelect(
@@ -542,6 +546,7 @@ class Student extends FHCAPI_Controller
$this->_validate();
// TODO(chris): This should be in a library
$this->load->model('crm/Student_model', 'StudentModel');
$this->load->model('crm/Prestudent_model', 'PrestudentModel');
$this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
@@ -793,8 +798,8 @@ class Student extends FHCAPI_Controller
$this->form_validation->set_rules('geschlecht', 'Geschlecht', 'callback_requiredIfNotPersonId', [
'requiredIfNotPersonId' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('person', 'geschlecht')])
]);
$this->form_validation->set_rules('gebdatum', 'Geburtsdatum', ['isValidDate', function($value) { return isValidDate($value); }], [
'isValidDate' => $this->p->t('ui', 'error_invalid_date')
$this->form_validation->set_rules('gebdatum', 'Geburtsdatum', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_invalid_date')
]);
//$this->form_validation->set_rules('address[checked]', 'Address', 'required');
$this->form_validation->set_rules('address[plz]', 'PLZ', 'callback_requiredIfAddressFunc', [
@@ -611,7 +611,7 @@ class Students extends FHCAPI_Controller
if (!$verband && !$gruppe && $orgform_kurzbz !== null) {
$this->PrestudentModel->db->where(
"(
SELECT orgform_kurzbz
SELECT orgform_kurzbz
FROM public.tbl_prestudentstatus
WHERE prestudent_id=tbl_prestudent.prestudent_id
AND studiensemester_kurzbz=" . $this->PrestudentModel->escape($studiensemester_kurzbz) . "
@@ -626,7 +626,7 @@ class Students extends FHCAPI_Controller
$this->addFilter($studiensemester_kurzbz);
$result = $this->PrestudentModel->loadWhere($where);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
@@ -850,6 +850,45 @@ class Students extends FHCAPI_Controller
{
$stdsemEsc = $studiensemester_kurzbz ? $this->PrestudentModel->escape($studiensemester_kurzbz) : 'NULL';
$this->load->config('stv');
if(defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED)
{
$tags = $this->config->item('stv_prestudent_tags');
$whereTags = '';
if (is_array($tags) && !isEmptyArray($tags)) {
$tags = array_keys($tags);
foreach ($tags as $key => $tag) {
$tags[$key] = $this->db->escape($tag);
}
$whereTags = " AND nt.typ_kurzbz IN (" . implode(",", $tags) . ")";
}
$subQueryTag = "
(
SELECT
tag.prestudent_id,
COALESCE(json_agg(tag ORDER BY tag.done), '[]'::json) AS tags
FROM (
SELECT DISTINCT ON (n.notiz_id)
n.notiz_id AS id,
nt.typ_kurzbz,
array_to_json(nt.bezeichnung_mehrsprachig)->>0 AS beschreibung,
n.text AS notiz,
nt.style,
n.erledigt AS done,
nz.prestudent_id
FROM public.tbl_notizzuordnung AS nz
JOIN public.tbl_notiz AS n ON nz.notiz_id = n.notiz_id
JOIN public.tbl_notiz_typ AS nt ON n.typ = nt.typ_kurzbz "
. $whereTags .
"
) AS tag
GROUP BY tag.prestudent_id
) AS tag_data_agg
";
}
$this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
$this->PrestudentModel->addJoin('public.tbl_person p', 'person_id');
@@ -872,8 +911,17 @@ class Students extends FHCAPI_Controller
AND ps.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')
AND ps.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')', 'LEFT');
if(defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED)
{
$this->PrestudentModel->addJoin($subQueryTag, 'tag_data_agg.prestudent_id = tbl_prestudent.prestudent_id', 'LEFT');
}
$this->PrestudentModel->addSelect("b.uid");
if(defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED)
{
$this->PrestudentModel->addSelect('tag_data_agg.tags');
}
$this->PrestudentModel->addSelect('titelpre');
$this->PrestudentModel->addSelect('nachname');
$this->PrestudentModel->addSelect('vorname');
@@ -931,6 +979,7 @@ class Students extends FHCAPI_Controller
$this->PrestudentModel->addSelect('mentor');
$this->PrestudentModel->addSelect('b.aktiv AS bnaktiv');
$this->PrestudentModel->addSelect('unruly');
$this->PrestudentModel->db->where_in('tbl_prestudent.studiengang_kz', $this->allowedStgs);
@@ -0,0 +1,48 @@
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class Tags extends Tag_Controller
{
const BERECHTIGUNG_KURZBZ = ['admin:rw', 'assistenz:rw'];
public function __construct()
{
parent::__construct([
'getTag' => self::BERECHTIGUNG_KURZBZ,
'getTags' => self::BERECHTIGUNG_KURZBZ,
'addTag' => self::BERECHTIGUNG_KURZBZ,
'updateTag' => self::BERECHTIGUNG_KURZBZ,
'doneTag' => self::BERECHTIGUNG_KURZBZ,
'deleteTag' => self::BERECHTIGUNG_KURZBZ
]);
$this->config->load('stv');
}
public function getTag($readonly_tags = null)
{
parent::getTag($this->config->item('stv_prestudent_tags'));
}
public function getTags($tags = null)
{
parent::getTags($this->config->item('stv_prestudent_tags'));
}
public function addTag($withZuordnung = true, $updatable_tags = null)
{
parent::addTag(true, $this->config->item('stv_prestudent_tags'));
}
public function updateTag($updatable_tags = null)
{
parent::updateTag($this->config->item('stv_prestudent_tags'));
}
public function deleteTag($withZuordnung = true, $updatable_tags = null)
{
parent::deleteTag(true, $this->config->item('stv_prestudent_tags'));
}
public function doneTag($updatable_tags = null)
{
parent::doneTag($this->config->item('stv_prestudent_tags'));
}
}
@@ -76,9 +76,7 @@ class Vertrag extends FHCAPI_Controller
if (isError($allOe)) $this->terminateWithError(getError($allOe), self::ERROR_TYPE_GENERAL);
$allOe = hasData($allOe) ? getData($allOe) : [];
$this->addMeta('oe', $allOe);
$allOe = hasData($allOe) ? array_column(getData($allOe), 'oe_kurzbz') : [];
// * then check if the user has permissions to cancel the corresponding lv-organisational units
if (!$this->permissionlib->isBerechtigtMultipleOe('admin', $allOe, 'suid') &&
@@ -0,0 +1,62 @@
<?php
/**
* Copyright (C) 2024 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (!defined('BASEPATH')) exit('No direct script access allowed');
use CI3_Events as Events;
/**
* This controller operates between (interface) the JS (GUI) and the back-end
* Provides data to the ajax get calls about the VV Config
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Config extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'printDocument' => ['vertrag/mitarbeiter:r'],
]);
}
public function printDocument()
{
$params = [];
$menu = [];
Events::trigger(
'multiActionPrintHonorarvertrag',
// passing $menu per reference
function & () use (&$menu) {
return $menu;
},
$params
);
if (is_array($menu) && isset($menu[0]))
{
$this->terminateWithSuccess($menu[0]);
}
else
{
// $this->terminateWithError('Error with Event 'multiActionPrintHonorarvertrag');
$this->terminateWithSuccess();
}
}
}
@@ -26,9 +26,6 @@ class Vertraege extends FHCAPI_Controller
'deleteLehrauftrag' =>['vertrag/mitarbeiter:w'],
'deleteBetreuung' =>['vertrag/mitarbeiter:w'],
'getMitarbeiter' => ['vertrag/mitarbeiter:r'],
'getHeader' => ['vertrag/mitarbeiter:r'],
'getPersonAbteilung' => ['vertrag/mitarbeiter:r'],
'getLeitungOrg' => ['vertrag/mitarbeiter:r'],
]);
//Load Models and Libraries
@@ -241,7 +238,7 @@ class Vertraege extends FHCAPI_Controller
}
}
$this->db->trans_complete();
$this->terminateWithSuccess(true);
$this->terminateWithSuccess($vertrag_id);
}
public function updateContract()
@@ -358,7 +355,7 @@ class Vertraege extends FHCAPI_Controller
}
$this->db->trans_complete();
$this->terminateWithSuccess(true);
$this->terminateWithSuccess($vertrag_id);
}
public function loadContract($vertrag_id)
@@ -684,37 +681,4 @@ class Vertraege extends FHCAPI_Controller
}
return $this->terminateWithSuccess(getData($result));
}
public function getPersonAbteilung($mitarbeiter_uid)
{
$this->load->model('ressource/Mitarbeiter_model', 'Mitarbeitermodel');
$result = $this->Mitarbeitermodel->getPersonAbteilung($mitarbeiter_uid);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(current($data));
}
public function getLeitungOrg($oekurzbz)
{
$this->load->model('ressource/Mitarbeiter_model', 'Mitarbeitermodel');
$result = $this->Mitarbeitermodel->getLeitungOrg($oekurzbz);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(current($data));
}
public function getHeader($person_id)
{
$this->load->model('ressource/Mitarbeiter_model', 'Mitarbeitermodel');
$result = $this->Mitarbeitermodel->getHeader($person_id);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(current($data));
}
}
@@ -0,0 +1,52 @@
<?php
/**
* Copyright (C) 2026 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*/
class Admin extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
// Set required permissions
parent::__construct(
array(
'index' => 'dashboard/admin:rw',
'preview' => 'dashboard/admin:r',
)
);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
public function index()
{
$this->load->view('dashboard/admin.php', []);
}
public function preview($dashboard_kurzbz = 'CIS')
{
$this->load->view('dashboard/preview.php', [
'dashboard_kurzbz' => $dashboard_kurzbz
]);
}
}
-76
View File
@@ -1,76 +0,0 @@
<?php
defined('BASEPATH') || exit('No direct script access allowed');
class Api extends Auth_Controller
{
public function __construct()
{
parent::__construct(
array(
'index' => 'dashboard/admin:rw',
'getNews' => 'dashboard/benutzer:r',
'getAmpeln' => 'dashboard/benutzer:r',
)
);
$this->load->library('AuthLib', null, 'AuthLib');
$this->_setAuthUID();
}
public function index()
{
echo 'Dashboard API Controller';
}
/**
* Get News.
*/
public function getNews()
{
$limit = $this->input->get('limit');
$this->load->model('content/News_model', 'NewsModel');
$result = $this->NewsModel->getAll($limit);
if (hasData($result))
{
$this->outputJson(getData($result), REST_Controller::HTTP_OK);
}
else
{
$this->terminateWithJsonError('fehler entdeckt');
}
}
/**
* Get Ampeln.
*/
public function getAmpeln()
{
$this->load->model('content/Ampel_model', 'AmpelModel');
$result = $this->AmpelModel->getByUser($this->_uid);
if (hasData($result))
{
$this->outputJson(getData($result), REST_Controller::HTTP_OK);
}
else
{
$this->terminateWithJsonError('fehler entdeckt');
}
}
/**
* Retrieve the UID of the logged user and checks if it is valid
*/
private function _setAuthUID()
{
$this->_uid = getAuthUID();
if (!$this->_uid) show_error('User authentification failed');
}
}
@@ -1,216 +0,0 @@
<?php
defined('BASEPATH') || exit('No direct script access allowed');
/**
* Description of Config
*
* @author bambi
*/
class Config extends Auth_Controller
{
public function __construct()
{
parent::__construct(
array(
'index' => 'dashboard/benutzer:r',
'dummy' => 'dashboard/benutzer:r',
'genWidgetId' => 'dashboard/benutzer:rw',
'addWidgetsToPreset' => 'dashboard/admin:rw',
'removeWidgetFromPreset' => 'dashboard/admin:rw',
'addWidgetsToUserOverride' => 'dashboard/benutzer:rw',
'removeWidgetFromUserOverride' => 'dashboard/benutzer:rw',
'funktionen' => 'dashboard/admin:r',
'preset' => 'dashboard/admin:r',
'presetBatch' => 'dashboard/admin:r'
)
);
$this->load->library('dashboard/DashboardLib', null, 'DashboardLib');
$this->load->library('AuthLib', null, 'AuthLib');
$this->load->model('ressource/Funktion_model', 'FunktionModel');
}
public function index()
{
$dashboard_kurzbz = $this->input->get('db');
$uid = $this->AuthLib->getAuthObj()->username;
$dashboard = $this->DashboardLib->getDashboardByKurzbz($dashboard_kurzbz);
if(!$dashboard) {
http_response_code(404);
$this->terminateWithJsonError(array(
'error' => 'Dashboard ' . $dashboard_kurzbz . ' not found.'
));
}
$mergedconfig = $this->DashboardLib->getMergedConfig($dashboard->dashboard_id, $uid);
$this->outputJsonSuccess($mergedconfig);
}
public function genWidgetId()
{
$dashboard_kurzbz = $this->input->get('db');
$widgetid = $this->DashboardLib->generateWidgetId($dashboard_kurzbz);
$this->outputJsonSuccess(array(
'widgetid' => $widgetid
));
}
public function addWidgetsToPreset()
{
$input = json_decode($this->input->raw_input_stream);
$dashboard_kurzbz = $input->db;
$funktion_kurzbz = $input->funktion_kurzbz;
$preset = $this->DashboardLib->getPresetOrCreateEmptyPreset($dashboard_kurzbz, $funktion_kurzbz);
$preset_decoded = json_decode($preset->preset, true);
$this->DashboardLib->addWidgetsToWidgets($preset_decoded, $dashboard_kurzbz, $funktion_kurzbz, $input->widgets);
$preset->preset = json_encode($preset_decoded);
$result = $this->DashboardLib->insertOrUpdatePreset($preset);
if (isError($result)) {
http_response_code(500);
$this->terminateWithJsonError('preset could not be saved');
}
$this->outputJsonSuccess(array('msg' => 'preset successfully stored.', 'data' => $preset_decoded));
}
public function removeWidgetFromPreset()
{
$input = json_decode($this->input->raw_input_stream);
$dashboard_kurzbz = $input->db;
$funktion_kurzbz = $input->funktion_kurzbz;
$widgetid = $input->widgetid;
$preset = $this->DashboardLib->getPreset($dashboard_kurzbz, $funktion_kurzbz);
if ($preset === null) {
http_response_code(404);
$this->terminateWithJsonError('preset for dashboard ' . $dashboard_kurzbz . ' and funktion ' . $funktion_kurzbz . ' not found.');
}
$preset_decoded = json_decode($preset->preset, true);
if (!$this->DashboardLib->removeWidgetFromWidgets($preset_decoded, $funktion_kurzbz, $widgetid))
{
http_response_code(404);
$this->terminateWithJsonError('widgetid ' . $widgetid . ' not found');
}
$preset->preset = json_encode($preset_decoded);
$result = $this->DashboardLib->insertOrUpdatePreset($preset);
if (isError($result))
{
http_response_code(500);
$this->terminateWithJsonError('failed to remove widget');
}
$this->outputJsonSuccess(array('msg' => 'preset successfully updated.'));
}
public function addWidgetsToUserOverride()
{
$input = json_decode($this->input->raw_input_stream);
$dashboard_kurzbz = $input->db;
$funktion_kurzbz = $input->funktion_kurzbz;
$uid = $this->AuthLib->getAuthObj()->username;
$override = $this->DashboardLib->getOverrideOrCreateEmptyOverride($dashboard_kurzbz, $uid);
$override_decoded = json_decode($override->override, true);
$this->DashboardLib->addWidgetsToWidgets($override_decoded, $dashboard_kurzbz, $funktion_kurzbz, $input->widgets);
$override->override = json_encode($override_decoded);
$result = $this->DashboardLib->insertOrUpdateOverride($override);
if (isError($result)) {
http_response_code(500);
$this->terminateWithJsonError('override could not be saved');
}
$this->outputJsonSuccess(array('msg' => 'override successfully stored.', 'data' => $override_decoded));
}
public function removeWidgetFromUserOverride()
{
$input = json_decode($this->input->raw_input_stream);
$dashboard_kurzbz = $input->db;
$funktion_kurzbz = $input->funktion_kurzbz;
$uid = $this->AuthLib->getAuthObj()->username;
$widgetid = $input->widgetid;
$override = $this->DashboardLib->getOverride($dashboard_kurzbz, $uid);
if (empty($override)) {
http_response_code(404);
$this->terminateWithJsonError('userconfig for dashboard ' . $dashboard_kurzbz . ' not found.');
}
$override_decoded = json_decode($override->override, true);
if (!$this->DashboardLib->removeWidgetFromWidgets($override_decoded, $funktion_kurzbz, $widgetid))
{
http_response_code(404);
$this->terminateWithJsonError('widgetid ' . $widgetid . ' not found');
}
$override->override = json_encode($override_decoded);
$result = $this->DashboardLib->insertOrUpdateOverride($override, $uid);
if (isError($result))
{
http_response_code(500);
$this->terminateWithJsonError('failed to remove widget');
}
$this->outputJsonSuccess(array('msg' => 'override successfully updated.'));
}
public function funktionen()
{
$funktionen = $this->FunktionModel->load();
if (isError($funktionen)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($funktionen)
]);
}
return $this->outputJsonSuccess(getData($funktionen) ?: []);
}
public function preset()
{
$db = $this->input->get('db');
$funktion = $this->input->get('funktion');
$conf = $this->DashboardLib->getPreset($db, $funktion);
if (!$conf)
return $this->outputJsonSuccess(['widgets' => [$funktion => []]]);
return $this->outputJsonSuccess(json_decode($conf->preset, true));
}
public function presetBatch()
{
$db = $this->input->get('db');
$funktionen = $this->input->get('funktionen');
$result = [];
foreach ($funktionen as $funktion) {
$conf = $this->DashboardLib->getPreset($db, $funktion);
if ($conf)
{
$preset = json_decode($conf->preset, true);
if (!isset($preset[$funktion]) || !isset($preset[$funktion]['widgets']))
$result[$funktion] = [];
else
$result[$funktion] = $preset[$funktion]['widgets'];
}
else
$result[$funktion] = [];
}
return $this->outputJsonSuccess($result);
}
}
@@ -1,86 +0,0 @@
<?php
defined('BASEPATH') || exit('No direct script access allowed');
/**
* Description of Widget
*
* @author chris
*/
class Dashboard extends Auth_Controller
{
public function __construct()
{
parent::__construct(
array(
'index' => 'dashboard/admin:r',
'create' => 'dashboard/admin:rw',
'update' => 'dashboard/admin:rw',
'delete' => 'dashboard/admin:rw'
)
);
$this->load->library('dashboard/DashboardLib', null, 'DashboardLib');
$this->load->model('dashboard/Dashboard_model', 'DashboardModel');
}
public function index()
{
$result = $this->DashboardModel->load();
if (isError($result)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($result)
]);
}
return $this->outputJsonSuccess(getData($result) ?: []);
}
public function create()
{
$input = $this->getPostJSON();
$result = $this->DashboardModel->insert($input);
if (isError($result)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($result)
]);
}
return $this->outputJsonSuccess(getData($result) ?: []);
}
public function update()
{
$input = $this->getPostJSON();
$result = $this->DashboardModel->update($input->dashboard_id, $input);
if (isError($result)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($result)
]);
}
return $this->outputJsonSuccess(getData($result) ?: []);
}
public function delete()
{
$input = $this->getPostJSON();
$result = $this->DashboardModel->delete($input->dashboard_id);
if (isError($result)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($result)
]);
}
return $this->outputJsonSuccess(getData($result) ?: []);
}
}
@@ -1,58 +0,0 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*/
class DashboardDemo extends Auth_Controller
{
private $_uid; // uid of the logged user
/**
* Constructor
*/
public function __construct()
{
// Set required permissions
parent::__construct(
array(
'index' => 'dashboard/benutzer:r',
'admin' => 'dashboard/admin:rw'
)
);
$this->load->library('AuthLib');
$this->load->library('WidgetLib');
$this->_setAuthUID(); // sets property uid
$this->setControllerId(); // sets the controller id
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
public function index()
{
$this->load->view('dashboard/dashboard_demo.php', []);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
public function admin()
{
$this->load->view('dashboard/dashboard_demo_admin.php', []);
}
// -----------------------------------------------------------------------------------------------------------------
// Private methods
/**
* Retrieve the UID of the logged user and checks if it is valid
*/
private function _setAuthUID()
{
$this->_uid = getAuthUID();
if (!$this->_uid) show_error('User authentification failed');
}
}
@@ -1,134 +0,0 @@
<?php
defined('BASEPATH') || exit('No direct script access allowed');
/**
* Description of Widget
*
* @author chris
*/
class Widget extends Auth_Controller
{
public function __construct()
{
parent::__construct(
array(
'index' => ['dashboard/benutzer:r', 'dashboard/admin:r'],
'getAll' => 'dashboard/admin:r',
'getWidgetsForDashboard' => ['dashboard/benutzer:rw', 'dashboard/admin:r'],
'setAllowed' => 'dashboard/admin:rw'
)
);
$this->load->library('dashboard/DashboardLib', null, 'DashboardLib');
$this->load->model('dashboard/Widget_model', 'WidgetModel');
$this->load->model('dashboard/Dashboard_Widget_model', 'DashboardWidgetModel');
}
public function index()
{
$widget_id = $this->input->get('id');
$widget = $this->WidgetModel->load($widget_id);
if (isError($widget) || !getData($widget))
return $this->outputJsonSuccess([
"widget_id" => 0,
"widget_kurzbz" => "notfound",
"arguments" => [
"className" => 'alert-danger',
"title" => 'Widget Not Found',
"msg" => 'The widget with the id ' . $widget_id . ' could not be found'
],
"setup" => [
"name" => 'Widget Not Found',
"file" => absoluteJsImportUrl('public/js/components/DashboardWidget/Default.js'),
"width" => 1,
"height" => 1
]
]);
$widget = current(getData($widget));
$widget->arguments = json_decode($widget->arguments);
$tmpsetup = json_decode($widget->setup);
$tmpsetup->file = absoluteJsImportUrl($tmpsetup->file);
$widget->setup = $tmpsetup;
return $this->outputJsonSuccess($widget);
}
public function getAll()
{
$dashboard_id = $this->input->get('dashboard_id');
$result = $this->WidgetModel->getWithAllowedForDashboard($dashboard_id);
if (isError($result))
return $this->outputJsonError(getError($result));
$tmpwidgets = getData($result) ?: [];
$widgets = array_map(function($widget) {
$widget->arguments = json_decode($widget->arguments);
$tmpsetup = json_decode($widget->setup);
$tmpsetup->file = absoluteJsImportUrl($tmpsetup->file);
$widget->setup = $tmpsetup;
return $widget;
}, $tmpwidgets);
$this->outputJsonSuccess($widgets);
}
public function getWidgetsForDashboard()
{
$db = $this->input->get('db');
$result = $this->WidgetModel->getForDashboard($db);
if (isError($result)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($result)
]);
}
$tmpwidgets = getData($result) ?: [];
$widgets = array_map(function($widget) {
$widget->arguments = json_decode($widget->arguments);
$tmpsetup = json_decode($widget->setup);
$tmpsetup->file = absoluteJsImportUrl($tmpsetup->file);
$widget->setup = $tmpsetup;
return $widget;
}, $tmpwidgets);
$this->outputJsonSuccess($widgets);
}
public function setAllowed()
{
$input = $this->getPostJSON();
$dashboard_id = $input->dashboard_id;
$widget_id = $input->widget_id;
$action = $input->action;
if ($action == 'add') {
$result = $this->DashboardWidgetModel->insert([
'dashboard_id' => $dashboard_id,
'widget_id' => $widget_id
]);
} elseif ($action == 'delete') {
$result = $this->DashboardWidgetModel->delete([
'dashboard_id' => $dashboard_id,
'widget_id' => $widget_id
]);
} else {
http_response_code(404); // TODO(chris): 400?
$this->terminateWithJsonError([
'error' => 'action value invalid'
]);
}
if (isError($result)) {
http_response_code(404);
$this->terminateWithJsonError([
'error' => getError($result)
]);
}
return $this->outputJsonSuccess(getData($result));
}
}
+296 -4
View File
@@ -22,11 +22,272 @@ class AbgabetoolJob extends JOB_Controller
$this->_ci->load->model('crm/Student_model', 'StudentModel');
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
$this->_ci->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
$this->_ci->load->library('SignatureLib');
$this->_ci->load->config('abgabe');
$this->loadPhrases([
'abgabetool'
]);
}
// basically the notifyBetreuerMail function but email goes to assistenz
// and new abgaben are further evaluated for missing signature status
public function notifyAssistenzAboutMissingSignatureUploads() {
$this->_ci->logInfo('Start job FHC-Core->notifyAssistenzAboutMissingSignatureUploads');
$interval = $this->_ci->config->item('PAABGABE_EMAIL_JOB_INTERVAL');
$relevantTypes = $this->_ci->config->item('RELEVANT_PAABGABETYPEN_SAMMELMAIL_ASSISTENZ');
$result = $this->_ci->PaabgabeModel->findAbgabenNewOrUpdatedSinceByAbgabedatum($interval, $relevantTypes);
$retval = getData($result);
// retval are paabgaben joined with projektarbeit and betreuer
if(count($retval) == 0) {
$this->logInfo("Keine Emails über neue Paabgaben an Assistenzen versandt");
return;
}
// group changed/new abgaben for projektarbeiten
$projektarbeiten = [];
foreach($retval as $abgabeWithNewUpload) {
// Check if the current item has a 'projektarbeit_id' field.
// Replace 'projektarbeit_id' with the actual key name if it's different.
if (isset($abgabeWithNewUpload->projektarbeit_id)) {
$projektarbeitId = $abgabeWithNewUpload->projektarbeit_id;
// If the 'projektarbeit_id' is not yet a key in $projektarbeiten,
// initialize it as an empty array.
if (!isset($projektarbeiten[$projektarbeitId])) {
$projektarbeiten[$projektarbeitId] = [];
}
// check signature for that abgabe, main point of this job
$this->checkAbgabeSignatur($abgabeWithNewUpload, $abgabeWithNewUpload->student_uid);
// Add the current row to the array associated with its 'projektarbeit_id'.
$projektarbeiten[$projektarbeitId][] = $abgabeWithNewUpload;
}
}
// for each projektarbeit fetch their assistenz and same them in their own dictionary to avoid too many mails
$assistenzMap = [];
// for each projektarbeit fetch their betreuer and save them in their own dictionary to avoid too many mails
$projektarbeitBetreuerMap = [];
forEach($projektarbeiten as $projektarbeit_id => $abgaben) {
$assistenzResult = $this->_ci->OrganisationseinheitModel->getAssistenzForOE($abgaben[0]->stg_oe_kurzbz);
forEach($assistenzResult->retval as $assistenzRow) {
if (!isset($assistenzMap[$assistenzRow->person_id])) {
$assistenzMap[$assistenzRow->person_id] = [];
}
// Add the current $assistenzRow to the $assistenzMap as an array associated with its projektarbeit_id.
$assistenzMap[$assistenzRow->person_id][] = [$projektarbeit_id, $assistenzRow];
}
$betreuerResult = $this->_ci->ProjektbetreuerModel->getAllBetreuerOfProjektarbeit($projektarbeit_id);
forEach($betreuerResult->retval as $betreuerRow) {
if (!isset($projektarbeitBetreuerMap[$projektarbeit_id])) {
$projektarbeitBetreuerMap[$projektarbeit_id] = [];
}
// Add the current betreuerRow to the betreuerMap as an array associated with its projektarbeit_id.
$projektarbeitBetreuerMap[$projektarbeit_id][] = $betreuerRow;
}
}
$count = 0;
foreach($assistenzMap as $assistenz_person_id => $tupelArr) {
$abgabenString = '<div style="font-family: Arial, sans-serif; color: #333;">';
$hasIssues = false; // Track if this assistant actually needs an email
foreach($tupelArr as $tupel) {
$projektarbeit_id = $tupel[0];
$assistenzRow = $tupel[1];
$betreuerArray = $projektarbeitBetreuerMap[$projektarbeit_id] ?? [];
$allAbgaben = $projektarbeiten[$projektarbeit_id];
// only keep abgaben that are not correctly signed
$issueAbgaben = array_filter($allAbgaben, function($abgabe) {
// We only care about cases where it's explicitly NOT true (false, error, or null)
return $abgabe->signatur !== true;
});
// if this specific project has no signature issues, skip to the next project
if(empty($issueAbgaben)) {
continue;
}
// If we reached here, we have at least one issue to report
$hasIssues = true;
// Format the Student Name (using the first available abgabe object)
$s = reset($issueAbgaben);
$nameParts = array_filter([$s->titelpre, $s->vorname, $s->nachname, $s->titelpost]);
$studentFullName = implode(' ', $nameParts);
// Format the Supervisors string
$betreuerStrings = [];
foreach($betreuerArray as $b) {
$bNameParts = array_filter([$b->titelpre, $b->vorname, $b->nachname, $b->titelpost]);
$bFullName = implode(' ', $bNameParts);
$betreuerStrings[] = "{$bFullName} ({$b->betreuerart_kurzbz})";
}
$allBetreuerFormatted = implode(', ', $betreuerStrings);
$projektarbeit_titel = $s->titel ?? 'Kein Titel vergeben';
// Project Header Section
$abgabenString .= "
<div style='margin-top: 25px; padding: 12px; background-color: #fff5f5; border-left: 4px solid #dc3545; border-bottom: 1px solid #fee;'>
<strong style='font-size: 16px; color: #b02a37;'>Projekt: {$projektarbeit_titel}</strong><br/>
<div style='margin-top: 5px; font-size: 14px;'>
<strong>Studierende/r:</strong> {$studentFullName}
</div>
<div style='margin-top: 3px; font-size: 14px;'>
<strong>Betreuer:</strong> {$allBetreuerFormatted}
</div>
<span style='color: #666; font-size: 12px;'>
ID: {$projektarbeit_id} | Stg: {$s->stgtyp}{$s->stgkz} ({$s->studiensemester_kurzbz})
</span>
</div>";
// Start Table
$abgabenString .= '
<table style="width: 100%; border-collapse: collapse; margin-bottom: 25px;">
<thead>
<tr style="background-color: #f8f9fa; text-align: left;">
<th style="padding: 10px; border: 1px solid #ddd; font-size: 13px; width: 20%;">Datum</th>
<th style="padding: 10px; border: 1px solid #ddd; font-size: 13px; width: 45%;">Abgabe/Bezeichnung</th>
<th style="padding: 10px; border: 1px solid #ddd; font-size: 13px; width: 35%;">Status</th>
</tr>
</thead>
<tbody>';
$printed = []; // lazy hack to avoid duplicate rows
foreach ($issueAbgaben as $abgabe) {
// if we had this paabgabe already (erstbetreuer/zweitbetreuer fetch achieves duplicates
if(in_array($abgabe->paabgabe_id, $printed)) {
continue; // skip this forEach iteration
}
$printed[] = $abgabe->paabgabe_id;
$abgabedatumFormatted = (new DateTime($abgabe->abgabedatum))->format('d.m.Y');
// label and color
if ($abgabe->signatur === false) {
$sigLabel = "FEHLENDE SIGNATUR";
$sigBg = "#dc3545";
} elseif ($abgabe->signatur === 'error') {
$sigLabel = "PRÜFUNG FEHLGESCHLAGEN";
$sigBg = "#fd7e14";
} else {
$sigLabel = "DATEI NICHT GEFUNDEN";
$sigBg = "#6c757d";
}
$abgabenString .= "
<tr>
<td style='padding: 10px; border: 1px solid #ddd; font-size: 13px; vertical-align: top;'>{$abgabedatumFormatted}</td>
<td style='padding: 10px; border: 1px solid #ddd; font-size: 13px;'>
<strong>{$abgabe->bezeichnung}</strong>
</td>
<td style='padding: 10px; border: 1px solid #ddd; font-size: 13px; text-align: center;'>
<span style='color: #fff; background-color: {$sigBg}; padding: 3px 8px; border-radius: 3px; font-weight: bold; font-size: 11px;'>
{$sigLabel}
</span>
</td>
</tr>";
}
$abgabenString .= '</tbody></table>';
}
$abgabenString .= '</div>';
// only send the email if at least one project had an issue
if ($hasIssues) {
$assistenzRow = $tupelArr[0][1];
$anrede = $assistenzRow->anrede;
$anredeFillString = $assistenzRow->anrede == "Herr" ? "r" : "";
$fullFormattedNameString = $assistenzRow->first;
$path = $this->_ci->config->item('URL_ASSISTENZ');
$url = CIS_ROOT . $path;
$body_fields = array(
'anrede' => $anrede,
'anredeFillString' => $anredeFillString,
'fullFormattedNameString' => $fullFormattedNameString,
'abgabenString' => $abgabenString,
'linkAbgabetool' => $url
);
$email = $assistenzRow->uid . "@" . DOMAIN;
sendSanchoMail(
'PAANoSigAssSM',
$body_fields,
$email,
$this->p->t('abgabetool', 'c4missingSignatureNotification')
);
$count++;
}
}
$this->_ci->logInfo($count . " Emails bezüglich fehlender Signaturen erfolgreich versandt");
$this->_ci->logInfo('End job FHC-Core->notifyAssistenzAboutMissingSignatureUploads');
}
/**
* helper function to check the signature status of uploaded files for zwischenabgabe & endupload
*/
private function checkAbgabeSignatur($abgabe, $student_uid) {
$paabgabetypenToCheck = $this->config->item('SIGNATUR_CHECK_PAABGABETYPEN');
if(!in_array($abgabe->paabgabetyp_kurzbz, $paabgabetypenToCheck)) {
return;
}
if (!defined('SIGNATUR_URL')) {
$abgabe->signatur = 'error';
return;
}
$path = PAABGABE_PATH.$abgabe->paabgabe_id.'_'.$student_uid.'.pdf';
$signaturVorhanden = null; // if frontend receives null -> indicates no file found at path
if(file_exists($path)) {
// Check if the document is signed
$signList = SignatureLib::list($path);
if (is_array($signList) && count($signList) > 0)
{
// The document is signed
$signaturVorhanden = true;
}
elseif ($signList === null)
{
// frontend knows to handle it this way for signatures
$signaturVorhanden = 'error';
}
else
{
$signaturVorhanden = false;
}
$abgabe->signatur = $signaturVorhanden;
}
}
public function notifyAssistenzAboutChangedAbgaben() {
@@ -234,8 +495,7 @@ class AbgabetoolJob extends JOB_Controller
// get all new or changed termine in interval
$result = $this->_ci->PaabgabeModel->findAbgabenNewOrUpdatedSince($interval, $relevantTypes);
$retval = getData($result);
if(count($retval) == 0) {
if(!$retval) {
$this->_ci->logInfo("Keine Emails an Betreuer über neue oder veränderte Termine versandt");
return;
}
@@ -248,17 +508,29 @@ class AbgabetoolJob extends JOB_Controller
if (isset($newOrChangedAbgabe->projektarbeit_id)) {
$projektarbeitId = $newOrChangedAbgabe->projektarbeit_id;
// check if the updatevon field is NOT the same as the student the projektarbeit is assigned to
// since uploading a file to a paabgabe is also putting updateamum & updatevon
// we have our own "student has uploaded a file" emailjob anyways
if($newOrChangedAbgabe->student_uid === $newOrChangedAbgabe->updatevon) {
continue;
}
// If the 'projektarbeit_id' is not yet a key in $projektarbeiten,
// initialize it as an empty array.
if (!isset($projektarbeiten[$projektarbeitId])) {
$projektarbeiten[$projektarbeitId] = [];
}
// Add the current row to the array associated with its 'projektarbeit_id'.
$projektarbeiten[$projektarbeitId][] = $newOrChangedAbgabe;
}
}
if(count($projektarbeiten) == 0) {
$this->_ci->logInfo("Keine Emails an Betreuer über neue oder veränderte Termine versandt");
return;
}
// for each projektarbeit fetch their betreuer and save them in their own dictionary to avoid too many mails
$betreuerMap = [];
forEach($projektarbeiten as $projektarbeit_id => $abgaben) {
@@ -289,6 +561,8 @@ class AbgabetoolJob extends JOB_Controller
$anredeFillString = $data->anrede == "Herr" ? "r" : "";
$fullFormattedNameString = $data->first;
$relevantCounter = 0; // workaround to check if a betreuer needs to have any notification about relevant
// abgaben at all to avoid sending empty emails since we filter on certain conditions
forEach($tupelArr as $tupel) {
$projektarbeit_id = $tupel[0];
$betreuerRow = $tupel[1];
@@ -307,6 +581,8 @@ class AbgabetoolJob extends JOB_Controller
continue;
}
$relevantCounter++;
// format the Student Name
$s = $relevantAbgaben[0];
$nameParts = [];
@@ -365,6 +641,11 @@ class AbgabetoolJob extends JOB_Controller
// done with building the change list, now send it
$betreuerRow = $tupelArr[0][1];
if($relevantCounter == 0) {
$this->_ci->logInfo('No Relevant Abgaben to notify Betreuer PersonID: "'.$betreuerRow->person_id.'".');
continue;
}
$path = $this->_ci->config->item('URL_MITARBEITER');
$url = CIS_ROOT.$path;
@@ -377,6 +658,11 @@ class AbgabetoolJob extends JOB_Controller
);
$email = $betreuerRow->uid ? $betreuerRow->uid."@".DOMAIN : $betreuerRow->private_email;
if(!$email) {
$this->_ci->logInfo('Could not send Email for Betreuer PersonID: "'.$data->person_id.'".');
continue;
}
// send email with bundled info
sendSanchoMail(
@@ -500,6 +786,12 @@ class AbgabetoolJob extends JOB_Controller
$email = $data->uid ? $data->uid."@".DOMAIN : $data->private_email;
// in rare cases there are betreuer (often zweitbetreuer) without uid and without private email
if(!$email) {
$this->_ci->logInfo('Could not send Email for Betreuer PersonID: "'.$data->person_id.'".');
continue;
}
// send email with bundled info
sendSanchoMail(
'PaabgabeUpdatesBetSM',
@@ -109,7 +109,7 @@ class Lehrauftrag extends Auth_Controller
$studiensemester_kurzbz = $this->input->get('studiensemester'); // if provided by selected studiensemester
if (is_null($studiensemester_kurzbz)) // else set next studiensemester as default value
{
$studiensemester = $this->StudiensemesterModel->getAktOrNextSemester(62);
$studiensemester = $this->StudiensemesterModel->getAktOrNextSemester();
if (hasData($studiensemester))
{
$studiensemester_kurzbz = $studiensemester->retval[0]->studiensemester_kurzbz;
@@ -75,7 +75,7 @@ class LehrauftragAkzeptieren extends Auth_Controller
$studiensemester_kurzbz = $this->input->get('studiensemester'); // if provided by selected studiensemester
if (is_null($studiensemester_kurzbz)) // else set next studiensemester as default value
{
$studiensemester = $this->StudiensemesterModel->getAktOrNextSemester(62);
$studiensemester = $this->StudiensemesterModel->getAktOrNextSemester();
if (hasData($studiensemester))
{
$studiensemester_kurzbz = $studiensemester->retval[0]->studiensemester_kurzbz;
@@ -91,7 +91,7 @@ class LehrauftragErteilen extends Auth_Controller
$studiensemester_kurzbz = $this->input->get('studiensemester'); // if provided by selected studiensemester
if (is_null($studiensemester_kurzbz)) // else set next studiensemester as default value
{
$studiensemester = $this->StudiensemesterModel->getAktOrNextSemester(62);
$studiensemester = $this->StudiensemesterModel->getAktOrNextSemester();
if (hasData($studiensemester))
{
$studiensemester_kurzbz = $studiensemester->retval[0]->studiensemester_kurzbz;
-212
View File
@@ -1,212 +0,0 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Phrases extends Auth_Controller
{
/**
*
*/
public function __construct()
{
parent::__construct(
array(
'index' => 'system/phrase:r',
'table' => 'system/phrase:r',
'view' => 'system/phrase:r',
'deltext' => 'system/phrase:rw',
'edit' => 'system/phrase:rw',
'save' => 'system/phrase:rw',
'newText' => 'system/phrase:rw',
'editText' => 'system/phrase:rw',
'saveText' => 'system/phrase:rw'
)
);
// Loads the phrases library
$this->load->library('PhrasesLib');
// Loads the widget library
$this->load->library('WidgetLib');
}
/**
*
*/
public function index()
{
$this->load->view('system/phrases/phrases.php');
}
/**
*
*/
public function table()
{
$phrases = $this->phraseslib->getPhraseByApp('aufnahme');
if ($phrases->error)
show_error(getError($phrases));
$data = array(
'app' => 'aufnahme',
'phrases' => $phrases->retval
);
$this->load->view('system/phrases/phrasesList.php', $data);
}
/**
*
*/
public function view($phrase_id)
{
if (!is_numeric($phrase_id))
show_error('Invalid phrase_id parameter');
$phrase = $this->phraseslib->getPhrase($phrase_id);
$phrase_inhalt = $this->phraseslib->getPhraseInhalt($phrase_id);
if ($phrase_inhalt->error)
show_error(getError($phrase_inhalt));
$data = array(
'phrase_id' => $phrase_id,
'phrase' => $phrase->retval[0]->phrase,
'phrase_inhalt' => $phrase_inhalt->retval
);
$this->load->view('system/phrases/phrasesinhaltList.php', $data);
}
/**
*
*/
public function deltext($phrasentext_id, $phrase_id)
{
if (!is_numeric($phrasentext_id) || !is_numeric($phrase_id))
show_error('Invalid phrasentext_id or phrase_id parameter');
$phrase_inhalt = $this->phraseslib->delPhrasentext($phrasentext_id);
if ($phrase_inhalt->error)
show_error(getError($phrase_inhalt));
redirect('/system/Phrases/view/'.$phrase_id);
}
/**
*
*/
public function edit($phrase_id = null)
{
if (!is_numeric($phrase_id)) return;
$phrase = $this->phraseslib->getPhrase($phrase_id);
if ($phrase->error)
show_error(getError($phrase));
if (count($phrase->retval) != 1)
show_error('Phrase nicht vorhanden! ID: '.$phrase_id);
$data = array(
'phrase' => $phrase->retval[0]
);
$this->load->view('system/phrases/phrasesEdit', $data);
}
/**
*
*/
public function save()
{
$phrase_id = $this->input->post('phrase_id');
$data = array('phrase' => $this->input->post('phrase'));
$phrase = $this->phraseslib->savePhrase($phrase_id, $data);
if ($phrase->error)
show_error(getError($phrase));
$phrase_id = $phrase->retval;
redirect('/system/Phrases/edit/'.$phrase_id);
}
/**
*
*/
public function newText()
{
$phrase_id = $this->input->post('phrase_id');
$this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
$this->OrganisationseinheitModel->addLimit(1);
$this->OrganisationseinheitModel->addOrder('oe_kurzbz');
$resultOE = $this->OrganisationseinheitModel->loadWhere(array('aktiv' => true, 'oe_parent_kurzbz' => null));
if ($resultOE->error)
show_error(getError($resultOE));
if (hasData($resultOE))
{
$orgeinheit_kurzbz = $resultOE->retval[0]->oe_kurzbz;
$data = array(
'phrase_id' => $phrase_id,
'sprache' => 'German',
'text' => '',
'description' => '',
'orgeinheit_kurzbz' => $orgeinheit_kurzbz
);
$phrase_inhalt = $this->phraseslib->insertPhraseinhalt($data);
if ($phrase_inhalt->error)
show_error(getError($phrase_inhalt));
$phrase_inhalt_id = $phrase_inhalt->retval;
redirect('/system/Phrases/editText/'.$phrase_inhalt_id);
}
else
{
show_error('No valid organisation unit found');
}
}
/**
*
*/
public function editText($phrasentext_id)
{
$phrase_inhalt = $this->phraseslib->getPhrasentextById($phrasentext_id);
if ($phrase_inhalt->error)
show_error(getError($phrase_inhalt));
$data = $phrase_inhalt->retval[0];
$this->load->view('system/phrases/phraseinhaltEdit', $data);
}
/**
*
*/
public function saveText()
{
$phrase_inhalt_id = $this->input->post('phrase_inhalt_id');
$data = array(
'orgeinheit_kurzbz' => $this->input->post('oe_kurzbz'),
'orgform_kurzbz' => $this->input->post('orgform_kurzbz'),
'text' => $this->input->post('text'),
'description' => $this->input->post('description'),
'sprache' => $this->input->post('sprache')
);
$phrase_inhalt = $this->phraseslib->updatePhraseInhalt($phrase_inhalt_id, $data);
if ($phrase_inhalt->error)
show_error(getError($phrase_inhalt));
redirect('/system/Phrases/editText/'.$phrase_inhalt_id);
}
}
@@ -11,8 +11,8 @@ class CLI_Manager extends CLI_Controller
*
*/
public function __construct()
{
parent::__construct();
{
parent::__construct();
// Load helpers to upload files
$this->load->helper('form');
@@ -28,9 +28,19 @@ class CLI_Manager extends CLI_Controller
* die Commandline ohne Upload durchzufuehren.
* @param $extensioName string Name der Extension
* @param $filename Url Encoded Pfad zum tgz File der Extension
* @param $perform_sql boolean ob die SQL Befehle ausgeführt werden
*/
public function uploadExtension($extensionName = null, $filename = null)
public function installExtension($extensionName, $filename)
{
$this->extensionslib->installExtension($extensionName, urldecode($filename));
$this->extensionslib->installExtension($extensionName, urldecode($filename), true);
}
/**
* Install an extension, same as installExtension but without running the SQL statements
*/
public function installExtensionNoSQL($extensionName, $filename)
{
$this->extensionslib->installExtension($extensionName, urldecode($filename), false);
}
}
@@ -11,8 +11,8 @@ class Manager extends Auth_Controller
*
*/
public function __construct()
{
parent::__construct(
{
parent::__construct(
array(
'index' => 'system/extensions:r',
'toggleExtension' => 'system/extensions:rw',
@@ -21,11 +21,22 @@ class Manager extends Auth_Controller
)
);
// Load helpers to upload files
// Loads the form helper
$this->load->helper('form');
// Loads WidgetLib
$this->load->library('WidgetLib');
// Loads the extensions library
$this->load->library('ExtensionsLib');
$this->loadPhrases(
array(
'extensions',
'table',
'ui'
)
);
}
/**
@@ -33,11 +44,7 @@ class Manager extends Auth_Controller
*/
public function index()
{
$viewData = array(
'extensions' => $this->extensionslib->getInstalledExtensions()
);
$this->load->view('system/extensions/manager.php', $viewData);
$this->load->view('system/extensions/manager.php');
}
/**
@@ -45,23 +52,16 @@ class Manager extends Auth_Controller
*/
public function toggleExtension()
{
$toggleExtension = false;
$extension_id = $this->input->post('extension_id');
$enabled = $this->input->post('enabled');
if ($enabled === 'true')
{
$toggleExtension = $this->extensionslib->enableExtension($extension_id);
}
else
{
$toggleExtension = $this->extensionslib->disableExtension($extension_id);
}
// Clean the parameter
$enabled = $enabled == 'true' ? true : false;
$this->output
->set_content_type('application/json')
->set_output(json_encode($toggleExtension));
// Output the enable/disable of the extension
$this->outputJsonSuccess(
$this->extensionslib->toggleExtension($extension_id, $enabled)
);
}
/**
@@ -69,15 +69,11 @@ class Manager extends Auth_Controller
*/
public function delExtension()
{
$delExtension = false;
$extension_id = $this->input->post('extension_id');
$delExtension = $this->extensionslib->delExtension($extension_id);
$this->output
->set_content_type('application/json')
->set_output(json_encode($delExtension));
$this->outputJsonSuccess($delExtension);
}
/**
@@ -87,9 +83,16 @@ class Manager extends Auth_Controller
* die Commandline ohne Upload durchzufuehren.
* @param $extensioName string Name der Extension
* @param $filename Url Encoded Pfad zum tgz File der Extension
* @param $perform_sql boolean ob die SQL Befehle ausgeführt werden
*/
public function uploadExtension($extensionName = null, $filename = null)
public function uploadExtension()
{
$this->extensionslib->installExtension($extensionName, urldecode($filename));
$notPerformSql = $this->input->post('notPerformSql');
// It converts the notPerformSql parameter from the checkbox value to a boolean one
if ($notPerformSql == 'on') $notPerformSql = true;
if ($notPerformSql !== true) $notPerformSql = false;
$this->extensionslib->installExtension(null, null, !$notPerformSql);
}
}
@@ -0,0 +1,50 @@
<?php
/**
* Copyright (C) 2024 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (!defined("BASEPATH")) exit("No direct script access allowed");
class CLI_Manager extends CLI_Controller
{
/**
*
*/
public function __construct()
{
parent::__construct();
// Loads PhrasesLib
$this->load->library('PhrasesLib');
}
/**
*
*/
public function installFrom($phrasesDirectoryPath)
{
$this->phraseslib->installFrom(urldecode($phrasesDirectoryPath));
}
/**
* Calls the PhrasesLib->syncFiles to create/update the phrases files under the directory application/phrases/
*/
public function syncFiles()
{
$this->phraseslib->syncFiles();
}
}
@@ -0,0 +1,30 @@
<?php
if (!defined("BASEPATH")) exit("No direct script access allowed");
class Manager extends Auth_Controller
{
/**
*
*/
public function __construct()
{
parent::__construct(
array(
'installFromCore' => 'admin:rw'
)
);
// Loads PhrasesLib
$this->load->library('PhrasesLib');
}
/**
*
*/
public function installFromCore()
{
$this->phraseslib->installFromCore();
}
}
@@ -0,0 +1,45 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Overview on cronjob logs
*/
class PhrasesViewer extends Auth_Controller
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
array(
'index' => 'system/developer:r'
)
);
// Loads WidgetLib
$this->load->library('WidgetLib');
// Loads phrases system
$this->loadPhrases(
array(
'global',
'ui',
'filter'
)
);
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* Everything has a beginning
*/
public function index()
{
$this->load->view('system/phrases/phrasesViewer.php');
}
}
+1 -1
View File
@@ -35,7 +35,7 @@ class CI3_Events
});
self::$eventsSorted[$event] = true;
}
foreach (self::$events[$event] as $conf) {
$conf[1](...$args);
}
+46 -61
View File
@@ -8,7 +8,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller
{
const DEFAULT_PERMISSION_R = 'admin:r';
const DEFAULT_PERMISSION_RW = 'admin:rw';
//public function __construct($zuordnung = 'person/Notizzuordnung_model')
public function __construct($permissions)
{
$default_permissions = [
@@ -97,13 +97,13 @@ abstract class Notiz_Controller extends FHCAPI_Controller
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
return $this->terminateWithSuccess(getData($result) ?: []);
$this->terminateWithSuccess(getData($result) ?: []);
}
//Override function
protected function isBerechtigt($id, $typeId){
return $this->terminateWithError("in abstract function: define right in extension", self::ERROR_TYPE_GENERAL);
$this->terminateWithError("in abstract function: define right in extension", self::ERROR_TYPE_GENERAL);
}
public function loadNotiz()
@@ -112,7 +112,6 @@ abstract class Notiz_Controller extends FHCAPI_Controller
$notiz_id = $this->input->post('notiz_id');
//$this->load->model('person/Notiz_model', 'NotizModel');
$this->NotizModel->addJoin('public.tbl_notiz_dokument', 'notiz_id', 'LEFT');
$this->NotizModel->addSelect('*');
$this->NotizModel->addSelect("TO_CHAR(CASE WHEN public.tbl_notiz.updateamum >= public.tbl_notiz.insertamum
@@ -143,14 +142,9 @@ abstract class Notiz_Controller extends FHCAPI_Controller
$uid = getAuthUID();
if (isset($_POST['data']))
{
$data = json_decode($_POST['data']);
unset($_POST['data']);
foreach ($data as $k => $v) {
$_POST[$k] = $v;
}
}
$json = $this->input->post('data');
$post_data = json_decode($json, true);
$this->form_validation->set_data($post_data);
//Form Validation
$this->form_validation->set_rules('titel', 'Titel', 'required', [
@@ -166,26 +160,25 @@ abstract class Notiz_Controller extends FHCAPI_Controller
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$titel = $this->input->post('titel');
$text = $this->input->post('text');
$erledigt = $this->input->post('erledigt');
$verfasser_uid = isset($_POST['verfasser']) ? $_POST['verfasser'] : $uid;
$bearbeiter_uid = isset($_POST['bearbeiter']) ? $_POST['bearbeiter'] : null;
$type = $this->input->post('typeId');
$start = $this->input->post('start');
$ende = $this->input->post('ende');
$titel = $post_data['titel'];
$text = $post_data['text'];
$erledigt = $post_data['erledigt'];
$bearbeiter_uid = isset($post_data['bearbeiter']) ? $post_data['bearbeiter'] : null;
$type = $post_data['typeId'];
$start = isset($post_data['start']) ? $post_data['start'] : null;
$ende = isset($post_data['ende']) ? $post_data['ende'] : null;
// Start DB transaction
$this->db->trans_start();
//Save note
$result = $this->NotizModel->insert(array('titel' => $titel, 'text' => $text, 'erledigt' => $erledigt, 'verfasser_uid' => $verfasser_uid,
"insertvon" => $verfasser_uid, 'start' => $start, 'ende' => $ende, 'bearbeiter_uid' => $bearbeiter_uid));
$result = $this->NotizModel->insert(array('titel' => $titel, 'text' => $text, 'erledigt' => $erledigt, 'verfasser_uid' => $uid,
"insertvon" => $uid, 'start' => $start, 'ende' => $ende, 'bearbeiter_uid' => $bearbeiter_uid));
if (isError($result))
{
$this->db->trans_rollback();
return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
$notiz_id = $result->retval;
@@ -220,7 +213,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller
if (isError($result))
{
$this->db->trans_rollback();
return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
$dms_id_arr[] = $result->retval['dms_id'];
}
@@ -235,34 +228,28 @@ abstract class Notiz_Controller extends FHCAPI_Controller
if (isError($result))
{
$this->db->trans_rollback();
return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
}
}
$this->db->trans_commit();
return $this->terminateWithSuccess($result);
$this->terminateWithSuccess($result);
}
public function updateNotiz()
{
$this->load->library('form_validation');
$this->load->library('DmsLib');
if (isset($_POST['data']))
{
$data = json_decode($_POST['data']);
unset($_POST['data']);
foreach ($data as $k => $v) {
$_POST[$k] = $v;
}
}
$json = $this->input->post('data');
$post_data = json_decode($json, true);
$notiz_id = $this->input->post('notiz_id');
$this->form_validation->set_data($post_data);
if(!$notiz_id)
{
$this->terminateWithError($this->p->t('ui','error_missingId',['id'=>'Notiz_id']), self::ERROR_TYPE_GENERAL);
}
$this->form_validation->set_rules('notiz_id', 'Notiz ID', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'notiz_id'])
]);
//Form Validation
$this->form_validation->set_rules('titel', 'Titel', 'required', [
@@ -280,25 +267,23 @@ abstract class Notiz_Controller extends FHCAPI_Controller
//update Notiz
$uid = getAuthUID();
$titel = $this->input->post('titel');
$text = $this->input->post('text');
$verfasser_uid = isset($_POST['verfasser']) ? $_POST['verfasser'] : $uid;
$bearbeiter_uid = isset($_POST['bearbeiter']) ? $_POST['bearbeiter'] : $uid;
$erledigt = $this->input->post('erledigt');
$start = $this->input->post('start');
$ende = $this->input->post('ende');
$titel = $post_data['titel'];
$text = $post_data['text'];
$bearbeiter_uid = isset($post_data['bearbeiter']) ? $post_data['bearbeiter'] : $post_data['bearbeiter_uid'];
$erledigt = $post_data['erledigt'];
$start = $post_data['start'];
$ende = $post_data['ende'];
$result = $this->NotizModel->update(
[
'notiz_id' => $notiz_id
'notiz_id' => $post_data['notiz_id'],
],
[
'titel' => $titel,
'updatevon' => $uid,
'updateamum' => date('c'),
'text' => $text,
'verfasser_uid' => $verfasser_uid,
'bearbeiter_uid' => $bearbeiter_uid,
'bearbeiter_uid' => isEmptyString($bearbeiter_uid) ? null : $bearbeiter_uid,
'start' => $start,
'ende' => $ende,
'erledigt' => $erledigt
@@ -306,7 +291,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller
);
if (isError($result))
{
return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
//update(1) loading all dms-entries with this notiz_id
@@ -314,7 +299,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller
$this->load->model('person/Notizdokument_model', 'NotizdokumentModel');
$this->NotizdokumentModel->addJoin('campus.tbl_dms_version', 'dms_id');
$result = $this->NotizdokumentModel->loadWhere(array('notiz_id' => $notiz_id));
$result = $this->NotizdokumentModel->loadWhere(array('notiz_id' => $post_data['notiz_id']));
$result = $this->getDataOrTerminateWithError($result);
foreach ($result as $doc) {
$dms_id_arr[$doc->dms_id] = array(
@@ -351,7 +336,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller
$result = $this->getDataOrTerminateWithError($result);
$dms_id = $result['dms_id'];
$result = $this->NotizdokumentModel->insert(array('notiz_id' => $notiz_id, 'dms_id' => $dms_id));
$result = $this->NotizdokumentModel->insert(array('notiz_id' => $post_data['notiz_id'], 'dms_id' => $dms_id));
$this->getDataOrTerminateWithError($result);
}
@@ -365,7 +350,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller
$this->getDataOrTerminateWithError($result);
}
return $this->terminateWithSuccess($result);
$this->terminateWithSuccess($result);
}
public function deleteNotiz()
@@ -416,15 +401,15 @@ abstract class Notiz_Controller extends FHCAPI_Controller
if (isError($result))
{
$this->db->trans_rollback();
return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
if(!hasData($result))
{
return $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL);
$this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL);
}
$this->db->trans_complete();
return $this->terminateWithSuccess(getData($result));
$this->terminateWithSuccess(getData($result));
}
public function loadDokumente()
@@ -440,14 +425,14 @@ abstract class Notiz_Controller extends FHCAPI_Controller
array('public.tbl_notiz.notiz_id' => $notiz_id)
);
if (isError($result)) {
return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
if(!hasData($result))
{
return $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL);
$this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL);
}
return $this->terminateWithSuccess(getData($result));
$this->terminateWithSuccess(getData($result));
}
public function getMitarbeiter($searchString)
@@ -457,7 +442,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller
if (isError($result)) {
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
return $this->terminateWithSuccess($result);
$this->terminateWithSuccess($result);
}
public function getCountNotes($person_id)
@@ -476,4 +461,4 @@ abstract class Notiz_Controller extends FHCAPI_Controller
return $this->terminateWithSuccess($anzahl->anzahl ?: 0);
}
}
}
+3 -18
View File
@@ -91,7 +91,7 @@ function var_dump_to_error_log($parameter)
var_dump($parameter); // KEEP IT!!!
$ob_get_contents = ob_get_contents();
ob_end_clean();
error_log(str_replace("\n", '', $ob_get_contents)); // KEEP IT!!!
error_log(str_replace("\n", '', $ob_get_contents) . ', referer: ' . "http".(!empty($_SERVER['HTTPS'])?"s":"")."://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']); // KEEP IT!!!
}
/**
@@ -408,22 +408,6 @@ function findResource($path, $resource, $subdir = false, $extraDir = null)
return null;
}
/**
* check if String can be converted to a date
*/
function isValidDate($dateString)
{
try
{
return (new DateTime($dateString)) !== false;
}
catch(Exception $e)
{
return false;
}
}
// ------------------------------------------------------------------------
// PHP functions that don't exist in older versions
// ------------------------------------------------------------------------
@@ -446,7 +430,8 @@ if (!function_exists('array_is_list')) {
// ------------------------------------------------------------------------
/**
* check if string can be converted to a date
* Check if the provided parameter is a string containing a valid date
* NOTE: the name is in the "snake case" format because othewise the CI form validation _cannot_ use it
*/
function is_valid_date($dateString)
{
+214 -14
View File
@@ -1,20 +1,20 @@
<?php
/**
* FH-Complete
* Copyright (C) 2025 FH Technikum-Wien
*
* @package FHC-Helper
* @author FHC-Team
* @copyright Copyright (c) 2016 fhcomplete.org
* @license GPLv3
* @since Version 1.0.0
*/
/**
* FHC Helper
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* @subpackage Helpers
* @category Helpers
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
@@ -136,7 +136,7 @@ function generateJSPhrasesStorageObject($phrases)
$toPrint = "\n";
$toPrint .= '<script type="text/javascript">';
$toPrint .= "\n";
$toPrint .= ' var FHC_JS_PHRASES_STORAGE_OBJECT = '.$ci->pj->getJSON().';';
$toPrint .= ' var FHC_JS_PHRASES_STORAGE_OBJECT = '.$ci->pj->toJSON().';';
$toPrint .= "\n";
$toPrint .= '</script>';
$toPrint .= "\n\n";
@@ -255,6 +255,9 @@ function generateSkipLink($skipID)
echo $toPrint;
}
/**
*
*/
function absoluteJsImportUrl($relurl)
{
$ci =& get_instance();
@@ -269,3 +272,200 @@ function absoluteJsImportUrl($relurl)
}
return $url;
}
/*
* Manipulate CI views includes Array to load
* - public/js/FhcApps.js via customJSs and
* - app customisation js and/or css from extensions via customJSModules
* if customJSModules contains at least one vuejs app and customisation files
* exist in extensions
*/
class ExtendableAppsHelper
{
private static $instance = null;
protected $extensions;
protected $customCSSs;
protected $customJSs;
protected $customJSModules;
protected $initialised;
protected $appscount;
protected $extCustomCSSs;
protected $extCustomJSs;
protected $extCustomJSModules;
private function __construct()
{
$this->extensions = array();
$this->customCSSs = null;
$this->customJSs = null;
$this->customJSModules = null;
$this->initialised = false;
$this->appscount = 0;
$this->extCustomCSSs = null;
$this->extCustomJSs = null;
$this->extCustomJSModules = null;
}
public static function getInstance()
{
if(self::$instance === null)
{
self::$instance = new ExtendableAppsHelper();
}
return self::$instance;
}
public function init($customCSSs, $customJSs, $customJSModules)
{
if($this->initialised)
{
return;
}
$this->customCSSs = $customCSSs;
$this->customJSs = $customJSs;
$this->customJSModules = $customJSModules;
$this->initialised = true;
if(!isset($this->customJSModules))
{
return;
}
if(!is_array($this->customJSModules))
{
$this->customJSModules = array($this->customJSModules);
}
if(count($this->customJSModules) < 1)
{
return;
}
$this->buildExtensionsList();
$this->prepareExtendedArrays();
}
public function getCustomCSSs()
{
if(is_null($this->extCustomCSSs))
{
return $this->customCSSs;
}
return $this->extCustomCSSs;
}
public function getCustomJSs()
{
if(is_null($this->extCustomJSs))
{
return $this->customJSs;
}
return $this->extCustomJSs;
}
public function getCustomJSModules()
{
if(is_null($this->extCustomJSModules))
{
return $this->customJSModules;
}
return $this->extCustomJSModules;
}
protected function buildExtensionsList()
{
$this->extensions = array();
$fsiterator = new FilesystemIterator(FHCPATH . 'application/extensions');
foreach ($fsiterator as $fsitem)
{
if(preg_match('/^FHC-Core-/', $fsitem->getBasename()))
{
$this->extensions[] = $fsitem->getBasename();
}
}
}
protected function prepareExtendedArrays()
{
$this->appscount = 0;
$this->initExtCustomCSSs();
$this->extCustomJSModules = array();
foreach($this->customJSModules as $item)
{
$matches = array();
if(preg_match('#^public/(extensions/FHC-Core-.+)?js/apps/(.*)\.js$#', $item, $matches))
{
$this->appscount++;
$fhcextension = $matches[1];
$app = $matches[2];
$extend_js_suffix = 'js/extend_app/' . $fhcextension . $app . '.js';
$extend_css_suffix = 'css/extend_app/' . $fhcextension . $app . '.css';
foreach($this->extensions as $extension)
{
$extend_js = 'public/extensions/' . $extension . '/' . $extend_js_suffix;
$extend_css = 'public/extensions/' . $extension . '/' . $extend_css_suffix;
if(is_readable(FHCPATH . $extend_js))
{
array_push($this->extCustomJSModules, $extend_js);
}
if(is_readable(FHCPATH . $extend_css))
{
array_push($this->extCustomCSSs, $extend_css);
}
}
}
array_push($this->extCustomJSModules, $item);
}
if($this->appscount > 0)
{
$this->addFhcAppsJs();
}
}
protected function initExtCustomCSSs()
{
if(!isset($this->customCSSs))
{
$this->extCustomCSSs = array();
}
elseif(!is_array($this->customCSSs))
{
$this->extCustomCSSs = array($this->customCSSs);
}
else
{
$this->extCustomCSSs = $this->customCSSs;
}
}
protected function addFhcAppsJs()
{
if(!isset($this->customJSs))
{
$this->extCustomJSs = array();
}
elseif(!is_array($this->customJSs))
{
$this->extCustomJSs = array($this->customJSs);
}
else
{
$this->extCustomJSs = $this->customJSs;
}
array_push($this->extCustomJSs, 'public/js/FhcApps.js');
}
}
+1 -1
View File
@@ -128,7 +128,7 @@ class AntragLib
return $this->_ci->StudierendenantragstatusModel->resumeAntraegeForAbmeldungStgl($antrag_id);
}
// NOTE(chris): get last status that is not pause
$this->_ci->StudierendenantragstatusModel->addOrder('insertamum');
$this->_ci->StudierendenantragstatusModel->addOrder('insertamum', 'DESC');
$this->_ci->StudierendenantragstatusModel->addLimit(1);
$result = $this->_ci->StudierendenantragstatusModel->loadWhere([
'studierendenantrag_id' => $antrag_id,
+2 -1
View File
@@ -180,7 +180,8 @@ class DocsboxLib
}
// Just started or still working on it
elseif ($getStatusResponse->body->status == self::STATUS_WORKING
|| $getStatusResponse->body->status == self::STATUS_STARTED)
|| $getStatusResponse->body->status == self::STATUS_STARTED
|| $getStatusResponse->body->status == self::STATUS_QUEUED)
{
// go on!
}
+256 -168
View File
@@ -1,6 +1,6 @@
<?php
/**
* Copyright (C) 2022 fhcomplete.org
* Copyright (C) 2025 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \stdClass as stdClass;
use \PharData as PharData;
/**
* Library to manage core extensions
@@ -33,11 +34,20 @@ class ExtensionsLib
const EXTENSION_JSON_NAME = 'extension.json'; // file that contains extension data
const EXTENSIONS_DIR_NAME = 'extensions'; // name of the directories where will be created the symlinks
private $_ci;
const PHRASES_DIRECTORY = 'phrases/'; // directory name where phrases files are
private $ARCHIVE_EXTENSIONS = array('.tgz', '.tbz2'); // accepted file extensions for an uploaded extension
private $UPLOAD_PATH; // temporary directory to store the upload file and checks the archive
private $EXTENSIONS_PATH; // directory where all the extensions are
const UPLOAD_PATH = 'tmp/';
private $_ci; // Code igniter instance
private $_errorOccurred; // boolean, true if an error occurred while installing an extension
private $_currentInstalledExtensionVersion; // contains the version of the current installation of an extension
// NOTE: the following have been declared as properties to maintain compatibility with previous PHP versions
// where arrays cannot be declared as constants
// Accepted file extensions for an uploaded extension
private $ARCHIVE_EXTENSIONS = array('.tgz', '.tbz2');
// Directories that are part of the extension archive
private $SOFTLINK_TARGET_DIRECTORIES = array(
@@ -45,16 +55,11 @@ class ExtensionsLib
DOC_ROOT => array('public')
);
private $_errorOccurred; // boolean, true if an error occurred while installing an extension
private $_currentInstalledExtensionVersion; // contains the version of the current installation of an extension
/**
* Class constructor
*/
public function __construct()
{
$this->UPLOAD_PATH = APPPATH.'tmp/';
$this->EXTENSIONS_PATH = APPPATH.'extensions/';
// Get code igniter instance
$this->_ci =& get_instance();
@@ -63,6 +68,8 @@ class ExtensionsLib
// Loads EPrintfLib
$this->_ci->load->library('EPrintfLib');
// Loads PhrasesLib
$this->_ci->load->library('PhrasesLib');
// Loading models
$this->_ci->load->model('system/Extensions_model', 'ExtensionsModel');
@@ -70,6 +77,13 @@ class ExtensionsLib
// Set default values fot class properties
$this->_errorOccurred = false;
$this->_currentInstalledExtensionVersion = 0;
// If SERVER_NAME is _not_ declared or it is an empty string
if (!defined('SERVER_NAME') || (defined('SERVER_NAME') && isEmptyString(SERVER_NAME)))
{
$this->_printError('Global constant SERVER_NAME is not declared or it is not valid');
exit();
}
}
// -------------------------------------------------------------------------------------------------
@@ -82,32 +96,44 @@ class ExtensionsLib
* @param $extensionName string Name of Extension (optional)
* @param $filename Path to tgz Extension File (optional)
*/
public function installExtension($extensionName = null, $filename = null)
public function installExtension($extensionName, $filename, $perform_sql)
{
$extensionDB = null; // contains data from DB about an extension
$extensionJson = null; // contains the extension.json data
$this->_printInfo('WARNING!!! Please do not change page or stop this procedure before it is finished');
if (!is_null($extensionName) && !is_null($filename))
{
$uploadData = new stdClass();
$uploadData->fullPath = $filename;
$uploadData->extensionName = $extensionName;
}
else
// Create an object with the given paramenters
$uploadData = new stdClass();
$uploadData->fullPath = $filename;
$uploadData->extensionName = $extensionName;
// If no extension name or file name are provided
if (is_null($extensionName) || is_null($filename))
{
$this->_loadUploadLibrary(); // loads CI upload library
$uploadData = $this->_uploadExtension(); // perform the upload of the file and returns info about it
}
if ($uploadData != null) // if no error occurred
// If a file has been uploaded
if (isset($uploadData))
{
// If the given filename is the upper directory or the current one
if (trim($uploadData->fullPath) == '..' || trim($uploadData->fullPath) == '.')
{
$this->_printFailure('wrong file name: / has to be escaped with %2F');
$uploadData = null; // then it is a wrong one!
}
}
// If the no error occurred
if ($uploadData != null)
{
$this->_extractExtension($uploadData->fullPath); // extract the archive of the uploaded extension
if (!$this->_errorOccurred) // if no error occurred
{
// Retives data about any previous installation of this extension
// Retrieves data about any previous installation of this extension on this server
$extensionDB = $this->_loadPreviousInstallation($uploadData->extensionName);
}
@@ -128,15 +154,17 @@ class ExtensionsLib
$this->_printStart('Proceding with the installation of the extension: '.$extensionJson->name);
$this->_printEnd();
$this->_cleanPreviousInstallation($extensionJson); // cleans any previous installation
// Remove any previous installation from file system and database
$this->_cleanPreviousInstallation($extensionJson);
$this->_installExtension($extensionJson); // records extension data in DB
// Records extension data in DB
$this->_installExtension($extensionJson);
if (!$this->_errorOccurred) // if no error occurred
if (!$this->_errorOccurred && $perform_sql === true) // if no error occurred
{
// Loads and executes neede SQL scripts
// Loads and executes the needed SQL scripts
$this->_loadSQLs(
$this->UPLOAD_PATH.$extensionJson->name.'/'.ExtensionsLib::SQL_DIRECTORY,
$this->_getUploadPath().$extensionJson->name.DIRECTORY_SEPARATOR.ExtensionsLib::SQL_DIRECTORY,
$extensionJson
);
}
@@ -152,20 +180,19 @@ class ExtensionsLib
// Create the symlinks to the installed extension
$this->_createSymLinks($extensionJson->name);
}
if (!$this->_errorOccurred) // if no error occurred
{
// Create the symlinks to the installed extension
$this->_installPhrases($extensionJson->name);
}
}
else
{
$this->_errorOccurred = true;
}
}
else
{
$this->_errorOccurred = true;
}
if ($this->_errorOccurred === false) // if no errors occurred
{
if (!$this->_rrm($uploadData->fullPath)) // removes uploaded file
// If a file has been uploaded then remove them
if (isset($uploadData) && !$this->_rrm($uploadData->fullPath))
{
$this->_printInfo('Error while cleaning upload directory. Not a blocking error');
}
@@ -191,19 +218,26 @@ class ExtensionsLib
$result = $this->_ci->ExtensionsModel->load($extensionId);
if (hasData($result)) // if something was found
{
$extensionName = $result->retval[0]->name; // extension name
$this->_delSoftLinks($extensionName); // not to be checked, could fail if the extension is disabled
// remove the extension from the extensions installation directory
$delExtension = $this->_rrm($this->EXTENSIONS_PATH.$extensionName);
// If this server is _not_ the same where the extension was installed then exit with a failure
if (getData($result)[0]->server_kurzbz != SERVER_NAME) return false;
$extensionName = getData($result)[0]->name; // extension name
// Not to be checked, could fail if the extension is disabled
$this->_delSoftLinks($extensionName);
// Remove the extension from the extensions installation directory
$delExtension = $this->_rrm($this->_getExtensionsPath().$extensionName);
// Select all the version of this extension
$this->_ci->ExtensionsModel->addSelect('extension_id');
$result = $this->_ci->ExtensionsModel->loadWhere(array('name' => $extensionName));
$result = $this->_ci->ExtensionsModel->loadWhere(array('name' => $extensionName, 'server_kurzbz' => SERVER_NAME));
// If something was found
if (hasData($result))
{
// Loops on them
foreach ($result->retval as $extension)
foreach (getData($result) as $extension) // loops on them
{
// Remove them all
$result = $this->_ci->ExtensionsModel->delete($extension->extension_id);
@@ -220,23 +254,57 @@ class ExtensionsLib
*/
public function getInstalledExtensions()
{
return $this->_ci->ExtensionsModel->getInstalledExtensions();
$this->_ci->ExtensionsModel->addOrder('name', 'ASC');
$this->_ci->ExtensionsModel->addOrder('server_kurzbz', 'ASC');
$this->_ci->ExtensionsModel->addOrder('version', 'ASC');
return $this->_ci->ExtensionsModel->loadWhere(array('server_kurzbz' => SERVER_NAME));
}
/**
* To enable an extension
* To enable/disable an extension
*/
public function enableExtension($extensionId)
public function toggleExtension($extensionId, $enabled)
{
return $this->_toggleExtension($extensionId, true);
}
$_toggleExtension = false;
/**
* To disable an extension
*/
public function disableExtension($extensionId)
{
return $this->_toggleExtension($extensionId, false);
// Loads data from DB about the given extension
$result = $this->_ci->ExtensionsModel->load($extensionId);
if (hasData($result))
{
// If this server is _not_ the same where the extension was installed then exit with a failure
if (getData($result)[0]->server_kurzbz != SERVER_NAME) return false;
$extensionName = getData($result)[0]->name; // extension name
// If to be enabled
if ($enabled === true)
{
// Add the symlinks
$_toggleExtension = $this->_addSoftLinks($extensionName);
}
else // If to be disabled
{
// Remove all the symlinks
$_toggleExtension = $this->_delSoftLinks($extensionName);
}
if ($_toggleExtension) // if is a success
{
// Updates DB
$result = $this->_ci->ExtensionsModel->update($extensionId, array('enabled' => $enabled));
if (isSuccess($result))
{
$_toggleExtension = true;
}
else // if DB update fails remove symlinks from file system
{
$this->_delSoftLinks($extensionName);
}
}
}
return $_toggleExtension;
}
// -------------------------------------------------------------------------------------------------
@@ -250,7 +318,7 @@ class ExtensionsLib
$this->_ci->load->library(
'upload',
array(
'upload_path' => $this->UPLOAD_PATH,
'upload_path' => $this->_getUploadPath(),
'allowed_types' => '*',
'overwrite' => true
)
@@ -314,7 +382,7 @@ class ExtensionsLib
// Extracts the uploaded file
$pd = new PharData($uploadPath);
$pd->extractTo($this->UPLOAD_PATH, null, true);
$pd->extractTo($this->_getUploadPath(), null, true);
}
catch (UnexpectedValueException $uva)
{
@@ -322,6 +390,16 @@ class ExtensionsLib
$this->_printFailure('provided an invalid archive');
}
catch (PharException $pe)
{
$this->_errorOccurred = true;
$this->_printFailure('phar error occurred');
}
catch (InvalidArgumentException $iae)
{
$this->_errorOccurred = true;
$this->_printFailure('wrong file name');
}
catch (Exception $e)
{
$this->_errorOccurred = true;
$this->_printFailure('generic error occurred, check logs');
@@ -344,24 +422,29 @@ class ExtensionsLib
// Loads the last version of the previous installation of this extension
$this->_ci->ExtensionsModel->addOrder('version', 'DESC');
$this->_ci->ExtensionsModel->addLimit(1);
$result = $this->_ci->ExtensionsModel->loadWhere(array('name' => $extensionName));
// Loads extensions installed on this server
$result = $this->_ci->ExtensionsModel->loadWhere(
array(
'name' => $extensionName,
'server_kurzbz' => SERVER_NAME
)
);
// In an error occurred
if (isError($result))
{
$this->_errorOccurred = true;
$this->_printFailure('data base error: '.$result->retval);
$this->_printFailure('data base error: '.getData($result));
}
else
elseif (hasData($result))
{
if (hasData($result)) // if found
{
$extensionDB = $result->retval[0]; // return it!
}
else
{
$this->_printMessage('not found');
}
$extensionDB = getData($result)[0];
}
// If no data have been found
if ($extensionDB == null) $this->_printMessage('not found');
$this->_printSuccess(!$this->_errorOccurred);
$this->_printEnd();
@@ -377,10 +460,10 @@ class ExtensionsLib
$this->_printStart('Checking extension file system structure');
// Checks if the root directory of this archive has the same name of the extension
if (is_dir($this->UPLOAD_PATH.$extensionName))
if (is_dir($this->_getUploadPath().$extensionName))
{
// Checks if file extension.json exists inside the uploaded archive
if (!file_exists($this->UPLOAD_PATH.$extensionName.'/'.ExtensionsLib::EXTENSION_JSON_NAME))
if (!file_exists($this->_getUploadPath().$extensionName.DIRECTORY_SEPARATOR.ExtensionsLib::EXTENSION_JSON_NAME))
{
$this->_errorOccurred = true;
$this->_printFailure('missing extension.json');
@@ -402,11 +485,14 @@ class ExtensionsLib
*/
private function _chkExtensionJson($extensionName, $extensionDB)
{
// Set a default FHComplete version
$fhcomplete_version = 0;
$this->_printStart('Parsing and checking extension.json');
// Decodes extension.json
$extensionJson = json_decode(
file_get_contents($this->UPLOAD_PATH.$extensionName.'/'.ExtensionsLib::EXTENSION_JSON_NAME)
file_get_contents($this->_getUploadPath().$extensionName.DIRECTORY_SEPARATOR.ExtensionsLib::EXTENSION_JSON_NAME)
);
// Checks if the parameter name of the extension.json has the same value of the extension name
@@ -416,36 +502,41 @@ class ExtensionsLib
if (isset($extensionJson->version))
{
$extensionJson->currentInstalledVersion = 0; // default current installed version of this extension
if ($extensionDB != null) // if no previous installation was found in DB
// If a previous installation was found in DB
if ($extensionDB != null)
{
// Then get the data from database
$extensionJson->extension_id = $extensionDB->extension_id; // get the extension_id from DB
$extensionJson->currentInstalledVersion = $extensionDB->version; // get the current installed version from DB
// Prompt a summary
$this->_printMessage('Extension already installed!');
$this->_printMessage('Current version: '.$extensionDB->version);
$this->_printMessage('Version of the uploaded extension: '.$extensionJson->version);
// Check if the version of the uploaded extension is the same
// as the one from the dataabase
if ($extensionJson->version == $extensionDB->version)
{
$this->_printMessage('Updating the same version!');
}
elseif ($extensionJson->version > $extensionDB->version)
elseif ($extensionJson->version > $extensionDB->version) // or it is higher
{
$this->_printMessage('Updating to a new version!');
}
else // downgrade is not possible
else // otherwise is lower, then the downgrade is not possible
{
$extensionJson = null;
$this->_printFailure('downgrade must be performed manually');
}
}
else
else // otherwise if it is not installed on this server
{
$this->_printMessage('Version of the uploaded extension: '.$extensionJson->version);
}
// If no errors occurred
// If no errors occurred then check the JSON file content within the uploaded extension
if ($extensionJson != null)
{
// Default value
@@ -454,7 +545,7 @@ class ExtensionsLib
require_once('version.php'); // get the core version
// Checks if the required core version of the extension is the same of this system
if (isset($extensionJson->core_version) && version_compare($extensionJson->core_version, $fhcomplete_version,'<='))
if (isset($extensionJson->core_version) && version_compare($extensionJson->core_version, $fhcomplete_version, '<='))
{
$this->_printMessage('Required core version: '.$extensionJson->core_version);
$this->_printMessage('Current core version: '.$fhcomplete_version);
@@ -467,7 +558,7 @@ class ExtensionsLib
// Gets the required dependencies
$result = $this->_ci->ExtensionsModel->getDependencies($extensionJson->dependencies);
// If they are matcheds
if (hasData($result) && count($result->retval) == count($extensionJson->dependencies))
if (hasData($result) && count(getData($result)) == count($extensionJson->dependencies))
{
if (isset($extensionJson->dependencies))
{
@@ -562,6 +653,7 @@ class ExtensionsLib
{
$this->_printStart('Adding new entry in the DB');
// Insert into database the extension information
$result = $this->_ci->ExtensionsModel->insert(
array(
'name' => $extensionJson->name,
@@ -570,7 +662,8 @@ class ExtensionsLib
'license' => isset($extensionJson->license) ? $extensionJson->license : null,
'url' => isset($extensionJson->url) ? $extensionJson->url : null,
'core_version' => $extensionJson->core_version,
'dependencies' => isset($extensionJson->dependencies) ? $extensionJson->dependencies : null
'dependencies' => isset($extensionJson->dependencies) ? $extensionJson->dependencies : null,
'server_kurzbz' => SERVER_NAME
)
);
if (isSuccess($result))
@@ -606,14 +699,16 @@ class ExtensionsLib
// Loops through the versions
for ($sqlDir = $startVersion; $sqlDir <= $extensionJson->version; $sqlDir++)
{
// Gets all the SQL files in the directory having the same name of the version
$files = glob($pkgSQLsPath.DIRECTORY_SEPARATOR.$sqlDir.'/*'.ExtensionsLib::SQL_FILE_EXTENSION);
// If a directory with the same value of the version is present in the sql scripts directory
$files = glob($pkgSQLsPath.'/'.$sqlDir.'/*'.ExtensionsLib::SQL_FILE_EXTENSION);
if ($files != false)
{
{
// Loads every sql files
foreach ($files as $file)
{
$sql = file_get_contents($file); // gets the entire content of the file
$sql = file_get_contents($file); // gets the entire content of the file
$this->_printMessage('Executing query:');
$this->_printMessage($sql);
@@ -651,17 +746,20 @@ class ExtensionsLib
{
$this->_printStart('Moving the upload extension from upload folder to extension folder');
$this->_printMessage('Current extension directory: '.$this->UPLOAD_PATH.$extensionName);
$this->_printMessage('Directory where it will be moved: '.$this->EXTENSIONS_PATH.$extensionName);
$this->_printMessage('Current extension directory: '.$this->_getUploadPath().$extensionName);
$this->_printMessage('Directory where it will be moved: '.$this->_getExtensionsPath().$extensionName);
if (rename($this->UPLOAD_PATH.$extensionName.'/', $this->EXTENSIONS_PATH.$extensionName))
if (!file_exists($this->_getExtensionsPath().$extensionName))
{
$this->_printSuccess(true);
}
else
{
$this->_errorOccurred = true;
$this->_printFailure('error while moving');
if (rename($this->_getUploadPath().$extensionName.DIRECTORY_SEPARATOR, $this->_getExtensionsPath().$extensionName))
{
$this->_printSuccess(true);
}
else
{
$this->_errorOccurred = true;
$this->_printFailure('error while moving');
}
}
$this->_printEnd();
@@ -695,13 +793,21 @@ class ExtensionsLib
{
$_delSoftLinks = false;
// For every set of target directories where:
// rootPath: is the prefix of the absolute path for the target directory
// targetDirectories: is an array of target directories
foreach ($this->SOFTLINK_TARGET_DIRECTORIES as $rootPath => $targetDirectories)
{
// For every target directory in the current set
foreach ($targetDirectories as $targetDirectory)
{
if (file_exists($rootPath.$targetDirectory.'/'.ExtensionsLib::EXTENSIONS_DIR_NAME.'/'.$extensionName))
// If the symlink exists
if (file_exists($rootPath.$targetDirectory.DIRECTORY_SEPARATOR.ExtensionsLib::EXTENSIONS_DIR_NAME.DIRECTORY_SEPARATOR.$extensionName))
{
$_delSoftLinks = unlink($rootPath.$targetDirectory.'/'.ExtensionsLib::EXTENSIONS_DIR_NAME.'/'.$extensionName);
// Try to delete it
$_delSoftLinks = unlink(
$rootPath.$targetDirectory.DIRECTORY_SEPARATOR.ExtensionsLib::EXTENSIONS_DIR_NAME.DIRECTORY_SEPARATOR.$extensionName
);
}
}
}
@@ -714,29 +820,23 @@ class ExtensionsLib
*/
private function _rrm($dir)
{
if (!file_exists($dir))
// If the directory does not exist return success
if (!file_exists($dir)) return true;
// If it is not a directory then delete it and return the result
if (!is_dir($dir)) return unlink($dir);
// For each subdirectory
foreach (scandir($dir) as $subdir)
{
return true;
}
if (!is_dir($dir))
{
return unlink($dir);
}
foreach (scandir($dir) as $item)
{
if ($item == '.' || $item == '..')
{
continue;
}
if (!$this->_rrm($dir.DIRECTORY_SEPARATOR.$item))
{
return false;
}
// If it is the same directory or the parent directory skip to the next one
if ($subdir == '.' || $subdir == '..') continue;
// Try to remove a subdirectory, if it fails then return a failure
if (!$this->_rrm($dir.DIRECTORY_SEPARATOR.$subdir)) return false;
}
// Delete the directory and return the result
return rmdir($dir);
}
@@ -746,27 +846,36 @@ class ExtensionsLib
private function _addSoftLinks($extensionName)
{
$_addSoftLinks = false;
$extensionPath = $this->EXTENSIONS_PATH.$extensionName.'/';
$extensionPath = $this->_getExtensionsPath().$extensionName.DIRECTORY_SEPARATOR;
// For every target directory
// For every set of target directories where:
// rootPath: is the prefix of the absolute path for the target directory
// targetDirectories: is an array of target directories
foreach ($this->SOFTLINK_TARGET_DIRECTORIES as $rootPath => $targetDirectories)
{
// For every target directory in the current set
foreach ($targetDirectories as $targetDirectory)
{
// If destination of the symlink does not exist
if (!file_exists($rootPath.$targetDirectory.'/'.ExtensionsLib::EXTENSIONS_DIR_NAME.'/'.$extensionName))
// Checks if the link already exists
$_addSoftLinks = file_exists(
$rootPath.$targetDirectory.DIRECTORY_SEPARATOR.ExtensionsLib::EXTENSIONS_DIR_NAME.DIRECTORY_SEPARATOR.$extensionName
);
// If the symlink does not exist
if (!$_addSoftLinks)
{
// If the target directory does not exist than creates that
if (!is_dir($extensionPath.$targetDirectory))
{
mkdir($extensionPath.$targetDirectory);
}
// If the target directory does not exist than creates it
if (!is_dir($extensionPath.$targetDirectory)) mkdir($extensionPath.$targetDirectory);
// Create the symlink
$_addSoftLinks = symlink(
$_addSoftLinks = @symlink(
// Target
$extensionPath.$targetDirectory,
$rootPath.$targetDirectory.'/'.ExtensionsLib::EXTENSIONS_DIR_NAME.'/'.$extensionName
// Link
$rootPath.$targetDirectory.DIRECTORY_SEPARATOR.ExtensionsLib::EXTENSIONS_DIR_NAME.DIRECTORY_SEPARATOR.$extensionName
);
// On failure
if (!$_addSoftLinks)
{
log_message('error', 'Failed to create Symlink to '.$extensionPath.$targetDirectory);
@@ -796,9 +905,9 @@ class ExtensionsLib
$this->_printMessage('Removing the extracted data from the upload directory');
if ($uploadData != null
&& isset($uploadData->extensionName)
&& file_exists($this->UPLOAD_PATH.$uploadData->extensionName))
&& file_exists($this->_getUploadPath().$uploadData->extensionName))
{
$this->_rrm($this->UPLOAD_PATH.$uploadData->extensionName);
$this->_rrm($this->_getUploadPath().$uploadData->extensionName);
}
// If the upload of the file is a success and the extension name is present and no previous installation were found
@@ -812,16 +921,13 @@ class ExtensionsLib
{
// Remove them all from file system and DB
$this->_printMessage('Removing entries in the DB related to this extension and from extensions directory');
$this->delExtension($result->retval[0]->extension_id);
$this->delExtension(getData($result)[0]->extension_id);
}
}
else // otherwise
// Otherwise remove them all only from DB
elseif ($extensionJson != null && isset($extensionJson->extension_id))
{
// Remove them all only from DB
if ($extensionJson != null && isset($extensionJson->extension_id))
{
$this->_ci->ExtensionsModel->delete($extensionJson->extension_id);
}
$this->_ci->ExtensionsModel->delete($extensionJson->extension_id);
}
$this->_printMessage('Rollback finished');
@@ -830,46 +936,19 @@ class ExtensionsLib
}
/**
* To enable/disable an extension
* Returns the absolute upload path
*/
private function _toggleExtension($extensionId, $enabled)
private function _getUploadPath()
{
$_toggleExtension = false;
return APPPATH.self::UPLOAD_PATH;
}
// Loads data from DB about the given extension
$result = $this->_ci->ExtensionsModel->load($extensionId);
if (hasData($result))
{
$extensionName = $result->retval[0]->name; // extension name
// If to be enabled
if ($enabled === true)
{
// Add the symlinks
$_toggleExtension = $this->_addSoftLinks($extensionName);
}
else // If to be disabled
{
// Remove all the symlinks
$_toggleExtension = $this->_delSoftLinks($extensionName);
}
if ($_toggleExtension) // if is a success
{
// Updates DB
$result = $this->_ci->ExtensionsModel->update($extensionId, array('enabled' => $enabled));
if (isSuccess($result))
{
$_toggleExtension = true;
}
else // if DB update fails remove symlinks from file system
{
$this->_delSoftLinks($extensionName);
}
}
}
return $_toggleExtension;
/**
* Returns the absolute extensions path
*/
private function _getExtensionsPath()
{
return APPPATH.self::EXTENSIONS_DIR_NAME.DIRECTORY_SEPARATOR;
}
/**
@@ -931,4 +1010,13 @@ class ExtensionsLib
{
$this->_printInfo('------------------------------------------------------------------------------------------');
}
/**
* Install the phrases from the given extension
*/
private function _installPhrases($extensionName)
{
$this->_ci->phraseslib->installFrom($this->_getExtensionsPath().$extensionName.'/'.self::PHRASES_DIRECTORY);
}
}
+16 -1
View File
@@ -50,6 +50,7 @@ class PermissionLib
const LOGINAS_PERSONIDS_BLACKLIST = 'permission_loginas_personids_blacklist';
private $_ci; // CI instance
private $access_rights; // current users access rights
private static $bb; // benutzerberechtigung
/**
@@ -61,6 +62,8 @@ class PermissionLib
// Loads CI instance
$this->_ci =& get_instance();
$this->access_rights = null;
$this->_ci->config->load('permission'); // Loads permission configuration
// If it's NOT called from command line
@@ -69,8 +72,10 @@ class PermissionLib
// API Caller rights initialization
$authObj = $this->_ci->authlib->getAuthObj();
self::$bb = new benutzerberechtigung();
if ($authObj)
if ($authObj) {
self::$bb->getBerechtigungen($authObj->{AuthLib::AO_USERNAME});
$this->access_rights = self::$bb->berechtigungen;
}
}
}
@@ -340,6 +345,16 @@ class PermissionLib
}
}
/**
* Returns the access rights for the current user
*
* @return array|null
*/
public function getAccessRights()
{
return $this->access_rights;
}
//------------------------------------------------------------------------------------------------------------------
// Private methods
+458 -118
View File
@@ -1,98 +1,96 @@
<?php
/**
* Copyright (C) 2025 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \Netcarver\Textile\Parser as NTParser;
class PhrasesLib
{
// Directory name where all the category files are
const CORE_PHRASES_DIRECTORY = 'phrases/';
// Old config file used for the phrases
const CORE_PHRASES_LEGACY_CFG_FILE = 'system/phrasesupdate.php';
// Who adds phrases into the database
const INSERT_BY = 'PhrasesManager';
// Array elements names
const APP = 'app';
const CATEGORY = 'category';
const PHRASE = 'phrase';
const SPRACHE = 'sprache';
const TEXT = 'text';
const DESCRIPTION = 'description';
private $_ci; // Code igniter instance
private $_phrases; // Contains the retrieved phrases
/**
* Loads parser library
*/
public function __construct()
{
public function __construct()
{
$this->_ci =& get_instance();
$this->_phrases = null; // set the property _phrases as null by default
// CI parser
$this->_ci->load->library('parser');
// Loads EPrintfLib
$this->_ci->load->library('EPrintfLib');
// Loads the PhraseModel
$this->_ci->load->model('system/Phrase_model', 'PhraseModel');
// Loads the PhrasentextModel
$this->_ci->load->model('system/Phrasentext_model', 'PhrasentextModel');
// Workaround to use more parameters in the construct since PHP doesn't support many constructors
$this->_extend_construct(func_get_args());
}
$this->_extendConstruct(func_get_args());
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
/**
* getPhrase() - loads a specific Phrase
*/
public function getPhrase($phrase_id)
{
if (isEmptyString($phrase_id)) return error(MSG_ERR_INVALID_MSG_ID);
return $this->_ci->PhraseModel->load($phrase_id);
}
/**
* getSubMessages() - will return all Messages subordinated from a specified message.
*/
public function getPhraseByApp($app = null)
{
return $this->_ci->PhraseModel->loadWhere(array('app' => $app));
}
/**
* getPhraseInhalt
*/
public function getPhraseInhalt($phrase_id)
{
if (isEmptyString($phrase_id)) return error(MSG_ERR_INVALID_MSG_ID);
return $this->_ci->PhrasentextModel->loadWhere(array('phrase_id' => $phrase_id));
}
/**
* delPhrasentext
*/
public function delPhrasentext($phrasentext_id)
{
if (isEmptyString($phrasentext_id)) return error(MSG_ERR_INVALID_MSG_ID);
return $this->_ci->PhrasentextModel->delete(array('phrasentext_id' => $phrasentext_id));
}
/**
* savePhrase() - will save a spezific Phrase.
*/
public function savePhrase($phrase_id, $data)
{
if (isEmptyString($data)) return error(MSG_ERR_INVALID_MSG_ID);
return $this->_ci->PhraseModel->update($phrase_id, $data);
}
/**
* getVorlagetextByVorlage() - will load tbl_vorlagestudiengang for a spezific Template.
*/
public function getPhrasentextById($phrasentext_id)
* Return the phrases in JSON format
*/
public function toJSON()
{
if (isEmptyString($phrasentext_id)) return error('Not a valid phrasentext_id');
return $this->_ci->PhrasentextModel->load($phrasentext_id);
}
return json_encode($this->_phrases);
}
/**
* getPhrases() - Retrieves phrases from the DB
* getPhrase() - loads a specific Phrase
*/
public function getPhrase($phrase_id)
{
if (isEmptyString($phrase_id)) return error(MSG_ERR_INVALID_MSG_ID);
return $this->_ci->PhraseModel->load($phrase_id);
}
/**
* getPhrases() - Retrieves phrases from the DB
* The given parameter are the same needed to read from the table system.tb_phrase
*/
public function getPhrases($app, $sprache, $phrase = null, $orgeinheit_kurzbz = null, $orgform_kurzbz = null, $blockTags = null)
{
*/
public function getPhrases($app, $sprache, $phrase = null, $orgeinheit_kurzbz = null, $orgform_kurzbz = null, $blockTags = null)
{
if (isset($app) && isset($sprache))
{
$result = $this->_ci->PhraseModel->getPhrases($app, $sprache, $phrase, $orgeinheit_kurzbz, $orgform_kurzbz);
@@ -100,7 +98,7 @@ class PhrasesLib
if (hasData($result))
{
// Textile parser
$textileParser = new \Netcarver\Textile\Parser();
$textileParser = new NTParser();
for ($i = 0; $i < count($result->retval); $i++)
{
@@ -139,31 +137,7 @@ class PhrasesLib
}
return $result;
}
/**
* insertPhraseinhalt() - will load tbl_vorlagestudiengang for a spezific Template.
*/
public function insertPhraseinhalt($data)
{
return $this->_ci->PhrasentextModel->insert($data);
}
/**
* getVorlagetextById() - will load tbl_vorlagestudiengang for a spezific Template.
*/
public function getVorlagetextById($vorlagestudiengang_id)
{
return $this->_ci->VorlageStudiengangModel->load($vorlagestudiengang_id);
}
/**
* saveVorlagetext() - will load tbl_vorlagestudiengang for a spezific Template.
*/
public function updatePhraseInhalt($phrasentext_id, $data)
{
return $this->_ci->PhrasentextModel->update($phrasentext_id, $data);
}
}
/**
* Retrieves a phrases from the the property _phrases with the given parameters
@@ -176,7 +150,7 @@ class PhrasesLib
public function t($category, $phrase, $parameters = array(), $orgeinheit_kurzbz = null, $orgform_kurzbz = null)
{
// If the property _phrases is populated
if (is_array($this->_phrases))
if (!isEmptyArray($this->_phrases))
{
// Loops through the _phrases property
for ($i = 0; $i < count($this->_phrases); $i++)
@@ -202,6 +176,107 @@ class PhrasesLib
}
/**
* Install phrases from the core
*/
public function installFromCore()
{
$this->_installPhrases(APPPATH.self::CORE_PHRASES_DIRECTORY);
}
/**
* Install phrases from the given path
*/
public function installFrom($phrasesDirectory)
{
$this->_installPhrases($phrasesDirectory);
}
/**
* Creates/updates the phrases files under the directory application/phrases/
*/
public function syncFiles()
{
// Legacy phrases file absolute path
$legacyPhrasesFile = FHCPATH.self::CORE_PHRASES_LEGACY_CFG_FILE;
// Try to include the legacy file used to store the phrases
// It is using the @ to suppress errors in case the file is not readable or does not exist
// In case is not readable or does not exists it stops the execution and prompts a message
if ((@include_once $legacyPhrasesFile) === false)
{
$this->_ci->eprintflib->printError($legacyPhrasesFile.' not found or not readable!'."\n");
exit;
}
// If the phrases array exists and it is not empty, otherwise it stops the executions and prompts a message
if (!isset($phrases) || isEmptyArray($phrases))
{
$this->_ci->eprintflib->printError($legacyPhrasesFile.' does not contain a populated array called "$phrases"');
exit;
}
// For each phrases contained in the array
foreach ($phrases as $phrase)
{
// If it contains the element category
if (isset($phrase[self::CATEGORY]) && isset($phrase[self::PHRASE]))
{
//
$toAppend = false;
// Path and name of the phrases category file
$phrasesCategoryFile = APPPATH.self::CORE_PHRASES_DIRECTORY.$phrase[self::CATEGORY].'.php';
// Checks if a phrases file already exists for this category
if (file_exists($phrasesCategoryFile))
{
// Get the phrases file category content
$phrasesCategoryFileContent = file_get_contents($phrasesCategoryFile);
// If an error occurred
if ($phrasesCategoryFileContent === false)
{
$this->_ci->eprintflib->printError('Was not possible to get the content of: '.$phrasesCategoryFile);
exit;
}
// Check if the phrase already exists inside this file
if (stristr($phrasesCategoryFileContent, $phrase[self::PHRASE]) === false) $toAppend = true;
}
else // if not then
{
// Create the new phrases category file
if (!$this->_createPhraseToCategoryFile($phrasesCategoryFile))
{
$this->_ci->eprintflib->printError('Was not possible to create the phrases category file: '.$phrasesCategoryFile);
exit;
}
$this->_ci->eprintflib->printMessage('Created new phrases category file: '.$phrasesCategoryFile);
$toAppend = true;
}
// If the phrase is to be appended to the phrases category file
if ($toAppend)
{
// And then append the phrase to it
if (!$this->_appendPhraseToCategoryFile($phrase, $phrasesCategoryFile))
{
$this->_ci->eprintflib->printError('Was not possible to append to the phrases category file: '.$phrasesCategoryFile);
exit;
}
}
}
else // otherwise prompt an error message and continue
{
$this->_ci->eprintflib->printInfo('Missing "'.self::CATEGORY.'" or "'.self::PHRASE.'" for the following element:');
var_dump($phrase);
$this->_ci->eprintflib->printInfo('-------------------------------------------');
}
}
}
/*
* Workaround to reload the phrases array on an already constructed library.
* @parameters -> look for _setPhrases docs
*/
@@ -215,6 +290,68 @@ class PhrasesLib
// -----------------------------------------------------------------------------------------------------------------
// Private methods
/**
* Append a new phrases to the related phrases category file
*/
private function _appendPhraseToCategoryFile($phrase, $phrasesCategoryFile)
{
// Open the category phrases file and a temporary one
$srcFileHandle = @fopen($phrasesCategoryFile, 'r');
// In case exists then it is truncated
$dstFileHandle = @fopen($phrasesCategoryFile.'.tmp', 'w');
// If an error occurred then return false
if (!$srcFileHandle || !$dstFileHandle) return false;
$line = '';
// Read the file line by line
while (!feof($srcFileHandle))
{
// Read a single line from the source file
$line = fgets($srcFileHandle, 4096);
// If an error occurred then exit
if ($line === false && !feof($srcFileHandle)) return false;
// If the first phrase or the end of the array
if ($line == '$phrases = array();' || stristr($line, ');'))
{
$first_coma = ',';
if ($line == '$phrases = array();') $first_coma = '';
// If found then append the new phrase to the current line
// and replace the end of the array
$line = str_replace(');', $first_coma."\n".var_export($phrase, true)."\n".');', $line);
}
// In any case copy the line to the temp file
if (@fwrite($dstFileHandle, $line) === false) return false;
}
// Close the file handles
fclose($srcFileHandle);
fclose($dstFileHandle);
// Delete the old file
if (@unlink($phrasesCategoryFile) === false) return false;
// Rename the temp file as the old one
if (@rename($phrasesCategoryFile.'.tmp', $phrasesCategoryFile) === false) return false;
return true; // if everything was fine
}
/**
* Creates a new phrases category file with the given name
* and having an empy array called $phrases as content
*/
private function _createPhraseToCategoryFile($phrasesCategoryFile)
{
return !(file_put_contents(
$phrasesCategoryFile,
'<?php'."\n\n".'$phrases = array();'
) === false);
}
/**
* Extends the functionalities of the constructor of this class
* This is a workaround to use more parameters in the construct since PHP doesn't support many constructors
@@ -224,22 +361,19 @@ class PhrasesLib
* - could be an array of categories, and for each category there is an array of phrases
* language: optional parameter must be a string. It's used to load phrases
*/
private function _extend_construct($params)
private function _extendConstruct($params)
{
// Checks if the $params is an array with at least one element
if (is_array($params) && count($params) > 0)
if (!isEmptyArray($params))
{
$parameters = $params[0]; // temporary variable
$isIndexArray = false; //flag for indexed array
// If there are parameters
if (is_array($parameters) && count($parameters) > 0)
if (!isEmptyArray($parameters))
{
$categories = $parameters[0]; // categories is always the first parameter
if (!is_array($categories)) // if it is not an array, then convert into one
{
$categories = array($categories);
}
// If it is not an array, then convert into one
if (!is_array($categories)) $categories = array($categories);
// Retrieves the language of the logged user
$language = getUserLanguage(count($parameters) == 2 ? $parameters[1] : null);
@@ -279,7 +413,7 @@ class PhrasesLib
// If language is not default language and phrasentext is null -> fallback to default language
if ($language != DEFAULT_LANGUAGE)
{
// get array with phrasentexte in the default language
// Get array with phrasentexte in the default language
$defaultPhrases = null;
if ($isIndexArray)
{
@@ -290,19 +424,19 @@ class PhrasesLib
$defaultPhrases = $this->_ci->PhraseModel->getPhrasesByCategoryAndPhrasesAndLanguage($categories, DEFAULT_LANGUAGE);
}
// combine array with phrasentexte in users language and in default language
// Combine array with phrasentexte in users language and in default language
// (default used if phrasentext in users language is null or not set)
if (hasData($phrases) && hasData($defaultPhrases))
{
// loop through phrases in default language
// Loop through phrases in default language
foreach ($defaultPhrases->retval as $defaultPhrase)
{
$found = false; // flag for found phrase
// loop through phrases in users language
// Loop through phrases in users language
foreach ($phrases->retval as $phrase)
{
// if same phrase and category found and text is not null
// If same phrase and category found and text is not null
// use phrase in users language
if ($phrase->phrase == $defaultPhrase->phrase
&& $phrase->category == $defaultPhrase->category
@@ -313,13 +447,11 @@ class PhrasesLib
}
}
// otherwise use phrase in default language
if (!$found)
{
array_push($phrases->retval, $defaultPhrase);
}
// Otherwise use phrase in default language
if (!$found) array_push($phrases->retval, $defaultPhrase);
}
}
// Otherwise if only defaultPhrases have data
elseif (hasData($defaultPhrases))
{
$phrases = $defaultPhrases;
@@ -327,19 +459,227 @@ class PhrasesLib
}
// If there are phrases loaded then store them in the property _phrases
if (hasData($phrases))
{
$this->_phrases = $phrases->retval;
}
if (hasData($phrases)) $this->_phrases = $phrases->retval;
}
/**
* Returns the property _phrases JSON encoded
* @return json encoded property _phrases
* Install phrases from the given directory
*/
public function getJSON()
private function _installPhrases($phrasesDirectory)
{
return json_encode($this->_phrases);
$this->_ci->eprintflib->printInfo('------------------------------------------------------------------------------------------');
$this->_ci->eprintflib->printInfo('Phrases installation started from: '.$phrasesDirectory);
// If the given directory name does not exist
if (!is_dir($phrasesDirectory))
{
$this->_ci->eprintflib->printError('The directory '.$phrasesDirectory.' does not exist');
}
else // otherwise install the phrases from the given directory
{
// Get the list of category files from the given directory
$phrasesCategoryFiles = scandir($phrasesDirectory);
if ($phrasesCategoryFiles == false)
{
$this->_ci->eprintflib->printError('An error occurred while trying to access to the given directory: '.$phrasesDirectory);
}
else
{
// If no files are inside the given directory
if (count($phrasesCategoryFiles) == 2)
{
$this->_ci->eprintflib->printInfo('No phrases files are inside the given directory: '.$phrasesDirectory);
}
// For each file in this directory that represents a phrases category
foreach ($phrasesCategoryFiles as $phrasesCategoryFile)
{
// Gets the infos about the file
$pathInfo = pathinfo($phrasesDirectory.$phrasesCategoryFile);
// Skip the upper directory, the same directory and files that are not a php file
if ($phrasesCategoryFile != '.'
&& $phrasesCategoryFile != '..'
&& $pathInfo['extension'] == 'php')
{
$phrases = null; // define the variable
// Include the php file that contains phrases for that category
require_once($phrasesDirectory.$phrasesCategoryFile);
// If this file contains an array called phrases
if (isset($phrases) && is_array($phrases))
{
$addPhrases = $this->_addPhrases($phrases); // add them to the database
// If a blocking error occurred then print an error and stop the execution
if (isError($addPhrases))
{
$this->_ci->eprintflib->printError(getError($addPhrases));
break;
}
}
else // otherwise print an error and continue with the next file
{
$this->_ci->eprintflib->printInfo(
'The file '.$phrasesDirectory.$phrasesCategoryFile.' does not contain an array called "phrases"'
);
}
// Clean for the next file
unset($phrases);
}
}
}
}
$this->_ci->eprintflib->printInfo('Phrases installation ended');
$this->_ci->eprintflib->printInfo('------------------------------------------------------------------------------------------');
}
}
/**
* Add new phrases to the database
*/
private function _addPhrases($phrases)
{
// For eache given phrase
foreach ($phrases as $phrase)
{
$phrase_id = null; // The id of the new/existing phrase
// Checks the mandatory fields, if one of them is not valid continue with the next phrase
if (!$this->_isValidElement($phrase, self::APP)) continue;
if (!$this->_isValidElement($phrase, self::CATEGORY)) continue;
if (!$this->_isValidElement($phrase, self::PHRASE)) continue;
// Checks if the phrase already exists in the database
$phraseResult = $this->_ci->PhraseModel->loadWhere(
array(
'app' => $phrase[self::APP],
'category' => $phrase[self::CATEGORY],
'phrase' => $phrase[self::PHRASE]
)
);
// If an error occurred then return the error itself
if (isError($phraseResult)) return $phraseResult;
// If no phrase has been found
if (!hasData($phraseResult))
{
// Then add the phrase to the database
$phraseInsertResult = $this->_ci->PhraseModel->insert(
array(
'app' => $phrase[self::APP],
'category' => $phrase[self::CATEGORY],
'phrase' => $phrase[self::PHRASE],
'insertamum' => 'NOW()',
'insertvon' => self::INSERT_BY
)
);
// If an error occurred then return the error itself
if (isError($phraseInsertResult)) return $phraseInsertResult;
$phrase_id = getData($phraseInsertResult); // the phrase_id of the new added phrase
// Prints info about the new added phrase
$this->_ci->eprintflib->printMessage(
sprintf(
'A new phrase has been added into the database: '.
'phrase_id => %s | app => %s | category => %s | phrase => %s',
$phrase_id,
$phrase[self::APP],
$phrase[self::CATEGORY],
$phrase[self::PHRASE]
)
);
}
else // otherwise if the phrase already exists in the database
{
$phrase_id = getData($phraseResult)[0]->phrase_id; // gets the phrase_id
}
// If not a valid phrase_id
if ($phrase_id == null) return error('Not a valid phrase id');
// For each phrase text, one text for each language
foreach ($phrase['phrases'] as $phraseText)
{
// Checks the mandatory fields, if one of them is not valid continue with the next phrase text
if (!$this->_isValidElement($phraseText, self::SPRACHE)) continue;
if (!$this->_isValidElement($phraseText, self::TEXT)) continue;
// Set the not optional fields if they have not been set
if (!isset($phraseText[self::DESCRIPTION])) $phraseText[self::DESCRIPTION] = null;
// Checks if the phrase already exists in the database
$phraseTextResult = $this->_ci->PhrasentextModel->loadWhere(
array(
'phrase_id' => $phrase_id,
'sprache' => $phraseText[self::SPRACHE]
)
);
// If an error occurred then return the error itself
if (isError($phraseTextResult)) return $phraseTextResult;
// If no text for the phrase was found
if (!hasData($phraseTextResult))
{
// Then add the text phrase to the database
$phraseTextInsertResult = $this->_ci->PhrasentextModel->insert(
array(
'phrase_id' => $phrase_id,
'sprache' => $phraseText[self::SPRACHE],
'text' => $phraseText[self::TEXT],
'description' => $phraseText[self::DESCRIPTION],
'insertvon' => self::INSERT_BY,
'insertamum' => 'NOW()',
'orgeinheit_kurzbz' => null,
'orgform_kurzbz' => null
)
);
// If an error occurred then return the error itself
if (isError($phraseTextInsertResult)) return $phraseTextInsertResult;
// Prints info about the new added text phrase
$this->_ci->eprintflib->printMessage(
sprintf(
'A new text has been added into the database: '.
'phrase_id => %s | sprache => %s | text => %s | description => %s',
$phrase_id,
$phraseText[self::SPRACHE],
substr($phraseText[self::TEXT], 0, 42).'...',
substr($phraseText[self::DESCRIPTION], 0, 42).'...'
)
);
}
}
}
// If here then no blocking errors occurred
return success();
}
/**
* Checks if the given array element exists in the given array and if it is a valid string and then returns true
* Otherwise prints an info and then returns false
*/
private function _isValidElement($array, $elementName)
{
// If a not valid text is set
if ((isset($array[$elementName]) && isEmptyString($array[$elementName])) || !isset($array[$elementName]))
{
$this->_ci->eprintflib->printInfo('Not a valid element "'.$elementName.'":');
var_dump($array); // KEEP IT!!!
$this->_ci->eprintflib->printEOL();
return false;
}
return true;
}
}
@@ -49,7 +49,7 @@ class DashboardLib
public function getMergedConfig($dashboard_id, $uid)
{
$defaultconfig = $this->getDefaultConfig($dashboard_id, $uid);
$defaultconfig = $this->getDefaultConfig($dashboard_id);
$userconfig = $this->getUserConfig($dashboard_id, $uid);
$mergedconfig = array_replace_recursive($defaultconfig, $userconfig);
@@ -57,14 +57,31 @@ class DashboardLib
return $mergedconfig;
}
public function getDefaultConfig($dashboard_id, $uid)
public function getDefaultConfig($dashboard_id)
{
$res_presets = $this->_ci->DashboardPresetModel->getPresets($dashboard_id, $uid);
$funktion_kurzbzs = [];
$rights = $this->_ci->permissionlib->getAccessRights();
if ($rights)
$funktion_kurzbzs = array_unique(array_map(function ($right) {
return $right->funktion_kurzbz;
}, $rights));
$this->_ci->DashboardPresetModel->db
->group_start()
->where_in('funktion_kurzbz', $funktion_kurzbzs)
->or_where('funktion_kurzbz IS NULL')
->group_end();
$this->_ci->DashboardPresetModel->addOrder('funktion_kurzbz', 'DESC');
$result = $this->_ci->DashboardPresetModel->loadWhere([
'dashboard_id' => $dashboard_id
]);
$defaultconfig = array();
if (hasData($res_presets))
if (hasData($result))
{
$presets = getData($res_presets);
$presets = getData($result);
foreach ($presets as $presetobj)
{
$preset = json_decode($presetobj->preset, true);
@@ -137,8 +154,10 @@ class DashboardLib
$dashboard = $this->getDashboardByKurzbz($dashboard_kurzbz);
$funktion_kurzbz = ($section === self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL) ? null : $section;
$result = $this->_ci->DashboardPresetModel
->getPresetByDashboardAndFunktion($dashboard->dashboard_id, $funktion_kurzbz);
$result = $this->_ci->DashboardPresetModel->loadWhere([
'dashboard_id' => $dashboard->dashboard_id,
'funktion_kurzbz' => $funktion_kurzbz
]);
if (hasData($result))
{
@@ -195,11 +214,11 @@ class DashboardLib
{
foreach ($addwigets as $widget)
{
if(!isset($widget->widgetid))
if(!isset($widget['widgetid']))
{
$widget->widgetid = $this->generateWidgetId($dashboard_kurzbz);
$widget['widgetid'] = $this->generateWidgetId($dashboard_kurzbz);
}
$this->addWidgetToWidgets($widgets, $section, $widget, $widget->widgetid);
$this->addWidgetToWidgets($widgets, $section, $widget, $widget['widgetid']);
}
}
@@ -3,6 +3,7 @@ namespace vertragsbestandteil;
use Exception;
use vertragsbestandteil\VertragsbestandteilStunden;
use vertragsbestandteil\VertragsbestandteilLohnguide;
/**
* Description of VertragsbestandteilFactory
@@ -22,6 +23,7 @@ class VertragsbestandteilFactory
const VERTRAGSBESTANDTEIL_URLAUBSANSPRUCH = 'urlaubsanspruch';
const VERTRAGSBESTANDTEIL_ZEITAUFZEICHNUNG = 'zeitaufzeichnung';
const VERTRAGSBESTANDTEIL_LEHRE = 'lehre';
const VERTRAGSBESTANDTEIL_LOHNGUIDE = 'lohnguide';
public static function getVertragsbestandteil($data, $fromdb=false)
{
@@ -69,6 +71,11 @@ class VertragsbestandteilFactory
$vertragsbestandteil = new VertragsbestandteilZeitaufzeichnung();
$vertragsbestandteil->hydrateByStdClass($data, $fromdb);
break;
case self::VERTRAGSBESTANDTEIL_LOHNGUIDE:
$vertragsbestandteil = new VertragsbestandteilLohnguide();
$vertragsbestandteil->hydrateByStdClass($data, $fromdb);
break;
default:
throw new Exception('Unknown vertragsbestandteiltyp_kurzbz '
@@ -127,6 +134,12 @@ class VertragsbestandteilFactory
$vertragsbestandteildbmodel = $CI->VertragsbestandteilZeitaufzeichnung_model;
break;
case self::VERTRAGSBESTANDTEIL_LOHNGUIDE:
$CI->load->model('vertragsbestandteil/VertragsbestandteilLohnguide_model',
'VertragsbestandteilLohnguide_model');
$vertragsbestandteildbmodel = $CI->VertragsbestandteilLohnguide_model;
break;
default:
throw new Exception('Unknown vertragsbestandteil_kurzbz '
. $vertragsbestandteil_kurzbz);
@@ -10,6 +10,7 @@ require_once __DIR__ . '/VertragsbestandteilKuendigungsfrist.php';
require_once __DIR__ . '/VertragsbestandteilUrlaubsanspruch.php';
require_once __DIR__ . '/VertragsbestandteilFreitext.php';
require_once __DIR__ . '/VertragsbestandteilKarenz.php';
require_once __DIR__ . '/VertragsbestandteilLohnguide.php';
require_once __DIR__ . '/VertragsbestandteilFactory.php';
require_once __DIR__ . '/OverlapChecker.php';
@@ -0,0 +1,155 @@
<?php
namespace vertragsbestandteil;
use vertragsbestandteil\Vertragsbestandteil;
use vertragsbestandteil\VertragsbestandteilFactory;
class VertragsbestandteilLohnguide extends Vertragsbestandteil
{
protected $stellenbezeichnung;
protected $vordienstzeit;
protected $fachrichtung_kurzbz;
protected $modellstelle_kurzbz;
protected $kommentar_person;
protected $kommentar_modellstelle;
public function __construct()
{
parent::__construct();
$this->setVertragsbestandteiltyp_kurzbz(
VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_LOHNGUIDE);
}
public function getStellenbezeichnung()
{
return $this->stellenbezeichnung;
}
public function setStellenbezeichnung($stellenbezeichnung): self
{
$this->markDirty('stellenbezeichnung', $this->stellenbezeichnung, $stellenbezeichnung);
$this->stellenbezeichnung = $stellenbezeichnung;
return $this;
}
public function getVordienstzeit()
{
return $this->vordienstzeit;
}
public function setVordienstzeit($vordienstzeit): self
{
$this->markDirty('vordienstzeit', $this->vordienstzeit, $vordienstzeit);
$this->vordienstzeit = $vordienstzeit;
return $this;
}
public function getFachrichtung_kurzbz()
{
return $this->fachrichtung_kurzbz;
}
public function setFachrichtung_kurzbz($fachrichtung_kurzbz): self
{
$this->markDirty('fachrichtung_kurzbz', $this->fachrichtung_kurzbz, $fachrichtung_kurzbz);
$this->fachrichtung_kurzbz = $fachrichtung_kurzbz;
return $this;
}
public function getModellstelle_kurzbz()
{
return $this->modellstelle_kurzbz;
}
public function setModellstelle_kurzbz($modellstelle_kurzbz): self
{
$this->markDirty('modellstelle_kurzbz', $this->modellstelle_kurzbz, $modellstelle_kurzbz);
$this->modellstelle_kurzbz = $modellstelle_kurzbz;
return $this;
}
public function getKommentar_person()
{
return $this->kommentar_person;
}
public function setKommentar_person($kommentar_person): self
{
$this->markDirty('kommentar_person', $this->kommentar_person, $kommentar_person);
$this->kommentar_person = $kommentar_person;
return $this;
}
public function getKommentar_modellstelle()
{
return $this->kommentar_modellstelle;
}
public function setKommentar_modellstelle($kommentar_modellstelle): self
{
$this->markDirty('kommentar_modellstelle', $this->kommentar_modellstelle, $kommentar_modellstelle);
$this->kommentar_modellstelle = $kommentar_modellstelle;
return $this;
}
public function hydrateByStdClass($data, $fromdb=false)
{
parent::hydrateByStdClass($data, $fromdb);
$this->fromdb = $fromdb;
isset($data->fachrichtung_kurzbz) && $this->setFachrichtung_kurzbz($data->fachrichtung_kurzbz);
isset($data->stellenbezeichnung) && $this->setStellenbezeichnung($data->stellenbezeichnung);
isset($data->vordienstzeit) && $this->setVordienstzeit($data->vordienstzeit);
isset($data->modellstelle_kurzbz) && $this->setModellstelle_kurzbz($data->modellstelle_kurzbz);
isset($data->kommentar_person) && $this->setKommentar_person($data->kommentar_person);
isset($data->kommentar_modellstelle) && $this->setKommentar_modellstelle($data->kommentar_modellstelle);
$this->fromdb = false;
}
public function toStdClass(): \stdClass
{
$tmp = array(
'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
'stellenbezeichnung' => $this->getStellenbezeichnung(),
'vordienstzeit' => $this->getVordienstzeit(),
'fachrichtung_kurzbz' => $this->getFachrichtung_kurzbz(),
'modellstelle_kurzbz' => $this->getModellstelle_kurzbz(),
'kommentar_person' => $this->getKommentar_person(),
'kommentar_modellstelle' => $this->getKommentar_modellstelle(),
);
$tmp = array_filter($tmp, function($k) {
return in_array($k, $this->modifiedcolumns);
}, ARRAY_FILTER_USE_KEY);
return (object) $tmp;
}
public function __toString()
{
$txt = <<<EOTXT
modellstelle_kurzbz: {$this->getModellstelle_kurzbz()}
EOTXT;
return parent::__toString() . $txt;
}
/* public function validate()
{
if( !(filter_var($this->tage, FILTER_VALIDATE_INT,
array(
'options' => array(
'min_range' => 1,
'max_range' => 50
)
)
)) ) {
$this->validationerrors[] = 'Urlaubsanspruch muss eine Tagesanzahl im Bereich 1 bis 50 sein.';
}
return parent::validate();
} */
}
@@ -490,6 +490,175 @@ class Vertrag_model extends DB_Model
return $bezeichnung;
}
/**
* Loads all Contracts of a Person
* @param $person_id
* @return array of objects
*/
public function loadContractsOfPerson($person_id)
{
$query = "
SELECT
*,
tbl_vertrag.bezeichnung as bezeichnung,
tbl_vertragstyp.bezeichnung as vertragstyp_bezeichnung,
tbl_vertrag.vertragsdatum,
(SELECT bezeichnung FROM lehre.tbl_vertragsstatus
JOIN lehre.tbl_vertrag_vertragsstatus USING(vertragsstatus_kurzbz)
WHERE vertrag_id=tbl_vertrag.vertrag_id ORDER BY datum desc limit 1) as status, anmerkung,
CASE
WHEN EXISTS (
SELECT 1
FROM lehre.tbl_vertrag_vertragsstatus
WHERE vertrag_id = tbl_vertrag.vertrag_id
AND vertragsstatus_kurzbz = 'abgerechnet'
) THEN true
ELSE false
END AS isAbgerechnet
FROM
lehre.tbl_vertrag
LEFT JOIN lehre.tbl_vertragstyp USING(vertragstyp_kurzbz)
WHERE person_id= ?";
return $this->execQuery($query, array($person_id));
}
/**
* Loads all Contracts of a Person that are not assigned yet
* @param $person_id
* @return array of objects
*/
public function loadContractsOfPersonNotAssigned($person_id)
{
$query = "
SELECT
'Lehrauftrag' as type,
lehreinheit_id,
mitarbeiter_uid,
null as pruefung_id,
null as projektarbeit_id,
(tbl_lehreinheitmitarbeiter.semesterstunden*tbl_lehreinheitmitarbeiter.stundensatz) as betrag1,
tbl_lehreinheit.studiensemester_kurzbz,
null as betreuerart_kurzbz,
( SELECT
upper(tbl_studiengang.typ || tbl_studiengang.kurzbz) || tbl_lehrveranstaltung.semester || '-' || tbl_lehrveranstaltung.kurzbz || '-' || tbl_lehreinheit.lehrform_kurzbz
FROM
lehre.tbl_lehrveranstaltung
JOIN public.tbl_studiengang USING(studiengang_kz)
WHERE
lehrveranstaltung_id=tbl_lehreinheit.lehrveranstaltung_id)
as bezeichnung
FROM
lehre.tbl_lehreinheitmitarbeiter
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
WHERE
mitarbeiter_uid IN (SELECT uid FROM public.tbl_benutzer WHERE person_id=?)
AND vertrag_id IS NULL
UNION
SELECT
'Betreuung' as type,
tbl_projektarbeit.lehreinheit_id as lehreinheit_id,
null as mitarbeiter_uid,
null::integer as pruefung_id,
projektarbeit_id,
(tbl_projektbetreuer.stunden*tbl_projektbetreuer.stundensatz) as betrag1,
tbl_lehreinheit.studiensemester_kurzbz,
tbl_projektbetreuer.betreuerart_kurzbz,
(SELECT nachname || ' ' || vorname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) WHERE uid=tbl_projektarbeit.student_uid)
as bezeichnung
FROM
lehre.tbl_projektbetreuer
JOIN lehre.tbl_projektarbeit USING(projektarbeit_id)
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
WHERE
tbl_projektbetreuer.person_id=?
AND vertrag_id IS NULL
";
return $this->execQuery($query, array($person_id, $person_id));
}
/**
* Loads all Contracts of a Person that are assigned yet
* @param $person_id, $vertrag_id
* @return array of objects
*/
public function loadContractsOfPersonAssigned($person_id, $vertrag_id)
{
$query = "
SELECT
'Lehrauftrag' as type,
lehreinheit_id,
mitarbeiter_uid,
null as pruefung_id,
null as projektarbeit_id,
(tbl_lehreinheitmitarbeiter.semesterstunden * tbl_lehreinheitmitarbeiter.stundensatz) as betrag,
tbl_lehreinheit.studiensemester_kurzbz,
null as betreuerart_kurzbz,
( SELECT
upper(tbl_studiengang.typ || tbl_studiengang.kurzbz) || tbl_lehrveranstaltung.semester || '-' || tbl_lehrveranstaltung.kurzbz || '-' || tbl_lehreinheit.lehrform_kurzbz
FROM
lehre.tbl_lehrveranstaltung
JOIN public.tbl_studiengang USING(studiengang_kz)
WHERE
lehrveranstaltung_id=tbl_lehreinheit.lehrveranstaltung_id)
as bezeichnung, vertrag_id
FROM
lehre.tbl_lehreinheitmitarbeiter
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
WHERE
mitarbeiter_uid IN (SELECT uid FROM public.tbl_benutzer WHERE person_id=?)
AND vertrag_id = ?
UNION
SELECT
'Betreuung' as type,
tbl_projektarbeit.lehreinheit_id as lehreinheit_id,
null as mitarbeiter_uid,
null::integer as pruefung_id,
projektarbeit_id,
(tbl_projektbetreuer.stunden * tbl_projektbetreuer.stundensatz) as betrag,
tbl_lehreinheit.studiensemester_kurzbz,
tbl_projektbetreuer.betreuerart_kurzbz,
(SELECT nachname || ' ' || vorname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) WHERE uid=tbl_projektarbeit.student_uid)
as bezeichnung, vertrag_id
FROM
lehre.tbl_projektbetreuer
JOIN lehre.tbl_projektarbeit USING(projektarbeit_id)
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
WHERE
tbl_projektbetreuer.person_id=?
AND vertrag_id = ?
";
return $this->execQuery($query, array($person_id, $vertrag_id, $person_id, $vertrag_id));
}
/**
* Returns all stati of a contract
*
* @param $vertrag_id
* @return array
*/
public function getStatiOfContract($vertrag_id)
{
$query = "
SELECT
*,
tbl_vertrag_vertragsstatus.datum,
tbl_vertrag_vertragsstatus.insertamum,
tbl_vertrag_vertragsstatus.updateamum
FROM
lehre.tbl_vertrag_vertragsstatus
JOIN lehre.tbl_vertragsstatus USING(vertragsstatus_kurzbz)
WHERE
tbl_vertrag_vertragsstatus.vertrag_id = ?
ORDER BY tbl_vertrag_vertragsstatus.datum DESC";
return $this->execQuery($query, array($vertrag_id));
}
private function _updateVertragRelevant($vertrag_id)
{
$this->LehreinheitmitarbeiterModel->update(
@@ -11,4 +11,5 @@ class Vertragstyp_model extends DB_Model
$this->dbTable = 'lehre.tbl_vertragstyp';
$this->pk = 'vertragstyp_kurzbz';
}
}
@@ -190,4 +190,6 @@ class Vertragvertragsstatus_model extends DB_Model
return $this->loadWhere($condition);
}
}
+53 -15
View File
@@ -10,7 +10,7 @@ class Reihungstest_model extends DB_Model
parent::__construct();
$this->dbTable = 'public.tbl_reihungstest';
$this->pk = 'reihungstest_id';
}
}
/**
* Gets a test from a test id only if it is available
@@ -42,8 +42,8 @@ class Reihungstest_model extends DB_Model
/**
* Checks if there are active studyplans which have no public placement tests assigned yet.
* Only check assignment to studyplans that are
* - Bachelor,
* - active,
* - Bachelor,
* - active,
* - set as online application
* - valid for 1st terms
* @return array Returns object array with studyplans that have no public placement tests assigned yet.
@@ -97,7 +97,7 @@ class Reihungstest_model extends DB_Model
USING (reihungstest_id)
WHERE
datum >= now()
AND
AND
oeffentlich = \'t\'
)
';
@@ -105,7 +105,7 @@ class Reihungstest_model extends DB_Model
return $this->execQuery($query);
}
/**
/**
* Gets amount of free places.
* @return array Returns object array with faculty and amount of free places
* for each public actual placement test date.
@@ -432,10 +432,10 @@ class Reihungstest_model extends DB_Model
}
/**
* Loads all applicants of a placement test
* @param integer $reihungstest_id ID of placement test
* @return array Returns object array with data of applicants.
*/
* Loads all applicants of a placement test
* @param integer $reihungstest_id ID of placement test
* @return array Returns object array with data of applicants.
*/
public function getApplicantsOfPlacementTest($reihungstest_id)
{
$query = '
@@ -556,13 +556,22 @@ class Reihungstest_model extends DB_Model
* Calculates Result of Placement Test for a given Person and given placementtest
* and with taking account of weighting per area
*
* @param $person_id ID of Person
* @param $punkte if true result is points else result is percentage of sum
* @param $reihungstest_id ID of Placementtest
* @param $weightedArray array of weighting per area (gewicht per gebiet_id)
* @return float result
* @param Number $person_id ID of Person
* @param Boolean $punkte if true result is points else result is percentage of sum
* @param Number $reihungstest_id ID of Placementtest
* @param Array $weightedArray array of weighting per area (gewicht per gebiet_id)
* @param Boolean $has_excluded_gebiete if true, areas in the configArray will be excluded
* @param Array $basis_gebiet_id_toString areas to exclude
* @return float result points of RT
*/
public function getReihungstestErgebnisPerson($person_id, $punkte, $reihungstest_id, $weightedArray = null)
public function getReihungstestErgebnisPerson(
$person_id,
$punkte,
$reihungstest_id,
$weightedArray = null,
$has_excluded_gebiete = false,
$basis_gebiet_id_toString = null
)
{
$parametersArray = array($reihungstest_id);
@@ -577,6 +586,35 @@ class Reihungstest_model extends DB_Model
WHERE
reihungstest_id = ? ";
//areas of Studiengang
if (!empty($basis_gebiet_id_toString))
{
$qry .= "
AND
gebiet_id IN (". $basis_gebiet_id_toString. ")
";
}
//areas to exclude
if($has_excluded_gebiete)
{
if (defined('FAS_REIHUNGSTEST_EXCLUDE_GEBIETE') && !empty(FAS_REIHUNGSTEST_EXCLUDE_GEBIETE))
{
$excluded_gebiete = unserialize(FAS_REIHUNGSTEST_EXCLUDE_GEBIETE);
$exclude_gebiet_id_arr = $excluded_gebiete;
if (is_array($exclude_gebiet_id_arr) && count($exclude_gebiet_id_arr) > 0)
{
$exclude_gebiet_id_toString = implode(', ', $exclude_gebiet_id_arr);
$qry .= "
AND
gebiet_id NOT IN (". $exclude_gebiet_id_toString. ")
-- AND
-- typ = 'b'
";
}
}
}
//using prestudent Status to avoid to get the sum of more than 1 placement tests
$qry .= "
AND prestudent_id = (
@@ -11,57 +11,4 @@ class Dashboard_Preset_model extends DB_Model
$this->dbTable = 'dashboard.tbl_dashboard_preset';
$this->pk = 'preset_id';
}
/**
* Get Presets of given uid.
* @param integer dashboard_id
* @param string $uid
* @return array
*/
public function getPresets($dashboard_id, $uid)
{
// TODO: get Funktionen for uid and load all preset for all funktionen for uid
//return $this->loadWhere(array('dashboard_id' => $dashboard_id, 'funktion_kurzbz'=> null));
$sql = <<<EOSQL
SELECT
*
FROM
dashboard.tbl_dashboard_preset
WHERE
dashboard_id = ?
AND (
funktion_kurzbz IN (
SELECT
DISTINCT funktion_kurzbz
FROM
public.tbl_benutzerfunktion
WHERE
uid = ?
AND
NOW()::date
BETWEEN
COALESCE(datum_von, '1970-01-01')
AND
COALESCE(datum_bis, '2170-12-31')
)
OR
funktion_kurzbz IS NULL
)
ORDER BY
funktion_kurzbz DESC
EOSQL;
return $this->execQuery($sql, array($dashboard_id, $uid));
}
/**
* Get Preset by Dashboard and Funktion
* @param integer dashboard_id
* @param string funktion_kurzbz
* @return array
*/
public function getPresetByDashboardAndFunktion($dashboard_id, $funktion_kurzbz)
{
return $this->loadWhere(array('dashboard_id' => $dashboard_id, 'funktion_kurzbz' => $funktion_kurzbz));
}
}
@@ -402,14 +402,17 @@ class Lehrveranstaltung_model extends DB_Model
SELECT
vorname, nachname, mitarbeiter_uid, lehrfunktion_kurzbz
FROM
lehre.tbl_lehreinheit
lehre.tbl_lehreinheit le
JOIN lehre.tbl_lehreinheitmitarbeiter lema USING (lehreinheit_id)
JOIN public.tbl_benutzer b ON b.uid = lema.mitarbeiter_uid
JOIN public.tbl_person p using (person_id)
WHERE
tbl_lehreinheit.lehrveranstaltung_id= ?
AND tbl_lehreinheit.studiensemester_kurzbz = ?
le.lehrveranstaltung_id= ?
AND le.studiensemester_kurzbz = ?
AND lehrfunktion_kurzbz = 'LV-Leitung'
AND lema.mitarbeiter_uid NOT like '_Dummy%'
AND b.aktiv = TRUE
AND p.aktiv = TRUE
ORDER BY
lema.insertamum DESC
LIMIT 1
+32 -21
View File
@@ -79,34 +79,45 @@ class Paabgabe_model extends DB_Model
JOIN public.tbl_benutzer ON (public.tbl_benutzer.uid = student_uid)
JOIN public.tbl_person USING (person_id)
WHERE (campus.tbl_paabgabe.insertamum >= NOW() - INTERVAL ?
OR campus.tbl_paabgabe.updateamum >= NOW() - INTERVAL ?)
AND campus.tbl_paabgabe.paabgabetyp_kurzbz IN ?";
WHERE (campus.tbl_paabgabe.insertamum::date = CURRENT_DATE - INTERVAL ?
OR campus.tbl_paabgabe.updateamum::date = CURRENT_DATE - INTERVAL ?)
AND campus.tbl_paabgabe.paabgabetyp_kurzbz IN ?";
return $this->execQuery($query, [$interval, $interval, $relevantTypes]);
}
public function findAbgabenNewOrUpdatedSinceByAbgabedatum($interval) {
$query = "SELECT projektarbeit_id, paabgabe_id, paabgabetyp_kurzbz, fixtermin, datum, kurzbz, campus.tbl_paabgabetyp.bezeichnung, campus.tbl_paabgabe.abgabedatum,
campus.tbl_paabgabe.insertvon, campus.tbl_paabgabe.insertamum, campus.tbl_paabgabe.updatevon, campus.tbl_paabgabe.updateamum,
campus.tbl_paabgabe.note, upload_allowed, beurteilungsnotiz, student_uid, tbl_projektarbeit.note, lehre.tbl_projektarbeit.titel,
lehre.tbl_projektbetreuer.betreuerart_kurzbz, lehre.tbl_projektbetreuer.person_id,
public.tbl_person.anrede, public.tbl_person.titelpre, public.tbl_person.vorname, public.tbl_person.nachname, public.tbl_person.titelpost
public function findAbgabenNewOrUpdatedSinceByAbgabedatum($interval, $relevantTypes = null) {
$queryParams = [$interval];
$query = "SELECT projektarbeit_id, paabgabe_id, paabgabetyp_kurzbz, fixtermin, datum, campus.tbl_paabgabe.kurzbz, campus.tbl_paabgabetyp.bezeichnung, campus.tbl_paabgabe.abgabedatum,
campus.tbl_paabgabe.insertvon, campus.tbl_paabgabe.insertamum, campus.tbl_paabgabe.updatevon, campus.tbl_paabgabe.updateamum,
campus.tbl_paabgabe.note, upload_allowed, beurteilungsnotiz, student_uid, tbl_projektarbeit.note, lehre.tbl_projektarbeit.titel,
UPPER(tbl_studiengang.typ) as stgtyp, UPPER(tbl_studiengang.kurzbz) as stgkz, public.tbl_studiengang.studiengang_kz,
public.tbl_studiengang.oe_kurzbz as stg_oe_kurzbz, tbl_lehreinheit.studiensemester_kurzbz,
lehre.tbl_projektbetreuer.betreuerart_kurzbz, lehre.tbl_projektbetreuer.person_id,
public.tbl_person.anrede, public.tbl_person.titelpre, public.tbl_person.vorname, public.tbl_person.nachname, public.tbl_person.titelpost
FROM campus.tbl_paabgabe
JOIN campus.tbl_paabgabetyp USING (paabgabetyp_kurzbz)
JOIN lehre.tbl_projektarbeit USING (projektarbeit_id)
JOIN lehre.tbl_projektbetreuer USING (projektarbeit_id)
JOIN public.tbl_benutzer ON (public.tbl_benutzer.uid = student_uid)
JOIN public.tbl_person ON (public.tbl_benutzer.person_id = public.tbl_person.person_id)
FROM campus.tbl_paabgabe
JOIN campus.tbl_paabgabetyp USING (paabgabetyp_kurzbz)
JOIN lehre.tbl_projektarbeit USING (projektarbeit_id)
JOIN lehre.tbl_projektbetreuer USING (projektarbeit_id)
JOIN lehre.tbl_lehreinheit using(lehreinheit_id)
JOIN lehre.tbl_lehrveranstaltung using(lehrveranstaltung_id)
JOIN public.tbl_studiengang on(lehre.tbl_lehrveranstaltung.studiengang_kz = public.tbl_studiengang.studiengang_kz)
JOIN public.tbl_benutzer ON (public.tbl_benutzer.uid = student_uid)
JOIN public.tbl_person ON (public.tbl_benutzer.person_id = public.tbl_person.person_id)
WHERE campus.tbl_paabgabe.abgabedatum IS NOT NULL
AND campus.tbl_paabgabe.abgabedatum >= NOW() - INTERVAL ?
ORDER BY abgabedatum DESC
";
AND campus.tbl_paabgabe.abgabedatum = CURRENT_DATE - INTERVAL ?";
if($relevantTypes !== null) {
$query .= " AND campus.tbl_paabgabe.paabgabetyp_kurzbz IN ?";
$queryParams[]= $relevantTypes;
}
return $this->execQuery($query, [$interval]);
$query .= " ORDER BY abgabedatum DESC";
return $this->execQuery($query, $queryParams);
}
public function loadByIDs($paabgabe_ids) {
@@ -354,8 +354,10 @@ class Projektarbeit_model extends DB_Model
student_person.nachname as student_nachname,
tbl_student.matrikelnr, tbl_lehreinheit.studiensemester_kurzbz,
betreuer_benutzer.uid as betreuer_benutzer_uid,
betreuer_person.titelpre as betreuer_titelpre,
betreuer_person.vorname as betreuer_vorname,
betreuer_person.nachname as betreuer_nachname,
betreuer_person.titelpost as betreuer_titelpost,
lehre.tbl_projektbetreuer.betreuerart_kurzbz as betreuerart,
lehre.tbl_projektbetreuer.person_id as betreuer_person_id,
lehre.tbl_projektarbeit.sprache as sprache,
@@ -415,6 +417,50 @@ class Projektarbeit_model extends DB_Model
LIMIT 1
)
as zweitbetreuer_full_name,
(
SELECT titelpre
FROM public.tbl_person
JOIN lehre.tbl_projektbetreuer ON (lehre.tbl_projektbetreuer.person_id = public.tbl_person.person_id)
LEFT JOIN public.tbl_benutzer ON (public.tbl_benutzer.person_id = public.tbl_person.person_id)
LEFT JOIN public.tbl_mitarbeiter ON (public.tbl_benutzer.uid = public.tbl_mitarbeiter.mitarbeiter_uid)
WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id
AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter', 'Senatsmitglied')
LIMIT 1
)
as zweitbetreuer_titelpre,
(
SELECT vorname
FROM public.tbl_person
JOIN lehre.tbl_projektbetreuer ON (lehre.tbl_projektbetreuer.person_id = public.tbl_person.person_id)
LEFT JOIN public.tbl_benutzer ON (public.tbl_benutzer.person_id = public.tbl_person.person_id)
LEFT JOIN public.tbl_mitarbeiter ON (public.tbl_benutzer.uid = public.tbl_mitarbeiter.mitarbeiter_uid)
WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id
AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter', 'Senatsmitglied')
LIMIT 1
)
as zweitbetreuer_vorname,
(
SELECT nachname
FROM public.tbl_person
JOIN lehre.tbl_projektbetreuer ON (lehre.tbl_projektbetreuer.person_id = public.tbl_person.person_id)
LEFT JOIN public.tbl_benutzer ON (public.tbl_benutzer.person_id = public.tbl_person.person_id)
LEFT JOIN public.tbl_mitarbeiter ON (public.tbl_benutzer.uid = public.tbl_mitarbeiter.mitarbeiter_uid)
WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id
AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter', 'Senatsmitglied')
LIMIT 1
)
as zweitbetreuer_nachname,
(
SELECT titelpost
FROM public.tbl_person
JOIN lehre.tbl_projektbetreuer ON (lehre.tbl_projektbetreuer.person_id = public.tbl_person.person_id)
LEFT JOIN public.tbl_benutzer ON (public.tbl_benutzer.person_id = public.tbl_person.person_id)
LEFT JOIN public.tbl_mitarbeiter ON (public.tbl_benutzer.uid = public.tbl_mitarbeiter.mitarbeiter_uid)
WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id
AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter', 'Senatsmitglied')
LIMIT 1
)
as zweitbetreuer_titelpost,
(
SELECT
COALESCE(tbl_studienplan.orgform_kurzbz,
@@ -594,7 +594,10 @@ class Studiengang_model extends DB_Model
$this->addSelect('p.prestudent_id');
$this->addSelect('pers.vorname');
$this->addSelect('pers.nachname');
$this->addSelect("CONCAT(UPPER(pers.nachname), ' ', pers.vorname, ' (', " . $this->dbTable . ".bezeichnung, ')') AS name");
$this->addSelect("CONCAT(UPPER(pers.nachname), ' ', pers.vorname, ' (', "
. $this->dbTable . ".bezeichnung, ', ', "
. "UPPER(" . $this->dbTable . ".typ), "
. "UPPER(" . $this->dbTable . ".kurzbz),')') AS name");
$this->addJoin('public.tbl_prestudent p', 'studiengang_kz');
$this->addJoin(
@@ -53,9 +53,11 @@ class Studienjahr_model extends DB_Model
* @param int $days
* @return array|stdClass|null
*/
public function getLastOrAktStudienjahr($days = 0)
public function getLastOrAktStudienjahr($days = 60)
{
$days = is_numeric($days) ? $this->escape($days) : 0;
if (!is_numeric($days)) {
$days = 60;
}
$query = '
SELECT *
@@ -75,25 +77,19 @@ class Studienjahr_model extends DB_Model
* @param int $days
* @return array|stdClass|null
*/
public function getAktOrNextStudienjahr($days = 0)
public function getAktOrNextStudienjahr($days = 62)
{
$days = is_numeric($days) ? $this->escape($days) : 0;
if (!is_numeric($days)) {
$days = 62;
}
$query = '
SELECT * FROM (
SELECT
jahr.*, MIN(sem.start) AS beginn, MAX(sem.ende) AS ende
FROM
public.tbl_studienjahr jahr
JOIN public.tbl_studiensemester sem using(studienjahr_kurzbz)
GROUP BY
studienjahr_kurzbz
) jahre
WHERE
ende >= NOW() + \'' . $days . ' DAYS\'::INTERVAL
ORDER BY
ende
LIMIT 1
SELECT *
FROM public.tbl_studienjahr
JOIN public.tbl_studiensemester using(studienjahr_kurzbz)
WHERE start < NOW() + \'' . $days . ' DAYS\'::INTERVAL
ORDER by start DESC
LIMIT 1
';
return $this->execQuery($query);
@@ -45,44 +45,39 @@ class Studiensemester_model extends DB_Model
/**
* getLastOrAktSemester
* @param $days offset in days, if last semester should be returned instead of current
*/
public function getLastOrAktSemester($days = 0)
public function getLastOrAktSemester($days = 60)
{
if (!is_numeric($days)) $days = 0;
if (!is_numeric($days))
{
$days = 60;
}
$query = '
SELECT
studiensemester_kurzbz, start, ende
FROM
public.tbl_studiensemester
WHERE
start < NOW() - \'' . $this->escape($days) . ' DAYS\'::INTERVAL
ORDER
BY start DESC
LIMIT 1';
$query = 'SELECT studiensemester_kurzbz, start, ende
FROM public.tbl_studiensemester
WHERE start < NOW() - \'' . $days . ' DAYS\'::INTERVAL
ORDER BY start DESC
LIMIT 1';
return $this->execQuery($query);
}
/**
* Returns current semester, or next
* @param $days offset in days, if next semester should be returned earlier
* getNextOrAktSemester
* 62 days - in july and august, semester after summer is returned
*/
public function getAktOrNextSemester($days = 0)
public function getAktOrNextSemester($days = 62)
{
$days = is_numeric($days) ? $this->escape($days) : 0;
if (!is_numeric($days))
{
$days = 62;
}
$query = "
SELECT
studiensemester_kurzbz, start, ende
FROM
public.tbl_studiensemester
WHERE
ende >= NOW() + '". $this->escape($days) . " DAYS'::INTERVAL
ORDER BY
ende
LIMIT 1;";
$query = 'SELECT studiensemester_kurzbz, start, ende
FROM public.tbl_studiensemester
WHERE start < NOW() + \'' . $days . ' DAYS\':: INTERVAL
ORDER BY start DESC
LIMIT 1';
return $this->execQuery($query);
}
@@ -182,19 +177,15 @@ class Studiensemester_model extends DB_Model
*/
public function getByDate($date)
{
// gets the studiensemster of a date or the closest previous studiensemester if a date is not within a studiensemester
// gets the studiensemster of a date or the next closest previous studiensemester if a date is not within a studiensemester
$query = "
SELECT
studiensemester_kurzbz, start, ende
FROM
public.tbl_studiensemester
WHERE
start <= ?::date
ORDER BY
start DESC
SELECT studiensemester_kurzbz, start, ende
FROM public.tbl_studiensemester
WHERE ( ende >= ?::date AND start <= ?::date ) OR ( ende >= ?::date + '-45 days'::interval AND start <= ?::date + '-45 days'::interval )
ORDER BY start DESC
LIMIT 1";
return $this->execQuery($query, array($date));
return $this->execQuery($query, array($date,$date,$date,$date));
}
/**
@@ -209,13 +200,10 @@ class Studiensemester_model extends DB_Model
return success(array());
$query = "
SELECT *
FROM
public.tbl_studiensemester
WHERE
?::date < ende AND ?::date > start
ORDER BY
start DESC";
SELECT *
FROM public.tbl_studiensemester
WHERE ( ?::date < ende AND ?::date > start )
ORDER BY start DESC";
return $this->execQuery($query, array($from, $to));
}
@@ -287,7 +275,7 @@ class Studiensemester_model extends DB_Model
$this->addLimit($minus);
$this->db->where('start <= NOW()', null, false);
$minus = $this->db->get_compiled_select($this->dbTable);
$this->db->where_in($this->pk, '(' . $plus . ') UNION (' . $minus . ')', false);
}
@@ -261,6 +261,42 @@ class Benutzerfunktion_model extends DB_Model
}
/**
* Get active Kompetenzfeldleitung bei UID.
*
* @param $uid
* @return array|stdClass|null
*/
public function getKFLByUID($uid)
{
$query = '
SELECT
bf.uid,
bf.oe_kurzbz,
oe.organisationseinheittyp_kurzbz
FROM
public.tbl_benutzerfunktion bf
JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz)
JOIN public.tbl_benutzer b USING (uid)
WHERE
b.uid = ?
AND b.aktiv = TRUE
AND funktion_kurzbz = \'Leitung\'
AND organisationseinheittyp_kurzbz = \'Kompetenzfeld\'
AND (datum_von IS NULL OR datum_von <= now())
AND (datum_bis IS NULL OR datum_bis >= now())
';
$parameters_array = array();
if (is_string($uid))
{
$parameters_array[] = $uid;
}
return $this->execQuery($query, $parameters_array);
}
public function insertBenutzerfunktion($Json)
{
unset($Json['benutzerfunktion_id']);
@@ -209,7 +209,7 @@ class Mitarbeiter_model extends DB_Model
{
$qry = "
SELECT
titelpre, vorname, nachname, titelpost, foto, foto_sperre, person_id, alias, telefonklappe
titelpre, vorname, nachname, titelpost, foto, foto_sperre, person_id, alias, telefonklappe, personalnummer, mitarbeiter_uid
FROM
public.tbl_person
JOIN public.tbl_benutzer b USING(person_id)
@@ -363,14 +363,14 @@ class Mitarbeiter_model extends DB_Model
$returnwert .= ", ma.mitarbeiter_uid, CONCAT(p.nachname, ' ', p.vorname, ' (', ma.mitarbeiter_uid , ')') as mitarbeiter";
$qry = "
SELECT " . $returnwert . "
FROM
SELECT " . $returnwert . "
FROM
public.tbl_mitarbeiter ma
JOIN
JOIN
public.tbl_benutzer b on (ma.mitarbeiter_uid = b.uid)
JOIN
JOIN
public.tbl_person p on (p.person_id = b.person_id)
WHERE
WHERE
lower (p.nachname) LIKE '%". $this->db->escape_like_str($filter)."%'
OR
lower (p.vorname) LIKE '%". $this->db->escape_like_str($filter)."%'
@@ -393,14 +393,14 @@ class Mitarbeiter_model extends DB_Model
public function getMitarbeiterFromLV($lehrveranstaltung_id)
{
$qry = "SELECT DISTINCT
lehrveranstaltung_id, uid, vorname, wahlname, vornamen, nachname, titelpre, titelpost, kurzbz, mitarbeiter_uid
FROM
lehrveranstaltung_id, uid, vorname, wahlname, vornamen, nachname, titelpre, titelpost, kurzbz, mitarbeiter_uid
FROM
lehre.tbl_lehreinheitmitarbeiter, campus.vw_mitarbeiter, lehre.tbl_lehreinheit
WHERE
WHERE
lehrveranstaltung_id= ?
AND
mitarbeiter_uid=uid
AND
AND
mitarbeiter_uid=uid
AND
tbl_lehreinheitmitarbeiter.lehreinheit_id=tbl_lehreinheit.lehreinheit_id;";
$parametersArray = array($lehrveranstaltung_id);
@@ -470,12 +470,12 @@ class Stundenplan_model extends DB_Model
}
foreach($studentlehrverbaende[$sem_date] as $key=>$lehrverband)
{
$query .= "((sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND sp.verband = ".$this->escape($lehrverband->verband)." AND sp.gruppe = ".$this->escape($lehrverband->gruppe)." AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).")";
$query .= "(((sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND sp.verband = ".$this->escape($lehrverband->verband)." AND sp.gruppe = ".$this->escape($lehrverband->gruppe)." AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).")";
// Eintraege fuer den ganzen Verband
$query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND sp.verband = ".$this->escape($lehrverband->verband)." AND (sp.gruppe is null OR sp.gruppe='') AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).")";
// Eintraege fuer das ganze Semester
$query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND (sp.verband is null OR sp.verband='') AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)
." AND ".$this->escape($sem_date_range->ende).")". $stringGroupLv. ")";
." AND ".$this->escape($sem_date_range->ende).")) AND gruppe_kurzbz is null)";
$query .="OR";
}
+1 -16
View File
@@ -26,22 +26,6 @@ class Extensions_model extends DB_Model
);
}
/**
*
*/
public function getInstalledExtensions()
{
$query = 'SELECT extension_id, e1.name, e1.version, description, license, url, core_version, dependencies, enabled
FROM system.tbl_extensions e1
INNER JOIN (
SELECT name, MAX(version) AS version
FROM system.tbl_extensions
GROUP BY name) e2
ON (e1.name = e2.name AND e1.version = e2.version)';
return $this->execQuery($query);
}
/**
*
*/
@@ -50,3 +34,4 @@ class Extensions_model extends DB_Model
return $this->execQuery($sql);
}
}
+74 -55
View File
@@ -242,74 +242,93 @@ class Message_model extends DB_Model
*/
public function getMessagesForTable($person_id, $offset, $limit)
{
$sql_base = "
SELECT
$limitoffset = (!is_null($offset) && !is_null($limit)) ? 'limit ? offset ?' : '';
$sql = <<<EOSQL
with filtered_messages as (
select
m.message_id, m.person_id as sender_id, mr.person_id as recipient_id
from
public.tbl_msg_message m
join
public.tbl_msg_recipient mr on mr.message_id = m.message_id
where
m.person_id = ?
group by
m.message_id, m.person_id, mr.person_id
union all
select
m.message_id, m.person_id as sender_id, mr.person_id as recipient_id
from
public.tbl_msg_message m
join
public.tbl_msg_recipient mr on mr.message_id = m.message_id
where
mr.person_id = ?
group by
m.message_id, m.person_id, mr.person_id
), lastmsgstatus as (
select
ms.*
from (
select
s.message_id, s.person_id, MAX(s.insertamum) as lastinserted
from
public.tbl_msg_status s
join
filtered_messages fm on fm.message_id = s.message_id and fm.recipient_id = s.person_id
group by
s.message_id, s.person_id
) ls
join
public.tbl_msg_status ms on ms.message_id = ls.message_id and ms.person_id = ls.person_id and ms.insertamum = ls.lastinserted
)
select
(select count(*) from filtered_messages) as total_msgs,
m.message_id AS message_id,
m.subject AS subject,
m.body AS body,
m.insertamum AS insertamum,
m.relationmessage_id AS relationmessage_id,
(SELECT COALESCE(titelpre,'') || ' ' || COALESCE(vorname,'') || ' ' || COALESCE(nachname,'') || ' ' || COALESCE(titelpost,'') FROM public.tbl_person WHERE person_id = m.person_id) as sender,
(SELECT COALESCE(titelpre,'') || ' ' || COALESCE(vorname,'') || ' ' || COALESCE(nachname,'') || ' ' || COALESCE(titelpost,'') FROM public.tbl_person WHERE person_id = r.person_id) as recipient,
m.person_id as sender_id,
r.person_id as recipient_id,
MAX(ss.status) as status,
MAX(ss.insertamum) as statusdatum
FROM public.tbl_msg_message m
JOIN public.tbl_msg_recipient r USING(message_id)
JOIN public.tbl_msg_status ss ON(r.message_id = ss.message_id AND ss.person_id = r.person_id)
WHERE m.person_id = ?
GROUP BY m.message_id, m.subject, m.body, m.insertamum, m.relationmessage_id, sender, recipient, sender_id, recipient_id
UNION ALL
SELECT
m.message_id AS message_id,
m.subject AS subject,
m.body AS body,
m.insertamum AS insertamum,
m.relationmessage_id AS relationmessage_id,
(SELECT COALESCE(titelpre,'') || ' ' || COALESCE(vorname,'') || ' ' || COALESCE(nachname,'') || ' ' || COALESCE(titelpost,'') FROM public.tbl_person WHERE person_id = m.person_id) as sender,
(SELECT COALESCE(titelpre,'') || ' ' || COALESCE(vorname,'') || ' ' || COALESCE(nachname,'') || ' ' || COALESCE(titelpost,'') FROM public.tbl_person WHERE person_id = r.person_id) as recipient,
m.person_id as sender_id,
r.person_id as recipient_id,
MAX(ss.status) as status,
MAX(ss.insertamum) as statusdatum
FROM public.tbl_msg_recipient r
JOIN public.tbl_msg_status ss USING(message_id, person_id)
JOIN public.tbl_msg_message m USING(message_id)
WHERE r.person_id = ?
GROUP BY m.message_id, m.subject, m.body, m.insertamum, m.relationmessage_id, sender, recipient, sender_id, recipient_id
";
$sql = "
SELECT COUNT(*) AS count FROM (
" . $sql_base . "
) a
";
(COALESCE(ps.titelpre,'') || ' ' || COALESCE(ps.vorname,'') || ' ' || COALESCE(ps.nachname,'') || ' ' || COALESCE(ps.titelpost,'')) as sender,
(COALESCE(pr.titelpre,'') || ' ' || COALESCE(pr.vorname,'') || ' ' || COALESCE(pr.nachname,'') || ' ' || COALESCE(pr.titelpost,'')) as recipient,
fm.sender_id,
fm.recipient_id,
ms.status,
ms.insertamum as statusdatum
from
filtered_messages fm
join
public.tbl_msg_message m on fm.message_id = m.message_id
join
lastmsgstatus ms on fm.message_id = ms.message_id and fm.recipient_id = ms.person_id
left join
public.tbl_person ps on ps.person_id = fm.sender_id
left join
public.tbl_person pr on pr.person_id = fm.recipient_id
order by
m.insertamum DESC
{$limitoffset}
EOSQL;
$parametersArray = array($person_id, $person_id);
$count = $this->execQuery($sql, $parametersArray);
if (isError($count))
return $count;
$count = ceil(current(getData($count))->count/$limit);
$sql = "
SELECT * FROM (
" . $sql_base . "
) a
ORDER BY insertamum DESC
LIMIT ?
OFFSET ?
";
$parametersArray = array($person_id, $person_id, $limit, $offset);
$parametersArray = $limitoffset
? array($person_id, $person_id, $limit, $offset)
: array($person_id, $person_id);
$count = 0;
$data = $this->execQuery($sql, $parametersArray);
if (isError($data))
return $data;
$data = getData($data);
if($data)
{
$count = is_null($limit) ? 1 : ceil($data[0]->total_msgs / $limit);
}
return success(['data' => $data, 'count' => $count]);
}
@@ -0,0 +1,11 @@
<?php
class VertragsbestandteilLohnguide_model extends DB_Model
{
public function __construct()
{
parent::__construct();
$this->dbTable = 'hr.tbl_vertragsbestandteil_lohnguide';
$this->pk = 'vertragsbestandteil_id';
}
}
@@ -37,7 +37,8 @@ class Vertragsbestandteil_model extends DB_Model
kf.arbeitgeber_frist, kf.arbeitnehmer_frist,
s.wochenstunden, s.teilzeittyp_kurzbz,
u.tage,
z.zeitaufzeichnung, z.azgrelevant, z.homeoffice
z.zeitaufzeichnung, z.azgrelevant, z.homeoffice,
lg.stellenbezeichnung, lg.vordienstzeit, lg.fachrichtung_kurzbz, lg.modellstelle_kurzbz, lg.kommentar_person, lg.kommentar_modellstelle
FROM
hr.tbl_vertragsbestandteil v
LEFT JOIN
@@ -63,6 +64,8 @@ class Vertragsbestandteil_model extends DB_Model
hr.tbl_vertragsbestandteil_urlaubsanspruch u USING(vertragsbestandteil_id)
LEFT JOIN
hr.tbl_vertragsbestandteil_zeitaufzeichnung z USING(vertragsbestandteil_id)
LEFT JOIN
hr.tbl_vertragsbestandteil_lohnguide lg USING(vertragsbestandteil_id)
EOSQL;
return $sql;
}
+268
View File
@@ -0,0 +1,268 @@
<?php
$phrases = array(
array (
'app' => 'core',
'category' => 'LvPlan',
'phrase' => 'previousWeek',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Vorherige Woche',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Previous week',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'LvPlan',
'phrase' => 'previousYear',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Vorheriges Jahr',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Previous year',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'LvPlan',
'phrase' => 'previousMonth',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Vorheriges Monat',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Previous month',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'LvPlan',
'phrase' => 'previousDay',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Vorheriger Tag',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Previous day',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'LvPlan',
'phrase' => 'nextDay',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Nächster Tag',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Next day',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'LvPlan',
'phrase' => 'nextWeek',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Nächste Woche',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Next week',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'LvPlan',
'phrase' => 'nextMonth',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Nächster Monat',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Next month',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'LvPlan',
'phrase' => 'nextYear',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Nächstes Jahr',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Next year',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'LvPlan',
'phrase' => 'modeDay',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Tages Ansicht',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Daily view',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'LvPlan',
'phrase' => 'modeWeek',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Wochen Ansicht',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Week view',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'LvPlan',
'phrase' => 'modeMonth',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Monats Ansicht',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Month view',
'description' => '',
'insertvon' => 'system',
),
),
),
);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+141
View File
@@ -0,0 +1,141 @@
<?php
/* Copyright (C) 2013 FH Technikum-Wien
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
*/
$phrases = array(
array(
'app' => 'core',
'category' => 'account',
'phrase' => 'title',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Account Aktivierung',
'description' => '',
),
array(
'sprache' => 'English',
'text' => 'Account Activation',
'description' => '',
)
)
),
array(
'app' => 'core',
'category' => 'account',
'phrase' => 'usage',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Bitte wählen Sie ein Passwort für Ihren Account.<br>Das Passwort muss zumindest 8 Zeichen enthalten, davon mindestens 1 Großbuchstabe, 1 Kleinbuchstabe und eine Ziffer.<br>Das Passwort darf keine Leerzeichen und Umlaute enthalten.<br>Erlaubte Sonderzeichen sind: -$#[]{}!().,*:;_',
'description' => '',
),
array(
'sprache' => 'English',
'text' => 'Please choose a password for your account<br>The password must contain at least 8 characters, of which 1 must be upper case, 1 lower case and 1 a numeral.<br>The password may not include spaces or umlauts.<br>The following special characters are allowed: -$#[]{}!().,*:;_',
'description' => '',
)
)
),
array(
'app' => 'core',
'category' => 'account',
'phrase' => 'username',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Username',
'description' => '',
),
array(
'sprache' => 'English',
'text' => 'Username',
'description' => '',
)
)
),
array(
'app' => 'core',
'category' => 'account',
'phrase' => 'code',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Code',
'description' => '',
),
array(
'sprache' => 'English',
'text' => 'Code',
'description' => '',
)
)
),
array(
'app' => 'core',
'category' => 'account',
'phrase' => 'activate',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Abschicken',
'description' => '',
),
array(
'sprache' => 'English',
'text' => 'Activate',
'description' => '',
)
)
),
array(
'app' => 'core',
'category' => 'account',
'phrase' => 'missingParameters',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Bitte geben Sie Benutzername, Code und Passwort ein',
'description' => '',
),
array(
'sprache' => 'English',
'text' => 'Please enter username, code and password',
'description' => '',
)
)
),
array(
'app' => 'core',
'category' => 'account',
'phrase' => 'wrongActivationCode',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Der angegebene Aktivierungscode ist falsch',
'description' => '',
),
array(
'sprache' => 'English',
'text' => 'The provided activation code is wrong',
'description' => '',
)
)
)
);
+388
View File
@@ -0,0 +1,388 @@
<?php
$phrases = array(
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'admission_edit',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Aufnahmetermin bearbeiten',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Edit appointment for participation placement test',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'admission_delete',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Aufnahmetermin Löschen',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Delete Admission Date',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'admission_new',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Termin für Teilnahme am Reihungstest anlegen',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Create appointment for participation placement test',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'anmeldundRtAm',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Anmeldung zum Reihungstest am',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Registration for the ranking test on',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'rtAngetreten',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Zum Reihungstest angetreten',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Participated in the ranking test',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'rtAbsolviert',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Reihungstestverfahren absolviert',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Placement test procedure completed',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'gesamtpunkte',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Gesamtpunkte',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Total Points',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'gesamtpunkteBerechnen',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Gesamtpunkte berechnen',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Calculate total points',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'allgemein',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Allgemein',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Generally',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'headerRTVerwaltung',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Zur Reihungstestverwaltung',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Administration Placement Test',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'loadZukuenftigeRT',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Nur zukünftige Reihungstests laden',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Show future placement tests only',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'getRTErgebnis',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Reihungstestergebnis holen',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Get placement test result',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'stufe',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Stufe',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'level',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'anmeldedatum',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Anmeldedatum',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Registration Date',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'teilgenommen',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'teilgenommen',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'participated',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'admission',
'phrase' => 'stg_kurz',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Kürzel',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'shorthand',
'description' => '',
'insertvon' => 'system',
),
),
),
);
+76
View File
@@ -0,0 +1,76 @@
<?php
$phrases = array(
array (
'app' => 'core',
'category' => 'alert',
'phrase' => 'attention',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Achtung',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Attention',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'alert',
'phrase' => 'confirm_delete',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Möchten Sie wirklich löschen?',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Do you really want to delete?',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'alert',
'phrase' => 'systemerror',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Systemfehler',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'System Error',
'description' => '',
'insertvon' => 'system',
),
),
),
);
+220
View File
@@ -0,0 +1,220 @@
<?php
$phrases = array(
array (
'app' => 'core',
'category' => 'ampeln',
'phrase' => 'newestAmpeln',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Neueste Ampeln',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Newest Ampeln',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'ampeln',
'phrase' => 'allAmpeln',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Alle Ampeln',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'All Ampeln',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'ampeln',
'phrase' => 'overdue',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Überfällig: {count}',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Overdue: {count}',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'ampeln',
'phrase' => 'ampelnDeadline',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Stichtag: {value}',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Deadline: {value}',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'ampeln',
'phrase' => 'noOpenAmpeln',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Keine offenen Ampeln.',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'No open Ampeln.',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'ampeln',
'phrase' => 'allMyAmpeln',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Alle meine Ampeln',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'All my Ampeln',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'ampeln',
'phrase' => 'mandatory',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Pflicht',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Mandatory',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'ampeln',
'phrase' => 'ampelBestaetigt',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Ampel bestätigt',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Ampel confirmed',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'ampeln',
'phrase' => 'super',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Super!',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Super!',
'description' => '',
'insertvon' => 'system',
),
),
),
);
File diff suppressed because it is too large Load Diff
+76
View File
@@ -0,0 +1,76 @@
<?php
$phrases = array(
array (
'app' => 'core',
'category' => 'betriebsmittel',
'phrase' => 'btn_printUebernahmebestaetigung',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Übernahmebestätigung drucken',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Print acceptance confirmation',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'betriebsmittel',
'phrase' => 'btn_editBetriebsmittel',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Betriebsmittel bearbeiten',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Edit Resource',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'betriebsmittel',
'phrase' => 'btn_deleteBetriebsmittel',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Betriebsmittel löschen',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Delete Resource',
'description' => '',
'insertvon' => 'system',
),
),
),
);
+28
View File
@@ -0,0 +1,28 @@
<?php
$phrases = array(
array (
'app' => 'infocenter',
'category' => 'bewerbung',
'phrase' => 'erklaerungInvoices',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Ablauf und Zahlungsbedingungen',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Procedure and terms of payment',
'description' => '',
'insertvon' => 'system',
),
),
),
);
+148
View File
@@ -0,0 +1,148 @@
<?php
$phrases = array(
array (
'app' => 'core',
'category' => 'bismeldestichtag',
'phrase' => 'stichtagHinzufuegen',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Meldestichtag hinzufügen',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Add report target date',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bismeldestichtag',
'phrase' => 'stichtageVerwalten',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'BIS-Meldestichtage verwalten',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Manage report target dates',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bismeldestichtag',
'phrase' => 'stichtagLoeschen',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Meldestichtag löschen',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Delete report target date',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bismeldestichtag',
'phrase' => 'meldestichtag_erreicht',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Meldestichtag erreicht - Bearbeiten nicht mehr möglich',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'report target date reached - editing no longer possible',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bismeldestichtag',
'phrase' => 'info_MeldestichtagStatusgrund',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Meldestichtag erreicht - ausschließlich Bearbeiten Statusgrund möglich',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Reporting deadline reached - only editing status reason possible',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bismeldestichtag',
'phrase' => 'info_MeldestichtagStatusgrundSemester',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Meldestichtag erreicht - Bearbeiten Ausbildungssemester und Statusgrund möglich',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Edit education semester and status reason possible',
'description' => '',
'insertvon' => 'system',
),
),
),
);
+244
View File
@@ -0,0 +1,244 @@
<?php
$phrases = array(
array (
'app' => 'core',
'category' => 'bookmark',
'phrase' => 'newLink',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Neuer Link',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'New Link',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bookmark',
'phrase' => 'saveLink',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Link speichern',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Save link',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bookmark',
'phrase' => 'editLink',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Link bearbeiten',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Edit link',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bookmark',
'phrase' => 'bookmarkDeleted',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Link gelöscht',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Link deleted',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bookmark',
'phrase' => 'bookmarkAdded',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Link hinzugefügt',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Link added',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bookmark',
'phrase' => 'bookmarkUpdated',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Link geändert',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Link updated',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bookmark',
'phrase' => 'myBookmarks',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Meine Urls',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'My Urls',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bookmark',
'phrase' => 'emptyBookmarks',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Du hast noch keine Bookmarks gesetzt',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'You have not set any bookmarks yet',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bookmark',
'phrase' => 'invalidUrl',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Ungültiger Link',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Invalid link',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'bookmark',
'phrase' => 'invalidTitel',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Ungültiger Titel',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Invalid title',
'description' => '',
'insertvon' => 'system',
),
),
),
);
+76
View File
@@ -0,0 +1,76 @@
<?php
$phrases = array(
array (
'app' => 'core',
'category' => 'calendar',
'phrase' => 'kw',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'W',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'W',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'calendar',
'phrase' => 'year_kw',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => '{year} KW {week}',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => '{year} W {week}',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'calendar',
'phrase' => 'today',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Heute',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'today',
'description' => '',
'insertvon' => 'system',
),
),
),
);
+56
View File
@@ -0,0 +1,56 @@
<?php
/* Copyright (C) 2013 FH Technikum-Wien
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
*/
$phrases = array(
array(
'app' => 'core',
'category' => 'captcha',
'phrase' => 'label',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Tippen Sie die angezeigten<br>Zeichen in das untere Feld.',
'description' => '',
),
array(
'sprache' => 'English',
'text' => 'Enter the characters in<br>the field below.',
'description' => '',
)
)
),
array(
'app' => 'core',
'category' => 'captcha',
'phrase' => 'reload',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Ich kann das Bild nicht lesen - neu laden',
'description' => '',
),
array(
'sprache' => 'English',
'text' => 'Reload picture',
'description' => '',
)
)
)
);
+28
View File
@@ -0,0 +1,28 @@
<?php
$phrases = array(
array (
'app' => 'personalverwaltung',
'category' => 'core',
'phrase' => 'unternehmen',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Unternehmen',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'company',
'description' => '',
'insertvon' => 'system',
),
),
),
);
+195
View File
@@ -0,0 +1,195 @@
<?php
$phrases = array(
array (
'app' => 'core',
'category' => 'dashboard',
'phrase' => 'general',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Allgemein',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'General',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'dashboard',
'phrase' => 'addLine',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Weitere Zeile hinzufügen',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Add another line',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'dashboard',
'phrase' => 'custom',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Benutzerdefiniert',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Custom',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'dashboard',
'phrase' => 'dashboardGeneralSectionDescription',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Hier befinden sich die vordefinierten Widgets',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Here are the predefined widgets',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'dashboard',
'phrase' => 'dashboardCustomSectionDescription',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Hier befinden sich die Widgets Ihrer persönlichen Anpassungen',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Here are the widgets of your personal cutomizations',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'dashboard',
'phrase' => 'dashboardSectionDescription',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Hier befinden sich die Widgets der {0} Funktion',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Here are the widgets of the {0} function',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'dashboard',
'phrase' => 'success_savePreset',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Voreinstellung erfolgreich aktualisiert',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Preset successfully updated',
'description' => '',
'insertvon' => 'system',
),
),
)
,
array (
'app' => 'core',
'category' => 'dashboard',
'phrase' => 'alert_deleteWidget',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Sind Sie sicher, dass Sie dieses Widget löschen möchten?',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Are you sure you want to delete this widget?',
'description' => '',
'insertvon' => 'system',
),
),
)
);
+39
View File
@@ -0,0 +1,39 @@
<?php
/* Copyright (C) 2013 FH Technikum-Wien
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
*/
$phrases = array(
array(
'app' => 'core',
'category' => 'dms',
'phrase' => 'informationsblattExterneLehrende',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '<a href="../../../cms/dms.php?id={DMS_ID_INFOBLATT_EXTERNE_LEHRENDE}" target="_blank">Informationsblatt für externe Lehrende</a>',
'description' => '',
),
array(
'sprache' => 'English',
'text' => '<a href="../../../cms/dms.php?id={DMS_ID_INFOBLATT_EXTERNE_LEHRENDE}" target="_blank">Information sheet for external lecturers</a>',
'description' => '',
)
)
)
);
+340
View File
@@ -0,0 +1,340 @@
<?php
$phrases = array(
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_unoconv',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Unoconv nicht gefunden - Bitte installieren sie Unoconv',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Unoconv not found - Please install Unoconv',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_unoconv_version',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Unoconv Version konnte nicht ermittelt werden',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Could not get Unoconv Version',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_conv_timeout',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Dokumentenkonvertierung ist derzeit nicht möglich. Bitte versuchen Sie es in einer Minute erneut oder kontaktieren Sie einen Administrator',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Document conversion is currently not possible. Please try again in a minute or contact an administrator',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_sign_timeout',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Signaturserver ist derzeit nicht erreichbar',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Signature server is currently unavailable',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_sign_pdf',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Derzeit können nur PDFs signiert werden',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Currently only PDFs can be signed',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_outputformat_missing',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Ausgabeformat fehlt',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Outputformat is not defined',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_template_missing',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Keine Vorlage gefunden',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'No template found',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_headers',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Header wurden bereits gesendet -> Abbruch',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Header already sent -> Abort',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_file_copy',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Kopieren fehlgeschlagen',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Copy failed',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_file_load',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Datei konnte nicht geladen werden',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Unable to load file',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_xml_load',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'XML konnte nicht geladen werden: {url} XML: {xml} PARAMETER: {params}',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Unable to load xml: {url} XML: {xml} PARAMS: {params}',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_xsl_load',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'XSL konnte nicht geladen werden',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Unable to load xsl',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_styles_load',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Styles XSL konnte nicht geladen werden',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Unable to load styles xsl',
'description' => '',
'insertvon' => 'system',
),
),
),
array (
'app' => 'core',
'category' => 'document_export',
'phrase' => 'error_manifest',
'insertvon' => 'system',
'phrases' =>
array (
0 =>
array (
'sprache' => 'German',
'text' => 'Manifest ungültig',
'description' => '',
'insertvon' => 'system',
),
1 =>
array (
'sprache' => 'English',
'text' => 'Manifest file invalid',
'description' => '',
'insertvon' => 'system',
),
),
),
);

Some files were not shown because too many files have changed in this diff Show More