diff --git a/.gitignore b/.gitignore index f2e4d7bdb..bd98c9b59 100644 --- a/.gitignore +++ b/.gitignore @@ -1,36 +1,40 @@ -.htaccess -.htaccessbak -bin -/nbproject/ -/vendor/* -!/vendor/FHC-vendor -/.idea/ documents/ +vendor/ + +/nbproject/ +/.idea/ .settings .project .buildpath +.ptp-sync* + +.htaccess +.htaccessbak + application/config/development/ -application/config/testing/ -application/config/production -application/extensions/ -application/controllers/extensions/ application/config/extensions/ +application/config/production +application/config/testing/ +application/controllers/extensions/ +application/extensions/ application/helpers/extensions/ application/hooks/extensions/ application/libraries/extensions/ +application/logs/ application/models/extensions/ application/views/extensions/ application/widgets/extensions/ -application/logs/ + public/extensions/ + tests/codeception/_output/* !/tests/codeception/_output/.placeholder tests/codeception/codeception.yml +tests/codeception/tests/acceptance.suite.yml tests/codeception/tests/api.suite.yml tests/codeception/tests/functional.suite.yml -tests/codeception/tests/acceptance.suite.yml tests/codeception/tests/unit.suite.yml + /sparks/* /webdav/google.php system/sql/ -.ptp-sync* \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d712a143..fe2a855d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -119,7 +119,7 @@ - **[DEPRECATED]** Spalte ort_kurzbz in tbl_reihungstest wird nicht mehr verwendet und in zukünftigen Versionen entfernt Zum Update auf diese Version folgen Sie den Anweisungen auf folgender Seite: -http://fhcomplete.technikum-wien.at/dokuwiki/doku.php?id=fh-complete:codeigniter +https://wiki.fhcomplete.org/doku.php?id=fh-complete:codeigniter ## [3.1.0] - 2015-11-12 ### Added diff --git a/vendor/FHC-vendor/angular-tablesort/.gitignore b/FHC-vendor/angular-tablesort/.gitignore similarity index 100% rename from vendor/FHC-vendor/angular-tablesort/.gitignore rename to FHC-vendor/angular-tablesort/.gitignore diff --git a/vendor/FHC-vendor/angular-tablesort/LICENSE b/FHC-vendor/angular-tablesort/LICENSE similarity index 100% rename from vendor/FHC-vendor/angular-tablesort/LICENSE rename to FHC-vendor/angular-tablesort/LICENSE diff --git a/vendor/FHC-vendor/angular-tablesort/README.md b/FHC-vendor/angular-tablesort/README.md similarity index 100% rename from vendor/FHC-vendor/angular-tablesort/README.md rename to FHC-vendor/angular-tablesort/README.md diff --git a/vendor/FHC-vendor/angular-tablesort/bower.json b/FHC-vendor/angular-tablesort/bower.json similarity index 100% rename from vendor/FHC-vendor/angular-tablesort/bower.json rename to FHC-vendor/angular-tablesort/bower.json diff --git a/vendor/FHC-vendor/angular-tablesort/example.html b/FHC-vendor/angular-tablesort/example.html similarity index 100% rename from vendor/FHC-vendor/angular-tablesort/example.html rename to FHC-vendor/angular-tablesort/example.html diff --git a/vendor/FHC-vendor/angular-tablesort/index.js b/FHC-vendor/angular-tablesort/index.js similarity index 100% rename from vendor/FHC-vendor/angular-tablesort/index.js rename to FHC-vendor/angular-tablesort/index.js diff --git a/vendor/FHC-vendor/angular-tablesort/js/angular-tablesort.js b/FHC-vendor/angular-tablesort/js/angular-tablesort.js similarity index 100% rename from vendor/FHC-vendor/angular-tablesort/js/angular-tablesort.js rename to FHC-vendor/angular-tablesort/js/angular-tablesort.js diff --git a/vendor/FHC-vendor/angular-tablesort/package.json b/FHC-vendor/angular-tablesort/package.json similarity index 100% rename from vendor/FHC-vendor/angular-tablesort/package.json rename to FHC-vendor/angular-tablesort/package.json diff --git a/vendor/FHC-vendor/angular-tablesort/tablesort.css b/FHC-vendor/angular-tablesort/tablesort.css similarity index 100% rename from vendor/FHC-vendor/angular-tablesort/tablesort.css rename to FHC-vendor/angular-tablesort/tablesort.css diff --git a/vendor/FHC-vendor/easyui/changelog.txt b/FHC-vendor/easyui/changelog.txt similarity index 100% rename from vendor/FHC-vendor/easyui/changelog.txt rename to FHC-vendor/easyui/changelog.txt diff --git a/vendor/FHC-vendor/easyui/easyloader.js b/FHC-vendor/easyui/easyloader.js similarity index 100% rename from vendor/FHC-vendor/easyui/easyloader.js rename to FHC-vendor/easyui/easyloader.js diff --git a/vendor/FHC-vendor/easyui/jquery.easyui.min.js b/FHC-vendor/easyui/jquery.easyui.min.js similarity index 100% rename from vendor/FHC-vendor/easyui/jquery.easyui.min.js rename to FHC-vendor/easyui/jquery.easyui.min.js diff --git a/vendor/FHC-vendor/easyui/jquery.easyui.mobile.js b/FHC-vendor/easyui/jquery.easyui.mobile.js similarity index 100% rename from vendor/FHC-vendor/easyui/jquery.easyui.mobile.js rename to FHC-vendor/easyui/jquery.easyui.mobile.js diff --git a/vendor/FHC-vendor/easyui/jquery.min.js b/FHC-vendor/easyui/jquery.min.js similarity index 100% rename from vendor/FHC-vendor/easyui/jquery.min.js rename to FHC-vendor/easyui/jquery.min.js diff --git a/vendor/FHC-vendor/easyui/license_freeware.txt b/FHC-vendor/easyui/license_freeware.txt similarity index 100% rename from vendor/FHC-vendor/easyui/license_freeware.txt rename to FHC-vendor/easyui/license_freeware.txt diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-af.js b/FHC-vendor/easyui/locale/easyui-lang-af.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-af.js rename to FHC-vendor/easyui/locale/easyui-lang-af.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-am.js b/FHC-vendor/easyui/locale/easyui-lang-am.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-am.js rename to FHC-vendor/easyui/locale/easyui-lang-am.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-ar.js b/FHC-vendor/easyui/locale/easyui-lang-ar.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-ar.js rename to FHC-vendor/easyui/locale/easyui-lang-ar.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-bg.js b/FHC-vendor/easyui/locale/easyui-lang-bg.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-bg.js rename to FHC-vendor/easyui/locale/easyui-lang-bg.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-ca.js b/FHC-vendor/easyui/locale/easyui-lang-ca.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-ca.js rename to FHC-vendor/easyui/locale/easyui-lang-ca.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-cs.js b/FHC-vendor/easyui/locale/easyui-lang-cs.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-cs.js rename to FHC-vendor/easyui/locale/easyui-lang-cs.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-cz.js b/FHC-vendor/easyui/locale/easyui-lang-cz.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-cz.js rename to FHC-vendor/easyui/locale/easyui-lang-cz.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-da.js b/FHC-vendor/easyui/locale/easyui-lang-da.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-da.js rename to FHC-vendor/easyui/locale/easyui-lang-da.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-de.js b/FHC-vendor/easyui/locale/easyui-lang-de.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-de.js rename to FHC-vendor/easyui/locale/easyui-lang-de.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-el.js b/FHC-vendor/easyui/locale/easyui-lang-el.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-el.js rename to FHC-vendor/easyui/locale/easyui-lang-el.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-en.js b/FHC-vendor/easyui/locale/easyui-lang-en.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-en.js rename to FHC-vendor/easyui/locale/easyui-lang-en.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-es.js b/FHC-vendor/easyui/locale/easyui-lang-es.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-es.js rename to FHC-vendor/easyui/locale/easyui-lang-es.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-fr.js b/FHC-vendor/easyui/locale/easyui-lang-fr.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-fr.js rename to FHC-vendor/easyui/locale/easyui-lang-fr.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-it.js b/FHC-vendor/easyui/locale/easyui-lang-it.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-it.js rename to FHC-vendor/easyui/locale/easyui-lang-it.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-jp.js b/FHC-vendor/easyui/locale/easyui-lang-jp.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-jp.js rename to FHC-vendor/easyui/locale/easyui-lang-jp.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-nl.js b/FHC-vendor/easyui/locale/easyui-lang-nl.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-nl.js rename to FHC-vendor/easyui/locale/easyui-lang-nl.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-pl.js b/FHC-vendor/easyui/locale/easyui-lang-pl.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-pl.js rename to FHC-vendor/easyui/locale/easyui-lang-pl.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-pt_BR.js b/FHC-vendor/easyui/locale/easyui-lang-pt_BR.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-pt_BR.js rename to FHC-vendor/easyui/locale/easyui-lang-pt_BR.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-ru.js b/FHC-vendor/easyui/locale/easyui-lang-ru.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-ru.js rename to FHC-vendor/easyui/locale/easyui-lang-ru.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-sv_SE.js b/FHC-vendor/easyui/locale/easyui-lang-sv_SE.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-sv_SE.js rename to FHC-vendor/easyui/locale/easyui-lang-sv_SE.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-tr.js b/FHC-vendor/easyui/locale/easyui-lang-tr.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-tr.js rename to FHC-vendor/easyui/locale/easyui-lang-tr.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-zh_CN.js b/FHC-vendor/easyui/locale/easyui-lang-zh_CN.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-zh_CN.js rename to FHC-vendor/easyui/locale/easyui-lang-zh_CN.js diff --git a/vendor/FHC-vendor/easyui/locale/easyui-lang-zh_TW.js b/FHC-vendor/easyui/locale/easyui-lang-zh_TW.js similarity index 100% rename from vendor/FHC-vendor/easyui/locale/easyui-lang-zh_TW.js rename to FHC-vendor/easyui/locale/easyui-lang-zh_TW.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.accordion.js b/FHC-vendor/easyui/plugins/jquery.accordion.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.accordion.js rename to FHC-vendor/easyui/plugins/jquery.accordion.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.calendar.js b/FHC-vendor/easyui/plugins/jquery.calendar.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.calendar.js rename to FHC-vendor/easyui/plugins/jquery.calendar.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.combo.js b/FHC-vendor/easyui/plugins/jquery.combo.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.combo.js rename to FHC-vendor/easyui/plugins/jquery.combo.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.combobox.js b/FHC-vendor/easyui/plugins/jquery.combobox.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.combobox.js rename to FHC-vendor/easyui/plugins/jquery.combobox.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.combogrid.js b/FHC-vendor/easyui/plugins/jquery.combogrid.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.combogrid.js rename to FHC-vendor/easyui/plugins/jquery.combogrid.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.combotree.js b/FHC-vendor/easyui/plugins/jquery.combotree.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.combotree.js rename to FHC-vendor/easyui/plugins/jquery.combotree.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.datagrid.js b/FHC-vendor/easyui/plugins/jquery.datagrid.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.datagrid.js rename to FHC-vendor/easyui/plugins/jquery.datagrid.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.datalist.js b/FHC-vendor/easyui/plugins/jquery.datalist.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.datalist.js rename to FHC-vendor/easyui/plugins/jquery.datalist.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.datebox.js b/FHC-vendor/easyui/plugins/jquery.datebox.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.datebox.js rename to FHC-vendor/easyui/plugins/jquery.datebox.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.datetimebox.js b/FHC-vendor/easyui/plugins/jquery.datetimebox.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.datetimebox.js rename to FHC-vendor/easyui/plugins/jquery.datetimebox.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.datetimespinner.js b/FHC-vendor/easyui/plugins/jquery.datetimespinner.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.datetimespinner.js rename to FHC-vendor/easyui/plugins/jquery.datetimespinner.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.dialog.js b/FHC-vendor/easyui/plugins/jquery.dialog.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.dialog.js rename to FHC-vendor/easyui/plugins/jquery.dialog.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.draggable.js b/FHC-vendor/easyui/plugins/jquery.draggable.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.draggable.js rename to FHC-vendor/easyui/plugins/jquery.draggable.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.droppable.js b/FHC-vendor/easyui/plugins/jquery.droppable.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.droppable.js rename to FHC-vendor/easyui/plugins/jquery.droppable.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.filebox.js b/FHC-vendor/easyui/plugins/jquery.filebox.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.filebox.js rename to FHC-vendor/easyui/plugins/jquery.filebox.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.form.js b/FHC-vendor/easyui/plugins/jquery.form.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.form.js rename to FHC-vendor/easyui/plugins/jquery.form.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.layout.js b/FHC-vendor/easyui/plugins/jquery.layout.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.layout.js rename to FHC-vendor/easyui/plugins/jquery.layout.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.linkbutton.js b/FHC-vendor/easyui/plugins/jquery.linkbutton.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.linkbutton.js rename to FHC-vendor/easyui/plugins/jquery.linkbutton.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.menu.js b/FHC-vendor/easyui/plugins/jquery.menu.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.menu.js rename to FHC-vendor/easyui/plugins/jquery.menu.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.menubutton.js b/FHC-vendor/easyui/plugins/jquery.menubutton.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.menubutton.js rename to FHC-vendor/easyui/plugins/jquery.menubutton.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.messager.js b/FHC-vendor/easyui/plugins/jquery.messager.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.messager.js rename to FHC-vendor/easyui/plugins/jquery.messager.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.mobile.js b/FHC-vendor/easyui/plugins/jquery.mobile.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.mobile.js rename to FHC-vendor/easyui/plugins/jquery.mobile.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.numberbox.js b/FHC-vendor/easyui/plugins/jquery.numberbox.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.numberbox.js rename to FHC-vendor/easyui/plugins/jquery.numberbox.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.numberspinner.js b/FHC-vendor/easyui/plugins/jquery.numberspinner.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.numberspinner.js rename to FHC-vendor/easyui/plugins/jquery.numberspinner.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.pagination.js b/FHC-vendor/easyui/plugins/jquery.pagination.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.pagination.js rename to FHC-vendor/easyui/plugins/jquery.pagination.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.panel.js b/FHC-vendor/easyui/plugins/jquery.panel.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.panel.js rename to FHC-vendor/easyui/plugins/jquery.panel.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.parser.js b/FHC-vendor/easyui/plugins/jquery.parser.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.parser.js rename to FHC-vendor/easyui/plugins/jquery.parser.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.progressbar.js b/FHC-vendor/easyui/plugins/jquery.progressbar.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.progressbar.js rename to FHC-vendor/easyui/plugins/jquery.progressbar.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.propertygrid.js b/FHC-vendor/easyui/plugins/jquery.propertygrid.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.propertygrid.js rename to FHC-vendor/easyui/plugins/jquery.propertygrid.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.resizable.js b/FHC-vendor/easyui/plugins/jquery.resizable.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.resizable.js rename to FHC-vendor/easyui/plugins/jquery.resizable.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.searchbox.js b/FHC-vendor/easyui/plugins/jquery.searchbox.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.searchbox.js rename to FHC-vendor/easyui/plugins/jquery.searchbox.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.slider.js b/FHC-vendor/easyui/plugins/jquery.slider.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.slider.js rename to FHC-vendor/easyui/plugins/jquery.slider.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.spinner.js b/FHC-vendor/easyui/plugins/jquery.spinner.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.spinner.js rename to FHC-vendor/easyui/plugins/jquery.spinner.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.splitbutton.js b/FHC-vendor/easyui/plugins/jquery.splitbutton.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.splitbutton.js rename to FHC-vendor/easyui/plugins/jquery.splitbutton.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.switchbutton.js b/FHC-vendor/easyui/plugins/jquery.switchbutton.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.switchbutton.js rename to FHC-vendor/easyui/plugins/jquery.switchbutton.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.tabs.js b/FHC-vendor/easyui/plugins/jquery.tabs.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.tabs.js rename to FHC-vendor/easyui/plugins/jquery.tabs.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.textbox.js b/FHC-vendor/easyui/plugins/jquery.textbox.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.textbox.js rename to FHC-vendor/easyui/plugins/jquery.textbox.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.timespinner.js b/FHC-vendor/easyui/plugins/jquery.timespinner.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.timespinner.js rename to FHC-vendor/easyui/plugins/jquery.timespinner.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.tooltip.js b/FHC-vendor/easyui/plugins/jquery.tooltip.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.tooltip.js rename to FHC-vendor/easyui/plugins/jquery.tooltip.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.tree.js b/FHC-vendor/easyui/plugins/jquery.tree.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.tree.js rename to FHC-vendor/easyui/plugins/jquery.tree.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.treegrid.js b/FHC-vendor/easyui/plugins/jquery.treegrid.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.treegrid.js rename to FHC-vendor/easyui/plugins/jquery.treegrid.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.validatebox.js b/FHC-vendor/easyui/plugins/jquery.validatebox.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.validatebox.js rename to FHC-vendor/easyui/plugins/jquery.validatebox.js diff --git a/vendor/FHC-vendor/easyui/plugins/jquery.window.js b/FHC-vendor/easyui/plugins/jquery.window.js similarity index 100% rename from vendor/FHC-vendor/easyui/plugins/jquery.window.js rename to FHC-vendor/easyui/plugins/jquery.window.js diff --git a/vendor/FHC-vendor/easyui/readme.txt b/FHC-vendor/easyui/readme.txt similarity index 100% rename from vendor/FHC-vendor/easyui/readme.txt rename to FHC-vendor/easyui/readme.txt diff --git a/vendor/FHC-vendor/easyui/src/easyloader.js b/FHC-vendor/easyui/src/easyloader.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/easyloader.js rename to FHC-vendor/easyui/src/easyloader.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.accordion.js b/FHC-vendor/easyui/src/jquery.accordion.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.accordion.js rename to FHC-vendor/easyui/src/jquery.accordion.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.calendar.js b/FHC-vendor/easyui/src/jquery.calendar.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.calendar.js rename to FHC-vendor/easyui/src/jquery.calendar.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.combobox.js b/FHC-vendor/easyui/src/jquery.combobox.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.combobox.js rename to FHC-vendor/easyui/src/jquery.combobox.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.datebox.js b/FHC-vendor/easyui/src/jquery.datebox.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.datebox.js rename to FHC-vendor/easyui/src/jquery.datebox.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.draggable.js b/FHC-vendor/easyui/src/jquery.draggable.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.draggable.js rename to FHC-vendor/easyui/src/jquery.draggable.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.droppable.js b/FHC-vendor/easyui/src/jquery.droppable.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.droppable.js rename to FHC-vendor/easyui/src/jquery.droppable.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.form.js b/FHC-vendor/easyui/src/jquery.form.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.form.js rename to FHC-vendor/easyui/src/jquery.form.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.linkbutton.js b/FHC-vendor/easyui/src/jquery.linkbutton.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.linkbutton.js rename to FHC-vendor/easyui/src/jquery.linkbutton.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.menu.js b/FHC-vendor/easyui/src/jquery.menu.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.menu.js rename to FHC-vendor/easyui/src/jquery.menu.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.parser.js b/FHC-vendor/easyui/src/jquery.parser.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.parser.js rename to FHC-vendor/easyui/src/jquery.parser.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.progressbar.js b/FHC-vendor/easyui/src/jquery.progressbar.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.progressbar.js rename to FHC-vendor/easyui/src/jquery.progressbar.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.propertygrid.js b/FHC-vendor/easyui/src/jquery.propertygrid.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.propertygrid.js rename to FHC-vendor/easyui/src/jquery.propertygrid.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.resizable.js b/FHC-vendor/easyui/src/jquery.resizable.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.resizable.js rename to FHC-vendor/easyui/src/jquery.resizable.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.slider.js b/FHC-vendor/easyui/src/jquery.slider.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.slider.js rename to FHC-vendor/easyui/src/jquery.slider.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.tabs.js b/FHC-vendor/easyui/src/jquery.tabs.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.tabs.js rename to FHC-vendor/easyui/src/jquery.tabs.js diff --git a/vendor/FHC-vendor/easyui/src/jquery.window.js b/FHC-vendor/easyui/src/jquery.window.js similarity index 100% rename from vendor/FHC-vendor/easyui/src/jquery.window.js rename to FHC-vendor/easyui/src/jquery.window.js diff --git a/vendor/FHC-vendor/easyui/themes/black/accordion.css b/FHC-vendor/easyui/themes/black/accordion.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/accordion.css rename to FHC-vendor/easyui/themes/black/accordion.css diff --git a/vendor/FHC-vendor/easyui/themes/black/calendar.css b/FHC-vendor/easyui/themes/black/calendar.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/calendar.css rename to FHC-vendor/easyui/themes/black/calendar.css diff --git a/vendor/FHC-vendor/easyui/themes/black/combo.css b/FHC-vendor/easyui/themes/black/combo.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/combo.css rename to FHC-vendor/easyui/themes/black/combo.css diff --git a/vendor/FHC-vendor/easyui/themes/black/combobox.css b/FHC-vendor/easyui/themes/black/combobox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/combobox.css rename to FHC-vendor/easyui/themes/black/combobox.css diff --git a/vendor/FHC-vendor/easyui/themes/black/datagrid.css b/FHC-vendor/easyui/themes/black/datagrid.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/datagrid.css rename to FHC-vendor/easyui/themes/black/datagrid.css diff --git a/vendor/FHC-vendor/easyui/themes/black/datalist.css b/FHC-vendor/easyui/themes/black/datalist.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/datalist.css rename to FHC-vendor/easyui/themes/black/datalist.css diff --git a/vendor/FHC-vendor/easyui/themes/black/datebox.css b/FHC-vendor/easyui/themes/black/datebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/datebox.css rename to FHC-vendor/easyui/themes/black/datebox.css diff --git a/vendor/FHC-vendor/easyui/themes/black/dialog.css b/FHC-vendor/easyui/themes/black/dialog.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/dialog.css rename to FHC-vendor/easyui/themes/black/dialog.css diff --git a/vendor/FHC-vendor/easyui/themes/black/easyui.css b/FHC-vendor/easyui/themes/black/easyui.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/easyui.css rename to FHC-vendor/easyui/themes/black/easyui.css diff --git a/vendor/FHC-vendor/easyui/themes/black/filebox.css b/FHC-vendor/easyui/themes/black/filebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/filebox.css rename to FHC-vendor/easyui/themes/black/filebox.css diff --git a/vendor/FHC-vendor/easyui/themes/black/images/accordion_arrows.png b/FHC-vendor/easyui/themes/black/images/accordion_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/accordion_arrows.png rename to FHC-vendor/easyui/themes/black/images/accordion_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/blank.gif b/FHC-vendor/easyui/themes/black/images/blank.gif similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/blank.gif rename to FHC-vendor/easyui/themes/black/images/blank.gif diff --git a/vendor/FHC-vendor/easyui/themes/black/images/calendar_arrows.png b/FHC-vendor/easyui/themes/black/images/calendar_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/calendar_arrows.png rename to FHC-vendor/easyui/themes/black/images/calendar_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/combo_arrow.png b/FHC-vendor/easyui/themes/black/images/combo_arrow.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/combo_arrow.png rename to FHC-vendor/easyui/themes/black/images/combo_arrow.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/datagrid_icons.png b/FHC-vendor/easyui/themes/black/images/datagrid_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/datagrid_icons.png rename to FHC-vendor/easyui/themes/black/images/datagrid_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/datebox_arrow.png b/FHC-vendor/easyui/themes/black/images/datebox_arrow.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/datebox_arrow.png rename to FHC-vendor/easyui/themes/black/images/datebox_arrow.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/layout_arrows.png b/FHC-vendor/easyui/themes/black/images/layout_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/layout_arrows.png rename to FHC-vendor/easyui/themes/black/images/layout_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/linkbutton_bg.png b/FHC-vendor/easyui/themes/black/images/linkbutton_bg.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/linkbutton_bg.png rename to FHC-vendor/easyui/themes/black/images/linkbutton_bg.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/loading.gif b/FHC-vendor/easyui/themes/black/images/loading.gif similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/loading.gif rename to FHC-vendor/easyui/themes/black/images/loading.gif diff --git a/vendor/FHC-vendor/easyui/themes/black/images/menu_arrows.png b/FHC-vendor/easyui/themes/black/images/menu_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/menu_arrows.png rename to FHC-vendor/easyui/themes/black/images/menu_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/messager_icons.png b/FHC-vendor/easyui/themes/black/images/messager_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/messager_icons.png rename to FHC-vendor/easyui/themes/black/images/messager_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/pagination_icons.png b/FHC-vendor/easyui/themes/black/images/pagination_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/pagination_icons.png rename to FHC-vendor/easyui/themes/black/images/pagination_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/panel_tools.png b/FHC-vendor/easyui/themes/black/images/panel_tools.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/panel_tools.png rename to FHC-vendor/easyui/themes/black/images/panel_tools.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/searchbox_button.png b/FHC-vendor/easyui/themes/black/images/searchbox_button.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/searchbox_button.png rename to FHC-vendor/easyui/themes/black/images/searchbox_button.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/slider_handle.png b/FHC-vendor/easyui/themes/black/images/slider_handle.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/slider_handle.png rename to FHC-vendor/easyui/themes/black/images/slider_handle.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/spinner_arrows.png b/FHC-vendor/easyui/themes/black/images/spinner_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/spinner_arrows.png rename to FHC-vendor/easyui/themes/black/images/spinner_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/tabs_icons.png b/FHC-vendor/easyui/themes/black/images/tabs_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/tabs_icons.png rename to FHC-vendor/easyui/themes/black/images/tabs_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/tree_icons.png b/FHC-vendor/easyui/themes/black/images/tree_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/tree_icons.png rename to FHC-vendor/easyui/themes/black/images/tree_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/black/images/validatebox_warning.png b/FHC-vendor/easyui/themes/black/images/validatebox_warning.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/images/validatebox_warning.png rename to FHC-vendor/easyui/themes/black/images/validatebox_warning.png diff --git a/vendor/FHC-vendor/easyui/themes/black/layout.css b/FHC-vendor/easyui/themes/black/layout.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/layout.css rename to FHC-vendor/easyui/themes/black/layout.css diff --git a/vendor/FHC-vendor/easyui/themes/black/linkbutton.css b/FHC-vendor/easyui/themes/black/linkbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/linkbutton.css rename to FHC-vendor/easyui/themes/black/linkbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/black/menu.css b/FHC-vendor/easyui/themes/black/menu.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/menu.css rename to FHC-vendor/easyui/themes/black/menu.css diff --git a/vendor/FHC-vendor/easyui/themes/black/menubutton.css b/FHC-vendor/easyui/themes/black/menubutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/menubutton.css rename to FHC-vendor/easyui/themes/black/menubutton.css diff --git a/vendor/FHC-vendor/easyui/themes/black/messager.css b/FHC-vendor/easyui/themes/black/messager.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/messager.css rename to FHC-vendor/easyui/themes/black/messager.css diff --git a/vendor/FHC-vendor/easyui/themes/black/numberbox.css b/FHC-vendor/easyui/themes/black/numberbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/numberbox.css rename to FHC-vendor/easyui/themes/black/numberbox.css diff --git a/vendor/FHC-vendor/easyui/themes/black/pagination.css b/FHC-vendor/easyui/themes/black/pagination.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/pagination.css rename to FHC-vendor/easyui/themes/black/pagination.css diff --git a/vendor/FHC-vendor/easyui/themes/black/panel.css b/FHC-vendor/easyui/themes/black/panel.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/panel.css rename to FHC-vendor/easyui/themes/black/panel.css diff --git a/vendor/FHC-vendor/easyui/themes/black/progressbar.css b/FHC-vendor/easyui/themes/black/progressbar.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/progressbar.css rename to FHC-vendor/easyui/themes/black/progressbar.css diff --git a/vendor/FHC-vendor/easyui/themes/black/propertygrid.css b/FHC-vendor/easyui/themes/black/propertygrid.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/propertygrid.css rename to FHC-vendor/easyui/themes/black/propertygrid.css diff --git a/vendor/FHC-vendor/easyui/themes/black/searchbox.css b/FHC-vendor/easyui/themes/black/searchbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/searchbox.css rename to FHC-vendor/easyui/themes/black/searchbox.css diff --git a/vendor/FHC-vendor/easyui/themes/black/slider.css b/FHC-vendor/easyui/themes/black/slider.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/slider.css rename to FHC-vendor/easyui/themes/black/slider.css diff --git a/vendor/FHC-vendor/easyui/themes/black/spinner.css b/FHC-vendor/easyui/themes/black/spinner.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/spinner.css rename to FHC-vendor/easyui/themes/black/spinner.css diff --git a/vendor/FHC-vendor/easyui/themes/black/splitbutton.css b/FHC-vendor/easyui/themes/black/splitbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/splitbutton.css rename to FHC-vendor/easyui/themes/black/splitbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/black/switchbutton.css b/FHC-vendor/easyui/themes/black/switchbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/switchbutton.css rename to FHC-vendor/easyui/themes/black/switchbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/black/tabs.css b/FHC-vendor/easyui/themes/black/tabs.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/tabs.css rename to FHC-vendor/easyui/themes/black/tabs.css diff --git a/vendor/FHC-vendor/easyui/themes/black/textbox.css b/FHC-vendor/easyui/themes/black/textbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/textbox.css rename to FHC-vendor/easyui/themes/black/textbox.css diff --git a/vendor/FHC-vendor/easyui/themes/black/tooltip.css b/FHC-vendor/easyui/themes/black/tooltip.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/tooltip.css rename to FHC-vendor/easyui/themes/black/tooltip.css diff --git a/vendor/FHC-vendor/easyui/themes/black/tree.css b/FHC-vendor/easyui/themes/black/tree.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/tree.css rename to FHC-vendor/easyui/themes/black/tree.css diff --git a/vendor/FHC-vendor/easyui/themes/black/validatebox.css b/FHC-vendor/easyui/themes/black/validatebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/validatebox.css rename to FHC-vendor/easyui/themes/black/validatebox.css diff --git a/vendor/FHC-vendor/easyui/themes/black/window.css b/FHC-vendor/easyui/themes/black/window.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/black/window.css rename to FHC-vendor/easyui/themes/black/window.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/accordion.css b/FHC-vendor/easyui/themes/bootstrap/accordion.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/accordion.css rename to FHC-vendor/easyui/themes/bootstrap/accordion.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/calendar.css b/FHC-vendor/easyui/themes/bootstrap/calendar.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/calendar.css rename to FHC-vendor/easyui/themes/bootstrap/calendar.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/combo.css b/FHC-vendor/easyui/themes/bootstrap/combo.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/combo.css rename to FHC-vendor/easyui/themes/bootstrap/combo.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/combobox.css b/FHC-vendor/easyui/themes/bootstrap/combobox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/combobox.css rename to FHC-vendor/easyui/themes/bootstrap/combobox.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/datagrid.css b/FHC-vendor/easyui/themes/bootstrap/datagrid.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/datagrid.css rename to FHC-vendor/easyui/themes/bootstrap/datagrid.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/datebox.css b/FHC-vendor/easyui/themes/bootstrap/datebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/datebox.css rename to FHC-vendor/easyui/themes/bootstrap/datebox.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/dialog.css b/FHC-vendor/easyui/themes/bootstrap/dialog.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/dialog.css rename to FHC-vendor/easyui/themes/bootstrap/dialog.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/easyui.css b/FHC-vendor/easyui/themes/bootstrap/easyui.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/easyui.css rename to FHC-vendor/easyui/themes/bootstrap/easyui.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/filebox.css b/FHC-vendor/easyui/themes/bootstrap/filebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/filebox.css rename to FHC-vendor/easyui/themes/bootstrap/filebox.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/accordion_arrows.png b/FHC-vendor/easyui/themes/bootstrap/images/accordion_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/accordion_arrows.png rename to FHC-vendor/easyui/themes/bootstrap/images/accordion_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/blank.gif b/FHC-vendor/easyui/themes/bootstrap/images/blank.gif similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/blank.gif rename to FHC-vendor/easyui/themes/bootstrap/images/blank.gif diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/calendar_arrows.png b/FHC-vendor/easyui/themes/bootstrap/images/calendar_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/calendar_arrows.png rename to FHC-vendor/easyui/themes/bootstrap/images/calendar_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/combo_arrow.png b/FHC-vendor/easyui/themes/bootstrap/images/combo_arrow.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/combo_arrow.png rename to FHC-vendor/easyui/themes/bootstrap/images/combo_arrow.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/datagrid_icons.png b/FHC-vendor/easyui/themes/bootstrap/images/datagrid_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/datagrid_icons.png rename to FHC-vendor/easyui/themes/bootstrap/images/datagrid_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/datebox_arrow.png b/FHC-vendor/easyui/themes/bootstrap/images/datebox_arrow.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/datebox_arrow.png rename to FHC-vendor/easyui/themes/bootstrap/images/datebox_arrow.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/layout_arrows.png b/FHC-vendor/easyui/themes/bootstrap/images/layout_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/layout_arrows.png rename to FHC-vendor/easyui/themes/bootstrap/images/layout_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/linkbutton_bg.png b/FHC-vendor/easyui/themes/bootstrap/images/linkbutton_bg.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/linkbutton_bg.png rename to FHC-vendor/easyui/themes/bootstrap/images/linkbutton_bg.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/loading.gif b/FHC-vendor/easyui/themes/bootstrap/images/loading.gif similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/loading.gif rename to FHC-vendor/easyui/themes/bootstrap/images/loading.gif diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/menu_arrows.png b/FHC-vendor/easyui/themes/bootstrap/images/menu_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/menu_arrows.png rename to FHC-vendor/easyui/themes/bootstrap/images/menu_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/messager_icons.png b/FHC-vendor/easyui/themes/bootstrap/images/messager_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/messager_icons.png rename to FHC-vendor/easyui/themes/bootstrap/images/messager_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/pagination_icons.png b/FHC-vendor/easyui/themes/bootstrap/images/pagination_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/pagination_icons.png rename to FHC-vendor/easyui/themes/bootstrap/images/pagination_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/panel_tools.png b/FHC-vendor/easyui/themes/bootstrap/images/panel_tools.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/panel_tools.png rename to FHC-vendor/easyui/themes/bootstrap/images/panel_tools.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/searchbox_button.png b/FHC-vendor/easyui/themes/bootstrap/images/searchbox_button.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/searchbox_button.png rename to FHC-vendor/easyui/themes/bootstrap/images/searchbox_button.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/slider_handle.png b/FHC-vendor/easyui/themes/bootstrap/images/slider_handle.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/slider_handle.png rename to FHC-vendor/easyui/themes/bootstrap/images/slider_handle.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/spinner_arrows.png b/FHC-vendor/easyui/themes/bootstrap/images/spinner_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/spinner_arrows.png rename to FHC-vendor/easyui/themes/bootstrap/images/spinner_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/tabs_icons.png b/FHC-vendor/easyui/themes/bootstrap/images/tabs_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/tabs_icons.png rename to FHC-vendor/easyui/themes/bootstrap/images/tabs_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/tree_icons.png b/FHC-vendor/easyui/themes/bootstrap/images/tree_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/tree_icons.png rename to FHC-vendor/easyui/themes/bootstrap/images/tree_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/images/validatebox_warning.png b/FHC-vendor/easyui/themes/bootstrap/images/validatebox_warning.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/images/validatebox_warning.png rename to FHC-vendor/easyui/themes/bootstrap/images/validatebox_warning.png diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/layout.css b/FHC-vendor/easyui/themes/bootstrap/layout.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/layout.css rename to FHC-vendor/easyui/themes/bootstrap/layout.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/linkbutton.css b/FHC-vendor/easyui/themes/bootstrap/linkbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/linkbutton.css rename to FHC-vendor/easyui/themes/bootstrap/linkbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/menu.css b/FHC-vendor/easyui/themes/bootstrap/menu.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/menu.css rename to FHC-vendor/easyui/themes/bootstrap/menu.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/menubutton.css b/FHC-vendor/easyui/themes/bootstrap/menubutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/menubutton.css rename to FHC-vendor/easyui/themes/bootstrap/menubutton.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/messager.css b/FHC-vendor/easyui/themes/bootstrap/messager.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/messager.css rename to FHC-vendor/easyui/themes/bootstrap/messager.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/numberbox.css b/FHC-vendor/easyui/themes/bootstrap/numberbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/numberbox.css rename to FHC-vendor/easyui/themes/bootstrap/numberbox.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/pagination.css b/FHC-vendor/easyui/themes/bootstrap/pagination.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/pagination.css rename to FHC-vendor/easyui/themes/bootstrap/pagination.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/panel.css b/FHC-vendor/easyui/themes/bootstrap/panel.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/panel.css rename to FHC-vendor/easyui/themes/bootstrap/panel.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/progressbar.css b/FHC-vendor/easyui/themes/bootstrap/progressbar.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/progressbar.css rename to FHC-vendor/easyui/themes/bootstrap/progressbar.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/propertygrid.css b/FHC-vendor/easyui/themes/bootstrap/propertygrid.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/propertygrid.css rename to FHC-vendor/easyui/themes/bootstrap/propertygrid.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/searchbox.css b/FHC-vendor/easyui/themes/bootstrap/searchbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/searchbox.css rename to FHC-vendor/easyui/themes/bootstrap/searchbox.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/slider.css b/FHC-vendor/easyui/themes/bootstrap/slider.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/slider.css rename to FHC-vendor/easyui/themes/bootstrap/slider.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/spinner.css b/FHC-vendor/easyui/themes/bootstrap/spinner.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/spinner.css rename to FHC-vendor/easyui/themes/bootstrap/spinner.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/splitbutton.css b/FHC-vendor/easyui/themes/bootstrap/splitbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/splitbutton.css rename to FHC-vendor/easyui/themes/bootstrap/splitbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/switchbutton.css b/FHC-vendor/easyui/themes/bootstrap/switchbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/switchbutton.css rename to FHC-vendor/easyui/themes/bootstrap/switchbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/tabs.css b/FHC-vendor/easyui/themes/bootstrap/tabs.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/tabs.css rename to FHC-vendor/easyui/themes/bootstrap/tabs.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/textbox.css b/FHC-vendor/easyui/themes/bootstrap/textbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/textbox.css rename to FHC-vendor/easyui/themes/bootstrap/textbox.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/tooltip.css b/FHC-vendor/easyui/themes/bootstrap/tooltip.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/tooltip.css rename to FHC-vendor/easyui/themes/bootstrap/tooltip.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/tree.css b/FHC-vendor/easyui/themes/bootstrap/tree.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/tree.css rename to FHC-vendor/easyui/themes/bootstrap/tree.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/validatebox.css b/FHC-vendor/easyui/themes/bootstrap/validatebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/validatebox.css rename to FHC-vendor/easyui/themes/bootstrap/validatebox.css diff --git a/vendor/FHC-vendor/easyui/themes/bootstrap/window.css b/FHC-vendor/easyui/themes/bootstrap/window.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/bootstrap/window.css rename to FHC-vendor/easyui/themes/bootstrap/window.css diff --git a/vendor/FHC-vendor/easyui/themes/color.css b/FHC-vendor/easyui/themes/color.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/color.css rename to FHC-vendor/easyui/themes/color.css diff --git a/vendor/FHC-vendor/easyui/themes/default/accordion.css b/FHC-vendor/easyui/themes/default/accordion.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/accordion.css rename to FHC-vendor/easyui/themes/default/accordion.css diff --git a/vendor/FHC-vendor/easyui/themes/default/calendar.css b/FHC-vendor/easyui/themes/default/calendar.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/calendar.css rename to FHC-vendor/easyui/themes/default/calendar.css diff --git a/vendor/FHC-vendor/easyui/themes/default/combo.css b/FHC-vendor/easyui/themes/default/combo.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/combo.css rename to FHC-vendor/easyui/themes/default/combo.css diff --git a/vendor/FHC-vendor/easyui/themes/default/combobox.css b/FHC-vendor/easyui/themes/default/combobox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/combobox.css rename to FHC-vendor/easyui/themes/default/combobox.css diff --git a/vendor/FHC-vendor/easyui/themes/default/datagrid.css b/FHC-vendor/easyui/themes/default/datagrid.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/datagrid.css rename to FHC-vendor/easyui/themes/default/datagrid.css diff --git a/vendor/FHC-vendor/easyui/themes/default/datalist.css b/FHC-vendor/easyui/themes/default/datalist.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/datalist.css rename to FHC-vendor/easyui/themes/default/datalist.css diff --git a/vendor/FHC-vendor/easyui/themes/default/datebox.css b/FHC-vendor/easyui/themes/default/datebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/datebox.css rename to FHC-vendor/easyui/themes/default/datebox.css diff --git a/vendor/FHC-vendor/easyui/themes/default/dialog.css b/FHC-vendor/easyui/themes/default/dialog.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/dialog.css rename to FHC-vendor/easyui/themes/default/dialog.css diff --git a/vendor/FHC-vendor/easyui/themes/default/easyui.css b/FHC-vendor/easyui/themes/default/easyui.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/easyui.css rename to FHC-vendor/easyui/themes/default/easyui.css diff --git a/vendor/FHC-vendor/easyui/themes/default/filebox.css b/FHC-vendor/easyui/themes/default/filebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/filebox.css rename to FHC-vendor/easyui/themes/default/filebox.css diff --git a/vendor/FHC-vendor/easyui/themes/default/images/accordion_arrows.png b/FHC-vendor/easyui/themes/default/images/accordion_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/accordion_arrows.png rename to FHC-vendor/easyui/themes/default/images/accordion_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/blank.gif b/FHC-vendor/easyui/themes/default/images/blank.gif similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/blank.gif rename to FHC-vendor/easyui/themes/default/images/blank.gif diff --git a/vendor/FHC-vendor/easyui/themes/default/images/calendar_arrows.png b/FHC-vendor/easyui/themes/default/images/calendar_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/calendar_arrows.png rename to FHC-vendor/easyui/themes/default/images/calendar_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/combo_arrow.png b/FHC-vendor/easyui/themes/default/images/combo_arrow.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/combo_arrow.png rename to FHC-vendor/easyui/themes/default/images/combo_arrow.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/datagrid_icons.png b/FHC-vendor/easyui/themes/default/images/datagrid_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/datagrid_icons.png rename to FHC-vendor/easyui/themes/default/images/datagrid_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/datebox_arrow.png b/FHC-vendor/easyui/themes/default/images/datebox_arrow.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/datebox_arrow.png rename to FHC-vendor/easyui/themes/default/images/datebox_arrow.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/layout_arrows.png b/FHC-vendor/easyui/themes/default/images/layout_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/layout_arrows.png rename to FHC-vendor/easyui/themes/default/images/layout_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/linkbutton_bg.png b/FHC-vendor/easyui/themes/default/images/linkbutton_bg.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/linkbutton_bg.png rename to FHC-vendor/easyui/themes/default/images/linkbutton_bg.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/loading.gif b/FHC-vendor/easyui/themes/default/images/loading.gif similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/loading.gif rename to FHC-vendor/easyui/themes/default/images/loading.gif diff --git a/vendor/FHC-vendor/easyui/themes/default/images/menu_arrows.png b/FHC-vendor/easyui/themes/default/images/menu_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/menu_arrows.png rename to FHC-vendor/easyui/themes/default/images/menu_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/messager_icons.png b/FHC-vendor/easyui/themes/default/images/messager_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/messager_icons.png rename to FHC-vendor/easyui/themes/default/images/messager_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/pagination_icons.png b/FHC-vendor/easyui/themes/default/images/pagination_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/pagination_icons.png rename to FHC-vendor/easyui/themes/default/images/pagination_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/panel_tools.png b/FHC-vendor/easyui/themes/default/images/panel_tools.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/panel_tools.png rename to FHC-vendor/easyui/themes/default/images/panel_tools.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/searchbox_button.png b/FHC-vendor/easyui/themes/default/images/searchbox_button.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/searchbox_button.png rename to FHC-vendor/easyui/themes/default/images/searchbox_button.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/slider_handle.png b/FHC-vendor/easyui/themes/default/images/slider_handle.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/slider_handle.png rename to FHC-vendor/easyui/themes/default/images/slider_handle.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/spinner_arrows.png b/FHC-vendor/easyui/themes/default/images/spinner_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/spinner_arrows.png rename to FHC-vendor/easyui/themes/default/images/spinner_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/tabs_icons.png b/FHC-vendor/easyui/themes/default/images/tabs_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/tabs_icons.png rename to FHC-vendor/easyui/themes/default/images/tabs_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/tree_icons.png b/FHC-vendor/easyui/themes/default/images/tree_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/tree_icons.png rename to FHC-vendor/easyui/themes/default/images/tree_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/default/images/validatebox_warning.png b/FHC-vendor/easyui/themes/default/images/validatebox_warning.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/images/validatebox_warning.png rename to FHC-vendor/easyui/themes/default/images/validatebox_warning.png diff --git a/vendor/FHC-vendor/easyui/themes/default/layout.css b/FHC-vendor/easyui/themes/default/layout.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/layout.css rename to FHC-vendor/easyui/themes/default/layout.css diff --git a/vendor/FHC-vendor/easyui/themes/default/linkbutton.css b/FHC-vendor/easyui/themes/default/linkbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/linkbutton.css rename to FHC-vendor/easyui/themes/default/linkbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/default/menu.css b/FHC-vendor/easyui/themes/default/menu.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/menu.css rename to FHC-vendor/easyui/themes/default/menu.css diff --git a/vendor/FHC-vendor/easyui/themes/default/menubutton.css b/FHC-vendor/easyui/themes/default/menubutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/menubutton.css rename to FHC-vendor/easyui/themes/default/menubutton.css diff --git a/vendor/FHC-vendor/easyui/themes/default/messager.css b/FHC-vendor/easyui/themes/default/messager.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/messager.css rename to FHC-vendor/easyui/themes/default/messager.css diff --git a/vendor/FHC-vendor/easyui/themes/default/numberbox.css b/FHC-vendor/easyui/themes/default/numberbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/numberbox.css rename to FHC-vendor/easyui/themes/default/numberbox.css diff --git a/vendor/FHC-vendor/easyui/themes/default/pagination.css b/FHC-vendor/easyui/themes/default/pagination.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/pagination.css rename to FHC-vendor/easyui/themes/default/pagination.css diff --git a/vendor/FHC-vendor/easyui/themes/default/panel.css b/FHC-vendor/easyui/themes/default/panel.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/panel.css rename to FHC-vendor/easyui/themes/default/panel.css diff --git a/vendor/FHC-vendor/easyui/themes/default/progressbar.css b/FHC-vendor/easyui/themes/default/progressbar.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/progressbar.css rename to FHC-vendor/easyui/themes/default/progressbar.css diff --git a/vendor/FHC-vendor/easyui/themes/default/propertygrid.css b/FHC-vendor/easyui/themes/default/propertygrid.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/propertygrid.css rename to FHC-vendor/easyui/themes/default/propertygrid.css diff --git a/vendor/FHC-vendor/easyui/themes/default/searchbox.css b/FHC-vendor/easyui/themes/default/searchbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/searchbox.css rename to FHC-vendor/easyui/themes/default/searchbox.css diff --git a/vendor/FHC-vendor/easyui/themes/default/slider.css b/FHC-vendor/easyui/themes/default/slider.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/slider.css rename to FHC-vendor/easyui/themes/default/slider.css diff --git a/vendor/FHC-vendor/easyui/themes/default/spinner.css b/FHC-vendor/easyui/themes/default/spinner.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/spinner.css rename to FHC-vendor/easyui/themes/default/spinner.css diff --git a/vendor/FHC-vendor/easyui/themes/default/splitbutton.css b/FHC-vendor/easyui/themes/default/splitbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/splitbutton.css rename to FHC-vendor/easyui/themes/default/splitbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/default/switchbutton.css b/FHC-vendor/easyui/themes/default/switchbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/switchbutton.css rename to FHC-vendor/easyui/themes/default/switchbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/default/tabs.css b/FHC-vendor/easyui/themes/default/tabs.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/tabs.css rename to FHC-vendor/easyui/themes/default/tabs.css diff --git a/vendor/FHC-vendor/easyui/themes/default/textbox.css b/FHC-vendor/easyui/themes/default/textbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/textbox.css rename to FHC-vendor/easyui/themes/default/textbox.css diff --git a/vendor/FHC-vendor/easyui/themes/default/tooltip.css b/FHC-vendor/easyui/themes/default/tooltip.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/tooltip.css rename to FHC-vendor/easyui/themes/default/tooltip.css diff --git a/vendor/FHC-vendor/easyui/themes/default/tree.css b/FHC-vendor/easyui/themes/default/tree.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/tree.css rename to FHC-vendor/easyui/themes/default/tree.css diff --git a/vendor/FHC-vendor/easyui/themes/default/validatebox.css b/FHC-vendor/easyui/themes/default/validatebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/validatebox.css rename to FHC-vendor/easyui/themes/default/validatebox.css diff --git a/vendor/FHC-vendor/easyui/themes/default/window.css b/FHC-vendor/easyui/themes/default/window.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/default/window.css rename to FHC-vendor/easyui/themes/default/window.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/accordion.css b/FHC-vendor/easyui/themes/gray/accordion.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/accordion.css rename to FHC-vendor/easyui/themes/gray/accordion.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/calendar.css b/FHC-vendor/easyui/themes/gray/calendar.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/calendar.css rename to FHC-vendor/easyui/themes/gray/calendar.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/combo.css b/FHC-vendor/easyui/themes/gray/combo.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/combo.css rename to FHC-vendor/easyui/themes/gray/combo.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/combobox.css b/FHC-vendor/easyui/themes/gray/combobox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/combobox.css rename to FHC-vendor/easyui/themes/gray/combobox.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/datagrid.css b/FHC-vendor/easyui/themes/gray/datagrid.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/datagrid.css rename to FHC-vendor/easyui/themes/gray/datagrid.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/datalist.css b/FHC-vendor/easyui/themes/gray/datalist.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/datalist.css rename to FHC-vendor/easyui/themes/gray/datalist.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/datebox.css b/FHC-vendor/easyui/themes/gray/datebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/datebox.css rename to FHC-vendor/easyui/themes/gray/datebox.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/dialog.css b/FHC-vendor/easyui/themes/gray/dialog.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/dialog.css rename to FHC-vendor/easyui/themes/gray/dialog.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/easyui.css b/FHC-vendor/easyui/themes/gray/easyui.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/easyui.css rename to FHC-vendor/easyui/themes/gray/easyui.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/filebox.css b/FHC-vendor/easyui/themes/gray/filebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/filebox.css rename to FHC-vendor/easyui/themes/gray/filebox.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/accordion_arrows.png b/FHC-vendor/easyui/themes/gray/images/accordion_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/accordion_arrows.png rename to FHC-vendor/easyui/themes/gray/images/accordion_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/blank.gif b/FHC-vendor/easyui/themes/gray/images/blank.gif similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/blank.gif rename to FHC-vendor/easyui/themes/gray/images/blank.gif diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/calendar_arrows.png b/FHC-vendor/easyui/themes/gray/images/calendar_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/calendar_arrows.png rename to FHC-vendor/easyui/themes/gray/images/calendar_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/combo_arrow.png b/FHC-vendor/easyui/themes/gray/images/combo_arrow.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/combo_arrow.png rename to FHC-vendor/easyui/themes/gray/images/combo_arrow.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/datagrid_icons.png b/FHC-vendor/easyui/themes/gray/images/datagrid_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/datagrid_icons.png rename to FHC-vendor/easyui/themes/gray/images/datagrid_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/datebox_arrow.png b/FHC-vendor/easyui/themes/gray/images/datebox_arrow.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/datebox_arrow.png rename to FHC-vendor/easyui/themes/gray/images/datebox_arrow.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/layout_arrows.png b/FHC-vendor/easyui/themes/gray/images/layout_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/layout_arrows.png rename to FHC-vendor/easyui/themes/gray/images/layout_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/linkbutton_bg.png b/FHC-vendor/easyui/themes/gray/images/linkbutton_bg.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/linkbutton_bg.png rename to FHC-vendor/easyui/themes/gray/images/linkbutton_bg.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/loading.gif b/FHC-vendor/easyui/themes/gray/images/loading.gif similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/loading.gif rename to FHC-vendor/easyui/themes/gray/images/loading.gif diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/menu_arrows.png b/FHC-vendor/easyui/themes/gray/images/menu_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/menu_arrows.png rename to FHC-vendor/easyui/themes/gray/images/menu_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/messager_icons.png b/FHC-vendor/easyui/themes/gray/images/messager_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/messager_icons.png rename to FHC-vendor/easyui/themes/gray/images/messager_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/pagination_icons.png b/FHC-vendor/easyui/themes/gray/images/pagination_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/pagination_icons.png rename to FHC-vendor/easyui/themes/gray/images/pagination_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/panel_tools.png b/FHC-vendor/easyui/themes/gray/images/panel_tools.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/panel_tools.png rename to FHC-vendor/easyui/themes/gray/images/panel_tools.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/searchbox_button.png b/FHC-vendor/easyui/themes/gray/images/searchbox_button.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/searchbox_button.png rename to FHC-vendor/easyui/themes/gray/images/searchbox_button.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/slider_handle.png b/FHC-vendor/easyui/themes/gray/images/slider_handle.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/slider_handle.png rename to FHC-vendor/easyui/themes/gray/images/slider_handle.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/spinner_arrows.png b/FHC-vendor/easyui/themes/gray/images/spinner_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/spinner_arrows.png rename to FHC-vendor/easyui/themes/gray/images/spinner_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/tabs_icons.png b/FHC-vendor/easyui/themes/gray/images/tabs_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/tabs_icons.png rename to FHC-vendor/easyui/themes/gray/images/tabs_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/tree_icons.png b/FHC-vendor/easyui/themes/gray/images/tree_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/tree_icons.png rename to FHC-vendor/easyui/themes/gray/images/tree_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/images/validatebox_warning.png b/FHC-vendor/easyui/themes/gray/images/validatebox_warning.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/images/validatebox_warning.png rename to FHC-vendor/easyui/themes/gray/images/validatebox_warning.png diff --git a/vendor/FHC-vendor/easyui/themes/gray/layout.css b/FHC-vendor/easyui/themes/gray/layout.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/layout.css rename to FHC-vendor/easyui/themes/gray/layout.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/linkbutton.css b/FHC-vendor/easyui/themes/gray/linkbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/linkbutton.css rename to FHC-vendor/easyui/themes/gray/linkbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/menu.css b/FHC-vendor/easyui/themes/gray/menu.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/menu.css rename to FHC-vendor/easyui/themes/gray/menu.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/menubutton.css b/FHC-vendor/easyui/themes/gray/menubutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/menubutton.css rename to FHC-vendor/easyui/themes/gray/menubutton.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/messager.css b/FHC-vendor/easyui/themes/gray/messager.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/messager.css rename to FHC-vendor/easyui/themes/gray/messager.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/numberbox.css b/FHC-vendor/easyui/themes/gray/numberbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/numberbox.css rename to FHC-vendor/easyui/themes/gray/numberbox.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/pagination.css b/FHC-vendor/easyui/themes/gray/pagination.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/pagination.css rename to FHC-vendor/easyui/themes/gray/pagination.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/panel.css b/FHC-vendor/easyui/themes/gray/panel.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/panel.css rename to FHC-vendor/easyui/themes/gray/panel.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/progressbar.css b/FHC-vendor/easyui/themes/gray/progressbar.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/progressbar.css rename to FHC-vendor/easyui/themes/gray/progressbar.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/propertygrid.css b/FHC-vendor/easyui/themes/gray/propertygrid.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/propertygrid.css rename to FHC-vendor/easyui/themes/gray/propertygrid.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/searchbox.css b/FHC-vendor/easyui/themes/gray/searchbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/searchbox.css rename to FHC-vendor/easyui/themes/gray/searchbox.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/slider.css b/FHC-vendor/easyui/themes/gray/slider.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/slider.css rename to FHC-vendor/easyui/themes/gray/slider.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/spinner.css b/FHC-vendor/easyui/themes/gray/spinner.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/spinner.css rename to FHC-vendor/easyui/themes/gray/spinner.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/splitbutton.css b/FHC-vendor/easyui/themes/gray/splitbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/splitbutton.css rename to FHC-vendor/easyui/themes/gray/splitbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/switchbutton.css b/FHC-vendor/easyui/themes/gray/switchbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/switchbutton.css rename to FHC-vendor/easyui/themes/gray/switchbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/tabs.css b/FHC-vendor/easyui/themes/gray/tabs.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/tabs.css rename to FHC-vendor/easyui/themes/gray/tabs.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/textbox.css b/FHC-vendor/easyui/themes/gray/textbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/textbox.css rename to FHC-vendor/easyui/themes/gray/textbox.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/tooltip.css b/FHC-vendor/easyui/themes/gray/tooltip.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/tooltip.css rename to FHC-vendor/easyui/themes/gray/tooltip.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/tree.css b/FHC-vendor/easyui/themes/gray/tree.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/tree.css rename to FHC-vendor/easyui/themes/gray/tree.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/validatebox.css b/FHC-vendor/easyui/themes/gray/validatebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/validatebox.css rename to FHC-vendor/easyui/themes/gray/validatebox.css diff --git a/vendor/FHC-vendor/easyui/themes/gray/window.css b/FHC-vendor/easyui/themes/gray/window.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/gray/window.css rename to FHC-vendor/easyui/themes/gray/window.css diff --git a/vendor/FHC-vendor/easyui/themes/icon.css b/FHC-vendor/easyui/themes/icon.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icon.css rename to FHC-vendor/easyui/themes/icon.css diff --git a/vendor/FHC-vendor/easyui/themes/icons/back.png b/FHC-vendor/easyui/themes/icons/back.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/back.png rename to FHC-vendor/easyui/themes/icons/back.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/blank.gif b/FHC-vendor/easyui/themes/icons/blank.gif similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/blank.gif rename to FHC-vendor/easyui/themes/icons/blank.gif diff --git a/vendor/FHC-vendor/easyui/themes/icons/cancel.png b/FHC-vendor/easyui/themes/icons/cancel.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/cancel.png rename to FHC-vendor/easyui/themes/icons/cancel.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/clear.png b/FHC-vendor/easyui/themes/icons/clear.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/clear.png rename to FHC-vendor/easyui/themes/icons/clear.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/cut.png b/FHC-vendor/easyui/themes/icons/cut.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/cut.png rename to FHC-vendor/easyui/themes/icons/cut.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/edit_add.png b/FHC-vendor/easyui/themes/icons/edit_add.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/edit_add.png rename to FHC-vendor/easyui/themes/icons/edit_add.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/edit_remove.png b/FHC-vendor/easyui/themes/icons/edit_remove.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/edit_remove.png rename to FHC-vendor/easyui/themes/icons/edit_remove.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/filesave.png b/FHC-vendor/easyui/themes/icons/filesave.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/filesave.png rename to FHC-vendor/easyui/themes/icons/filesave.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/filter.png b/FHC-vendor/easyui/themes/icons/filter.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/filter.png rename to FHC-vendor/easyui/themes/icons/filter.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/help.png b/FHC-vendor/easyui/themes/icons/help.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/help.png rename to FHC-vendor/easyui/themes/icons/help.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/large_chart.png b/FHC-vendor/easyui/themes/icons/large_chart.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/large_chart.png rename to FHC-vendor/easyui/themes/icons/large_chart.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/large_clipart.png b/FHC-vendor/easyui/themes/icons/large_clipart.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/large_clipart.png rename to FHC-vendor/easyui/themes/icons/large_clipart.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/large_picture.png b/FHC-vendor/easyui/themes/icons/large_picture.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/large_picture.png rename to FHC-vendor/easyui/themes/icons/large_picture.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/large_shapes.png b/FHC-vendor/easyui/themes/icons/large_shapes.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/large_shapes.png rename to FHC-vendor/easyui/themes/icons/large_shapes.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/large_smartart.png b/FHC-vendor/easyui/themes/icons/large_smartart.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/large_smartart.png rename to FHC-vendor/easyui/themes/icons/large_smartart.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/lock.png b/FHC-vendor/easyui/themes/icons/lock.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/lock.png rename to FHC-vendor/easyui/themes/icons/lock.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/man.png b/FHC-vendor/easyui/themes/icons/man.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/man.png rename to FHC-vendor/easyui/themes/icons/man.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/mini_add.png b/FHC-vendor/easyui/themes/icons/mini_add.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/mini_add.png rename to FHC-vendor/easyui/themes/icons/mini_add.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/mini_edit.png b/FHC-vendor/easyui/themes/icons/mini_edit.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/mini_edit.png rename to FHC-vendor/easyui/themes/icons/mini_edit.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/mini_refresh.png b/FHC-vendor/easyui/themes/icons/mini_refresh.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/mini_refresh.png rename to FHC-vendor/easyui/themes/icons/mini_refresh.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/more.png b/FHC-vendor/easyui/themes/icons/more.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/more.png rename to FHC-vendor/easyui/themes/icons/more.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/no.png b/FHC-vendor/easyui/themes/icons/no.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/no.png rename to FHC-vendor/easyui/themes/icons/no.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/ok.png b/FHC-vendor/easyui/themes/icons/ok.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/ok.png rename to FHC-vendor/easyui/themes/icons/ok.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/pencil.png b/FHC-vendor/easyui/themes/icons/pencil.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/pencil.png rename to FHC-vendor/easyui/themes/icons/pencil.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/print.png b/FHC-vendor/easyui/themes/icons/print.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/print.png rename to FHC-vendor/easyui/themes/icons/print.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/redo.png b/FHC-vendor/easyui/themes/icons/redo.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/redo.png rename to FHC-vendor/easyui/themes/icons/redo.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/reload.png b/FHC-vendor/easyui/themes/icons/reload.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/reload.png rename to FHC-vendor/easyui/themes/icons/reload.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/search.png b/FHC-vendor/easyui/themes/icons/search.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/search.png rename to FHC-vendor/easyui/themes/icons/search.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/sum.png b/FHC-vendor/easyui/themes/icons/sum.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/sum.png rename to FHC-vendor/easyui/themes/icons/sum.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/tip.png b/FHC-vendor/easyui/themes/icons/tip.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/tip.png rename to FHC-vendor/easyui/themes/icons/tip.png diff --git a/vendor/FHC-vendor/easyui/themes/icons/undo.png b/FHC-vendor/easyui/themes/icons/undo.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/icons/undo.png rename to FHC-vendor/easyui/themes/icons/undo.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/accordion.css b/FHC-vendor/easyui/themes/metro/accordion.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/accordion.css rename to FHC-vendor/easyui/themes/metro/accordion.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/calendar.css b/FHC-vendor/easyui/themes/metro/calendar.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/calendar.css rename to FHC-vendor/easyui/themes/metro/calendar.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/combo.css b/FHC-vendor/easyui/themes/metro/combo.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/combo.css rename to FHC-vendor/easyui/themes/metro/combo.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/combobox.css b/FHC-vendor/easyui/themes/metro/combobox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/combobox.css rename to FHC-vendor/easyui/themes/metro/combobox.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/datagrid.css b/FHC-vendor/easyui/themes/metro/datagrid.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/datagrid.css rename to FHC-vendor/easyui/themes/metro/datagrid.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/datalist.css b/FHC-vendor/easyui/themes/metro/datalist.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/datalist.css rename to FHC-vendor/easyui/themes/metro/datalist.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/datebox.css b/FHC-vendor/easyui/themes/metro/datebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/datebox.css rename to FHC-vendor/easyui/themes/metro/datebox.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/dialog.css b/FHC-vendor/easyui/themes/metro/dialog.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/dialog.css rename to FHC-vendor/easyui/themes/metro/dialog.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/easyui.css b/FHC-vendor/easyui/themes/metro/easyui.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/easyui.css rename to FHC-vendor/easyui/themes/metro/easyui.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/filebox.css b/FHC-vendor/easyui/themes/metro/filebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/filebox.css rename to FHC-vendor/easyui/themes/metro/filebox.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/accordion_arrows.png b/FHC-vendor/easyui/themes/metro/images/accordion_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/accordion_arrows.png rename to FHC-vendor/easyui/themes/metro/images/accordion_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/blank.gif b/FHC-vendor/easyui/themes/metro/images/blank.gif similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/blank.gif rename to FHC-vendor/easyui/themes/metro/images/blank.gif diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/calendar_arrows.png b/FHC-vendor/easyui/themes/metro/images/calendar_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/calendar_arrows.png rename to FHC-vendor/easyui/themes/metro/images/calendar_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/combo_arrow.png b/FHC-vendor/easyui/themes/metro/images/combo_arrow.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/combo_arrow.png rename to FHC-vendor/easyui/themes/metro/images/combo_arrow.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/datagrid_icons.png b/FHC-vendor/easyui/themes/metro/images/datagrid_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/datagrid_icons.png rename to FHC-vendor/easyui/themes/metro/images/datagrid_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/datebox_arrow.png b/FHC-vendor/easyui/themes/metro/images/datebox_arrow.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/datebox_arrow.png rename to FHC-vendor/easyui/themes/metro/images/datebox_arrow.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/layout_arrows.png b/FHC-vendor/easyui/themes/metro/images/layout_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/layout_arrows.png rename to FHC-vendor/easyui/themes/metro/images/layout_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/linkbutton_bg.png b/FHC-vendor/easyui/themes/metro/images/linkbutton_bg.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/linkbutton_bg.png rename to FHC-vendor/easyui/themes/metro/images/linkbutton_bg.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/loading.gif b/FHC-vendor/easyui/themes/metro/images/loading.gif similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/loading.gif rename to FHC-vendor/easyui/themes/metro/images/loading.gif diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/menu_arrows.png b/FHC-vendor/easyui/themes/metro/images/menu_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/menu_arrows.png rename to FHC-vendor/easyui/themes/metro/images/menu_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/messager_icons.png b/FHC-vendor/easyui/themes/metro/images/messager_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/messager_icons.png rename to FHC-vendor/easyui/themes/metro/images/messager_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/pagination_icons.png b/FHC-vendor/easyui/themes/metro/images/pagination_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/pagination_icons.png rename to FHC-vendor/easyui/themes/metro/images/pagination_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/panel_tools.png b/FHC-vendor/easyui/themes/metro/images/panel_tools.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/panel_tools.png rename to FHC-vendor/easyui/themes/metro/images/panel_tools.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/searchbox_button.png b/FHC-vendor/easyui/themes/metro/images/searchbox_button.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/searchbox_button.png rename to FHC-vendor/easyui/themes/metro/images/searchbox_button.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/slider_handle.png b/FHC-vendor/easyui/themes/metro/images/slider_handle.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/slider_handle.png rename to FHC-vendor/easyui/themes/metro/images/slider_handle.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/spinner_arrows.png b/FHC-vendor/easyui/themes/metro/images/spinner_arrows.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/spinner_arrows.png rename to FHC-vendor/easyui/themes/metro/images/spinner_arrows.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/tabs_icons.png b/FHC-vendor/easyui/themes/metro/images/tabs_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/tabs_icons.png rename to FHC-vendor/easyui/themes/metro/images/tabs_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/tree_icons.png b/FHC-vendor/easyui/themes/metro/images/tree_icons.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/tree_icons.png rename to FHC-vendor/easyui/themes/metro/images/tree_icons.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/images/validatebox_warning.png b/FHC-vendor/easyui/themes/metro/images/validatebox_warning.png similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/images/validatebox_warning.png rename to FHC-vendor/easyui/themes/metro/images/validatebox_warning.png diff --git a/vendor/FHC-vendor/easyui/themes/metro/layout.css b/FHC-vendor/easyui/themes/metro/layout.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/layout.css rename to FHC-vendor/easyui/themes/metro/layout.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/linkbutton.css b/FHC-vendor/easyui/themes/metro/linkbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/linkbutton.css rename to FHC-vendor/easyui/themes/metro/linkbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/menu.css b/FHC-vendor/easyui/themes/metro/menu.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/menu.css rename to FHC-vendor/easyui/themes/metro/menu.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/menubutton.css b/FHC-vendor/easyui/themes/metro/menubutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/menubutton.css rename to FHC-vendor/easyui/themes/metro/menubutton.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/messager.css b/FHC-vendor/easyui/themes/metro/messager.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/messager.css rename to FHC-vendor/easyui/themes/metro/messager.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/numberbox.css b/FHC-vendor/easyui/themes/metro/numberbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/numberbox.css rename to FHC-vendor/easyui/themes/metro/numberbox.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/pagination.css b/FHC-vendor/easyui/themes/metro/pagination.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/pagination.css rename to FHC-vendor/easyui/themes/metro/pagination.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/panel.css b/FHC-vendor/easyui/themes/metro/panel.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/panel.css rename to FHC-vendor/easyui/themes/metro/panel.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/progressbar.css b/FHC-vendor/easyui/themes/metro/progressbar.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/progressbar.css rename to FHC-vendor/easyui/themes/metro/progressbar.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/propertygrid.css b/FHC-vendor/easyui/themes/metro/propertygrid.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/propertygrid.css rename to FHC-vendor/easyui/themes/metro/propertygrid.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/searchbox.css b/FHC-vendor/easyui/themes/metro/searchbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/searchbox.css rename to FHC-vendor/easyui/themes/metro/searchbox.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/slider.css b/FHC-vendor/easyui/themes/metro/slider.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/slider.css rename to FHC-vendor/easyui/themes/metro/slider.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/spinner.css b/FHC-vendor/easyui/themes/metro/spinner.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/spinner.css rename to FHC-vendor/easyui/themes/metro/spinner.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/splitbutton.css b/FHC-vendor/easyui/themes/metro/splitbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/splitbutton.css rename to FHC-vendor/easyui/themes/metro/splitbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/switchbutton.css b/FHC-vendor/easyui/themes/metro/switchbutton.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/switchbutton.css rename to FHC-vendor/easyui/themes/metro/switchbutton.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/tabs.css b/FHC-vendor/easyui/themes/metro/tabs.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/tabs.css rename to FHC-vendor/easyui/themes/metro/tabs.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/textbox.css b/FHC-vendor/easyui/themes/metro/textbox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/textbox.css rename to FHC-vendor/easyui/themes/metro/textbox.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/tooltip.css b/FHC-vendor/easyui/themes/metro/tooltip.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/tooltip.css rename to FHC-vendor/easyui/themes/metro/tooltip.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/tree.css b/FHC-vendor/easyui/themes/metro/tree.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/tree.css rename to FHC-vendor/easyui/themes/metro/tree.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/validatebox.css b/FHC-vendor/easyui/themes/metro/validatebox.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/validatebox.css rename to FHC-vendor/easyui/themes/metro/validatebox.css diff --git a/vendor/FHC-vendor/easyui/themes/metro/window.css b/FHC-vendor/easyui/themes/metro/window.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/metro/window.css rename to FHC-vendor/easyui/themes/metro/window.css diff --git a/vendor/FHC-vendor/easyui/themes/mobile.css b/FHC-vendor/easyui/themes/mobile.css similarity index 100% rename from vendor/FHC-vendor/easyui/themes/mobile.css rename to FHC-vendor/easyui/themes/mobile.css diff --git a/vendor/FHC-vendor/easyui/themes/vilesci b/FHC-vendor/easyui/themes/vilesci similarity index 100% rename from vendor/FHC-vendor/easyui/themes/vilesci rename to FHC-vendor/easyui/themes/vilesci diff --git a/vendor/FHC-vendor/jquery-tablesorter/.gitattributes b/FHC-vendor/jquery-tablesorter/.gitattributes similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/.gitattributes rename to FHC-vendor/jquery-tablesorter/.gitattributes diff --git a/vendor/FHC-vendor/jquery-tablesorter/.gitignore b/FHC-vendor/jquery-tablesorter/.gitignore similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/.gitignore rename to FHC-vendor/jquery-tablesorter/.gitignore diff --git a/vendor/FHC-vendor/jquery-tablesorter/.jscsrc b/FHC-vendor/jquery-tablesorter/.jscsrc similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/.jscsrc rename to FHC-vendor/jquery-tablesorter/.jscsrc diff --git a/vendor/FHC-vendor/jquery-tablesorter/CONTRIBUTING.md b/FHC-vendor/jquery-tablesorter/CONTRIBUTING.md similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/CONTRIBUTING.md rename to FHC-vendor/jquery-tablesorter/CONTRIBUTING.md diff --git a/vendor/FHC-vendor/jquery-tablesorter/Gruntfile.js b/FHC-vendor/jquery-tablesorter/Gruntfile.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/Gruntfile.js rename to FHC-vendor/jquery-tablesorter/Gruntfile.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/README.md b/FHC-vendor/jquery-tablesorter/README.md similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/README.md rename to FHC-vendor/jquery-tablesorter/README.md diff --git a/vendor/FHC-vendor/jquery-tablesorter/addons/pager/icons/first.png b/FHC-vendor/jquery-tablesorter/addons/pager/icons/first.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/addons/pager/icons/first.png rename to FHC-vendor/jquery-tablesorter/addons/pager/icons/first.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/addons/pager/icons/last.png b/FHC-vendor/jquery-tablesorter/addons/pager/icons/last.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/addons/pager/icons/last.png rename to FHC-vendor/jquery-tablesorter/addons/pager/icons/last.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/addons/pager/icons/loading.gif b/FHC-vendor/jquery-tablesorter/addons/pager/icons/loading.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/addons/pager/icons/loading.gif rename to FHC-vendor/jquery-tablesorter/addons/pager/icons/loading.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/addons/pager/icons/next.png b/FHC-vendor/jquery-tablesorter/addons/pager/icons/next.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/addons/pager/icons/next.png rename to FHC-vendor/jquery-tablesorter/addons/pager/icons/next.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/addons/pager/icons/prev.png b/FHC-vendor/jquery-tablesorter/addons/pager/icons/prev.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/addons/pager/icons/prev.png rename to FHC-vendor/jquery-tablesorter/addons/pager/icons/prev.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.css b/FHC-vendor/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.css rename to FHC-vendor/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js b/FHC-vendor/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js rename to FHC-vendor/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/beta-testing/example-pager-custom-controls.html b/FHC-vendor/jquery-tablesorter/beta-testing/example-pager-custom-controls.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/beta-testing/example-pager-custom-controls.html rename to FHC-vendor/jquery-tablesorter/beta-testing/example-pager-custom-controls.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/beta-testing/example-widget-column-reorder.html b/FHC-vendor/jquery-tablesorter/beta-testing/example-widget-column-reorder.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/beta-testing/example-widget-column-reorder.html rename to FHC-vendor/jquery-tablesorter/beta-testing/example-widget-column-reorder.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/beta-testing/pager-custom-controls.js b/FHC-vendor/jquery-tablesorter/beta-testing/pager-custom-controls.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/beta-testing/pager-custom-controls.js rename to FHC-vendor/jquery-tablesorter/beta-testing/pager-custom-controls.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/beta-testing/widget-reorder.js b/FHC-vendor/jquery-tablesorter/beta-testing/widget-reorder.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/beta-testing/widget-reorder.js rename to FHC-vendor/jquery-tablesorter/beta-testing/widget-reorder.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/bower.json b/FHC-vendor/jquery-tablesorter/bower.json similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/bower.json rename to FHC-vendor/jquery-tablesorter/bower.json diff --git a/vendor/FHC-vendor/jquery-tablesorter/changelog.txt b/FHC-vendor/jquery-tablesorter/changelog.txt similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/changelog.txt rename to FHC-vendor/jquery-tablesorter/changelog.txt diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/bootstrap.less b/FHC-vendor/jquery-tablesorter/css/bootstrap.less similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/bootstrap.less rename to FHC-vendor/jquery-tablesorter/css/bootstrap.less diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/dragtable.mod.css b/FHC-vendor/jquery-tablesorter/css/dragtable.mod.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/dragtable.mod.css rename to FHC-vendor/jquery-tablesorter/css/dragtable.mod.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/filter.formatter.css b/FHC-vendor/jquery-tablesorter/css/filter.formatter.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/filter.formatter.css rename to FHC-vendor/jquery-tablesorter/css/filter.formatter.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/black-asc.gif b/FHC-vendor/jquery-tablesorter/css/images/black-asc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/black-asc.gif rename to FHC-vendor/jquery-tablesorter/css/images/black-asc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/black-desc.gif b/FHC-vendor/jquery-tablesorter/css/images/black-desc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/black-desc.gif rename to FHC-vendor/jquery-tablesorter/css/images/black-desc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/black-unsorted.gif b/FHC-vendor/jquery-tablesorter/css/images/black-unsorted.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/black-unsorted.gif rename to FHC-vendor/jquery-tablesorter/css/images/black-unsorted.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/bootstrap-black-unsorted.png b/FHC-vendor/jquery-tablesorter/css/images/bootstrap-black-unsorted.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/bootstrap-black-unsorted.png rename to FHC-vendor/jquery-tablesorter/css/images/bootstrap-black-unsorted.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/bootstrap-white-unsorted.png b/FHC-vendor/jquery-tablesorter/css/images/bootstrap-white-unsorted.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/bootstrap-white-unsorted.png rename to FHC-vendor/jquery-tablesorter/css/images/bootstrap-white-unsorted.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/dragtable-handle.png b/FHC-vendor/jquery-tablesorter/css/images/dragtable-handle.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/dragtable-handle.png rename to FHC-vendor/jquery-tablesorter/css/images/dragtable-handle.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/dragtable-handle.svg b/FHC-vendor/jquery-tablesorter/css/images/dragtable-handle.svg similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/dragtable-handle.svg rename to FHC-vendor/jquery-tablesorter/css/images/dragtable-handle.svg diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/dropbox-asc-hovered.png b/FHC-vendor/jquery-tablesorter/css/images/dropbox-asc-hovered.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/dropbox-asc-hovered.png rename to FHC-vendor/jquery-tablesorter/css/images/dropbox-asc-hovered.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/dropbox-asc.png b/FHC-vendor/jquery-tablesorter/css/images/dropbox-asc.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/dropbox-asc.png rename to FHC-vendor/jquery-tablesorter/css/images/dropbox-asc.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/dropbox-desc-hovered.png b/FHC-vendor/jquery-tablesorter/css/images/dropbox-desc-hovered.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/dropbox-desc-hovered.png rename to FHC-vendor/jquery-tablesorter/css/images/dropbox-desc-hovered.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/dropbox-desc.png b/FHC-vendor/jquery-tablesorter/css/images/dropbox-desc.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/dropbox-desc.png rename to FHC-vendor/jquery-tablesorter/css/images/dropbox-desc.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/green-asc.gif b/FHC-vendor/jquery-tablesorter/css/images/green-asc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/green-asc.gif rename to FHC-vendor/jquery-tablesorter/css/images/green-asc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/green-desc.gif b/FHC-vendor/jquery-tablesorter/css/images/green-desc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/green-desc.gif rename to FHC-vendor/jquery-tablesorter/css/images/green-desc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/green-header.gif b/FHC-vendor/jquery-tablesorter/css/images/green-header.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/green-header.gif rename to FHC-vendor/jquery-tablesorter/css/images/green-header.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/green-unsorted.gif b/FHC-vendor/jquery-tablesorter/css/images/green-unsorted.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/green-unsorted.gif rename to FHC-vendor/jquery-tablesorter/css/images/green-unsorted.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/ice-asc.gif b/FHC-vendor/jquery-tablesorter/css/images/ice-asc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/ice-asc.gif rename to FHC-vendor/jquery-tablesorter/css/images/ice-asc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/ice-desc.gif b/FHC-vendor/jquery-tablesorter/css/images/ice-desc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/ice-desc.gif rename to FHC-vendor/jquery-tablesorter/css/images/ice-desc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/ice-unsorted.gif b/FHC-vendor/jquery-tablesorter/css/images/ice-unsorted.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/ice-unsorted.gif rename to FHC-vendor/jquery-tablesorter/css/images/ice-unsorted.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/metro-black-asc.png b/FHC-vendor/jquery-tablesorter/css/images/metro-black-asc.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/metro-black-asc.png rename to FHC-vendor/jquery-tablesorter/css/images/metro-black-asc.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/metro-black-desc.png b/FHC-vendor/jquery-tablesorter/css/images/metro-black-desc.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/metro-black-desc.png rename to FHC-vendor/jquery-tablesorter/css/images/metro-black-desc.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/metro-loading.gif b/FHC-vendor/jquery-tablesorter/css/images/metro-loading.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/metro-loading.gif rename to FHC-vendor/jquery-tablesorter/css/images/metro-loading.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/metro-unsorted.png b/FHC-vendor/jquery-tablesorter/css/images/metro-unsorted.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/metro-unsorted.png rename to FHC-vendor/jquery-tablesorter/css/images/metro-unsorted.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/metro-white-asc.png b/FHC-vendor/jquery-tablesorter/css/images/metro-white-asc.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/metro-white-asc.png rename to FHC-vendor/jquery-tablesorter/css/images/metro-white-asc.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/metro-white-desc.png b/FHC-vendor/jquery-tablesorter/css/images/metro-white-desc.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/metro-white-desc.png rename to FHC-vendor/jquery-tablesorter/css/images/metro-white-desc.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/white-asc.gif b/FHC-vendor/jquery-tablesorter/css/images/white-asc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/white-asc.gif rename to FHC-vendor/jquery-tablesorter/css/images/white-asc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/white-desc.gif b/FHC-vendor/jquery-tablesorter/css/images/white-desc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/white-desc.gif rename to FHC-vendor/jquery-tablesorter/css/images/white-desc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/images/white-unsorted.gif b/FHC-vendor/jquery-tablesorter/css/images/white-unsorted.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/images/white-unsorted.gif rename to FHC-vendor/jquery-tablesorter/css/images/white-unsorted.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/metro.less b/FHC-vendor/jquery-tablesorter/css/metro.less similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/metro.less rename to FHC-vendor/jquery-tablesorter/css/metro.less diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/psd/green-asc.psd b/FHC-vendor/jquery-tablesorter/css/psd/green-asc.psd similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/psd/green-asc.psd rename to FHC-vendor/jquery-tablesorter/css/psd/green-asc.psd diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/psd/green-desc.psd b/FHC-vendor/jquery-tablesorter/css/psd/green-desc.psd similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/psd/green-desc.psd rename to FHC-vendor/jquery-tablesorter/css/psd/green-desc.psd diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/psd/green-unsorted.psd b/FHC-vendor/jquery-tablesorter/css/psd/green-unsorted.psd similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/psd/green-unsorted.psd rename to FHC-vendor/jquery-tablesorter/css/psd/green-unsorted.psd diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/psd/metro-style.psd b/FHC-vendor/jquery-tablesorter/css/psd/metro-style.psd similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/psd/metro-style.psd rename to FHC-vendor/jquery-tablesorter/css/psd/metro-style.psd diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/theme.black-ice.css b/FHC-vendor/jquery-tablesorter/css/theme.black-ice.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/theme.black-ice.css rename to FHC-vendor/jquery-tablesorter/css/theme.black-ice.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/theme.blue.css b/FHC-vendor/jquery-tablesorter/css/theme.blue.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/theme.blue.css rename to FHC-vendor/jquery-tablesorter/css/theme.blue.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/theme.bootstrap.css b/FHC-vendor/jquery-tablesorter/css/theme.bootstrap.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/theme.bootstrap.css rename to FHC-vendor/jquery-tablesorter/css/theme.bootstrap.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/theme.bootstrap_2.css b/FHC-vendor/jquery-tablesorter/css/theme.bootstrap_2.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/theme.bootstrap_2.css rename to FHC-vendor/jquery-tablesorter/css/theme.bootstrap_2.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/theme.dark.css b/FHC-vendor/jquery-tablesorter/css/theme.dark.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/theme.dark.css rename to FHC-vendor/jquery-tablesorter/css/theme.dark.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/theme.default.css b/FHC-vendor/jquery-tablesorter/css/theme.default.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/theme.default.css rename to FHC-vendor/jquery-tablesorter/css/theme.default.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/theme.dropbox.css b/FHC-vendor/jquery-tablesorter/css/theme.dropbox.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/theme.dropbox.css rename to FHC-vendor/jquery-tablesorter/css/theme.dropbox.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/theme.green.css b/FHC-vendor/jquery-tablesorter/css/theme.green.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/theme.green.css rename to FHC-vendor/jquery-tablesorter/css/theme.green.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/theme.grey.css b/FHC-vendor/jquery-tablesorter/css/theme.grey.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/theme.grey.css rename to FHC-vendor/jquery-tablesorter/css/theme.grey.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/theme.ice.css b/FHC-vendor/jquery-tablesorter/css/theme.ice.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/theme.ice.css rename to FHC-vendor/jquery-tablesorter/css/theme.ice.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/theme.jui.css b/FHC-vendor/jquery-tablesorter/css/theme.jui.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/theme.jui.css rename to FHC-vendor/jquery-tablesorter/css/theme.jui.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/theme.less b/FHC-vendor/jquery-tablesorter/css/theme.less similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/theme.less rename to FHC-vendor/jquery-tablesorter/css/theme.less diff --git a/vendor/FHC-vendor/jquery-tablesorter/css/theme.metro-dark.css b/FHC-vendor/jquery-tablesorter/css/theme.metro-dark.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/css/theme.metro-dark.css rename to FHC-vendor/jquery-tablesorter/css/theme.metro-dark.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/dragtable.mod.min.css b/FHC-vendor/jquery-tablesorter/dist/css/dragtable.mod.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/dragtable.mod.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/dragtable.mod.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/filter.formatter.min.css b/FHC-vendor/jquery-tablesorter/dist/css/filter.formatter.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/filter.formatter.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/filter.formatter.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/black-asc.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/black-asc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/black-asc.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/black-asc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/black-desc.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/black-desc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/black-desc.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/black-desc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/black-unsorted.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/black-unsorted.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/black-unsorted.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/black-unsorted.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/bootstrap-black-unsorted.png b/FHC-vendor/jquery-tablesorter/dist/css/images/bootstrap-black-unsorted.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/bootstrap-black-unsorted.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/bootstrap-black-unsorted.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/bootstrap-white-unsorted.png b/FHC-vendor/jquery-tablesorter/dist/css/images/bootstrap-white-unsorted.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/bootstrap-white-unsorted.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/bootstrap-white-unsorted.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/dragtable-handle.png b/FHC-vendor/jquery-tablesorter/dist/css/images/dragtable-handle.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/dragtable-handle.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/dragtable-handle.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/dragtable-handle.svg b/FHC-vendor/jquery-tablesorter/dist/css/images/dragtable-handle.svg similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/dragtable-handle.svg rename to FHC-vendor/jquery-tablesorter/dist/css/images/dragtable-handle.svg diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-asc-hovered.png b/FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-asc-hovered.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-asc-hovered.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-asc-hovered.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-asc.png b/FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-asc.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-asc.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-asc.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-desc-hovered.png b/FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-desc-hovered.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-desc-hovered.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-desc-hovered.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-desc.png b/FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-desc.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-desc.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/dropbox-desc.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/first.png b/FHC-vendor/jquery-tablesorter/dist/css/images/first.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/first.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/first.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/green-asc.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/green-asc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/green-asc.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/green-asc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/green-desc.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/green-desc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/green-desc.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/green-desc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/green-header.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/green-header.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/green-header.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/green-header.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/green-unsorted.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/green-unsorted.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/green-unsorted.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/green-unsorted.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/ice-asc.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/ice-asc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/ice-asc.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/ice-asc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/ice-desc.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/ice-desc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/ice-desc.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/ice-desc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/ice-unsorted.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/ice-unsorted.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/ice-unsorted.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/ice-unsorted.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/last.png b/FHC-vendor/jquery-tablesorter/dist/css/images/last.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/last.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/last.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/loading.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/loading.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/loading.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/loading.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/metro-black-asc.png b/FHC-vendor/jquery-tablesorter/dist/css/images/metro-black-asc.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/metro-black-asc.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/metro-black-asc.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/metro-black-desc.png b/FHC-vendor/jquery-tablesorter/dist/css/images/metro-black-desc.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/metro-black-desc.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/metro-black-desc.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/metro-loading.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/metro-loading.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/metro-loading.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/metro-loading.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/metro-unsorted.png b/FHC-vendor/jquery-tablesorter/dist/css/images/metro-unsorted.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/metro-unsorted.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/metro-unsorted.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/metro-white-asc.png b/FHC-vendor/jquery-tablesorter/dist/css/images/metro-white-asc.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/metro-white-asc.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/metro-white-asc.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/metro-white-desc.png b/FHC-vendor/jquery-tablesorter/dist/css/images/metro-white-desc.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/metro-white-desc.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/metro-white-desc.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/next.png b/FHC-vendor/jquery-tablesorter/dist/css/images/next.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/next.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/next.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/prev.png b/FHC-vendor/jquery-tablesorter/dist/css/images/prev.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/prev.png rename to FHC-vendor/jquery-tablesorter/dist/css/images/prev.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/white-asc.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/white-asc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/white-asc.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/white-asc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/white-desc.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/white-desc.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/white-desc.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/white-desc.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/images/white-unsorted.gif b/FHC-vendor/jquery-tablesorter/dist/css/images/white-unsorted.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/images/white-unsorted.gif rename to FHC-vendor/jquery-tablesorter/dist/css/images/white-unsorted.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/jquery.tablesorter.pager.min.css b/FHC-vendor/jquery-tablesorter/dist/css/jquery.tablesorter.pager.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/jquery.tablesorter.pager.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/jquery.tablesorter.pager.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/less/bootstrap.less b/FHC-vendor/jquery-tablesorter/dist/css/less/bootstrap.less similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/less/bootstrap.less rename to FHC-vendor/jquery-tablesorter/dist/css/less/bootstrap.less diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/less/metro.less b/FHC-vendor/jquery-tablesorter/dist/css/less/metro.less similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/less/metro.less rename to FHC-vendor/jquery-tablesorter/dist/css/less/metro.less diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/less/theme.less b/FHC-vendor/jquery-tablesorter/dist/css/less/theme.less similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/less/theme.less rename to FHC-vendor/jquery-tablesorter/dist/css/less/theme.less diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.blackice.min.css b/FHC-vendor/jquery-tablesorter/dist/css/theme.blackice.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.blackice.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/theme.blackice.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.blue.min.css b/FHC-vendor/jquery-tablesorter/dist/css/theme.blue.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.blue.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/theme.blue.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.bootstrap.min.css b/FHC-vendor/jquery-tablesorter/dist/css/theme.bootstrap.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.bootstrap.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/theme.bootstrap.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.bootstrap_2.min.css b/FHC-vendor/jquery-tablesorter/dist/css/theme.bootstrap_2.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.bootstrap_2.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/theme.bootstrap_2.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.dark.min.css b/FHC-vendor/jquery-tablesorter/dist/css/theme.dark.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.dark.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/theme.dark.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.default.min.css b/FHC-vendor/jquery-tablesorter/dist/css/theme.default.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.default.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/theme.default.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.dropbox.min.css b/FHC-vendor/jquery-tablesorter/dist/css/theme.dropbox.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.dropbox.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/theme.dropbox.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.green.min.css b/FHC-vendor/jquery-tablesorter/dist/css/theme.green.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.green.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/theme.green.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.grey.min.css b/FHC-vendor/jquery-tablesorter/dist/css/theme.grey.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.grey.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/theme.grey.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.ice.min.css b/FHC-vendor/jquery-tablesorter/dist/css/theme.ice.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.ice.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/theme.ice.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.jui.min.css b/FHC-vendor/jquery-tablesorter/dist/css/theme.jui.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.jui.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/theme.jui.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.metro-dark.min.css b/FHC-vendor/jquery-tablesorter/dist/css/theme.metro-dark.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/css/theme.metro-dark.min.css rename to FHC-vendor/jquery-tablesorter/dist/css/theme.metro-dark.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/extras/jquery.dragtable.mod.min.js b/FHC-vendor/jquery-tablesorter/dist/js/extras/jquery.dragtable.mod.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/extras/jquery.dragtable.mod.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/extras/jquery.dragtable.mod.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/extras/jquery.metadata.min.js b/FHC-vendor/jquery-tablesorter/dist/js/extras/jquery.metadata.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/extras/jquery.metadata.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/extras/jquery.metadata.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/extras/jquery.tablesorter.pager.min.js b/FHC-vendor/jquery-tablesorter/dist/js/extras/jquery.tablesorter.pager.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/extras/jquery.tablesorter.pager.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/extras/jquery.tablesorter.pager.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/extras/semver-mod.min.js b/FHC-vendor/jquery-tablesorter/dist/js/extras/semver-mod.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/extras/semver-mod.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/extras/semver-mod.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.combined.js b/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.combined.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.combined.js rename to FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.combined.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.combined.min.js b/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.combined.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.combined.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.combined.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.js b/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.js rename to FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.min.js b/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.widgets.js b/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.widgets.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.widgets.js rename to FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.widgets.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.widgets.min.js b/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.widgets.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.widgets.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/jquery.tablesorter.widgets.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-extract.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-extract.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-extract.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-extract.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-iso8601.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-iso8601.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-iso8601.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-iso8601.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-month.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-month.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-month.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-month.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-range.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-range.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-range.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-range.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-two-digit-year.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-two-digit-year.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-two-digit-year.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-two-digit-year.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-weekday.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-weekday.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-weekday.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date-weekday.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-date.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-duration.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-duration.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-duration.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-duration.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-feet-inch-fraction.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-feet-inch-fraction.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-feet-inch-fraction.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-feet-inch-fraction.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-file-type.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-file-type.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-file-type.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-file-type.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-globalize.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-globalize.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-globalize.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-globalize.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-ignore-articles.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-ignore-articles.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-ignore-articles.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-ignore-articles.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-image.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-image.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-image.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-image.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-input-select.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-input-select.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-input-select.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-input-select.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-metric.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-metric.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-metric.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-metric.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-named-numbers.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-named-numbers.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-named-numbers.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-named-numbers.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-network.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-network.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-network.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-network.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-roman.min.js b/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-roman.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-roman.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/parsers/parser-roman.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-alignChar.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-alignChar.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-alignChar.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-alignChar.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-build-table.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-build-table.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-build-table.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-build-table.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-chart.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-chart.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-chart.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-chart.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-columnSelector.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-columnSelector.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-columnSelector.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-columnSelector.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-columns.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-columns.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-columns.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-columns.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-cssStickyHeaders.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-cssStickyHeaders.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-cssStickyHeaders.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-cssStickyHeaders.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-editable.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-editable.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-editable.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-editable.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-formatter-html5.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-formatter-html5.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-formatter-html5.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-formatter-html5.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-formatter-jui.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-formatter-jui.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-formatter-jui.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-formatter-jui.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-formatter-select2.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-formatter-select2.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-formatter-select2.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-formatter-select2.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-type-insideRange.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-type-insideRange.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-type-insideRange.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter-type-insideRange.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-filter.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-formatter.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-formatter.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-formatter.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-formatter.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-grouping.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-grouping.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-grouping.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-grouping.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-headerTitles.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-headerTitles.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-headerTitles.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-headerTitles.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-lazyload.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-lazyload.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-lazyload.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-lazyload.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-math.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-math.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-math.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-math.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-output.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-output.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-output.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-output.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-pager.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-pager.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-pager.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-pager.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-print.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-print.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-print.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-print.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-reflow.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-reflow.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-reflow.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-reflow.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-repeatheaders.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-repeatheaders.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-repeatheaders.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-repeatheaders.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-resizable.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-resizable.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-resizable.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-resizable.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-saveSort.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-saveSort.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-saveSort.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-saveSort.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-scroller.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-scroller.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-scroller.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-scroller.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-sort2Hash.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-sort2Hash.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-sort2Hash.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-sort2Hash.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-sortTbodies.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-sortTbodies.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-sortTbodies.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-sortTbodies.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-staticRow.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-staticRow.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-staticRow.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-staticRow.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-stickyHeaders.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-stickyHeaders.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-stickyHeaders.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-stickyHeaders.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-storage.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-storage.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-storage.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-storage.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-toggle.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-toggle.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-toggle.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-toggle.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-uitheme.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-uitheme.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-uitheme.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-uitheme.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-view.min.js b/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-view.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-view.min.js rename to FHC-vendor/jquery-tablesorter/dist/js/widgets/widget-view.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/assets/City0.json b/FHC-vendor/jquery-tablesorter/docs/assets/City0.json similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/assets/City0.json rename to FHC-vendor/jquery-tablesorter/docs/assets/City0.json diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/assets/City1.json b/FHC-vendor/jquery-tablesorter/docs/assets/City1.json similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/assets/City1.json rename to FHC-vendor/jquery-tablesorter/docs/assets/City1.json diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/assets/City2.json b/FHC-vendor/jquery-tablesorter/docs/assets/City2.json similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/assets/City2.json rename to FHC-vendor/jquery-tablesorter/docs/assets/City2.json diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/assets/City3.json b/FHC-vendor/jquery-tablesorter/docs/assets/City3.json similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/assets/City3.json rename to FHC-vendor/jquery-tablesorter/docs/assets/City3.json diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/assets/ajax-content.html b/FHC-vendor/jquery-tablesorter/docs/assets/ajax-content.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/assets/ajax-content.html rename to FHC-vendor/jquery-tablesorter/docs/assets/ajax-content.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/assets/build.json b/FHC-vendor/jquery-tablesorter/docs/assets/build.json similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/assets/build.json rename to FHC-vendor/jquery-tablesorter/docs/assets/build.json diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/assets/build.txt b/FHC-vendor/jquery-tablesorter/docs/assets/build.txt similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/assets/build.txt rename to FHC-vendor/jquery-tablesorter/docs/assets/build.txt diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/assets/theme_switcher.json b/FHC-vendor/jquery-tablesorter/docs/assets/theme_switcher.json similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/assets/theme_switcher.json rename to FHC-vendor/jquery-tablesorter/docs/assets/theme_switcher.json diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/bootstrap-v2.min.css b/FHC-vendor/jquery-tablesorter/docs/css/bootstrap-v2.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/bootstrap-v2.min.css rename to FHC-vendor/jquery-tablesorter/docs/css/bootstrap-v2.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/bootstrap.min.css b/FHC-vendor/jquery-tablesorter/docs/css/bootstrap.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/bootstrap.min.css rename to FHC-vendor/jquery-tablesorter/docs/css/bootstrap.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/glyphicons-halflings-white.png b/FHC-vendor/jquery-tablesorter/docs/css/images/glyphicons-halflings-white.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/glyphicons-halflings-white.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/glyphicons-halflings-white.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/glyphicons-halflings.png b/FHC-vendor/jquery-tablesorter/docs/css/images/glyphicons-halflings.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/glyphicons-halflings.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/glyphicons-halflings.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_flat_15_cd0a0a_40x100.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_flat_15_cd0a0a_40x100.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_flat_15_cd0a0a_40x100.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_flat_15_cd0a0a_40x100.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_glass_100_e4f1fb_1x400.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_glass_100_e4f1fb_1x400.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_glass_100_e4f1fb_1x400.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_glass_100_e4f1fb_1x400.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_glass_50_3baae3_1x400.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_glass_50_3baae3_1x400.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_glass_50_3baae3_1x400.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_glass_50_3baae3_1x400.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_glass_80_d7ebf9_1x400.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_glass_80_d7ebf9_1x400.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_glass_80_d7ebf9_1x400.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_glass_80_d7ebf9_1x400.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-hard_70_000000_1x100.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-hard_70_000000_1x100.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-hard_70_000000_1x100.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-hard_70_000000_1x100.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-soft_100_deedf7_1x100.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-soft_100_deedf7_1x100.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-soft_100_deedf7_1x100.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-soft_100_deedf7_1x100.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-soft_25_ffef8f_1x100.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-soft_25_ffef8f_1x100.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-soft_25_ffef8f_1x100.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-bg_highlight-soft_25_ffef8f_1x100.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_2694e8_256x240.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_2694e8_256x240.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_2694e8_256x240.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_2694e8_256x240.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_2e83ff_256x240.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_2e83ff_256x240.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_2e83ff_256x240.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_2e83ff_256x240.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_3d80b3_256x240.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_3d80b3_256x240.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_3d80b3_256x240.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_3d80b3_256x240.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_72a7cf_256x240.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_72a7cf_256x240.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_72a7cf_256x240.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_72a7cf_256x240.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_ffffff_256x240.png b/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_ffffff_256x240.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_ffffff_256x240.png rename to FHC-vendor/jquery-tablesorter/docs/css/images/ui-icons_ffffff_256x240.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/jq.css b/FHC-vendor/jquery-tablesorter/docs/css/jq.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/jq.css rename to FHC-vendor/jquery-tablesorter/docs/css/jq.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/jquery-ui.min.css b/FHC-vendor/jquery-tablesorter/docs/css/jquery-ui.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/jquery-ui.min.css rename to FHC-vendor/jquery-tablesorter/docs/css/jquery-ui.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/magnific-popup.css b/FHC-vendor/jquery-tablesorter/docs/css/magnific-popup.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/magnific-popup.css rename to FHC-vendor/jquery-tablesorter/docs/css/magnific-popup.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/menu.css b/FHC-vendor/jquery-tablesorter/docs/css/menu.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/menu.css rename to FHC-vendor/jquery-tablesorter/docs/css/menu.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/prettify.css b/FHC-vendor/jquery-tablesorter/docs/css/prettify.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/prettify.css rename to FHC-vendor/jquery-tablesorter/docs/css/prettify.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/rangeslider.css b/FHC-vendor/jquery-tablesorter/docs/css/rangeslider.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/rangeslider.css rename to FHC-vendor/jquery-tablesorter/docs/css/rangeslider.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/select2-3.4.6.min.css b/FHC-vendor/jquery-tablesorter/docs/css/select2-3.4.6.min.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/select2-3.4.6.min.css rename to FHC-vendor/jquery-tablesorter/docs/css/select2-3.4.6.min.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/select2-spinner.gif b/FHC-vendor/jquery-tablesorter/docs/css/select2-spinner.gif similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/select2-spinner.gif rename to FHC-vendor/jquery-tablesorter/docs/css/select2-spinner.gif diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/select2.png b/FHC-vendor/jquery-tablesorter/docs/css/select2.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/select2.png rename to FHC-vendor/jquery-tablesorter/docs/css/select2.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/select2x2.png b/FHC-vendor/jquery-tablesorter/docs/css/select2x2.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/select2x2.png rename to FHC-vendor/jquery-tablesorter/docs/css/select2x2.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/css/tipsy.css b/FHC-vendor/jquery-tablesorter/docs/css/tipsy.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/css/tipsy.css rename to FHC-vendor/jquery-tablesorter/docs/css/tipsy.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-add-rows.html b/FHC-vendor/jquery-tablesorter/docs/example-add-rows.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-add-rows.html rename to FHC-vendor/jquery-tablesorter/docs/example-add-rows.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-ajax.html b/FHC-vendor/jquery-tablesorter/docs/example-ajax.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-ajax.html rename to FHC-vendor/jquery-tablesorter/docs/example-ajax.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-apply-widget.html b/FHC-vendor/jquery-tablesorter/docs/example-apply-widget.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-apply-widget.html rename to FHC-vendor/jquery-tablesorter/docs/example-apply-widget.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-child-rows-filtered.html b/FHC-vendor/jquery-tablesorter/docs/example-child-rows-filtered.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-child-rows-filtered.html rename to FHC-vendor/jquery-tablesorter/docs/example-child-rows-filtered.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-child-rows.html b/FHC-vendor/jquery-tablesorter/docs/example-child-rows.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-child-rows.html rename to FHC-vendor/jquery-tablesorter/docs/example-child-rows.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-css-highlighting.html b/FHC-vendor/jquery-tablesorter/docs/example-css-highlighting.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-css-highlighting.html rename to FHC-vendor/jquery-tablesorter/docs/example-css-highlighting.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-dragtable.html b/FHC-vendor/jquery-tablesorter/docs/example-dragtable.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-dragtable.html rename to FHC-vendor/jquery-tablesorter/docs/example-dragtable.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-empty-table.html b/FHC-vendor/jquery-tablesorter/docs/example-empty-table.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-empty-table.html rename to FHC-vendor/jquery-tablesorter/docs/example-empty-table.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-extending-defaults.html b/FHC-vendor/jquery-tablesorter/docs/example-extending-defaults.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-extending-defaults.html rename to FHC-vendor/jquery-tablesorter/docs/example-extending-defaults.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-extractors-parsers.html b/FHC-vendor/jquery-tablesorter/docs/example-extractors-parsers.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-extractors-parsers.html rename to FHC-vendor/jquery-tablesorter/docs/example-extractors-parsers.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-header-column-span.html b/FHC-vendor/jquery-tablesorter/docs/example-header-column-span.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-header-column-span.html rename to FHC-vendor/jquery-tablesorter/docs/example-header-column-span.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-locale-sort.html b/FHC-vendor/jquery-tablesorter/docs/example-locale-sort.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-locale-sort.html rename to FHC-vendor/jquery-tablesorter/docs/example-locale-sort.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-meta-headers.html b/FHC-vendor/jquery-tablesorter/docs/example-meta-headers.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-meta-headers.html rename to FHC-vendor/jquery-tablesorter/docs/example-meta-headers.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-meta-parsers.html b/FHC-vendor/jquery-tablesorter/docs/example-meta-parsers.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-meta-parsers.html rename to FHC-vendor/jquery-tablesorter/docs/example-meta-parsers.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-meta-sort-list.html b/FHC-vendor/jquery-tablesorter/docs/example-meta-sort-list.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-meta-sort-list.html rename to FHC-vendor/jquery-tablesorter/docs/example-meta-sort-list.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-method-sortreset.html b/FHC-vendor/jquery-tablesorter/docs/example-method-sortreset.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-method-sortreset.html rename to FHC-vendor/jquery-tablesorter/docs/example-method-sortreset.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-multiple-tbodies.html b/FHC-vendor/jquery-tablesorter/docs/example-multiple-tbodies.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-multiple-tbodies.html rename to FHC-vendor/jquery-tablesorter/docs/example-multiple-tbodies.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-custom-sort.html b/FHC-vendor/jquery-tablesorter/docs/example-option-custom-sort.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-custom-sort.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-custom-sort.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-date-format.html b/FHC-vendor/jquery-tablesorter/docs/example-option-date-format.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-date-format.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-date-format.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-debug.html b/FHC-vendor/jquery-tablesorter/docs/example-option-debug.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-debug.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-debug.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-delay-init.html b/FHC-vendor/jquery-tablesorter/docs/example-option-delay-init.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-delay-init.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-delay-init.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-digits.html b/FHC-vendor/jquery-tablesorter/docs/example-option-digits.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-digits.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-digits.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-render-header.html b/FHC-vendor/jquery-tablesorter/docs/example-option-render-header.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-render-header.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-render-header.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-render-template.html b/FHC-vendor/jquery-tablesorter/docs/example-option-render-template.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-render-template.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-render-template.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-selectorsort.html b/FHC-vendor/jquery-tablesorter/docs/example-option-selectorsort.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-selectorsort.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-selectorsort.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-show-processing.html b/FHC-vendor/jquery-tablesorter/docs/example-option-show-processing.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-show-processing.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-show-processing.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sort-append.html b/FHC-vendor/jquery-tablesorter/docs/example-option-sort-append.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sort-append.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-sort-append.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sort-empty.html b/FHC-vendor/jquery-tablesorter/docs/example-option-sort-empty.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sort-empty.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-sort-empty.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sort-force.html b/FHC-vendor/jquery-tablesorter/docs/example-option-sort-force.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sort-force.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-sort-force.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sort-key.html b/FHC-vendor/jquery-tablesorter/docs/example-option-sort-key.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sort-key.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-sort-key.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sort-list.html b/FHC-vendor/jquery-tablesorter/docs/example-option-sort-list.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sort-list.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-sort-list.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sort-order.html b/FHC-vendor/jquery-tablesorter/docs/example-option-sort-order.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sort-order.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-sort-order.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sortreset-sortrestart.html b/FHC-vendor/jquery-tablesorter/docs/example-option-sortreset-sortrestart.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-sortreset-sortrestart.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-sortreset-sortrestart.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-text-extraction.html b/FHC-vendor/jquery-tablesorter/docs/example-option-text-extraction.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-text-extraction.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-text-extraction.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-textsorter-semver.html b/FHC-vendor/jquery-tablesorter/docs/example-option-textsorter-semver.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-textsorter-semver.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-textsorter-semver.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-option-theme-metro-style.html b/FHC-vendor/jquery-tablesorter/docs/example-option-theme-metro-style.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-option-theme-metro-style.html rename to FHC-vendor/jquery-tablesorter/docs/example-option-theme-metro-style.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-options-headers-digits-strings.html b/FHC-vendor/jquery-tablesorter/docs/example-options-headers-digits-strings.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-options-headers-digits-strings.html rename to FHC-vendor/jquery-tablesorter/docs/example-options-headers-digits-strings.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-options-headers-locked.html b/FHC-vendor/jquery-tablesorter/docs/example-options-headers-locked.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-options-headers-locked.html rename to FHC-vendor/jquery-tablesorter/docs/example-options-headers-locked.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-options-headers-order.html b/FHC-vendor/jquery-tablesorter/docs/example-options-headers-order.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-options-headers-order.html rename to FHC-vendor/jquery-tablesorter/docs/example-options-headers-order.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-options-headers-parser.html b/FHC-vendor/jquery-tablesorter/docs/example-options-headers-parser.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-options-headers-parser.html rename to FHC-vendor/jquery-tablesorter/docs/example-options-headers-parser.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-options-headers.html b/FHC-vendor/jquery-tablesorter/docs/example-options-headers.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-options-headers.html rename to FHC-vendor/jquery-tablesorter/docs/example-options-headers.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-pager-ajax.html b/FHC-vendor/jquery-tablesorter/docs/example-pager-ajax.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-pager-ajax.html rename to FHC-vendor/jquery-tablesorter/docs/example-pager-ajax.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-pager-filtered.html b/FHC-vendor/jquery-tablesorter/docs/example-pager-filtered.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-pager-filtered.html rename to FHC-vendor/jquery-tablesorter/docs/example-pager-filtered.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-pager.html b/FHC-vendor/jquery-tablesorter/docs/example-pager.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-pager.html rename to FHC-vendor/jquery-tablesorter/docs/example-pager.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-advanced.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-advanced.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-advanced.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-advanced.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-class-name.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-class-name.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-class-name.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-class-name.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-date-range.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-date-range.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-date-range.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-date-range.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-dates.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-dates.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-dates.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-dates.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-duration.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-duration.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-duration.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-duration.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-feet-inch-fraction.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-feet-inch-fraction.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-feet-inch-fraction.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-feet-inch-fraction.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-file-type.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-file-type.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-file-type.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-file-type.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-globalize.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-globalize.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-globalize.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-globalize.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-ignore-articles.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-ignore-articles.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-ignore-articles.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-ignore-articles.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-ip-address.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-ip-address.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-ip-address.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-ip-address.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-jquery-data.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-jquery-data.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-jquery-data.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-jquery-data.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-metric.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-metric.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-metric.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-metric.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-named-numbers.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-named-numbers.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-named-numbers.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-named-numbers.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-roman.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers-roman.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers-roman.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers-roman.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers.html b/FHC-vendor/jquery-tablesorter/docs/example-parsers.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-parsers.html rename to FHC-vendor/jquery-tablesorter/docs/example-parsers.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-trigger-sort.html b/FHC-vendor/jquery-tablesorter/docs/example-trigger-sort.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-trigger-sort.html rename to FHC-vendor/jquery-tablesorter/docs/example-trigger-sort.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-triggers.html b/FHC-vendor/jquery-tablesorter/docs/example-triggers.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-triggers.html rename to FHC-vendor/jquery-tablesorter/docs/example-triggers.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-update-all.html b/FHC-vendor/jquery-tablesorter/docs/example-update-all.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-update-all.html rename to FHC-vendor/jquery-tablesorter/docs/example-update-all.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-update-cell.html b/FHC-vendor/jquery-tablesorter/docs/example-update-cell.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-update-cell.html rename to FHC-vendor/jquery-tablesorter/docs/example-update-cell.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-align-character.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-align-character.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-align-character.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-align-character.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-bootstrap-theme-v2.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-bootstrap-theme-v2.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-bootstrap-theme-v2.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-bootstrap-theme-v2.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-bootstrap-theme.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-bootstrap-theme.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-bootstrap-theme.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-bootstrap-theme.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-build-table.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-build-table.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-build-table.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-build-table.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-chart.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-chart.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-chart.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-chart.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-column-selector.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-column-selector.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-column-selector.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-column-selector.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-columns.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-columns.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-columns.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-columns.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-css-sticky-header.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-css-sticky-header.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-css-sticky-header.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-css-sticky-header.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-editable.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-editable.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-editable.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-editable.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-any-match.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-any-match.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-any-match.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-filter-any-match.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-childrows.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-childrows.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-childrows.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-filter-childrows.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-custom-search.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-custom-search.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-custom-search.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-filter-custom-search.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-custom-search2.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-custom-search2.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-custom-search2.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-filter-custom-search2.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-custom.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-custom.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-custom.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-filter-custom.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-external-inputs.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-external-inputs.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-external-inputs.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-filter-external-inputs.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-formatter-1.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-formatter-1.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-formatter-1.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-filter-formatter-1.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-formatter-2.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-formatter-2.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-formatter-2.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-filter-formatter-2.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-formatter-select2.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-formatter-select2.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-formatter-select2.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-filter-formatter-select2.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-selectmenu.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-selectmenu.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter-selectmenu.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-filter-selectmenu.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-filter.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-filter.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-filter.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-formatter.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-formatter.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-formatter.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-formatter.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-grouping-filter-childrows.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-grouping-filter-childrows.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-grouping-filter-childrows.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-grouping-filter-childrows.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-grouping.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-grouping.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-grouping.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-grouping.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-header-titles.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-header-titles.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-header-titles.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-header-titles.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-lazyload.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-lazyload.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-lazyload.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-lazyload.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-math.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-math.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-math.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-math.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-output.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-output.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-output.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-output.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-pager-ajax.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-pager-ajax.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-pager-ajax.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-pager-ajax.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-pager.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-pager.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-pager.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-pager.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-print.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-print.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-print.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-print.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-reflow.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-reflow.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-reflow.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-reflow.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-reflow1.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-reflow1.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-reflow1.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-reflow1.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-reflow2.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-reflow2.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-reflow2.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-reflow2.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-reflow3.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-reflow3.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-reflow3.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-reflow3.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-resizable.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-resizable.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-resizable.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-resizable.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-savesort.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-savesort.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-savesort.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-savesort.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-scroller.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-scroller.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-scroller.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-scroller.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-sort-tbodies.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-sort-tbodies.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-sort-tbodies.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-sort-tbodies.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-sort-to-hash.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-sort-to-hash.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-sort-to-hash.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-sort-to-hash.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-static-row.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-static-row.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-static-row.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-static-row.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-sticky-header.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-sticky-header.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-sticky-header.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-sticky-header.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-toggle-tablesorter.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-toggle-tablesorter.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-toggle-tablesorter.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-toggle-tablesorter.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-ui-theme.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-ui-theme.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-ui-theme.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-ui-theme.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-view.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-view.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-view.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-view.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-zebra.html b/FHC-vendor/jquery-tablesorter/docs/example-widget-zebra.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widget-zebra.html rename to FHC-vendor/jquery-tablesorter/docs/example-widget-zebra.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/example-widgets.html b/FHC-vendor/jquery-tablesorter/docs/example-widgets.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/example-widgets.html rename to FHC-vendor/jquery-tablesorter/docs/example-widgets.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.eot b/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.eot similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.eot rename to FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.eot diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.svg b/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.svg similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.svg rename to FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.svg diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.ttf b/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.ttf similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.ttf rename to FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.ttf diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.woff b/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.woff similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.woff rename to FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.woff diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.woff2 b/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.woff2 similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.woff2 rename to FHC-vendor/jquery-tablesorter/docs/fonts/glyphicons-halflings-regular.woff2 diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/img/external.png b/FHC-vendor/jquery-tablesorter/docs/img/external.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/img/external.png rename to FHC-vendor/jquery-tablesorter/docs/img/external.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/img/grid-default-thumb.png b/FHC-vendor/jquery-tablesorter/docs/img/grid-default-thumb.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/img/grid-default-thumb.png rename to FHC-vendor/jquery-tablesorter/docs/img/grid-default-thumb.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/img/link.png b/FHC-vendor/jquery-tablesorter/docs/img/link.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/img/link.png rename to FHC-vendor/jquery-tablesorter/docs/img/link.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/img/new-product-banner.png b/FHC-vendor/jquery-tablesorter/docs/img/new-product-banner.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/img/new-product-banner.png rename to FHC-vendor/jquery-tablesorter/docs/img/new-product-banner.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/img/sale-banner.png b/FHC-vendor/jquery-tablesorter/docs/img/sale-banner.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/img/sale-banner.png rename to FHC-vendor/jquery-tablesorter/docs/img/sale-banner.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/img/screens-blue.png b/FHC-vendor/jquery-tablesorter/docs/img/screens-blue.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/img/screens-blue.png rename to FHC-vendor/jquery-tablesorter/docs/img/screens-blue.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/img/screens.png b/FHC-vendor/jquery-tablesorter/docs/img/screens.png similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/img/screens.png rename to FHC-vendor/jquery-tablesorter/docs/img/screens.png diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/index.html b/FHC-vendor/jquery-tablesorter/docs/index.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/index.html rename to FHC-vendor/jquery-tablesorter/docs/index.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/bootstrap.min.js b/FHC-vendor/jquery-tablesorter/docs/js/bootstrap.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/bootstrap.min.js rename to FHC-vendor/jquery-tablesorter/docs/js/bootstrap.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/chili/jquery.chili-2.2.js b/FHC-vendor/jquery-tablesorter/docs/js/chili/jquery.chili-2.2.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/chili/jquery.chili-2.2.js rename to FHC-vendor/jquery-tablesorter/docs/js/chili/jquery.chili-2.2.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/chili/recipes.js b/FHC-vendor/jquery-tablesorter/docs/js/chili/recipes.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/chili/recipes.js rename to FHC-vendor/jquery-tablesorter/docs/js/chili/recipes.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/demo-build-table.js b/FHC-vendor/jquery-tablesorter/docs/js/demo-build-table.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/demo-build-table.js rename to FHC-vendor/jquery-tablesorter/docs/js/demo-build-table.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/docs.js b/FHC-vendor/jquery-tablesorter/docs/js/docs.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/docs.js rename to FHC-vendor/jquery-tablesorter/docs/js/docs.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery-1.2.6.min.js b/FHC-vendor/jquery-tablesorter/docs/js/jquery-1.2.6.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery-1.2.6.min.js rename to FHC-vendor/jquery-tablesorter/docs/js/jquery-1.2.6.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery-1.4.4.min.js b/FHC-vendor/jquery-tablesorter/docs/js/jquery-1.4.4.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery-1.4.4.min.js rename to FHC-vendor/jquery-tablesorter/docs/js/jquery-1.4.4.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery-latest.min.js b/FHC-vendor/jquery-tablesorter/docs/js/jquery-latest.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery-latest.min.js rename to FHC-vendor/jquery-tablesorter/docs/js/jquery-latest.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery-ui.min.js b/FHC-vendor/jquery-tablesorter/docs/js/jquery-ui.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery-ui.min.js rename to FHC-vendor/jquery-tablesorter/docs/js/jquery-ui.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery.jui_theme_switch.min.js b/FHC-vendor/jquery-tablesorter/docs/js/jquery.jui_theme_switch.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery.jui_theme_switch.min.js rename to FHC-vendor/jquery-tablesorter/docs/js/jquery.jui_theme_switch.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery.magnific-popup.min.js b/FHC-vendor/jquery-tablesorter/docs/js/jquery.magnific-popup.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery.magnific-popup.min.js rename to FHC-vendor/jquery-tablesorter/docs/js/jquery.magnific-popup.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery.tipsy.min.js b/FHC-vendor/jquery-tablesorter/docs/js/jquery.tipsy.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/jquery.tipsy.min.js rename to FHC-vendor/jquery-tablesorter/docs/js/jquery.tipsy.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/prettify.js b/FHC-vendor/jquery-tablesorter/docs/js/prettify.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/prettify.js rename to FHC-vendor/jquery-tablesorter/docs/js/prettify.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/rangeslider.min.js b/FHC-vendor/jquery-tablesorter/docs/js/rangeslider.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/rangeslider.min.js rename to FHC-vendor/jquery-tablesorter/docs/js/rangeslider.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/search-ie.js b/FHC-vendor/jquery-tablesorter/docs/js/search-ie.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/search-ie.js rename to FHC-vendor/jquery-tablesorter/docs/js/search-ie.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/search.js b/FHC-vendor/jquery-tablesorter/docs/js/search.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/search.js rename to FHC-vendor/jquery-tablesorter/docs/js/search.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/select2-3.4.6.min.js b/FHC-vendor/jquery-tablesorter/docs/js/select2-3.4.6.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/select2-3.4.6.min.js rename to FHC-vendor/jquery-tablesorter/docs/js/select2-3.4.6.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/js/sugar.min.js b/FHC-vendor/jquery-tablesorter/docs/js/sugar.min.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/js/sugar.min.js rename to FHC-vendor/jquery-tablesorter/docs/js/sugar.min.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/docs/themes.html b/FHC-vendor/jquery-tablesorter/docs/themes.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/docs/themes.html rename to FHC-vendor/jquery-tablesorter/docs/themes.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/example.json b/FHC-vendor/jquery-tablesorter/example.json similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/example.json rename to FHC-vendor/jquery-tablesorter/example.json diff --git a/vendor/FHC-vendor/jquery-tablesorter/index.html b/FHC-vendor/jquery-tablesorter/index.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/index.html rename to FHC-vendor/jquery-tablesorter/index.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/extras/jquery.dragtable.mod.js b/FHC-vendor/jquery-tablesorter/js/extras/jquery.dragtable.mod.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/extras/jquery.dragtable.mod.js rename to FHC-vendor/jquery-tablesorter/js/extras/jquery.dragtable.mod.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/extras/jquery.metadata.js b/FHC-vendor/jquery-tablesorter/js/extras/jquery.metadata.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/extras/jquery.metadata.js rename to FHC-vendor/jquery-tablesorter/js/extras/jquery.metadata.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/extras/semver-mod.js b/FHC-vendor/jquery-tablesorter/js/extras/semver-mod.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/extras/semver-mod.js rename to FHC-vendor/jquery-tablesorter/js/extras/semver-mod.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/extras/semver.js b/FHC-vendor/jquery-tablesorter/js/extras/semver.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/extras/semver.js rename to FHC-vendor/jquery-tablesorter/js/extras/semver.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/jquery.tablesorter.combined.js b/FHC-vendor/jquery-tablesorter/js/jquery.tablesorter.combined.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/jquery.tablesorter.combined.js rename to FHC-vendor/jquery-tablesorter/js/jquery.tablesorter.combined.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/jquery.tablesorter.js b/FHC-vendor/jquery-tablesorter/js/jquery.tablesorter.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/jquery.tablesorter.js rename to FHC-vendor/jquery-tablesorter/js/jquery.tablesorter.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/jquery.tablesorter.widgets.js b/FHC-vendor/jquery-tablesorter/js/jquery.tablesorter.widgets.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/jquery.tablesorter.widgets.js rename to FHC-vendor/jquery-tablesorter/js/jquery.tablesorter.widgets.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-extract.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-extract.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-extract.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-date-extract.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-iso8601.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-iso8601.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-iso8601.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-date-iso8601.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-month.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-month.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-month.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-date-month.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-range.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-range.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-range.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-date-range.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-two-digit-year.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-two-digit-year.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-two-digit-year.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-date-two-digit-year.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-weekday.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-weekday.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date-weekday.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-date-weekday.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-date.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-date.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-date.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-duration.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-duration.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-duration.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-duration.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-feet-inch-fraction.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-feet-inch-fraction.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-feet-inch-fraction.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-feet-inch-fraction.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-file-type.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-file-type.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-file-type.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-file-type.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-globalize.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-globalize.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-globalize.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-globalize.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-ignore-articles.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-ignore-articles.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-ignore-articles.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-ignore-articles.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-image.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-image.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-image.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-image.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-input-select.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-input-select.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-input-select.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-input-select.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-metric.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-metric.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-metric.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-metric.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-named-numbers.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-named-numbers.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-named-numbers.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-named-numbers.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-network.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-network.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-network.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-network.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-roman.js b/FHC-vendor/jquery-tablesorter/js/parsers/parser-roman.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/parsers/parser-roman.js rename to FHC-vendor/jquery-tablesorter/js/parsers/parser-roman.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-alignChar.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-alignChar.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-alignChar.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-alignChar.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-build-table.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-build-table.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-build-table.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-build-table.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-chart.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-chart.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-chart.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-chart.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-columnSelector.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-columnSelector.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-columnSelector.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-columnSelector.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-columns.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-columns.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-columns.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-columns.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-cssStickyHeaders.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-cssStickyHeaders.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-cssStickyHeaders.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-cssStickyHeaders.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-editable.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-editable.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-editable.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-editable.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-formatter-html5.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-formatter-html5.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-formatter-html5.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-formatter-html5.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-formatter-jui.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-formatter-jui.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-formatter-jui.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-formatter-jui.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-formatter-select2.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-formatter-select2.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-formatter-select2.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-formatter-select2.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-type-insideRange.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-type-insideRange.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-type-insideRange.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-filter-type-insideRange.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-filter.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-filter.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-formatter.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-formatter.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-formatter.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-formatter.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-grouping.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-grouping.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-grouping.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-grouping.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-headerTitles.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-headerTitles.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-headerTitles.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-headerTitles.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-lazyload.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-lazyload.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-lazyload.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-lazyload.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-math.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-math.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-math.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-math.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-output.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-output.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-output.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-output.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-pager.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-pager.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-pager.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-pager.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-print.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-print.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-print.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-print.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-reflow.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-reflow.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-reflow.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-reflow.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-repeatheaders.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-repeatheaders.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-repeatheaders.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-repeatheaders.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-resizable.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-resizable.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-resizable.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-resizable.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-saveSort.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-saveSort.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-saveSort.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-saveSort.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-scroller.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-scroller.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-scroller.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-scroller.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-sort2Hash.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-sort2Hash.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-sort2Hash.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-sort2Hash.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-sortTbodies.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-sortTbodies.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-sortTbodies.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-sortTbodies.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-staticRow.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-staticRow.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-staticRow.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-staticRow.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-stickyHeaders.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-stickyHeaders.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-stickyHeaders.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-stickyHeaders.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-storage.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-storage.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-storage.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-storage.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-toggle.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-toggle.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-toggle.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-toggle.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-uitheme.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-uitheme.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-uitheme.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-uitheme.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-view.js b/FHC-vendor/jquery-tablesorter/js/widgets/widget-view.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/js/widgets/widget-view.js rename to FHC-vendor/jquery-tablesorter/js/widgets/widget-view.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/package.json b/FHC-vendor/jquery-tablesorter/package.json similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/package.json rename to FHC-vendor/jquery-tablesorter/package.json diff --git a/vendor/FHC-vendor/jquery-tablesorter/tablesorter.jquery.json b/FHC-vendor/jquery-tablesorter/tablesorter.jquery.json similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/tablesorter.jquery.json rename to FHC-vendor/jquery-tablesorter/tablesorter.jquery.json diff --git a/vendor/FHC-vendor/jquery-tablesorter/test.html b/FHC-vendor/jquery-tablesorter/test.html similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/test.html rename to FHC-vendor/jquery-tablesorter/test.html diff --git a/vendor/FHC-vendor/jquery-tablesorter/testing/qunit-1.20.0.css b/FHC-vendor/jquery-tablesorter/testing/qunit-1.20.0.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/testing/qunit-1.20.0.css rename to FHC-vendor/jquery-tablesorter/testing/qunit-1.20.0.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/testing/qunit-1.20.0.js b/FHC-vendor/jquery-tablesorter/testing/qunit-1.20.0.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/testing/qunit-1.20.0.js rename to FHC-vendor/jquery-tablesorter/testing/qunit-1.20.0.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/testing/testing-ipv6.js b/FHC-vendor/jquery-tablesorter/testing/testing-ipv6.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/testing/testing-ipv6.js rename to FHC-vendor/jquery-tablesorter/testing/testing-ipv6.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/testing/testing-widgets.js b/FHC-vendor/jquery-tablesorter/testing/testing-widgets.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/testing/testing-widgets.js rename to FHC-vendor/jquery-tablesorter/testing/testing-widgets.js diff --git a/vendor/FHC-vendor/jquery-tablesorter/testing/testing.css b/FHC-vendor/jquery-tablesorter/testing/testing.css similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/testing/testing.css rename to FHC-vendor/jquery-tablesorter/testing/testing.css diff --git a/vendor/FHC-vendor/jquery-tablesorter/testing/testing.js b/FHC-vendor/jquery-tablesorter/testing/testing.js similarity index 100% rename from vendor/FHC-vendor/jquery-tablesorter/testing/testing.js rename to FHC-vendor/jquery-tablesorter/testing/testing.js diff --git a/README.md b/README.md index c4b24c64d..d5620010a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # FH-Complete -* [FH-Complete Homepage](http://www.fhcomplete.org) -* [Wiki](http://fhcomplete.technikum-wien.at/dokuwiki/) +* [FH-Complete Homepage](https://www.fhcomplete.org) +* [Wiki](https://wiki.fhcomplete.org/) * [Changelog](CHANGELOG.md) diff --git a/application/config/config.php b/application/config/config.php index 1c0993c92..591b84f2c 100644 --- a/application/config/config.php +++ b/application/config/config.php @@ -503,3 +503,15 @@ $config['rewrite_short_tags'] = FALSE; | Array: array('10.0.1.200', '192.168.5.0/24') */ $config['proxy_ips'] = ''; + +/* +|-------------------------------------------------------------------------- +| FHComplete Build Version +|-------------------------------------------------------------------------- +| +| Version Number of the Current Build +| This is used to invalidate Cache for JS and CSS Files +| +| Example: 2019102901 +*/ +$config['fhcomplete_build_version'] = '2019102903'; diff --git a/application/config/constants.php b/application/config/constants.php index ac2ecc649..ef4cdaf2c 100644 --- a/application/config/constants.php +++ b/application/config/constants.php @@ -64,7 +64,9 @@ define('LDAP_TOO_MANY_USER_DN', 11); |-------------------------------------------------------------------------- */ define('LANG_SESSION_NAME', 'LANGUAGE'); -define('LANG_SESSION_INDEXES', 'LANGUAGE_INDEXES'); +define('LANG_SESSION_INDEXES', 'INDEXES'); +define('LANG_SESSION_ACTIVE_LANGUAGES', 'ACTIVE_LANGUAGES'); +define('LANG_SESSION_CURRENT_LANGUAGE', 'sprache'); // NOTE: it is not under LANG_SESSION_NAME /* |-------------------------------------------------------------------------- @@ -125,37 +127,25 @@ define('EMAIL_CONFIG_INDEX', 'mail'); | Messaging system constants |-------------------------------------------------------------------------- */ -// Email kontakt type -define('EMAIL_KONTAKT_TYPE', 'email'); -// tbl_msg_recipient->sentInfo separator -define('SENT_INFO_NEWLINE', '\n'); - // Message statuses define('MSG_STATUS_UNREAD', 0); define('MSG_STATUS_READ', 1); define('MSG_STATUS_ARCHIVED', 2); define('MSG_STATUS_DELETED', 3); -// Priority -define('PRIORITY_LOW', 1); -define('PRIORITY_NORMAL', 2); -define('PRIORITY_HIGH', 3); -define('PRIORITY_URGENT', 4); +// Message priorities +define('MSG_PRIORITY_LOW', 1); +define('MSG_PRIORITY_NORMAL', 2); +define('MSG_PRIORITY_HIGH', 3); +define('MSG_PRIORITY_URGENT', 4); -define('MSG_ERR_SUBJECT_EMPTY', 40); -define('MSG_ERR_BODY_EMPTY', 41); -define('MSG_ERR_TEMPLATE_NOT_FOUND', 42); -define('MSG_ERR_DELIVERY_MESSAGE', 43); -define('MSG_ERR_CONTACT_NOT_FOUND', 44); -define('MSG_ERR_OU_CONTACTS_NOT_FOUND', 45); - -define('MSG_ERR_INVALID_USER_ID', 100); -define('MSG_ERR_INVALID_MSG_ID', 101); -define('MSG_ERR_INVALID_THREAD_ID', 102); -define('MSG_ERR_INVALID_STATUS_ID', 103); -define('MSG_ERR_INVALID_SENDER_ID', 104); -define('MSG_ERR_INVALID_RECIPIENTS', 105); -define('MSG_ERR_INVALID_RECEIVER_ID', 106); -define('MSG_ERR_INVALID_OU', 107); -define('MSG_ERR_INVALID_TEMPLATE', 108); -define('MSG_ERR_INVALID_TOKEN', 109); +// Message error status +define('MSG_ERR_INVALID_SUBJECT', 40); +define('MSG_ERR_INVALID_BODY', 41); +define('MSG_ERR_INVALID_TEMPLATE', 42); +define('MSG_ERR_INVALID_MSG_ID', 43); +define('MSG_ERR_INVALID_STATUS_ID', 44); +define('MSG_ERR_INVALID_SENDER', 45); +define('MSG_ERR_INVALID_RECIPIENTS', 46); +define('MSG_ERR_INVALID_OU', 47); +define('MSG_ERR_INVALID_TOKEN', 48); diff --git a/application/config/dbskel.php b/application/config/dbskel.php deleted file mode 100644 index dafdc0d31..000000000 --- a/application/config/dbskel.php +++ /dev/null @@ -1,27 +0,0 @@ -/addons/aufnahme/OE_ROOT/cis/index.php'; +// $config['message_redirect_url']['OE_ROOT_2'] = 'https:///'; diff --git a/application/config/navigation.php b/application/config/navigation.php index d6f4b8452..a89c259ee 100644 --- a/application/config/navigation.php +++ b/application/config/navigation.php @@ -14,6 +14,7 @@ $config['navigation_header'] = array( 'icon' => 'sitemap', 'description' => 'Organisation', 'sort' => 20, + 'requiredPermissions' => 'basis/vilesci:r', 'children'=> array( 'vilesci' => array( 'link' => base_url('vilesci'), @@ -30,6 +31,7 @@ $config['navigation_header'] = array( 'icon' => 'graduation-cap', 'description' => 'Lehre', 'sort' => 30, + 'requiredPermissions' => 'basis/vilesci:r', 'children'=> array( 'cis' => array( 'link' => CIS_ROOT, @@ -51,6 +53,16 @@ $config['navigation_header'] = array( 'sort' => 30, 'requiredPermissions' => 'infocenter:r' ), + 'lehrauftrag' => array( + 'link' => site_url('lehre/lehrauftrag/Lehrauftrag/Dashboard'), + 'description' => 'Lehrauftrag', + 'expand' => true, + 'sort' => 40, + 'requiredPermissions' => array( + 'lehre/lehrauftrag_bestellen:r', + 'lehre/lehrauftrag_erteilen:r' + ) + ) ) ), 'Personen' => array( @@ -58,12 +70,20 @@ $config['navigation_header'] = array( 'icon' => 'user', 'description' => 'Personen', 'sort' => 40, + 'requiredPermissions' => 'basis/vilesci:r', 'children'=> array( + 'messages' => array( + 'link' => site_url('system/messages/MessageClient/read'), + 'icon' => '', + 'target' => '_blank', + 'description' => 'Messages', + 'sort' => 10, + ), 'bpk' => array( 'link' => site_url('person/BPKWartung'), 'icon' => '', 'description' => 'BPK Wartung', - 'sort' => 10, + 'sort' => 20, 'requiredPermissions' => 'admin:r' ) ) @@ -82,6 +102,13 @@ $config['navigation_header'] = array( 'expand' => true, 'sort' => 10, 'requiredPermissions' => 'admin:r' + ), + 'logsviewer' => array( + 'link' => site_url('system/LogsViewer'), + 'description' => 'Logs', + 'expand' => true, + 'sort' => 20, + 'requiredPermissions' => 'system/developer:r' ) ) ) @@ -118,3 +145,62 @@ $config['navigation_menu']['organisation/Reihungstest/index'] = array( 'target' => '_blank' ) ); + +$config['navigation_menu']['lehre/lehrauftrag/Lehrauftrag/*'] = array( + 'lehrauftragDashboard' => array( + 'link' => site_url('lehre/lehrauftrag/Lehrauftrag/Dashboard'), + 'description' => 'Dashboard', + 'icon' => 'dashboard', + 'sort' => 1, + 'requiredPermissions' => array('lehre/lehrauftrag_bestellen:r','lehre/lehrauftrag_erteilen:r') + ),'lehrauftragBestellen' => array( + 'link' => site_url('lehre/lehrauftrag/Lehrauftrag'), + 'description' => 'Lehrauftrag bestellen', + 'icon' => '', + 'sort' => 1, + 'requiredPermissions' => 'lehre/lehrauftrag_bestellen:r' + ), + 'lehrauftragErteilen' => array( + 'link' => site_url('lehre/lehrauftrag/LehrauftragErteilen'), + 'description' => 'Lehrauftrag erteilen', + 'icon' => '', + 'sort' => 1, + 'requiredPermissions' => 'lehre/lehrauftrag_erteilen:r' + ), + 'lehrauftragLehrendeÜbersicht' => array( + 'link' => site_url('lehre/lehrauftrag/Lehrauftrag/LehrendeUebersicht'), + 'description' => 'Lehrendenübersicht', + 'icon' => '', + 'sort' => 1, + 'requiredPermissions' => array('lehre/lehrauftrag_erteilen:r') + ) +); +$config['navigation_menu']['lehre/lehrauftrag/LehrauftragErteilen/*'] = array( + 'lehrauftragDashboard' => array( + 'link' => site_url('lehre/lehrauftrag/Lehrauftrag/Dashboard'), + 'description' => 'Dashboard', + 'icon' => 'dashboard', + 'sort' => 1, + 'requiredPermissions' => array('lehre/lehrauftrag_bestellen:r','lehre/lehrauftrag_erteilen:r') + ),'lehrauftragBestellen' => array( + 'link' => site_url('lehre/lehrauftrag/Lehrauftrag'), + 'description' => 'Lehrauftrag bestellen', + 'icon' => '', + 'sort' => 1, + 'requiredPermissions' => 'lehre/lehrauftrag_bestellen:r' + ), + 'lehrauftragErteilen' => array( + 'link' => site_url('lehre/lehrauftrag/LehrauftragErteilen'), + 'description' => 'Lehrauftrag erteilen', + 'icon' => '', + 'sort' => 1, + 'requiredPermissions' => 'lehre/lehrauftrag_erteilen:r' + ), + 'lehrauftragLehrendeÜbersicht' => array( + 'link' => site_url('lehre/lehrauftrag/Lehrauftrag/LehrendeUebersicht'), + 'description' => 'Lehrendenübersicht', + 'icon' => '', + 'sort' => 1, + 'requiredPermissions' => array('lehre/lehrauftrag_erteilen:r') + ) +); diff --git a/application/config/rest.php b/application/config/rest.php index 9bbbf40ef..833a99881 100644 --- a/application/config/rest.php +++ b/application/config/rest.php @@ -1,6 +1,6 @@ '1234', 'test' => 'test']; - -/* -|-------------------------------------------------------------------------- -| Global IP Whitelisting -|-------------------------------------------------------------------------- -| -| Limit connections to your REST server to whitelisted IP addresses +| Limit connections to your REST server to White-listed IP addresses | | Usage: | 1. Set to TRUE and select an auth option for extreme security (client's IP -| address must be in whitelist and they must also log in) -| 2. Set to TRUE with auth set to FALSE to allow whitelisted IPs access with no login -| 3. Set to FALSE but set 'auth_override_class_method' to 'whitelist' to -| restrict certain methods to IPs in your whitelist +| address must be in white-list and they must also log in) +| 2. Set to TRUE with auth set to FALSE to allow White-listed IPs access with no login +| 3. Set to FALSE but set 'auth_override_class_method' to 'white-list' to +| restrict certain methods to IPs in your white-list | */ $config['rest_ip_whitelist_enabled'] = TRUE; /* |-------------------------------------------------------------------------- -| REST IP Whitelist +| REST IP White-list |-------------------------------------------------------------------------- | | Limit connections to your REST server with a comma separated @@ -240,42 +107,6 @@ $config['rest_ip_whitelist_enabled'] = TRUE; */ $config['rest_ip_whitelist'] = '127.0.0.1'; -/* -|-------------------------------------------------------------------------- -| Global IP Blacklisting -|-------------------------------------------------------------------------- -| -| Prevent connections to the REST server from blacklisted IP addresses -| -| Usage: -| 1. Set to TRUE and add any IP address to 'rest_ip_blacklist' -| -*/ -$config['rest_ip_blacklist_enabled'] = FALSE; - -/* -|-------------------------------------------------------------------------- -| REST IP Blacklist -|-------------------------------------------------------------------------- -| -| Prevent connections from the following IP addresses -| -| e.g: '123.456.789.0, 987.654.32.1' -| -*/ -$config['rest_ip_blacklist'] = ''; - -/* -|-------------------------------------------------------------------------- -| REST Database Group -|-------------------------------------------------------------------------- -| -| Connect to a database group for keys, logging, etc. It will only connect -| if you have any of these features enabled -| -*/ -$config['rest_database_group'] = 'default'; - /* |-------------------------------------------------------------------------- | REST API Keys Table Name @@ -298,6 +129,7 @@ $config['rest_keys_table'] = 'ci_apikey'; | Default table schema: | CREATE TABLE `keys` ( | `id` INT(11) NOT NULL AUTO_INCREMENT, +| `user_id` INT(11) NOT NULL, | `key` VARCHAR(40) NOT NULL, | `level` INT(2) NOT NULL, | `ignore_limits` TINYINT(1) NOT NULL DEFAULT '0', @@ -310,45 +142,6 @@ $config['rest_keys_table'] = 'ci_apikey'; */ $config['rest_enable_keys'] = TRUE; -/* -|-------------------------------------------------------------------------- -| REST Table Key Column Name -|-------------------------------------------------------------------------- -| -| If not using the default table schema in 'rest_enable_keys', specify the -| column name to match e.g. my_key -| -*/ -$config['rest_key_column'] = 'key'; - -/* -|-------------------------------------------------------------------------- -| REST API Limits method -|-------------------------------------------------------------------------- -| -| Specify the method used to limit the API calls -| -| Available methods are : -| $config['rest_limits_method'] = 'API_KEY'; // Put a limit per api key -| $config['rest_limits_method'] = 'METHOD_NAME'; // Put a limit on method calls -| $config['rest_limits_method'] = 'ROUTED_URL'; // Put a limit on the routed URL -| -*/ -$config['rest_limits_method'] = 'ROUTED_URL'; - -/* -|-------------------------------------------------------------------------- -| REST Key Length -|-------------------------------------------------------------------------- -| -| Length of the created keys. Check your default database schema on the -| maximum length allowed -| -| Note: The maximum length is 40 -| -*/ -$config['rest_key_length'] = 40; - /* |-------------------------------------------------------------------------- | REST API Key Variable @@ -364,156 +157,10 @@ $config['rest_key_name'] = 'FHC-API-KEY'; /* |-------------------------------------------------------------------------- -| REST Enable Logging +| REST Methods name format |-------------------------------------------------------------------------- | -| When set to TRUE, the REST API will log actions based on the column names 'key', 'date', -| 'time' and 'ip_address'. This is a general rule that can be overridden in the -| $this->method array for each controller -| -| Default table schema: -| CREATE TABLE `logs` ( -| `id` INT(11) NOT NULL AUTO_INCREMENT, -| `uri` VARCHAR(255) NOT NULL, -| `method` VARCHAR(6) NOT NULL, -| `params` TEXT DEFAULT NULL, -| `api_key` VARCHAR(40) NOT NULL, -| `ip_address` VARCHAR(45) NOT NULL, -| `time` INT(11) NOT NULL, -| `rtime` FLOAT DEFAULT NULL, -| `authorized` VARCHAR(1) NOT NULL, -| `response_code` smallint(3) DEFAULT '0', -| PRIMARY KEY (`id`) -| ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +| REST Controllers methods name format | */ -$config['rest_enable_logging'] = FALSE; - -/* -|-------------------------------------------------------------------------- -| REST API Logs Table Name -|-------------------------------------------------------------------------- -| -| If not using the default table schema in 'rest_enable_logging', specify the -| table name to match e.g. my_logs -| -*/ -$config['rest_logs_table'] = 'logs'; - -/* -|-------------------------------------------------------------------------- -| REST Method Access Control -|-------------------------------------------------------------------------- -| When set to TRUE, the REST API will check the access table to see if -| the API key can access that controller. 'rest_enable_keys' must be enabled -| to use this -| -| Default table schema: -| CREATE TABLE `access` ( -| `id` INT(11) unsigned NOT NULL AUTO_INCREMENT, -| `key` VARCHAR(40) NOT NULL DEFAULT '', -| `controller` VARCHAR(50) NOT NULL DEFAULT '', -| `date_created` DATETIME DEFAULT NULL, -| `date_modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -| PRIMARY KEY (`id`) -| ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -| -*/ -$config['rest_enable_access'] = FALSE; - -/* -|-------------------------------------------------------------------------- -| REST API Access Table Name -|-------------------------------------------------------------------------- -| -| If not using the default table schema in 'rest_enable_access', specify the -| table name to match e.g. my_access -| -*/ -$config['rest_access_table'] = 'access'; - -/* -|-------------------------------------------------------------------------- -| REST API Param Log Format -|-------------------------------------------------------------------------- -| -| When set to TRUE, the REST API log parameters will be stored in the database as JSON -| Set to FALSE to log as serialized PHP -| -*/ -$config['rest_logs_json_params'] = FALSE; - -/* -|-------------------------------------------------------------------------- -| REST Enable Limits -|-------------------------------------------------------------------------- -| -| When set to TRUE, the REST API will count the number of uses of each method -| by an API key each hour. This is a general rule that can be overridden in the -| $this->method array in each controller -| -| Default table schema: -| CREATE TABLE `limits` ( -| `id` INT(11) NOT NULL AUTO_INCREMENT, -| `uri` VARCHAR(255) NOT NULL, -| `count` INT(10) NOT NULL, -| `hour_started` INT(11) NOT NULL, -| `api_key` VARCHAR(40) NOT NULL, -| PRIMARY KEY (`id`) -| ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -| -| To specify the limits within the controller's __construct() method, add per-method -| limits with: -| -| $this->method['METHOD_NAME']['limit'] = [NUM_REQUESTS_PER_HOUR]; -| -| See application/controllers/api/example.php for examples -*/ -$config['rest_enable_limits'] = FALSE; - -/* -|-------------------------------------------------------------------------- -| REST API Limits Table Name -|-------------------------------------------------------------------------- -| -| If not using the default table schema in 'rest_enable_limits', specify the -| table name to match e.g. my_limits -| -*/ -$config['rest_limits_table'] = 'limits'; - -/* -|-------------------------------------------------------------------------- -| REST Ignore HTTP Accept -|-------------------------------------------------------------------------- -| -| Set to TRUE to ignore the HTTP Accept and speed up each request a little. -| Only do this if you are using the $this->rest_format or /format/xml in URLs -| -*/ -$config['rest_ignore_http_accept'] = FALSE; - -/* -|-------------------------------------------------------------------------- -| REST AJAX Only -|-------------------------------------------------------------------------- -| -| Set to TRUE to allow AJAX requests only. Set to FALSE to accept HTTP requests -| -| Note: If set to TRUE and the request is not AJAX, a 505 response with the -| error message 'Only AJAX requests are accepted.' will be returned. -| -| Hint: This is good for production environments -| -*/ -$config['rest_ajax_only'] = FALSE; - -/* -|-------------------------------------------------------------------------- -| REST Language File -|-------------------------------------------------------------------------- -| -| Language file to load from the language directory -| -*/ -$config['rest_language'] = 'english'; +$config['rest_methods_name_format'] = '%2$s%1$s'; diff --git a/application/config/routes.php b/application/config/routes.php index 791b6d03c..36bfdcb1e 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -1,5 +1,6 @@ my_controller/index -| my-controller/my-method -> my_controller/my_method +| Examples: my-controller/index -> my_controller/index +| my-controller/my-method -> my_controller/my_method */ $route['default_controller'] = 'Vilesci'; -$route['404_override'] = ''; $route['translate_uri_dashes'] = FALSE; // Class name conflicts @@ -59,4 +59,4 @@ $route['api/v1/organisation/[F|f]achbereich/(:any)'] = 'api/v1/organisation/fach $route['api/v1/organisation/[G|g]eschaeftsjahr/(:any)'] = 'api/v1/organisation/geschaeftsjahr2/$1'; $route['api/v1/organisation/[O|o]rganisationseinheit/(:any)'] = 'api/v1/organisation/organisationseinheit2/$1'; $route['api/v1/ressource/[B|b]etriebsmittelperson/(:any)'] = 'api/v1/ressource/betriebsmittelperson2/$1'; -$route['api/v1/system/[S|s]prache/(:any)'] = 'api/v1/system/sprache2/$1'; \ No newline at end of file +$route['api/v1/system/[S|s]prache/(:any)'] = 'api/v1/system/sprache2/$1'; diff --git a/application/controllers/MailJob.php b/application/controllers/MailJob.php deleted file mode 100644 index 2f8b5b92d..000000000 --- a/application/controllers/MailJob.php +++ /dev/null @@ -1,35 +0,0 @@ -load->library('MessageLib'); - } - - public function sendMessages($numberToSent = null, $numberPerTimeRange = null, $email_time_range = null, $email_from_system = null) - { - $this->messagelib->sendAll($numberToSent, $numberPerTimeRange, $email_time_range, $email_from_system); - } -} diff --git a/application/controllers/Redirect.php b/application/controllers/Redirect.php deleted file mode 100644 index 8a24c590d..000000000 --- a/application/controllers/Redirect.php +++ /dev/null @@ -1,86 +0,0 @@ -load->model('system/MessageToken_model', 'MessageTokenModel'); - } - - /** - * redirectByToken - * - * - Loads the message using a token - * - Loads the root of the organisation unit tree using the oe_kurzbz present in the message - * - Redirect to the aufnahme related to the found organisation unit - */ - public function redirectByToken($token) - { - $msg = $this->MessageTokenModel->getMessageByToken($token); - if ($msg->error) - { - show_error($msg->retval); - } - - $oe_kurzbz = $msg->retval[0]->oe_kurzbz; - - if ($oe_kurzbz != null && $oe_kurzbz != '') - { - $organisationRoot = null; - - $getOERoot = $this->MessageTokenModel->getOERoot($oe_kurzbz); - if (isSuccess($getOERoot)) // If no errors occurred - { - $organisationRoot = $getOERoot->retval; - } - else - { - show_error('No organisation unit present in the message'); - } - - $addonAufnahmeUrls = $this->config->item('message_redirect_url'); - if(!isset($addonAufnahmeUrls[$organisationRoot])) - $organisationRoot = 'fallback'; - - if (isset($token) - && hasData($msg) - && is_array($addonAufnahmeUrls) - && $organisationRoot != null - && isset($addonAufnahmeUrls[$organisationRoot])) - { - redirect($addonAufnahmeUrls[$organisationRoot] . '?token=' . $token); - } - } - else - { - $addonAufnahmeUrls = $this->config->item('message_redirect_url'); - if (isset($token) - && hasData($msg) - && is_array($addonAufnahmeUrls) - && isset($addonAufnahmeUrls['fallback'])) - { - redirect($addonAufnahmeUrls['fallback'] . '?token=' . $token); - } - } - } -} diff --git a/application/controllers/ViewMessage.php b/application/controllers/ViewMessage.php deleted file mode 100644 index 3c22c8977..000000000 --- a/application/controllers/ViewMessage.php +++ /dev/null @@ -1,152 +0,0 @@ -config->load('message'); - - // Load model MessageToken_model, not calling the authentication system - $this->load->model('system/MessageToken_model', 'MessageTokenModel'); - $this->load->model('CL/Messages_model', 'CLMessagesModel'); - } - - /** - * Using the MessageTokenModel instead of MessageLib to allow - * viewing the message without prompting the login - */ - public function toHTML($token) - { - $msg = $this->MessageTokenModel->getMessageByToken($token); - - if ($msg->error) - { - show_error(getData($msg)); - } - - if (is_array(getData($msg)) && count(getData($msg)) > 0) - { - $setReadMessageStatusByToken = $this->MessageTokenModel->setReadMessageStatusByToken($token); - - if (isError($setReadMessageStatusByToken)) - { - show_error($msg->$setReadMessageStatusByToken); - } - - $sender_id = getData($msg)[0]->sender_id; - $receiver_id = getData($msg)[0]->receiver_id; - $sender = $this->MessageTokenModel->getSenderData($sender_id); - - // To decide how to change the redirection - $isEmployee = $this->MessageTokenModel->isEmployee($receiver_id); - if (!is_bool($isEmployee) && isError($isEmployee)) - { - show_error($isEmployee); - } - - if($this->config->item('redirect_view_message_url') != '') - $href = $this->config->item('message_server').$this->config->item('redirect_view_message_url').$token; - else - $href = ''; - - $data = array ( - 'sender_id' => $sender_id, - 'sender' => getData($sender)[0], - 'message' => getData($msg)[0], - 'isEmployee' => $isEmployee, - 'href' => $href - ); - - $this->load->view('system/messages/messageHTML.php', $data); - } - } - - /** - * write the reply - */ - public function writeReply() - { - $token = $this->input->get('token'); - - if (isEmptyString($token)) - { - show_error('No token supplied'); - } - - $msg = null; - - // Get message data if possible - $msg = $this->MessageTokenModel->getMessageByToken($token); - if (!hasData($msg)) - { - show_error('No message found'); - } - - $msg = getData($msg)[0]; - - // Get variables - $receiverData = $this->MessageTokenModel->getPersonData($msg->sender_id); - if (!hasData($receiverData)) - { - show_error('No sender found'); - } - - $data = array ( - 'receivers' => getData($receiverData), - 'message' => $msg, - 'token' => $token - ); - - $this->load->view('system/messages/messageWriteReply', $data); - } - - /** - * Send a reply - */ - public function sendReply() - { - $subject = $this->input->post('subject'); - $body = $this->input->post('body'); - $persons = $this->input->post('persons'); - $relationmessage_id = $this->input->post('relationmessage_id'); - $token = $this->input->post('token'); - - if (!isset($relationmessage_id) || $relationmessage_id == '' || !isset($token) || $token == '') - { - show_error('Error while sending reply'); - } - - $sendReply = $this->CLMessagesModel->sendReply($subject, $body, $persons, $relationmessage_id, $token); - if (isError($sendReply)) - { - show_error(getData($sendReply)); - } - - $this->load->view('system/messages/messageReplySent'); - } -} diff --git a/application/controllers/api/v1/CheckUserAuth.php b/application/controllers/api/v1/CheckUserAuth.php index 4d6522fe2..ee751e886 100644 --- a/application/controllers/api/v1/CheckUserAuth.php +++ b/application/controllers/api/v1/CheckUserAuth.php @@ -2,7 +2,7 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); -class CheckUserAuth extends REST_Controller +class CheckUserAuth extends RESTFul_Controller { /** * Course API constructor. diff --git a/application/controllers/api/v1/Test.php b/application/controllers/api/v1/Test.php index 41feb1a16..c9918f52b 100644 --- a/application/controllers/api/v1/Test.php +++ b/application/controllers/api/v1/Test.php @@ -5,7 +5,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); /** * Testing class for REST calls and authentication */ -class Test extends REST_Controller +class Test extends RESTFul_Controller { public function __construct() { diff --git a/application/controllers/api/v1/person/Benutzer.php b/application/controllers/api/v1/person/Benutzer.php index 23fcdadac..f1ea4f149 100644 --- a/application/controllers/api/v1/person/Benutzer.php +++ b/application/controllers/api/v1/person/Benutzer.php @@ -37,7 +37,7 @@ class Benutzer extends APIv1_Controller if (isset($uid)) { - $result = $this->BenutzerModel->load($uid); + $result = $this->BenutzerModel->load(array('uid' => $uid)); $this->response($result, REST_Controller::HTTP_OK); } diff --git a/application/controllers/api/v1/person/Person.php b/application/controllers/api/v1/person/Person.php index c8c95ae06..ca8a66bea 100644 --- a/application/controllers/api/v1/person/Person.php +++ b/application/controllers/api/v1/person/Person.php @@ -1,267 +1,267 @@ - 'basis/person:rw', 'CheckBewerbung' => 'basis/person:r')); - // Load model PersonModel - $this->load->model('person/person_model', 'PersonModel'); - } - - /** - * @return void - */ - public function getPerson() - { - $person_id = $this->get('person_id'); - $code = $this->get('code'); - $email = $this->get('email'); - - if (isset($code) || isset($email) || isset($person_id)) - { - if (isset($code) && isset($email)) - { - $result = $this->PersonModel->getPersonKontaktByZugangscode($code, $email); - } - else - { - $parametersArray = array(); - - if (isset($code)) - { - $parametersArray['zugangscode'] = $code; - } - else - { - $parametersArray['person_id'] = $person_id; - } - - $result = $this->PersonModel->loadWhere($parametersArray); - } - - $this->response($result, REST_Controller::HTTP_OK); - } - else - { - $this->response(); - } - } - - /** - * @return void - */ - public function getCheckBewerbung() - { - $email = $this->get('email'); - $studiensemester_kurzbz = $this->get('studiensemester_kurzbz'); - - if (isset($email)) - { - $result = $this->PersonModel->checkBewerbung($email, $studiensemester_kurzbz); - - $this->response($result, REST_Controller::HTTP_OK); - } - else - { - $this->response(); - } - } - - /** - * @return void - */ - public function postPerson() - { - $person = $this->post(); - $validation = $this->_validate($person); - - if (isSuccess($validation)) - { - if(isset($person['person_id']) && !(is_null($person['person_id'])) && ($person['person_id'] != '')) - { - $result = $this->PersonModel->updatePerson($person); - } - else - { - $result = $this->PersonModel->insert($person); - } - - $this->response($result, REST_Controller::HTTP_OK); - } - else - { - $this->response($validation, REST_Controller::HTTP_OK); - } - } - - private function _validate($person) - { - // If $person is consistent - if (!isset($person) || (isset($person) && !is_array($person))) - { - return error('Any parameters posted'); - } - - // Trim all the values - foreach($person as $key => $value) - { - if (gettype($value) == 'string') - { - $person[$key] = trim($value); - } - } - - if (isset($person['sprache']) && mb_strlen($person['sprache']) > 16) - { - return error('Sprache darf nicht laenger als 16 Zeichen sein'); - } - if (isset($person['anrede']) && mb_strlen($person['anrede']) > 16) - { - return error('Anrede darf nicht laenger als 16 Zeichen sein'); - } - if (isset($person['titelpost']) && mb_strlen($person['titelpost']) > 32) - { - return error('Titelpost darf nicht laenger als 32 Zeichen sein'); - } - if (isset($person['titelpre']) && mb_strlen($person['titelpre']) > 64) - { - return error('Titelpre darf nicht laenger als 64 Zeichen sein'); - } - if (isset($person['nachname']) && mb_strlen($person['nachname']) > 64) - { - return error('Nachname darf nicht laenger als 64 Zeichen sein'); - } - if (isset($person['nachname']) && ($person['nachname'] == '' || is_null($person['nachname']))) - { - return error('Nachname muss eingegeben werden'); - } - if (isset($person['vorname']) && mb_strlen($person['vorname']) > 32) - { - return error('Vorname darf nicht laenger als 32 Zeichen sein'); - } - if (isset($person['vornamen']) && mb_strlen($person['vornamen']) > 128) - { - return error('Vornamen darf nicht laenger als 128 Zeichen sein'); - } - if (isset($person['gebort']) && mb_strlen($person['gebort']) > 128) - { - return error('Geburtsort darf nicht laenger als 128 Zeichen sein'); - } - if (isset($person['homepage']) && mb_strlen($person['homepage']) > 256) - { - return error('Homepage darf nicht laenger als 256 Zeichen sein'); - } - if (isset($person['matr_nr']) && mb_strlen($person['matr_nr']) > 32) - { - return error('Matrikelnummer darf nicht laenger als 32 Zeichen sein'); - } - if (isset($person['ersatzkennzeichen']) && mb_strlen($person['ersatzkennzeichen']) > 10) - { - return error('Ersatzkennzeichen darf nicht laenger als 10 Zeichen sein'); - } - if (isset($person['familienstand']) && mb_strlen($person['familienstand']) > 1) - { - return error('Familienstand ist ungueltig'); - } - if (isset($person['anzahlkinder']) && $person['anzahlkinder'] != '' && !is_numeric($person['anzahlkinder'])) - { - return error('Anzahl der Kinder ist ungueltig'); - } - if (!isset($person['aktiv']) || (isset($person['aktiv']) && $person['aktiv'] !== true && $person['aktiv'] !== false)) - { - return error('Aktiv ist ungueltig'); - } - if (!isset($person['person_id']) && isset($person['insertvon']) && mb_strlen($person['insertvon']) > 32) - { - return error('Insertvon darf nicht laenger als 32 Zeichen sein'); - } - if (isset($person['updatevon']) && mb_strlen($person['updatevon']) > 32) - { - return error('Updatevon darf nicht laenger als 32 Zeichen sein'); - } - if (isset($person['geburtsnation']) && mb_strlen($person['geburtsnation']) > 3) - { - return error('Geburtsnation darf nicht laenger als 3 Zeichen sein'); - } - if (isset($person['staatsbuergerschaft']) && mb_strlen($person['staatsbuergerschaft']) > 3) - { - return error('Staatsbuergerschaft darf nicht laenger als 3 Zeichen sein'); - } - if (!isset($person['geschlecht']) || (isset($person['geschlecht']) && mb_strlen($person['geschlecht']) > 1)) - { - return error('Geschlecht darf nicht laenger als 1 Zeichen sein'); - } - if (isset($person['geschlecht']) && $person['geschlecht'] != 'm' && $person['geschlecht'] != 'w' && $person['geschlecht'] != 'u') - { - return error('Geschlecht muss w, m oder u sein!'); - } - - if (isset($person['svnr'])) - { - if ($person['svnr'] != '' && mb_strlen($person['svnr']) != 16 - && mb_strlen($person['svnr']) != 12 && mb_strlen($person['svnr']) != 10) - { - return error('SVNR muss 10, 12 oder 16 Zeichen lang sein'); - } - if (mb_strlen($person['svnr']) == 10 || mb_strlen($person['svnr']) == 12) - { - //SVNR mit Pruefziffer pruefen - //Die 4. Stelle in der SVNR ist die Pruefziffer - //(Summe von (gewichtung[i]*svnr[i])) modulo 11 ergibt diese Pruefziffer - //Falls nicht, ist die SVNR ungueltig - $gewichtung = array(3, 7, 9, 0, 5, 8, 4, 2, 1, 6); - $erg = 0; - $tmpSvnr = substr($person['svnr'], 0, 10); - //Quersumme bilden - for ($i = 0; $i < 10; $i++) - { - $erg += $gewichtung[$i] * $tmpSvnr{$i}; - } - - if ($tmpSvnr{3} != ($erg % 11)) //Vergleichen der Pruefziffer mit Quersumme Modulo 11 - { - return error('SVNR ist ungueltig'); - } - - if (mb_strlen($person['svnr']) == 12) - { - $last = substr($person['svnr'], 10, 12); - if ($last{0} != 'v' || !is_numeric($last{1})) - { - return error('SVNR ist ungueltig'); - } - } - } - - //Pruefen ob das Geburtsdatum mit der SVNR uebereinstimmt. - if (isset($person['gebdatum']) && $person['svnr'] != '' && $person['gebdatum'] != '') - { - if (!mb_ereg('([0-9]{1,2}).([0-9]{1,2}).([0-9]{4})', $person['gebdatum']) - && !mb_ereg('([0-9]{4})-([0-9]{2})-([0-9]{2})', $person['gebdatum'])) - { - return error('Format des Geburtsdatums ist ungueltig'); - } - } - } - - return success('Input data are valid'); - } -} + 'basis/person:rw', 'CheckBewerbung' => 'basis/person:r')); + // Load model PersonModel + $this->load->model('person/person_model', 'PersonModel'); + } + + /** + * @return void + */ + public function getPerson() + { + $person_id = $this->get('person_id'); + $code = $this->get('code'); + $email = $this->get('email'); + + if (isset($code) || isset($email) || isset($person_id)) + { + if (isset($code) && isset($email)) + { + $result = $this->PersonModel->getPersonKontaktByZugangscode($code, $email); + } + else + { + $parametersArray = array(); + + if (isset($code)) + { + $parametersArray['zugangscode'] = $code; + } + else + { + $parametersArray['person_id'] = $person_id; + } + + $result = $this->PersonModel->loadWhere($parametersArray); + } + + $this->response($result, REST_Controller::HTTP_OK); + } + else + { + $this->response(); + } + } + + /** + * @return void + */ + public function getCheckBewerbung() + { + $email = $this->get('email'); + $studiensemester_kurzbz = $this->get('studiensemester_kurzbz'); + + if (isset($email)) + { + $result = $this->PersonModel->checkBewerbung($email, $studiensemester_kurzbz); + + $this->response($result, REST_Controller::HTTP_OK); + } + else + { + $this->response(); + } + } + + /** + * @return void + */ + public function postPerson() + { + $person = $this->post(); + $validation = $this->_validate($person); + + if (isSuccess($validation)) + { + if(isset($person['person_id']) && !(is_null($person['person_id'])) && ($person['person_id'] != '')) + { + $result = $this->PersonModel->updatePerson($person); + } + else + { + $result = $this->PersonModel->insert($person); + } + + $this->response($result, REST_Controller::HTTP_OK); + } + else + { + $this->response($validation, REST_Controller::HTTP_OK); + } + } + + private function _validate($person) + { + // If $person is consistent + if (!isset($person) || (isset($person) && !is_array($person))) + { + return error('Any parameters posted'); + } + + // Trim all the values + foreach($person as $key => $value) + { + if (gettype($value) == 'string') + { + $person[$key] = trim($value); + } + } + + if (isset($person['sprache']) && mb_strlen($person['sprache']) > 16) + { + return error('Sprache darf nicht laenger als 16 Zeichen sein'); + } + if (isset($person['anrede']) && mb_strlen($person['anrede']) > 16) + { + return error('Anrede darf nicht laenger als 16 Zeichen sein'); + } + if (isset($person['titelpost']) && mb_strlen($person['titelpost']) > 32) + { + return error('Titelpost darf nicht laenger als 32 Zeichen sein'); + } + if (isset($person['titelpre']) && mb_strlen($person['titelpre']) > 64) + { + return error('Titelpre darf nicht laenger als 64 Zeichen sein'); + } + if (isset($person['nachname']) && mb_strlen($person['nachname']) > 64) + { + return error('Nachname darf nicht laenger als 64 Zeichen sein'); + } + if (isset($person['nachname']) && ($person['nachname'] == '' || is_null($person['nachname']))) + { + return error('Nachname muss eingegeben werden'); + } + if (isset($person['vorname']) && mb_strlen($person['vorname']) > 32) + { + return error('Vorname darf nicht laenger als 32 Zeichen sein'); + } + if (isset($person['vornamen']) && mb_strlen($person['vornamen']) > 128) + { + return error('Vornamen darf nicht laenger als 128 Zeichen sein'); + } + if (isset($person['gebort']) && mb_strlen($person['gebort']) > 128) + { + return error('Geburtsort darf nicht laenger als 128 Zeichen sein'); + } + if (isset($person['homepage']) && mb_strlen($person['homepage']) > 256) + { + return error('Homepage darf nicht laenger als 256 Zeichen sein'); + } + if (isset($person['matr_nr']) && mb_strlen($person['matr_nr']) > 32) + { + return error('Matrikelnummer darf nicht laenger als 32 Zeichen sein'); + } + if (isset($person['ersatzkennzeichen']) && mb_strlen($person['ersatzkennzeichen']) > 10) + { + return error('Ersatzkennzeichen darf nicht laenger als 10 Zeichen sein'); + } + if (isset($person['familienstand']) && mb_strlen($person['familienstand']) > 1) + { + return error('Familienstand ist ungueltig'); + } + if (isset($person['anzahlkinder']) && $person['anzahlkinder'] != '' && !is_numeric($person['anzahlkinder'])) + { + return error('Anzahl der Kinder ist ungueltig'); + } + if (!isset($person['aktiv']) || (isset($person['aktiv']) && $person['aktiv'] !== true && $person['aktiv'] !== false)) + { + return error('Aktiv ist ungueltig'); + } + if (!isset($person['person_id']) && isset($person['insertvon']) && mb_strlen($person['insertvon']) > 32) + { + return error('Insertvon darf nicht laenger als 32 Zeichen sein'); + } + if (isset($person['updatevon']) && mb_strlen($person['updatevon']) > 32) + { + return error('Updatevon darf nicht laenger als 32 Zeichen sein'); + } + if (isset($person['geburtsnation']) && mb_strlen($person['geburtsnation']) > 3) + { + return error('Geburtsnation darf nicht laenger als 3 Zeichen sein'); + } + if (isset($person['staatsbuergerschaft']) && mb_strlen($person['staatsbuergerschaft']) > 3) + { + return error('Staatsbuergerschaft darf nicht laenger als 3 Zeichen sein'); + } + if (!isset($person['geschlecht']) || (isset($person['geschlecht']) && mb_strlen($person['geschlecht']) > 1)) + { + return error('Geschlecht darf nicht laenger als 1 Zeichen sein'); + } + if (isset($person['geschlecht']) && $person['geschlecht'] != 'm' && $person['geschlecht'] != 'w' && $person['geschlecht'] != 'u') + { + return error('Geschlecht muss w, m oder u sein!'); + } + + if (isset($person['svnr'])) + { + if ($person['svnr'] != '' && mb_strlen($person['svnr']) != 16 + && mb_strlen($person['svnr']) != 12 && mb_strlen($person['svnr']) != 10) + { + return error('SVNR muss 10, 12 oder 16 Zeichen lang sein'); + } + if (mb_strlen($person['svnr']) == 10 || mb_strlen($person['svnr']) == 12) + { + //SVNR mit Pruefziffer pruefen + //Die 4. Stelle in der SVNR ist die Pruefziffer + //(Summe von (gewichtung[i]*svnr[i])) modulo 11 ergibt diese Pruefziffer + //Falls nicht, ist die SVNR ungueltig + $gewichtung = array(3, 7, 9, 0, 5, 8, 4, 2, 1, 6); + $erg = 0; + $tmpSvnr = substr($person['svnr'], 0, 10); + //Quersumme bilden + for ($i = 0; $i < 10; $i++) + { + $erg += $gewichtung[$i] * $tmpSvnr{$i}; + } + + if ($tmpSvnr{3} != ($erg % 11)) //Vergleichen der Pruefziffer mit Quersumme Modulo 11 + { + return error('SVNR ist ungueltig'); + } + + if (mb_strlen($person['svnr']) == 12) + { + $last = substr($person['svnr'], 10, 12); + if ($last{0} != 'v' || !is_numeric($last{1})) + { + return error('SVNR ist ungueltig'); + } + } + } + + //Pruefen ob das Geburtsdatum mit der SVNR uebereinstimmt. + if (isset($person['gebdatum']) && $person['svnr'] != '' && $person['gebdatum'] != '') + { + if (!mb_ereg('([0-9]{1,2}).([0-9]{1,2}).([0-9]{4})', $person['gebdatum']) + && !mb_ereg('([0-9]{4})-([0-9]{2})-([0-9]{2})', $person['gebdatum'])) + { + return error('Format des Geburtsdatums ist ungueltig'); + } + } + } + + return success('Input data are valid'); + } +} diff --git a/application/controllers/api/v1/system/CallerLibrary.php b/application/controllers/api/v1/system/CallerLibrary.php deleted file mode 100644 index 594786384..000000000 --- a/application/controllers/api/v1/system/CallerLibrary.php +++ /dev/null @@ -1,77 +0,0 @@ - 'admin:rw')); - - // Loads the CallerLib - $this->load->library('CallerLib'); - } - - /** - * Manages a HTTP get call - */ - public function getCall() - { - // Start me up! - $result = $this->callerlib->callLibrary($this->get()); - - // Print the result - $this->response($result, REST_Controller::HTTP_OK); - } - - /** - * @return void - */ - public function postCall() - { - // Start me up! - $result = $this->callerlib->callLibrary($this->post()); - - // Print the result - $this->response($result, REST_Controller::HTTP_OK); - } - - /** - * @return void - */ - public function putCall() - { - // Start me up! - $result = $this->callerlib->callLibrary($this->put()); - - // Print the result - $this->response($result, REST_Controller::HTTP_OK); - } - - /** - * @return void - */ - public function deleteCall() - { - // Start me up! - $result = $this->callerlib->callLibrary($this->delete()); - - // Print the result - $this->response($result, REST_Controller::HTTP_OK); - } -} diff --git a/application/controllers/api/v1/system/CallerModel.php b/application/controllers/api/v1/system/CallerModel.php deleted file mode 100644 index 68296aff8..000000000 --- a/application/controllers/api/v1/system/CallerModel.php +++ /dev/null @@ -1,77 +0,0 @@ - 'admin:rw')); - - // Loads the CallerLib - $this->load->library('CallerLib'); - } - - /** - * Manages a HTTP get call - */ - public function getCall() - { - // Start me up! - $result = $this->callerlib->callModel($this->get()); - - // Print the result - $this->response($result, REST_Controller::HTTP_OK); - } - - /** - * @return void - */ - public function postCall() - { - // Start me up! - $result = $this->callerlib->callModel($this->post()); - - // Print the result - $this->response($result, REST_Controller::HTTP_OK); - } - - /** - * @return void - */ - public function putCall() - { - // Start me up! - $result = $this->callerlib->callModel($this->put()); - - // Print the result - $this->response($result, REST_Controller::HTTP_OK); - } - - /** - * @return void - */ - public function deleteCall() - { - // Start me up! - $result = $this->callerlib->callModel($this->delete()); - - // Print the result - $this->response($result, REST_Controller::HTTP_OK); - } -} diff --git a/application/controllers/api/v1/system/Message.php b/application/controllers/api/v1/system/Message.php index be87526ed..1825b7db9 100644 --- a/application/controllers/api/v1/system/Message.php +++ b/application/controllers/api/v1/system/Message.php @@ -144,26 +144,26 @@ class Message extends APIv1_Controller */ public function postMessage() { - $validation = $this->_validatePostMessage($this->post()); + $postMessage = $this->_validatePostMessage($this->post()); - if (isSuccess($validation)) + if (isSuccess($postMessage)) { - $result = $this->messagelib->sendMessage( - isset($this->post()['person_id']) ? $this->post()['person_id'] : null, - isset($this->post()['receiver_id']) ? $this->post()['receiver_id'] : null, - $this->post()['subject'], - $this->post()['body'], - PRIORITY_NORMAL, - isset($this->post()['relationmessage_id']) ? $this->post()['relationmessage_id'] : null, - isset($this->post()['oe_kurzbz']) ? $this->post()['oe_kurzbz'] : null, // Sender organisation unit - isset($this->post()['multiPartMime']) ? $this->post()['multiPartMime'] : true + $result = $this->messagelib->sendMessageUser( + $this->post()['receiver_id'], // receiverPersonId + $this->post()['subject'], // subject + $this->post()['body'], // body + $this->post()['person_id'] ? $this->post()['person_id'] : null, // sender_id + isset($this->post()['oe_kurzbz']) ? $this->post()['oe_kurzbz'] : null, // senderOU + isset($this->post()['relationmessage_id']) ? $this->post()['relationmessage_id'] : null, // relationmessage_id + MSG_PRIORITY_NORMAL, // priority + isset($this->post()['multiPartMime']) ? $this->post()['multiPartMime'] : true // multiPartMime ); $this->response($result, REST_Controller::HTTP_OK); } else { - $this->response($validation, REST_Controller::HTTP_OK); + $this->response($postMessage, REST_Controller::HTTP_OK); } } @@ -172,26 +172,27 @@ class Message extends APIv1_Controller */ public function postMessageVorlage() { - $validation = $this->_validatePostMessageVorlage($this->post()); + $postMessage = $this->_validatePostMessageVorlage($this->post()); - if (isSuccess($validation)) + if (isSuccess($postMessage)) { - $result = $this->messagelib->sendMessageVorlage( - isset($this->post()['sender_id']) ? $this->post()['sender_id'] : null, - isset($this->post()['receiver_id']) ? $this->post()['receiver_id'] : null, - $this->post()['vorlage_kurzbz'], - isset($this->post()['oe_kurzbz']) ? $this->post()['oe_kurzbz'] : null, // Sender organisation unit - $this->post()['data'], - isset($this->post()['relationmessage_id']) ? $this->post()['relationmessage_id'] : null, - isset($this->post()['orgform_kurzbz']) ? $this->post()['orgform_kurzbz'] : null, - isset($this->post()['multiPartMime']) ? $this->post()['multiPartMime'] : true + $result = $this->messagelib->sendMessageUserTemplate( + isset($this->post()['receiver_id']) ? $this->post()['receiver_id'] : null, // receiversPersonId + $this->post()['vorlage_kurzbz'], // vorlage + $this->post()['data'], // parseData + isset($this->post()['orgform_kurzbz']) ? $this->post()['orgform_kurzbz'] : null, // orgform + isset($this->post()['sender_id']) ? $this->post()['sender_id'] : null, // sender_id + isset($this->post()['oe_kurzbz']) ? $this->post()['oe_kurzbz'] : null, // senderOU + isset($this->post()['relationmessage_id']) ? $this->post()['relationmessage_id'] : null, // relationmessage_id + MSG_PRIORITY_NORMAL, // priority + isset($this->post()['multiPartMime']) ? $this->post()['multiPartMime'] : true // multiPartMime ); $this->response($result, REST_Controller::HTTP_OK); } else { - $this->response($validation, REST_Controller::HTTP_OK); + $this->response($postMessage, REST_Controller::HTTP_OK); } } @@ -220,26 +221,26 @@ class Message extends APIv1_Controller /** * _validatePostMessage */ - private function _validatePostMessage($message = null) + private function _validatePostMessage($post = null) { - if (!isset($message)) + if (!isset($post)) { return error('Parameter is null'); } - if (!isset($message['subject'])) + if (!isset($post['subject'])) { return error('subject is not set'); } - if( !isset($message['body'])) + if (!isset($post['body'])) { return error('body is not set'); } - if (!isset($message['receiver_id']) && !isset($message['oe_kurzbz'])) + if (!isset($post['receiver_id'])) { - return error('If a receiver_id is not given a oe_kurzbz must be specified'); + return error('receiver_id is not set'); } - return success('Input data are valid'); + return success(); } /** diff --git a/application/controllers/crm/Statusgrund.php b/application/controllers/crm/Statusgrund.php index 472270ef3..344ac06dc 100644 --- a/application/controllers/crm/Statusgrund.php +++ b/application/controllers/crm/Statusgrund.php @@ -35,7 +35,7 @@ class Statusgrund extends Auth_Controller $status = $this->StatusModel->load(); if ($status->error) { - show_error($status->retval); + show_error(getError($status)); } $data = array ( @@ -50,7 +50,7 @@ class Statusgrund extends Auth_Controller $statusGrund = $this->StatusgrundModel->loadWhere(array("status_kurzbz" => $status_kurzbz)); if ($statusGrund->error) { - show_error($statusGrund->retval); + show_error(getError($statusGrund)); } $data = array ( @@ -66,13 +66,13 @@ class Statusgrund extends Auth_Controller $statusGrund = $this->StatusgrundModel->load($statusgrund_id); if ($statusGrund->error) { - show_error($statusGrund->retval); + show_error(getError($statusGrund)); } $sprache = $this->SpracheModel->loadWhere(array('content' => true)); if ($sprache->error) { - show_error($sprache->retval); + show_error(getError($sprache)); } $data = array ( @@ -89,13 +89,13 @@ class Statusgrund extends Auth_Controller $status = $this->StatusModel->load($status_id); if ($status->error) { - show_error($status->retval); + show_error(getError($status)); } $sprache = $this->SpracheModel->loadWhere(array('content' => true)); if ($sprache->error) { - show_error($sprache->retval); + show_error(getError($sprache)); } $data = array ( @@ -112,7 +112,7 @@ class Statusgrund extends Auth_Controller $sprache = $this->SpracheModel->loadWhere(array('content' => true)); if ($sprache->error) { - show_error($sprache->retval); + show_error(getError($sprache)); } $data = array ( @@ -184,7 +184,7 @@ class Statusgrund extends Auth_Controller if ($statusgrund->error) { - show_error($statusgrund->retval); + show_error(getError($statusgrund)); } redirect("/crm/Statusgrund/editGrund/" . $statusgrund_id . "/" . true); @@ -252,7 +252,7 @@ class Statusgrund extends Auth_Controller if ($statusgrund->error) { - show_error($statusgrund->retval); + show_error(getError($statusgrund)); } redirect("/crm/Statusgrund/editGrund/" . $statusgrund->retval . "/" . true); @@ -297,7 +297,7 @@ class Statusgrund extends Auth_Controller if ($status->error) { - show_error($status->retval); + show_error(getError($status)); } redirect("/crm/Statusgrund/editStatus/" . $status_kurzbz . "/" . true); diff --git a/application/controllers/jobs/AmpelMail.php b/application/controllers/jobs/AmpelMail.php index e29cac8fd..67acd76d0 100644 --- a/application/controllers/jobs/AmpelMail.php +++ b/application/controllers/jobs/AmpelMail.php @@ -121,13 +121,13 @@ class AmpelMail extends CLI_Controller } elseif (isError($result_ampel_user)) { - show_error($result_ampel_user->error); + show_error(getError($result_ampel_user)); } } } elseif (isError($result_active_ampeln)) { - show_error($result_active_ampeln->error); + show_error(getError($result_active_ampeln)); } // Send mails for new ampeln merged by user diff --git a/application/controllers/jobs/LehrauftragJob.php b/application/controllers/jobs/LehrauftragJob.php new file mode 100644 index 000000000..2f6b928c7 --- /dev/null +++ b/application/controllers/jobs/LehrauftragJob.php @@ -0,0 +1,536 @@ +load->model('accounting/Vertrag_model', 'VertragModel'); + $this->load->model('accounting/Vertragvertragsstatus_model', 'VertragvertragsstatusModel'); + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + $this->load->model('system/Benutzerrolle_model', 'BenutzerrolleModel'); + + // Load libraries + $this->load->library('PermissionLib'); + + // Load helpers + $this->load->helper('hlp_sancho_helper'); + } + + /** + * This daily job sends information about all lehr-/projektauftraege ordered (and not approved) the day bofore. + * Receivers: Department-/Kompetenzfeldleiter + **/ + public function mailLehrauftraegeToApprove() + { + // Get vertrag_ids of lehrauftraege that had been ordered and had NOT been approved or cancelled YESTERDAY + $this->VertragvertragsstatusModel->addSelect('vertrag_id'); + $result = $this->VertragvertragsstatusModel->getOrdered_fromDate('YESTERDAY'); + + // Get lehrveranstaltung_ids and studiensemester of the lehr-/or projektauftrag contracts + $lehreinheit_data_arr = array(); + if ($vertrag_arr = getData($result)) + { + foreach ($vertrag_arr as $vertrag) + { + $result = $this->VertragModel->getLehreinheitData($vertrag->vertrag_id, 'lehrveranstaltung_id, studiensemester_kurzbz'); + + if (hasData($result)) + { + $obj = new StdClass(); + $obj->lehrveranstaltung_id = $result->retval[0]->lehrveranstaltung_id; + $obj->studiensemester_kurzbz = $result->retval[0]->studiensemester_kurzbz; + $lehreinheit_data_arr []= $obj; + } + } + } + + /** + * Build the data array to be used in the email. Data array is clustered as follows: + * Array + * [studiensemester_kurzbz] // studiensemester of lehreinheit + * Array + * [oe_kurzbz] // oe of lehreinheits lehrveranstaltung + * [oe_bezeichnung] + * Array + * [stg_kz] // stg of lehreinheits lehrveranstaltung + * [stg_kurzbz] + * [stg_bezeichnung] + * [amount] // amount of new ordered lehrauftraege of that stg + */ + $data_arr = array(); + foreach ($lehreinheit_data_arr as $lehreinheit_data) + { + $result = $this->_getLVData($lehreinheit_data->lehrveranstaltung_id); + + if (hasData($result)) + { + // Search if studiensemester exists in data_arr + $ss_index = array_search($lehreinheit_data->studiensemester_kurzbz, array_column($data_arr, 'studiensemester_kurzbz')); + + // If studiensemester is new, add studienesemester, oe and stg + if ($ss_index === false) + { + $data = array( + 'studiensemester_kurzbz' => $lehreinheit_data->studiensemester_kurzbz + ); + + $data []= array( + 'oe_kurzbz' => $result->retval[0]->oe_kurzbz, + 'oe_bezeichnung' => $result->retval[0]->lv_oe_bezeichnung + ); + + // Add stg data to oe, start amount with 1 + $data[0][] = array( + 'stg_kz' => $result->retval[0]->studiengang_kz, + 'stg_kurzbz' => strtoupper($result->retval[0]->stg_typ. $result->retval[0]->stg_kurzbz), + 'stg_bezeichnung' => $result->retval[0]->lv_stg_bezeichnung, + 'amount' => 1 + ); + + // Push to final data_arr + $data_arr []= $data; + } + // Else if studiensemester exists + else + { + // Search if oe exists inside existing studiensemester of data_arr + $oe_index = array_search($result->retval[0]->oe_kurzbz, array_column($data_arr[$ss_index], 'oe_kurzbz')); + + // If oe is new, add oe and stg to studiensemester + if ($oe_index === false) + { + // Add oe data + $data_arr[$ss_index][] = array( + 'oe_kurzbz' => $result->retval[0]->oe_kurzbz, + 'oe_bezeichnung' => $result->retval[0]->lv_oe_bezeichnung, + + // Add stg data to oe, start amount with 1 + array( + 'stg_kz' => $result->retval[0]->studiengang_kz, + 'stg_kurzbz' => strtoupper($result->retval[0]->stg_typ. $result->retval[0]->stg_kurzbz), + 'stg_bezeichnung' => $result->retval[0]->lv_stg_bezeichnung, + 'amount' => 1 + ) + ); + } + // Else if oe exists + else + { + // Search if stg exists inside existing oe of data_arr + $stg_index = array_search($result->retval[0]->studiengang_kz, array_column($data_arr[$ss_index][$oe_index], 'stg_kz')); + + // If stg is new, add stg to oe, start amount with 1 + if ($stg_index === false) + { + $data_arr[$ss_index][$oe_index][] = array( + 'stg_kz' => $result->retval[0]->studiengang_kz, + 'stg_kurzbz' => strtoupper($result->retval[0]->stg_typ. $result->retval[0]->stg_kurzbz), + 'stg_bezeichnung' => $result->retval[0]->lv_stg_bezeichnung, + 'amount' => 1 + ); + } + // Else if stg exists + else + { + // Increase amount +1 + $data_arr[$ss_index][$oe_index][$stg_index]['amount']++; + } + } + } + } + } + + /** + * Cluster data by uid of entitled mail receivers. + * Returning array is clustered as follows: + * Array + * [uid] + * Array + * [studiensemester_kurzbz] // studiensemester of lehreinheit + * Array + * [oe_kurzbz] // oe of lehreinheits lehrveranstaltung + * [oe_bezeichnung] + * Array + * [stg_kz] // stg of lehreinheits lehrveranstaltung + * [stg_kurzbz] + * [stg_bezeichnung] + * [amount] // amount of new ordered lehrauftraege of that stg + */ + $data_arr = $this->_clusterData_byReceiver($data_arr); + + // Send email + if(!$this->_sendMail_toApprove($data_arr)) + { + $this->logInfo('SUCCEDED: Sending emails about yesterdays ordered lehrauftraege succeded.'); + } + else + { + $this->logError('Error when sending emails in job MailLehrauftragToApprove'); + } + } + + /** + * This daily job sends information about all lehr-/projektauftraege approved the day bofore. + * Receivers: lectors + **/ + public function mailLehrauftraegeToAccept() + { + // Get vertrag_id and uid of lehrauftraege that had been approved and had NOT been accepted or cancelled YESTERDAY + $this->VertragvertragsstatusModel->addSelect('vertrag_id, uid'); + $this->VertragvertragsstatusModel->addOrder('uid'); + $result = $this->VertragvertragsstatusModel->getApproved_fromDate('YESTERDAY'); + + /** + * Build the data array to be used in the email. Data array is clustered as follows: + * Array + * [uid] // lectors uid (mail receiver) + * [studiensemester] // studiensemester of the lehrauftraege (can be more, e.g. 'WS2019 and SS2020') + * [amount] // amount of new approved lehrauftraege + **/ + $data_arr = array(); + if ($vertrag_arr = getData($result)) + { + foreach ($vertrag_arr as $vertrag) + { + // Get studiensemester of the lehrauftrag + $this->VertragModel->addSelect('vertragsstunden_studiensemester_kurzbz'); + $result = $this->VertragModel->load($vertrag->vertrag_id); + if ($studiensemester = getData($result)) + { + $studiensemester = $studiensemester[0]->vertragsstunden_studiensemester_kurzbz; + } + + // Search if uid exists in data_arr + $uid_index = array_search($vertrag->uid, array_column($data_arr, 'uid')); + + // If uid is new, add uid, studiensemester and start amount with 1 + if ($uid_index === false) + { + $data = array(); + $data['uid'] = $vertrag->uid; + $data['studiensemester'] = $studiensemester; + $data['amount']= 1; + $data_arr []= $data; + } + // Else if uid exists + else + { + // If studiensemester is new, add to studiensemester-string + if (strpos($data_arr[$uid_index]['studiensemester'], $studiensemester) === false) + { + $data_arr[$uid_index]['studiensemester'] .= ' und '. $studiensemester; + } + + // Increase amount +1 + $data_arr[$uid_index]['amount']++; + } + } + } + + // Send email + if ($this->_sendMail_toAccept($data_arr)) + { + $this->logInfo('SUCCEDED: Sending emails about yesterdays approved lehrauftraege succeded.'); + } + else + { + $this->logError('Error when sending emails in job MailLehrauftragToAccept'); + } + } + + //****************************************************************************************************************** + // PRIVATE FUNCTIONS + //****************************************************************************************************************** + + /** + * Get data of given lehrveranstaltung. + * @param $lehrveranstaltung_id + * @return mixed + */ + private function _getLVData($lehrveranstaltung_id) + { + $this->LehrveranstaltungModel->addSelect(' + tbl_lehrveranstaltung.oe_kurzbz, + oe.bezeichnung AS "lv_oe_bezeichnung", + tbl_lehrveranstaltung.studiengang_kz, + stg.bezeichnung AS "lv_stg_bezeichnung", + stg.typ AS "stg_typ", + stg.kurzbz AS "stg_kurzbz" + '); + + $this->LehrveranstaltungModel->addJoin('lehre.tbl_studienplan_lehrveranstaltung stpllv', 'lehrveranstaltung_id'); + $this->LehrveranstaltungModel->addJoin('lehre.tbl_studienplan stpl', 'studienplan_id'); + $this->LehrveranstaltungModel->addJoin('lehre.tbl_studienordnung sto', 'studienordnung_id'); + $this->LehrveranstaltungModel->addJoin('public.tbl_studiengang stg', 'ON stg.studiengang_kz = tbl_lehrveranstaltung.studiengang_kz'); + $this->LehrveranstaltungModel->addJoin('public.tbl_organisationseinheit oe', 'ON oe.oe_kurzbz = tbl_lehrveranstaltung.oe_kurzbz'); + $this->LehrveranstaltungModel->addOrder('stpllv.insertamum', 'DESC'); + $this->LehrveranstaltungModel->addLimit(1); + + return $this->LehrveranstaltungModel->load($lehrveranstaltung_id); + } + + /** + * Send Sancho eMail about ordered Lehrauftraege. + * @param $data_arr + */ + private function _sendMail_toApprove($data_arr) + { + // Loop through 'container' of mail recipients + foreach($data_arr as $data) + { + // Set mail recipients (department assistance/leader) + $to = $data['uid']. '@'. DOMAIN; + $html_table = $this->_renderData_LehrauftraegeToApprove($data); + + // Prepare mail content + $content_data_arr = array( + 'table' => $html_table + ); + + sendSanchoMail( + 'LehrauftragNeueBestellungen', + $content_data_arr, + $to, + 'Bestellung neuer Lehraufträge', + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg' + ); + } + } + + /** + * Cluster the data array by entitled mail receiver. + * Returning array is clustered as follows: + * Array + * [uid] + * Array + * [studiensemester_kurzbz] // studiensemester of lehreinheit + * Array + * [oe_kurzbz] // oe of lehreinheits lehrveranstaltung + * [oe_bezeichnung] + * Array + * [stg_kz] // stg of lehreinheits lehrveranstaltung + * [stg_kurzbz] + * [stg_bezeichnung] + * [amount] // amount of new ordered lehrauftraege of that stg + * @param $data_arr + * @return array + * + */ + private function _clusterData_byReceiver($data_arr) + { + $mail_data_arr = array(); // final array with all data clustered by mail receiver + + // Loop through 'container' of studiensemester + foreach ($data_arr as $data) + { + $data_len = count($data) - 1; + + // Loop through 'container' of organisational units + for ($i = 0; $i < $data_len; $i++) + { + // Get all users entitled by organisational unit + $result = $this->BenutzerrolleModel->getBenutzerByBerechtigung(self::BERECHTIGUNG_LEHRAUFTRAG_ERTEILEN, $data[$i]['oe_kurzbz']); + + if ($berechtigung_arr = getData($result)) + { + // Loop through entitled users + foreach ($berechtigung_arr as $berechtigung) + { + // Search if UID exists inside mail_data_arr + $uid_index = array_search($berechtigung->uid, array_column($mail_data_arr, 'uid')); + + // If UID is new, add UID to final array + if ($uid_index === false) + { + // add UID with corresponding data + $mail_data_arr [] = array( + 'uid' => $berechtigung->uid, + array( + 'studiensemester_kurzbz' => $data['studiensemester_kurzbz'], + $data[$i] + ) + ); + } // Else if UID exists + else + { + // Search if studiensemester exists + $ss_index = array_search($data['studiensemester_kurzbz'], array_column($mail_data_arr, 'studiensemester_kurzbz')); + + // If studiensemester is new, add studiensemester to existing UID + if ($ss_index === false) + { + $mail_data_arr[$uid_index] []= array( + 'studiensemester_kurzbz' => $data['studiensemester_kurzbz'], + $data[$i] + ); + } + // Else if studiensemester exists + else + { + // Add corresponding data to existing studiensemester of UID + $mail_data_arr[$uid_index]['studiensemester_kurbz'][] = $data[$i]; + } + + } + } + } + } + } + + return $mail_data_arr; + } + + /** + * Render the data array for the mail template returing a HTML table. + * @param $data_arr Data to be used in HTML table + * @return string HTML table to be embedded in eMail + */ + private function _renderData_LehrauftraegeToApprove($data_arr) + { + $html = ''; + foreach ($data_arr as $studiensemester_container) + { + if (is_array($studiensemester_container)) // is_array 'trims' the outer associative key [uid] + { + if (isset($studiensemester_container['studiensemester_kurzbz'])) + { + $studiensemester = $studiensemester_container['studiensemester_kurzbz']; + + // Link to LehrauftragErteilen + $url = site_url(self::LEHRAUFTRAG_ERTEILEN_URI).'?studiensemester='. $studiensemester; + } + + // HTML table header + $html .= ' +
+ Studiensemester: '. $studiensemester. ' +

+ + + + + + + + + + ' + ; + + // HTML table body + foreach ($studiensemester_container as $oe_container) + { + if (is_array($oe_container)) // is_array 'trims' the outer associative key [studiensemester_kurzbz] + { + if (isset($oe_container['oe_bezeichnung'])) + { + $oe_bezeichnung = $oe_container['oe_bezeichnung']; + } + + foreach ($oe_container as $stg_data) + { + if (is_array($stg_data)) // is_array 'trims' the outer associative keys [oe_kurzbz] and [oe_bezeichnung] + { + $html .= ' + + + + + + + '; + } + } + } + } + + // HTML table body end and link + $html .= ' + +
LV-OrganisationseinheitStudiengangSTG-KurzbezeichnungAnzahl neu bestellter Lehraufträge
'. $oe_bezeichnung. ''. $stg_data['stg_bezeichnung']. ''. $stg_data['stg_kurzbz']. ''. $stg_data['amount']. '
+
+ '. anchor($url, 'Lehraufträge Übersicht '. $studiensemester). ' +

+ '; + } + } + + return $html; + } + + /** + * Send Sancho eMail about ordered Lehrauftraege. + * @param $data_arr + */ + private function _sendMail_toAccept($data_arr) + { + // Loop through 'container' of mail recipients + foreach($data_arr as $data) + { + // Set mail recipient (lector) + $to = $data['uid']. '@'. DOMAIN; + + // Link to LehrauftragAkzeptieren + $url = CIS_ROOT. 'cis/index.php?menu='. + CIS_ROOT. 'cis/menu.php?content_id=&content='. + CIS_ROOT. index_page(). self::LEHRAUFTRAG_AKZEPTIEREN_URI; + + // Get first name + $first_name = ''; + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $this->BenutzerModel->addSelect('vorname'); + $this->BenutzerModel->addJoin('public.tbl_person', 'person_id'); + $result = $this->BenutzerModel->loadWhere(array('uid' => $data['uid'])); + + if (hasData($result)) + { + $first_name = $result->retval[0]->vorname; + } + + // Prepare mail content + $content_data_arr = array( + 'vorname' => $first_name, + 'studiensemester' => $data['studiensemester'], + 'anzahl' => $data['amount'], + 'link' => anchor($url, 'Lehraufträge Übersicht') + ); + + sendSanchoMail( + 'LehrauftragNeueErteilte', + $content_data_arr, + $to, + 'Neu erteilte Lehraufträge zum Annehmen bereit' + ); + } + } +} diff --git a/application/controllers/jobs/MailJob.php b/application/controllers/jobs/MailJob.php new file mode 100644 index 000000000..f459d4d3e --- /dev/null +++ b/application/controllers/jobs/MailJob.php @@ -0,0 +1,47 @@ +load->library('MessageLib'); + } + + /** + * Send all the NOT sent notice emails for messaging system + * The parameters are all not mandatory, they could be used to overrides the configs for testing, debug or one shot purposes + */ + public function sendAllMessageEmailNotices($since = '1970-01-01', $numberToSent = null, $numberPerTimeRange = null, $emailTimeRange = null, $emailFromSystem = null) + { + $this->logInfo('Send all message email notices started'); + + // Send them all! + $sendAllEmailNotices = $this->messagelib->sendAllEmailNotices($since, $numberToSent, $numberPerTimeRange, $emailTimeRange, $emailFromSystem); + + if (isError($sendAllEmailNotices)) + { + $optionalParameters = new stdClass(); + $optionalParameters->$since = $since; + $optionalParameters->$numberToSent = $numberToSent; + $optionalParameters->$numberPerTimeRange = $numberPerTimeRange; + $optionalParameters->$emailTimeRange = $emailTimeRange; + $optionalParameters->$emailFromSystem = $emailFromSystem; + + $this->logError($sendAllEmailNotices->retval, $optionalParameters); + } + elseif (!hasData($sendAllEmailNotices)) + { + $this->logInfo('There were no unsent messages'); + } + + $this->logInfo('Send all message email notices ended'); + } +} diff --git a/application/controllers/jobs/Prestudentstatus.php b/application/controllers/jobs/Prestudentstatus.php index 27cafeb0e..a3b765f07 100644 --- a/application/controllers/jobs/Prestudentstatus.php +++ b/application/controllers/jobs/Prestudentstatus.php @@ -37,7 +37,8 @@ class Prestudentstatus extends CLI_Controller tbl_prestudent.studiengang_kz, tbl_prestudentstatus.studienplan_id, tbl_studienplan.orgform_kurzbz, - tbl_prestudent.person_id'); + tbl_prestudent.person_id, + tbl_studienplan.sprache'); $this->PrestudentstatusModel->addJoin('public.tbl_prestudent', 'prestudent_id'); $this->PrestudentstatusModel->addJoin('lehre.tbl_studienplan', 'studienplan_id','LEFT'); $this->PrestudentstatusModel->addJoin('lehre.tbl_studienordnung', 'studienordnung_id','LEFT'); @@ -64,7 +65,8 @@ class Prestudentstatus extends CLI_Controller $row_status->studiengang_kz, $row_status->studiensemester_kurzbz, $row_status->ausbildungssemester, - $row_status->orgform_kurzbz); + $row_status->orgform_kurzbz, + $row_status->sprache); if(isSuccess($studienplan) && count($studienplan->retval) == 1) { @@ -107,7 +109,7 @@ class Prestudentstatus extends CLI_Controller } else { - show_error($status->retval); + show_error(getError($status)); } echo "Corrected:".$sum_corrected."\n"; echo "Not Corrected:".$sum_notcorrected."\n"; diff --git a/application/controllers/jobs/ReihungstestJob.php b/application/controllers/jobs/ReihungstestJob.php index 2ef2d30f7..859b8f265 100644 --- a/application/controllers/jobs/ReihungstestJob.php +++ b/application/controllers/jobs/ReihungstestJob.php @@ -1,5 +1,4 @@ load->model('crm/Reihungstest_model', 'ReihungstestModel'); $this->load->model('crm/RtStudienplan_model', 'RtStudienplanModel'); + $this->load->model('crm/Konto_model', 'KontoModel'); + $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); $this->load->model('organisation/Studienplan_model', 'StudienplanModel'); @@ -36,7 +37,7 @@ class ReihungstestJob extends CLI_Controller } elseif (isError($result)) { - show_error($result->error); + show_error(getError($result)); } // Get free places @@ -49,7 +50,7 @@ class ReihungstestJob extends CLI_Controller } elseif (isError($result)) { - show_error($result->error); + show_error(getError($result)); } // Prepare data for mail template 'ReihungstestJob' @@ -66,13 +67,35 @@ class ReihungstestJob extends CLI_Controller } } - /** - * runZentraleReihungstestAnmeldefristAssistenzJob + /* + * Sends an email to all assistants of a placement test when an anmeldeschluss has been reached + * + * @param integer $degreeProgram. Kennzahl of Degree Program to check + * @param string $bcc. Optional. BCC-Mailadress to send the Mails to + * @param string $from. Optional. Sender-Mailadress shown to recipient */ - public function runZentraleReihungstestAnmeldefristAssistenzJob() + public function runZentraleReihungstestAnmeldefristAssistenzJob($degreeProgram, $bcc = null, $from = null) { + // Encode Params + if ($bcc != '') + { + // $bcc can be given as null-string, so check that too + if ($bcc == 'null') + { + $bcc = ''; + } + else + { + $bcc = urldecode($bcc); + } + } + if ($from != '') + { + $from = urldecode($from); + } + // Get placement tests where registration date was yesterday - $result = $this->ReihungstestModel->checkReachedRegistrationDate(11000); + $result = $this->ReihungstestModel->checkReachedRegistrationDate($degreeProgram); $reachedRegistration_rt_arr = array(); @@ -82,7 +105,7 @@ class ReihungstestJob extends CLI_Controller } elseif (isError($result)) { - show_error($result->error); + show_error(getError($result)); } $applicants_arr = array(); @@ -97,11 +120,12 @@ class ReihungstestJob extends CLI_Controller } elseif (isError($applicants)) { - show_error($applicants->error); + show_error(getError($applicants)); } // Get all Bachelor-Degree-Programs with Mailadress $bachelorStudiengeange = $this->StudiengangModel->loadStudiengaengeFromTyp('b'); + $bachelorStudiengeange_arr = array(); if (hasData($bachelorStudiengeange)) { @@ -109,7 +133,7 @@ class ReihungstestJob extends CLI_Controller } elseif (isError($bachelorStudiengeange)) { - show_error($bachelorStudiengeange->error); + show_error(getError($bachelorStudiengeange)); } // If a person ist an applicant of this degree-program send mail with application data @@ -117,29 +141,13 @@ class ReihungstestJob extends CLI_Controller foreach ($bachelorStudiengeange_arr as $bachelorStudiengang) { $studiengang_kuerzel = strtoupper($bachelorStudiengang->typ.$bachelorStudiengang->kurzbz); - $applicants_list = ''; $applicantCounter = 0; - $rowstyle = 'style="background-color: #EEEEEE; padding: 4px;"'; - $mailReceipients = ''; // String with all mailadresses $mailcontent_data_arr = array(); foreach ($applicants_arr as $applicant) { if ($bachelorStudiengang->studiengang_kz == $applicant->studiengang_kz) { - $mailReceipients .= $applicant->email. ';'; $applicantCounter ++; - $applicants_list .= ' - - '. $applicant->orgform_kurzbz. ' - '. $applicant->ausbildungssemester. ' - '. $applicant->nachname. ' - '. $applicant->vorname. ' - '. $applicant->zgv_kurzbz. ' - '. $applicant->prioritaet. ' - '. $applicant->qualifikationskurs. ' - '. $applicant->email. ' - - '; } } if ($applicantCounter == 0) @@ -149,30 +157,14 @@ class ReihungstestJob extends CLI_Controller } else { - $headerstyle = 'style="background: #DCE4EF; border: 1px solid #FFF; padding: 4px; text-align: left;"'; - $mailcontent = '

Der Anmeldeschluss für den zentralen Reihungstest am ' . date_format(date_create($reihungstest->datum), 'd.m.Y') . ' um ' . $reihungstest->uhrzeit . ' Uhr wurde gestern erreicht.

'; $mailcontent .= ' -

Folgende ' . $applicantCounter . ' InteressentInnen des Studiengangs ' . $studiengang_kuerzel . ' nehmen daran teil:

- - - - - - - - - - - - - '; - $mailcontent .= $applicants_list; - $mailcontent .= ' - -
OrgFormSemesterNachnameVornameZGVPrioritätQualikursE-Mail
- '; - $mailcontent .= '

Mail an alle schicken

'; +

' . $applicantCounter . ' InteressentIn(nen) des Studiengangs ' . $studiengang_kuerzel . ' nehmen daran teil:

+

+ + Liste der Anmeldungen + +

'; } $mailcontent_data_arr['table'] = $mailcontent; @@ -182,22 +174,47 @@ class ReihungstestJob extends CLI_Controller sendSanchoMail( 'Sancho_ReihungstestteilnehmerJob', $mailcontent_data_arr, - array($bachelorStudiengang->email,'kindlm@technikum-wien.at'), + $bachelorStudiengang->email, 'Anmeldeschluss Reihungstest ' . date_format(date_create($reihungstest->datum), 'd.m.Y') . ' ' . $reihungstest->uhrzeit . ' Uhr', 'sancho_header_min_bw.jpg', - 'sancho_footer_min_bw.jpg'); + 'sancho_footer_min_bw.jpg', + $from, + '', + $bcc); } } } } - /** - * Checks, if an applicant was assigned to a test after Anmeldefrist + /* + * Checks, if an applicant was assigned to a test after Anmeldefrist and sends an email to all responsible assistants + * + * @param integer $degreeProgram. Kennzahl of Degree Program to check + * @param string $bcc. Optional. BCC-Mailadress to send the Mails to + * @param string $from. Optional. Sender-Mailadress shown to recipient */ - public function runZentraleReihungstestNachtraeglichHinzugefuegtJob() + public function runZentraleReihungstestNachtraeglichHinzugefuegtJob($degreeProgram, $bcc = null, $from = null) { + // Encode Params + if ($bcc != '') + { + // $bcc can be given as null-string, so check that too + if ($bcc == 'null') + { + $bcc = ''; + } + else + { + $bcc = urldecode($bcc); + } + } + if ($from != '') + { + $from = urldecode($from); + } + // Get applicants that have been added to a test after Anmeldefrist - $result = $this->ReihungstestModel->getApplicantAssignedAfterDate(11000); + $result = $this->ReihungstestModel->getApplicantAssignedAfterDate($degreeProgram); $applicants_after_anmeldefrist_arr = array(); @@ -207,7 +224,7 @@ class ReihungstestJob extends CLI_Controller } elseif (isError($result)) { - show_error($result->error); + show_error(getError($result)); } $studiengang = ''; @@ -229,20 +246,27 @@ class ReihungstestJob extends CLI_Controller $bachelorStudiengang = $this->StudiengangModel->load($studiengang); $mailcontent .= $applicants_list; $mailcontent .= ''; - $mailcontent .= '

Mail an alle schicken

'; + $mailcontent .= '

+ + Liste der Anmeldungen + +

'; $mailcontent_data_arr['table'] = $mailcontent; sendSanchoMail( 'Sancho_ReihungstestteilnehmerJob', $mailcontent_data_arr, - array($bachelorStudiengang->retval[0]->email,'kindlm@technikum-wien.at'), + $bachelorStudiengang->retval[0]->email, 'InteressentIn nach Reihungstest-Anmeldeschluss hinzugefügt', 'sancho_header_min_bw.jpg', - 'sancho_footer_min_bw.jpg'); + 'sancho_footer_min_bw.jpg', + $from, + '', + $bcc); $applicants_list = ''; $mailcontent_data_arr = array(); } - $mailcontent = '

Folgende InteressentInnen wurden nach der Anmeldefrist zu einem Reihungstest hinzugefügt.

'; + $mailcontent = '

Folgende InteressentInnen wurden nach der Anmeldefrist zu einem Reihungstest hinzugefügt.
Details siehe Link

'; $mailcontent .= ' @@ -252,10 +276,6 @@ class ReihungstestJob extends CLI_Controller - - - - '; @@ -271,45 +291,52 @@ class ReihungstestJob extends CLI_Controller - - - - '; }; $bachelorStudiengang = $this->StudiengangModel->load($studiengang); $mailcontent .= $applicants_list; $mailcontent .= '
Semester Nachname VornameZGVPrioritätQualikursE-Mail
' . $applicant->ausbildungssemester . ' ' . $applicant->nachname . ' ' . $applicant->vorname . '' . $applicant->zgv_kurzbz . '' . $applicant->prioritaet . '' . $applicant->qualifikationskurs . '' . $applicant->email . '
'; - $mailcontent .= '

Mail an alle schicken

'; + $mailcontent .= '

+ + Liste der Anmeldungen + +

'; $mailcontent_data_arr['table'] = $mailcontent; sendSanchoMail( 'Sancho_ReihungstestteilnehmerJob', $mailcontent_data_arr, - array($bachelorStudiengang->retval[0]->email,'kindlm@technikum-wien.at'), + $bachelorStudiengang->retval[0]->email, 'InteressentIn nach Reihungstest-Anmeldeschluss hinzugefügt', 'sancho_header_min_bw.jpg', - 'sancho_footer_min_bw.jpg'); + 'sancho_footer_min_bw.jpg', + $from, + '', + $bcc); } } /* - * Sends an email to all applicants of a placement test to remind them 3 working days before + * Sends an email to all applicants of a placement test to remind them 2 working days before * * @param integer $degreeProgram. Kennzahl of Degree Program to check * @param string $bcc. Optional. BCC-Mailadress to send the Mails to * @param string $from. Optional. Sender-Mailadress shown to recipient */ - public function remindApplicantsOfPlacementTest() + public function remindApplicantsOfPlacementTest($degreeProgram, $bcc = null, $from = null) { - $degreeProgram = $this->input->get('degreeprogram'); - $bcc = $this->input->get('bcc'); - $from = $this->input->get('from'); - // Encode Params if ($bcc != '') { - $bcc = urldecode($bcc); + // $bcc can be given as null-string, so check that too + if ($bcc == 'null') + { + $bcc = ''; + } + else + { + $bcc = urldecode($bcc); + } } if ($from != '') { @@ -328,16 +355,16 @@ class ReihungstestJob extends CLI_Controller $workingdays = 0; $testsOndate = array(); - // Deduct days till 3 working days are reached + // Deduct days till 2 working days are reached for ($i = 1; ; $i++) { if (isDateWorkingDay($testDates->datum, $i) === true) { $workingdays++; } - if ($workingdays == 3) + if ($workingdays == 2) { - $enddate = date("Y-m-d", strtotime("$testDates->datum -".$i." days")); + $enddate = date("Y-m-d", strtotime("$testDates->datum -" . $i . " days")); break; } else @@ -357,7 +384,7 @@ class ReihungstestJob extends CLI_Controller } elseif (isError($resultTestsOnDate)) { - show_error($resultTestsOnDate->error); + show_error(getError($resultTestsOnDate)); } } @@ -374,7 +401,7 @@ class ReihungstestJob extends CLI_Controller } elseif (isError($applicants)) { - show_error($applicants->error); + show_error(getError($applicants)); } foreach ($applicants_arr as $applicant) @@ -386,7 +413,14 @@ class ReihungstestJob extends CLI_Controller $mailcontent_data_arr['rt_datum'] = date_format(date_create($reihungstest->datum), 'd.m.Y'); $mailcontent_data_arr['rt_uhrzeit'] = date_format(date_create($reihungstest->uhrzeit), 'H:i'); $mailcontent_data_arr['rt_raum'] = $applicant->planbezeichnung; - $mailcontent_data_arr['wegbeschreibung'] = $applicant->lageplan; + if ($applicant->lageplan == '') + { + $mailcontent_data_arr['wegbeschreibung'] = 'Für diesen Raum liegt noch keine Wegbeschreibung vor.

No directions were found for this room'; + } + else + { + $mailcontent_data_arr['wegbeschreibung'] = $applicant->lageplan; + } sendSanchoMail( 'Sancho_RemindApplicantsOfTest', @@ -405,11 +439,185 @@ class ReihungstestJob extends CLI_Controller } } + /** + * This job sends eMail(s) to the relevant stg assistance(s) informing about: + * All applicants, who have sent new applications AFTER they had absolved a + * placement test in the actual studiensemester + * AND who have been confirmed yesterday. + */ + public function mailNewApplicants() + { + // Get yesterdays confirmed applicants for Bachelor-studies + $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + $this->PrestudentstatusModel->addSelect(' + tbl_person.person_id, + tbl_prestudentstatus.prestudent_id, + tbl_prestudent.studiengang_kz, + tbl_prestudentstatus.studiensemester_kurzbz, + tbl_prestudentstatus.bestaetigtam, + tbl_prestudentstatus.bewerbung_abgeschicktamum + '); + $this->PrestudentstatusModel->addJoin('public.tbl_prestudent', 'prestudent_id'); + $this->PrestudentstatusModel->addJoin('public.tbl_studiengang', 'studiengang_kz'); + $this->PrestudentstatusModel->addJoin('public.tbl_studiengangstyp', 'typ'); + $this->PrestudentstatusModel->addJoin('public.tbl_person', 'person_id'); + + $yesterdays_applicants_arr = $this->PrestudentstatusModel->loadWhere(' + status_kurzbz = \'Interessent\' AND + typ = \'b\' AND + bestaetigtam = current_date - 1 + '); + + // Retrieve the person_ids of yesterdays confirmed applicants + $person_id_arr = array(); + if (hasData($yesterdays_applicants_arr)) + { + foreach ($yesterdays_applicants_arr->retval as $yesterdays_applicant) + { + if (isset($yesterdays_applicant->person_id)) { + $person_id_arr[] = $yesterdays_applicant->person_id; + } + } + } + elseif (isError($yesterdays_applicants_arr)) + { + show_error(getError($yesterdays_applicants_arr)); + } + + // Get all other prestudenten of the given persons. + if (!isEmptyArray($person_id_arr)) + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $this->PrestudentModel->addDistinct(); + $this->PrestudentModel->addSelect(' + person_id, + tbl_reihungstest.studiensemester_kurzbz, + tbl_reihungstest.reihungstest_id, + (SELECT(tbl_reihungstest.datum::text || \' \' || tbl_reihungstest.uhrzeit::text)::timestamp) AS reihungstest_timestamp + '); + $this->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz'); + $this->PrestudentModel->addJoin('public.tbl_studiengangstyp', 'typ'); + $this->PrestudentModel->addJoin('public.tbl_prestudentstatus', 'prestudent_id'); + $this->PrestudentModel->addJoin('public.tbl_person', 'person_id'); + $this->PrestudentModel->addJoin('public.tbl_rt_person', 'person_id'); + $this->PrestudentModel->addJoin('public.tbl_reihungstest', 'tbl_reihungstest.reihungstest_id = tbl_rt_person.rt_id'); + + // Store them, if they have already absolved a placement test in the same study term they have applied for. + $placement_absolvents_arr = $this->PrestudentModel->loadWhere(' + person_id IN (' . implode(', ', $person_id_arr) . ') AND + typ = \'b\' AND + teilgenommen = \'t\' AND + tbl_reihungstest.studiensemester_kurzbz IN ( + SELECT + studiensemester_kurzbz + FROM + public.tbl_studiensemester + WHERE + ende >= now() + ) + '); + } + + // Store data to be send in the email-link + $result_arr = array(); + foreach($yesterdays_applicants_arr->retval as $yesterdays_applicant) + { + foreach ($placement_absolvents_arr->retval as $placement_absolvent) + { + if ($yesterdays_applicant->person_id == $placement_absolvent->person_id && + $yesterdays_applicant->studiensemester_kurzbz == $placement_absolvent->studiensemester_kurzbz && + $yesterdays_applicant->bewerbung_abgeschicktamum >= $placement_absolvent->reihungstest_timestamp) + { + $obj = new stdClass(); + $obj->prestudent_id = $yesterdays_applicant->prestudent_id; // prestudent_id of the yesterdays applicant + $obj->studiengang_kz = $yesterdays_applicant->studiengang_kz; // study program of interest of the yesterdays applicant + $obj->reihungstest_id = $placement_absolvent->reihungstest_id; // reihungstest_id of absolved reihungstest of that person + + $result_arr[]= $obj; + } + } + } + + // Sort by STG. This is important to send the mails clustered by STG to the different STG assistances. + usort($result_arr, function ($a, $b) + { + if ($a->studiengang_kz == $b->studiengang_kz) { + return 0; + } + return ($a->studiengang_kz < $b->studiengang_kz) ? -1 : 1; + }); + + $to = ''; // mail recipient (stg assistance) + $content_arr = array(); // url paths to the new applicants + $base_link = base_url('vilesci/stammdaten/auswertung_fhtw.php'); + + $i = 0; // loop counter + $len = count($result_arr); + + // Loop trough list of new applicants + foreach($result_arr as $result) + { + $studiengang = $this->StudiengangModel->load($result->studiengang_kz); + $mail_stg_assistance = $studiengang->retval[0]->email; + + // If first loop + if ($i == 0) + { + $to = $mail_stg_assistance; // set recipient initially + } + + // If new study is encountered but is not the first loop + if ($to != $mail_stg_assistance && $i != 0) + { + // Prepare content for mail template + $content_data_arr = $this->_getContentDataNewApplicant($content_arr); + + // Send mail + sendSanchoMail( + 'BewerberNachReihungstest', + $content_data_arr, + $to, + 'Neue Bewerbungen nach absolviertem Reihungstest', + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg' + ); + + // Reset content for new study applicants & reset recipient (new stg assistance) + $content_arr = array($base_link. '?reihungstest='. $result->reihungstest_id. '&prestudent_id='. $result->prestudent_id); + $to = $mail_stg_assistance; + } + // If same study + else + { + // just add content + $content_arr[]= $base_link. '?reihungstest='. $result->reihungstest_id. '&prestudent_id='. $result->prestudent_id; // add to content + } + + // If last loop + if (($i == $len - 1)) + { + // Prepare content for mail template + $content_data_arr = $this->_getContentDataNewApplicant($content_arr); + + // Send mail + sendSanchoMail( + 'BewerberNachReihungstest', + $content_data_arr, + $to, + 'Neue Bewerbungen nach absolviertem Reihungstest', + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg' + ); + } + $i++; // iterate counter + } + } + // ------------------------------------------------------------------------ // Private methods /** * Returns associative array with data as needed in the reihungstest job template. - * @param array $missing_rt_arr Array with studienpläne, which have no assigned placement tests. + * @param array $missing_rt_arr Array with studienpläne, which have no assigned placement tests. * @param array $free_places_arr Array with info and amount of free placement test places. * @return array */ @@ -419,38 +627,33 @@ class ReihungstestJob extends CLI_Controller $style_tbl2 = ' cellpadding="0" cellspacing="20" width="100%" style="font-family: courier, verdana, sans-serif; font-size: 0.95em; border: 1px solid #000000;" '; // Prepare HTML table with study plans that have no placement tests yet - if (!empty($missing_rt_arr)) - { + if (!empty($missing_rt_arr)) { $studienplan_list = ' - + '; - foreach ($missing_rt_arr as $rt) - { + foreach ($missing_rt_arr as $rt) { $studienplan_list .= ' - '. $rt->bezeichnung. ' + ' . $rt->bezeichnung . ' '; } $studienplan_list .= ' '; - } - else - { + } else { $studienplan_list = ' - + Alles okay! Alle Studienpläne haben zumindest einen Reihungstest. '; } // Prepare HTML table with information and amount of free places - if (!empty($free_places_arr)) - { + if (!empty($free_places_arr)) { $freie_plaetze_list = ' - + Fakultät Reihungstesttermine @@ -458,16 +661,15 @@ class ReihungstestJob extends CLI_Controller '; - foreach ($free_places_arr as $free_place) - { + foreach ($free_places_arr as $free_place) { $datum = new DateTime($free_place->datum); $style_alarm = ($free_place->freie_plaetze <= 5) ? ' style=" color: red; font-weight: bold" ' : ''; // mark if <=5 free places $freie_plaetze_list .= ' - '. $free_place->fakultaet. ' - '. $datum->format('d.m.Y'). ' - '. $free_place->freie_plaetze. ' + ' . $free_place->fakultaet . ' + ' . $datum->format('d.m.Y') . ' + ' . $free_place->freie_plaetze . ' '; } @@ -475,11 +677,9 @@ class ReihungstestJob extends CLI_Controller $freie_plaetze_list .= ' '; - } - else - { + } else { $freie_plaetze_list = ' - + Es gibt heute keine Ergebnisse zu freien Reihungstestplätze. '; @@ -493,6 +693,25 @@ class ReihungstestJob extends CLI_Controller return $content_data_arr; } + /** + * Returns associative array with data as needed in the BewerberNachReihungstest-template. + * @param array $content_arr Array with links to the testtool evaluation page of the new applicants. + * @return array + */ + private function _getContentDataNewApplicant($content_arr) + { + $content = ''; + $counter = 1; + foreach ($content_arr as $row) + { + $content .= '
Link zu: Bewerber '. $counter. ''; + $counter++; + } + + $content_data_arr['link'] = $content; + return $content_data_arr; + } + /** * Checks the upcoming placement tests if there are correct studyplans assigned @@ -538,28 +757,23 @@ class ReihungstestJob extends CLI_Controller $db = new DB_Model(); $result_rt = $db->execReadOnlyQuery($qry); - if(hasdata($result_rt)) - { - foreach ($result_rt->retval as $row_rt) - { + if (hasdata($result_rt)) { + foreach ($result_rt->retval as $row_rt) { // find an active studyplan for the same degree program with is valid in this semester $result_stpl = $this->StudienplanModel->getStudienplaeneBySemester( $row_rt->studiengang_kz, $row_rt->studiensemester_kurzbz ); - if(hasData($result_stpl)) - { - foreach($result_stpl->retval as $row_stpl) - { + if (hasData($result_stpl)) { + foreach ($result_stpl->retval as $row_stpl) { // Add new Studyplan to RtStudienplan if missing $rt_studienplan = $this->RtStudienplanModel->loadWhere(array( "reihungstest_id" => $row_rt->reihungstest_id, "studienplan_id" => $row_stpl->studienplan_id )); - if(!hasData($rt_studienplan)) - { + if (!hasData($rt_studienplan)) { echo "\nAdding StudienplanId: $row_stpl->studienplan_id"; echo " to ReihungstestId: $row_rt->reihungstest_id"; @@ -573,4 +787,267 @@ class ReihungstestJob extends CLI_Controller } } } + + /* + * Cronjob for priorisation process of FHTW + * + * Wenn ein Student in einer höheren Prio aufgenommen wird, werden die anderen Bewerbungen auf "Abgewiesen" gesetzt, + * solang diese noch im Status "Bewerber" sind. + * Andernfalls wird eine Mail an die niedrigeren Prios verschickt, dass eine höhere Prio aufgenommen hat + * Die Kaution wird automatisch gebucht + * + * @param string $bcc. Optional. BCC-Mailadress to send the Mails to + * @param string $from. Optional. Sender-Mailadress shown to recipient + */ + public function prioritizationJob($bcc = null, $from = null) + { + $qry = " SELECT DISTINCT + get_rolle_prestudent (tbl_prestudent.prestudent_id, 'WS2020') AS laststatus, /* Todo: Studiensemester dynamisch ermitteln oder als Parameter */ + tbl_prestudentstatus.studiensemester_kurzbz, + tbl_prestudent.* + FROM PUBLIC.tbl_person + JOIN PUBLIC.tbl_prestudent USING (person_id) + JOIN PUBLIC.tbl_prestudentstatus USING (prestudent_id) + JOIN lehre.tbl_studienplan USING (studienplan_id) + JOIN lehre.tbl_studienordnung USING (studienordnung_id) + JOIN PUBLIC.tbl_studiengang ON (tbl_studienordnung.studiengang_kz = tbl_studiengang.studiengang_kz) + WHERE tbl_prestudentstatus.datum >= (SELECT CURRENT_DATE -1) + AND get_rolle_prestudent (tbl_prestudent.prestudent_id, 'WS2020') IN ('Aufgenommener','Bewerber','Wartender') + AND studiensemester_kurzbz = 'WS2020' /* Todo: Studiensemester dynamisch ermitteln oder als Parameter */ + AND tbl_studiengang.typ = 'b' + ORDER BY studiengang_kz, laststatus + "; + + // Encode Params + if ($bcc != '') + { + // $bcc can be given as null-string, so check that too + if ($bcc == 'null') + { + $bcc = ''; + } + else + { + $bcc = urldecode($bcc); + } + } + if ($from != '') + { + $from = urldecode($from); + } + + $db = new DB_Model(); + $result_prestudents = $db->execReadOnlyQuery($qry); + $mailArray = array(); + + if (hasdata($result_prestudents)) + { + foreach ($result_prestudents->retval as $row_ps) + { + // Wenn der letzte Status "Aufgenommener" ist, alle niedrigeren Prios auf "Abgewiesen" setzen + // falls diese Bewerber oder Warteliste sind + // Danach Kaution einbuchen + if ($row_ps->laststatus == 'Aufgenommener') + { + // Alle niedrigeren Prios laden + $qryNiedrPrios = " + SELECT DISTINCT + get_rolle_prestudent (tbl_prestudent.prestudent_id, '".$row_ps->studiensemester_kurzbz."') AS laststatus, + tbl_studienplan.orgform_kurzbz, + tbl_person.nachname, + tbl_person.vorname, + tbl_prestudent.* + FROM PUBLIC.tbl_person + JOIN PUBLIC.tbl_prestudent USING (person_id) + JOIN PUBLIC.tbl_prestudentstatus USING (prestudent_id) + JOIN lehre.tbl_studienplan USING (studienplan_id) + JOIN PUBLIC.tbl_studiengang ON (tbl_prestudent.studiengang_kz = tbl_studiengang.studiengang_kz) + WHERE tbl_prestudent.person_id = ".$row_ps->person_id." + AND tbl_prestudent.prestudent_id != ".$row_ps->prestudent_id." + AND get_rolle_prestudent (tbl_prestudent.prestudent_id, '".$row_ps->studiensemester_kurzbz."') IN ('Aufgenommener','Bewerber','Wartender') + AND studiensemester_kurzbz = '".$row_ps->studiensemester_kurzbz."' + AND tbl_studiengang.typ = 'b' + AND priorisierung > ".$row_ps->priorisierung." + ORDER BY studiengang_kz, laststatus + "; + + $resultNiedrPrios = $db->execReadOnlyQuery($qryNiedrPrios); + + if (hasdata($resultNiedrPrios)) + { + foreach ($resultNiedrPrios->retval as $rowNiedrPrios) + { + if ($rowNiedrPrios->laststatus == 'Bewerber') + { + // Abgewiesenen-Status mit Statusgrund "Aufnahme anderer Studiengang" (ID 5) setzen + $lastStatus = $this->PrestudentstatusModel->getLastStatus($rowNiedrPrios->prestudent_id); + + $result = $this->PrestudentstatusModel->insert( + array( + 'prestudent_id' => $rowNiedrPrios->prestudent_id, + 'studiensemester_kurzbz' => $lastStatus->retval[0]->studiensemester_kurzbz, + 'ausbildungssemester' => $lastStatus->retval[0]->ausbildungssemester, + 'datum' => date('Y-m-d'), + 'orgform_kurzbz' => $lastStatus->retval[0]->orgform_kurzbz, + 'studienplan_id' => $lastStatus->retval[0]->studienplan_id, + 'status_kurzbz' => 'Abgewiesener', + 'statusgrund_id' => 5, + 'insertvon' => 'prioritizationJob', + 'insertamum' => date('Y-m-d H:i:s') + ) + ); + if (isSuccess($result)) + { + // Derzeit nur Info an Admins schicken, wenn er Bewerber war + $mailArray[$rowNiedrPrios->studiengang_kz][$rowNiedrPrios->orgform_kurzbz]['AbgewiesenWeilBewerber'][] + = $rowNiedrPrios->nachname.' '.$rowNiedrPrios->vorname.' ('.$rowNiedrPrios->prestudent_id.')'; + } + } + elseif ($rowNiedrPrios->laststatus == 'Wartender') + { + // Abgewiesenen-Status mit Statusgrund "Aufnahme anderer Studiengang" (ID 5) setzen + // Mail zur Info an Assistenz schicken + $lastStatus = $this->PrestudentstatusModel->getLastStatus($rowNiedrPrios->prestudent_id); + + $result = $this->PrestudentstatusModel->insert( + array( + 'prestudent_id' => $rowNiedrPrios->prestudent_id, + 'studiensemester_kurzbz' => $lastStatus->retval[0]->studiensemester_kurzbz, + 'ausbildungssemester' => $lastStatus->retval[0]->ausbildungssemester, + 'datum' => date('Y-m-d'), + 'orgform_kurzbz' => $lastStatus->retval[0]->orgform_kurzbz, + 'studienplan_id' => $lastStatus->retval[0]->studienplan_id, + 'status_kurzbz' => 'Abgewiesener', + 'statusgrund_id' => 5, + 'insertvon' => 'prioritizationJob', + 'insertamum' => date('Y-m-d H:i:s') + ) + ); + if (isSuccess($result)) + { + $mailArray[$rowNiedrPrios->studiengang_kz][$rowNiedrPrios->orgform_kurzbz]['AbgewiesenGesetztWartender'][] + = $rowNiedrPrios->nachname.' '.$rowNiedrPrios->vorname.' ('.$rowNiedrPrios->prestudent_id.')'; + } + } + elseif ($rowNiedrPrios->laststatus == 'Aufgenommener') + { + // Mail zur Info an Assistenz schicken, dass in höherer Prio aufgenommen wurde + $mailArray[$rowNiedrPrios->studiengang_kz][$rowNiedrPrios->orgform_kurzbz]['AufnahmeHoeherePrio'][] + = $rowNiedrPrios->nachname.' '.$rowNiedrPrios->vorname.' ('.$rowNiedrPrios->prestudent_id.')'; + } + } + } + + // Kaution einbuchen für $row_ps->prestudent_id + // Vorher prüfen, ob schon eine Kaution gebucht ist + // Todo: Betrag automatisch aus tbl_buchungstyp laden + + $qryKautionExists = " + SELECT count(*) as anzahl + FROM public.tbl_konto + WHERE person_id = ".$row_ps->person_id." + AND studiensemester_kurzbz = '".$row_ps->studiensemester_kurzbz."' + AND buchungstyp_kurzbz = 'Kaution'"; + + $resultKautionExists = $db->execReadOnlyQuery($qryKautionExists); + if (hasdata($resultKautionExists)) + { + if ($resultKautionExists->retval[0]->anzahl == '0') + { + // Todo: Zahlungsreferenz generieren (StudiengangsOE+Buchungsnummer) + $this->KontoModel->insert(array( + "person_id" => $row_ps->person_id, + "studiengang_kz" => $row_ps->studiengang_kz, + "studiensemester_kurzbz" => $row_ps->studiensemester_kurzbz, + "betrag" => -150, + "buchungsdatum" => date('Y-m-d'), + "buchungstext" => 'Kaution', + "buchungstyp_kurzbz" => 'Kaution', + "insertvon" => 'prioritizationJob', + "insertamum" => date('Y-m-d H:i:s') + )); + } + } + } + } + } + + // Mails senden + if (!isEmptyArray($mailArray)) + { + foreach ($mailArray AS $stg=>$orgform) + { + $studiengang = $this->StudiengangModel->load($stg); + $mailcontent = ''; + + foreach ($orgform AS $art=>$value) + { + // Orgform nur dazu schreiben, wenn es mehr als Eine gibt + if (count($orgform) > 1) + { + $mailcontent .= '

Orgform '.$art.'

'; + } + if (isset($value['AbgewiesenGesetztWartender']) && !isEmptyArray($value['AbgewiesenGesetztWartender'])) + { + $mailcontent .= '

+ Folgende Personen auf der Warteliste wurden in einem höher priorisierten Studiengang aufgenommen und haben deshalb einen Status "Abgewiesen" erhalten:

'; + $mailcontent .= ''; + //$mailcontent .= ''; + $mailcontent .= ' '; + sort($value['AbgewiesenGesetztWartender']); + foreach ($value['AbgewiesenGesetztWartender'] AS $key=>$bewerber) + { + $mailcontent .= ''; + } + $mailcontent .= '
Zuvor Warteliste
'.$bewerber.'


'; + } + if (isset($value['AufnahmeHoeherePrio']) && !isEmptyArray($value['AufnahmeHoeherePrio'])) + { + $mailcontent .= '

+ Folgende Aufgenommene wurden in einem höher priorisierten Studiengang aufgenommen:

'; + $mailcontent .= ''; + //$mailcontent .= ''; + $mailcontent .= ' '; + sort($value['AufnahmeHoeherePrio']); + foreach ($value['AufnahmeHoeherePrio'] AS $key=>$bewerber) + { + $mailcontent .= ''; + } + $mailcontent .= '
Aufgenommene
'.$bewerber.'
'; + } + if ($bcc != '' && isset($value['AbgewiesenWeilBewerber']) && !isEmptyArray($value['AbgewiesenWeilBewerber'])) + { + $mailcontent .= '

+ Folgende BewerberInnen wurden zu Abgewiesenen gemacht:

'; + $mailcontent .= ''; + //$mailcontent .= ''; + $mailcontent .= ' '; + sort($value['AbgewiesenWeilBewerber']); + foreach ($value['AbgewiesenWeilBewerber'] AS $key => $bewerber) + { + $mailcontent .= ''; + } + $mailcontent .= '
Aufgenommene
'.$bewerber.'
'; + } + } + + $mailcontent_data_arr['table'] = $mailcontent; + + // Send email in Sancho design + if (!isEmptyString($mailcontent)) + { + sendSanchoMail( + 'Sancho_ReihungstestteilnehmerJob', + $mailcontent_data_arr, + $studiengang->retval[0]->email, + 'Status Abgewiesen gesetzt', + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg', + $from, + '', + $bcc); + } + } + } + } } diff --git a/application/controllers/lehre/lehrauftrag/Lehrauftrag.php b/application/controllers/lehre/lehrauftrag/Lehrauftrag.php new file mode 100644 index 000000000..dade1fb21 --- /dev/null +++ b/application/controllers/lehre/lehrauftrag/Lehrauftrag.php @@ -0,0 +1,347 @@ + 'lehre/lehrauftrag_bestellen:r', + 'orderLehrauftrag' => 'lehre/lehrauftrag_bestellen:rw', + 'Dashboard' => array('lehre/lehrauftrag_bestellen:r', 'lehre/lehrauftrag_erteilen:r'), + 'LehrendeUebersicht' => array('lehre/lehrauftrag_erteilen:r') + ) + ); + + // Load models + $this->load->model('system/Benutzerrolle_model', 'BenutzerrolleModel'); + $this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + $this->load->model('accounting/Vertrag_model', 'VertragModel'); + + // Load libraries + $this->load->library('WidgetLib'); + $this->load->library('PermissionLib'); + + // Load helpers + $this->load->helper('array'); + $this->load->helper('url'); + $this->load->helper('hlp_sancho_helper'); + + // Load language phrases + $this->loadPhrases( + array( + 'global', + 'ui', + 'lehre' + ) + ); + + $this->_setAuthUID(); // sets property uid + + $this->setControllerId(); // sets the controller id + } + + /** + * Display of Custom Dashboard for Lehraufträge App + * Charts are hooked from Reporting Addon + */ + public function Dashboard() + { + $this->load->view('lehre/lehrauftrag/Dashboard.php'); + } + + /** + * Display of Lehrauftragsübersicht report + */ + public function LehrendeUebersicht() + { + $this->load->view('lehre/lehrauftrag/LehrendeUebersicht.php'); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + /** + * Main page of Lehrauftrag + */ + public function index() + { + // Set studiengang selected for studiengang dropdown + $studiengang_kz = $this->input->get('studiengang'); // if provided by selected studiengang + $studiengang_kz = ($studiengang_kz == 'null' ? null : $studiengang_kz); + + // Retrieve studiengaenge the user is entitled for to populate studiengang dropdown + if (!$studiengang_kz_arr = $this->permissionlib->getSTG_isEntitledFor(self::BERECHTIGUNG_LEHRAUFTRAG_BESTELLEN)) { + show_error('Fehler bei Berechtigungsprüfung'); + } + + // If studiengang_kz get param was set, check against entitled stg + if (!is_null($studiengang_kz)) + { + if (!in_array($studiengang_kz, $studiengang_kz_arr)) + { + show_error('Keine Berechtigung für diesen Studiengang'); + } + } + + // Set studiensemester selected for studiengang dropdown + $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(); + if (hasData($studiensemester)) + { + $studiensemester_kurzbz = $studiensemester->retval[0]->studiensemester_kurzbz; + } + elseif (isError($studiensemester)) + { + show_error(getError($studiensemester)); + } + } + + // Set ausbildungssemester selected for ausbildungssemester dropdown + $ausbildungssemester = $this->input->get('ausbildungssemester'); // if provided by selected ausbildungssemester + $ausbildungssemester = ($ausbildungssemester == 'null' ? null : $ausbildungssemester); + + $view_data = array( + 'studiengang_selected' => $studiengang_kz, + 'studiengang' => $studiengang_kz_arr, + 'studiensemester_selected' => $studiensemester_kurzbz, + 'ausbildungssemester_selected' => $ausbildungssemester, + ); + + $this->load->view('lehre/lehrauftrag/orderLehrauftrag.php', $view_data); + } + + public function orderLehrauftrag() + { + $new_lehrvertrag_data_arr = array(); // information of new lehrvertraege to be used in mail + $lehrauftrag_arr = json_decode($this->input->post('selected_data')); + + // Loop through lehraufträge + if(is_array($lehrauftrag_arr)) + { + foreach($lehrauftrag_arr as $lehrauftrag) + { + $lehreinheit_id = (isset($lehrauftrag->lehreinheit_id)) ? $lehrauftrag->lehreinheit_id : null; + $lehrveranstaltung_id = (isset($lehrauftrag->lehrveranstaltung_id)) ? $lehrauftrag->lehrveranstaltung_id : null; + $person_id = (isset($lehrauftrag->person_id)) ? $lehrauftrag->person_id : null; + $mitarbeiter_uid = (isset($lehrauftrag->mitarbeiter_uid)) ? $lehrauftrag->mitarbeiter_uid : null; + $vertrag_id = (isset($lehrauftrag->vertrag_id)) ? $lehrauftrag->vertrag_id : null; + $projektarbeit_id = (isset($lehrauftrag->projektarbeit_id)) ? $lehrauftrag->projektarbeit_id : null; + $stunden = (isset($lehrauftrag->stunden)) ? $lehrauftrag->stunden : 0; + $betrag = (isset($lehrauftrag->betrag)) ? $lehrauftrag->betrag : 0; + $studiensemester_kurzbz = (isset($lehrauftrag->studiensemester_kurzbz)) ? $lehrauftrag->studiensemester_kurzbz : null; + $studiengang_kz = (isset($lehrauftrag->studiengang_kz)) ? $lehrauftrag->studiengang_kz : null; + + // Check if user is entitled to order this Lehrauftrag + if (!$this->permissionlib->isBerechtigt(self::BERECHTIGUNG_LEHRAUFTRAG_BESTELLEN, 'suid', $studiengang_kz)) + { + return $this->outputJsonError('Sie haben keine Bestellberechtigung für diesen Studiengang: '. $studiengang_kz); + } + + // update contract if contract exists and the betrag was changed + if (!is_null($vertrag_id)) + { + $this->VertragModel->addSelect('vertragsstunden, betrag'); + + if($result = getData($this->VertragModel->load($vertrag_id))) + { + $vertrag_betrag = $result[0]->betrag; + $vertrag_stunden = $result[0]->vertragsstunden; + } + elseif (isError($result)) + { + return $this->outputJsonError('Fehler beim Laden des Vertrags'); + } + + $hasChanged = ($betrag != floatval($vertrag_betrag) || $stunden != $vertrag_stunden) ? true : false; + + if ($hasChanged) + { + $result = $this->VertragModel->updateVertrag( + $vertrag_id, + $stunden, + $betrag, + $mitarbeiter_uid + ); + + if (isSuccess($result)) + { + $json []= array( + 'row_index' => $lehrauftrag->row_index, + 'bestellt' => date('Y-m-d'), + 'vertrag_betrag' => $betrag, + 'vertrag_stunden' => $stunden, + 'erteilt' => null + ); + } + else + { + return $this->outputJsonError('Fehler beim Vertragsupdate'); + } + } + } + // else save new contract + else + { + $result = $this->VertragModel->save( + $person_id, + $mitarbeiter_uid, + $lehrveranstaltung_id, + $lehreinheit_id, + $projektarbeit_id, + $stunden, + $betrag, + $studiensemester_kurzbz + ); + + if (isSuccess($result)) + { + $json []= array( + 'row_index' => $lehrauftrag->row_index, + 'bestellt' => date('Y-m-d'), + 'vertrag_betrag' => $betrag, + 'vertrag_stunden' => $stunden + ); + } + elseif (isError($result) && $result->retval) + { + return $this->outputJsonError($result->retval); + } + else + { + return $this->outputJsonError('Fehler beim Speichern des Vertrags'); + } + + $new_lehrvertrag_data_arr[] = array( + 'studiensemester_kurzbz' => $lehrauftrag->studiensemester_kurzbz, + 'studiengang_kz' => $lehrauftrag->studiengang_kz, + 'lv_oe_kurzbz' => $lehrauftrag->lv_oe_kurzbz + ); + } + } + } + else + { + return $this->outputJsonError('Fehler beim Übertragen der Daten.'); + } + + if (isset($json) && !isEmptyArray($json)) + { + $this->outputJsonSuccess($json); + } + } + + // ----------------------------------------------------------------------------------------------------------------- + // 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'); + } + + private function _sendMail($lehrvertrag_data_arr) + { + // Cluster data of new lehrvertraege as needed to send mail + $lehrvertrag_data_arr = $this->_cluster_newVertragData($lehrvertrag_data_arr); + + foreach ($lehrvertrag_data_arr as $lehrvertrag_data) + { + // Get mail recipients + $result = $this->BenutzerrolleModel->getBenutzerByBerechtigung('lehre/lehrauftrag_erteilen', $lehrvertrag_data['lv_oe_kurzbz']); + + // If given lv organisational unit has no authorized user, check if is a Kompetenzfeld. + // If so, look up for authorized user on Department level. + if (!hasData($result)) { + $result = $this->OrganisationseinheitModel->getParent($lehrvertrag_data['lv_oe_kurzbz']); + + if (hasData($result)) { + if ($result->retval[0]->organisationseinheittyp_kurzbz === 'Department') { + $result = $this->BenutzerrolleModel->getBenutzerByBerechtigung('lehre/lehrauftrag_erteilen', $result->retval[0]->oe_kurzbz); + } + } + } + + // Set mail recipients (department assistance/leader) + $to = ''; + $to_arr = array(); + foreach ($result->retval as $berechtigung) { + $to_arr []= $berechtigung->uid . '@' . DOMAIN; // TODO: als array, dann splitten mit ;? oder als array lassen? + } + $to = implode(', ', $to_arr); + + // Set link to lehrauftrag-site with preselected studiengang and studiensemester of new lehrauftraege + $url = site_url(self::LEHRAUFTRAG_URI).'?studiensemester='. $lehrvertrag_data['studiensemester_kurzbz']. '&studiengang='. $lehrvertrag_data['studiengang_kz']; + + // Prepare mail content + $content_data_arr = array( + 'anzahl' => $lehrvertrag_data['amount_new_lehrvertraege'], + 'studiengang' => $lehrvertrag_data['studiengang_kz'], + 'studiensemester' => $lehrvertrag_data['studiensemester_kurzbz'], + 'link' => anchor($url, 'Lehrverträge Übersicht') + ); + + // Send mail + sendSanchoMail( + 'LehrauftragBestellMail', + $content_data_arr, + $to, + 'Bestellung neuer Lehraufträge', + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg' + ); + } + } + + /** + * Clusters data as needed for _sendMail. + * Makes array of new lehrvertraege unique (by studiensemester, studiengang and lv_oe_kurzbz) + * Adds the amount of lehrvertraege of each unique array element. + * @param $new_lehrvertrag_data_arr + * @return array + */ + private function _cluster_newVertragData($new_lehrvertrag_data_arr) + { + $unique_new_lehrvertrag_data_arr = array_unique($new_lehrvertrag_data_arr, SORT_REGULAR); + foreach ($unique_new_lehrvertrag_data_arr as &$new_lehrvertrag) + { + $cnt = 1; + foreach ($new_lehrvertrag_data_arr as $item) + { + if ($new_lehrvertrag['studiensemester_kurzbz'] === $item['studiensemester_kurzbz'] && + $new_lehrvertrag['studiengang_kz'] === $item['studiengang_kz'] && + $new_lehrvertrag['lv_oe_kurzbz'] === $item['lv_oe_kurzbz']) + { + $new_lehrvertrag['amount_new_lehrvertraege'] = $cnt++; + } + } + } + + return $unique_new_lehrvertrag_data_arr; + } +} diff --git a/application/controllers/lehre/lehrauftrag/LehrauftragAkzeptieren.php b/application/controllers/lehre/lehrauftrag/LehrauftragAkzeptieren.php new file mode 100644 index 000000000..4fc0a879b --- /dev/null +++ b/application/controllers/lehre/lehrauftrag/LehrauftragAkzeptieren.php @@ -0,0 +1,219 @@ + 'lehre/lehrauftrag_akzeptieren:r', + 'acceptLehrauftrag' => 'lehre/lehrauftrag_akzeptieren:rw', + 'checkInkludierteLehre' => 'lehre/lehrauftrag_akzeptieren:rw' + ) + ); + + // Load models + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->load->model('accounting/Vertrag_model', 'VertragModel'); + $this->load->model('accounting/Vertragvertragsstatus_model', 'VertragvertragsstatusModel'); + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('codex/Bisverwendung_model', 'BisverwendungModel'); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + + // Load libraries + $this->load->library('WidgetLib'); + $this->load->library('PermissionLib'); + $this->load->library('AuthLib'); + + // Load helpers + $this->load->helper('array'); + $this->load->helper('url'); + + // Load language phrases + $this->loadPhrases( + array( + 'global', + 'ui', + 'lehre' + ) + ); + + $this->_setAuthUID(); // sets property uid + + $this->setControllerId(); // sets the controller id + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * Main page of Lehrauftrag + */ + public function index() + { + // Set studiensemester selected for studiengang dropdown + $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(); + if (hasData($studiensemester)) + { + $studiensemester_kurzbz = $studiensemester->retval[0]->studiensemester_kurzbz; + } + elseif (isError($studiensemester)) + { + show_error(getError($studiensemester)); + } + } + + $view_data = array( + 'studiensemester_selected' => $studiensemester_kurzbz + ); + + $this->load->view('lehre/lehrauftrag/acceptLehrauftrag.php', $view_data); + } + + /** + * Set the contract status of Lehrauftrag to 'akzeptiert'. + * Performed on ajax call. + */ + public function acceptLehrauftrag() + { + // Verify password + $password = $this->input->post('password'); + if (!isEmptyString($password)) + { + $result = $this->authlib->checkUserAuthByUsernamePassword($this->_uid, $password); + if (isError($result)) + { + return $this->outputJsonError('Passwort ist inkorrekt'); // exit if password is incorrect + } + } + else + { + return $this->outputJsonError('Passwort fehlt'); + } + + // Loop through lehraufträge + $lehrauftrag_arr = $this->input->post('selected_data'); + + if(is_array($lehrauftrag_arr)) + { + foreach($lehrauftrag_arr as $lehrauftrag) + { + $vertrag_id = (!is_null($lehrauftrag['vertrag_id'])) ? $lehrauftrag['vertrag_id'] : null; + + // Check if user is entitled to accept this Lehrauftrag + // * first retrieve person_id of the contract + $this->VertragModel->addSelect('person_id'); + + if ($result = getData($this->VertragModel->load($vertrag_id))) + { + // * then find the uid of that contracts person_id + $this->BenutzerModel->addSelect('uid'); + + if ($result = getData($this->BenutzerModel->getFromPersonId($result[0]->person_id))) + { + // * finally check uid of contract against the logged in user + $account_found = false; + foreach($result as $row_accounts) + { + if($row_accounts->uid == $this->_uid) + { + $account_found = true; + } + } + + if (!$account_found) + { + return $this->outputJsonError('Sie haben keine Berechtigung für einen Vertrag'); + } + } + else + { + return $this->outputJsonError('Fehler beim Laden der Benutzerdaten'); + } + } + else + { + return $this->outputJsonError('Fehler beim Laden des Vertrags'); + } + + // Set status to accepted + $result = $this->VertragvertragsstatusModel->setStatus($vertrag_id, $this->_uid, 'akzeptiert'); + + if ($result->retval) + { + $json []= array( + 'row_index' => $lehrauftrag['row_index'], + 'akzeptiert' => date('Y-m-d') + ); + } + else + { + return $this->outputJsonError($result->retval); + } + } + + // Output json to ajax + if (isset($json) && !isEmptyArray($json)) + { + $this->outputJsonSuccess($json); + } + } + else + { + return $this->outputJsonError('Fehler beim Übertragen der Daten.'); + } + } + + /** + * Check if lectors latest Verwendung has inkludierte Lehre + * - inkludierte_lehre is null OR 0: freelancer lector -> has NO inkludierte Lehre + * - inkludierte_lehre -1: fix employed lector -> has inkludierte Lehre (all inclusive) + * - inkludierte_lehre > 0: fix employed lector -> has inkludierte Lehre (value is amount of hours included) + */ + public function checkInkludierteLehre() + { + $result = $this->BisverwendungModel->getLast($this->_uid, false); + + if (hasData($result)) + { + $this->outputJsonSuccess(!is_null($result->retval[0]->inkludierte_lehre) && $result->retval[0]->inkludierte_lehre != 0); + } + else + { + $this->outputJsonError(getError($result)); + } + } + + // ----------------------------------------------------------------------------------------------------------------- + // 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'); + } + +} diff --git a/application/controllers/lehre/lehrauftrag/LehrauftragErteilen.php b/application/controllers/lehre/lehrauftrag/LehrauftragErteilen.php new file mode 100644 index 000000000..b339c81a4 --- /dev/null +++ b/application/controllers/lehre/lehrauftrag/LehrauftragErteilen.php @@ -0,0 +1,204 @@ + 'lehre/lehrauftrag_erteilen:r', + 'approveLehrauftrag' => 'lehre/lehrauftrag_erteilen:rw' + ) + ); + + // Load models + $this->load->model('system/Benutzerrolle_model', 'BenutzerrolleModel'); + $this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + $this->load->model('accounting/Vertrag_model', 'VertragModel'); + $this->load->model('accounting/Vertragvertragsstatus_model', 'VertragvertragsstatusModel'); + + // Load libraries + $this->load->library('WidgetLib'); + $this->load->library('PermissionLib'); + + // Load helpers + $this->load->helper('array'); + $this->load->helper('url'); + + // Load language phrases + $this->loadPhrases( + array( + 'global', + 'ui', + 'lehre' + ) + ); + + $this->_setAuthUID(); // sets property uid + + $this->setControllerId(); // sets the controller id + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * Main page of Lehrauftrag + */ + public function index() + { + // Set studiengang to be selected in studiengang dropdown + $oe_kurzbz = $this->input->get('organisationseinheit'); // if provided by selected studiengang + $oe_kurzbz = ($oe_kurzbz == 'null' ? null : $oe_kurzbz); + + // Retrieve studiengaenge the user is entitled for to populate studiengang dropdown + if (!$oe_kurzbz_arr = $this->permissionlib->getOE_isEntitledFor(self::BERECHTIGUNG_LEHRAUFTRAG_ERTEILEN)) + { + show_error('Fehler bei Berechtigungsprüfung'); + } + + // If oe_kurzbz get param was set, check against entitled stg + if (!is_null($oe_kurzbz)) + { + if (!in_array($oe_kurzbz, $oe_kurzbz_arr)) + { + show_error('Keine Berechtigung für diese Organisationseinheit'); + } + } + + // Set studiensemester selected for studiengang dropdown + $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(); + if (hasData($studiensemester)) + { + $studiensemester_kurzbz = $studiensemester->retval[0]->studiensemester_kurzbz; + } + elseif (isError($studiensemester)) + { + show_error(getError($studiensemester)); + } + } + + // Set ausbildungssemester selected for ausbildungssemester dropdown + $ausbildungssemester = $this->input->get('ausbildungssemester'); // if provided by selected ausbildungssemester + $ausbildungssemester = ($ausbildungssemester == 'null' ? null : $ausbildungssemester); + + $view_data = array( + 'organisationseinheit_selected' => $oe_kurzbz, + 'organisationseinheit' => $oe_kurzbz_arr, + 'studiensemester_selected' => $studiensemester_kurzbz, + 'ausbildungssemester_selected' => $ausbildungssemester, + ); + + $this->load->view('lehre/lehrauftrag/approveLehrauftrag.php', $view_data); + } + + /** + * Set the contract status of Lehrauftrag to 'erteilt'. + * Performed on ajax call. + */ + public function approveLehrauftrag() + { + $lehrauftrag_arr = json_decode($this->input->post('selected_data')); + + if (is_array($lehrauftrag_arr)) + { + foreach ($lehrauftrag_arr as $lehrauftrag) + { + $mitarbeiter_uid = (isset($lehrauftrag->mitarbeiter_uid)) ? $lehrauftrag->mitarbeiter_uid : null; + $vertrag_id = (isset($lehrauftrag->vertrag_id)) ? $lehrauftrag->vertrag_id : null; + + $lv_oe_kurzbz = null; + + // Retrieve organisational unit to which the lehrveranstaltung of the contract belongs to + // * first get lehrveranstaltung + $result = $this->VertragModel->getLehreinheitData($vertrag_id, 'lehrveranstaltung_id'); + if (hasData($result)) + { + // * then get corresponding organisational unit + $this->load->model('education/Lehrveranstaltung_model', 'Lehrveranstaltung_model'); + $result = $this->LehrveranstaltungModel->load($result->retval[0]->lehrveranstaltung_id); + if (hasData($result)) + { + $lv_oe_kurzbz = $result->retval[0]->oe_kurzbz; + } + elseif (isError(($result))) + { + return $this->outputJsonError('Fehler beim Laden einer Lehrveranstaltung.'); + } + } + elseif (isError($result)) + { + return $this->outputJsonError('Fehler beim Laden von Lehreinheitdaten.'); + } + + // Check if user is entitled to approve this lehrauftrag (by permission and organisational unit) + if (!$this->permissionlib->isBerechtigt(self::BERECHTIGUNG_LEHRAUFTRAG_ERTEILEN, 'suid', $lv_oe_kurzbz)) + { + return $this->outputJsonError('Sie haben keine Erteilberechtigung für diese Organisationseinheit: '. $lv_oe_kurzbz); + } + + // Approve lehrauftrag by setting vertragsstatus to 'erteilt' + $result = $this->VertragvertragsstatusModel->setStatus($vertrag_id, $mitarbeiter_uid, 'erteilt'); + + if (!isError($result)) + { + $json [] = array( + 'row_index' => $lehrauftrag->row_index, + 'erteilt' => date('Y-m-d') + ); + } + else + { + return $this->outputJsonError($result->retval); + } + } + } + else + { + return $this->outputJsonError('Fehler beim Übertragen der Daten.'); + } + + // output success json to ajax + if (isset($json) && !isEmptyArray($json)) + { + $this->outputJsonSuccess($json); + } + } + + // ----------------------------------------------------------------------------------------------------------------- + // 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'); + } + +} diff --git a/application/controllers/organisation/Studienjahr.php b/application/controllers/organisation/Studienjahr.php index c3c841df9..ed8c0b6a1 100644 --- a/application/controllers/organisation/Studienjahr.php +++ b/application/controllers/organisation/Studienjahr.php @@ -20,7 +20,7 @@ class Studienjahr extends Auth_Controller 'editStudienjahr' => 'basis/studiensemester:rw', 'newStudienjahr' => 'basis/studiensemester:rw', 'insStudienjahr' => 'basis/studiensemester:rw', - 'saveStudienjahr' => 'basis/studiensemester:rw', + 'updateStudienjahr' => 'basis/studiensemester:rw', 'deleteStudienjahr' => 'basis/studiensemester:rw' ) ); @@ -44,7 +44,7 @@ class Studienjahr extends Auth_Controller $studienjahr = $this->StudienjahrModel->load(); if ($studienjahr->error) { - show_error($studienjahr->retval); + show_error(getError($studienjahr)); } $data = array( @@ -66,7 +66,7 @@ class Studienjahr extends Auth_Controller $studienjahr = $this->StudienjahrModel->load($studienjahr_kurzbez); if ($studienjahr->error) { - show_error($studienjahr->retval); + show_error(getError($studienjahr)); } $data = array( "studienjahr" => $studienjahr->retval @@ -86,7 +86,7 @@ class Studienjahr extends Auth_Controller $allstudienjahrkurzbz = $this->StudienjahrModel->load(); if ($allstudienjahrkurzbz->error) { - show_error($allstudienjahrkurzbz->retval); + show_error(getError($allstudienjahrkurzbz)); } $studienjahrkurzbz = $allstudienjahrkurzbz->retval[0]->studienjahr_kurzbz; $years = $this->__getYearsFromStudienjahr($studienjahrkurzbz); @@ -117,11 +117,15 @@ class Studienjahr extends Auth_Controller public function insStudienjahr() { $data = $this->__retrieveStudienjahrData(); + $studienjahr_exists = $this->StudienjahrModel->load($data['studienjahr_kurzbz']); + if (hasData($studienjahr_exists)) + show_error("Studienjahr existiert bereits"); + $studienjahr = $this->StudienjahrModel->insert($data); if ($studienjahr->error) { - show_error($studienjahr->retval); + show_error(getError($studienjahr)); } redirect("/organisation/studienjahr/editStudienjahr/".str_replace("/", "_", $data['studienjahr_kurzbz']."?saved=true")); @@ -149,7 +153,7 @@ class Studienjahr extends Auth_Controller return $data; } else { - show_error($validation->retval); + show_error(getError($validation)); } } @@ -177,14 +181,14 @@ class Studienjahr extends Auth_Controller * replaces slash in Kurzbezeichnung with underscore * saved=true is a GET parameter passed for showing save message */ - public function saveStudienjahr() + public function updateStudienjahr() { $data = $this->__retrieveStudienjahrData(); $studienjahr = $this->StudienjahrModel->update($data['studienjahr_kurzbz'], $data); if ($studienjahr->error) { - show_error($studienjahr->retval); + show_error(getError($studienjahr)); } redirect("/organisation/studienjahr/editStudienjahr/".str_replace("/", "_", $data['studienjahr_kurzbz']."?saved=true")); @@ -203,7 +207,7 @@ class Studienjahr extends Auth_Controller if ($studienjahr->error) { - show_error($studienjahr->retval); + show_error(getError($studienjahr)); } redirect("/organisation/studienjahr/listStudienjahr"); diff --git a/application/controllers/organisation/Studiensemester.php b/application/controllers/organisation/Studiensemester.php index cdca4997d..10fa5b3ad 100644 --- a/application/controllers/organisation/Studiensemester.php +++ b/application/controllers/organisation/Studiensemester.php @@ -20,7 +20,7 @@ class Studiensemester extends Auth_Controller 'editStudiensemester' => 'basis/studiensemester:rw', 'newStudiensemester' => 'basis/studiensemester:rw', 'insStudiensemester' => 'basis/studiensemester:rw', - 'saveStudiensemester' => 'basis/studiensemester:rw', + 'updateStudiensemester' => 'basis/studiensemester:rw', 'deleteStudiensemester' => 'basis/studiensemester:rw' ) ); @@ -45,7 +45,7 @@ class Studiensemester extends Auth_Controller $semester = $this->StudiensemesterModel->load(); if ($semester->error) { - show_error($semester->retval); + show_error(getError($semester)); } $data = array( @@ -64,13 +64,13 @@ class Studiensemester extends Auth_Controller $semester = $this->StudiensemesterModel->load($semester_kurzbez); if ($semester->error) { - show_error($semester->retval); + show_error(getError($semester)); } $this->StudienjahrModel->addOrder('studienjahr_kurzbz', "DESC"); $allstudienjahre = $this->StudienjahrModel->load(); if ($allstudienjahre->error) { - show_error($allstudienjahre->retval); + show_error(getError($allstudienjahre)); } $data = array( "semester" => $semester->retval, @@ -90,7 +90,7 @@ class Studiensemester extends Auth_Controller $allstudienjahre = $this->StudienjahrModel->load(); if ($allstudienjahre->error) { - show_error($allstudienjahre->retval); + show_error(getError($allstudienjahre)); } $data = array( @@ -108,11 +108,16 @@ class Studiensemester extends Auth_Controller public function insStudiensemester() { $data = $this->__retrieveStudiensemesterData(); + + $studiensemester_exists = $this->StudiensemesterModel->load($data['studiensemester_kurzbz']); + if (hasData($studiensemester_exists)) + show_error("Studiensemester existiert bereits"); + $semester = $this->StudiensemesterModel->insert($data); if ($semester->error) { - show_error($semester->retval); + show_error(getError($semester)); } redirect("/organisation/studiensemester/editStudiensemester/".$data['studiensemester_kurzbz']."?saved=true"); @@ -156,7 +161,7 @@ class Studiensemester extends Auth_Controller return $data; } else { - show_error($validation->retval); + show_error(getError($validation)); } } @@ -185,14 +190,14 @@ class Studiensemester extends Auth_Controller * redirects to edit page after inserting * saved=true is a GET parameter passed for showing save message */ - public function saveStudiensemester() + public function updateStudiensemester() { $data = $this->__retrieveStudiensemesterData(); $semester = $this->StudiensemesterModel->update($data['studiensemester_kurzbz'], $data); if ($semester->error) { - show_error($semester->retval); + show_error(getError($semester)); } redirect("/organisation/studiensemester/editStudiensemester/".$data['studiensemester_kurzbz']."?saved=true"); @@ -209,10 +214,9 @@ class Studiensemester extends Auth_Controller if ($semester->error) { - show_error($semester->retval); + show_error(getError($semester)); } redirect("/organisation/studiensemester/listStudiensemester"); } - } diff --git a/application/controllers/person/BPKWartung.php b/application/controllers/person/BPKWartung.php index a8e9b8829..52cb09c5c 100644 --- a/application/controllers/person/BPKWartung.php +++ b/application/controllers/person/BPKWartung.php @@ -71,7 +71,7 @@ class BPKWartung extends Auth_Controller $personexists = $this->PersonModel->load($person_id); if (isError($personexists)) - show_error($personexists->retval); + show_error(getError($personexists)); if (!hasData($personexists)) show_error('Person does not exist!'); @@ -122,7 +122,7 @@ class BPKWartung extends Auth_Controller if (isError($stammdaten)) { - show_error($stammdaten->retval); + show_error(getError($stammdaten)); } if (!isset($stammdaten->retval)) @@ -132,7 +132,7 @@ class BPKWartung extends Auth_Controller if (isError($adresse)) { - show_error($adresse->retval); + show_error(getError($adresse)); } $data = array( diff --git a/application/controllers/person/Gradelist.php b/application/controllers/person/Gradelist.php index 70913061b..230c7f67f 100644 --- a/application/controllers/person/Gradelist.php +++ b/application/controllers/person/Gradelist.php @@ -28,6 +28,7 @@ class Gradelist extends Auth_Controller $this->load->model('education/zeugnisnote_model', 'ZeugnisnoteModel'); $this->load->model('education/lehrveranstaltung_model', 'LehrveranstaltungModel'); $this->load->model('codex/note_model', 'NoteModel'); + $this->load->model('education/lehrveranstaltung_model', 'LehrveranstaltungModel'); $this->loadPhrases( array( @@ -45,6 +46,9 @@ class Gradelist extends Auth_Controller $this->_grades[$row->note]['anmerkung'] = $row->anmerkung; $this->_grades[$row->note]['notenwert'] = $row->notenwert; } + $this->_grades['']['positiv'] = false; + $this->_grades['']['anmerkung'] = ''; + $this->_grades['']['notenwert'] = 0; } /** @@ -163,6 +167,14 @@ class Gradelist extends Auth_Controller 'studienplan_bezeichnung' => $stpl_bezeichnung, ); } + $result_zuordnung = $this->LehrveranstaltungModel->getLvsByStudent($uid, $row_status->studiensemester_kurzbz); + if(isSuccess($result_zuordnung) && hasData($result_zuordnung)) + { + $this->setZuordnung( + $result_zuordnung, + $courses['semester'][$row_status->studiensemester_kurzbz]['lvs'] + ); + } } // Load Grades and add to studyplan @@ -186,6 +198,7 @@ class Gradelist extends Auth_Controller if (!isset($row_noten->found)) { $result_lv = $this->LehrveranstaltungModel->load($row_noten->lehrveranstaltung_id); + $result_stg = $this->StudiengangModel->load($result_lv->retval[0]->studiengang_kz); $courses['semester'][$row_noten->studiensemester_kurzbz]['lvs_nonstpl'][] = array( 'lehrveranstaltung_id' => $row_noten->lehrveranstaltung_id, 'lehrtyp_kurzbz' => $result_lv->retval[0]->lehrtyp_kurzbz, @@ -194,13 +207,20 @@ class Gradelist extends Auth_Controller 'sws' => $result_lv->retval[0]->sws, 'zeugnis' => $result_lv->retval[0]->zeugnis, 'bezeichnung' => $result_lv->retval[0]->bezeichnung, + 'kurzbz' => $result_lv->retval[0]->kurzbz, 'ects' => $result_lv->retval[0]->ects, + 'semester' => $result_lv->retval[0]->semester, 'note' => $row_noten->note, - 'datum' => $row_noten->benotungsdatum + 'datum' => $row_noten->benotungsdatum, + 'zugeordnet' => true, + 'studiengang_kurzbz' => $result_stg->retval[0]->kurzbzlang ); if(!isset($courses['semester'][$row_noten->studiensemester_kurzbz]['data']['ectssumme_nonstpl'])) $courses['semester'][$row_noten->studiensemester_kurzbz]['data']['ectssumme_nonstpl'] = 0; + if(!isset($courses['semester'][$row_noten->studiensemester_kurzbz]['data']['swssumme_nonstpl'])) + $courses['semester'][$row_noten->studiensemester_kurzbz]['data']['swssumme_nonstpl'] = 0; $courses['semester'][$row_noten->studiensemester_kurzbz]['data']['ectssumme_nonstpl'] += $result_lv->retval[0]->ects; + $courses['semester'][$row_noten->studiensemester_kurzbz]['data']['swssumme_nonstpl'] += $result_lv->retval[0]->sws; } } @@ -210,6 +230,8 @@ class Gradelist extends Auth_Controller $num_grades_overall = 0; $sum_ects_overall = 0; $sum_ects_positiv_overall = 0; + $sum_sws_overall = 0; + $sum_sws_positiv_overall = 0; // Calculate Sum and Average foreach ($courses['semester'] as $stsem => $row_lvs) @@ -219,6 +241,8 @@ class Gradelist extends Auth_Controller $num_grades = 0; $sum_ects = 0; $sum_ects_positiv = 0; + $sum_sws = 0; + $sum_sws_positiv = 0; $sum_grades = 0; $notendurchschnitt = 0; $sum_gradeweighted = 0; @@ -235,8 +259,12 @@ class Gradelist extends Auth_Controller $sum_gradeweighted += $row['ects'] * $this->_grades[$row['note']]['notenwert']; } $sum_ects += $row['ects']; + $sum_sws += $row['sws']; if ($this->_grades[$row['note']]['positiv']) + { $sum_ects_positiv += $row['ects']; + $sum_sws_positiv += $row['sws']; + } } if ($num_grades > 0) $notendurchschnitt = $sum_grades / $num_grades; @@ -254,11 +282,15 @@ class Gradelist extends Auth_Controller $sum_ectsweighted_overall += $sum_ectsweighted; $sum_ects_overall += $sum_ects; $sum_ects_positiv_overall += $sum_ects_positiv; + $sum_sws_overall += $sum_sws; + $sum_sws_positiv_overall += $sum_sws_positiv; $courses['semester'][$stsem]['data']['notendurchschnitt'] = number_format($notendurchschnitt, 2); $courses['semester'][$stsem]['data']['notendurchschnittgewichtet'] = number_format($notendurchschnittgewichtet, 2); $courses['semester'][$stsem]['data']['ectssumme'] = number_format($sum_ects,2); - $courses['semester'][$stsem]['data']['ectssumme_positiv'] = number_formaT($sum_ects_positiv,2); + $courses['semester'][$stsem]['data']['ectssumme_positiv'] = number_format($sum_ects_positiv,2); + $courses['semester'][$stsem]['data']['swssumme'] = number_format($sum_sws,2); + $courses['semester'][$stsem]['data']['swssumme_positiv'] = number_format($sum_sws_positiv,2); } if ($num_grades_overall > 0) @@ -275,7 +307,9 @@ class Gradelist extends Auth_Controller 'notendurchschnitt' => number_format($notendurchschnitt, 2), 'notendurchschnittgewichtet' => number_format($notendurchschnittgewichtet, 2), 'ectssumme' => $sum_ects_overall, - 'ectssumme_positiv' => $sum_ects_positiv_overall + 'ectssumme_positiv' => $sum_ects_positiv_overall, + 'swssumme' => $sum_sws_overall, + 'swssumme_positiv' => $sum_sws_positiv_overall ); return $courses; } @@ -306,6 +340,37 @@ class Gradelist extends Auth_Controller } } + /** + * Checks if the Student is Assigned to this course and marks the course + * @param $zuordnung reference to array of all assigned courses. + * @param $courses reference to array of all courses. + * @param $studiensemester_kurzbz Studiensemester of the Course and Grades + */ + private function setZuordnung(&$zuordnung, &$courses) + { + $subtree_zugeordnet = false; + foreach ($courses as $key => $value) + { + foreach ($zuordnung->retval as $zuordnungkey => $row_zuordnung) + { + if ($row_zuordnung->lehrveranstaltung_id == $value['lehrveranstaltung_id']) + { + $courses[$key]['zugeordnet'] = true; + $subtree_zugeordnet = true; + } + if (isset($value['childs'])) + { + if ($this->setZuordnung($zuordnung, $courses[$key]['childs']) === true) + { + $courses[$key]['zugeordnet'] = true; + $subtree_zugeordnet = true; + } + } + } + } + return $subtree_zugeordnet; + } + /** * Reads all the Courses recursivly and Returns an Array with the Grades and ECTS * @param $courses array of courses @@ -320,7 +385,17 @@ class Gradelist extends Auth_Controller { $grades[] = array( 'note' => $row['note'], - 'ects' => $row['ects'] + 'ects' => $row['ects'], + 'sws' => $row['sws'] + ); + } + elseif (isset($row['zugeordnet']) && $row['zugeordnet'] == true && $row['lehrtyp_kurzbz']=='lv') + { + // ECTS und SWS mitzaehlen wenn die Person zugeordnet ist auch wenn noch keine Noten vorhanden ist. + $grades[] = array( + 'note' => '', + 'ects' => $row['ects'], + 'sws' => $row['sws'] ); } diff --git a/application/controllers/system/DBSkel.php b/application/controllers/system/DBSkel.php deleted file mode 100644 index 94ba18cf6..000000000 --- a/application/controllers/system/DBSkel.php +++ /dev/null @@ -1,26 +0,0 @@ -load->library('DBSkelLib'); - } - - /** - * Starts the DBSkel procedure - */ - public function start($step = null, $selectedDirectories = null) - { - // If the DBSkel procedure fails then exit with an error - // In this way it's possible to undestand from console what is the exit status of the procedure - $this->dbskellib->start($step, $selectedDirectories) === true ? exit(0) : exit(1); - } -} diff --git a/application/controllers/system/FASMessages.php b/application/controllers/system/FASMessages.php deleted file mode 100644 index 6928a919d..000000000 --- a/application/controllers/system/FASMessages.php +++ /dev/null @@ -1,191 +0,0 @@ - 'basis/message:rw', - 'writeReply' => 'basis/message:rw' - ) - ); - - // Loads the message library - $this->load->library('MessageLib'); - - // Loads the widget library - $this->load->library('WidgetLib'); - - $this->loadPhrases( - array( - 'global', - 'ui' - ) - ); - } - - // ----------------------------------------------------------------------------------------------------------------- - // Public methods - - /** - * Write a new message - */ - public function write($sender_id) - { - $prestudent_id = $this->input->post('prestudent_id'); // recipients prestudend_id(s) - - if (!is_numeric($sender_id)) - { - show_error('The current logged user person_id is not defined'); - } - - $msgVarsData = $this->_getMsgVarsData($prestudent_id); - - // Retrieves message vars for a person from view view vw_msg_vars_person - $variablesArray = $this->_getMessageVarsPerson(); - - // Organisation units used to get the templates - $oe_kurzbz = $this->_getOeKurzbz($sender_id); - - // Admin or commoner? - $isAdmin = $this->_getIsAdmin($sender_id); - - $data = array( - 'recipients' => getData($msgVarsData), - 'variables' => $variablesArray, - 'oe_kurzbz' => $oe_kurzbz, // used to get the templates - 'isAdmin' => $isAdmin - ); - - $this->load->view('system/messages/messageWrite', $data); - } - - /** - * Write a reply - */ - public function writeReply($sender_id, $msg_id, $receiver_id) - { - $prestudent_id = $this->input->post('prestudent_id'); // recipients prestudend_id(s) - - if (!is_numeric($sender_id)) - { - show_error('The current logged user person_id is not defined'); - } - - if (!is_numeric($msg_id)) - { - show_error('The msg_id must be a number'); - } - - if (!is_numeric($receiver_id)) - { - show_error('The receiver_id must be a number'); - } - - $msg = $this->_getMessage($msg_id, $receiver_id); - - $msgVarsData = $this->_getMsgVarsData($prestudent_id); - - // Retrieves message vars for a person from view view vw_msg_vars_person - $variablesArray = $this->_getMessageVarsPerson(); - - // Organisation units used to get the templates - $oe_kurzbz = $this->_getOeKurzbz($sender_id); - - // Admin or commoner? - $isAdmin = $this->_getIsAdmin($sender_id); - - $data = array( - 'recipients' => getData($msgVarsData), - 'message' => $msg, - 'variables' => $variablesArray, - 'oe_kurzbz' => $oe_kurzbz, // used to get the templates - 'isAdmin' => $isAdmin - ); - - $this->load->view('system/messages/messageWrite', $data); - } - - // ----------------------------------------------------------------------------------------------------------------- - // Private methods - - /** - * - */ - private function _getMessage($msg_id, $receiver_id) - { - $msg = $this->messagelib->getMessage($msg_id, $receiver_id); - if (isError($msg)) - { - show_error(getData($msg)); - } - elseif (!hasData($msg)) - { - show_error('The selected message does not exist'); - } - else - { - $msg = getData($msg)[0]; - } - - return $msg; - } - - /** - * Retrieves message vars from view vw_msg_vars - */ - private function _getMsgVarsData($prestudent_id) - { - $this->load->model('system/Message_model', 'MessageModel'); - $msgVarsData = $this->MessageModel->getMsgVarsDataByPrestudentId($prestudent_id); - - if (isError($msgVarsData)) - { - show_error(getData($msgVarsData)); - } - - return $msgVarsData; - } - - /** - * Wrapper method to call messagelib->getMessageVarsPerson - */ - private function _getMessageVarsPerson() - { - $variables = $this->messagelib->getMessageVarsPerson(); - - if (isError($variables)) show_error(getData($variables)); - - return getData($variables); - } - - /** - * Wrapper method to call messagelib->getOeKurzbz - */ - private function _getOeKurzbz($sender_id) - { - $oe_kurzbz = $this->messagelib->getOeKurzbz($sender_id); - - if (isError($oe_kurzbz)) show_error(getData($oe_kurzbz)); - - return getData($oe_kurzbz); - } - - /** - * Wrapper method to call messagelib->getIsAdmin - */ - private function _getIsAdmin($sender_id) - { - $isAdmin = $this->messagelib->getIsAdmin($sender_id); - - if (isError($isAdmin)) show_error(getData($isAdmin)); - - return getData($isAdmin); - } -} diff --git a/application/controllers/system/UDF.php b/application/controllers/system/FAS_UDF.php similarity index 66% rename from application/controllers/system/UDF.php rename to application/controllers/system/FAS_UDF.php index dafa3f8f7..cd78d64d2 100644 --- a/application/controllers/system/UDF.php +++ b/application/controllers/system/FAS_UDF.php @@ -2,8 +2,10 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); -class UDF extends Auth_Controller +class FAS_UDF extends Auth_Controller { + const FAS_UDF_SESSION_NAME = 'fasUdfSessionName'; + public function __construct() { parent::__construct( @@ -22,31 +24,33 @@ class UDF extends Auth_Controller */ public function index() { + $fasUdfSession = getSession(self::FAS_UDF_SESSION_NAME); + $person_id = $this->input->get('person_id'); - if (isset($this->session->person_id)) + if (isset($fasUdfSession['person_id'])) { if (!isset($person_id)) { - $person_id = $this->session->person_id; + $person_id = $fasUdfSession['person_id']; } - unset($this->session->person_id); + unset($fasUdfSession['person_id']); } $prestudent_id = $this->input->get('prestudent_id'); - if (isset($this->session->prestudent_id)) + if (isset($fasUdfSession['prestudent_id'])) { if (!isset($prestudent_id)) { - $prestudent_id = $this->session->prestudent_id; + $prestudent_id = $fasUdfSession['prestudent_id']; } - unset($this->session->prestudent_id); + unset($fasUdfSession['prestudent_id']); } $result = null; - if (isset($this->session->result)) + if (isset($fasUdfSession['result'])) { - $result = clone $this->session->result; - $this->session->set_userdata('result', null); + $result = clone $fasUdfSession['result']; + setSessionElement(self::FAS_UDF_SESSION_NAME, 'result', null); } $data = array('result' => $result); @@ -71,7 +75,7 @@ class UDF extends Auth_Controller } } - $this->load->view('system/udf', $data); + $this->load->view('system/fas_udf', $data); } /** @@ -90,9 +94,9 @@ class UDF extends Auth_Controller if (isSuccess($validation)) { // Load model UDF_model - $this->load->model('system/UDF_model', 'UDFModel'); + $this->load->model('system/FAS_UDF_model', 'FASUDFModel'); - $result = $this->UDFModel->saveUDFs($udfs); + $result = $this->FASUDFModel->saveUDFs($udfs); $userdata['result'] = $result; } @@ -101,8 +105,11 @@ class UDF extends Auth_Controller $userdata['result'] = $validation; } - $this->session->set_userdata($userdata); - redirect('system/UDF'); + setSessionElement(self::FAS_UDF_SESSION_NAME, 'person_id', $userdata['person_id']); + setSessionElement(self::FAS_UDF_SESSION_NAME, 'prestudent_id', $userdata['prestudent_id']); + setSessionElement(self::FAS_UDF_SESSION_NAME, 'result', $userdata['result']); + + redirect('system/FAS_UDF'); } /** diff --git a/application/controllers/system/LogsViewer.php b/application/controllers/system/LogsViewer.php new file mode 100644 index 000000000..8caf9f3a7 --- /dev/null +++ b/application/controllers/system/LogsViewer.php @@ -0,0 +1,44 @@ + 'system/developer:r' + ) + ); + + // Loads WidgetLib + $this->load->library('WidgetLib'); + + // Loads phrases system + $this->loadPhrases( + array( + 'global', + 'ui', + 'filter' + ) + ); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * Main page of the InfoCenter tool + */ + public function index() + { + $this->load->view('system/logs/logsViewer.php'); + } +} diff --git a/application/controllers/system/Messages.php b/application/controllers/system/Messages.php deleted file mode 100644 index ec630da1e..000000000 --- a/application/controllers/system/Messages.php +++ /dev/null @@ -1,210 +0,0 @@ - array('basis/message:rw', 'infocenter:rw'), - 'send' => array('basis/message:rw', 'infocenter:rw'), - 'sendJson' => array('basis/message:rw', 'infocenter:rw'), - 'getVorlage' => array('basis/message:r', 'infocenter:r'), - 'parseMessageText' => array('basis/message:r', 'infocenter:r'), - 'getMessageFromIds' => array('basis/message:r', 'infocenter:r') - ) - ); - - // Loads the message library - $this->load->library('MessageLib'); - - // Loads the widget library - $this->load->library('WidgetLib'); - - $this->load->model('system/Message_model', 'MessageModel'); - $this->load->model('CL/Messages_model', 'CLMessagesModel'); - - $this->loadPhrases( - array( - 'global', - 'ui' - ) - ); - } - - // ----------------------------------------------------------------------------------------------------------------- - // Public methods - - /** - * Write a new message - */ - public function write() - { - $person_id = $this->input->post('person_id'); - $sender_id = null; - - $authUser = $this->CLMessagesModel->getAuthUser(); - if (isError($authUser)) - { - show_error(getData($authUser)); - } - else - { - $sender_id = getData($authUser)[0]->person_id; - } - - $msgVarsData = $this->MessageModel->getMsgVarsDataByPersonId($person_id); - if (isError($msgVarsData)) show_error(getData($msgVarsData)); - - // Retrieves message vars for a person from view view vw_msg_vars_person - $variables = $this->messagelib->getMessageVarsPerson(); - if (isError($variables)) show_error(getData($variables)); - - // Organisation units used to get the templates - $oe_kurzbz = $this->messagelib->getOeKurzbz($sender_id); - if (isError($oe_kurzbz)) show_error(getData($oe_kurzbz)); - - // Admin or commoner? - $isAdmin = $this->messagelib->getIsAdmin($sender_id); - if (isError($isAdmin)) show_error(getData($isAdmin)); - - $data = array ( - 'recipients' => getData($msgVarsData), - 'variables' => getData($variables), - 'oe_kurzbz' => getData($oe_kurzbz), // used to get the templates - 'isAdmin' => getData($isAdmin) - ); - - $this->load->view('system/messages/messageWrite', $data); - } - - /** - * Send message - */ - public function send() - { - $persons = $this->input->post('persons'); - $relationmessage_id = $this->input->post('relationmessage_id'); - - $msgVarsData = $this->MessageModel->getMsgVarsDataByPersonId($persons); - - $send = $this->CLMessagesModel->send($msgVarsData, $relationmessage_id); - - $this->load->view('system/messages/messageSent', array('success' => isSuccess($send))); - } - - /** - * Send message, response is in JSON format - */ - public function sendJson() - { - $prestudents = $this->input->post('prestudents'); - $vorlage_kurzbz = $this->input->post('vorlage_kurzbz'); - $oe_kurzbz = $this->input->post('oe_kurzbz'); - $msgVars = $this->input->post('msgvars'); - - $msgVarsData = $this->MessageModel->getMsgVarsDataByPrestudentId($prestudents); - - $this->load->model('crm/Prestudent_model', 'PrestudentModel'); - $prestudentsData = $this->PrestudentModel->getOrganisationunits($prestudents); - - // Adds the organisation unit to each prestudent - if (isEmptyString($oe_kurzbz) && hasData($msgVarsData) && hasData($prestudentsData)) - { - $this->CLMessagesModel->addOeToPrestudents($msgVarsData, $prestudentsData); - } - - $send = $this->CLMessagesModel->send($msgVarsData, null, $oe_kurzbz, $vorlage_kurzbz, $msgVars); - if (isError($send)) - { - $this->outputJsonError(getData($send)); - } - else - { - $this->outputJsonSuccess(getData($send)); - } - } - - /** - * getVorlage - */ - public function getVorlage() - { - $vorlage_kurzbz = $this->input->get('vorlage_kurzbz'); - $result = null; - - if (!isEmptyString($vorlage_kurzbz)) - { - $this->load->model('system/Vorlagestudiengang_model', 'VorlagestudiengangModel'); - $this->VorlagestudiengangModel->addOrder('version','DESC'); - - $result = $this->VorlagestudiengangModel->loadWhere(array('vorlage_kurzbz' => $vorlage_kurzbz)); - } - else - { - $result = error('The given vorlage_kurzbz is not valid'); - } - - if (isError($result) || !hasData($result)) - { - $this->outputJsonError(getData($result)); - } - else - { - $this->outputJsonSuccess(getData($result)); - } - } - - /** - * parseMessageText - */ - public function parseMessageText() - { - $person_id = $this->input->get('person_id'); - $text = $this->input->get('text'); - $parsedText = ''; - $data = null; - - if (is_numeric($person_id)) - { - $data = $this->MessageModel->getMsgVarsDataByPersonId($person_id); - } - else - { - $data = error('The given person_id is not a valid number'); - } - - if (isError($data) || !hasData($data)) - { - $this->outputJsonError(getData($data)); - } - else - { - $parsedText = $this->messagelib->parseMessageText($text, $this->CLMessagesModel->replaceKeys((array)getData($data)[0])); - - $this->outputJsonSuccess($parsedText); - } - } - - /** - * Outputs message data for a message (identified my msg id and receiver id) in JSON format - * @param $msg_id - * @param $receiver_id - */ - public function getMessageFromIds() - { - $msg_id = $this->input->get('msg_id'); - $receiver_id = $this->input->get('receiver_id'); - - $msg = $this->messagelib->getMessage($msg_id, $receiver_id); - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(array(getData($msg)[0]))); - } -} diff --git a/application/controllers/system/Navigation.php b/application/controllers/system/Navigation.php index 1abf7d9a8..190f84acd 100644 --- a/application/controllers/system/Navigation.php +++ b/application/controllers/system/Navigation.php @@ -7,7 +7,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); * Provides data to the ajax get calls about the filter * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON */ -class Navigation extends Auth_Controller +class Navigation extends FHC_Controller { const NAVIGATION_PAGE_PARAM = 'navigation_page'; // Navigation page parameter name @@ -16,12 +16,9 @@ class Navigation extends Auth_Controller */ public function __construct() { - parent::__construct( - array( - 'menu' => 'basis/vilesci:r', - 'header' => 'basis/vilesci:r' - ) - ); + parent::__construct(); + + $this->load->library('AuthLib'); $this->_loadNavigationLib(); // Loads the NavigationLib with parameters } diff --git a/application/controllers/system/Phrases.php b/application/controllers/system/Phrases.php index 070750b7c..2bb003567 100644 --- a/application/controllers/system/Phrases.php +++ b/application/controllers/system/Phrases.php @@ -45,7 +45,7 @@ class Phrases extends Auth_Controller { $phrases = $this->phraseslib->getPhraseByApp('aufnahme'); if ($phrases->error) - show_error($phrases->retval); + show_error(getError($phrases)); $data = array( 'app' => 'aufnahme', @@ -67,7 +67,7 @@ class Phrases extends Auth_Controller $phrase_inhalt = $this->phraseslib->getPhraseInhalt($phrase_id); if ($phrase_inhalt->error) - show_error($phrase_inhalt->retval); + show_error(getError($phrase_inhalt)); $data = array( 'phrase_id' => $phrase_id, @@ -88,7 +88,7 @@ class Phrases extends Auth_Controller $phrase_inhalt = $this->phraseslib->delPhrasentext($phrasentext_id); if ($phrase_inhalt->error) - show_error($phrase_inhalt->retval); + show_error(getError($phrase_inhalt)); redirect('/system/Phrases/view/'.$phrase_id); } @@ -102,7 +102,7 @@ class Phrases extends Auth_Controller $phrase = $this->phraseslib->getPhrase($phrase_id); if ($phrase->error) - show_error($phrase->retval); + show_error(getError($phrase)); if (count($phrase->retval) != 1) show_error('Phrase nicht vorhanden! ID: '.$phrase_id); @@ -124,7 +124,7 @@ class Phrases extends Auth_Controller $phrase = $this->phraseslib->savePhrase($phrase_id, $data); if ($phrase->error) - show_error($phrase->retval); + show_error(getError($phrase)); $phrase_id = $phrase->retval; @@ -145,7 +145,7 @@ class Phrases extends Auth_Controller $resultOE = $this->OrganisationseinheitModel->loadWhere(array('aktiv' => true, 'oe_parent_kurzbz' => null)); if ($resultOE->error) - show_error($resultOE->retval); + show_error(getError($resultOE)); if (hasData($resultOE)) { @@ -161,7 +161,7 @@ class Phrases extends Auth_Controller $phrase_inhalt = $this->phraseslib->insertPhraseinhalt($data); if ($phrase_inhalt->error) - show_error($phrase_inhalt->retval); + show_error(getError($phrase_inhalt)); $phrase_inhalt_id = $phrase_inhalt->retval; @@ -180,7 +180,7 @@ class Phrases extends Auth_Controller { $phrase_inhalt = $this->phraseslib->getPhrasentextById($phrasentext_id); if ($phrase_inhalt->error) - show_error($phrase_inhalt->retval); + show_error(getError($phrase_inhalt)); $data = $phrase_inhalt->retval[0]; @@ -204,7 +204,7 @@ class Phrases extends Auth_Controller $phrase_inhalt = $this->phraseslib->updatePhraseInhalt($phrase_inhalt_id, $data); if ($phrase_inhalt->error) - show_error($phrase_inhalt->retval); + show_error(getError($phrase_inhalt)); redirect('/system/Phrases/editText/'.$phrase_inhalt_id); diff --git a/application/controllers/system/Variables.php b/application/controllers/system/Variables.php new file mode 100644 index 000000000..20303118b --- /dev/null +++ b/application/controllers/system/Variables.php @@ -0,0 +1,78 @@ + 'basis/variable:rw', + 'getVar' => 'basis/variable:rw', + 'changeStudiensemesterVar' => 'basis/variable:rw' + ) + ); + + $this->load->model('system/variable_model', 'VariableModel'); + + $this->_setAuthUID(); + + $this->load->library('VariableLib', array('uid' => $this->_uid)); + } + + /** + * Sets a user variable based on received post parameters, outputs JSON response. + */ + public function setVar() + { + $name = $this->input->post('name'); + $wert = $this->input->post('wert'); + + $result = $this->VariableModel->setVariable($this->_uid, $name, $wert); + + $this->outputJson($result); + } + + /** + * gets a user variable based on received post parameter, outputs JSON response. + */ + public function getVar() + { + $name = $this->input->get('name'); + $this->outputJson($this->VariableModel->getVariables($this->_uid, array($name))); + } + + /** + * Changes a user variable containing a Studiensemester based on received post parameters, outputs JSON response. + */ + public function changeStudiensemesterVar() + { + $name = $this->input->post('name'); + $change = $this->input->post('change'); + + $result = $this->variablelib->changeStudiensemesterVar($this->_uid, $name, $change); + + $this->outputJson($result); + } + + /** + * 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'); + } +} diff --git a/application/controllers/system/Vorlage.php b/application/controllers/system/Vorlage.php index 4712d0e68..7ae79c77f 100644 --- a/application/controllers/system/Vorlage.php +++ b/application/controllers/system/Vorlage.php @@ -49,7 +49,7 @@ class Vorlage extends Auth_Controller $vorlage = $this->vorlagelib->getVorlageByMimetype($mimetype); if ($vorlage->error) - show_error($vorlage->retval); + show_error(getError($vorlage)); $data = array ( 'mimetype' => $mimetype, @@ -66,7 +66,7 @@ class Vorlage extends Auth_Controller $vorlagentext = $this->vorlagelib->getVorlagetextByVorlage($vorlage_kurzbz); if ($vorlagentext->error) - show_error($vorlagentext->retval); + show_error(getError($vorlagentext)); $data = array ( 'vorlage_kurzbz' => $vorlage_kurzbz, @@ -83,7 +83,7 @@ class Vorlage extends Auth_Controller $vorlage = $this->vorlagelib->getVorlage($vorlage_kurzbz); if ($vorlage->error) - show_error($vorlage->retval); + show_error(getError($vorlage)); if (count($vorlage->retval) != 1) show_error('Nachricht nicht vorhanden! ID: '.$vorlage_kurzbz); @@ -119,7 +119,7 @@ class Vorlage extends Auth_Controller $vorlage = $this->vorlagelib->saveVorlage($vorlage_kurzbz, $data); if ($vorlage->error) - show_error($vorlage->retval); + show_error(getError($vorlage)); $vorlage_kurzbz = $vorlage->retval; @@ -137,7 +137,7 @@ class Vorlage extends Auth_Controller $resultOE = $this->OrganisationseinheitModel->loadWhere(array('aktiv' => true, 'oe_parent_kurzbz' => null)); if ($resultOE->error) - show_error($resultOE->retval); + show_error(getError($resultOE)); if (hasData($resultOE)) { @@ -153,7 +153,7 @@ class Vorlage extends Auth_Controller $vorlagetext = $this->vorlagelib->insertVorlagetext($data); if ($vorlagetext->error) - show_error($vorlagetext->retval); + show_error(getError($vorlagetext)); $vorlagestudiengang_id = $vorlagetext->retval; @@ -170,7 +170,7 @@ class Vorlage extends Auth_Controller $vorlagetext = $this->vorlagelib->getVorlagetextById($vorlagestudiengang_id); if ($vorlagetext->error) - show_error($vorlagetext->retval); + show_error(getError($vorlagetext)); $data = $vorlagetext->retval[0]; @@ -254,7 +254,7 @@ class Vorlage extends Auth_Controller $vorlagetext = $this->vorlagelib->updateVorlagetext($data['vorlagestudiengang_id'], $data); if ($vorlagetext->error) - show_error($vorlagetext->retval); + show_error(getError($vorlagetext)); redirect('/system/vorlage/editText/'.$data['vorlagestudiengang_id']); } @@ -266,10 +266,10 @@ class Vorlage extends Auth_Controller $vorlagetext = $this->vorlagelib->getVorlagetextById($vorlagestudiengang_id); if ($vorlagetext->error) - show_error($vorlagetext->retval); + show_error(getError($vorlagetext)); $data = array( - 'text' => $this->vorlagelib->parseVorlagetext($vorlagetext->retval[0]->text, $jsonDecodedForm) + 'text' => parseText($vorlagetext->retval[0]->text, $jsonDecodedForm) ); $this->load->view('system/vorlage/templatetextPreview', $data); diff --git a/application/controllers/system/aufnahme/PrestudentMultiAssign.php b/application/controllers/system/aufnahme/PrestudentMultiAssign.php index 30df81281..9906e83cb 100644 --- a/application/controllers/system/aufnahme/PrestudentMultiAssign.php +++ b/application/controllers/system/aufnahme/PrestudentMultiAssign.php @@ -61,7 +61,7 @@ class PrestudentMultiAssign extends Auth_Controller } else if (isError($returnUsers)) { - show_error($returnUsers->retval); + show_error(getError($returnUsers)); } } diff --git a/application/controllers/system/infocenter/InfoCenter.php b/application/controllers/system/infocenter/InfoCenter.php index 575f1f23b..92636e6df 100644 --- a/application/controllers/system/infocenter/InfoCenter.php +++ b/application/controllers/system/infocenter/InfoCenter.php @@ -24,6 +24,7 @@ class InfoCenter extends Auth_Controller const FILTER_ID = 'filter_id'; const PREV_FILTER_ID = 'prev_filter_id'; + const KEEP_TABLESORTER_FILTER = 'keepTsFilter'; private $_uid; // contains the UID of the logged user @@ -65,6 +66,14 @@ class InfoCenter extends Auth_Controller ) ); + // Name of Interessentenstatus + const INTERESSENTSTATUS = 'Interessent'; + const ABGEWIESENERSTATUS = 'Abgewiesener'; + const BEWERBERSTATUS = 'Bewerber'; + + // Statusgruende for which no Studiengangsfreigabemessage should be sent + private $_statusgruendeNoStgFreigabeMessage = array('FIT Programm', 'FIT program', 'FIT programme'); + /** * Constructor */ @@ -93,9 +102,11 @@ class InfoCenter extends Auth_Controller 'reloadNotizen' => 'infocenter:r', 'reloadLogs' => 'infocenter:r', 'outputAkteContent' => 'infocenter:r', - 'getParkedDate' => 'infocenter:r', + 'getPostponeDate' => 'infocenter:r', 'park' => 'infocenter:rw', 'unpark' => 'infocenter:rw', + 'setOnHold' => 'infocenter:rw', + 'removeOnHold' => 'infocenter:rw', 'getStudienjahrEnd' => 'infocenter:r', 'setNavigationMenuArrayJson' => 'infocenter:r' ) @@ -129,6 +140,8 @@ class InfoCenter extends Auth_Controller $this->_setAuthUID(); // sets property uid + $this->load->library('VariableLib', array('uid' => $this->_uid)); + $this->setControllerId(); // sets the controller id } @@ -168,7 +181,6 @@ class InfoCenter extends Auth_Controller /** * Personal details page of the InfoCenter tool * Initialization function, gets person and prestudent data and loads the view with the data - * @param $person_id */ public function showDetails() { @@ -182,7 +194,7 @@ class InfoCenter extends Auth_Controller $personexists = $this->PersonModel->load($person_id); if (isError($personexists)) - show_error($personexists->retval); + show_error(getError($personexists)); if (!hasData($personexists)) show_error('Person does not exist!'); @@ -193,8 +205,7 @@ class InfoCenter extends Auth_Controller // mark person as locked for editing $result = $this->PersonLockModel->lockPerson($person_id, $this->_uid, self::APP); - if (isError($result)) - show_error($result->retval); + if (isError($result)) show_error(getError($result)); } $persondata = $this->_loadPersonData($person_id); @@ -220,13 +231,12 @@ class InfoCenter extends Auth_Controller { $result = $this->PersonLockModel->unlockPerson($person_id, self::APP); - if (isError($result)) - show_error($result->retval); + if (isError($result)) show_error(getError($result)); $redirectLink = '/'.self::INFOCENTER_URI.'?'.self::FHC_CONTROLLER_ID.'='.$this->getControllerId(); // Force reload of Dataset after Unlock - $redirectLink .= '&reloadDataset=true'; + $redirectLink .= '&'.self::KEEP_TABLESORTER_FILTER.'=true'; $currentFilterId = $this->input->get(self::FILTER_ID); if (isset($currentFilterId)) @@ -343,7 +353,6 @@ class InfoCenter extends Auth_Controller /** * Saves a ZGV for a prestudent, includes Ort, Datum, Nation for bachelor and master - * @param $prestudent_id */ public function saveZgvPruefung() { @@ -372,7 +381,7 @@ class InfoCenter extends Auth_Controller $zgvmadatum = isEmptyString($zgvmadatum) ? null : date_format(date_create($zgvmadatum), 'Y-m-d'); $zgvmanation_code = $this->input->post('zgvmanation') === 'null' ? null : $this->input->post('zgvmanation'); - $lastStatus = $this->PrestudentstatusModel->getLastStatus($prestudent_id, '', 'Interessent'); + $lastStatus = $this->PrestudentstatusModel->getLastStatus($prestudent_id, '', self::INTERESSENTSTATUS); $semresult = null; @@ -423,7 +432,6 @@ class InfoCenter extends Auth_Controller /** * Saves Absage for Prestudent including the reason for the Absage (statusgrund). * inserts Studiensemester and Ausbildungssemester for the new Absage of (chronologically) last status. - * @param $prestudent_id */ public function saveAbsage() { @@ -439,7 +447,7 @@ class InfoCenter extends Auth_Controller if (hasData($lastStatus) && hasData($statusgrresult)) { //check if still Interessent and not freigegeben yet - if ($lastStatus->retval[0]->status_kurzbz === 'Interessent' && !isset($lastStatus->retval[0]->bestaetigtam)) + if ($lastStatus->retval[0]->status_kurzbz === self::INTERESSENTSTATUS && !isset($lastStatus->retval[0]->bestaetigtam)) { $result = $this->PrestudentstatusModel->insert( array( @@ -449,7 +457,7 @@ class InfoCenter extends Auth_Controller 'datum' => date('Y-m-d'), 'orgform_kurzbz' => $lastStatus->retval[0]->orgform_kurzbz, 'studienplan_id' => $lastStatus->retval[0]->studienplan_id, - 'status_kurzbz' => 'Abgewiesener', + 'status_kurzbz' => self::ABGEWIESENERSTATUS, 'statusgrund_id' => $statusgrund, 'insertvon' => $this->_uid, 'insertamum' => date('Y-m-d H:i:s') @@ -475,7 +483,6 @@ class InfoCenter extends Auth_Controller /** * Saves Freigabe of a Prestudent to the Studiengang. * updates bestaetigtam and bestaetigtvon fields of the last status - * @param $prestudent_id */ public function saveFreigabe() { @@ -487,14 +494,16 @@ class InfoCenter extends Auth_Controller $logdata = $this->_getPersonAndStudiengangFromPrestudent($prestudent_id); - $akteresult = $this->AkteModel->loadWhere(array('person_id' => $logdata['person_id'], 'formal_geprueft_amum !=' => NULL)); + $person_id = $logdata['person_id']; + + $akteresult = $this->AkteModel->loadWhere(array('person_id' => $person_id, 'formal_geprueft_amum !=' => NULL)); if (hasData($lastStatus) && isSuccess($akteresult)) { $lastStatus = $lastStatus->retval[0]; //check if still Interessent and not freigegeben yet - if ($lastStatus->status_kurzbz === 'Interessent' && !isset($lastStatus->bestaetigtam)) + if ($lastStatus->status_kurzbz === self::INTERESSENTSTATUS && !isset($lastStatus->bestaetigtam)) { $statusdata = array( 'bestaetigtvon' => $this->_uid, @@ -523,6 +532,8 @@ class InfoCenter extends Auth_Controller if (isSuccess($result)) { $this->load->model('crm/Dokumentprestudent_model', 'DokumentprestudentModel'); + $json->retval['nonCriticalErrors'] = array(); + $json->retval['infoMessages'] = array(); //set documents which have been formal geprüft to accepted $dokument_kurzbzs = array(); @@ -536,7 +547,7 @@ class InfoCenter extends Auth_Controller // acceptresult returns null if no documents to accept if ($acceptresult !== null && isError($acceptresult)) - $json->retval['nonCriticalErrors'] = 'error when accepting documents in FAS'; + $json->retval['nonCriticalErrors'][] = 'error when accepting documents in FAS'; $logparams = array($prestudent_id, $logdata['studiengang_kurzbz'], ''); @@ -548,8 +559,69 @@ class InfoCenter extends Auth_Controller if (hasData($statusgrund_kurzbz)) $logparams[2] = ', confirmation type '.$statusgrund_kurzbz->retval[0]->bezeichnung_mehrsprachig[0]; } + else + { + // check if there is already a Bewerberstatus and Reihungsverfahren already absolviert + $bewerber = $this->PersonModel->hasBewerber($person_id, $lastStatus->studiensemester_kurzbz, 'b'); - $this->_log($logdata['person_id'], 'freigegeben', $logparams); + if (hasData($bewerber)) + { + $bewerbercnt = getData($bewerber); + + if (is_numeric($bewerbercnt[0]->anzahl_bewerber) && $bewerbercnt[0]->anzahl_bewerber > 0) + { + // then insert Bewerberstatus and rt absolviert, teilgenommen for prestudent + $bewerberresult = $this->PrestudentstatusModel->insert( + array( + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => self::BEWERBERSTATUS, + 'studiensemester_kurzbz' => $lastStatus->studiensemester_kurzbz, + 'ausbildungssemester' => $lastStatus->ausbildungssemester, + 'datum' => date('Y-m-d'), + 'orgform_kurzbz' => $lastStatus->orgform_kurzbz, + 'studienplan_id' => $lastStatus->studienplan_id, + 'insertvon' => $this->_uid, + 'insertamum' => date('Y-m-d H:i:s') + ) + ); + + if (isError($bewerberresult)) + $json->retval['nonCriticalErrors'][] = 'error when inserting Bewerberstatus'; + + $rtangetretenres = $this->PrestudentModel->update( + $prestudent_id, + array( + 'reihungstestangetreten' => true + ) + ); + + if (isError($rtangetretenres)) + { + $json->retval['nonCriticalErrors'][] = 'error when setting reihungstestangetreten'; + } + else + { + $json->retval['infoMessages'][] = $this->p->t('infocenter', 'rtPunkteEintragenInfo'); + $this->load->model('crm/RtPerson_model', 'RtPersonModel'); + + $rtteilgenommenres = $this->RtPersonModel->update( + array( + 'person_id' => $person_id, + 'studienplan_id' => $lastStatus->studienplan_id + ), + array( + 'teilgenommen' => true + ) + ); + + if (isError($rtteilgenommenres)) + $json->retval['nonCriticalErrors'][] = 'error when setting reihungstest teilgenommen'; + } + } + } + } + + $this->_log($person_id, 'freigegeben', $logparams); $this->_sendFreigabeMail($prestudent_id); } @@ -596,7 +668,6 @@ class InfoCenter extends Auth_Controller /** * Updates a new Notiz for a person * @param int $notiz_id - * @param int $person_id */ public function updateNotiz($notiz_id) { @@ -644,7 +715,7 @@ class InfoCenter extends Auth_Controller public function reloadMessages($person_id) { $messages = $this->MessageModel->getMessagesOfPerson($person_id, 1); - $this->load->view('system/messages/messageList.php', array('messages' => $messages->retval)); + $this->load->view('system/infocenter/messageList.php', array('messages' => $messages->retval)); } /** @@ -657,7 +728,7 @@ class InfoCenter extends Auth_Controller if (isError($notizen)) { - show_error($notizen->retval); + show_error(getError($notizen)); } $this->load->view('system/infocenter/notizen.php', array('notizen' => $notizen->retval)); @@ -685,14 +756,14 @@ class InfoCenter extends Auth_Controller if (isError($akte)) { - show_error($akte->retval); + show_error(getError($akte)); } $aktecontent = $this->dmslib->getAkteContent($akte_id); if (isError($aktecontent)) { - show_error($aktecontent->retval); + show_error(getError($aktecontent)); } $this->output @@ -707,11 +778,32 @@ class InfoCenter extends Auth_Controller * Gets the date until which a person is parked * @param $person_id */ - public function getParkedDate($person_id) + public function getPostponeDate($person_id) { + $result = array( + 'type' => null, + 'date' => null + ); + $parkedDate = $this->personloglib->getParkedDate($person_id); - $this->outputJsonSuccess(array($parkedDate)); + if (isset($parkedDate)) + { + $result['type'] = 'parked'; + $result['date'] = $parkedDate; + } + else + { + $onholdDate = $this->personloglib->getOnHoldDate($person_id); + + if (isset($onholdDate)) + { + $result['type'] = 'onhold'; + $result['date'] = $onholdDate; + } + } + + $this->outputJsonSuccess($result); } /** @@ -739,6 +831,31 @@ class InfoCenter extends Auth_Controller $this->outputJson($result); } + /** + * Sets a person on hold ("zurückstellen") + */ + public function setOnHold() + { + $person_id = $this->input->post('person_id'); + $date = $this->input->post('onholddate'); + + $result = $this->personloglib->setOnHold($person_id, date_format(date_create($date), 'Y-m-d'), self::TAETIGKEIT, self::APP, null, $this->_uid); + + $this->outputJson($result); + } + + /** + * Removed on hold status of a person + */ + public function removeOnHold() + { + $person_id = $this->input->post('person_id'); + + $result = $this->personloglib->removeOnHold($person_id); + + $this->outputJson($result); + } + /** * Gets the End date of the current Studienjahr */ @@ -889,6 +1006,7 @@ class InfoCenter extends Auth_Controller $freigegebenLink = site_url(self::INFOCENTER_URI.'/'.self::FREIGEGEBEN_PAGE); $reihungstestAbsolviertLink = site_url(self::INFOCENTER_URI.'/'.self::REIHUNGSTESTABSOLVIERT_PAGE); + $currentFilterId = $this->input->get(self::FILTER_ID); if (isset($currentFilterId)) { @@ -946,7 +1064,7 @@ class InfoCenter extends Auth_Controller $origin_page = $this->input->get(self::ORIGIN_PAGE); - $link = site_url(self::INFOCENTER_URI.'/'.self::INDEX_PAGE); + $link = site_url(self::INFOCENTER_URI); if ($origin_page == self::FREIGEGEBEN_PAGE) { $link = site_url(self::INFOCENTER_URI.'/'.self::FREIGEGEBEN_PAGE); @@ -959,7 +1077,7 @@ class InfoCenter extends Auth_Controller $prevFilterId = $this->input->get(self::PREV_FILTER_ID); if (isset($prevFilterId)) { - $link .= '?'.self::FILTER_ID.'='.$prevFilterId; + $link .= '?'.self::FILTER_ID.'='.$prevFilterId.'&'.self::KEEP_TABLESORTER_FILTER.'=true'; } $this->navigationlib->setSessionMenu( @@ -1110,7 +1228,7 @@ class InfoCenter extends Auth_Controller if (isError($locked)) { - show_error($locked->retval); + show_error(getError($locked)); } $lockedby = null; @@ -1129,7 +1247,7 @@ class InfoCenter extends Auth_Controller if (isError($stammdaten)) { - show_error($stammdaten->retval); + show_error(getError($stammdaten)); } if (!isset($stammdaten->retval)) @@ -1139,21 +1257,21 @@ class InfoCenter extends Auth_Controller if (isError($dokumente)) { - show_error($dokumente->retval); + show_error(getError($dokumente)); } $dokumente_nachgereicht = $this->AkteModel->getAktenWithDokInfo($person_id, null, true); if (isError($dokumente_nachgereicht)) { - show_error($dokumente_nachgereicht->retval); + show_error(getError($dokumente_nachgereicht)); } $messages = $this->MessageModel->getMessagesOfPerson($person_id, 1); if (isError($messages)) { - show_error($messages->retval); + show_error(getError($messages)); } $logs = $this->personloglib->getLogs($person_id); @@ -1162,21 +1280,21 @@ class InfoCenter extends Auth_Controller if (isError($notizen)) { - show_error($notizen->retval); + show_error(getError($notizen)); } $notizen_bewerbung = $this->NotizModel->getNotizByTitel($person_id, 'Anmerkung zur Bewerbung%'); if (isError($notizen_bewerbung)) { - show_error($notizen_bewerbung->retval); + show_error(getError($notizen_bewerbung)); } $user_person = $this->PersonModel->getByUid($this->_uid); if (isError($user_person)) { - show_error($user_person->retval); + show_error(getError($user_person)); } $data = array ( @@ -1207,47 +1325,82 @@ class InfoCenter extends Auth_Controller if (isError($prestudenten)) { - show_error($prestudenten->retval); + show_error(getError($prestudenten)); } - $interessentenCount = array(); - foreach ($prestudenten->retval as $prestudent) { - $prestudent = $this->PrestudentModel->getPrestudentWithZgv($prestudent->prestudent_id); + $prestudentWithZgv = $this->PrestudentModel->getPrestudentWithZgv($prestudent->prestudent_id); - if (isError($prestudent)) + if (isError($prestudentWithZgv)) { - show_error($prestudent->retval); + show_error(getError($prestudentWithZgv)); } - $zgvpruefung = $prestudent->retval[0]; + $zgvpruefung = $prestudentWithZgv->retval[0]; if (isset($zgvpruefung->prestudentstatus)) { + //get orgform for german and english + if (isset($zgvpruefung->prestudentstatus->bezeichnung_orgform) && is_array($zgvpruefung->prestudentstatus->bezeichnung_orgform)) + { + $zgvpruefung->prestudentstatus->bezeichnung_orgform_german = getPhraseByLanguage($zgvpruefung->prestudentstatus->bezeichnung_orgform, 'German'); + $zgvpruefung->prestudentstatus->bezeichnung_orgform_english = getPhraseByLanguage($zgvpruefung->prestudentstatus->bezeichnung_orgform, 'English'); + } + $position = strpos($zgvpruefung->prestudentstatus->anmerkung, 'Alt:'); //parse Anmerkung for Alternative (Prio is given in orgform and sprache anyway) $zgvpruefung->prestudentstatus->alternative = is_numeric($position) ? substr($zgvpruefung->prestudentstatus->anmerkung, $position) : null; } //if prestudent is not interessent or is already bestaetigt, then show only as information, non-editable - $zgvpruefung->infoonly = !isset($zgvpruefung->prestudentstatus) || isset($zgvpruefung->prestudentstatus->bestaetigtam) || $zgvpruefung->prestudentstatus->status_kurzbz != 'Interessent'; + $zgvpruefung->infoonly = !isset($zgvpruefung->prestudentstatus) + || isset($zgvpruefung->prestudentstatus->bestaetigtam) + || $zgvpruefung->prestudentstatus->status_kurzbz != self::INTERESSENTSTATUS; - //numeric application priority + //wether prestudent was freigegeben for RT/Stg + $zgvpruefung->isRtFreigegeben = false; + $zgvpruefung->isStgFreigegeben = false; + $zgvpruefung->sendStgFreigabeMsg = true;//wether Stgudiengangfreigabemessage can be sent (for "exceptions", Studiengänge with no message sending) + $this->PrestudentstatusModel->addSelect('bestaetigtam, statusgrund_id, tbl_status_grund.bezeichnung_mehrsprachig AS bezeichnung_statusgrund'); + $this->PrestudentstatusModel->addJoin('public.tbl_status_grund', 'statusgrund_id', 'LEFT'); + $isFreigegeben = $this->PrestudentstatusModel->loadWhere(array('studiensemester_kurzbz' => $zgvpruefung->prestudentstatus->studiensemester_kurzbz, + 'tbl_prestudentstatus.status_kurzbz' => self::INTERESSENTSTATUS, 'prestudent_id' => $prestudent->prestudent_id)); + + + if (hasData($isFreigegeben)) + { + foreach ($isFreigegeben->retval as $prestudentstatus) + { + if (isset($prestudentstatus->bestaetigtam)) + { + //if statusgrund set - RTfreigabe, otherwise Stgfreigabe + if (isset($prestudentstatus->statusgrund_id)) + { + if (isset($prestudentstatus->bezeichnung_statusgrund[0]) + && in_array($prestudentstatus->bezeichnung_statusgrund[0], $this->_statusgruendeNoStgFreigabeMessage)) + $zgvpruefung->sendStgFreigabeMsg = false; + else + $zgvpruefung->isStgFreigegeben = true; + + } + else + $zgvpruefung->isRtFreigegeben = true; + } + } + } + + //application priority change possible? $zgvpruefung->changeup = false; $zgvpruefung->changedown = false; - if (isset($zgvpruefung->prestudentstatus->status_kurzbz) && $zgvpruefung->prestudentstatus->status_kurzbz == 'Interessent') + if (isset($zgvpruefung->prestudentstatus->status_kurzbz) && $zgvpruefung->prestudentstatus->status_kurzbz == self::INTERESSENTSTATUS) { if (isset($zgvpruefung->prestudentstatus->studiensemester_kurzbz)) { $studiensemester = $zgvpruefung->prestudentstatus->studiensemester_kurzbz; $zgvpruefung->changeup = $this->PrestudentModel->checkPrioChange($zgvpruefung->prestudent_id, $studiensemester, -1); $zgvpruefung->changedown = $this->PrestudentModel->checkPrioChange($zgvpruefung->prestudent_id, $studiensemester, 1); - if (array_key_exists($studiensemester, $interessentenCount)) - $interessentenCount[$studiensemester]++; - else - $interessentenCount[$studiensemester] = 1; } } @@ -1256,8 +1409,8 @@ class InfoCenter extends Auth_Controller $this->_sortPrestudents($zgvpruefungen); - $abwstatusgruende = $this->StatusgrundModel->loadWhere(array('status_kurzbz' => 'Abgewiesener'))->retval; - $intstatusgruende = $this->StatusgrundModel->loadWhere(array('status_kurzbz' => 'Interessent'))->retval; + $abwstatusgruende = $this->StatusgrundModel->loadWhere(array('status_kurzbz' => self::ABGEWIESENERSTATUS))->retval; + $intstatusgruende = $this->StatusgrundModel->loadWhere(array('status_kurzbz' => self::INTERESSENTSTATUS))->retval; $data = array ( 'zgvpruefungen' => $zgvpruefungen, @@ -1289,13 +1442,13 @@ class InfoCenter extends Auth_Controller $starta = $this->StudiensemesterModel->load($a->prestudentstatus->studiensemester_kurzbz); if (!hasData($starta)) { - show_error($starta->retval); + show_error(getError($starta)); } $startb = $this->StudiensemesterModel->load($b->prestudentstatus->studiensemester_kurzbz); if (!hasData($startb)) { - show_error($startb->retval); + show_error(getError($startb)); } $starta = date_format(date_create($starta->retval[0]->start), 'Y-m-d'); @@ -1315,9 +1468,9 @@ class InfoCenter extends Auth_Controller return 1; elseif ($a->prestudentstatus->status_kurzbz !== $b->prestudentstatus->status_kurzbz) { - if ($a->prestudentstatus->status_kurzbz === 'Interessent') + if ($a->prestudentstatus->status_kurzbz === self::INTERESSENTSTATUS) return -1; - elseif ($b->prestudentstatus->status_kurzbz === 'Interessent') + elseif ($b->prestudentstatus->status_kurzbz === self::INTERESSENTSTATUS) return 1; } } @@ -1367,7 +1520,7 @@ class InfoCenter extends Auth_Controller if (isError($prestudent)) { - show_error($prestudent->retval); + show_error(getError($prestudent)); } $person_id = $prestudent->retval[0]->person_id; @@ -1409,7 +1562,7 @@ class InfoCenter extends Auth_Controller } /** - * Sends infomail with prestudent and person data when Prestudent is freigegeben + * Sends infomail to Studiengang with prestudent and person data when Prestudent is freigegeben * @param $prestudent_id */ private function _sendFreigabeMail($prestudent_id) diff --git a/application/controllers/system/messages/FASMessages.php b/application/controllers/system/messages/FASMessages.php new file mode 100644 index 000000000..55d1da25f --- /dev/null +++ b/application/controllers/system/messages/FASMessages.php @@ -0,0 +1,60 @@ + 'basis/message:rw', + 'writeReplyTemplate' => 'basis/message:rw' + ) + ); + + // Loads model CLMessagesModel which contains the GUI logic + $this->load->model('CL/Messages_model', 'CLMessagesModel'); + + // Phrases used in loaded views + $this->loadPhrases( + array( + 'global', + 'ui' + ) + ); + } + + /** + * Writes a new message to a prestudent using templates + */ + public function writeTemplate() + { + $prestudents = $this->input->post('prestudent_id'); // recipients prestudend_id(s) + + // Loads the view to write a new message with a template + $this->load->view( + 'system/messages/htmlWriteTemplate', + $this->CLMessagesModel->prepareHtmlWriteTemplatePrestudents($prestudents) + ); + } + + /** + * Writes a reply to a message identified by parameters $message_id and $recipient_id + * The recipient is a prestudent + * Uses templates + */ + public function writeReplyTemplate($message_id, $recipient_id) + { + $prestudents = $this->input->post('prestudent_id'); // recipients prestudend_id(s) + + // Loads the view to write a new message with a template + $this->load->view( + 'system/messages/htmlWriteTemplate', + $this->CLMessagesModel->prepareHtmlWriteTemplatePrestudents($prestudents, $message_id, $recipient_id) + ); + } +} diff --git a/application/controllers/system/messages/MessageClient.php b/application/controllers/system/messages/MessageClient.php new file mode 100644 index 000000000..a0cc5c518 --- /dev/null +++ b/application/controllers/system/messages/MessageClient.php @@ -0,0 +1,112 @@ +load->library('AuthLib'); + + // Loads model CLMessagesModel which contains the GUI logic + $this->load->model('CL/Messages_model', 'CLMessagesModel'); + + // Phrases used in loaded views + $this->loadPhrases( + array( + 'global', + 'ui' + ) + ); + } + + /** + * Starts the GUI used to read all the personal messages + */ + public function read() + { + // Loads the view to read messages + $this->load->view('system/messages/ajaxRead'); + } + + /** + * Starts the GUI used to write a personal message to an organisation unit + */ + public function write() + { + // Loads the view to write a message + $this->load->view('system/messages/ajaxWrite', $this->CLMessagesModel->prepareAjaxWrite()); + } + + /** + * Starts the GUI used to reply to a received personal message + */ + public function writeReply() + { + $token = $this->input->get('token'); + + // Loads the view to reply to a message + $this->load->view('system/messages/ajaxWriteReply', $this->CLMessagesModel->prepareAjaxWriteReply($token)); + } + + /** + * Returns JSON that that contains all the received messages by the currently logged user + */ + public function listReceivedMessages() + { + $this->outputJson($this->CLMessagesModel->prepareAjaxReadReceived()); + } + + /** + * Returns JSON that that contains all the sent messages by the currently logged user + */ + public function listSentMessages() + { + $this->outputJson($this->CLMessagesModel->prepareAjaxReadSent()); + } + + /** + * Sends a message to an organisation unit + */ + public function sendMessageToOU() + { + $receiverOU = $this->input->post('receiverOU'); + $subject = $this->input->post('subject'); + $body = $this->input->post('body'); + + $this->outputJson($this->CLMessagesModel->sendToOrganisationUnit($receiverOU, $subject, $body)); + } + + /** + * Sends a message to an organisation unit + */ + public function sendMessageReply() + { + $receiver_id = $this->input->post('receiver_id'); + $relationmessage_id = $this->input->post('relationmessage_id'); + $token = $this->input->post('token'); + $subject = $this->input->post('subject'); + $body = $this->input->post('body'); + + $this->outputJson($this->CLMessagesModel->sendReply($receiver_id, $subject, $body, $relationmessage_id, $token)); + } + + /** + * Set a message as read + */ + public function setMessageRead() + { + $message_id = $this->input->post('message_id'); + $statusPersonId = $this->input->post('statusPersonId'); + + $this->outputJson($this->CLMessagesModel->setMessageRead($message_id, $statusPersonId)); + } +} diff --git a/application/controllers/system/messages/Messages.php b/application/controllers/system/messages/Messages.php new file mode 100644 index 000000000..296022ca4 --- /dev/null +++ b/application/controllers/system/messages/Messages.php @@ -0,0 +1,144 @@ + array('basis/message:rw', 'infocenter:rw'), + 'sendImplicitTemplate' => array('basis/message:rw', 'infocenter:rw'), + 'sendExplicitTemplateJson' => array('basis/message:rw', 'infocenter:rw'), + 'getVorlage' => array('basis/message:r', 'infocenter:r'), + 'parseMessageText' => array('basis/message:r', 'infocenter:r'), + 'getMessageFromIds' => array('basis/message:r', 'infocenter:r') + ) + ); + + // Loads model CLMessagesModel which contains the GUI logic + $this->load->model('CL/Messages_model', 'CLMessagesModel'); + + // Phrases used in loaded views + $this->loadPhrases( + array( + 'global', + 'ui' + ) + ); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Methods with HTML output + + /** + * Initialize all the parameters used by view system/messages/htmlWriteTemplate + * to build a GUI used to write a messate to user/s using a template + */ + public function writeTemplate() + { + $persons = $this->input->post('person_id'); + + // Loads the view to write a new message with a template + $this->load->view( + 'system/messages/htmlWriteTemplate', + $this->CLMessagesModel->prepareHtmlWriteTemplatePersons($persons) + ); + } + + /** + * Send a new message or reply to user/s + * If a relationmessage_id this message is a reply to another one + * Body is a template and will be parsed using information present in persons parameter + */ + public function sendImplicitTemplate() + { + $subject = $this->input->post('subject'); + $body = $this->input->post('body'); + $recipients_ids = $this->input->post('recipients_ids'); + $relationmessage_id = $this->input->post('relationmessage_id'); + $type = $this->input->post('type'); + + $sendImplicitTemplate = $this->CLMessagesModel->sendImplicitTemplate($type, $recipients_ids, $subject, $body, $relationmessage_id); + if (isSuccess($sendImplicitTemplate)) + { + $this->load->view('system/messages/htmlMessageSentSuccess'); + } + else + { + $this->load->view('system/messages/htmlMessageSentError'); + } + } + + // ----------------------------------------------------------------------------------------------------------------- + // Methods with JSON output called by this controller and FASMessages (view system/messages/htmlWriteTemplate) + + /** + * Returns an object that represent a template store in database + * If no templates are found with the given parameter or the given parameter is an empty string, + * then an error is returned + */ + public function getVorlage() + { + $vorlage_kurzbz = $this->input->get('vorlage_kurzbz'); + + $this->outputJson($this->CLMessagesModel->getVorlage($vorlage_kurzbz)); + } + + /** + * Parse the given given text using data from the given user + * Use the CI parser which performs simple text substitution for pseudo-variable + */ + public function parseMessageText() + { + $receiver_id = $this->input->post('receiver_id'); + $text = $this->input->post('text'); + $type = $this->input->post('type'); + + if ($type == Messages_model::TYPE_PERSONS) + { + $this->outputJson($this->CLMessagesModel->parseMessageTextPerson($receiver_id, $text)); + } + elseif ($type == Messages_model::TYPE_PRESTUDENTS) + { + $this->outputJson($this->CLMessagesModel->parseMessageTextPrestudent($receiver_id, $text)); + } + else + { + $this->outputJsonError('Not a person nor a prestudent was provided'); + } + } + + // ----------------------------------------------------------------------------------------------------------------- + // Methods with JSON output called by infocenter + + /** + * Outputs message data for a message (identified my msg id and receiver id) in JSON format + */ + public function getMessageFromIds() + { + $message_id = $this->input->get('msg_id'); + $receiver_id = $this->input->get('receiver_id'); + + $this->outputJson($this->CLMessagesModel->getMessageFromIds($message_id, $receiver_id)); + } + + /** + * Send a new message + * - The recipients are prestudents + * - An email template with message var may be provided + * - A global organisation unit may be provided, otherwise is used the prestudent one + * - A template is explicitly specified + */ + public function sendExplicitTemplateJson() + { + $prestudents = $this->input->post('prestudents'); + $oe_kurzbz = $this->input->post('oe_kurzbz'); + $vorlage_kurzbz = $this->input->post('vorlage_kurzbz'); + $msgVars = $this->input->post('msgvars'); + + $sendExplicitTemplate = $this->CLMessagesModel->sendExplicitTemplate($prestudents, $oe_kurzbz, $vorlage_kurzbz, $msgVars); + $this->outputJson(getData($sendExplicitTemplate)); + } +} diff --git a/application/controllers/system/messages/ViewMessage.php b/application/controllers/system/messages/ViewMessage.php new file mode 100644 index 000000000..ccb9afb33 --- /dev/null +++ b/application/controllers/system/messages/ViewMessage.php @@ -0,0 +1,134 @@ +config->load('message'); + + // Load model MessageToken_model, not calling the authentication system + $this->load->model('CL/Messages_model', 'CLMessagesModel'); + + // Phrases used in loaded views + $this->loadPhrases( + array( + 'global', + 'ui' + ) + ); + } + + /** + * Display a message in read mode only using the specified token + */ + public function toHTML($token) + { + // Loads the view to read a received message using its token as identifier + $this->load->view('system/messages/htmlRead', $this->CLMessagesModel->prepareHtmlRead($token)); + } + + /** + * Write a reply message to a received one using its token as identifier + */ + public function writeReply() + { + $token = $this->input->get('token'); // gets received message token + + // Loads the view to write a reply message + $this->load->view('system/messages/htmlWriteReply', $this->CLMessagesModel->prepareHtmlWriteReply($token)); + } + + /** + * Send a reply message (no templates are used) + */ + public function sendReply() + { + $subject = $this->input->post('subject'); + $body = $this->input->post('body'); + $receiver_id = $this->input->post('receiver_id'); + $relationmessage_id = $this->input->post('relationmessage_id'); + $token = $this->input->post('token'); + + $sendReply = $this->CLMessagesModel->sendReply($receiver_id, $subject, $body, $relationmessage_id, $token); + if (isSuccess($sendReply)) + { + $this->load->view('system/messages/htmlMessageSentSuccess'); + } + else + { + $this->load->view('system/messages/htmlMessageSentError'); + } + } + + /** + * With the given token redirects the user to reply page configured in the config/message.php file + */ + public function redirectByToken($token) + { + // Loads model MessageTokenModel + $this->load->model('system/MessageToken_model', 'MessageTokenModel'); + + // Retrieves the single message data using the given token + $msg = $this->MessageTokenModel->getMessageByToken($token); + // If it is an error or it does not contain data show an error + if (!hasData($msg)) show_error('MSG-ERR-0001: An error occurred while redirecting, please contact the administrator'); + // else + $oe_kurzbz = getData($msg)[0]->oe_kurzbz; + + $organisationRoot = null; // by default is null + + // If an organisation unit is present in the message tries to retrieve the root organisation unit + // from the one found in the message + if (!isEmptyString($oe_kurzbz)) + { + // Retrieves the root organisation unit from the one found in the message + $getOERoot = $this->MessageTokenModel->getOERoot($oe_kurzbz); + // If it is an error or it does not contain data show an error + if (!hasData($getOERoot)) show_error('MSG-ERR-0002: An error occurred while redirecting, please contact the administrator'); + // else + $organisationRoot = getData($getOERoot)[0]->oe_kurzbz; + } + + // Retrieves the possible redirecting URLs array from configs + $messageRedirectUrls = $this->config->item('message_redirect_url'); + // If it is not a valid array then show an error + if (isEmptyArray($messageRedirectUrls)) show_error('MSG-ERR-0003: An error occurred while redirecting, please contact the administrator'); + + // If this organisation unit root is not configured as an entry in the possible redirecting URLs array, + // then tries to use the default one... + if (!isset($messageRedirectUrls[$organisationRoot])) + { + $organisationRoot = 'fallback'; + + // ...if even the default one is not present show an error + if (!isset($messageRedirectUrls[$organisationRoot])) + { + show_error('MSG-ERR-0004: An error occurred while redirecting, please contact the administrator'); + } + } + + // Finally if everything was right then the user can be redirected + redirect($messageRedirectUrls[$organisationRoot] . '?token=' . $token); + } +} diff --git a/application/controllers/system/Filters.php b/application/controllers/widgets/Filters.php similarity index 68% rename from application/controllers/system/Filters.php rename to application/controllers/widgets/Filters.php index 3bdb6dde2..b5cbc07ea 100644 --- a/application/controllers/system/Filters.php +++ b/application/controllers/widgets/Filters.php @@ -3,7 +3,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); /** - * This controller operates between (interface) the JS (GUI) and the FiltersLib (back-end) + * This controller operates between (interface) the JS (GUI) and the FilterWidgetLib (back-end) * Provides data to the ajax get calls about the filter * Accepts ajax post calls to change the filter data * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON @@ -12,10 +12,10 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); */ class Filters extends FHC_Controller { - const FILTER_PAGE_PARAM = 'filter_page'; + const FILTER_UNIQUE_ID = 'filterUniqueId'; /** - * Calls the parent's constructor and loads the FiltersLib + * Calls the parent's constructor and loads the FilterWidgetLib */ public function __construct() { @@ -24,8 +24,8 @@ class Filters extends FHC_Controller // Loads authentication library and starts authentication $this->load->library('AuthLib'); - // Loads the FiltersLib with HTTP GET/POST parameters - $this->_loadFiltersLib(); + // Loads the FilterWidgetLib with HTTP GET/POST parameters + $this->_loadFilterWidgetLib(); // Checks if the caller is allow to read this data $this->_isAllowed(); @@ -39,7 +39,7 @@ class Filters extends FHC_Controller */ public function getFilter() { - $this->outputJsonSuccess($this->filterslib->getSession()); + $this->outputJsonSuccess($this->filterwidgetlib->getSession()); } /** @@ -48,7 +48,7 @@ class Filters extends FHC_Controller public function rowNumber() { $rowNumber = 0; - $dataset = $this->filterslib->getSessionElement(FiltersLib::SESSION_DATASET); + $dataset = $this->filterwidgetlib->getSessionElement(FilterWidgetLib::SESSION_DATASET); if (isset($dataset) && is_array($dataset)) { @@ -66,7 +66,7 @@ class Filters extends FHC_Controller { $selectedFields = $this->input->post('selectedFields'); - if ($this->filterslib->sortSelectedFields($selectedFields) == true) + if ($this->filterwidgetlib->sortSelectedFields($selectedFields) == true) { $this->getFilter(); } @@ -84,7 +84,7 @@ class Filters extends FHC_Controller { $selectedField = $this->input->post('selectedField'); - if ($this->filterslib->removeSelectedField($selectedField) == true) + if ($this->filterwidgetlib->removeSelectedField($selectedField) == true) { $this->getFilter(); } @@ -101,7 +101,7 @@ class Filters extends FHC_Controller { $selectedField = $this->input->post('selectedField'); - if ($this->filterslib->addSelectedField($selectedField) == true) + if ($this->filterwidgetlib->addSelectedField($selectedField) == true) { $this->getFilter(); } @@ -118,7 +118,7 @@ class Filters extends FHC_Controller { $appliedFilter = $this->input->post('appliedFilter'); - if ($this->filterslib->removeAppliedFilter($appliedFilter) == true) + if ($this->filterwidgetlib->removeAppliedFilter($appliedFilter) == true) { $this->outputJsonSuccess('Removed'); } @@ -138,7 +138,7 @@ class Filters extends FHC_Controller $appliedFiltersConditions = $this->input->post('appliedFiltersConditions'); $appliedFiltersOptions = $this->input->post('appliedFiltersOptions'); - if ($this->filterslib->applyFilters( + if ($this->filterwidgetlib->applyFilters( $appliedFilters, $appliedFiltersOperations, $appliedFiltersConditions, @@ -160,7 +160,7 @@ class Filters extends FHC_Controller { $filter = $this->input->post('filter'); - if ($this->filterslib->addFilter($filter) == true) + if ($this->filterwidgetlib->addFilter($filter) == true) { $this->getFilter(); } @@ -177,7 +177,7 @@ class Filters extends FHC_Controller { $customFilterDescription = $this->input->post('customFilterDescription'); - if ($this->filterslib->saveCustomFilter($customFilterDescription) == true) + if ($this->filterwidgetlib->saveCustomFilter($customFilterDescription) == true) { $this->outputJsonSuccess('Saved'); } @@ -194,7 +194,7 @@ class Filters extends FHC_Controller { $filter_id = $this->input->post('filter_id'); - if ($this->filterslib->removeCustomFilter($filter_id) == true) + if ($this->filterwidgetlib->removeCustomFilter($filter_id) == true) { $this->outputJsonSuccess('Removed'); } @@ -211,7 +211,17 @@ class Filters extends FHC_Controller public function setNavigationMenu() { // Generates the filters structure array - $filterMenu = $this->filterslib->generateFilterMenu($this->input->get(FiltersLib::NAVIGATION_PAGE)); + $filterMenu = $this->filterwidgetlib->generateFilterMenu($this->input->get(FilterWidgetLib::NAVIGATION_PAGE)); + + $this->outputJsonSuccess('Success'); + } + + /** + * Reloads the dataset + */ + public function reloadDataset() + { + $this->filterwidgetlib->reloadDataset(); $this->outputJsonSuccess('Success'); } @@ -224,38 +234,40 @@ class Filters extends FHC_Controller */ private function _isAllowed() { - if (!$this->filterslib->isAllowed()) + if (!$this->filterwidgetlib->isAllowed()) { $this->terminateWithJsonError('You are not allowed to access to this content'); } } /** - * Loads the FiltersLib with the FILTER_PAGE_PARAM parameter - * If the parameter FILTER_PAGE_PARAM is not given then the execution of the controller is terminated and + * Loads the FilterWidgetLib with the FILTER_UNIQUE_ID parameter + * If the parameter FILTER_UNIQUE_ID is not given then the execution of the controller is terminated and * an error message is printed */ - private function _loadFiltersLib() + private function _loadFilterWidgetLib() { - // If the parameter FILTER_PAGE_PARAM is present in the HTTP GET or POST - if (isset($_GET[self::FILTER_PAGE_PARAM]) || isset($_POST[self::FILTER_PAGE_PARAM])) + // If the parameter FILTER_UNIQUE_ID is present in the HTTP GET or POST + if (isset($_GET[self::FILTER_UNIQUE_ID]) || isset($_POST[self::FILTER_UNIQUE_ID])) { // If it is present in the HTTP GET - if (isset($_GET[self::FILTER_PAGE_PARAM])) + if (isset($_GET[self::FILTER_UNIQUE_ID])) { - $filterPage = $this->input->get(self::FILTER_PAGE_PARAM); // is retrieved from the HTTP GET + $filterUniqueId = $this->input->get(self::FILTER_UNIQUE_ID); // is retrieved from the HTTP GET } - elseif (isset($_POST[self::FILTER_PAGE_PARAM])) // Else if it is present in the HTTP POST + elseif (isset($_POST[self::FILTER_UNIQUE_ID])) // Else if it is present in the HTTP POST { - $filterPage = $this->input->post(self::FILTER_PAGE_PARAM); // is retrieved from the HTTP POST + $filterUniqueId = $this->input->post(self::FILTER_UNIQUE_ID); // is retrieved from the HTTP POST } - // Loads the FiltersLib that contains all the used logic - $this->load->library('FiltersLib', array(self::FILTER_PAGE_PARAM => $filterPage)); + // Loads the FilterWidgetLib that contains all the used logic + $this->load->library('FilterWidgetLib'); + + $this->filterwidgetlib->setFilterUniqueId($filterUniqueId); } else // Otherwise an error will be written in the output { - $this->terminateWithJsonError('Parameter "'.self::FILTER_PAGE_PARAM.'" not provided!'); + $this->terminateWithJsonError('Parameter "'.self::FILTER_UNIQUE_ID.'" not provided!'); } } } diff --git a/application/controllers/widgets/Language.php b/application/controllers/widgets/Language.php new file mode 100644 index 000000000..8269d3b2d --- /dev/null +++ b/application/controllers/widgets/Language.php @@ -0,0 +1,31 @@ +input->post('language'); + + $this->outputJson(setUserLanguage($language)); + } +} diff --git a/application/controllers/widgets/Tables.php b/application/controllers/widgets/Tables.php new file mode 100644 index 000000000..21161ff9f --- /dev/null +++ b/application/controllers/widgets/Tables.php @@ -0,0 +1,105 @@ +load->library('AuthLib'); + + // Loads the tablewidgetlib with HTTP GET/POST parameters + $this->_loadTableWidgetLib(); + + // Checks if the caller is allow to read this data + $this->_isAllowed(); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Retrieves data about the current filter from the session and will be written on the output in JSON format + */ + public function getTable() + { + $this->outputJsonSuccess($this->tablewidgetlib->getSession()); + } + + /** + * Retrieves the number of records present in the current dataset and will be written on the output in JSON format + */ + public function rowNumber() + { + $rowNumber = 0; + $dataset = $this->tablewidgetlib->getSessionElement(TableWidgetLib::SESSION_DATASET); + + if (isset($dataset) && is_array($dataset)) + { + $rowNumber = count($dataset); + } + + $this->outputJsonSuccess($rowNumber); + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Checks if the user is allowed to use this filter + */ + private function _isAllowed() + { + if (!$this->tablewidgetlib->isAllowed()) + { + $this->terminateWithJsonError('You are not allowed to access to this content'); + } + } + + /** + * Loads the tablewidgetlib with the TABLE_UNIQUE_ID parameter + * If the parameter TABLE_UNIQUE_ID is not given then the execution of the controller is terminated and + * an error message is printed + */ + private function _loadTableWidgetLib() + { + // If the parameter TABLE_UNIQUE_ID is present in the HTTP GET or POST + if (isset($_GET[self::TABLE_UNIQUE_ID]) || isset($_POST[self::TABLE_UNIQUE_ID])) + { + // If it is present in the HTTP GET + if (isset($_GET[self::TABLE_UNIQUE_ID])) + { + $tableUniqueId = $this->input->get(self::TABLE_UNIQUE_ID); // is retrieved from the HTTP GET + } + elseif (isset($_POST[self::TABLE_UNIQUE_ID])) // Else if it is present in the HTTP POST + { + $tableUniqueId = $this->input->post(self::TABLE_UNIQUE_ID); // is retrieved from the HTTP POST + } + + // Loads the tablewidgetlib that contains all the used logic + $this->load->library('TableWidgetLib'); + + $this->tablewidgetlib->setTableUniqueId($tableUniqueId); + } + else // Otherwise an error will be written in the output + { + $this->terminateWithJsonError('Parameter "'.self::TABLE_UNIQUE_ID.'" not provided!'); + } + } +} diff --git a/application/core/APIv1_Controller.php b/application/core/APIv1_Controller.php index 6432c87db..14b4b626d 100644 --- a/application/core/APIv1_Controller.php +++ b/application/core/APIv1_Controller.php @@ -1,9 +1,11 @@ isEntitled * - Checks if the caller is allowed to access to this content with the given permissions * if it is not allowed will set the HTTP header with code 401 * - Calls the parent (REST_Controller) _remap method to performs other checks + * NOTE: this methods override the parent method!!! */ - public function _remap($object_called, $arguments) + public function _remap($object_called, $arguments = []) { if (isset($this->authlib)) // if set then the authentication is ok { diff --git a/application/core/Auth_Controller.php b/application/core/Auth_Controller.php index 1427a318d..c407a106f 100644 --- a/application/core/Auth_Controller.php +++ b/application/core/Auth_Controller.php @@ -1,8 +1,11 @@ load->library('AuthLib'); - // Loads authentication helper - $this->load->helper('hlp_authentication'); - // Checks if the caller is allowed to access to this content $this->_isAllowed($requiredPermissions); } diff --git a/application/core/CLI_Controller.php b/application/core/CLI_Controller.php index 61e3eb4c9..79e2a1283 100644 --- a/application/core/CLI_Controller.php +++ b/application/core/CLI_Controller.php @@ -2,7 +2,10 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); -class CLI_Controller extends FHC_Controller +/** + * + */ +abstract class CLI_Controller extends FHC_Controller { const INFO_FORMAT = '%s %s %s %s'; // Info message format const REQUIRED_PARAM_FORMAT = ' %s'; // Info message required method parameter format diff --git a/application/core/DB_Model.php b/application/core/DB_Model.php index b1e88e164..ca760c662 100644 --- a/application/core/DB_Model.php +++ b/application/core/DB_Model.php @@ -1,5 +1,10 @@ _checkHTTPS(); + $this->_controllerId = null; // set _controllerId as null by default // Loads helper message to manage returning messages @@ -126,4 +132,20 @@ class FHC_Controller extends CI_Controller { $this->output->set_content_type('application/json')->set_output(json_encode($mixed)); } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Checks if the call is performed via web and if HTTPS is enabled and used + * If NOT then an error is raised and the execution is terminated + */ + private function _checkHTTPS() + { + // If NOT called from command line and if the HTTPS protocol is NOT enabled + if (!$this->input->is_cli_request() && !isset($_SERVER['HTTPS'])) + { + show_error('This web site cannot work correctly without the HTTPS protocol enabled'); + } + } } diff --git a/application/core/FS_Model.php b/application/core/FS_Model.php index 4081bf8f4..03a0ee095 100644 --- a/application/core/FS_Model.php +++ b/application/core/FS_Model.php @@ -1,6 +1,11 @@ load->library('LogLib', array( + 'classIndex' => 5, + 'functionIndex' => 5, + 'lineIndex' => 4, + 'dbLogType' => 'job', // required + 'dbExecuteUser' => 'Cronjob system' + )); + } + + //------------------------------------------------------------------------------------------------------------------ + // Protected methods + + /** + * Writes a cronjob info log + */ + protected function logInfo($response, $parameters = null) + { + $this->_log(LogLib::INFO, 'Cronjob info', $response, $parameters); + } + + /** + * Writes a cronjob debug log + */ + protected function logDebug($response, $parameters = null) + { + $this->_log(LogLib::DEBUG, 'Cronjob debug', $response, $parameters); + } + + /** + * Writes a cronjob warning log + */ + protected function logWarning($response, $parameters = null) + { + $this->_log(LogLib::WARNING, 'Cronjob warning', $response, $parameters); + } + + /** + * Writes a cronjob error log + */ + protected function logError($response, $parameters = null) + { + $this->_log(LogLib::ERROR, 'Cronjob error', $response, $parameters); + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Writes a log to database + */ + private function _log($level, $requestId, $response, $parameters) + { + $data = new stdClass(); + + $data->response = $response; + if ($parameters != null) $data->parameters = $parameters; + + switch($level) + { + case LogLib::INFO: + $this->loglib->logInfoDB($requestId, json_encode(success($data, LogLib::INFO))); + break; + case LogLib::DEBUG: + $this->loglib->logDebugDB($requestId, json_encode(success($data, LogLib::DEBUG))); + break; + case LogLib::WARNING: + $this->loglib->logWarningDB($requestId, json_encode(error($data, LogLib::WARNING))); + break; + case LogLib::ERROR: + $this->loglib->logErrorDB($requestId, json_encode(error($data, LogLib::ERROR))); + break; + } + } +} diff --git a/application/core/RESTFul_Controller.php b/application/core/RESTFul_Controller.php new file mode 100644 index 000000000..984f193de --- /dev/null +++ b/application/core/RESTFul_Controller.php @@ -0,0 +1,215 @@ +load->helper('hlp_return_object'); + + // Loads helper session to manage the php session + $this->load->helper('hlp_session'); + + // Loads helper with generic utility function + $this->load->helper('hlp_common'); + } + + /** + * Totally overrode parent's _perform_library_auth method to keep file and class name + * for AuthLib and to call AuthLib with the extra parameter + */ + protected function _perform_library_auth($username = '', $password = NULL) + { + if (empty($username)) + { + log_message('error', 'Library Auth: Failure, empty username'); + return FALSE; + } + + $auth_library_class = $this->config->item('auth_library_class'); + $auth_library_function = $this->config->item('auth_library_function'); + + if (empty($auth_library_class)) + { + log_message('debug', 'Library Auth: Failure, empty auth_library_class'); + return FALSE; + } + + if (empty($auth_library_function)) + { + log_message('debug', 'Library Auth: Failure, empty auth_library_function'); + return FALSE; + } + + if (is_callable([$auth_library_class, $auth_library_function]) === FALSE) + { + $this->load->library($auth_library_class, array(false)); + } + + return $this->{strtolower($auth_library_class)}->$auth_library_function($username, $password); + } + + /** + * Totally overrode parent's _remap method to change the naming convention of controllers methods + */ + public function _remap($object_called, $arguments = []) + { + // Should we answer if not over SSL? + if ($this->config->item('force_https') && $this->request->ssl === FALSE) + { + $this->response([ + $this->config->item('rest_status_field_name') => FALSE, + $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_unsupported') + ], self::HTTP_FORBIDDEN); + + $this->is_valid_request = false; + } + + // Remove the supported format from the function name e.g. index.json => index + $object_called = preg_replace('/^(.*)\.(?:'.implode('|', array_keys($this->_supported_formats)).')$/', '$1', $object_called); + + // NOTE: START changes + $controller_method = $object_called.'_'.$this->request->method; // Method name fallback + // If the config entry rest_methods_name_format is provided and is not empty then use it to produce the method name + if (!empty($this->config->item('rest_methods_name_format'))) + { + $controller_method = sprintf($this->config->item('rest_methods_name_format'), $object_called, $this->request->method); + } + // END changes + + // Does this method exist? If not, try executing an index method + if (!method_exists($this, $controller_method)) { + $controller_method = "index_" . $this->request->method; + array_unshift($arguments, $object_called); + } + + // Do we want to log this method (if allowed by config)? + $log_method = ! (isset($this->methods[$controller_method]['log']) && $this->methods[$controller_method]['log'] === FALSE); + + // Use keys for this method? + $use_key = ! (isset($this->methods[$controller_method]['key']) && $this->methods[$controller_method]['key'] === FALSE); + + // They provided a key, but it wasn't valid, so get them out of here + if ($this->config->item('rest_enable_keys') && $use_key && $this->_allow === FALSE) + { + if ($this->config->item('rest_enable_logging') && $log_method) + { + $this->_log_request(); + } + + // fix cross site to option request error + if($this->request->method == 'options') { + exit; + } + + $this->response([ + $this->config->item('rest_status_field_name') => FALSE, + $this->config->item('rest_message_field_name') => sprintf($this->lang->line('text_rest_invalid_api_key'), $this->rest->key) + ], self::HTTP_FORBIDDEN); + + $this->is_valid_request = false; + } + + // Check to see if this key has access to the requested controller + if ($this->config->item('rest_enable_keys') && $use_key && empty($this->rest->key) === FALSE && $this->_check_access() === FALSE) + { + if ($this->config->item('rest_enable_logging') && $log_method) + { + $this->_log_request(); + } + + $this->response([ + $this->config->item('rest_status_field_name') => FALSE, + $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_api_key_unauthorized') + ], self::HTTP_UNAUTHORIZED); + + $this->is_valid_request = false; + } + + // Sure it exists, but can they do anything with it? + if (! method_exists($this, $controller_method)) + { + $this->response([ + $this->config->item('rest_status_field_name') => FALSE, + $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_unknown_method') + ], self::HTTP_METHOD_NOT_ALLOWED); + + $this->is_valid_request = false; + } + + // Doing key related stuff? Can only do it if they have a key right? + if ($this->config->item('rest_enable_keys') && empty($this->rest->key) === FALSE) + { + // Check the limit + if ($this->config->item('rest_enable_limits') && $this->_check_limit($controller_method) === FALSE) + { + $response = [$this->config->item('rest_status_field_name') => FALSE, $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_api_key_time_limit')]; + $this->response($response, self::HTTP_UNAUTHORIZED); + + $this->is_valid_request = false; + } + + // If no level is set use 0, they probably aren't using permissions + $level = isset($this->methods[$controller_method]['level']) ? $this->methods[$controller_method]['level'] : 0; + + // If no level is set, or it is lower than/equal to the key's level + $authorized = $level <= $this->rest->level; + // IM TELLIN! + if ($this->config->item('rest_enable_logging') && $log_method) + { + $this->_log_request($authorized); + } + if($authorized === FALSE) + { + // They don't have good enough perms + $response = [$this->config->item('rest_status_field_name') => FALSE, $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_api_key_permissions')]; + $this->response($response, self::HTTP_UNAUTHORIZED); + + $this->is_valid_request = false; + } + } + + //check request limit by ip without login + elseif ($this->config->item('rest_limits_method') == "IP_ADDRESS" && $this->config->item('rest_enable_limits') && $this->_check_limit($controller_method) === FALSE) + { + $response = [$this->config->item('rest_status_field_name') => FALSE, $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_ip_address_time_limit')]; + $this->response($response, self::HTTP_UNAUTHORIZED); + + $this->is_valid_request = false; + } + + // No key stuff, but record that stuff is happening + elseif ($this->config->item('rest_enable_logging') && $log_method) + { + $this->_log_request($authorized = TRUE); + } + + // Call the controller method and passed arguments + try + { + if ($this->is_valid_request) { + call_user_func_array([$this, $controller_method], $arguments); + } + } + catch (Exception $ex) + { + if ($this->config->item('rest_handle_exceptions') === FALSE) { + throw $ex; + } + + // If the method doesn't exist, then the error will be caught and an error response shown + $_error = &load_class('Exceptions', 'core'); + $_error->show_exception($ex); + } + } +} diff --git a/application/core/REST_Controller.php b/application/core/REST_Controller.php deleted file mode 100644 index 9cd276556..000000000 --- a/application/core/REST_Controller.php +++ /dev/null @@ -1,2166 +0,0 @@ - 'application/json', - 'array' => 'application/json', - 'csv' => 'application/csv', - 'html' => 'text/html', - 'jsonp' => 'application/javascript', - 'php' => 'text/plain', - 'serialized' => 'application/vnd.php.serialized', - 'xml' => 'application/xml' - ]; - - /** - * Information about the current API user - * - * @var object - */ - protected $_apiuser; - - /** - * Enable XSS flag - * Determines whether the XSS filter is always active when - * GET, OPTIONS, HEAD, POST, PUT, DELETE and PATCH data is encountered. - * Set automatically based on config setting - * - * @var bool - */ - protected $_enable_xss = FALSE; - - /** - * HTTP status codes and their respective description - * Note: Only the widely used HTTP status codes are used - * - * @var array - * @link http://www.restapitutorial.com/httpstatuscodes.html - */ - protected $http_status_codes = [ - self::HTTP_OK => 'OK', - self::HTTP_CREATED => 'CREATED', - self::HTTP_NO_CONTENT => 'NO CONTENT', - self::HTTP_NOT_MODIFIED => 'NOT MODIFIED', - self::HTTP_BAD_REQUEST => 'BAD REQUEST', - self::HTTP_UNAUTHORIZED => 'UNAUTHORIZED', - self::HTTP_FORBIDDEN => 'FORBIDDEN', - self::HTTP_NOT_FOUND => 'NOT FOUND', - self::HTTP_METHOD_NOT_ALLOWED => 'METHOD NOT ALLOWED', - self::HTTP_NOT_ACCEPTABLE => 'NOT ACCEPTABLE', - self::HTTP_CONFLICT => 'CONFLICT', - self::HTTP_INTERNAL_SERVER_ERROR => 'INTERNAL SERVER ERROR', - self::HTTP_NOT_IMPLEMENTED => 'NOT IMPLEMENTED' - ]; - - /** - * Extend this function to apply additional checking early on in the process - * - * @access protected - * @return void - */ - protected function early_checks() - { - // Loads helper message to manage returning messages - $this->load->helper('hlp_return_object'); - - // Loads helper session to manage the php session - $this->load->helper('hlp_session'); - - // Loads helper with generic utility function - $this->load->helper('hlp_common'); - } - - /** - * Constructor for the REST API - * - * @access public - * @param string $config Configuration filename minus the file extension - * e.g: my_rest.php is passed as 'my_rest' - * @return void - */ - public function __construct($config = 'rest') - { - parent::__construct(); - - // Disable XML Entity (security vulnerability) - libxml_disable_entity_loader(TRUE); - - // Check to see if PHP is equal to or greater than 5.4.x - if (is_php('5.4') === FALSE) - { - // CodeIgniter 3 is recommended for v5.4 or above - throw new Exception('Using PHP v' . PHP_VERSION . ', though PHP v5.4 or greater is required'); - } - - // Check to see if this is CI 3.x - $ci_version_number = explode('.', CI_VERSION, 2); - if ($ci_version_number[0] < 3) - { - throw new Exception('REST Server requires CodeIgniter 3.x'); - } - - // Set the default value of global xss filtering. Same approach as CodeIgniter 3 - $this->_enable_xss = ($this->config->item('global_xss_filtering') === TRUE); - - // Don't try to parse template variables like {elapsed_time} and {memory_usage} - // when output is displayed for not damaging data accidentally - $this->output->parse_exec_vars = FALSE; - - // Start the timer for how long the request takes - $this->_start_rtime = microtime(TRUE); - - // Load the rest.php configuration file - $this->load->config($config); - - // At present the library is bundled with REST_Controller 2.5+, but will eventually be part of CodeIgniter (no citation) - $this->load->library('format'); - - // Determine supported output formats from configiguration. - $supported_formats = $this->config->item('rest_supported_formats'); - - // Validate the configuration setting output formats - if (empty($supported_formats)) - { - $supported_formats = []; - } - - if (!is_array($supported_formats)) - { - $supported_formats = [$supported_formats]; - } - - // Add silently the default output format if it is missing. - $default_format = $this->_get_default_output_format(); - if (!in_array($default_format, $supported_formats)) - { - $supported_formats[] = $default_format; - } - - // Now update $this->_supported_formats - $this->_supported_formats = array_intersect_key($this->_supported_formats, array_flip($supported_formats)); - - // Get the language - $language = $this->config->item('rest_language'); - if ($language === NULL) - { - $language = 'en-US'; - } - - // Load the language file - $this->lang->load('rest_controller', $language); - - // Initialise the response, request and rest objects - $this->request = new stdClass(); - $this->response = new stdClass(); - $this->rest = new stdClass(); - - // Check to see if the current IP address is blacklisted - if ($this->config->item('rest_ip_blacklist_enabled') === TRUE) - { - $this->_check_blacklist_auth(); - } - - // Determine whether the connection is HTTPS - $this->request->ssl = is_https(); - - // How is this request being made? GET, POST, PATCH, DELETE, INSERT, PUT, HEAD or OPTIONS - $this->request->method = $this->_detect_method(); - - // Create an argument container if it doesn't exist e.g. _get_args - if (isset($this->{'_' . $this->request->method . '_args'}) === FALSE) - { - $this->{'_' . $this->request->method . '_args'} = []; - } - - // Set up the query parameters - $this->_parse_query(); - - // Set up the GET variables - $this->_get_args = array_merge($this->_get_args, $this->uri->ruri_to_assoc()); - - // Try to find a format for the request (means we have a request body) - $this->request->format = $this->_detect_input_format(); - - // Not all methods have a body attached with them - $this->request->body = NULL; - - $this->{'_parse_' . $this->request->method}(); - - // Now we know all about our request, let's try and parse the body if it exists - if ($this->request->format && $this->request->body) - { - $this->request->body = $this->format->factory($this->request->body, $this->request->format)->to_array(); - // Assign payload arguments to proper method container - $this->{'_' . $this->request->method . '_args'} = $this->request->body; - } - - // Merge both for one mega-args variable - $this->_args = array_merge( - $this->_get_args, - $this->_options_args, - $this->_patch_args, - $this->_head_args, - $this->_put_args, - $this->_post_args, - $this->_delete_args, - $this->{'_' . $this->request->method . '_args'} - ); - - // Which format should the data be returned in? - $this->response->format = $this->_detect_output_format(); - - // Which language should the data be returned in? - $this->response->lang = $this->_detect_lang(); - - // Extend this function to apply additional checking early on in the process - $this->early_checks(); - - // Load DB if its enabled - if ($this->config->item('rest_database_group') && ($this->config->item('rest_enable_keys') || $this->config->item('rest_enable_logging'))) - { - $this->rest->db = $this->load->database($this->config->item('rest_database_group'), TRUE); - } - - // Use whatever database is in use (isset returns FALSE) - elseif (property_exists($this, 'db')) - { - $this->rest->db = $this->db; - } - - // Check if there is a specific auth type for the current class/method - // _auth_override_check could exit so we need $this->rest->db initialized before - $this->auth_override = $this->_auth_override_check(); - - // Checking for keys? GET TO WorK! - // Skip keys test for $config['auth_override_class_method']['class'['method'] = 'none' - if ($this->config->item('rest_enable_keys') && $this->auth_override !== TRUE) - { - $this->_allow = $this->_detect_api_key(); - } - - // Only allow ajax requests - if ($this->input->is_ajax_request() === FALSE && $this->config->item('rest_ajax_only')) - { - // Display an error response - $this->response([ - $this->config->item('rest_status_field_name') => FALSE, - $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_ajax_only') - ], self::HTTP_NOT_ACCEPTABLE); - } - - // When there is no specific override for the current class/method, use the default auth value set in the config - if ($this->auth_override === FALSE && ($this->config->item('rest_enable_keys') && $this->_allow === TRUE)) - { - $rest_auth = strtolower($this->config->item('rest_auth')); - switch ($rest_auth) - { - case 'basic': - $this->_prepare_basic_auth(); - break; - case 'digest': - $this->_prepare_digest_auth(); - break; - case 'session': - $this->_check_php_session(); - break; - } - if ($this->config->item('rest_ip_whitelist_enabled') === TRUE) - { - $this->_check_whitelist_auth(); - } - } - } - - /** - * Deconstructor - * - * @author Chris Kacerguis - * @access public - * @return void - */ - public function __destruct() - { - // Get the current timestamp - $this->_end_rtime = microtime(TRUE); - - // Log the loading time to the log table - if ($this->config->item('rest_enable_logging') === TRUE) - { - $this->_log_access_time(); - } - } - - /** - * Requests are not made to methods directly, the request will be for - * an "object". This simply maps the object and method to the correct - * Controller method - * - * @access public - * @param string $object_called - * @param array $arguments The arguments passed to the controller method - */ - public function _remap($object_called, $arguments) - { - // Should we answer if not over SSL? - if ($this->config->item('force_https') && $this->request->ssl === FALSE) - { - $this->response([ - $this->config->item('rest_status_field_name') => FALSE, - $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_unsupported') - ], self::HTTP_FORBIDDEN); - } - - // Remove the supported format from the function name e.g. index.json => index - $object_called = preg_replace('/^(.*)\.(?:' . implode('|', array_keys($this->_supported_formats)) . ')$/', '$1', $object_called); - - //$controller_method = $object_called . '_' . $this->request->method; - // CamelCase compliant - $controller_method = $this->request->method.ucfirst($object_called); - - // Do we want to log this method (if allowed by config)? - $log_method = !(isset($this->methods[$controller_method]['log']) && $this->methods[$controller_method]['log'] === FALSE); - - // Use keys for this method? - $use_key = !(isset($this->methods[$controller_method]['key']) && $this->methods[$controller_method]['key'] === FALSE); - - // They provided a key, but it wasn't valid, so get them out of here - if ($this->config->item('rest_enable_keys') && $use_key && $this->_allow === FALSE) - { - if ($this->config->item('rest_enable_logging') && $log_method) - { - $this->_log_request(); - } - - $this->response([ - $this->config->item('rest_status_field_name') => FALSE, - $this->config->item('rest_message_field_name') => sprintf($this->lang->line('text_rest_invalid_api_key'), $this->rest->key) - ], self::HTTP_FORBIDDEN); - } - - // Check to see if this key has access to the requested controller - if ($this->config->item('rest_enable_keys') && $use_key && empty($this->rest->key) === FALSE && $this->_check_access() === FALSE) - { - if ($this->config->item('rest_enable_logging') && $log_method) - { - $this->_log_request(); - } - - $this->response([ - $this->config->item('rest_status_field_name') => FALSE, - $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_api_key_unauthorized') - ], self::HTTP_UNAUTHORIZED); - } - - // Sure it exists, but can they do anything with it? - if (method_exists($this, $controller_method) === FALSE) - { - $this->response([ - $this->config->item('rest_status_field_name') => FALSE, - $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_unknown_method') - ], self::HTTP_NOT_FOUND); - } - - // Doing key related stuff? Can only do it if they have a key right? - if ($this->config->item('rest_enable_keys') && empty($this->rest->key) === FALSE) - { - // Check the limit - if ($this->config->item('rest_enable_limits') && $this->_check_limit($controller_method) === FALSE) - { - $response = [$this->config->item('rest_status_field_name') => FALSE, $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_api_key_time_limit')]; - $this->response($response, self::HTTP_UNAUTHORIZED); - } - - // If no level is set use 0, they probably aren't using permissions - $level = isset($this->methods[$controller_method]['level']) ? $this->methods[$controller_method]['level'] : 0; - - // If no level is set, or it is lower than/equal to the key's level - $authorized = $level <= $this->rest->level; - - // IM TELLIN! - if ($this->config->item('rest_enable_logging') && $log_method) - { - $this->_log_request($authorized); - } - - // They don't have good enough perms - $response = [$this->config->item('rest_status_field_name') => FALSE, $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_api_key_permissions')]; - $authorized || $this->response($response, self::HTTP_UNAUTHORIZED); - } - - // No key stuff, but record that stuff is happening - elseif ($this->config->item('rest_enable_logging') && $log_method) - { - $this->_log_request($authorized = TRUE); - } - - // Call the controller method and passed arguments - try - { - call_user_func_array([$this, $controller_method], $arguments); - } - catch (Exception $ex) - { - // If the method doesn't exist, then the error will be caught and an error response shown - $this->response([ - $this->config->item('rest_status_field_name') => FALSE, - $this->config->item('rest_message_field_name') => [ - 'classname' => get_class($ex), - 'message' => $ex->getMessage() - ] - ], self::HTTP_INTERNAL_SERVER_ERROR); - } - } - - /** - * Takes mixed data and optionally a status code, then creates the response - * - * @access public - * @param array|NULL $data Data to output to the user - * @param int|NULL $http_code HTTP status code - * @param bool $continue TRUE to flush the response to the client and continue - * running the script; otherwise, exit - */ - public function response($data = NULL, $http_code = NULL, $continue = FALSE) - { - // If the HTTP status is not NULL, then cast as an integer - if ($http_code !== NULL) - { - // So as to be safe later on in the process - $http_code = (int) $http_code; - } - - // Set the output as NULL by default - $output = NULL; - // If data is NULL and no HTTP status code provided, then display, error and exit - if ($data === NULL && $http_code === NULL) - { - $http_code = self::HTTP_NOT_FOUND; - } - - // If data is not NULL and a HTTP status code provided, then continue - elseif ($data !== NULL) - { - // If the format method exists, call and return the output in that format - if (method_exists($this->format, 'to_' . $this->response->format)) - { - // Set the format header - $this->output->set_content_type($this->_supported_formats[$this->response->format], strtolower($this->config->item('charset'))); - $output = $this->format->factory($data)->{'to_' . $this->response->format}(); - - // An array must be parsed as a string, so as not to cause an array to string error - // Json is the most appropriate form for such a datatype - if ($this->response->format === 'array') - { - $output = $this->format->factory($output)->{'to_json'}(); - } - } - else - { - // If an array or object, then parse as a json, so as to be a 'string' - if (is_array($data) || is_object($data)) - { - $data = $this->format->factory($data)->{'to_json'}(); - } - // Format is not supported, so output the raw data as a string - $output = $data; - } - } - - // If not greater than zero, then set the HTTP status code as 200 by default - // Though perhaps 500 should be set instead, for the developer not passing a - // correct HTTP status code - $http_code > 0 || $http_code = self::HTTP_OK; - - $this->output->set_status_header($http_code); - - // JC: Log response code only if rest logging enabled - if ($this->config->item('rest_enable_logging') === TRUE) - { - $this->_log_response_code($http_code); - } - - // Output the data - $this->output->set_output($output); - - if ($continue === FALSE) - { - // Display the data and exit execution - $this->output->_display(); - exit; - } - - // Otherwise dump the output automatically - } - - /** - * Takes mixed data and optionally a status code, then creates the response - * within the buffers of the Output class. The response is sent to the client - * lately by the framework, after the current controller's method termination. - * All the hooks after the controller's method termination are executable - * - * @access public - * @param array|NULL $data Data to output to the user - * @param int|NULL $http_code HTTP status code - */ - public function set_response($data = NULL, $http_code = NULL) - { - $this->response($data, $http_code, TRUE); - } - - /** - * Get the input format e.g. json or xml - * - * @access protected - * @return string|NULL Supported input format; otherwise, NULL - */ - protected function _detect_input_format() - { - // Get the CONTENT-TYPE value from the SERVER variable - $content_type = $this->input->server('CONTENT_TYPE'); - - if (empty($content_type) === FALSE) - { - // Check all formats against the HTTP_ACCEPT header - foreach ($this->_supported_formats as $key => $value) - { - // $key = format e.g. csv - // $value = mime type e.g. application/csv - - // If a semi-colon exists in the string, then explode by ; and get the value of where - // the current array pointer resides. This will generally be the first element of the array - $content_type = (strpos($content_type, ';') !== FALSE ? current(explode(';', $content_type)) : $content_type); - - // If both the mime types match, then return the format - if ($content_type === $value) - { - return $key; - } - } - } - - return NULL; - } - - /** - * Gets the default format from the configuration. Fallbacks to 'json'. - * if the corresponding configuration option $config['rest_default_format'] - * is missing or is empty. - * - * @access protected - * @return string The default supported input format - */ - protected function _get_default_output_format() - { - $default_format = (string) $this->config->item('rest_default_format'); - return $default_format === '' ? 'json' : $default_format; - } - - /** - * Detect which format should be used to output the data - * - * @access protected - * @return mixed|NULL|string Output format - */ - protected function _detect_output_format() - { - // Concatenate formats to a regex pattern e.g. \.(csv|json|xml) - $pattern = '/\.(' . implode('|', array_keys($this->_supported_formats)) . ')($|\/)/'; - $matches = []; - - // Check if a file extension is used e.g. http://example.com/api/index.json?param1=param2 - if (preg_match($pattern, $this->uri->uri_string(), $matches)) - { - return $matches[1]; - } - - // Get the format parameter named as 'format' - if (isset($this->_get_args['format'])) - { - $format = strtolower($this->_get_args['format']); - - if (isset($this->_supported_formats[$format]) === TRUE) - { - return $format; - } - } - - // Get the HTTP_ACCEPT server variable - $http_accept = $this->input->server('HTTP_ACCEPT'); - - // Otherwise, check the HTTP_ACCEPT server variable - if ($this->config->item('rest_ignore_http_accept') === FALSE && $http_accept !== NULL) - { - // Check all formats against the HTTP_ACCEPT header - foreach (array_keys($this->_supported_formats) as $format) - { - // Has this format been requested? - if (strpos($http_accept, $format) !== FALSE) - { - if ($format !== 'html' && $format !== 'xml') - { - // If not HTML or XML assume it's correct - return $format; - } - elseif ($format === 'html' && strpos($http_accept, 'xml') === FALSE) - { - // HTML or XML have shown up as a match - // If it is truly HTML, it wont want any XML - return $format; - } - else if ($format === 'xml' && strpos($http_accept, 'html') === FALSE) - { - // If it is truly XML, it wont want any HTML - return $format; - } - } - } - } - - // Check if the controller has a default format - if (empty($this->rest_format) === FALSE) - { - return $this->rest_format; - } - - // Obtain the default format from the configuration - return $this->_get_default_output_format(); - } - - /** - * Get the HTTP request string e.g. get or post - * - * @access protected - * @return string|NULL Supported request method as a lowercase string; otherwise, NULL if not supported - */ - protected function _detect_method() - { - // Declare a variable to store the method - $method = NULL; - - // Determine whether the 'enable_emulate_request' setting is enabled - if ($this->config->item('enable_emulate_request') === TRUE) - { - $method = $this->input->post('_method'); - if ($method === NULL) - { - $method = $this->input->server('HTTP_X_HTTP_METHOD_OVERRIDE'); - } - - $method = strtolower($method); - } - - if (empty($method)) - { - // Get the request method as a lowercase string - $method = $this->input->method(); - } - - return in_array($method, $this->allowed_http_methods) && method_exists($this, '_parse_' . $method) ? $method : 'get'; - } - - /** - * See if the user has provided an API key - * - * @access protected - * @return bool - */ - protected function _detect_api_key() - { - // Get the api key name variable set in the rest config file - $api_key_variable = $this->config->item('rest_key_name'); - - // Work out the name of the SERVER entry based on config - $key_name = 'HTTP_' . strtoupper(str_replace('-', '_', $api_key_variable)); - - $this->rest->key = NULL; - $this->rest->level = NULL; - $this->rest->user_id = NULL; - $this->rest->ignore_limits = FALSE; - - // Find the key from server or arguments - if (($key = isset($this->_args[$api_key_variable]) ? $this->_args[$api_key_variable] : $this->input->server($key_name))) - { - if (!($row = $this->rest->db->where($this->config->item('rest_key_column'), $key)->get($this->config->item('rest_keys_table'))->row())) - { - return FALSE; - } - - $this->rest->key = $row->{$this->config->item('rest_key_column')}; - - isset($row->user_id) && $this->rest->user_id = $row->user_id; - isset($row->level) && $this->rest->level = $row->level; - isset($row->ignore_limits) && $this->rest->ignore_limits = $row->ignore_limits; - - $this->_apiuser = $row; - - /* - * If "is private key" is enabled, compare the ip address with the list - * of valid ip addresses stored in the database - */ - if (empty($row->is_private_key) === FALSE) - { - // Check for a list of valid ip addresses - if (isset($row->ip_addresses)) - { - // multiple ip addresses must be separated using a comma, explode and loop - $list_ip_addresses = explode(',', $row->ip_addresses); - $found_address = FALSE; - - foreach ($list_ip_addresses as $ip_address) - { - if ($this->input->ip_address() === trim($ip_address)) - { - // there is a match, set the the value to TRUE and break out of the loop - $found_address = TRUE; - break; - } - } - - return $found_address; - } - else - { - // There should be at least one IP address for this private key - return FALSE; - } - } - - return TRUE; - } - - // No key has been sent - return FALSE; - } - - /** - * Preferred return language - * - * @access protected - * @return string|NULL The language code - */ - protected function _detect_lang() - { - $lang = $this->input->server('HTTP_ACCEPT_LANGUAGE'); - if ($lang === NULL) - { - return NULL; - } - - // It appears more than one language has been sent using a comma delimiter - if (strpos($lang, ',') !== FALSE) - { - $langs = explode(',', $lang); - - $return_langs = []; - foreach ($langs as $lang) - { - // Remove weight and trim leading and trailing whitespace - list($lang) = explode(';', $lang); - $return_langs[] = trim($lang); - } - - return $return_langs; - } - - // Otherwise simply return as a string - return $lang; - } - - /** - * Add the request to the log table - * - * @access protected - * @param bool $authorized TRUE the user is authorized; otherwise, FALSE - * @return bool TRUE the data was inserted; otherwise, FALSE - */ - protected function _log_request($authorized = FALSE) - { - // Insert the request into the log table - $is_inserted = $this->rest->db - ->insert( - $this->config->item('rest_logs_table'), [ - 'uri' => $this->uri->uri_string(), - 'method' => $this->request->method, - 'params' => $this->_args ? ($this->config->item('rest_logs_json_params') === TRUE ? json_encode($this->_args) : serialize($this->_args)) : NULL, - 'api_key' => isset($this->rest->key) ? $this->rest->key : '', - 'ip_address' => $this->input->ip_address(), - 'time' => time(), - 'authorized' => $authorized - ]); - - // Get the last insert id to update at a later stage of the request - $this->_insert_id = $this->rest->db->insert_id(); - - return $is_inserted; - } - - /** - * Check if the requests to a controller method exceed a limit - * - * @access protected - * @param string $controller_method The method being called - * @return bool TRUE the call limit is below the threshold; otherwise, FALSE - */ - protected function _check_limit($controller_method) - { - // They are special, or it might not even have a limit - if (empty($this->rest->ignore_limits) === FALSE) - { - // Everything is fine - return TRUE; - } - - switch ($this->config->item('rest_limits_method')) - { - case 'API_KEY': - $limited_uri = 'api-key:' . (isset($this->rest->key) ? $this->rest->key : ''); - $limited_method_name = isset($this->rest->key) ? $this->rest->key : ''; - break; - - case 'METHOD_NAME': - $limited_uri = 'method-name:' . $controller_method; - $limited_method_name = $controller_method; - break; - - case 'ROUTED_URL': - default: - $limited_uri = $this->uri->ruri_string(); - if (strpos(strrev($limited_uri), strrev($this->response->format)) === 0) - { - $limited_uri = substr($limited_uri,0, -strlen($this->response->format) - 1); - } - $limited_uri = 'uri:' . $limited_uri . ':' . $this->request->method; // It's good to differentiate GET from PUT - $limited_method_name = $controller_method; - break; - } - - if (isset($this->methods[$limited_method_name]['limit']) === FALSE ) - { - // Everything is fine - return TRUE; - } - - // How many times can you get to this method in a defined time_limit (default: 1 hour)? - $limit = $this->methods[$limited_method_name]['limit']; - - $time_limit = (isset($this->methods[$limited_method_name]['time']) ? $this->methods[$limited_method_name]['time'] : 3600); // 3600 = 60 * 60 - - // Get data about a keys' usage and limit to one row - $result = $this->rest->db - ->where('uri', $limited_uri) - ->where('api_key', $this->rest->key) - ->get($this->config->item('rest_limits_table')) - ->row(); - - // No calls have been made for this key - if ($result === NULL) - { - // Create a new row for the following key - $this->rest->db->insert($this->config->item('rest_limits_table'), [ - 'uri' => $limited_uri, - 'api_key' => isset($this->rest->key) ? $this->rest->key : '', - 'count' => 1, - 'hour_started' => time() - ]); - } - - // Been a time limit (or by default an hour) since they called - elseif ($result->hour_started < (time() - $time_limit)) - { - // Reset the started period and count - $this->rest->db - ->where('uri', $limited_uri) - ->where('api_key', isset($this->rest->key) ? $this->rest->key : '') - ->set('hour_started', time()) - ->set('count', 1) - ->update($this->config->item('rest_limits_table')); - } - - // They have called within the hour, so lets update - else - { - // The limit has been exceeded - if ($result->count >= $limit) - { - return FALSE; - } - - // Increase the count by one - $this->rest->db - ->where('uri', $limited_uri) - ->where('api_key', $this->rest->key) - ->set('count', 'count + 1', FALSE) - ->update($this->config->item('rest_limits_table')); - } - - return TRUE; - } - - /** - * Check if there is a specific auth type set for the current class/method/HTTP-method being called - * - * @access protected - * @return bool - */ - protected function _auth_override_check() - { - // Assign the class/method auth type override array from the config - $auth_override_class_method = $this->config->item('auth_override_class_method'); - - // Check to see if the override array is even populated - if (!empty($auth_override_class_method)) - { - // check for wildcard flag for rules for classes - if (!empty($auth_override_class_method[$this->router->class]['*'])) // Check for class overrides - { - // None auth override found, prepare nothing but send back a TRUE override flag - if ($auth_override_class_method[$this->router->class]['*'] === 'none') - { - return TRUE; - } - - // Basic auth override found, prepare basic - if ($auth_override_class_method[$this->router->class]['*'] === 'basic') - { - $this->_prepare_basic_auth(); - - return TRUE; - } - - // Digest auth override found, prepare digest - if ($auth_override_class_method[$this->router->class]['*'] === 'digest') - { - $this->_prepare_digest_auth(); - - return TRUE; - } - - // Session auth override found, check session - if ($auth_override_class_method[$this->router->class]['*'] === 'session') - { - $this->_check_php_session(); - - return TRUE; - } - - // Whitelist auth override found, check client's ip against config whitelist - if ($auth_override_class_method[$this->router->class]['*'] === 'whitelist') - { - $this->_check_whitelist_auth(); - - return TRUE; - } - } - - // Check to see if there's an override value set for the current class/method being called - if (!empty($auth_override_class_method[$this->router->class][$this->router->method])) - { - // None auth override found, prepare nothing but send back a TRUE override flag - if ($auth_override_class_method[$this->router->class][$this->router->method] === 'none') - { - return TRUE; - } - - // Basic auth override found, prepare basic - if ($auth_override_class_method[$this->router->class][$this->router->method] === 'basic') - { - $this->_prepare_basic_auth(); - - return TRUE; - } - - // Digest auth override found, prepare digest - if ($auth_override_class_method[$this->router->class][$this->router->method] === 'digest') - { - $this->_prepare_digest_auth(); - - return TRUE; - } - - // Session auth override found, check session - if ($auth_override_class_method[$this->router->class][$this->router->method] === 'session') - { - $this->_check_php_session(); - - return TRUE; - } - - // Whitelist auth override found, check client's ip against config whitelist - if ($auth_override_class_method[$this->router->class][$this->router->method] === 'whitelist') - { - $this->_check_whitelist_auth(); - - return TRUE; - } - } - } - - // Assign the class/method/HTTP-method auth type override array from the config - $auth_override_class_method_http = $this->config->item('auth_override_class_method_http'); - - // Check to see if the override array is even populated - if (!empty($auth_override_class_method_http)) - { - // check for wildcard flag for rules for classes - if (!empty($auth_override_class_method_http[$this->router->class]['*'][$this->request->method])) - { - // None auth override found, prepare nothing but send back a TRUE override flag - if ($auth_override_class_method_http[$this->router->class]['*'][$this->request->method] === 'none') - { - return TRUE; - } - - // Basic auth override found, prepare basic - if ($auth_override_class_method_http[$this->router->class]['*'][$this->request->method] === 'basic') - { - $this->_prepare_basic_auth(); - - return TRUE; - } - - // Digest auth override found, prepare digest - if ($auth_override_class_method_http[$this->router->class]['*'][$this->request->method] === 'digest') - { - $this->_prepare_digest_auth(); - - return TRUE; - } - - // Session auth override found, check session - if ($auth_override_class_method_http[$this->router->class]['*'][$this->request->method] === 'session') - { - $this->_check_php_session(); - - return TRUE; - } - - // Whitelist auth override found, check client's ip against config whitelist - if ($auth_override_class_method_http[$this->router->class]['*'][$this->request->method] === 'whitelist') - { - $this->_check_whitelist_auth(); - - return TRUE; - } - } - - // Check to see if there's an override value set for the current class/method/HTTP-method being called - if (!empty($auth_override_class_method_http[$this->router->class][$this->router->method][$this->request->method])) - { - // None auth override found, prepare nothing but send back a TRUE override flag - if ($auth_override_class_method_http[$this->router->class][$this->router->method][$this->request->method] === 'none') - { - return TRUE; - } - - // Basic auth override found, prepare basic - if ($auth_override_class_method_http[$this->router->class][$this->router->method][$this->request->method] === 'basic') - { - $this->_prepare_basic_auth(); - - return TRUE; - } - - // Digest auth override found, prepare digest - if ($auth_override_class_method_http[$this->router->class][$this->router->method][$this->request->method] === 'digest') - { - $this->_prepare_digest_auth(); - - return TRUE; - } - - // Session auth override found, check session - if ($auth_override_class_method_http[$this->router->class][$this->router->method][$this->request->method] === 'session') - { - $this->_check_php_session(); - - return TRUE; - } - - // Whitelist auth override found, check client's ip against config whitelist - if ($auth_override_class_method_http[$this->router->class][$this->router->method][$this->request->method] === 'whitelist') - { - $this->_check_whitelist_auth(); - - return TRUE; - } - } - } - return FALSE; - } - - /** - * Parse the GET request arguments - * - * @access protected - * @return void - */ - protected function _parse_get() - { - // Merge both the URI segments and query parameters - $this->_get_args = array_merge($this->_get_args, $this->_query_args); - } - - /** - * Parse the POST request arguments - * - * @access protected - * @return void - */ - protected function _parse_post() - { - $this->_post_args = $_POST; - - if ($this->request->format) - { - $this->request->body = $this->input->raw_input_stream; - } - } - - /** - * Parse the PUT request arguments - * - * @access protected - * @return void - */ - protected function _parse_put() - { - if ($this->request->format) - { - $this->request->body = $this->input->raw_input_stream; - } - else if ($this->input->method() === 'put') - { - // If no filetype is provided, then there are probably just arguments - $this->_put_args = $this->input->input_stream(); - } - } - - /** - * Parse the HEAD request arguments - * - * @access protected - * @return void - */ - protected function _parse_head() - { - // Parse the HEAD variables - parse_str(parse_url($this->input->server('REQUEST_URI'), PHP_URL_QUERY), $head); - - // Merge both the URI segments and HEAD params - $this->_head_args = array_merge($this->_head_args, $head); - } - - /** - * Parse the OPTIONS request arguments - * - * @access protected - * @return void - */ - protected function _parse_options() - { - // Parse the OPTIONS variables - parse_str(parse_url($this->input->server('REQUEST_URI'), PHP_URL_QUERY), $options); - - // Merge both the URI segments and OPTIONS params - $this->_options_args = array_merge($this->_options_args, $options); - } - - /** - * Parse the PATCH request arguments - * - * @access protected - * @return void - */ - protected function _parse_patch() - { - // It might be a HTTP body - if ($this->request->format) - { - $this->request->body = $this->input->raw_input_stream; - } - else if ($this->input->method() === 'patch') - { - // If no filetype is provided, then there are probably just arguments - $this->_patch_args = $this->input->input_stream(); - } - } - - /** - * Parse the DELETE request arguments - * - * @access protected - * @return void - */ - protected function _parse_delete() - { - // These should exist if a DELETE request - if ($this->input->method() === 'delete') - { - $this->_delete_args = $this->input->input_stream(); - } - } - - /** - * Parse the query parameters - * - * @access protected - * @return void - */ - protected function _parse_query() - { - $this->_query_args = $this->input->get(); - } - - // INPUT FUNCTION -------------------------------------------------------------- - - /** - * Retrieve a value from a GET request - * - * @access public - * @param NULL $key Key to retrieve from the GET request - * If NULL an array of arguments is returned - * @param NULL $xss_clean Whether to apply XSS filtering - * @return array|string|NULL Value from the GET request; otherwise, NULL - */ - public function get($key = NULL, $xss_clean = NULL) - { - if ($key === NULL) - { - return $this->_get_args; - } - - return isset($this->_get_args[$key]) ? $this->_xss_clean($this->_get_args[$key], $xss_clean) : NULL; - } - - /** - * Retrieve a value from a OPTIONS request - * - * @access public - * @param NULL $key Key to retrieve from the OPTIONS request. - * If NULL an array of arguments is returned - * @param NULL $xss_clean Whether to apply XSS filtering - * @return array|string|NULL Value from the OPTIONS request; otherwise, NULL - */ - public function options($key = NULL, $xss_clean = NULL) - { - if ($key === NULL) - { - return $this->_options_args; - } - - return isset($this->_options_args[$key]) ? $this->_xss_clean($this->_options_args[$key], $xss_clean) : NULL; - } - - /** - * Retrieve a value from a HEAD request - * - * @access public - * @param NULL $key Key to retrieve from the HEAD request - * If NULL an array of arguments is returned - * @param NULL $xss_clean Whether to apply XSS filtering - * @return array|string|NULL Value from the HEAD request; otherwise, NULL - */ - public function head($key = NULL, $xss_clean = NULL) - { - if ($key === NULL) - { - return $this->_head_args; - } - - return isset($this->_head_args[$key]) ? $this->_xss_clean($this->_head_args[$key], $xss_clean) : NULL; - } - - /** - * Retrieve a value from a POST request - * - * @access public - * @param NULL $key Key to retrieve from the POST request - * If NULL an array of arguments is returned - * @param NULL $xss_clean Whether to apply XSS filtering - * @return array|string|NULL Value from the POST request; otherwise, NULL - */ - public function post($key = NULL, $xss_clean = NULL) - { - if ($key === NULL) - { - return $this->_post_args; - } - - return isset($this->_post_args[$key]) ? $this->_xss_clean($this->_post_args[$key], $xss_clean) : NULL; - } - - /** - * Retrieve a value from a PUT request - * - * @access public - * @param NULL $key Key to retrieve from the PUT request - * If NULL an array of arguments is returned - * @param NULL $xss_clean Whether to apply XSS filtering - * @return array|string|NULL Value from the PUT request; otherwise, NULL - */ - public function put($key = NULL, $xss_clean = NULL) - { - if ($key === NULL) - { - return $this->_put_args; - } - - return isset($this->_put_args[$key]) ? $this->_xss_clean($this->_put_args[$key], $xss_clean) : NULL; - } - - /** - * Retrieve a value from a DELETE request - * - * @access public - * @param NULL $key Key to retrieve from the DELETE request - * If NULL an array of arguments is returned - * @param NULL $xss_clean Whether to apply XSS filtering - * @return array|string|NULL Value from the DELETE request; otherwise, NULL - */ - public function delete($key = NULL, $xss_clean = NULL) - { - if ($key === NULL) - { - return $this->_delete_args; - } - - return isset($this->_delete_args[$key]) ? $this->_xss_clean($this->_delete_args[$key], $xss_clean) : NULL; - } - - /** - * Retrieve a value from a PATCH request - * - * @access public - * @param NULL $key Key to retrieve from the PATCH request - * If NULL an array of arguments is returned - * @param NULL $xss_clean Whether to apply XSS filtering - * @return array|string|NULL Value from the PATCH request; otherwise, NULL - */ - public function patch($key = NULL, $xss_clean = NULL) - { - if ($key === NULL) - { - return $this->_patch_args; - } - - return isset($this->_patch_args[$key]) ? $this->_xss_clean($this->_patch_args[$key], $xss_clean) : NULL; - } - - /** - * Retrieve a value from the query parameters - * - * @access public - * @param NULL $key Key to retrieve from the query parameters - * If NULL an array of arguments is returned - * @param NULL $xss_clean Whether to apply XSS filtering - * @return array|string|NULL Value from the query parameters; otherwise, NULL - */ - public function query($key = NULL, $xss_clean = NULL) - { - if ($key === NULL) - { - return $this->_query_args; - } - - return isset($this->_query_args[$key]) ? $this->_xss_clean($this->_query_args[$key], $xss_clean) : NULL; - } - - /** - * Sanitizes data so that Cross Site Scripting Hacks can be - * prevented - * - * @access protected - * @param string $value Input data - * @param bool $xss_clean Whether to apply XSS filtering - * @return string - */ - protected function _xss_clean($value, $xss_clean) - { - is_bool($xss_clean) || $xss_clean = $this->_enable_xss; - - return $xss_clean === TRUE ? $this->security->xss_clean($value) : $value; - } - - /** - * Retrieve the validation errors - * - * @access public - * @return array - */ - public function validation_errors() - { - $string = strip_tags($this->form_validation->error_string()); - - return explode(PHP_EOL, trim($string, PHP_EOL)); - } - - // SECURITY FUNCTIONS --------------------------------------------------------- - - /** - * Perform LDAP Authentication - * - * @access protected - * @param string $username The username to validate - * @param string $password The password to validate - * @return bool - */ - protected function _perform_ldap_auth($username = '', $password = NULL) - { - if (empty($username)) - { - log_message('debug', 'LDAP Auth: failure, empty username'); - return FALSE; - } - - log_message('debug', 'LDAP Auth: Loading configuration'); - - $this->config->load('ldap.php', TRUE); - - $ldap = [ - 'timeout' => $this->config->item('timeout', 'ldap'), - 'host' => $this->config->item('server', 'ldap'), - 'port' => $this->config->item('port', 'ldap'), - 'rdn' => $this->config->item('binduser', 'ldap'), - 'pass' => $this->config->item('bindpw', 'ldap'), - 'basedn' => $this->config->item('basedn', 'ldap'), - ]; - - log_message('debug', 'LDAP Auth: Connect to ' . (isset($ldaphost) ? $ldaphost : '[ldap not configured]')); - - // Connect to the ldap server - $ldapconn = ldap_connect($ldap['host'], $ldap['port']); - if ($ldapconn) - { - log_message('debug', 'Setting timeout to ' . $ldap['timeout'] . ' seconds'); - - ldap_set_option($ldapconn, LDAP_OPT_NETWORK_TIMEOUT, $ldap['timeout']); - - log_message('debug', 'LDAP Auth: Binding to ' . $ldap['host'] . ' with dn ' . $ldap['rdn']); - - // Binding to the ldap server - $ldapbind = ldap_bind($ldapconn, $ldap['rdn'], $ldap['pass']); - - // Verify the binding - if ($ldapbind === FALSE) - { - log_message('error', 'LDAP Auth: bind was unsuccessful'); - return FALSE; - } - - log_message('debug', 'LDAP Auth: bind successful'); - } - - // Search for user - if (($res_id = ldap_search($ldapconn, $ldap['basedn'], "uid=$username")) === FALSE) - { - log_message('error', 'LDAP Auth: User ' . $username . ' not found in search'); - return FALSE; - } - - if (ldap_count_entries($ldapconn, $res_id) !== 1) - { - log_message('error', 'LDAP Auth: Failure, username ' . $username . 'found more than once'); - return FALSE; - } - - if (($entry_id = ldap_first_entry($ldapconn, $res_id)) === FALSE) - { - log_message('error', 'LDAP Auth: Failure, entry of search result could not be fetched'); - return FALSE; - } - - if (($user_dn = ldap_get_dn($ldapconn, $entry_id)) === FALSE) - { - log_message('error', 'LDAP Auth: Failure, user-dn could not be fetched'); - return FALSE; - } - - // User found, could not authenticate as user - if (($link_id = ldap_bind($ldapconn, $user_dn, $password)) === FALSE) - { - log_message('error', 'LDAP Auth: Failure, username/password did not match: ' . $user_dn); - return FALSE; - } - - log_message('debug', 'LDAP Auth: Success ' . $user_dn . ' authenticated successfully'); - - $this->_user_ldap_dn = $user_dn; - - ldap_close($ldapconn); - - return TRUE; - } - - /** - * Perform Library Authentication - Override this function to change the way the library is called - * - * @access protected - * @param string $username The username to validate - * @param string $password The password to validate - * @return bool - */ - protected function _perform_library_auth($username = '', $password = NULL) - { - if (empty($username)) - { - log_message('error', 'Library Auth: Failure, empty username'); - return FALSE; - } - - $auth_library_class = $this->config->item('auth_library_class'); - $auth_library_function = $this->config->item('auth_library_function'); - - if (empty($auth_library_class)) - { - log_message('debug', 'Library Auth: Failure, empty auth_library_class'); - return FALSE; - } - - if (empty($auth_library_function)) - { - log_message('debug', 'Library Auth: Failure, empty auth_library_function'); - return FALSE; - } - - if (is_callable([$auth_library_class, $auth_library_function]) === FALSE) - { - $this->load->library($auth_library_class, array(false)); - } - - return $this->{strtolower($auth_library_class)}->$auth_library_function($username, $password); - } - - /** - * Check if the user is logged in - * - * @access protected - * @param string $username The user's name - * @param bool|string $password The user's password - * @return bool - */ - protected function _check_login($username = NULL, $password = FALSE) - { - if (empty($username)) - { - return FALSE; - } - - $auth_source = strtolower($this->config->item('auth_source')); - $rest_auth = strtolower($this->config->item('rest_auth')); - $valid_logins = $this->config->item('rest_valid_logins'); - - if (!$this->config->item('auth_source') && $rest_auth === 'digest') - { - // For digest we do not have a password passed as argument - return md5($username . ':' . $this->config->item('rest_realm') . ':' . (isset($valid_logins[$username]) ? $valid_logins[$username] : '')); - } - - if ($password === FALSE) - { - return FALSE; - } - - if ($auth_source === 'ldap') - { - log_message('debug', "Performing LDAP authentication for $username"); - - return $this->_perform_ldap_auth($username, $password); - } - - if ($auth_source === 'library') - { - log_message('debug', "Performing Library authentication for $username"); - - return $this->_perform_library_auth($username, $password); - } - - if (array_key_exists($username, $valid_logins) === FALSE) - { - return FALSE; - } - - if ($valid_logins[$username] !== $password) - { - return FALSE; - } - - return TRUE; - } - - /** - * Check to see if the user is logged in with a PHP session key - * - * @access protected - * @return void - */ - protected function _check_php_session() - { - // Get the auth_source config item - $key = $this->config->item('auth_source'); - - // If falsy, then the user isn't logged in - if (!$this->session->userdata($key)) - { - // Display an error response - $this->response([ - $this->config->item('rest_status_field_name') => FALSE, - $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_unauthorized') - ], self::HTTP_UNAUTHORIZED); - } - } - - /** - * Prepares for basic authentication - * - * @access protected - * @return void - */ - protected function _prepare_basic_auth() - { - // If whitelist is enabled it has the first chance to kick them out - if ($this->config->item('rest_ip_whitelist_enabled')) - { - $this->_check_whitelist_auth(); - } - - // Returns NULL if the SERVER variables PHP_AUTH_USER and HTTP_AUTHENTICATION don't exist - $username = $this->input->server('PHP_AUTH_USER'); - $http_auth = $this->input->server('HTTP_AUTHENTICATION'); - - $password = NULL; - if ($username !== NULL) - { - $password = $this->input->server('PHP_AUTH_PW'); - } - elseif ($http_auth !== NULL) - { - // If the authentication header is set as basic, then extract the username and password from - // HTTP_AUTHORIZATION e.g. my_username:my_password. This is passed in the .htaccess file - if (strpos(strtolower($http_auth), 'basic') === 0) - { - // Search online for HTTP_AUTHORIZATION workaround to explain what this is doing - list($username, $password) = explode(':', base64_decode(substr($this->input->server('HTTP_AUTHORIZATION'), 6))); - } - } - - // Check if the user is logged into the system - if ($this->_check_login($username, $password) === FALSE) - { - $this->_force_login(); - } - } - - /** - * Prepares for digest authentication - * - * @access protected - * @return void - */ - protected function _prepare_digest_auth() - { - // If whitelist is enabled it has the first chance to kick them out - if ($this->config->item('rest_ip_whitelist_enabled')) - { - $this->_check_whitelist_auth(); - } - - // We need to test which server authentication variable to use, - // because the PHP ISAPI module in IIS acts different from CGI - $digest_string = $this->input->server('PHP_AUTH_DIGEST'); - if ($digest_string === NULL) - { - $digest_string = $this->input->server('HTTP_AUTHORIZATION'); - } - - $unique_id = uniqid(); - - // The $_SESSION['error_prompted'] variable is used to ask the password - // again if none given or if the user enters wrong auth information - if (empty($digest_string)) - { - $this->_force_login($unique_id); - } - - // We need to retrieve authentication data from the $digest_string variable - $matches = []; - preg_match_all('@(username|nonce|uri|nc|cnonce|qop|response)=[\'"]?([^\'",]+)@', $digest_string, $matches); - $digest = (empty($matches[1]) || empty($matches[2])) ? [] : array_combine($matches[1], $matches[2]); - - // For digest authentication the library function should return - // already stored password for that username, even if it is hashed - $username = $this->_check_login($digest['username'], TRUE); - // If there no password - if (array_key_exists('username', $digest) === FALSE || $username === FALSE || $username === NULL) - { - $this->_force_login($unique_id); - } - // If the password was found for this username, generete the string md5('USERNAME:REALM:PASSWORD') - else - { - $username = md5($digest['username'].":".$this->config->item('rest_realm').":".$username); - } - - $md5 = md5(strtoupper($this->request->method) . ':' . $digest['uri']); - $valid_response = md5($username . ':' . $digest['nonce'] . ':' . $digest['nc'] . ':' . $digest['cnonce'] . ':' . $digest['qop'] . ':' . $md5); - - // Check if the string don't compare (case-insensitive) - if (strcasecmp($digest['response'], $valid_response) !== 0) - { - // Display an error response - $this->response([ - $this->config->item('rest_status_field_name') => FALSE, - $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_invalid_credentials') - ], self::HTTP_UNAUTHORIZED); - } - } - - /** - * Checks if the client's ip is in the 'rest_ip_blacklist' config and generates a 401 response - * - * @access protected - * @return void - */ - protected function _check_blacklist_auth() - { - // Match an ip address in a blacklist e.g. 127.0.0.0, 0.0.0.0 - $pattern = sprintf('/(?:,\s*|^)\Q%s\E(?=,\s*|$)/m', $this->input->ip_address()); - - // Returns 1, 0 or FALSE (on error only). Therefore implicitly convert 1 to TRUE - if (preg_match($pattern, $this->config->item('rest_ip_blacklist'))) - { - // Display an error response - $this->response([ - $this->config->item('rest_status_field_name') => FALSE, - $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_ip_denied') - ], self::HTTP_UNAUTHORIZED); - } - } - - /** - * Check if the client's ip is in the 'rest_ip_whitelist' config and generates a 401 response - * - * @access protected - * @return void - */ - protected function _check_whitelist_auth() - { - $whitelist = explode(',', $this->config->item('rest_ip_whitelist')); - - array_push($whitelist, '127.0.0.1', '0.0.0.0'); - - foreach ($whitelist as &$ip) - { - // As $ip is a reference, trim leading and trailing whitespace, then store the new value - // using the reference - $ip = trim($ip); - } - - if (in_array($this->input->ip_address(), $whitelist) === FALSE) - { - $this->response([ - $this->config->item('rest_status_field_name') => FALSE, - $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_ip_unauthorized') - ], self::HTTP_UNAUTHORIZED); - } - } - - /** - * Force logging in by setting the WWW-Authenticate header - * - * @access protected - * @param string $nonce A server-specified data string which should be uniquely generated - * each time - * @return void - */ - protected function _force_login($nonce = '') - { - $rest_auth = $this->config->item('rest_auth'); - $rest_realm = $this->config->item('rest_realm'); - if (strtolower($rest_auth) === 'basic') - { - // See http://tools.ietf.org/html/rfc2617#page-5 - header('WWW-Authenticate: Basic realm="' . $rest_realm . '"'); - } - elseif (strtolower($rest_auth) === 'digest') - { - // See http://tools.ietf.org/html/rfc2617#page-18 - header( - 'WWW-Authenticate: Digest realm="' . $rest_realm - . '", qop="auth", nonce="' . $nonce - . '", opaque="' . md5($rest_realm) . '"'); - } - - // Display an error response - $this->response([ - $this->config->item('rest_status_field_name') => FALSE, - $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_unauthorized') - ], self::HTTP_UNAUTHORIZED); - } - - /** - * Updates the log table with the total access time - * - * @access protected - * @author Chris Kacerguis - * @return bool TRUE log table updated; otherwise, FALSE - */ - protected function _log_access_time() - { - $payload['rtime'] = $this->_end_rtime - $this->_start_rtime; - - return $this->rest->db->update( - $this->config->item('rest_logs_table'), $payload, [ - 'id' => $this->_insert_id - ]); - } - - /** - * Updates the log table with HTTP response code - * - * @access protected - * @author Justin Chen - * @param $http_code int HTTP status code - * @return bool TRUE log table updated; otherwise, FALSE - */ - protected function _log_response_code($http_code) - { - $payload['response_code'] = $http_code; - - return $this->rest->db->update( - $this->config->item('rest_logs_table'), $payload, [ - 'id' => $this->_insert_id - ]); - } - - /** - * Check to see if the API key has access to the controller and methods - * - * @access protected - * @return bool TRUE the API key has access; otherwise, FALSE - */ - protected function _check_access() - { - // If we don't want to check access, just return TRUE - if ($this->config->item('rest_enable_access') === FALSE) - { - return TRUE; - } - - // Fetch controller based on path and controller name - $controller = implode( - '/', [ - $this->router->directory, - $this->router->class - ]); - - // Remove any double slashes for safety - $controller = str_replace('//', '/', $controller); - - // Query the access table and get the number of results - return $this->rest->db - ->where('key', $this->rest->key) - ->where('controller', $controller) - ->get($this->config->item('rest_access_table')) - ->num_rows() > 0; - } -} diff --git a/application/dbskel/fue/TBL_aktivitaet.php b/application/dbskel/fue/TBL_aktivitaet.php deleted file mode 100644 index 05027ba92..000000000 --- a/application/dbskel/fue/TBL_aktivitaet.php +++ /dev/null @@ -1,27 +0,0 @@ - array( - 'aktivitaet_kurzbz' => array( - 'comment' => 'I guess this is the PK', - 'type' => 'character varying(16)', - 'null' => false - ), - 'beschreibung' => array( - 'comment' => 'none', - 'type' => 'character varying(256)', - 'null' => false, - 'default' => "'Test string'" - ), - 'sort' => array( - 'comment' => 'nope', - 'type' => 'integer', - 'default' => 1 - ), - 'oe_kurzbz' => array( - 'comment' => 'uhm', - 'type' => 'character varying(32)' - ) - ), - 'comment' => 'Timesheet SLA Activity' -); diff --git a/application/dbskel/fue/constraints.php b/application/dbskel/fue/constraints.php deleted file mode 100644 index a3e534cf1..000000000 --- a/application/dbskel/fue/constraints.php +++ /dev/null @@ -1,8 +0,0 @@ - 'ALTER TABLE fue.tbl_aktivitaet ADD CONSTRAINT pk_tbl_aktivitaet PRIMARY KEY (aktivitaet_kurzbz)', - 'fk_projekt_oe' => 'ALTER TABLE fue.tbl_aktivitaet ADD CONSTRAINT fk_test FOREIGN KEY (oe_kurzbz) REFERENCES public.tbl_organisationseinheit (oe_kurzbz)', - 'uk_beschreibung' => 'ALTER TABLE fue.tbl_aktivitaet ADD CONSTRAINT uk_beschreibung UNIQUE (beschreibung)', - 'testchk' => 'ALTER TABLE fue.tbl_aktivitaet ADD CONSTRAINT testchk CHECK (sort > 0)' -); diff --git a/application/dbskel/fue/extra.sql b/application/dbskel/fue/extra.sql deleted file mode 100644 index 3d826b40f..000000000 --- a/application/dbskel/fue/extra.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT 'Extra file' AS justatest; diff --git a/application/dbskel/fue/functions.php b/application/dbskel/fue/functions.php deleted file mode 100644 index f3dab4498..000000000 --- a/application/dbskel/fue/functions.php +++ /dev/null @@ -1,19 +0,0 @@ - - 'CREATE OR REPLACE FUNCTION fue.get_highest_content_version(bigint) RETURNS smallint AS $$ - DECLARE i_content_id ALIAS FOR $1; - DECLARE rec RECORD; - BEGIN - - SELECT INTO rec version - FROM campus.tbl_contentsprache - WHERE content_id = i_content_id - ORDER BY version desc - LIMIT 1; - - RETURN rec.version; - END; - $$ LANGUAGE plpgsql;' -); diff --git a/application/dbskel/fue/grants.sql b/application/dbskel/fue/grants.sql deleted file mode 100644 index cdc8c9c95..000000000 --- a/application/dbskel/fue/grants.sql +++ /dev/null @@ -1,20 +0,0 @@ ------------------------------------------------------ --- Revokes all privileges from all granted users ------------------------------------------------------ -REVOKE ALL PRIVILEGES ON SCHEMA fue FROM vilesci; -REVOKE ALL ON ALL TABLES IN SCHEMA fue FROM vilesci; -REVOKE ALL ON ALL SEQUENCES IN SCHEMA fue FROM vilesci; -REVOKE ALL ON ALL FUNCTIONS IN SCHEMA fue FROM vilesci; - ----------------------------------------------------------------------------------------------------- --- Gives the desired privileges to the chosen users (with great power comes great responsibility!) ----------------------------------------------------------------------------------------------------- - --- Schema privileges -GRANT ALL ON SCHEMA fue TO vilesci; -GRANT USAGE ON SCHEMA fue TO web; -GRANT USAGE ON SCHEMA fue TO wawi; - --- Sequences privileges -GRANT SELECT,UPDATE ON SEQUENCE fue.seq_projekt_dokument_projekt_dokument_id TO vilesci; -GRANT SELECT,UPDATE ON SEQUENCE fue.seq_projekt_dokument_projekt_dokument_id TO web; diff --git a/application/dbskel/fue/schema.sql b/application/dbskel/fue/schema.sql deleted file mode 100644 index 1dc28d796..000000000 --- a/application/dbskel/fue/schema.sql +++ /dev/null @@ -1,4 +0,0 @@ --- Create the schema if not exists -CREATE SCHEMA IF NOT EXISTS fue; --- Comment schema -COMMENT ON SCHEMA fue IS 'Projectmanagement'; diff --git a/application/dbskel/fue/sequences.php b/application/dbskel/fue/sequences.php deleted file mode 100644 index 98a1ca60b..000000000 --- a/application/dbskel/fue/sequences.php +++ /dev/null @@ -1,11 +0,0 @@ - - 'CREATE SEQUENCE fue.seq_projekt_dokument_projekt_dokument_id - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1;' -); diff --git a/application/dbskel/fue/views.php b/application/dbskel/fue/views.php deleted file mode 100644 index 69b911714..000000000 --- a/application/dbskel/fue/views.php +++ /dev/null @@ -1,50 +0,0 @@ - - 'CREATE OR REPLACE VIEW fue.vw_projektressourcen ( - projekt_ressource_id, - projekt_kurzbz, - projektphase_id, - projektphase, - typ, - ressource_id, - ressource, - funktion_kurzbz, - start, - ende, - oe_kurzbz, - projektbudget, - aufwandstyp_kurzbz, - projektphase_fk, - phasenbudget, - personentage, - nummer, - titel, - aufwand - ) - AS - SELECT tpr.projekt_ressource_id, - COALESCE(tpr.projekt_kurzbz, tpp.projekt_kurzbz) AS projekt_kurzbz, - tpr.projektphase_id, - tpp.bezeichnung AS projektphase, - COALESCE(tpp.typ, \'Projekt\'::character varying) AS typ, - tpr.ressource_id, - tr.bezeichnung AS ressource, - tpr.funktion_kurzbz, - COALESCE(tpp.start, tp.beginn) AS start, - COALESCE(tpp.ende, tp.ende) AS ende, - tp.oe_kurzbz, - tp.budget AS projektbudget, - tp.aufwandstyp_kurzbz, - tpp.projektphase_fk, - tpp.budget AS phasenbudget, - tpp.personentage, - tp.nummer, - tp.titel, - tpr.aufwand - FROM fue.tbl_projekt_ressource tpr - JOIN fue.tbl_ressource tr USING (ressource_id) - LEFT JOIN fue.tbl_projekt tp USING (projekt_kurzbz) - LEFT JOIN fue.tbl_projektphase tpp USING (projektphase_id);' -); diff --git a/application/dbskel/index.html b/application/dbskel/index.html deleted file mode 100644 index b702fbc39..000000000 --- a/application/dbskel/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/application/helpers/hlp_authentication_helper.php b/application/helpers/hlp_authentication_helper.php index 1c2e3603d..459c7fb80 100644 --- a/application/helpers/hlp_authentication_helper.php +++ b/application/helpers/hlp_authentication_helper.php @@ -2,20 +2,62 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); -// ------------------------------------------------------------------------ +// ----------------------------------------------------------------------------------------------------- // Functions needed to manage the user authentication -// ------------------------------------------------------------------------ +// NOTE: the following functions do NOT prompt a login page if the user is NOT logged in +// ----------------------------------------------------------------------------------------------------- /** - * It calls the AuthLib, if the user is NOT logged then the login page is shown + * If the user is NOT logged then a null value is returned. + * If the user is alredy logged, then it is possible to access to the authentication object + * that contains the person_id of the logged user + * NOTE: if a user is logged then a person_id is always present! + */ +function getAuthPersonId() +{ + $ci =& get_instance(); // get CI instance + + return isLogged() ? ($ci->authlib->getAuthObj())->{AuthLib::AO_PERSON_ID} : null; +} + +/** + * If the user is NOT logged then a null value is returned. * If the user is alredy logged, then it is possible to access to the authentication object * that contains the username of the logged user - * - * @return string or null + * NOTE: if the user is logged with a "foreign" method (ex. Bewerbungstool), + * then it is possible that the username is null! */ function getAuthUID() { $ci =& get_instance(); // get CI instance - return ($ci->authlib->getAuthObj())->{AuthLib::AO_USERNAME}; + return isLogged() ? ($ci->authlib->getAuthObj())->{AuthLib::AO_USERNAME} : null; +} + +/** + * If the user is NOT logged then a null value is returned. + * If the user is alredy logged, then it is possible to access to the authentication object + * that contains the firstname of the logged user + * NOTE: if the user is logged with a "foreign" method (ex. Bewerbungstool), + * then it is possible that the firstname is null! + */ +function getAuthFirstname() +{ + $ci =& get_instance(); // get CI instance + + return isLogged() ? ($ci->authlib->getAuthObj())->{AuthLib::AO_NAME} : null; +} + +/** + * If the user is NOT logged then a null value is returned. + * If the user is alredy logged, then it is possible to access to the authentication object + * that contains the surname of the logged user + * NOTE: if the user is logged with a "foreign" method (ex. Bewerbungstool), + * then it is possible that the surname is null! + */ +function getAuthSurname() +{ + $ci =& get_instance(); // get CI instance + + return isLogged() ? ($ci->authlib->getAuthObj())->{AuthLib::AO_SURNAME} : null; } diff --git a/application/helpers/hlp_common_helper.php b/application/helpers/hlp_common_helper.php index bc09cd32c..6a2675a04 100644 --- a/application/helpers/hlp_common_helper.php +++ b/application/helpers/hlp_common_helper.php @@ -24,39 +24,54 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); // ------------------------------------------------------------------------ /** - * generateToken() - generates a new token for diffent use - * - reading Messages from external - * - forgotten Password - * - * @return string + * Generates a new token for diffent use cases. Default token length is 64 + * - Reading messages + * - Forgotten password + * - etc + * Returns null on failure */ function generateToken($length = 64) { + $token = null; + $firstGeneratedToken = null; + // For PHP 7 you can use random_bytes() if (function_exists('random_bytes')) { - $token = base64_encode(random_bytes($length)); - //base64 is about 33% longer, so we need to truncate the result - return strtr(substr($token, 0, $length), '+/=', '-_,'); + try + { + $firstGeneratedToken = random_bytes($length); // try to generates cryptographically secure pseudo-random bytes... + } + catch (Exception $e) { $firstGeneratedToken = null; } // if fails $firstGeneratedToken is set to null } - - // for PHP >=5.3 and <7 - if (function_exists('openssl_random_pseudo_bytes')) + // For PHP >= 5.3 and < 7 and openssl is available + elseif (function_exists('openssl_random_pseudo_bytes')) { - $token = base64_encode(openssl_random_pseudo_bytes($length, $strong)); - // is the token strong enough? - if($strong == true) - return strtr(substr($token, 0, $length), '+/=', '-_,'); + $firstGeneratedToken = openssl_random_pseudo_bytes($length, $strong); + // If the token generation ended with errors OR the generated token is NOT strong enough + if ($firstGeneratedToken == false || $strong == false) $firstGeneratedToken = null; // $firstGeneratedToken is set to null } - //fallback to mt_rand if php < 5.3 or no openssl available - $characters = '0123456789'; - $characters .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/+'; - $charactersLength = strlen($characters)-1; - $token = ''; - //select some random characters - for ($i = 0; $i < $length; $i++) - $token .= $characters[mt_rand(0, $charactersLength)]; + if ($firstGeneratedToken != null) // If everything was fine + { + // base64 is about 33% longer, so we need to truncate the result + $token = strtr(substr(base64_encode($firstGeneratedToken), 0, $length), '+/=', '-_,'); + } + + // Fallback to mt_rand if: + // php < 5.3 + // OR no openssl is available + // OR openssl_random_pseudo_bytes used an algorithm that is cryptographically NOT strong + // OR one of the previous methods failed + if ($token == null) + { + $token = ''; // set $token as an empty string + $characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/+'; + $charactersLength = strlen($characters) - 1; + + // Select some random characters + for ($i = 0; $i < $length; $i++) $token .= $characters[mt_rand(0, $charactersLength)]; + } return $token; } @@ -224,3 +239,65 @@ function isDateWorkingDay($date, $days = null) return true; } } + +/** + * Parse the given text using the given data parameter + * Use the CI parser which performs simple text substitution for pseudo-variable + */ +function parseText($text, $data) +{ + $ci =& get_instance(); // get CI instance + $ci->load->library('parser'); // Loads CI parser library + + return $ci->parser->parse_string($text, $data, true); +} + +/** + * Parse the given template using the given data parameter + * Use the CI parser which performs simple text substitution for pseudo-variable + */ +function parseTemplate($template, $data) +{ + $ci =& get_instance(); // get CI instance + $ci->load->library('parser'); // Loads CI parser library + + return $ci->parser->parse($template, $data, true); +} + +/** + * Terminate immediately the execution of the current script. + * If message parameter is given then: + * - logs the given message in CI logs + * - prints the given message to standard output + * Otherwise terminate with the generic error + */ +function terminateWithError($message = null) +{ + if (!isEmptyString($message)) + { + $ci =& get_instance(); // get CI instance + $ci->load->library('LogLib'); // Loads LogLib + + $ci->loglib->logError($message); + + exit($message); + } + + exit(EXIT_ERROR); +} + +/** + * Checks if the current user is logged by checking that the AuthLib is loaded and + * it is present the authentication object in session + * NOTE: it is placed here instead of being placed in the helper hlp_authentication_helper + * because hlp_authentication_helper is loaded after the authentication. + * It is very useful to use this function even in those parts of the code that are accessible + * even when a user is NOT authenticated!!! + * If and only if this function returns true, then all the functions present in hlp_authentication_helper can be used! + */ +function isLogged() +{ + $ci =& get_instance(); // get CI instance + + return isset($ci->authlib) && $ci->authlib->getAuthObj() != null; +} diff --git a/application/helpers/hlp_header_helper.php b/application/helpers/hlp_header_helper.php index 611325722..1a0d9dc49 100644 --- a/application/helpers/hlp_header_helper.php +++ b/application/helpers/hlp_header_helper.php @@ -46,13 +46,16 @@ function generateCSSsInclude($CSSs) { $cssLink = ''; + $ci =& get_instance(); + $cachetoken = '?'.$ci->config->item('fhcomplete_build_version'); + if (isset($CSSs)) { $tmpCSSs = is_array($CSSs) ? $CSSs : array($CSSs); for ($tmpCSSsCounter = 0; $tmpCSSsCounter < count($tmpCSSs); $tmpCSSsCounter++) { - $toPrint = sprintf($cssLink, base_url($tmpCSSs[$tmpCSSsCounter])).PHP_EOL; + $toPrint = sprintf($cssLink, base_url($tmpCSSs[$tmpCSSsCounter]).$cachetoken).PHP_EOL; if ($tmpCSSsCounter > 0) $toPrint = "\t\t".$toPrint; @@ -108,13 +111,16 @@ function generateJSsInclude($JSs) { $jsInclude = ''; + $ci =& get_instance(); + $cachetoken = '?'.$ci->config->item('fhcomplete_build_version'); + if (isset($JSs)) { $tmpJSs = is_array($JSs) ? $JSs : array($JSs); for ($tmpJSsCounter = 0; $tmpJSsCounter < count($tmpJSs); $tmpJSsCounter++) { - $toPrint = sprintf($jsInclude, base_url($tmpJSs[$tmpJSsCounter])).PHP_EOL; + $toPrint = sprintf($jsInclude, base_url($tmpJSs[$tmpJSsCounter].$cachetoken)).PHP_EOL; if ($tmpJSsCounter > 0) $toPrint = "\t\t".$toPrint; diff --git a/application/helpers/hlp_language_helper.php b/application/helpers/hlp_language_helper.php index 4dfb53c7b..1678a4102 100644 --- a/application/helpers/hlp_language_helper.php +++ b/application/helpers/hlp_language_helper.php @@ -18,28 +18,48 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); /** * Function to retrieve the language of the logged user - * If is not possible to retrieve it, then the default system language is returnd - * If as parameter is given a valid language the it's returned useful to avoid - * to write the same control structures for the language + * If is not possible to retrieve it, then the default system language is returned + * NOTE: If the given parameter is a valid language then it is returned + * It is useful to avoid to write a lot of "if else" structures */ function getUserLanguage($language = null) { + // If the given parameter is a valid language then return it if (!isEmptyString($language)) return $language; - $ci =& get_instance(); // get CI instance - - // Use the default system language, if it's possible retrieves the language for the logged user + // Use the default system language as fallback $language = DEFAULT_LANGUAGE; - // Checks if the user is authenticated to retrieve the users's language - // NOTE: this helper could be called when the user is not logged in the system - // so this is why is checked if the function getAuthUID exists - if (function_exists('getAuthUID')) + + // If the language is present in the session and it is valid + if (isset($_SESSION[LANG_SESSION_CURRENT_LANGUAGE]) && !isEmptyString($_SESSION[LANG_SESSION_CURRENT_LANGUAGE])) { + $language = $_SESSION[LANG_SESSION_CURRENT_LANGUAGE]; // then use it + } + // Otherwise checks if the user is authenticated to retrieve the users's language + // NOTE: this helper could be called when the user is NOT logged in the system + // therefore is checked if the user is logged + elseif (isLogged()) + { + $ci =& get_instance(); // get CI instance + // NOTE: Stores the loaded model with the alias PersonModelLanguage to avoid to overwrite // an already loaded PersonModel used somewhere else $ci->load->model('person/Person_model', 'PersonModelLanguage'); - $language = $ci->PersonModelLanguage->getLanguage(getAuthUID()); + // Retrieves language/s for the logged user + $languagesDB = $ci->PersonModelLanguage->getLanguage(getAuthUID()); + if (hasData($languagesDB)) + { + // Looks for the first valid language + foreach (getData($languagesDB) as $languageDB) + { + if (!isEmptyString($languageDB->sprache)) + { + $language = $languageDB->sprache; + break; + } + } + } } return $language; @@ -62,31 +82,21 @@ function getPhraseByLanguage($phraseLanguagesArray, $language) $langArray = getSessionElement(LANG_SESSION_NAME, LANG_SESSION_INDEXES); if ($langArray == null) // If not already loaded in session { - // Loads the Sprache_model to retrieve the language settings from the DB - // NOTE: Stores the loaded model with the alias SpracheModelLanguage to avoid to overwrite - // an already loaded SpracheModel used somewhere else - $ci->load->model('system/Sprache_model', 'SpracheModelLanguage'); - - // Add order clause by index and select only the sprache column - $ci->SpracheModelLanguage->addOrder('index'); - $ci->SpracheModelLanguage->addSelect('sprache'); - - // Retrieves from public.tbl_sprache - $dbLanguages = $ci->SpracheModelLanguage->load(); + // Retrieves active languages + $dbLanguages = getDBActiveLanguages(); if (hasData($dbLanguages)) // If everything is ok and contains data { $index = 0; // Incremental integer - $languageIndexes = array(); // Array that will contains languages and their indexes + $langArray = array(); // Array that will contains languages and their indexes // Loops through database results foreach (getData($dbLanguages) as $dbLanguage) { - $languageIndexes[$dbLanguage->sprache] = $index++; // set $languageIndexes array elements + $langArray[$dbLanguage->sprache] = $index++; // set $languageIndexes array elements } } - $langArray = $languageIndexes; // copy $languageIndexes to $langArray - // Set session element $_SESSION['LANG']['LANG_INDEXES'] with $languageIndexes + // Set session element $_SESSION['LANG']['LANG_INDEXES'] with $langArray setSessionElement(LANG_SESSION_NAME, LANG_SESSION_INDEXES, $langArray); } @@ -100,3 +110,78 @@ function getPhraseByLanguage($phraseLanguagesArray, $language) return $phrase; } + +/** + * Tries to load active languages from session, if not present then loads them from database and stores them in session + */ +function getActiveLanguages() +{ + $languagesArray = getSessionElement(LANG_SESSION_NAME, LANG_SESSION_ACTIVE_LANGUAGES); + if ($languagesArray == null) + { + $languagesArray = array(); + + // Retrieves from public.tbl_sprache + $dbLanguages = getDBActiveLanguages(); + if (hasData($dbLanguages)) + { + // Loops through database results + foreach (getData($dbLanguages) as $dbLanguage) + { + $languagesArray[$dbLanguage->sprache] = $dbLanguage->bezeichnung; // set $languageIndexes array elements + } + } + + // Set session element $_SESSION['LANG']['LANG_SESSION_ACTIVE_LANGUAGES'] with $languagesArray + setSessionElement(LANG_SESSION_NAME, LANG_SESSION_ACTIVE_LANGUAGES, $languagesArray); + } + + return $languagesArray; +} + +/** + * Loads active languages from database + */ +function getDBActiveLanguages() +{ + $ci =& get_instance(); // get CI instance + + // Loads the Sprache_model to retrieve the language settings from the DB + // NOTE: Stores the loaded model with the alias SpracheModelLanguage to avoid to overwrite + // an already loaded SpracheModel used somewhere else + $ci->load->model('system/Sprache_model', 'SpracheModelLanguage'); + + // Add order clause by index and select only the sprache column + $ci->SpracheModelLanguage->addOrder('index'); + $ci->SpracheModelLanguage->addSelect('sprache, bezeichnung'); + + // Retrieves from public.tbl_sprache + return $ci->SpracheModelLanguage->loadWhere(array('content' => true)); +} + +/** + * Sets the current language to render the GUI in session + */ +function setUserLanguage($language) +{ + $languageValid = false; + + // Checks if the given language is valid (present between active languages) + foreach (getActiveLanguages() as $languageName => $languageTranslation) + { + if ($language == $languageName) + { + $languageValid = true; + break; + } + } + + if ($languageValid) // if the provided language is valid + { + $_SESSION[LANG_SESSION_CURRENT_LANGUAGE] = $language; // stores it in session + + return success('Language successfully changed'); // return success!! + } + + return error('The given language is not valid'); // return an error +} diff --git a/application/helpers/hlp_return_object_helper.php b/application/helpers/hlp_return_object_helper.php index 03b56bbbc..cc896856d 100644 --- a/application/helpers/hlp_return_object_helper.php +++ b/application/helpers/hlp_return_object_helper.php @@ -125,3 +125,18 @@ function getCode($result) return $code; } + +/** + * Returns the property retval if present, otherwise null + */ +function getError($result) +{ + $error = null; + + if (isset($result->retval)) + { + $error = $result->retval; + } + + return $error; +} diff --git a/application/helpers/hlp_sancho_helper.php b/application/helpers/hlp_sancho_helper.php index 6f5ef8c24..5d2d9f1f1 100644 --- a/application/helpers/hlp_sancho_helper.php +++ b/application/helpers/hlp_sancho_helper.php @@ -98,9 +98,7 @@ function _parseMailContent($vorlage_kurzbz, $vorlage_data) !isEmptyString($result->retval[0]->text)) { // Parses template text - $parsedText = $ci->vorlagelib->parseVorlagetext($result->retval[0]->text, $vorlage_data); - - return $parsedText; + return parseText($result->retval[0]->text, $vorlage_data); } } } diff --git a/application/language/english/rest_controller_lang.php b/application/language/english/rest_controller_lang.php deleted file mode 100644 index 1c665bdc5..000000000 --- a/application/language/english/rest_controller_lang.php +++ /dev/null @@ -1,17 +0,0 @@ -_createAuthObjByPerson(array('uid' => $_SERVER['PHP_AUTH_USER'])); + // NOTE: Username needs to be trimmed and lowered because htaccess is allowing login + $hta = $this->_createAuthObjByPerson(array('uid' => mb_strtolower(trim($_SERVER['PHP_AUTH_USER'])))); } // Invalid credentials @@ -391,7 +391,7 @@ class AuthLib } elseif (isError($hta)) // display error and stop execution { - $this->_showError(getData($hta)); + $this->_showError(getError($hta)); } return $hta; // if success then is returned! @@ -483,6 +483,8 @@ class AuthLib /** * Stores the authentication object into the authentication session + * Everything was fine, the user at this point is authenticated, it is possible to store the authentication object + * in the user session */ private function _storeSessionAuthObj($authObj) { @@ -549,10 +551,15 @@ class AuthLib } elseif (isError($auth)) // blocking error { - $this->_showError(getData($auth)); // display a generic error message and logs the occurred error + $this->_showError(getError($auth)); // display a generic error message and logs the occurred error } } - // else the user is already logged, then continue with the execution + // else the user is already logged, then loads authentication helper and continue with the execution + // NOTE: it is needed only here because: + // - it is called when a user is already logged in + // - it is called after login the user + // - it is NOT called in case of fatal error or wrong authentication + $this->_ci->load->helper('hlp_authentication'); } /** @@ -568,10 +575,11 @@ class AuthLib // Needed information $this->_ci->PersonModel->addSelect('person_id, vorname, nachname, uid'); - // Retrieves the uid if it is possible - $this->_ci->PersonModel->addJoin('public.tbl_benutzer', 'person_id', 'LEFT'); - - $queryParamsArray['tbl_person.aktiv'] = true; // only active users! + // Retrieves the uid if it is possible for active users + $this->_ci->PersonModel->addJoin( + '(SELECT uid, person_id FROM public.tbl_benutzer WHERE aktiv = TRUE) tb', 'person_id', + 'LEFT' + ); // Execute query with where clause $personResult = $this->_ci->PersonModel->loadWhere($queryParamsArray); diff --git a/application/libraries/CallerLib.php b/application/libraries/CallerLib.php deleted file mode 100644 index 82883cac4..000000000 --- a/application/libraries/CallerLib.php +++ /dev/null @@ -1,360 +0,0 @@ -_ci =& get_instance(); // Gets CI instance - } - - /** - * Wrapper method for _call - */ - public function callLibrary($callParameters) - { - return $this->_call($callParameters); - } - - /** - * Wrapper method for _call - */ - public function callModel($callParameters) - { - return $this->_call($callParameters); - } - - /** - * Everything starts here... - */ - private function _call($callParameters) - { - $result = null; - $parameters = $this->_getParameters($callParameters); - $validation = $this->_validateCall($parameters); - - // If the validation was passed - if (isSuccess($validation)) - { - $loaded = null; - // If the given resource is a model - if (strpos($parameters->resourceName, CallerLib::MODEL_PREFIX) !== false) - { - // Try to load the model - $result = $this->_loadModel($parameters->resourcePath, $parameters->resourceName); - if (isSuccess($result)) - { - $loaded = $result->retval; - } - } - // If the given resource is a library - elseif (strpos($parameters->resourceName, CallerLib::LIB_PREFIX) !== false) - { - // Check if the resource is already loaded, it works only with libraries and drivers - $isLoaded = $this->_ci->load->is_loaded($parameters->resourceName); - // If not loaded then load it - if ($isLoaded === false) - { - // Try to load the library - $result = $this->_loadLibrary($parameters->resourcePath, $parameters->resourceName); - if (isSuccess($result)) - { - $loaded = $result->retval; - } - } - // If it is already loaded $isLoaded contains the instance of the library - else - { - $loaded = $isLoaded; - } - } - // Wrong selection! - else - { - $result = error('Neither a lib nor model: '.$parameters->resourcePath.$parameters->resourceName); - } - - // If the resource was found and loaded - if (!is_null($loaded)) - { - $result = $this->_callThis($parameters->resourceName, $parameters->function, $parameters->parameters); - } - else - { - // Resource not loaded - } - } - else - { - $result = $validation; - } - - return $result; - } - - /** - * Gets the parameters from the http call - * Search for parameters and - * is the name of the model or of the library - * is the name of the method present in the model/library - * All the others parameters will be given to the method in the same order that - * they are present in the HTTP call - * EX: - * URL: ../system/CallerLibrary/Call?resource=&function=&=&=&= - * will call .(par1, par2, par3) - */ - private function _getParameters($parametersArray) - { - $parameters = new stdClass(); - $parameters->parameters = array(); - $count = 0; - - foreach ($parametersArray as $parameterName => $parameterValue) - { - // The name of the resource, path included - if ($parameterName == CallerLib::RESOURCE_PARAMETER) - { - // Separates the resource path from the resource name - $splittedResource = preg_split(CallerLib::REG_SPLIT_EXPR, $parameterValue); - $parameters->resourceName = $splittedResource[count($splittedResource) - 1]; - $parameters->resourcePath = str_replace($parameters->resourceName, '', $parameterValue); - } - // The name of the function - elseif ($parameterName == CallerLib::FUNCTION_PARAMETER) - { - $parameters->function = $parameterValue; - } - // It is assumed that all other parameters are the parameters to be passed to the function - // They will be passed to the function in the same order in which they are passed to - // this controller - else - { - $parameters->parameters[$count++] = $parameterValue; - } - } - - return $parameters; - } - - /** - * Validate the given parameters - */ - private function _validateCall($parameters) - { - if (!is_object($parameters)) - { - return error('Parameter is not an object'); - } - if (!isset($parameters->resourcePath)) - { - return error('Resource path is not specified'); - } - if (!isset($parameters->resourceName)) - { - return error('Resource name is not specified'); - } - if (!isset($parameters->function)) - { - return error('Function is not specified'); - } - if (!is_array($parameters->parameters)) - { - return error('Parameters are not specified'); - } - if (in_array($parameters->resourceName, CallerLib::$RESOURCES_BLACK_LIST)) - { - return error('You are trying to access to unauthorized resources'); - } - - return success('Input data are valid'); - } - - /** - * Loads a model using the given path and name - * - * NOTE: the models automatically handle the permissions - */ - private function _loadModel($resourcePath, $resourceName) - { - $loaded = null; - $result = null; - - try - { - $loaded = $this->_ci->load->model($resourcePath.$resourceName); - } - catch (Exception $e) - { - // Errors while loading the model - $result = error('Errors while loading the model: '.$e->getMessage()); - } - - if (!is_null($loaded)) - { - $result = success($loaded); - } - - return $result; - } - - /** - * Loads a library using the given path and name - * - * The method 'library' of the class CI_Loader provided by CI has some limitations, - * so to be able to check errors was used a workaround. - * It consists in: - * - Checking if the file (identified by parameters $resourcePath and $resourceName) exists - * - If exists it will be loaded using the method 'file' from CI_Loader - * - Checks if the loaded file contains a class identified by parameter $resourceName - * - * If one of the previous tests fails, it will be returned a null value - */ - private function _loadLibrary($resourcePath, $resourceName) - { - $loaded = null; - - try - { - // Gets all the configured resources paths - $packagePaths = $this->_ci->load->get_package_paths(); - // Looking for a file in every paths with the same name of the resource - $found = null; - for ($i = 0; $i < count($packagePaths) && is_null($found); $i++) - { - $file = $packagePaths[$i].CallerLib::LIBS_PATH.DIRECTORY_SEPARATOR. - $resourcePath.$resourceName.CallerLib::LIB_FILE_EXTENSION; - if (file_exists($file)) - { - $found = $file; - } - } - - // If the file was found - if (!is_null($found)) - { - // Load the file - $loaded = $this->_ci->load->file($found); - // If the resource is not present inside the file - if (!class_exists($resourceName)) - { - $loaded = null; - // Same phrase error as load->model() provided by CI - $result = error($found.' exists, but doesn\'t declare class '.$resourceName); - } - } - else - { - $loaded = null; - // Same phrase error as load->model() provided by CI - $result = error('Unable to load the requested class: '.$resourceName); - } - } - catch (Exception $e) - { - // Errors while loading the library - $result = error('Errors while loading the library: '.$e->getMessage()); - } - - if (!is_null($loaded)) - { - $result = success($loaded); - } - - return $result; - } - - /** - * Calls a method of a class with the given parameters and returns its result - * - * @param string $resourceName identifies the class name - * @param string $function identifies the method name - * @param array $parameters contains the parameters to be passed to the method - */ - private function _callThis($resourceName, $function, $parameters) - { - $result = null; - - try - { - // Get informations about the function - $reflectionMethod = new ReflectionMethod($resourceName, $function); - // If the number of given parameters is greater or equal to the number of - // parameters required by the function - if (count($parameters) >= $reflectionMethod->getNumberOfRequiredParameters()) - { - // If the function is static - if ($reflectionMethod->isStatic() === true) - { - $classMethod = $resourceName.'::'.$function; - } - // If the function is not static - else - { - $classMethod = array(new $resourceName(), $function); - } - - // If the resource's function is callable - if (is_callable($classMethod)) - { - // Call resource->function() - // @ was applied to prevent really ugly and unmanageable errors - $resultCall = @call_user_func_array($classMethod, $parameters); - // If errors occurred while running it - // NOTE: if the called function via call_user_func_array returns a boolean set as false, - // it will be recognized like a running error. A little bit tricky ;) - if ($resultCall === false) - { - $result = error('Error running '.$resourceName.'->'.$function.'()'); - } - // Returns the result of resource->function() - else - { - $result = success($resultCall); - } - } - else - { - $result = error($resourceName.'->'.$function.'() is not callable!'); - } - } - else - { - $result = error( - 'Number of required parameters: '.$reflectionMethod->getNumberOfRequiredParameters().'. Given: '.count($parameters) - ); - } - } - catch (Exception $e) - { - $result = error($e->getMessage()); - } - - return $result; - } -} diff --git a/application/libraries/CryptLib.php b/application/libraries/CryptLib.php new file mode 100644 index 000000000..ea19f3e5b --- /dev/null +++ b/application/libraries/CryptLib.php @@ -0,0 +1,28 @@ +setBlockLength(256); + $cipher->setKey($key); + + if ($paddingDisabled === true) $cipher->disablePadding(); + + return $cipher->encrypt($value); + } +} diff --git a/application/libraries/DBSkelLib.php b/application/libraries/DBSkelLib.php deleted file mode 100644 index 1d556d9a4..000000000 --- a/application/libraries/DBSkelLib.php +++ /dev/null @@ -1,1251 +0,0 @@ -_ci =& get_instance(); // get code igniter instance - - // Loads DB conns and confs using system settings - $this->_ci->load->database('system'); - - // Loads dbskel configs - $this->_ci->config->load('dbskel'); - - // Loads library EPrintfLib - $this->_ci->load->library('EPrintfLib'); - } - - //------------------------------------------------------------------------------------------------------------------ - // Public methods - - /** - * Starts the DBSkel procedure - * Returns false on failure and true on success - * All errors/warnings/infos are printed here using EPrintfLib - * Accept the step parameter that can be used to run only a wanted step - */ - public function start($steps, $selectedDirectories) - { - $start = false; - - // Checks if DBSkel is enabled - if ($this->_ci->config->item(self::CONF_ENABLED) === true) - { - // Checks if the given steps parameter is fine - if ($this->_checkParameterStep($steps)) - { - $this->_printSchemaSeparator(); - - $this->_printRunningMode(); - - // By default perform all steps - $stepsArray = range(1, self::MAX_STEPS); - // If steps parameter is given then use it to select the steps to be performed - if ($steps != null) $stepsArray = explode(self::SEPARATOR, $steps); - - // Gets all the directories in application/dbskel - $directories = glob(self::DBSKEL_DIR.'*', GLOB_ONLYDIR); - - // Checks if the selectedDirectories parameter is fine - if ($this->_checkParameterSelectedDirectories($selectedDirectories, $directories)) - { - $start = $this->_processDirectories($directories, $stepsArray); - - $this->_printSchemaSeparator(); - } - } - } - else - { - $this->_printInfo('DBSkel is NOT enabled'); - } - - return $start; - } - - //------------------------------------------------------------------------------------------------------------------ - // Private methods - - /** - * Process every single directory present in dbskel directory - */ - private function _processDirectories($directories, $stepsArray) - { - $processDirectories = false; // failure by default - - // For each directory - foreach ($directories as $directory) - { - $processDirectories = false; // Reset to false at the beginning of each loop - - $this->_printSchemaSeparator(); - $this->_printInfo('Found directory >>> '.basename($directory).' <<<'); - - // NOTE: the order in which these methods are called has a meaning! - // If a step fails then the loop is stopped - - // 0 - Checks file naming convention in current directory - // NOTE: no need to check a failure! NOT a blocking check!! Always performed!!! - $this->_checkFilenaming($directory); - - $this->_printFileSeparator(); - - // 1 - Process schema file - if (in_array(self::STEP_SCHEMA, $stepsArray)) - { - if (!$this->_processSchemaFile($directory)) break; - - $this->_printFileSeparator(); - } - - // 2 - Process sequence file - if (in_array(self::STEP_SEQUENCES, $stepsArray)) - { - if (!$this->_processSequencesFile($directory)) break; - - $this->_printFileSeparator(); - } - - // 3 - Process table files - if (in_array(self::STEP_TABLES, $stepsArray)) - { - if (!$this->_processTableFiles($directory)) break; - - $this->_printFileSeparator(); - } - - // 4 - Process constraints - if (in_array(self::STEP_CONSTRAINTS, $stepsArray)) - { - if (!$this->_processConstraintsFile($directory)) break; - - $this->_printFileSeparator(); - } - - // 5 - Process views file - if (in_array(self::STEP_VIEWS, $stepsArray)) - { - if (!$this->_processViewsFile($directory)) break; - - $this->_printFileSeparator(); - } - - // 6 - Process functions file - if (in_array(self::STEP_FUNCTIONS, $stepsArray)) - { - if (!$this->_processFunctionsFile($directory)) break; - - $this->_printFileSeparator(); - } - - // 7 - Process grants file - if (in_array(self::STEP_GRANTS, $stepsArray)) - { - if (!$this->_processGrantsFile($directory)) break; - - $this->_printFileSeparator(); - } - - // 8 - Process extra file - if (in_array(self::STEP_EXTRA, $stepsArray)) - { - if (!$this->_processExtraFile($directory)) break; - } - - $processDirectories = true; // If all the steps ends successfully - - $this->_printSchemaSeparator(); - } - - return $processDirectories; - } - - /** - * Checks file names are compliant with the file naming convention - */ - private function _checkFilenaming($directory) - { - $files = array_filter(glob($directory.'/*'), 'is_file'); - - // For each file - foreach ($files as $file) - { - $fileName = basename($file); // File name - // If the file name is NOT compliant with the file naming convention - if (!$this->_isFilenameValid($fileName)) - { - $this->_printInfo('Not valid file name, it is going to be ignored: '.$fileName); - } - } - } - - /** - * Checks if the file name is compliant with the file naming convention - */ - private function _isFilenameValid($fileName) - { - return $fileName == self::SCHEMA_FILENAME // Schema file - || $fileName == self::SEQUENCES_FILENAME // Sequences file - || (substr($fileName, 0, strlen(self::TABLE_PREFIX)) == self::TABLE_PREFIX - && substr($fileName, -4, strlen(self::PHP_EXT)) == self::PHP_EXT) // Table files - || $fileName == self::CONSTRAINTS_FILENAME // Constraints file - || $fileName == self::VIEWS_FILENAME // Views file - || $fileName == self::FUNCTIONS_FILENAME // Function file - || $fileName == self::GRANTS_FILENAME // Grants file - || $fileName == self::EXTRA_FILENAME; // Extra file - } - - /** - * Process the schema file - */ - private function _processSchemaFile($directory) - { - // Looks for a schema file - $files = array_filter(glob($directory.'/'.self::SCHEMA_FILENAME), 'is_file'); - - // If a schema file is found... - if (count($files) > 0) - { - $this->_printMessage('Found schema file: '.$files[0]); - - //...process it! - if ($this->_isDryrunMode()) // If dry run mode enabled - { - $this->_printInfo('Dry run >> would be executed in new and diff mode'); - } - else // new or diff mode - { - return $this->_execSQLFile($files[0]); - } - } - else - { - $this->_printMessage('No schema file found'); - } - - return true; // If no files are found then go forward -> is a success - } - - /** - * Process sequences file - * - Looks for sequences present in current schema, then sequences that are NOT present in php file are dropped (diff mode only) - * - Looks for sequences present in php files, then sequences that are NOT present in database are installed - */ - private function _processSequencesFile($directory) - { - // Looks for a sequences file - $files = array_filter(glob($directory.'/'.self::SEQUENCES_FILENAME), 'is_file'); - - // If a sequences file is found... - if (count($files) > 0) - { - $this->_printMessage('Found sequences file: '.$files[0]); - - //...process it! - require_once($files[0]); // Read sequences file - $schema = basename($directory); // retrieves schema name from directory path - $dbSequencesArray = $this->_listSequencesBySchema($schema); // get list of sequences currently present in DB schema - - // Loops through list of sequences currently present in database - foreach ($dbSequencesArray as $dbSequence) - { - // If NOT in new mode and if the sequence present in database is NOT present in the list of sequences from php file - if (!$this->_isNewMode() && !array_key_exists($dbSequence, $sequencesArray)) - { - if ($this->_isDryrunMode()) // If dry run mode enabled - { - $this->_printInfo('Dry run >> sequence '.$dbSequence.' NOT found in sequences file >> would be removed in diff mode'); - } - elseif ($this->_isDiffMode()) // only if in diff mode - { - // Then drop it and objects that depends on it from database! If it fails then ends execution - if (!$this->_execQuery(sprintf('DROP SEQUENCE %s.%s CASCADE', $schema, $dbSequence))) - { - $this->_printError('Error occurred while dropping sequence: '.$dbSequence); - return false; - } - else - { - $this->_printMessage('Sequence dropped successfully: '.$dbSequence); - } - } - } - } - - // Loops through list of sequences from php file - foreach ($sequencesArray as $sequenceName => $sequenceSQL) - { - // If the sequence from php file is NOT present in database - if (!in_array($sequenceName, $dbSequencesArray)) - { - if ($this->_isDryrunMode()) // If dry run mode enabled - { - $this->_printInfo('Dry run >> sequence '.$sequenceName.' NOT found database >> would be added in new and diff mode'); - } - else - { - // Then install it! If it fails then ends execution - if (!$this->_execQuery($sequenceSQL)) - { - $this->_printError('Error occurred while adding sequence: '.$sequenceName); - return false; - } - else - { - $this->_printMessage('Sequence added successfully: '.$sequenceName); - } - } - } - else - { - $this->_printMessage('Sequence already present in database: '.$sequenceName); - } - } - } - else - { - $this->_printMessage('No sequences file found'); - } - - return true; // If ends of procedure with no failures or no files are found then is a success - } - - /** - * Process table files - */ - private function _processTableFiles($directory) - { - // Looks for table files - $files = array_filter(glob($directory.'/'.self::TABLE_PREFIX.'*'.self::PHP_EXT), 'is_file'); - - // If table files are found... - if (count($files) > 0) - { - //...process them! - $schema = basename($directory); // retrieves schema name from directory path - $dbTablesArray = $this->_listTablesBySchema($schema); // get list of tables currently present in DB schema - - // For each table file - foreach ($files as $file) - { - $this->_printMessage('Found table file: '.$file); - - require_once($file); // Read table file - - // Loops through list of tables currently present in database - foreach ($dbTablesArray as $dbTable) - { - // If NOT in new mode and if the table present in database is NOT present in the php table file - if (!$this->_isNewMode() && !array_key_exists($dbTable, $tableArray)) - { - if ($this->_isDryrunMode()) // If dry run mode enabled - { - $this->_printInfo('Dry run >> table '.$dbTable.' NOT found in table file >> would be removed in diff mode'); - } - elseif ($this->_isDiffMode()) // only if in diff mode - { - // Then drop it! If it fails then ends execution - if (!$this->_execQuery(sprintf('DROP TABLE %s.%s', $schema, $dbTable))) - { - $this->_printError('Error occurred while dropping table: '.$dbTable); - return false; - } - else - { - $this->_printMessage('Table dropped successfully: '.$dbTable); - } - } - } - } - - // Retrieves all the elements from the $tableArray except the element 'comment' - $tableElements = array_keys(array_diff_key($tableArray, array(self::T_COMMENT => null))); - if (is_array($tableElements) && count($tableElements) == 1) // If there is only one element left... - { - $tableName = $tableElements[0]; // ...then it is the name of the table - - // If the table from php file is NOT present in database - if (!in_array($tableName, $dbTablesArray)) - { - if ($this->_isDryrunMode()) // If dry run mode enabled - { - $this->_printInfo('Dry run >> table '.$tableName.' would be created in new and diff mode'); - } - else // new and diff mode - { - // Then create the new table! If it fails then ends execution - if ($this->_createTable($schema, $tableArray)) - { - $this->_printMessage('Table created successfully: '.$tableName); - } - else - { - $this->_printError('Error occurred while creating a new table: '.$tableName); - return false; - } - } - } - else // if table is already present in database - { - $this->_printMessage('Table already present in database: '.$tableName); - - // Manage the differences between the table present in database and the one present in php file - return $this->_manageTableColumns($schema, $tableArray); - } - } - else // otherwise the array present in the php table file is not well formatted - { - $this->_printError('Table file with a bad format is going to be ignored: '.$file); - } - } - } - else - { - $this->_printMessage('No table files found'); - } - - return true; // If no files are found then go forward -> is a success - } - - /** - * Process constraints file - * - Looks for constraints present in current schema, then constraints that are NOT present in php file are dropped (diff mode only) - * - Looks for constraints present in php files, then constraints that are NOT present in database are installed - */ - private function _processConstraintsFile($directory) - { - // Looks for a constraints file - $files = array_filter(glob($directory.'/'.self::CONSTRAINTS_FILENAME), 'is_file'); - - // If a constraints file is found... - if (count($files) > 0) - { - $this->_printMessage('Found constraints file: '.$files[0]); - - //...process it! - require_once($files[0]); // Read constraints file - $schema = basename($directory); // retrieves schema name from directory path - $dbConstraintsArray = $this->_listConstraintsBySchema($schema); // get list of constraints currently present in DB schema - $dbConstraintsNamesArray = array(); // Contains only the names of the constraints - - // Loops through list of constraints currently present in database - foreach ($dbConstraintsArray as $dbConstraint) - { - $dbConstraintsNamesArray[] = $dbConstraint['name']; // Copy only the name of the constraint - - // If NOT in new mode and if the constraint present in database is NOT present in the list of constraints from php file - if (!$this->_isNewMode() && !array_key_exists($dbConstraint['name'], $constraintsArray)) - { - if ($this->_isDryrunMode()) // If dry run mode enabled - { - $this->_printInfo('Dry run >> constraint '.$dbConstraint['name'].' NOT found in constraints file >> would be removed in diff mode'); - } - elseif ($this->_isDiffMode()) // only if in diff mode - { - // Then drop it and objects that depends on it from database! If it fails then ends execution - if (!$this->_execQuery(sprintf('ALTER TABLE %s.%s DROP CONSTRAINT %s', $schema, $dbConstraint['table'], $dbConstraint['name']))) - { - $this->_printError('Error occurred while dropping constraint: '.$dbConstraint['name']); - return false; - } - else - { - $this->_printMessage('Constraint dropped successfully: '.$dbConstraint['name']); - } - } - } - } - - // Loops through list of constraints from php file - foreach ($constraintsArray as $constraintName => $constraintSQL) - { - // If the constraint from php file is NOT present in database - if (!in_array($constraintName, $dbConstraintsNamesArray)) - { - if ($this->_isDryrunMode()) // If dry run mode enabled - { - $this->_printInfo('Dry run >> constraint '.$constraintName.' would be added in new and diff mode'); - } - else - { - // Then install it! If it fails then ends execution - if (!$this->_execQuery($constraintSQL)) - { - $this->_printError('Error occurred while adding constraint: '.$constraintName); - return false; - } - else - { - $this->_printMessage('Constraint added successfully: '.$constraintName); - } - } - } - else - { - $this->_printMessage('Constraint already present in database: '.$constraintName); - } - } - } - else - { - $this->_printMessage('No constraints file found'); - } - - return true; // If ends of procedure with no failures or no files are found then is a success - } - - /** - * Process views file - * - Looks for views present in current schema, then views that are NOT present in php file are dropped (diff mode only) - * - Looks for views present in php files and install them all - */ - private function _processViewsFile($directory) - { - // Looks for a views file - $files = array_filter(glob($directory.'/'.self::VIEWS_FILENAME), 'is_file'); - - // If a views file is found... - if (count($files) > 0) - { - $this->_printMessage('Found views file: '.$files[0]); - - //...process it! - require_once($files[0]); // Read views file - $schema = basename($directory); // retrieves schema name from directory path - $dbViewsArray = $this->_listViewsBySchema($schema); // get list of views currently present in DB schema - - // Loops through list of views currently present in database - foreach ($dbViewsArray as $dbView) - { - // If NOT in new mode and if the view present in database is NOT present in the list of views from php file - if (!$this->_isNewMode() && !array_key_exists($dbView, $viewsArray)) - { - if ($this->_isDryrunMode()) // If dry run mode enabled - { - $this->_printInfo('Dry run >> view '.$dbView.' NOT found in views file >> would be removed in diff mode'); - } - elseif ($this->_isDiffMode()) // only if in diff mode - { - // Then drop it and objects that depends on it from database! If it fails then ends execution - if (!$this->_execQuery(sprintf('DROP VIEW %s.%s CASCADE', $schema, $dbView))) - { - $this->_printError('Error occurred while dropping view: '.$dbView); - return false; - } - else - { - $this->_printMessage('View dropped successfully: '.$dbView); - } - } - } - } - - // Loops through list of views from php file - foreach ($viewsArray as $viewName => $viewSQL) - { - if ($this->_isDryrunMode()) // If dry run mode enabled - { - $this->_printInfo('Dry run >> view '.$viewName.' would be added in new and diff mode'); - } - else - { - // Then install it! If it fails then ends execution - if (!$this->_execQuery($viewSQL)) - { - $this->_printError('Error occurred while adding view: '.$viewName); - return false; - } - else - { - $this->_printMessage('View added successfully: '.$viewName); - } - } - } - } - else - { - $this->_printMessage('No views file found'); - } - - return true; // If ends of procedure with no failures or no files are found then is a success - } - - /** - * Process functions file - * - Looks for functions present in current schema, then functions that are NOT present in php file are dropped (diff mode only) - * - Looks for functions present in php files and install them all - */ - private function _processFunctionsFile($directory) - { - // Looks for a functions file - $files = array_filter(glob($directory.'/'.self::FUNCTIONS_FILENAME), 'is_file'); - - // If a functions file is found... - if (count($files) > 0) - { - $this->_printMessage('Found functions file: '.$files[0]); - - //...process it! - require_once($files[0]); // Read functions file - $schema = basename($directory); // retrieves schema name from directory path - $dbFunctionsArray = $this->_listFunctionsBySchema($schema); // get list of functions currently present in DB schema - - // Loops through list of functions currently present in database - foreach ($dbFunctionsArray as $dbFunction) - { - // If NOT in new mode and if the function present in database is NOT present in the list of functions from php file - if (!$this->_isNewMode() && !array_key_exists($dbFunction, $functionsArray)) - { - if ($this->_isDryrunMode()) // If dry run mode enabled - { - $this->_printInfo('Dry run >> function '.$dbFunction.' NOT found in fucntions file >> would be removed in diff mode'); - } - elseif ($this->_isDiffMode()) // only if in diff mode - { - // Then drop it and objects that depends on it from database! If it fails then ends execution - if (!$this->_execQuery(sprintf('DROP FUNCTION %s.%s CASCADE', $schema, $dbFunction))) - { - $this->_printError('Error occurred while dropping function: '.$dbFunction); - return false; - } - else - { - $this->_printMessage('Function dropped successfully: '.$dbFunction); - } - } - } - } - - // Loops through list of functions from php file - foreach ($functionsArray as $functionName => $functionSQL) - { - if ($this->_isDryrunMode()) // If dry run mode enabled - { - $this->_printInfo('Dry run >> view '.$functionName.' would be added in new and diff mode'); - } - else - { - // Then install it! If it fails then ends execution - if (!$this->_execQuery($functionSQL)) - { - $this->_printError('Error occurred while adding function: '.$functionName); - return false; - } - else - { - $this->_printMessage('Function added successfully: '.$functionName); - } - } - } - } - else - { - $this->_printMessage('No functions file found'); - } - - return true; // If ends of procedure with no failures or no files are found then is a success - } - - /** - * Process grants file - */ - private function _processGrantsFile($directory) - { - // Looks for a grants file - $files = array_filter(glob($directory.'/'.self::GRANTS_FILENAME), 'is_file'); - - // If a grants file is found... - if (count($files) > 0) - { - $this->_printMessage('Found grants file: '.$files[0]); - - //...process it! - if ($this->_isDryrunMode()) // If dry run mode enabled - { - $this->_printInfo('Dry run >> would be executed in new and diff mode'); - } - else // new or diff mode - { - return $this->_execSQLFile($files[0]); - } - } - else - { - $this->_printMessage('No grants file found'); - } - - return true; // If no files are found then go forward -> is a success - } - - /** - * Process extra file - */ - private function _processExtraFile($directory) - { - // Looks for an extra file - $files = array_filter(glob($directory.'/'.self::EXTRA_FILENAME), 'is_file'); - - // If an extra file is found... - if (count($files) > 0) - { - $this->_printMessage('Found extra file: '.$files[0]); - - //...process it! - if ($this->_isDryrunMode()) // If dry run mode enabled - { - $this->_printInfo('Dry run >> would be executed in new and diff mode'); - } - else // new or diff mode - { - return $this->_execSQLFile($files[0]); - } - } - else - { - $this->_printMessage('No extra file found'); - } - - return true; // If no files are found then go forward -> is a success - } - - /** - * Load SQL from a file and then execute such SQL - */ - private function _execSQLFile($file) - { - $sql = file_get_contents($file); // Read the file content - if ($sql === false) // If failed - { - $this->_printError('Error occurred while reading file: '.$file); - } - else // otherwise - { - // Exec query - if ($this->_execQuery($sql) == false) // if failed - { - $this->_printError('Error occurred while executing SQL from file: '.$file); - } - else // otherwise - { - $this->_printMessage('Successfully executed SQL from file: '.$file); - return true; - } - } - - return false; - } - - /** - * Checks if the running mode is 'dryrun' - */ - private function _isDryrunMode() - { - return $this->_ci->config->item(self::CONF_MODE) == self::RUN_MODE_DRYRUN; - } - - /** - * Checks if the running mode is 'diff' - */ - private function _isDiffMode() - { - return $this->_ci->config->item(self::CONF_MODE) == self::RUN_MODE_DIFF; - } - - /** - * Checks if the running mode is 'new' - */ - private function _isNewMode() - { - return $this->_ci->config->item(self::CONF_MODE) == self::RUN_MODE_NEW; - } - - /** - * Checks if the parameter step is correct - */ - private function _checkParameterStep($steps) - { - if ($steps != null) // if it was given - { - $stepsArray = explode(self::SEPARATOR, $steps); // split the string in an array - foreach ($stepsArray as $step) - { - if (!is_numeric($step)) // if it is not a number - { - $this->_ci->eprintflib->printError('The given parameter must be a number or a string in the following format: 1:3:5'); - return false; - } - elseif ($step > self::MAX_STEPS) // if it is a number but > MAX_STEPS - { - $this->_ci->eprintflib->printError('The maximun value fot this parameter is: '.self::MAX_STEPS); - return false; - } - elseif ($step < 1) // if it is a number but < 1 - { - $this->_ci->eprintflib->printError('The minimum value fot this parameter is 1'); - return false; - } - } - } - - return true; - } - - /** - * Checks if the parameter selectedDirectories is correct and stores the result in $directories - */ - private function _checkParameterSelectedDirectories($selectedDirectories, &$directories) - { - if ($selectedDirectories != null) - { - $selectedDirectoriesArray = explode(self::SEPARATOR, $selectedDirectories); - - $found = true; - - foreach ($selectedDirectoriesArray as $key => $value) - { - $selectedDirectoriesArray[$key] = self::DBSKEL_DIR.$value; - - if (!in_array(self::DBSKEL_DIR.$value, $directories)) - { - $found = false; - break; - } - } - - if ($found) - { - $directories = $selectedDirectoriesArray; - } - else - { - $this->_printError('One or more of the given directories does NOT exist'); - return false; - } - } - - return true; - } - - //------------------------------------------------------------------------------------------------------------------ - // Private database methods - - /** - * Executes the given query - */ - private function _execQuery($query) - { - if (!@$this->_ci->db->simple_query($query)) - { - $error = $this->_ci->db->error(); - if (is_array($error) && isset($error['message'])) - { - $this->_printError($error['message']); - } - - return false; - } - - return true; - } - - /** - * Retrieves all the sequences present in the given database schema - */ - private function _listSequencesBySchema($schema) - { - $sequencesArray = array(); - $query = sprintf('SELECT sequence_name - FROM information_schema.sequences - WHERE sequence_schema = \'%s\'', $schema); - - if ($sequences = @$this->_ci->db->query($query)) - { - foreach ($sequences->result() as $sequence) - { - $sequencesArray[] = $sequence->sequence_name; - } - } - - return $sequencesArray; - } - - /** - * Retrieves all the tables present in the given database schema - */ - private function _listTablesBySchema($schema) - { - $tablesArray = array(); - $query = sprintf('SELECT table_name - FROM information_schema.tables - WHERE table_type = \'BASE TABLE\' - AND table_schema = \'%s\'', $schema); - - if ($tables = @$this->_ci->db->query($query)) - { - foreach ($tables->result() as $table) - { - $tablesArray[] = $table->table_name; - } - } - - return $tablesArray; - } - - /** - * Retrieves all the constraints present in the given database schema - * Returns an array with all the constraints, each element of the array is an array with two elements: - * - name: the name of the constraint - * - table: the name of the table where the constraint is applied - * NOTE: does not retrieve NOT NULL constraints - */ - private function _listConstraintsBySchema($schema) - { - $constraintsArray = array(); - $query = sprintf('SELECT constraint_name, - table_name - FROM information_schema.table_constraints - WHERE table_schema = \'%s\' - AND constraint_name NOT LIKE \'%%_not_null\'', $schema); // avoid to retrieve NOT NULL constraints - - if ($constraints = @$this->_ci->db->query($query)) - { - foreach ($constraints->result() as $constraint) - { - $constraintsArray[] = array('name' => $constraint->constraint_name, 'table' => $constraint->table_name); - } - } - - return $constraintsArray; - } - - /** - * Retrieves all the views present in the given database schema - */ - private function _listViewsBySchema($schema) - { - $viewsArray = array(); - $query = sprintf('SELECT table_name - FROM information_schema.views - WHERE table_schema = \'%s\'', $schema); - - if ($views = @$this->_ci->db->query($query)) - { - foreach ($views->result() as $view) - { - $viewsArray[] = $view->table_name; - } - } - - return $viewsArray; - } - - /** - * Retrieves all the functions present in the given database schema - */ - private function _listFunctionsBySchema($schema) - { - $functionsArray = array(); - $query = sprintf('SELECT routine_name - FROM information_schema.routines - WHERE specific_schema != \'pg_catalog\' - AND specific_schema != \'information_schema\' - AND routine_schema = \'%s\'', $schema); - - if ($functions = @$this->_ci->db->query($query)) - { - foreach ($functions->result() as $function) - { - $functionsArray[] = $function->routine_name; - } - } - - return $functionsArray; - } - - /** - * Retrieves all the columns from a database table - */ - private function _listColumns($schema, $table) - { - $columnsArray = array(); - $query = sprintf('SELECT column_name AS name, - data_type AS type, - column_default AS default, - is_nullable AS nullable, - character_maximum_length AS string_length, - numeric_precision AS number_length - FROM information_schema.columns - WHERE table_schema = \'%s\' - AND table_name = \'%s\'', $schema, $table); - - if ($columns = @$this->_ci->db->query($query)) - { - foreach ($columns->result() as $column) - { - $columnsArray[] = $column->routine_name; - } - } - - return $columnsArray; - } - - /** - * Creates a new table in database using the given schema and an array that defines the table structure - */ - private function _createTable($schema, $tableArray) - { - $tableName = ''; - $tableComment = ''; - $tableStructure = null; - - // For each element of the table array from the php file - foreach ($tableArray as $key => $value) - { - if ($key == self::T_COMMENT) // If it is the comment element - { - $tableComment = $value; - } - else // otherwise is the table structure element - { - $tableName = $key; - $tableStructure = $value; - } - } - - // Query to create a table - $query = sprintf('CREATE TABLE %s.%s (', $schema, $tableName); - // Query to comment the table and its columns - $queryComment = sprintf('COMMENT ON TABLE %s.%s IS \'%s\';', $schema, $tableName, $tableComment); - - // For each element of the table structure - foreach ($tableStructure as $colName => $colStructure) - { - $notNull = ''; // by default the column could be null - if (isset($colStructure[self::T_NULL]) && $colStructure[self::T_NULL] === false) - { - $notNull = 'NOT NULL'; // set to NOT NULL - } - - $default = ''; // by default there is no default for a column - if (isset($colStructure[self::T_DEFAULT])) - { - $default = 'DEFAULT '.$colStructure[self::T_DEFAULT]; // set as given by the table structure - } - - // Part of the query related to this column - $query .= sprintf('%s %s %s %s,', $colName, $colStructure[self::T_TYPE], $notNull, $default); - - // If a comment is present for this column then the query is built - if (isset($colStructure[self::T_COMMENT])) - { - $queryComment .= sprintf('COMMENT ON COLUMN %s.%s.%s IS \'%s\';', $schema, $tableName, $colName, $colStructure[self::T_COMMENT]); - } - } - - // Removes the last comma from the query - $query = substr($query, 0, strlen($query) - 1); - - // Close the round bracket - $query .= ');'; - - return $this->_execQuery($query.$queryComment); // executes query and returns its result - } - - /** - * TODO - * Changes the structure of a table using the given schema and an array that defines the table structure - */ - private function _manageTableColumns($schema, $tableArray) - { - $tableName = ''; - $tableComment = ''; - $tableStructure = null; - - // For each element of the table array from the php file - foreach ($tableArray as $key => $value) - { - if ($key == self::T_COMMENT) // If it is the comment element - { - $tableComment = $value; - } - else // otherwise is the table structure element - { - $tableName = $key; - $tableStructure = $value; - } - } - - // Comments the table - $queryComment = sprintf('COMMENT ON TABLE %s.%s IS \'%s\';', $schema, $tableName, $tableComment); - if ($this->_isDryrunMode()) - { - $this->_printInfo('Dry run >> table '.$tableName.' would be commented with: '.$queryComment); - } - else // new and diff mode - { - if (!$this->_execQuery($queryComment)) - { - $this->_printError('Error occurred while commenting table: '.$tableName); - return false; - } - else - { - $this->_printMessage('Table successfully commented: '.$tableName); - } - } - - // Retrieves the list of columns and their attributes from database - $dbTableColumns = $this->_listColumns($schema, $tableName); - - // For each element of the table structure - foreach ($tableStructure as $colName => $colStructure) - { - $notNull = ''; // by default the column could be null - if (isset($colStructure[self::T_NULL]) && $colStructure[self::T_NULL] === false) - { - $notNull = 'NOT NULL'; // set to NOT NULL - } - - $default = ''; // by default there is no default for a column - if (isset($colStructure[self::T_DEFAULT])) - { - $default = 'DEFAULT '.$colStructure[self::T_DEFAULT]; // set as given by the table structure - } - - // Part of the query related to this column - $query = sprintf('%s %s %s %s,', $colName, $colStructure[self::T_TYPE], $notNull, $default); - - // Comments a column - if (isset($colStructure[self::T_COMMENT])) - { - if ($this->_isDryrunMode()) - { - $this->_printInfo('Dry run >> column '.$tableName.'.'.$colName.' would be commented with: '.$colStructure[self::T_COMMENT]); - } - else // new and diff mode - { - $queryComment = sprintf('COMMENT ON COLUMN %s.%s.%s IS \'%s\';', $schema, $tableName, $colName, $colStructure[self::T_COMMENT]); - if (!$this->_execQuery($queryComment)) - { - $this->_printError('Error occurred while commenting column: '.$tableName.'.'.$colName); - return false; - } - else - { - $this->_printMessage('Column successfully commented: '.$tableName.'.'.$colName); - } - } - } - } - - return true; - } - - //------------------------------------------------------------------------------------------------------------------ - // Private output methods - - /** - * - */ - private function _printInfo($string) - { - $this->_ci->eprintflib->printInfo($string); - } - - /** - * - */ - private function _printError($string) - { - $this->_ci->eprintflib->printError($string); - } - - /** - * - */ - private function _printMessage($string) - { - $this->_ci->eprintflib->printMessage($string); - } - - /** - * - */ - private function _printSchemaSeparator() - { - $this->_printInfo('--------------------------------------------------------------------------------------------'); - } - - /** - * - */ - private function _printFileSeparator() - { - $this->_printMessage('--------------------------------------------------------------------------------------------'); - } - - /** - * - */ - private function _printRunningMode() - { - if ($this->_isDryrunMode()) $this->_printInfo('>> DBSkel is running in dry run mode <<'); - elseif ($this->_isNewMode()) $this->_printInfo('>> DBSkel is running in new mode <<'); - elseif ($this->_isDiffMode()) $this->_printInfo('>> DBSkel is running in diff mode <<'); - } -} diff --git a/application/libraries/DmsLib.php b/application/libraries/DmsLib.php index 6b86ce7f8..f32df5fd1 100644 --- a/application/libraries/DmsLib.php +++ b/application/libraries/DmsLib.php @@ -249,7 +249,7 @@ class DmsLib } else { - return error($dmscontent->retval); + return error(getError($dmscontent)); } } else @@ -259,7 +259,7 @@ class DmsLib } else { - return error($akte->retval); + return error(getError($akte)); } } diff --git a/application/libraries/DocumentLib.php b/application/libraries/DocumentLib.php index ed87a9f38..98e546b4e 100644 --- a/application/libraries/DocumentLib.php +++ b/application/libraries/DocumentLib.php @@ -68,7 +68,7 @@ class DocumentLib } else { - return error($ret->retval); + return error(getError($ret)); } case 'application/pdf': return success($filename); diff --git a/application/libraries/FiltersLib.php b/application/libraries/FilterWidgetLib.php similarity index 83% rename from application/libraries/FiltersLib.php rename to application/libraries/FilterWidgetLib.php index 9d0d67584..6e87833bd 100644 --- a/application/libraries/FiltersLib.php +++ b/application/libraries/FilterWidgetLib.php @@ -5,10 +5,12 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); /** * FilterWidget logic */ -class FiltersLib +class FilterWidgetLib { - // Session parameters names - const SESSION_NAME = 'FHC_FILTER_WIDGET'; // Filter session name + // FilterWidget session name + const SESSION_NAME = 'FHC_FILTER_WIDGET'; + + // Session elements const SESSION_FILTER_NAME = 'filterName'; const SESSION_FIELDS = 'fields'; const SESSION_SELECTED_FIELDS = 'selectedFields'; @@ -17,11 +19,18 @@ class FiltersLib const SESSION_CHECKBOXES = 'checkboxes'; const SESSION_FILTERS = 'filters'; const SESSION_METADATA = 'datasetMetadata'; - const SESSION_DATASET = 'dataset'; const SESSION_ROW_NUMBER = 'rowNumber'; - const SESSION_RELOAD_DATASET = 'reloadDataset'; + const SESSION_TIMEOUT = 'sessionTimeout'; + + // Session dataset elements + const SESSION_DATASET = 'dataset'; + const SESSION_DATASET_RELOAD = 'reloadDataset'; const SESSION_DATASET_REPRESENTATION = 'datasetRepresentation'; const SESSION_DATASET_REP_OPTIONS = 'datasetRepresentationOptions'; + const SESSION_DATASET_REP_FIELDS_DEFS = 'datasetRepresentationFieldsDefinitions'; + + // Default session timeout + const SESSION_DEFAULT_TIMEOUT = 30; // Alias for the dynamic table used to retrieve the dataset const DATASET_TABLE_ALIAS = 'datasetFilterTable'; @@ -32,16 +41,16 @@ class FiltersLib // ...to identify a single filter widget in the DB const FILTER_ID = 'filter_id'; - const APP_PARAMETER = 'app'; - const DATASET_NAME_PARAMETER = 'datasetName'; - const FILTER_KURZBZ_PARAMETER = 'filterKurzbz'; - const DATASET_RELOAD_PARAMETER = 'reloadDataset'; + const APP = 'app'; + const DATASET_NAME = 'datasetName'; + const FILTER_KURZBZ = 'filterKurzbz'; + const DATASET_RELOAD = 'reloadDataset'; // ...to specify permissions that are needed to use this FilterWidget - const REQUIRED_PERMISSIONS_PARAMETER = 'requiredPermissions'; + const REQUIRED_PERMISSIONS = 'requiredPermissions'; // ...stament to retrieve the dataset - const QUERY_PARAMETER = 'query'; + const QUERY = 'query'; // ...to specify more columns or aliases for them const ADDITIONAL_COLUMNS = 'additionalColumns'; @@ -53,18 +62,23 @@ class FiltersLib const MARK_ROW = 'markRow'; // ...to hide the options for a filter - const HIDE_HEADER = 'hideHeader'; + const HIDE_OPTIONS = 'hideOptions'; + const HIDE_SELECT_FIELDS = 'hideSelectFields'; + const HIDE_SELECT_FILTERS = 'hideSelectFilters'; const HIDE_SAVE = 'hideSave'; const CUSTOM_MENU = 'customMenu'; // ...to specify if the menu for this filter is custom (true) or not (false) + const HIDE_MENU = 'hideMenu'; // ...to specify if the menu should be shown or not // ...to specify how to represent the dataset (ex: tablesorter, pivotUI, ...) const DATASET_REPRESENTATION = 'datasetRepresentation'; const DATASET_REP_OPTIONS = 'datasetRepOptions'; + const DATASET_REP_FIELDS_DEFS = 'datasetRepFieldsDefs'; // Different dataset representations const DATASET_REP_TABLESORTER = 'tablesorter'; const DATASET_REP_PIVOTUI = 'pivotUI'; + const DATASET_REP_TABULATOR = 'tabulator'; // Filter operations values const OP_EQUAL = 'equal'; @@ -84,10 +98,10 @@ class FiltersLib const FILTER_PHRASES_CATEGORY = 'FilterWidget'; // The category used to store phrases for the FilterWidget - const FILTER_PAGE_PARAM = 'filter_page'; // Filter page parameter name + const FILTER_UNIQUE_ID = 'filterUniqueId'; // Filter page parameter name const PERMISSION_FILTER_METHOD = 'FilterWidget'; // Name for fake method to be checked by the PermissionLib - const PERMISSION_TYPE = 'rw'; + const PERMISSION_TYPE = 'r'; // Name and array keys of the filters menu array const NAV_MENU_FILTER_KEY = 'filters'; @@ -107,11 +121,6 @@ class FiltersLib public function __construct($params = null) { $this->_ci =& get_instance(); // get code igniter instance - - // Loads authentication helper - $this->_ci->load->helper('hlp_authentication'); // NOTE: needed to load custom filters do not remove! - - $this->_filterUniqueId = $this->_getFilterUniqueId($params); // sets the id for the related filter widget } //------------------------------------------------------------------------------------------------------------------ @@ -130,7 +139,7 @@ class FiltersLib // Gets the required permissions from the session if they are not provided as parameter $rq = $requiredPermissions; - if ($rq == null) $rq = $this->getSessionElement(self::REQUIRED_PERMISSIONS_PARAMETER); + if ($rq == null) $rq = $this->getSessionElement(self::REQUIRED_PERMISSIONS); return $this->_ci->permissionlib->hasAtLeastOne($rq, self::PERMISSION_FILTER_METHOD, self::PERMISSION_TYPE); } @@ -178,6 +187,29 @@ class FiltersLib setSessionElement(self::SESSION_NAME, $this->_filterUniqueId, $session); // stores the single value } + /** + * + */ + public function dropExpiredFilterWidgets() + { + // Loads the session for all the filter widgets + $filterWidgetsSession = getSession(self::SESSION_NAME); + + // If something is present in session + if ($filterWidgetsSession != null) + { + // Loops in the session for all the filter widgets + foreach ($filterWidgetsSession as $filterWidget => $filterWidgetData) + { + // If this filter widget is not the currrent used filter widget and the it is expired... + if ($this->_filterUniqueId != $filterWidget && $filterWidgetData[self::SESSION_TIMEOUT] <= time()) + { + cleanSessionElement(self::SESSION_NAME, $filterWidget); // ...remove it + } + } + } + } + /** * Loads the definition data from DB for a filter widget */ @@ -185,11 +217,8 @@ class FiltersLib { // Loads the needed models $this->_ci->load->model('system/Filters_model', 'FiltersModel'); - $this->_ci->load->model('person/Benutzer_model', 'BenutzerModel'); // to get the default custom filter - $this->_ci->FiltersModel->resetQuery(); // reset any previous built query - $this->_ci->FiltersModel->addJoin('public.tbl_benutzer', 'person_id', 'LEFT'); // left join with benutzer table $this->_ci->FiltersModel->addSelect('system.tbl_filters.*'); // select only from table filters $this->_ci->FiltersModel->addOrder('sort', 'ASC'); // sort on column sort $this->_ci->FiltersModel->addLimit(1); // if more than one filter is set as default only one will be retrieved @@ -223,7 +252,7 @@ class FiltersLib $whereParameters = array( 'app' => $app, 'dataset_name' => $datasetName, - 'uid' => getAuthUID(), + 'person_id' => getAuthPersonId(), 'default_filter' => true ); @@ -260,10 +289,10 @@ class FiltersLib $jsonEncodedFilter = null; // If the definition contains data and they are valid - if (hasData($definition) && isset($definition->retval[0]->filter) && trim($definition->retval[0]->filter) != '') + if (hasData($definition) && isset(getData($definition)[0]->filter) && trim(getData($definition)[0]->filter) != '') { // Get the json definition of the filter - $tmpJsonEncodedFilter = json_decode($definition->retval[0]->filter); + $tmpJsonEncodedFilter = json_decode(getData($definition)[0]->filter); // Checks required filter's properies if (isset($tmpJsonEncodedFilter->name) @@ -473,7 +502,7 @@ class FiltersLib // Write changes into the session $this->setSessionElement(self::SESSION_FILTERS, $filters); - $this->setSessionElement(self::SESSION_RELOAD_DATASET, true); // the dataset must be reloaded + $this->setSessionElement(self::SESSION_DATASET_RELOAD, true); // the dataset must be reloaded $removeAppliedFilter = true; } @@ -525,7 +554,7 @@ class FiltersLib // Write changes into the session $this->setSessionElement(self::SESSION_FILTERS, $filters); - $this->setSessionElement(self::SESSION_RELOAD_DATASET, true); // the dataset must be reloaded + $this->setSessionElement(self::SESSION_DATASET_RELOAD, true); // the dataset must be reloaded $applyFilters = true; } @@ -534,6 +563,14 @@ class FiltersLib return $applyFilters; } + /** + * Reloads dataset by setting session variable to true + */ + public function reloadDataset() + { + $this->setSessionElement(self::SESSION_DATASET_RELOAD, true); + } + /** * Add a filter (SQL where clause) to be applied to the current filter */ @@ -585,87 +622,76 @@ class FiltersLib $saveCustomFilter = false; // by default returns a failure // Checks parameter customFilterDescription if not valid stop the execution - if (isEmptyString($customFilterDescription)) - { - return $saveCustomFilter; - } + if (isEmptyString($customFilterDescription)) return $saveCustomFilter; $this->_ci->load->model('system/Filters_model', 'FiltersModel'); // to load the filter definitions - $this->_ci->load->model('person/Benutzer_model', 'BenutzerModel'); // to get the person_id of the authenticated user - $this->_ci->FiltersModel->resetQuery(); // reset any previous built query - $this->_ci->BenutzerModel->resetQuery(); // reset any previous built query - // Loads data for the authenticated user - $authBenutzer = $this->_ci->BenutzerModel->loadWhere(array('uid' => getAuthUID())); - if (hasData($authBenutzer)) // if data are found + // person_id of the authenticated user + $authPersonId = getAuthPersonId(); + // Postgres array for the description + $descPGArray = str_replace('%desc%', $customFilterDescription, '{"%desc%", "%desc%", "%desc%", "%desc%"}'); + + // Loads the definition to check if is already present in the DB + $definition = $this->_ci->FiltersModel->loadWhere(array( + 'app' => $this->getSessionElement(self::APP), + 'dataset_name' => $this->getSessionElement(self::DATASET_NAME), + 'description' => $descPGArray, + 'person_id' => $authPersonId + )); + + // New definition to be json encoded + $jsonDeifinition = new stdClass(); + $jsonDeifinition->name = $customFilterDescription; // name of the filter + + // Generates the "column" property + $jsonDeifinition->columns = array(); + $selectedFields = $this->getSessionElement(self::SESSION_SELECTED_FIELDS); // retrieved the selected fields + for ($i = 0; $i < count($selectedFields); $i++) { - // person_id of the authenticated user - $authPersonId = $authBenutzer->retval[0]->person_id; - // Postgres array for the description - $descPGArray = str_replace('%desc%', $customFilterDescription, '{"%desc%", "%desc%", "%desc%", "%desc%"}'); + // Each element is an object with a property called "name" + $jsonDeifinition->columns[$i] = new stdClass(); + $jsonDeifinition->columns[$i]->name = $selectedFields[$i]; + } - // Loads the definition to check if is already present in the DB - $definition = $this->_ci->FiltersModel->loadWhere(array( - 'app' => $this->getSessionElement(self::APP_PARAMETER), - 'dataset_name' => $this->getSessionElement(self::DATASET_NAME_PARAMETER), - 'description' => $descPGArray, - 'person_id' => $authPersonId - )); + // List of applied filters + $jsonDeifinition->filters = $this->getSessionElement(self::SESSION_FILTERS); - // New definition to be json encoded - $jsonDeifinition = new stdClass(); - $jsonDeifinition->name = $customFilterDescription; // name of the filter + // If it is already present + if (hasData($definition)) + { + // update it + $this->_ci->FiltersModel->update( + array( + 'app' => $this->getSessionElement(self::APP), + 'dataset_name' => $this->getSessionElement(self::DATASET_NAME), + 'description' => $descPGArray, + 'person_id' => $authPersonId + ), + array( + 'filter' => json_encode($jsonDeifinition) + ) + ); - // Generates the "column" property - $jsonDeifinition->columns = array(); - $selectedFields = $this->getSessionElement(self::SESSION_SELECTED_FIELDS); // retrieved the selected fields - for ($i = 0; $i < count($selectedFields); $i++) - { - // Each element is an object with a property called "name" - $jsonDeifinition->columns[$i] = new stdClass(); - $jsonDeifinition->columns[$i]->name = $selectedFields[$i]; - } + $saveCustomFilter = true; + } + else // otherwise insert a new one + { + $this->_ci->FiltersModel->insert( + array( + 'app' => $this->getSessionElement(self::APP), + 'dataset_name' => $this->getSessionElement(self::DATASET_NAME), + 'filter_kurzbz' => uniqid($authPersonId, true), + 'description' => $descPGArray, + 'person_id' => $authPersonId, + 'sort' => null, + 'default_filter' => false, + 'filter' => json_encode($jsonDeifinition), + 'oe_kurzbz' => null + ) + ); - // List of applied filters - $jsonDeifinition->filters = $this->getSessionElement(self::SESSION_FILTERS); - - // If it is already present - if (hasData($definition)) - { - // update it - $this->_ci->FiltersModel->update( - array( - 'app' => $this->getSessionElement(self::APP_PARAMETER), - 'dataset_name' => $this->getSessionElement(self::DATASET_NAME_PARAMETER), - 'description' => $descPGArray, - 'person_id' => $authPersonId - ), - array( - 'filter' => json_encode($jsonDeifinition) - ) - ); - - $saveCustomFilter = true; - } - else // otherwise insert a new one - { - $this->_ci->FiltersModel->insert( - array( - 'app' => $this->getSessionElement(self::APP_PARAMETER), - 'dataset_name' => $this->getSessionElement(self::DATASET_NAME_PARAMETER), - 'filter_kurzbz' => uniqid($authPersonId, true), - 'description' => $descPGArray, - 'person_id' => $authPersonId, - 'sort' => null, - 'default_filter' => false, - 'filter' => json_encode($jsonDeifinition), - 'oe_kurzbz' => null - ) - ); - - $saveCustomFilter = true; - } + $saveCustomFilter = true; } return $saveCustomFilter; @@ -698,7 +724,7 @@ class FiltersLib public function generateFilterMenu($navigationPage) { // Loads the NavigationLib for the current page (given as parameter) - $this->_ci->load->library('NavigationLib', array(FiltersLib::NAVIGATION_PAGE => $navigationPage)); + $this->_ci->load->library('NavigationLib', array(self::NAVIGATION_PAGE => $navigationPage)); $filterMenu = null; $currentMenu = $this->_ci->navigationlib->getSessionMenu(); // The navigation menu currently stored in session @@ -711,7 +737,7 @@ class FiltersLib // Loads all the filters related to this page (same dataset_name and same app name) $filters = $this->_ci->FiltersModel->getFiltersByAppDatasetName( - $session[self::APP_PARAMETER], $session[self::DATASET_NAME_PARAMETER] + $session[self::APP], $session[self::DATASET_NAME] ); // If filters were loaded @@ -721,7 +747,7 @@ class FiltersLib $childrenPersonalArray = array(); // contains all the children elements in menu enty for personal filters // Loops through loaded filters - foreach ($filters->retval as $filter) + foreach (getData($filters) as $filter) { // Generate a menu entry $menuEntry = $this->_ci->navigationlib->oneLevel( @@ -780,7 +806,7 @@ class FiltersLib ); // Sets in the session only the element related to the filters menu - $this->_ci->navigationlib->setSessionElementMenu(FiltersLib::NAV_MENU_FILTER_KEY, $filterMenu); + $this->_ci->navigationlib->setSessionElementMenu(self::NAV_MENU_FILTER_KEY, $filterMenu); } } } @@ -793,14 +819,14 @@ class FiltersLib * NOTE: The default value is the URI where the FilterWidget is called * If the fhc_controller_id is present then is also used */ - private function _getFilterUniqueId($params) + public function setFilterUniqueIdByParams($params) { if ($params != null && is_array($params) - && isset($params[self::FILTER_PAGE_PARAM]) - && !isEmptyString($params[self::FILTER_PAGE_PARAM])) + && isset($params[self::FILTER_UNIQUE_ID]) + && !isEmptyString($params[self::FILTER_UNIQUE_ID])) { - $filterUniqueId = $params[self::FILTER_PAGE_PARAM]; + $filterUniqueId = $params[self::FILTER_UNIQUE_ID]; } else { @@ -808,6 +834,14 @@ class FiltersLib $filterUniqueId = $this->_ci->router->directory.$this->_ci->router->class.'/'.$this->_ci->router->method; } + $this->setFilterUniqueId($filterUniqueId); + } + + /** + * + */ + public function setFilterUniqueId($filterUniqueId) + { // If the FHC_CONTROLLER_ID parameter is present in the HTTP GET if (isset($_GET[self::FHC_CONTROLLER_ID])) { @@ -818,7 +852,7 @@ class FiltersLib $filterUniqueId .= '/'.$this->_ci->input->post(self::FHC_CONTROLLER_ID); // then use it } - return $filterUniqueId; + $this->_filterUniqueId = $filterUniqueId; } /** diff --git a/application/libraries/Format.php b/application/libraries/Format.php deleted file mode 100644 index 0f7ea4a87..000000000 --- a/application/libraries/Format.php +++ /dev/null @@ -1,531 +0,0 @@ -_CI = &get_instance(); - - // Load the inflector helper - $this->_CI->load->helper('inflector'); - - // If the provided data is already formatted we should probably convert it to an array - if ($from_type !== NULL) - { - if (method_exists($this, '_from_' . $from_type)) - { - $data = call_user_func([$this, '_from_' . $from_type], $data); - } - else - { - throw new Exception('Format class does not support conversion from "' . $from_type . '".'); - } - } - - // Set the member variable to the data passed - $this->_data = $data; - } - - /** - * Create an instance of the format class - * e.g: echo $this->format->factory(['foo' => 'bar'])->to_csv(); - * - * @param mixed $data Data to convert/parse - * @param string $from_type Type to convert from e.g. json, csv, html - * - * @return object Instance of the format class - */ - public function factory($data, $from_type = NULL) - { - // $class = __CLASS__; - // return new $class(); - - return new static($data, $from_type); - } - - // FORMATTING OUTPUT --------------------------------------------------------- - - /** - * Format data as an array - * - * @param mixed|NULL $data Optional data to pass, so as to override the data passed - * to the constructor - * @return array Data parsed as an array; otherwise, an empty array - */ - public function to_array($data = NULL) - { - // If no data is passed as a parameter, then use the data passed - // via the constructor - if ($data === NULL && func_num_args() === 0) - { - $data = $this->_data; - } - - // Cast as an array if not already - if (is_array($data) === FALSE) - { - $data = (array) $data; - } - - $array = []; - foreach ((array) $data as $key => $value) - { - if (is_object($value) === TRUE || is_array($value) === TRUE) - { - $array[$key] = $this->to_array($value); - } - else - { - $array[$key] = $value; - } - } - - return $array; - } - - /** - * Format data as XML - * - * @param mixed|NULL $data Optional data to pass, so as to override the data passed - * to the constructor - * @param NULL $structure - * @param string $basenode - * @return mixed - */ - public function to_xml($data = NULL, $structure = NULL, $basenode = 'xml') - { - if ($data === NULL && func_num_args() === 0) - { - $data = $this->_data; - } - - // turn off compatibility mode as simple xml throws a wobbly if you don't. - if (ini_get('zend.ze1_compatibility_mode') == 1) - { - ini_set('zend.ze1_compatibility_mode', 0); - } - - if ($structure === NULL) - { - $structure = simplexml_load_string("<$basenode />"); - } - - // Force it to be something useful - if (is_array($data) === FALSE && is_object($data) === FALSE) - { - $data = (array) $data; - } - - foreach ($data as $key => $value) - { - - //change false/true to 0/1 - if (is_bool($value)) - { - $value = (int) $value; - } - - // no numeric keys in our xml please! - if (is_numeric($key)) - { - // make string key... - $key = (singular($basenode) != $basenode) ? singular($basenode) : 'item'; - } - - // replace anything not alpha numeric - $key = preg_replace('/[^a-z_\-0-9]/i', '', $key); - - if ($key === '_attributes' && (is_array($value) || is_object($value))) - { - $attributes = $value; - if (is_object($attributes)) - { - $attributes = get_object_vars($attributes); - } - - foreach ($attributes as $attribute_name => $attribute_value) - { - $structure->addAttribute($attribute_name, $attribute_value); - } - } - // if there is another array found recursively call this function - elseif (is_array($value) || is_object($value)) - { - $node = $structure->addChild($key); - - // recursive call. - $this->to_xml($value, $node, $key); - } - else - { - // add single node. - $value = htmlspecialchars(html_entity_decode($value, ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8'); - - $structure->addChild($key, $value); - } - } - - return $structure->asXML(); - } - - /** - * Format data as HTML - * - * @param mixed|NULL $data Optional data to pass, so as to override the data passed - * to the constructor - * @return mixed - */ - public function to_html($data = NULL) - { - // If no data is passed as a parameter, then use the data passed - // via the constructor - if ($data === NULL && func_num_args() === 0) - { - $data = $this->_data; - } - - // Cast as an array if not already - if (is_array($data) === FALSE) - { - $data = (array) $data; - } - - // Check if it's a multi-dimensional array - if (isset($data[0]) && count($data) !== count($data, COUNT_RECURSIVE)) - { - // Multi-dimensional array - $headings = array_keys($data[0]); - } - else - { - // Single array - $headings = array_keys($data); - $data = [$data]; - } - - // Load the table library - $this->_CI->load->library('table'); - - $this->_CI->table->set_heading($headings); - - foreach ($data as $row) - { - // Suppressing the "array to string conversion" notice - // Keep the "evil" @ here - $row = @array_map('strval', $row); - - $this->_CI->table->add_row($row); - } - - return $this->_CI->table->generate(); - } - - /** - * @link http://www.metashock.de/2014/02/create-csv-file-in-memory-php/ - * @param mixed|NULL $data Optional data to pass, so as to override the data passed - * to the constructor - * @param string $delimiter The optional delimiter parameter sets the field - * delimiter (one character only). NULL will use the default value (,) - * @param string $enclosure The optional enclosure parameter sets the field - * enclosure (one character only). NULL will use the default value (") - * @return string A csv string - */ - public function to_csv($data = NULL, $delimiter = ',', $enclosure = '"') - { - // Use a threshold of 1 MB (1024 * 1024) - $handle = fopen('php://temp/maxmemory:1048576', 'w'); - if ($handle === FALSE) - { - return NULL; - } - - // If no data is passed as a parameter, then use the data passed - // via the constructor - if ($data === NULL && func_num_args() === 0) - { - $data = $this->_data; - } - - // If NULL, then set as the default delimiter - if ($delimiter === NULL) - { - $delimiter = ','; - } - - // If NULL, then set as the default enclosure - if ($enclosure === NULL) - { - $enclosure = '"'; - } - - // Cast as an array if not already - if (is_array($data) === FALSE) - { - $data = (array) $data; - } - - // Check if it's a multi-dimensional array - if (isset($data[0]) && count($data) !== count($data, COUNT_RECURSIVE)) - { - // Multi-dimensional array - $headings = array_keys($data[0]); - } - else - { - // Single array - $headings = array_keys($data); - $data = [$data]; - } - - // Apply the headings - fputcsv($handle, $headings, $delimiter, $enclosure); - - foreach ($data as $record) - { - // If the record is not an array, then break. This is because the 2nd param of - // fputcsv() should be an array - if (is_array($record) === FALSE) - { - break; - } - - // Suppressing the "array to string conversion" notice. - // Keep the "evil" @ here. - $record = @ array_map('strval', $record); - - // Returns the length of the string written or FALSE - fputcsv($handle, $record, $delimiter, $enclosure); - } - - // Reset the file pointer - rewind($handle); - - // Retrieve the csv contents - $csv = stream_get_contents($handle); - - // Close the handle - fclose($handle); - - return $csv; - } - - /** - * Encode data as json - * - * @param mixed|NULL $data Optional data to pass, so as to override the data passed - * to the constructor - * @return string Json representation of a value - */ - public function to_json($data = NULL) - { - // If no data is passed as a parameter, then use the data passed - // via the constructor - if ($data === NULL && func_num_args() === 0) - { - $data = $this->_data; - } - - // Get the callback parameter (if set) - $callback = $this->_CI->input->get('callback'); - - if (empty($callback) === TRUE) - { - return json_encode($data); - } - - // We only honour a jsonp callback which are valid javascript identifiers - elseif (preg_match('/^[a-z_\$][a-z0-9\$_]*(\.[a-z_\$][a-z0-9\$_]*)*$/i', $callback)) - { - // Return the data as encoded json with a callback - return $callback . '(' . json_encode($data) . ');'; - } - - // An invalid jsonp callback function provided. - // Though I don't believe this should be hardcoded here - $data['warning'] = 'INVALID JSONP CALLBACK: ' . $callback; - - return json_encode($data); - } - - /** - * Encode data as a serialized array - * - * @param mixed|NULL $data Optional data to pass, so as to override the data passed - * to the constructor - * @return string Serialized data - */ - public function to_serialized($data = NULL) - { - // If no data is passed as a parameter, then use the data passed - // via the constructor - if ($data === NULL && func_num_args() === 0) - { - $data = $this->_data; - } - - return serialize($data); - } - - /** - * Format data using a PHP structure - * - * @param mixed|NULL $data Optional data to pass, so as to override the data passed - * to the constructor - * @return mixed String representation of a variable - */ - public function to_php($data = NULL) - { - // If no data is passed as a parameter, then use the data passed - // via the constructor - if ($data === NULL && func_num_args() === 0) - { - $data = $this->_data; - } - - return var_export($data, TRUE); - } - - // INTERNAL FUNCTIONS - - /** - * @param $data XML string - * @return SimpleXMLElement XML element object; otherwise, empty array - */ - protected function _from_xml($data) - { - return $data ? (array) simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA) : []; - } - - /** - * @param string $data CSV string - * @param string $delimiter The optional delimiter parameter sets the field - * delimiter (one character only). NULL will use the default value (,) - * @param string $enclosure The optional enclosure parameter sets the field - * enclosure (one character only). NULL will use the default value (") - * @return array A multi-dimensional array with the outer array being the number of rows - * and the inner arrays the individual fields - */ - protected function _from_csv($data, $delimiter = ',', $enclosure = '"') - { - // If NULL, then set as the default delimiter - if ($delimiter === NULL) - { - $delimiter = ','; - } - - // If NULL, then set as the default enclosure - if ($enclosure === NULL) - { - $enclosure = '"'; - } - - return str_getcsv($data, $delimiter, $enclosure); - } - - /** - * @param $data Encoded json string - * @return mixed Decoded json string with leading and trailing whitespace removed - */ - protected function _from_json($data) - { - return json_decode(trim($data)); - } - - /** - * @param string Data to unserialized - * @return mixed Unserialized data - */ - protected function _from_serialize($data) - { - return unserialize(trim($data)); - } - - /** - * @param $data Data to trim leading and trailing whitespace - * @return string Data with leading and trailing whitespace removed - */ - protected function _from_php($data) - { - return trim($data); - } - -} diff --git a/application/libraries/LogLib.php b/application/libraries/LogLib.php index cb0541003..b98575150 100644 --- a/application/libraries/LogLib.php +++ b/application/libraries/LogLib.php @@ -1,102 +1,252 @@ '; const LINE_SEPARATOR = ':'; - // -------------------------------------------------------------------------------------------------------------- - // Public methods + // CodeIgniter configuration log entry name and log debug value + const CI_LOG_THRESHOLD_NAME = 'log_threshold'; + const CI_LOG_THRESHOLD_DEBUG = 2; + + // LogLib parameters names + const P_NAME_CLASS_INDEX = 'classIndex'; + const P_NAME_FUNCTION_INDEX = 'functionIndex'; + const P_NAME_LINE_INDEX = 'lineIndex'; + const P_NAME_DB_LOG_TYPE = 'dbLogType'; + const P_NAME_DB_EXECUTE_USER = 'dbExecuteUser'; + + // Properties used to retrieve caller data + private $_classIndex; + private $_functionIndex; + private $_lineIndex; + + // Properties used when logging to database + private $_dbLogType; + private $_dbExecuteUser; /** - * logDebug + * Set properties to a default value or overwrites them with the given parameters + */ + public function __construct($params = null) + { + // Properties default values + $this->_classIndex = self::CLASS_INDEX; + $this->_functionIndex = self::FUNCTION_INDEX; + $this->_lineIndex = self::LINE_INDEX; + $this->_dbLogType = null; + $this->_dbExecuteUser = self::DB_EXECUTE_USER; + + // If parameters are given then overwrite the default values + if (!isEmptyArray($params)) + { + if (isset($params[self::P_NAME_CLASS_INDEX])) $this->_classIndex = $params[self::P_NAME_CLASS_INDEX]; + if (isset($params[self::P_NAME_FUNCTION_INDEX])) $this->_functionIndex = $params[self::P_NAME_FUNCTION_INDEX]; + if (isset($params[self::P_NAME_LINE_INDEX])) $this->_lineIndex = $params[self::P_NAME_LINE_INDEX]; + if (isset($params[self::P_NAME_DB_LOG_TYPE])) $this->_dbLogType = $params[self::P_NAME_DB_LOG_TYPE]; + if (isset($params[self::P_NAME_DB_EXECUTE_USER])) $this->_dbExecuteUser = $params[self::P_NAME_DB_EXECUTE_USER]; + } + } + + // -------------------------------------------------------------------------------------------------------------- + // Public methods based on CodeIgniter log system + + /** + * Writes a debug log to CodeIgniter log */ public function logDebug($message) { - $this->_log(LogLib::DEBUG, $message); + $this->_log(self::DEBUG, $message); } /** - * logInfo + * Writes an info log to CodeIgniter log */ public function logInfo($message) { - $this->_log(LogLib::INFO, $message); + $this->_log(self::INFO, $message); } /** - * logError + * Writes an error log to CodeIgniter log */ public function logError($message) { - $this->_log(LogLib::ERROR, $message); + $this->_log(self::ERROR, $message); + } + + // -------------------------------------------------------------------------------------------------------------- + // Public methods based on database + + /** + * Writes an info log to database + */ + public function logInfoDB($requestId, $data) + { + $this->_logDB(self::INFO, $requestId, $data); + } + + /** + * Writes a debug log to database + */ + public function logDebugDB($requestId, $data) + { + $this->_logDB(self::DEBUG, $requestId, $data); + } + + /** + * Writes an warning log to database + */ + public function logWarningDB($requestId, $data) + { + $this->_logDB(self::WARNING, $requestId, $data); + } + + /** + * Writes an error log to database + */ + public function logErrorDB($requestId, $data) + { + $this->_logDB(self::ERROR, $requestId, $data); } // -------------------------------------------------------------------------------------------------------------- // Private methods /** - * log + * Writes using CodeIgniter log system (file system) */ private function _log($level, $message) { - log_message($level, $this->_getCaller().$message); + log_message($level, $this->_getPrefix($this->_getCaller()).$message); } /** - * _getCaller + * Writes logs to database + */ + private function _logDB($level, $requestId, $data) + { + // If the _dbLogType parameter was not given when this library was loaded + // NOTE: this message will be displayed only to the developer AND stops the execution + if ($this->_dbLogType == null) + { + show_error('To log to database you need to specify the "'.self::P_NAME_DB_LOG_TYPE.'" parameter when the LogLib is loaded'); + } + + $ci =& get_instance(); // get code igniter instance + + // If only debug log is enabed then is possible to write a debug log, otherwise... + if ($level == self::DEBUG && $ci->config->item(self::CI_LOG_THRESHOLD_NAME) != self::CI_LOG_THRESHOLD_DEBUG) + { + // ...do nothing + } + else + { + // Loads WebservicelogModel + $ci->load->model('system/Webservicelog_model', 'WebservicelogModel'); + + // Get caller data + $callerData = $this->_getCaller(); + + // Writes a log to database + $ci->WebservicelogModel->insert(array( + 'webservicetyp_kurzbz' => $this->_dbLogType, + 'request_id' => $requestId, + 'beschreibung' => $this->_getDatabaseDescription($callerData), + 'request_data' => $data, + 'execute_user' => $this->_dbExecuteUser, + 'execute_time' => 'NOW()' // current time + )); + } + } + + /** + * Retrieves caller's data */ private function _getCaller() { - $classIndex = 3; - $functionIndex = 3; - $lineIndex = 2; $class = ''; $function = ''; $line = ''; $backtrace_arr = debug_backtrace(); - if (isset($backtrace_arr[$classIndex]['class']) && $backtrace_arr[$classIndex]['class'] != '') + + if (isset($backtrace_arr[$this->_classIndex]['class']) && $backtrace_arr[$this->_classIndex]['class'] != '') { - $class = $backtrace_arr[$classIndex]['class']; + $class = $backtrace_arr[$this->_classIndex]['class']; } - if (isset($backtrace_arr[$functionIndex]['function']) && $backtrace_arr[$functionIndex]['function'] != '') + if (isset($backtrace_arr[$this->_functionIndex]['function']) && $backtrace_arr[$this->_functionIndex]['function'] != '') { - $function = $backtrace_arr[$functionIndex]['function']; + $function = $backtrace_arr[$this->_functionIndex]['function']; } - if (isset($backtrace_arr[$lineIndex]['line']) && $backtrace_arr[$lineIndex]['line'] != '') + if (isset($backtrace_arr[$this->_lineIndex]['line']) && $backtrace_arr[$this->_lineIndex]['line'] != '') { - $line = $backtrace_arr[$lineIndex]['line']; + $line = $backtrace_arr[$this->_lineIndex]['line']; } - return $this->_format($class, $function, $line); + return array( + self::CLASS_NAME => $class, + self::FUNCTION_NAME => $function, + self::CODE_LINE => $line + ); } /** - * format + * Formats the log message prefix (file system based) */ - private function _format($class, $function, $line) + private function _getPrefix($callerData) { - $formatted = LogLib::CALLER_PREFIX; + $formatted = self::CALLER_PREFIX; - if (!is_null($class) && $class != '') + if (!isEmptyString($callerData[self::CLASS_NAME])) { - $formatted .= $class.LogLib::CLASS_POSTFIX; + $formatted .= $callerData[self::CLASS_NAME].self::CLASS_POSTFIX; } - $formatted .= $function.LogLib::LINE_SEPARATOR.$line.LogLib::CALLER_POSTFIX.' '; + $formatted .= $callerData[self::FUNCTION_NAME].self::LINE_SEPARATOR.$callerData[self::CODE_LINE].self::CALLER_POSTFIX.' '; + + return $formatted; + } + + /** + * Formats the database description for a log + */ + private function _getDatabaseDescription($callerData) + { + $formatted = $callerData[self::FUNCTION_NAME].self::LINE_SEPARATOR.$callerData[self::CODE_LINE]; + + if (!isEmptyString($callerData[self::CLASS_NAME])) + { + $formatted = $callerData[self::CLASS_NAME].self::CLASS_POSTFIX.$formatted; + } return $formatted; } diff --git a/application/libraries/MailLib.php b/application/libraries/MailLib.php index 6d0a48f73..dbbc22f08 100644 --- a/application/libraries/MailLib.php +++ b/application/libraries/MailLib.php @@ -7,6 +7,8 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); */ class MailLib { + const ENABLE_DEBUG = 'enable_debug'; + private $sended; // Sended email counter // Properties for storing the configuration @@ -15,6 +17,8 @@ class MailLib private $email_time_range; private $email_from_system; + private $_ci; // Codeigniter instance + /** * Class constructor */ @@ -24,16 +28,16 @@ class MailLib $this->sended = 0; // Get CI instance - $this->ci =& get_instance(); + $this->_ci =& get_instance(); // The second parameter is used to avoiding name collisions in the config array - $this->ci->config->load('mail', true); + $this->_ci->config->load('mail', true); // CI Email library - $this->ci->load->library('email'); + $this->_ci->load->library('email'); // Initializing email library with the loaded configurations - $this->ci->email->initialize($this->ci->config->config['mail']); + $this->_ci->email->initialize($this->_ci->config->config['mail']); // Set the configuration properties with the standard configuration values $this->email_number_to_sent = $this->getEmailCfgItem('email_number_to_sent'); @@ -48,6 +52,22 @@ class MailLib */ public function send($from, $to, $subject, $message, $alias = '', $cc = null, $bcc = null, $altMessage = '', $bulk = false, $autogenerated = false) { + // If it is configured then log mail info into the CI error logs + if ($this->getEmailCfgItem(self::ENABLE_DEBUG) === true) + { + $this->_ci->load->library('LogLib'); // Loads logging library + + // Log them all! + $this->_ci->loglib->logError('From: '.$from); + $this->_ci->loglib->logError('To: '.$to); + $this->_ci->loglib->logError('Subject: '.$subject); + $this->_ci->loglib->logError('Message: '.$message); + $this->_ci->loglib->logError('Alias: '.$alias); + $this->_ci->loglib->logError('CC: '.$cc); + $this->_ci->loglib->logError('BCC: '.$bcc); + $this->_ci->loglib->logError('Alternative message: '.$altMessage); + } + // If from is not specified then use the standard one if (is_null($from) || $from == '') { @@ -67,7 +87,7 @@ class MailLib } } - $this->ci->email->from($from, $alias); + $this->_ci->email->from($from, $alias); // Check if the email address of the debug recipient is a valid one $recipient = $to; @@ -83,20 +103,20 @@ class MailLib $recipientBCC = MAIL_DEBUG; } - $this->ci->email->to($recipient); - if (!is_null($recipientCC)) $this->ci->email->cc($recipientCC); - if (!is_null($recipientBCC)) $this->ci->email->bcc($recipientBCC); - $this->ci->email->subject($subject); - $this->ci->email->message($message); - if (!isEmptyString($altMessage)) $this->ci->email->set_alt_message($altMessage); + $this->_ci->email->to($recipient); + if (!is_null($recipientCC)) $this->_ci->email->cc($recipientCC); + if (!is_null($recipientBCC)) $this->_ci->email->bcc($recipientBCC); + $this->_ci->email->subject($subject); + $this->_ci->email->message($message); + if (!isEmptyString($altMessage)) $this->_ci->email->set_alt_message($altMessage); if($bulk) - $this->ci->email->set_header('Precedence', 'bulk'); + $this->_ci->email->set_header('Precedence', 'bulk'); if($autogenerated) - $this->ci->email->set_header('Auto-Submitted', 'auto-generated'); + $this->_ci->email->set_header('Auto-Submitted', 'auto-generated'); // Avoid printing on standard output ugly error messages - $result = @$this->ci->email->send(); + $result = @$this->_ci->email->send(); // If the email was succesfully sended then increment the counter // and checks if it has to wait until the sending of the next @@ -110,43 +130,34 @@ class MailLib } /** - * To ovveride the configurations + * Overrides configuration parameters + * If the given parameters are not null or empty strings then they are used to override + * the following properties of this object: + * - email_number_to_sent + * - email_number_per_time_range + * - email_time_range + * - email_from_system */ - public function overrideConfigs($cfg) + public function overrideConfigs($numberToSent, $numberPerTimeRange, $emailTimeRange, $emailFromSystem) { - if (!is_null($cfg)) + if (is_numeric($numberToSent)) $this->email_number_to_sent = $numberToSent; + + if (is_numeric($numberPerTimeRange)) $this->email_number_per_time_range = $numberPerTimeRange; + + if (is_numeric($emailTimeRange)) $this->email_time_range = $emailTimeRange; + + if (!isEmptyString($emailFromSystem) && filter_var($emailFromSystem, FILTER_VALIDATE_EMAIL)) { - if (isset($cfg->email_number_to_sent) && is_numeric($cfg->email_number_to_sent)) - { - $this->email_number_to_sent = $cfg->email_number_to_sent; - } - if (isset($cfg->email_number_per_time_range) && is_numeric($cfg->email_number_per_time_range)) - { - $this->email_number_per_time_range = $cfg->email_number_per_time_range; - } - if (isset($cfg->email_time_range) && is_numeric($cfg->email_time_range)) - { - $this->email_time_range = $cfg->email_time_range; - } - if (isset($cfg->email_from_system) && filter_var($cfg->email_from_system, FILTER_VALIDATE_EMAIL)) - { - $this->email_from_system = $cfg->email_from_system; - } + $this->email_from_system = $emailFromSystem; } } /** - * Returns the current configuration + * Returns value of property email_number_to_sent */ - public function getConfigs() + public function getEmailNumberToSent() { - $cfg = new stdClass(); - $cfg->email_number_to_sent = $this->email_number_to_sent; - $cfg->email_number_per_time_range = $this->email_number_per_time_range; - $cfg->email_time_range = $this->email_time_range; - $cfg->email_from_system = $this->email_from_system; - - return $cfg; + return $this->email_number_to_sent; } /** @@ -180,6 +191,6 @@ class MailLib */ private function getEmailCfgItem($itemName) { - return $this->ci->config->item($itemName, EMAIL_CONFIG_INDEX); + return $this->_ci->config->item($itemName, EMAIL_CONFIG_INDEX); } } diff --git a/application/libraries/MessageLib.php b/application/libraries/MessageLib.php index feba96473..fd2051f48 100644 --- a/application/libraries/MessageLib.php +++ b/application/libraries/MessageLib.php @@ -7,7 +7,25 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); */ class MessageLib { - const MSG_INDX_PREFIX = 'message_'; + // Config entries + const CFG_SYSTEM_PERSON_ID = 'system_person_id'; + const CFG_SEND_IMMEDIATELY = 'send_immediately'; + const CFG_MESSAGE_SERVER = 'message_server'; + const CFG_MESSAGE_HTML_VIEW_URL = 'message_html_view_url'; + const CFG_OU_RECEIVERS = 'ou_receivers'; + const CFG_OU_RECEIVERS_NO_NOTICE = 'ou_receivers_no_notice'; + const CFG_OU_RECEIVERS_PRIVATE = 'ou_receivers_private'; + const CFG_OU_FUNCTION_WHITELIST = 'ou_function_whitelist'; + const CFG_REDIRECT_VIEW_MESSAGE_URL = 'redirect_view_message_url'; + + // Templates names + const NOTICE_TEMPLATE_HTML = 'MessageMailHTML'; + const NOTICE_TEMPLATE_TXT = 'MessageMailTXT'; + const NOTICE_TEMPLATE_FALLBACK_HTML = 'templates/mailHTML'; + const NOTICE_TEMPLATE_FALLBACK_TXT = 'templates/mailTXT'; + + const EMAIL_KONTAKT_TYPE = 'email'; // Email kontakt type + const SENT_INFO_NEWLINE = '\n'; // tbl_msg_recipient->sentInfo separator private $_ci; @@ -22,16 +40,12 @@ class MessageLib // Loads message configuration $this->_ci->config->load('message'); - // CI Parser library - $this->_ci->load->library('parser'); - // Loads LogLib - $this->_ci->load->library('LogLib'); // Loads VorlageLib $this->_ci->load->library('VorlageLib'); // Loads Mail library $this->_ci->load->library('MailLib'); - // Loading models + // Loads message models $this->_ci->load->model('system/Message_model', 'MessageModel'); $this->_ci->load->model('system/MsgStatus_model', 'MsgStatusModel'); $this->_ci->load->model('system/Recipient_model', 'RecipientModel'); @@ -42,134 +56,305 @@ class MessageLib // Public methods /** - * getMessage() - returns the specified received message for a specified person + * Returns the specified message for a specified person */ public function getMessage($msg_id, $person_id) { - if (!is_numeric($msg_id)) - return $this->_error('', MSG_ERR_INVALID_MSG_ID); - if (!is_numeric($person_id)) - return $this->_error('', MSG_ERR_INVALID_RECIPIENTS); + if (!is_numeric($msg_id)) return error('The given message id is not valid', MSG_ERR_INVALID_MSG_ID); + if (!is_numeric($person_id)) return error('The given person id is not valid', MSG_ERR_INVALID_RECIPIENTS); return $this->_ci->RecipientModel->getMessage($msg_id, $person_id); } /** - * getMessagesByUID() - will return all messages, including the latest status for specified user. It don´t returns Attachments. + * Sends a message to persons ($receiversPersonId) */ - public function getMessagesByUID($uid, $oe_kurzbz = null, $all = false) + public function sendMessageUser( + $receiversPersonId, $subject, $body, // Required parameters + $sender_id = null, $senderOU = null, $relationmessage_id = null, $priority = MSG_PRIORITY_NORMAL, $multiPartMime = true + ) { - if (isEmptyString($uid)) - return $this->_error('', MSG_ERR_INVALID_MSG_ID); + // Retrieves receiver id and checks that is valid + $receivers = $this->_getReceiversByPersonId($receiversPersonId); + if (isError($receivers)) return $receivers; - return $this->_ci->RecipientModel->getMessagesByUID($uid, $oe_kurzbz, $all); + // Send the message and return the result + return $this->_sendMessage($receivers, null, $subject, $body, $sender_id, $senderOU, $relationmessage_id, $priority, $multiPartMime); } /** - * getMessagesByPerson() - will return all messages, including the latest status for specified user. It don´t returns Attachments. + * Sends a message to persons ($receiversPersonId) */ - public function getMessagesByPerson($person_id, $oe_kurzbz = null, $all = false) + public function sendMessageUserTemplate( + $receiversPersonId, $vorlage, $parseData, // Required parameters + $orgform = null, $sender_id = null, $senderOU = null, $relationmessage_id = null, $priority = MSG_PRIORITY_NORMAL, $multiPartMime = true + ) { - if (!is_numeric($person_id)) - return $this->_error('', MSG_ERR_INVALID_MSG_ID); + // Loads template data + $templateResult = $this->_ci->vorlagelib->loadVorlagetext($vorlage, $senderOU, $orgform, getUserLanguage()); + if (hasData($templateResult)) // if a template is found + { + $template = getData($templateResult)[0]; // template object - return $this->_ci->RecipientModel->getMessagesByPerson($person_id, $oe_kurzbz, $all); + // Parses template subject + $subject = parseText($template->subject, $parseData); + // Parses template text + $body = parseText($template->text, $parseData); + + return $this->sendMessageUser( + $receiversPersonId, $subject, $body, $sender_id, $senderOU, $relationmessage_id, $priority, $multiPartMime + ); + } + elseif (isError($templateResult)) // if an error occured + { + return $templateResult; // return it + } + else // if a template was not found + { + return error('Template was not found', MSG_ERR_INVALID_TEMPLATE); + } } /** - * getSentMessagesByPerson() - Get all sent messages from a person identified by person_id + * Sends a message to all the persons that are enabled to read messages for the given organisation unit ($receiversOU) */ - public function getSentMessagesByPerson($person_id, $oe_kurzbz = null, $all = false) + public function sendMessageOU( + $receiversOU, $subject, $body, // Required parameters + $sender_id = null, $senderOU = null, $relationmessage_id = null, $priority = MSG_PRIORITY_NORMAL, $multiPartMime = true + ) { - if (!is_numeric($person_id)) - return $this->_error('', MSG_ERR_INVALID_MSG_ID); + // If the recipient is an organisation unit that would be possible to send the same message (same message id) + // to the entire organisation unit (one to many functionality) + // In this case the receiver id is a the one present in message configuration + $receiver = new stdClass(); + $receiver->person_id = $this->_ci->config->item(self::CFG_SYSTEM_PERSON_ID); + $receivers = success(array($receiver)); - return $this->_ci->MessageModel->getMessagesByPerson($person_id, $oe_kurzbz, $all); + // Send the message and return the result + return $this->_sendMessage($receivers, $receiversOU, $subject, $body, $sender_id, $senderOU, $relationmessage_id, $priority, $multiPartMime); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods called by a job + + /** + * Gets all messages for which notice emails are still not sent from DB and sends for each of them the notice email + * Wrapper for _sendNoticeEmail. + */ + public function sendAllEmailNotices($since, $numberToSent, $numberPerTimeRange, $emailTimeRange, $emailFromSystem) + { + // Overrides MailLib configs with the given parameters + $this->_ci->maillib->overrideConfigs($numberToSent, $numberPerTimeRange, $emailTimeRange, $emailFromSystem); + + // Retrieves a certain amount of NOT sent messages + $messagesResult = $this->_ci->RecipientModel->getNotSentMessages( + $this->_ci->maillib->getEmailNumberToSent(), + $since + ); + + if (isError($messagesResult) || !hasData($messagesResult)) return $messagesResult; + + // Collects all the message ids in an array + $messageIds = array(); + foreach (getData($messagesResult) as $message) + { + $messageIds[] = $message->message_id; + } + + // Send'em all + return $this->_sendNoticeEmails($messageIds); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods used by to build the GUI to write messages to user/s + + /** + * Retrieves message vars from view vw_msg_vars_person + */ + public function getMessageVarsPerson() + { + // Retrieves message vars from view vw_msg_vars_person + $messageVarsPerson = $this->_ci->MessageModel->getMessageVarsPerson(); + if (isSuccess($messageVarsPerson)) // if everything is ok + { + $variablesArray = array(); + $tmpVariablesArray = getData($messageVarsPerson); + + // Starts from 1 to skip the first element which is person_id + for ($i = 1; $i < count($tmpVariablesArray); $i++) + { + $variablesArray['{'.str_replace(' ', '_', strtolower($tmpVariablesArray[$i])).'}'] = $tmpVariablesArray[$i]; + } + + return success($variablesArray); + } + + return $messageVarsPerson; // otherwise returns the error } /** - * getMessageByToken + * Retrieves message vars from view vw_msg_vars + */ + public function getMessageVarsPrestudent() + { + // Retrieves message vars from view vw_msg_vars + $messageVars = $this->_ci->MessageModel->getMessageVars(); + if (isSuccess($messageVars)) // if everything is ok + { + $variablesArray = array(); + $tmpVariablesArray = getData($messageVars); + + // Starts from 1 to skip the first element which is person_id + for ($i = 1; $i < count($tmpVariablesArray); $i++) + { + $variablesArray['{'.str_replace(' ', '_', strtolower($tmpVariablesArray[$i])).'}'] = $tmpVariablesArray[$i]; + } + + return success($variablesArray); + } + + return $messageVars; // otherwise returns the error + } + + /** + * Retrieves organisation units for each role that a user plays inside that organisation unit + */ + public function getOeKurzbz($sender_id) + { + $this->_ci->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + + // Retrieves organisation units for a user from database + $benutzer = $this->_ci->BenutzerfunktionModel->getActiveFunctionsByPersonId($sender_id); + if (isSuccess($benutzer)) // if everything is ok + { + $ouArray = array(); + + // Copies organisation units in $ouArray array + foreach (getData($benutzer) as $val) + { + // If the function is in the white list then get the organisation unit + if (in_array($val->funktion_kurzbz, $this->_ci->config->item(self::CFG_OU_FUNCTION_WHITELIST))) + { + $ouArray[] = $val->oe_kurzbz; + } + } + + return success($ouArray); + } + + return $benutzer; // otherwise returns the error + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods used by REST API + + /** + * Return all messages, including the latest status for specified user. It don´t returns Attachments. + * The sender organisation unit may be specified to filter messages + */ + public function getMessagesByUID($uid, $senderOU = null, $all = false) + { + if (isEmptyString($uid)) return error('The given message id is not valid', MSG_ERR_INVALID_MSG_ID); + + return $this->_ci->RecipientModel->getMessagesByUID($uid, $senderOU, $all); + } + + /** + * Return all messages, including the latest status for specified user. It does not return attachments + * The sender organisation unit may be specified to filter messages + */ + public function getMessagesByPerson($person_id, $senderOU = null, $all = false) + { + if (!is_numeric($person_id)) return error('The given message id is not valid', MSG_ERR_INVALID_MSG_ID); + + return $this->_ci->RecipientModel->getMessagesByPerson($person_id, $senderOU, $all); + } + + /** + * Get all sent messages from a person identified by person_id + * The sender organisation unit may be specified to filter messages + */ + public function getSentMessagesByPerson($person_id, $senderOU = null, $all = false) + { + if (!is_numeric($person_id)) return error('The given message id is not valid', MSG_ERR_INVALID_MSG_ID); + + return $this->_ci->MessageModel->getMessagesByPerson($person_id, $senderOU, $all); + } + + /** + * Retrieves a message by its token + * If a message is found with the given token then this message is set as read */ public function getMessageByToken($token) { - if (isEmptyString($token)) - return $this->_error('', MSG_ERR_INVALID_TOKEN); + if (isEmptyString($token)) return error('The given token is not valid', MSG_ERR_INVALID_TOKEN); - $result = $this->_ci->RecipientModel->getMessageByToken($token); - if (hasData($result)) + $messageTokenResult = $this->_ci->RecipientModel->getMessageByToken($token); + if (hasData($messageTokenResult)) { - // Searches for a status that is different from unread - $found = -1; - for ($i = 0; $i < count($result->retval); $i++) + // Searches for a status that is NOT unread + $found = false; + + foreach (getData($messageTokenResult) as $message) { - if ($result->retval[$i]->status > MSG_STATUS_UNREAD) + if ($message->status > MSG_STATUS_UNREAD) { - $found = $i; + $found = true; break; } } - // If not found then insert the read status - if ($found == -1) + // If NOT found then insert the read status + if (!$found) { - $statusKey = array( - 'message_id' => $result->retval[0]->message_id, - 'person_id' => $result->retval[0]->receiver_id, - 'status' => MSG_STATUS_READ + $uid = null; + if (!isEmptyString($messageTokenResult[0]->uid)) + { + $uid = $messageTokenResult[0]->uid; + } + + $statusData = array( + 'message_id' => getData($messageTokenResult)[0]->message_id, + 'person_id' => getData($messageTokenResult)[0]->receiver_id, + 'status' => MSG_STATUS_READ, + 'insertvon' => $uid ); - $resultIns = $this->_ci->MsgStatusModel->insert($statusKey); + $messageTokenResultIns = $this->_ci->MsgStatusModel->insert($statusData); // If an error occured while writing on data base, then return it - if (isError($resultIns)) - { - $result = $resultIns; - } + if (isError($messageTokenResultIns)) $messageTokenResult = $messageTokenResultIns; } } - return $result; + return $messageTokenResult; } /** - * getCountUnreadMessages + * Counts the unread messages for the given user + * The sender organisation unit may be specified to filter messages */ - public function getCountUnreadMessages($person_id, $oe_kurzbz = null) + public function getCountUnreadMessages($person_id, $senderOU = null) { - if (!is_numeric($person_id)) - return $this->_error('', MSG_ERR_INVALID_RECIPIENTS); + if (!is_numeric($person_id)) return error('The given person id is not valid', MSG_ERR_INVALID_RECIPIENTS); - return $this->_ci->RecipientModel->getCountUnreadMessages($person_id, $oe_kurzbz); + return $this->_ci->RecipientModel->getCountUnreadMessages($person_id, $senderOU); } /** - * updateMessageStatus() - will change status on message for particular user - * NOTE: it performs an insert, NOT an update + * Change the message status of the given message specified by message_id and person_id, using the given status + * NOTE: it performs an insert NOT an update */ public function updateMessageStatus($message_id, $person_id, $status) { - if (!is_numeric($message_id)) - { - return $this->_error('', MSG_ERR_INVALID_MSG_ID); - } + if (!is_numeric($message_id)) return error('The given message id is not valid', MSG_ERR_INVALID_MSG_ID); + if (!is_numeric($person_id)) return error('The given person id is not valid', MSG_ERR_INVALID_RECIPIENTS); + if (!is_numeric($status)) return error('The given status is not valid', MSG_ERR_INVALID_STATUS_ID); - if (!is_numeric($person_id)) - { - return $this->_error('', MSG_ERR_INVALID_USER_ID); - } - - // NOTE: Not use empty otherwise if status is 0 it returns an error - if (!isset($status)) - { - return $this->_error('', MSG_ERR_INVALID_STATUS_ID); - } + $this->_ci->MsgStatusModel->resetQuery(); // Reset an eventually already buit query // Searches if the status is already present - $result = $this->_ci->MsgStatusModel->load(array($message_id, $person_id, $status)); - if (hasData($result)) - { - // status already present - } - else + $updMessageStatusResult = $this->_ci->MsgStatusModel->load(array($message_id, $person_id, $status)); + if (!hasData($updMessageStatusResult)) // if not found { // Insert the new status $statusKey = array( @@ -177,820 +362,555 @@ class MessageLib 'person_id' => $person_id, 'status' => $status ); - - $result = $this->_ci->MsgStatusModel->insert($statusKey); + $updMessageStatusResult = $this->_ci->MsgStatusModel->insert($statusKey); } - return $result; - } - - /** - * sendMessage() - sends new internal message. This function will create a new thread - */ - public function sendMessage($sender_id, $receiver_id, $subject, $body, $priority = PRIORITY_NORMAL, $relationmessage_id = null, $oe_kurzbz = null, $multiPartMime = true) - { - if (!is_numeric($sender_id)) - { - $sender_id = $this->_ci->config->item('system_person_id'); - } - - $receivers = $this->_getReceivers($receiver_id, $oe_kurzbz); - - // If everything went ok - if (isSuccess($receivers) && is_array($receivers->retval)) - { - // If no receivers were found for this organization unit - if (count($receivers->retval) == 0) - { - $result = $this->_error($receivers->retval, MSG_ERR_OU_CONTACTS_NOT_FOUND); - } - - // Looping on receivers - for ($i = 0; $i < count($receivers->retval); $i++) - { - $receiver_id = $receivers->retval[$i]->person_id; - - // Checks if the receiver exists - if ($this->_checkReceiverId($receiver_id)) - { - // If the text and the subject of the template are not empty - if (!isEmptyString($subject) && !isEmptyString($body)) - { - $result = $this->_saveMessage($sender_id, $receiver_id, $subject, $body, $relationmessage_id, $oe_kurzbz); - // If no errors were occurred - // Leave the code commented - if (isSuccess($result)) - { - // If the system is configured to send messages immediately - if ($this->_ci->config->item('send_immediately') === true) - { - // Send message by email! - $resultSendEmail = $this->sendOne($result->retval, $subject, $body, $multiPartMime); - } - } - } - else - { - if (isEmptyString($subject)) - { - $result = $this->_error('', MSG_ERR_SUBJECT_EMPTY); - break; - } - elseif (isEmptyString($body)) - { - $result = $this->_error('', MSG_ERR_BODY_EMPTY); - break; - } - } - } - else - { - $result = $this->_error('', MSG_ERR_INVALID_RECEIVER_ID); - break; - } - } - } - // If there was some errors then copy them into the returning variable - else - { - $result = $receivers; - } - - return $result; - } - - /** - * Sends new internal message using a template - */ - public function sendMessageVorlage($sender_id, $receiver_id, $vorlage_kurzbz, $oe_kurzbz, $data, $relationmessage_id = null, $orgform_kurzbz = null, $multiPartMime = true) - { - if (!is_numeric($sender_id)) - { - $sender_id = $this->_ci->config->item('system_person_id'); - } - - $receivers = $this->_getReceivers($receiver_id, $oe_kurzbz); - - // If everything went ok - if (isSuccess($receivers) && is_array($receivers->retval)) - { - // If no receivers were found for this organization unit - if (count($receivers->retval) == 0) - { - $result = $this->_error($receivers->retval, MSG_ERR_OU_CONTACTS_NOT_FOUND); - } - else - { - // Load reveiver data to get its relative language - $this->_ci->load->model('person/Person_model', 'PersonModel'); - } - - // Looping on receivers - for ($i = 0; $i < count($receivers->retval); $i++) - { - $receiver_id = $receivers->retval[$i]->person_id; - - // Checks if the receiver exists - $result = $this->_ci->PersonModel->load($receiver_id); - if (hasData($result)) - { - // Retrieves the language of the logged user - $sprache = getUserLanguage(); - - // Loads template data - $result = $this->_ci->vorlagelib->loadVorlagetext($vorlage_kurzbz, $oe_kurzbz, $orgform_kurzbz, $sprache); - if (isSuccess($result)) - { - // If the text and the subject of the template are not empty - if (is_array($result->retval) && count($result->retval) > 0 && - !isEmptyString($result->retval[0]->text) && !isEmptyString($result->retval[0]->subject)) - { - // Parses template text - $parsedText = $this->_ci->vorlagelib->parseVorlagetext($result->retval[0]->text, $data); - // Parses subject - $subject = $this->_ci->vorlagelib->parseVorlagetext($result->retval[0]->subject, $data); - - // Save message - $result = $this->_saveMessage($sender_id, $receiver_id, $subject, $parsedText, $relationmessage_id, $oe_kurzbz); - // If no errors were occurred - if (isSuccess($result)) - { - // If the system is configured to send messages immediately - if ($this->_ci->config->item('send_immediately') === true) - { - // Send message by email! - $resultSendEmail = $this->sendOne($result->retval, $subject, $parsedText, $multiPartMime); - } - } - } - else - { - // Better message error - if (!is_array($result->retval) || (is_array($result->retval) && count($result->retval) == 0)) - { - $result = $this->_error('', MSG_ERR_TEMPLATE_NOT_FOUND); - break; - } - elseif (is_array($result->retval) && count($result->retval) > 0) - { - if (is_null($result->retval[0]->oe_kurzbz)) - { - $result = $this->_error('', MSG_ERR_TEMPLATE_NOT_FOUND); - break; - } - elseif (isEmptyString($result->retval[0]->text)) - { - $result = $this->_error('', MSG_ERR_INVALID_TEMPLATE); - break; - } - elseif (isEmptyString($result->retval[0]->subject)) - { - $result = $this->_error('', MSG_ERR_INVALID_TEMPLATE); - break; - } - } - } - } - else - { - $result = $this->_error($result->retval, EXIT_ERROR); - break; - } - } - else - { - $result = $this->_error('', MSG_ERR_INVALID_RECEIVER_ID); - break; - } - } - } - // If there was some errors then copy them into the returning variable - else - { - $result = $receivers; - } - - return $result; - } - - /** - * Gets all the messages from DB and sends them via email - */ - public function sendAll($numberToSent = null, $numberPerTimeRange = null, $email_time_range = null, $email_from_system = null) - { - $sent = true; // optimistic expectation - - // Gets standard configs - $cfg = $this->_ci->maillib->getConfigs(); - $cfg->email_number_to_sent = $numberToSent; - $cfg->email_number_per_time_range = $numberPerTimeRange; - $cfg->email_time_range = $email_time_range; - $cfg->email_from_system = $email_from_system; - - // Overrides configs with the parameters - $this->_ci->maillib->overrideConfigs($cfg); - - // Gets a number ($this->_ci->maillib->getMaxEmailToSent()) of unsent messages from DB - // having EMAIL_KONTAKT_TYPE as relative contact type - $result = $this->_ci->RecipientModel->getMessages( - EMAIL_KONTAKT_TYPE, - null, - $this->_ci->maillib->getConfigs()->email_number_to_sent - ); - // Checks if errors were occurred - if (isSuccess($result)) - { - // If data are present - if (is_array($result->retval) && count($result->retval) > 0) - { - // Iterating through the result set, if no errors occurred in the previous iteration - for ($i = 0; $i < count($result->retval) && $sent; $i++) - { - // If the person has an email account - if ((!is_null($result->retval[$i]->receiver) && $result->retval[$i]->receiver != '') - || (!is_null($result->retval[$i]->employeecontact) && $result->retval[$i]->employeecontact != '')) - { - $href = $this->_ci->config->item('message_server').$this->_ci->config->item('message_html_view_url').$result->retval[$i]->token; - - $vorlage = $this->_ci->vorlagelib->loadVorlagetext('MessageMailHTML'); - - if(hasData($vorlage)) - { - // Using a template for the html email body - $body = $this->_ci->parser->parse_string( - $vorlage->retval[0]->text, - array( - 'href' => $href, - 'subject' => $result->retval[$i]->subject, - 'body' => $result->retval[$i]->body - ), - true - ); - } - else - { - // Using a template for the html email body - $body = $this->_ci->parser->parse( - 'templates/mailHTML', - array( - 'href' => $href, - 'subject' => $result->retval[$i]->subject, - 'body' => $result->retval[$i]->body - ), - true - ); - } - if (is_null($body) || $body == '') - { - $this->_ci->loglib->logError('Error while parsing the mail template'); - } - - $vorlage = $this->_ci->vorlagelib->loadVorlagetext('MessageMailTXT'); - if(hasData($vorlage)) - { - // Using a template for the plain text email body - $altBody = $this->_ci->parser->parse_string( - $vorlage->retval[0]->text, - array( - 'href' => $href, - 'subject' => $result->retval[$i]->subject, - 'body' => $result->retval[$i]->body - ), - true - ); - } - else - { - // Using a template for the plain text email body - $altBody = $this->_ci->parser->parse( - 'templates/mailTXT', - array( - 'href' => $href, - 'subject' => $result->retval[$i]->subject, - 'body' => $result->retval[$i]->body - ), - true - ); - } - if (is_null($altBody) || $altBody == '') - { - $this->_ci->loglib->logError('Error while parsing the mail template'); - } - - // If the sender is not an employee, then system-sender is used if empty - $sender = ''; - if (!is_null($result->retval[0]->senderemployeecontact) && $result->retval[0]->senderemployeecontact != '') - { - $sender = $result->retval[0]->senderemployeecontact.'@'.DOMAIN; - } - - $receiverContact = $result->retval[$i]->receiver; - if (!is_null($result->retval[$i]->employeecontact) && $result->retval[$i]->employeecontact != '') - { - $receiverContact = $result->retval[$i]->employeecontact.'@'.DOMAIN; - } - - // Sending email - $sent = $this->_ci->maillib->send( - $sender, - $receiverContact, - $result->retval[$i]->subject, - $body, - null, - null, - null, - $altBody - ); - // If errors were occurred while sending the email - if (!$sent) - { - $this->_ci->loglib->logError('Error while sending an email'); - // Writing errors in tbl_msg_recipient - $sme = $this->setMessageError( - $result->retval[$i]->message_id, - $result->retval[$i]->receiver_id, - 'Error while sending an email', - $result->retval[$i]->sentinfo - ); - if (!$sme) - { - $this->_ci->loglib->logError('Error while updating DB'); - } - } - else - { - // Setting the message as sent in DB - $sent = $this->setMessageSent($result->retval[$i]->message_id, $result->retval[$i]->receiver_id); - // If some errors occurred - if (!$sent) - { - $this->_ci->loglib->logError('Error while updating DB'); - } - } - } - else - { - $this->_ci->loglib->logError('This person does not have an email account'); - // Writing errors in tbl_msg_recipient - $sme = $this->setMessageError( - $result->retval[$i]->message_id, - $result->retval[$i]->receiver_id, - 'This person does not have an email account', - $result->retval[$i]->sentinfo - ); - if (!$sme) - { - $this->_ci->loglib->logError('Error while updating DB'); - } - $sent = true; // Non blocking error - } - } - } - else - { - $this->_ci->loglib->logInfo('There are no email to be sent'); - $sent = false; - } - } - else - { - $this->_ci->loglib->logError('Something went wrong while getting data from DB'); - $sent = false; - } - - return $sent; - } - - /** - * Gets one message from DB and sends it via email - */ - public function sendOne($message_id, $subject = null, $body = null, $multiPartMime = true) - { - $sent = true; // optimistic expectation - - // Get a specific message from DB having EMAIL_KONTAKT_TYPE as relative contact type - $result = $this->_ci->RecipientModel->getMessages( - EMAIL_KONTAKT_TYPE, - null, - null, - $message_id - ); - - // Checks if errors were occurred - if (isSuccess($result)) - { - // If data are present - if (is_array($result->retval) && count($result->retval) > 0) - { - // If the person has an email account - if ((!is_null($result->retval[0]->receiver) && $result->retval[0]->receiver != '') - || (!is_null($result->retval[0]->employeecontact) && $result->retval[0]->employeecontact != '')) - { - // If it is required use a multi-part message in MIME format - if ($multiPartMime === true) - { - // Using a template for the html email body - $href = $this->_ci->config->item('message_server').$this->_ci->config->item('message_html_view_url').$result->retval[0]->token; - - $vorlage = $this->_ci->vorlagelib->loadVorlagetext('MessageMailHTML'); - if(hasData($vorlage)) - { - $bodyMsg = $this->_ci->parser->parse_string( - $vorlage->retval[0]->text, - array( - 'href' => $href, - 'subject' => $result->retval[0]->subject, - 'body' => $result->retval[0]->body - ), - true - ); - } - else - { - $bodyMsg = $this->_ci->parser->parse( - 'templates/mailHTML', - array( - 'href' => $href, - 'subject' => $result->retval[0]->subject, - 'body' => $result->retval[0]->body - ), - true - ); - } - if (is_null($bodyMsg) || $bodyMsg == '') - { - // $body = $result->retval[0]->body; - $this->_ci->loglib->logError('Error while parsing the html mail template'); - } - - // Using a template for the plain text email body - $vorlage = $this->_ci->vorlagelib->loadVorlagetext('MessageMailTXT'); - if(hasData($vorlage)) - { - $altBody = $this->_ci->parser->parse_string( - $vorlage->retval[0]->text, - array( - 'href' => $href, - 'subject' => $result->retval[0]->subject, - 'body' => $result->retval[0]->body - ), - true - ); - } - else - { - $altBody = $this->_ci->parser->parse( - 'templates/mailTXT', - array( - 'href' => $href, - 'subject' => $result->retval[0]->subject, - 'body' => $result->retval[0]->body - ), - true - ); - } - if (is_null($altBody) || $altBody == '') - { - $this->_ci->loglib->logError('Error while parsing the plain text mail template'); - } - } - else - { - $bodyMsg = $altBody = $body; - } - - // If the sender is not an employee, then system-sender is used if empty - $sender = ''; - if (!is_null($result->retval[0]->senderemployeecontact) && $result->retval[0]->senderemployeecontact != '') - { - $sender = $result->retval[0]->senderemployeecontact.'@'.DOMAIN; - } - - $receiverContact = $result->retval[0]->receiver; - if (!is_null($result->retval[0]->employeecontact) && $result->retval[0]->employeecontact != '') - { - $receiverContact = $result->retval[0]->employeecontact.'@'.DOMAIN; - } - - // Sending email - $sent = $this->_ci->maillib->send( - null, - $receiverContact, - is_null($subject) ? $result->retval[0]->subject : $subject, // if parameter subject is not null, use it! - $bodyMsg, - null, - null, - null, - $altBody - ); - // If errors were occurred while sending the email - if (!$sent) - { - $this->_ci->loglib->logError('Error while sending an email'); - // Writing errors in tbl_msg_recipient - $sme = $this->setMessageError( - $result->retval[0]->message_id, - $result->retval[0]->receiver_id, - 'Error while sending an email', - $result->retval[0]->sentinfo - ); - if (!$sme) - { - $this->_ci->loglib->logError('Error while updating DB'); - } - } - else - { - // Setting the message as sent in DB - $sent = $this->setMessageSent($result->retval[0]->message_id, $result->retval[0]->receiver_id); - // If the email has been sent and the DB updated - if (!$sent) - { - $this->_ci->loglib->logError('Error while updating DB'); - } - } - } - else - { - $this->_ci->loglib->logError('This person does not have an email account'); - // Writing errors in tbl_msg_recipient - $sme = $this->setMessageError( - $result->retval[0]->message_id, - $result->retval[0]->receiver_id, - 'This person does not have an email account', - $result->retval[0]->sentinfo - ); - if (!$sme) - { - $this->_ci->loglib->logError('Error while updating DB'); - } - $sent = true; // Non blocking error - } - } - else - { - $this->_ci->loglib->logInfo('There are no email to be sent'); - $sent = false; - } - } - else - { - $this->_ci->loglib->logError('Something went wrong while getting data from DB'); - $sent = false; - } - - return $sent; - } - - /** - * parseMessageText - */ - public function parseMessageText($text, $data = array()) - { - return $this->_ci->parser->parse_string($text, $data, true); - } - - /** - * Gets data for Person from view vw_msg_vars_person - * @param $person_id - */ - public function getMessageVarsPerson() - { - $variablesArray = array(); - - $variables = $this->_ci->MessageModel->getMessageVarsPerson(); - if (isError($variables)) - { - return $variables; - } - elseif (hasData($variables)) - { - $tmpVariablesArray = getData($variables); - // Skip person_id - for ($i = 1; $i < count($tmpVariablesArray); $i++) - { - $variablesArray['{'.str_replace(' ', '_', strtolower($tmpVariablesArray[$i])).'}'] = $tmpVariablesArray[$i]; - } - } - - return success($variablesArray); - } - - /** - * A person may belongs to more organisation units - */ - public function getOeKurzbz($sender_id) - { - $oe_kurzbz = array(); - - $this->_ci->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); - - $benutzer = $this->_ci->BenutzerfunktionModel->getByPersonId($sender_id); - if (isError($benutzer)) - { - return $benutzer; - } - elseif (hasData($benutzer)) - { - foreach (getData($benutzer) as $val) - { - $oe_kurzbz[] = $val->oe_kurzbz; - } - } - - return success($oe_kurzbz); - } - - /** - * Admin or commoner? - */ - public function getIsAdmin($sender_id) - { - $this->_ci->load->model('system/Benutzerrolle_model', 'BenutzerrolleModel'); - - return $this->_ci->BenutzerrolleModel->isAdminByPersonId($sender_id); + return $updMessageStatusResult; } //------------------------------------------------------------------------------------------------------------------ // Private methods /** - * Update the table tbl_msg_recipient + * */ - private function _updateMessageRecipient($message_id, $receiver_id, $parameters) + private function _getSender($sender_id) { - $updated = false; - - // Updates table tbl_msg_recipient - $resultUpdate = $this->_ci->RecipientModel->update(array($receiver_id, $message_id), $parameters); - // Checks if errors were occurred - if (isSuccess($resultUpdate) && is_array($resultUpdate->retval)) + // By default the sender is defined in message configuration + $sender = success($this->_ci->config->item(self::CFG_SYSTEM_PERSON_ID)); + if ($sender_id != null) // if it was given as parameter { - $updated = true; - } - - return $updated; - } - - /** - * Changes the status of the message from unsent to sent - */ - private function setMessageSent($message_id, $receiver_id) - { - $parameters = array('sent' => 'NOW()', 'sentinfo' => null); - - return $this->_updateMessageRecipient($message_id, $receiver_id, $parameters); - } - - /** - * Sets the sentInfo with the error - */ - private function setMessageError($message_id, $receiver_id, $sentInfo, $prevSentInfo = null) - { - if (!is_null($prevSentInfo) && $prevSentInfo != '') - { - $sentInfo = $prevSentInfo.SENT_INFO_NEWLINE.$sentInfo; - } - - $parameters = array('sent' => null, 'sentinfo' => $sentInfo); - - return $this->_updateMessageRecipient($message_id, $receiver_id, $parameters); - } - - /** - * Gets the receivers id that are enabled to read messages for that oe_kurzbz - */ - private function _getReceiversByOekurzbz($oe_kurzbz) - { - // Load Benutzerfunktion_model - $this->_ci->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); - // Join with table public.tbl_benutzer on field uid - $this->_ci->BenutzerfunktionModel->addJoin('public.tbl_benutzer', 'uid'); - // Get all the valid receivers id using the oe_kurzbz - $receivers = $this->_ci->BenutzerfunktionModel->loadWhere( - 'oe_kurzbz = '.$this->_ci->db->escape($oe_kurzbz). - ' AND funktion_kurzbz = '.$this->_ci->db->escape($this->_ci->config->item('assistent_function')). - ' AND (NOW() BETWEEN COALESCE(datum_von, NOW()) AND COALESCE(datum_bis, NOW()))' - ); - - return $receivers; - } - - /** - * Gets the receivers id - */ - private function _getReceivers($receiver_id, $oe_kurzbz = null) - { - $receivers = null; - - // If no receiver_id is given... - if (is_null($receiver_id)) - { - // ...a oe_kurzbz must be specified - if (is_null($oe_kurzbz)) + if (is_numeric($sender_id)) // if it valid -> it is a number { - $receivers = $this->_error('', MSG_ERR_INVALID_OU); + $sender = success($sender_id); // return it as a success object } else { - $receivers = $this->_getReceiversByOekurzbz($oe_kurzbz); + // Otherwise returns an error + $sender = error('The given sender is not valid', MSG_ERR_INVALID_SENDER); } } - // Else if the receiver id is given - else - { - $receivers = $this->_success(array(new stdClass())); - $receivers->retval[0]->person_id = $receiver_id; - } - return $receivers; + return $sender; } /** - * Checks if the given receiver id is a valid person + * Checks if the given receiver ids belong to persons in database */ - private function _checkReceiverId($receiver_id) + private function _getReceiversByPersonId($receiver_id) { - // Load Person_model $this->_ci->load->model('person/Person_model', 'PersonModel'); - $result = $this->_ci->PersonModel->load($receiver_id); - if (hasData($result)) - { - return true; - } - return false; + // Reset an eventually already buit query + $this->_ci->PersonModel->resetQuery(); + + // Get only this columns + $this->_ci->PersonModel->addSelect('person_id'); + + // Loads from database the person by its person_id + $personResult = $this->_ci->PersonModel->load($receiver_id); + if (hasData($personResult)) // if data are retrieved + { + return $personResult; // return them + } + else // otherwise an error occurred (blocking error or data not found) + { + return error('The given person id is not valid', MSG_ERR_INVALID_RECIPIENTS); + } } /** - * Save a message in DB - **/ - private function _saveMessage($sender_id, $receiver_id, $subject, $body, $relationmessage_id, $oe_kurzbz) + * Save a new message in DB + */ + private function _saveMessage($sender_id, $senderOU, $receiver_id, $receiverOU, $subject, $body, $priority, $relationmessage_id) { - // Starts db transaction + // Starts database transaction $this->_ci->db->trans_start(false); - // Save Message - $msgData = array( + $this->_ci->load->model('person/Benutzer_model', 'BenutzerModel'); + + $uid = null; + $benutzerDB = $this->_ci->BenutzerModel->loadWhere(array('person_id' => $sender_id)); + if (hasData($benutzerDB)) + { + $uid = getData($benutzerDB)[0]->uid; + } + + // Store message information in tbl_msg_message + $messageData = array( 'person_id' => $sender_id, 'subject' => $subject, 'body' => $body, - 'priority' => PRIORITY_NORMAL, + 'priority' => $priority, 'relationmessage_id' => $relationmessage_id, - 'oe_kurzbz' => $oe_kurzbz + 'oe_kurzbz' => $senderOU ); - $result = $this->_ci->MessageModel->insert($msgData); - if (isSuccess($result)) + + $saveMessageResult = $this->_ci->MessageModel->insert($messageData); + if (isSuccess($saveMessageResult)) { - // Link the message with the receiver - $msg_id = $result->retval; + $messageId = getData($saveMessageResult); // Gets the message id generated by database + + // Store message information in tbl_msg_recipient $recipientData = array( 'person_id' => $receiver_id, - 'message_id' => $msg_id, - 'token' => generateToken() + 'message_id' => $messageId, + 'token' => generateToken(), + 'oe_kurzbz' => $receiverOU ); - $result = $this->_ci->RecipientModel->insert($recipientData); - if (isSuccess($result)) + + $saveMessageResult = $this->_ci->RecipientModel->insert($recipientData); + if (isSuccess($saveMessageResult)) { - // Save message status + // Store message information in tbl_msg_status $statusData = array( - 'message_id' => $msg_id, + 'message_id' => $messageId, 'person_id' => $receiver_id, - 'status' => MSG_STATUS_UNREAD + 'status' => MSG_STATUS_UNREAD, + 'insertvon' => $uid ); - $result = $this->_ci->MsgStatusModel->insert($statusData); + $saveMessageResult = $this->_ci->MsgStatusModel->insert($statusData); } } - $this->_ci->db->trans_complete(); + $this->_ci->db->trans_complete(); // Ends database transaction - if ($this->_ci->db->trans_status() === false || isError($result)) + // If the transaction failed... + if ($this->_ci->db->trans_status() === false || isError($saveMessageResult)) { - $this->_ci->db->trans_rollback(); - $result = $this->_error('An error occurred while saving a message', EXIT_ERROR); + $this->_ci->db->trans_rollback(); // ...then rollback + } + else // otherwise commit... + { + $this->_ci->db->trans_commit(); + $saveMessageResult = success($messageId); // ...and returns the message id + } + + return $saveMessageResult; + } + + /** + * Set the message as sent successfully by setting columns 'sent' and 'sentinfo' of table tbl_msg_recipient + * sent column is set with date of delivery + * sentinfo is set to null + */ + private function _setSentSuccess($message_id, $receiver_id) + { + return $this->_ci->RecipientModel->update(array($receiver_id, $message_id), array('sent' => 'NOW()', 'sentinfo' => null)); + } + + /** + * Set the message as sent with error by setting columns 'sent' and 'sentinfo' of table tbl_msg_recipient + * Stores the type of error in 'sentinfo' column keeping en eventual previous error + * sent column is set to null + */ + private function _updatedRecipientNoticeEmailInfo($message_id, $receiver_id, $sentInfo, $prevSentInfo) + { + if (!isEmptyString($prevSentInfo)) + { + $sentInfo .= self::SENT_INFO_NEWLINE.$prevSentInfo; + } + + return $this->_ci->RecipientModel->update(array($receiver_id, $message_id), array('sent' => null, 'sentinfo' => $sentInfo)); + } + + /** + * Returns the notice body. Tries to use the template present in database and then falling back + * on the one present in filesystem. If both fail then an error is returned + */ + private function _getNoticeBody($dbEmailNoticeTemplate, $fsEmailNoticeTemplate, $viewMessageLink, $subject, $body) + { + $noticeBody = null; // pessimistic expectation + + if (!isEmptyString($dbEmailNoticeTemplate)) + { + $noticeBody = parseText( + $dbEmailNoticeTemplate, + array( + 'href' => $viewMessageLink, + 'subject' => $subject, + 'body' => $body + ) + ); } else { - $this->_ci->db->trans_commit(); - $result = $this->_success($msg_id); + $noticeBody = parseText( + $fsEmailNoticeTemplate, + array( + 'href' => $viewMessageLink, + 'subject' => $subject, + 'body' => $body + ) + ); } - return $result; + if (isEmptyString($noticeBody)) return error('An error occurred while generating the notice body'); + + return success($noticeBody); } /** - * Wrapper for function error + * Sends notice emails to the recipient of a message */ - private function _error($retval, $code) + private function _sendNoticeEmails($messageIds) { - return error($retval, $code); + // Retrieves the messages information using the given message ids array + $messagesResult = $this->_ci->RecipientModel->getMessagesById($messageIds); + if (isError($messagesResult)) return $messageRecipientResult; // if an error occured then return it + if (!hasData($messagesResult)) return error('No data found with the given message ids'); // if no data found then return an error + + $messages = array(); // all the worked messages will be added here + + // Loops through $messagesResult and stores data about a message in $message + foreach (getData($messagesResult) as $message) + { + // If the recipient organisation unit is in the list of organisation units that do not receive notice emails + if (array_search($message->receiver_ou, $this->_ci->config->item(self::CFG_OU_RECEIVERS_NO_NOTICE))) + { + // Then there is no need to send a notice email to this organisation unit + } + else // otherwise tries to retrieve the right email contact for the message recipient + { + $message->receiverContact = null; // by default set the recipient contact as null + + // If the message was sent to an organisation unit then retrives degree program email + if ($message->receiver_id == $this->_ci->config->item(self::CFG_SYSTEM_PERSON_ID) && !isEmptyString($message->receiver_ou)) + { + $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel'); + + $studiengangResult = $this->_ci->StudiengangModel->loadWhere(array('oe_kurzbz' => $message->receiver_ou)); + if (isError($studiengangResult)) return $studiengangResult; // if an error occured then return it + + // Use the degree program email + if (hasData($studiengangResult)) $message->receiverContact = getData($studiengangResult)[0]->email; + } + // If message was sent from FAS and NOT from infocenter + elseif (!isEmptyString($message->sender_ou) + && !array_search($message->sender_ou, $this->_ci->config->item(self::CFG_OU_RECEIVERS_NO_NOTICE))) + { + // If the recipient organisation unit is NOT in the list of organisation units that sent only to private emails + if (array_search($message->receiver_ou, $this->_ci->config->item(self::CFG_OU_RECEIVERS_PRIVATE)) === false) + { + $this->_ci->load->model('person/Benutzer_model', 'BenutzerModel'); + + // And the receiver has an active account for the given organisation unit + $benutzerResult = $this->_ci->BenutzerModel->getActiveUserByPersonIdAndOrganisationUnit($message->receiver_id, $message->sender_ou); + if (isError($benutzerResult)) return $benutzerResult; // if an error occured then return it + + // Use the uid + domain email + if (hasData($benutzerResult)) $message->receiverContact = getData($benutzerResult)[0]->uid .'@'.DOMAIN; + } + + // Otherwise try with the private email + if (isEmptyString($message->receiverContact)) + { + $privateEmailResult = $this->_getPrivateEmail($message->receiver_id); + if (isError($privateEmailResult)) return $privateEmailResult; // if an error occured then return it + + // Use the private email + if (hasData($privateEmailResult)) $message->receiverContact = getData($privateEmailResult); + } + } + else // the recipient is a person + { + $this->_ci->load->model('person/Benutzer_model', 'BenutzerModel'); + + // The recipient has an active account + $benutzerResult = $this->_ci->BenutzerModel->loadWhere(array('person_id' => $message->receiver_id, 'aktiv' => true)); + if (isError($benutzerResult)) return $benutzerResult; // if an error occured then return it + + // If the user is present and active + if (hasData($benutzerResult)) + { + $this->_ci->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + + $mitarbeiterResult = $this->_ci->MitarbeiterModel->loadWhere(array('mitarbeiter_uid' => getData($benutzerResult)[0]->uid)); + if (isError($mitarbeiterResult)) return $mitarbeiterResult; // if an error occured then return it + + // If employee + if (hasData($mitarbeiterResult)) + { + $message->receiverContact = getData($benutzerResult)[0]->uid .'@'.DOMAIN; // Use the uid + domain email + } + else // ...otherwise... + { + $this->_ci->load->model('crm/Prestudent_model', 'PrestudentModel'); + + // ...try to get all the prestudent for this receiver + $prestudentResults = $this->_ci->PrestudentModel->getOrganisationunitsByPersonId($message->receiver_id); + if (isError($prestudentResults)) return $prestudentResults; // if an error occured then return it + + // If there are presetudent + if (hasData($prestudentResults)) + { + $inArray = true; + $organisationUnits = getData($prestudentResults); + + // Look if any of the organization units of this prestudent are in the list of the + // organization units that will not send the notice email to the internal account + foreach ($organisationUnits as $organisationUnit) + { + // If the recipient organisation unit is NOT in the list of organisation units that sent only to private emails + if (array_search($organisationUnit, $this->_ci->config->item(self::CFG_OU_RECEIVERS_PRIVATE)) === false) + { + $inArray = false; + break; + } + } + + // If the recipient prestudent organization unit is not in in the list of the + // organization units that will not send the notice email to the internal account + if (!$inArray) + { + // Then use the private email + $privateEmailResult = $this->_getPrivateEmail($message->receiver_id); + if (isError($privateEmailResult)) return $privateEmailResult; // if an error occured then return it + + if (hasData($privateEmailResult)) $message->receiverContact = getData($privateEmailResult); + } + else // Use the most recent UID + domain + { + $this->_ci->BenutzerModel->resetQuery(); + + $this->_ci->BenutzerModel->addOrder('updateamum', 'DESC'); + $this->_ci->BenutzerModel->addOrder('insertamum', 'DESC'); + + $benutzerResult = $this->_ci->BenutzerModel->loadWhere(array('person_id' => $message->receiver_id)); + if (isError($benutzerResult)) return $benutzerResult; // if an error occured then return it + + $message->receiverContact = getData($benutzerResult)[0]->uid .'@'.DOMAIN; // Use the uid + domain email + } + } + } + } + else // otherwise use the private email + { + $privateEmailResult = $this->_getPrivateEmail($message->receiver_id); + if (isError($privateEmailResult)) return $privateEmailResult; // if an error occured then return it + + // Use the private email + if (hasData($privateEmailResult)) $message->receiverContact = getData($privateEmailResult); + } + } + } + + $messages[] = $message; // add new message to be noticed into the messages array + } + + return $this->_sendNoticeEmail($messages); } /** - * Wrapper for function success + * */ - private function _success($retval, $code = null) + private function _getPrivateEmail($person_id) { - return success($retval, $code); + $this->_ci->load->model('person/Kontakt_model', 'KontaktModel'); + + $getPrivateEmail = $this->_ci->KontaktModel->getContactByPersonId($person_id, self::EMAIL_KONTAKT_TYPE); + + if (hasData($getPrivateEmail)) return success(getData($getPrivateEmail)[0]->kontakt); + else return success(); + + return $getPrivateEmail; + } + + /** + * Core method to send one or more email notices for one or more messages + */ + private function _sendNoticeEmail($messages) + { + // Prefix for all links that will be subsequently generated + $prefixLink = $this->_ci->config->item(self::CFG_MESSAGE_SERVER).$this->_ci->config->item(self::CFG_MESSAGE_HTML_VIEW_URL); + + // Loads all the needed templates for HTML and plain text. Main templates from database, fallback templates from file system + $dbEmailNoticeTemplateHTML = $this->_loadDbNoticeEmailTemplate(self::NOTICE_TEMPLATE_HTML); + $dbEmailNoticeTemplateTXT = $this->_loadDbNoticeEmailTemplate(self::NOTICE_TEMPLATE_TXT); + $fsEmailNoticeTemplateHTML = $this->_loadFsNoticeEmailTemplate(self::NOTICE_TEMPLATE_FALLBACK_HTML); + $fsEmailNoticeTemplateTXT = $this->_loadFsNoticeEmailTemplate(self::NOTICE_TEMPLATE_FALLBACK_TXT); + + // Loops through all the messages to be sent + foreach ($messages as $messageData) + { + // Checks if this person has a valid email address where to send the notice email + if (!isEmptyString($messageData->receiverContact)) + { + // Create a link to the controller to view the message using a token + $viewMessageLink = $prefixLink.$messageData->token; + + // Generates notice email body in HTML format + $noticeHTMLBody = $this->_getNoticeBody( + $dbEmailNoticeTemplateHTML, $fsEmailNoticeTemplateHTML, $viewMessageLink, $messageData->subject, $messageData->body + ); + // If an error occured during the generation then the error itself is returned + if (isError($noticeHTMLBody)) return $noticeHTMLBody; + + // Generates notice email body in plain text format + $noticeTXTBody = $this->_getNoticeBody( + $dbEmailNoticeTemplateTXT, $fsEmailNoticeTemplateTXT, $viewMessageLink, $messageData->subject, $messageData->body + ); + // If an error occured during the generation then the error itself is returned + if (isError($noticeTXTBody)) return $noticeTXTBody; + + // Sending email + $sent = $this->_ci->maillib->send( + null, + $messageData->receiverContact, + $messageData->subject, + getData($noticeHTMLBody), + null, + null, + null, + getData($noticeTXTBody) + ); + + // If errors occurred while sending the email + if (!$sent) + { + // Set in database why this email is NOT going to be send + $sse = $this->_updatedRecipientNoticeEmailInfo( + $messageData->message_id, + $messageData->receiver_id, + 'An error occurred while sending the notice email', // current info + $messageData->sentinfo // previous info + ); + + // If database error occurred then return it, otherwise return a logic error + return isError($sse) ? $sse : error('An error occurred while updating the recipient notice email info'); + } + else // success! + { + // Set in database that the notice email was succesfully sent + $sss = $this->_setSentSuccess($messageData->message_id, $messageData->receiver_id); + if (isError($sss)) return $sss; // If database error occurred then return it + } + } + else // Because was not possible to find a valid contact + { + $reason = 'Was not possible to find a valid contact for this user'; // default reason + + // In case that the organisation unit does not receive any email notices + if (!isEmptyString($messageData->receiver_ou)) $reason = 'This organization unit does not receive email notices'; + + // In case that a degree program sent a message to a user without a valid contact or UID + if (!isEmptyString($messageData->sender_ou)) $reason = 'Sent from a degree program to a user that does not have a valid UID or a valid contact'; + + // Set in database why this email is NOT going to be send + $sse = $this->_updatedRecipientNoticeEmailInfo( + $messageData->message_id, + $messageData->receiver_id, + $reason, // current info + $messageData->sentinfo // previous info + ); + + // If database error occurred then return it + if (isError($sse)) return $sse; + } + } + + return success('Notice emails sent successfully'); + } + + /** + * Sends new message core method, may be wrapped by other methods. + * If success then returns an array of successfully saved message ids + */ + private function _sendMessage( + $receivers, $receiversOU, $subject, $body, $sender_id, $senderOU, $relationmessage_id, $priority, $multiPartMime + ) + { + // Checks if sender is fine + $sender = $this->_getSender($sender_id); + if (!hasData($sender)) return $sender; + + // Checks if the sender and receiver organisation unit are valid + if (($receiversOU != null && !$this->_ouExists($receiversOU)) || ($senderOU != null && !$this->_ouExists($senderOU))) + { + return error('The given organisation unit is not valid', MSG_ERR_INVALID_OU); + } + + // Checks subjects + if (isEmptyString($subject)) return error('The given subject is an empty string', MSG_ERR_INVALID_SUBJECT); + // Checks body + if (isEmptyString($body)) return error('The given body is an empty string', MSG_ERR_INVALID_BODY); + + $savedMessages = array(); // This array contains all the message ids of the saved messages + + // Looping on receivers + foreach (getData($receivers) as $receiver) + { + // Save message in database + $saveMessageResult = $this->_saveMessage( + getData($sender), $senderOU, $receiver->person_id, $receiversOU, $subject, $body, $priority, $relationmessage_id + ); + if (isSuccess($saveMessageResult)) // If successfully saved + { + $savedMessages[] = getData($saveMessageResult); // store the message id of the saved message + } + else + { + return $saveMessageResult; // If an error occured while saving + } + } + + // If the system is configured to send messages immediately + if ($this->_ci->config->item(self::CFG_SEND_IMMEDIATELY) === true) + { + // Looping through saved messages ids + foreach ($savedMessages as $message_id) + { + // Send message notice via email! + $sendNotice = $this->_sendNoticeEmails(array($message_id)); + + // If an error occurred then return it + if (isError($sendNotice)) return $sendNotice; + } + } + + return success($savedMessages); + } + + /** + * Checks if the given organisation unit exists in database + */ + private function _ouExists($ou) + { + $this->_ci->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel'); + + // Reset an eventually already buit query + $this->_ci->OrganisationseinheitModel->resetQuery(); + // Get only this columns + $this->_ci->OrganisationseinheitModel->addSelect('oe_kurzbz'); + // Retrieves the given organisation unit from database + $ouResults = $this->_ci->OrganisationseinheitModel->loadWhere(array('oe_kurzbz' => $ou)); + + return hasData($ouResults); + } + + /** + * Loads a the specified template from database + * Returns null if not found or on failure + */ + private function _loadDbNoticeEmailTemplate($dbTemplateName) + { + $emailNoticeTemplate = null; + + $vorlageResult = $this->_ci->vorlagelib->loadVorlagetext($dbTemplateName); + + if (hasData($vorlageResult)) + { + $emailNoticeTemplate = getData($vorlageResult)[0]->text; + } + + return $emailNoticeTemplate; + } + + /** + * Loads a the specified template from database + */ + private function _loadFsNoticeEmailTemplate($fsTemplateName) + { + return $this->_ci->load->view($fsTemplateName, null, true); } } diff --git a/application/libraries/PermissionLib.php b/application/libraries/PermissionLib.php index b84359216..348c8b87b 100644 --- a/application/libraries/PermissionLib.php +++ b/application/libraries/PermissionLib.php @@ -254,6 +254,45 @@ class PermissionLib return !$this->_inLAPersonIdsBlacklist($person_id) && $this->_hasLAPermissions(); } + /** + * Returns the study programs the person is entitled for. + * @param null $berechtigung_kurzbz If given, only study programs are retrieved according to organisational units + * assigned to that permission. + * @return array|bool array of studiengang_kz the person is entitled for. False on error. + */ + public function getSTG_isEntitledFor($berechtigung_kurzbz = null) + { + $studiengang_kz_arr = array(); + + if (self::$bb->getStgKz($berechtigung_kurzbz)) + { + return $studiengang_kz_arr = self::$bb->getStgKz($berechtigung_kurzbz); + } + else + { + return false; + } + } + + /** + * Returns the organisational units the person is entitled for. + * @param null $berechtigung_kurzbz + * @return array|bool array of oe_kurzbz the person is entitled for. False on error. + */ + public function getOE_isEntitledFor($berechtigung_kurzbz = null) + { + $oe_kurzbz_arr = array(); + + if (self::$bb->getOEkurzbz($berechtigung_kurzbz)) + { + return $oe_kurzbz_arr = self::$bb->getOEkurzbz($berechtigung_kurzbz); + } + else + { + return false; + } + } + //------------------------------------------------------------------------------------------------------------------ // Private methods diff --git a/application/libraries/PersonLogLib.php b/application/libraries/PersonLogLib.php index b56937dfe..fe9a82504 100644 --- a/application/libraries/PersonLogLib.php +++ b/application/libraries/PersonLogLib.php @@ -8,6 +8,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); class PersonLogLib { const PARKED_LOGNAME = 'Parked'; + const ONHOLD_LOGNAME = 'Onhold'; /** * Constructor @@ -75,7 +76,7 @@ class PersonLogLib return $decoded_logs; } else - show_error($result->retval); + show_error(getError($result)); } /** @@ -91,26 +92,20 @@ class PersonLogLib */ public function park($person_id, $date, $taetigkeit_kurzbz, $app = 'core', $oe_kurzbz = null, $user = null) { - $logdata = array( + $onhold = $this->getOnHoldDate($person_id); + + if (hasData($onhold)) + return error("Person already on hold"); + + $logjson = array( 'name' => self::PARKED_LOGNAME ); - $data = array( - 'person_id' => $person_id, - 'zeitpunkt' => $date, - 'taetigkeit_kurzbz' => $taetigkeit_kurzbz, - 'app' => $app, - 'oe_kurzbz' => $oe_kurzbz, - 'logtype_kurzbz' => 'Processstate', - 'logdata' => json_encode($logdata), - 'insertvon' => $user - ); - - return $this->ci->PersonLogModel->insert($data); + return $this->_savePsLog($person_id, $date, $taetigkeit_kurzbz, $logjson, $app, $oe_kurzbz, $user); } /** - * Unparks a person, i.e. removes all log entries in the future + * Unparks a person, i.e. removes all log entries in the future with logname for parking * @param $person_id * @return array with deleted logids */ @@ -131,17 +126,9 @@ class PersonLogLib { $deleted[] = $log->log_id; } - else - { - return $delresult; - } } } } - else - { - return $result; - } return success($deleted); } @@ -172,4 +159,111 @@ class PersonLogLib return $parkeddate; } + + /** + * Sets person on hold, i.e. marks a person so no actions are expected for the person (e.g. as a prestudent). + * Done by adding a logentry with a special name. can be undone only manually by clicking button. + * @param $person_id + * @param $date + * @param $taetigkeit_kurzbz + * @param string $app + * @param null $oe_kurzbz + * @param null $user + * @return array + */ + public function setOnHold($person_id, $date, $taetigkeit_kurzbz, $app = 'core', $oe_kurzbz = null, $user = null) + { + $parked = $this->getParkedDate($person_id); + + if (hasData($parked)) + return error("Person already parked"); + + $logjson = array( + 'name' => self::ONHOLD_LOGNAME + ); + + return $this->_savePsLog($person_id, $date, $taetigkeit_kurzbz, $logjson, $app, $oe_kurzbz, $user); + } + + /** + * Removes on hold status, i.e. removes all log entries with logname for on hold + * @param $person_id + * @return array + */ + public function removeOnHold($person_id) + { + $deleted = array(); + + $result = $this->ci->PersonLogModel->filterLog($person_id); + if (hasData($result)) + { + foreach ($result->retval as $log) + { + $logdata = json_decode($log->logdata); + if (isset($logdata->name) && $logdata->name === self::ONHOLD_LOGNAME) + { + $delresult = $this->ci->PersonLogModel->deleteLog($log->log_id); + if (isSuccess($delresult)) + { + $deleted[] = $log->log_id; + } + } + } + } + return success($deleted); + } + + /** + * Gets date until which a person is on hold + * @param $person_id + * @return the date if person is on hold, null otherwise + */ + public function getOnHoldDate($person_id) + { + $result = $this->ci->PersonLogModel->filterLog($person_id); + + $onholddate = null; + + if (hasData($result)) + { + foreach ($result->retval as $log) + { + $logdata = json_decode($log->logdata); + if (isset($logdata->name) && $logdata->name === self::ONHOLD_LOGNAME) + { + $onholddate = $log->zeitpunkt; + break; + } + } + } + + return $onholddate; + } + + /** + * Saves a processstate log with specified parameters, including a specified log date. + * @param $person_id + * @param $date + * @param $taetigkeit_kurzbz + * @param $logjson + * @param string $app + * @param null $oe_kurzbz + * @param null $user + * @return mixed + */ + private function _savePsLog($person_id, $date, $taetigkeit_kurzbz, $logjson, $app = 'core', $oe_kurzbz = null, $user = null) + { + $data = array( + 'person_id' => $person_id, + 'zeitpunkt' => $date, + 'taetigkeit_kurzbz' => $taetigkeit_kurzbz, + 'app' => $app, + 'oe_kurzbz' => $oe_kurzbz, + 'logtype_kurzbz' => 'Processstate', + 'logdata' => json_encode($logjson), + 'insertvon' => $user + ); + + return $this->ci->PersonLogModel->insert($data); + } } diff --git a/application/libraries/PhrasesLib.php b/application/libraries/PhrasesLib.php index af642fe9e..dec3d54c0 100644 --- a/application/libraries/PhrasesLib.php +++ b/application/libraries/PhrasesLib.php @@ -107,7 +107,7 @@ class PhrasesLib // If no

tags required if ($blockTags == 'no') { - $tmpText = $textileParser->textileThis($result->retval[$i]->text); // Parse + $tmpText = $textileParser->parse($result->retval[$i]->text); // Parse // Removes tags

and

from the beginning and from the end of the string if they are present // NOTE: Those tags are usually, but not always, added by the textile parser @@ -127,7 +127,7 @@ class PhrasesLib } else { - $result->retval[$i]->text = $textileParser->textileThis($result->retval[$i]->text); + $result->retval[$i]->text = $textileParser->parse($result->retval[$i]->text); } } } @@ -165,16 +165,6 @@ class PhrasesLib } /** - * parseVorlagetext() - will parse a Vorlagetext. - */ - public function parseVorlagetext($text, $data = array()) - { - if (isEmptyString($text)) return error('Not a valid text'); - - return $this->_ci->parser->parse_string($text, $data, true); - } - - /** * Retrieves a phrases from the the property _phrases with the given parameters * It also replace parameters inside the phrase if they are provided * @param string $category Category name which is used to categorize the phrase. @@ -201,7 +191,7 @@ class PhrasesLib { if (!is_array($parameters)) $parameters = array(); // if params is not an array - return $this->_ci->parser->parse_string($_phrase->text, $parameters, true); // parsing + return parseText($_phrase->text, $parameters); // parsing } } } diff --git a/application/libraries/StudienplanLib.php b/application/libraries/StudienplanLib.php index ecc66e5bf..1b393a8e9 100644 --- a/application/libraries/StudienplanLib.php +++ b/application/libraries/StudienplanLib.php @@ -37,7 +37,9 @@ class StudienplanLib 'pflicht' => $row->pflicht, 'zeugnis' => $row->zeugnis, 'bezeichnung' => $row->bezeichnung, - 'ects' => $row->ects + 'kurzbz' => $row->kurzbz, + 'ects' => $row->ects, + 'semester' => $row->semester ); $childs = $this->getChildElements($row->studienplan_lehrveranstaltung_id); if(is_array($childs) && count($childs) > 0) @@ -65,7 +67,9 @@ class StudienplanLib 'pflicht' => $row->pflicht, 'zeugnis' => $row->zeugnis, 'bezeichnung' => $row->bezeichnung, - 'ects' => $row->ects + 'kurzbz' => $row->kurzbz, + 'ects' => $row->ects, + 'semester' => $row->semester ); $childs = $this->getChildElements($row->studienplan_lehrveranstaltung_id); if(is_array($childs)) diff --git a/application/libraries/TableWidgetLib.php b/application/libraries/TableWidgetLib.php new file mode 100644 index 000000000..dc746b6d5 --- /dev/null +++ b/application/libraries/TableWidgetLib.php @@ -0,0 +1,238 @@ +_ci =& get_instance(); // get code igniter instance + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Checks if at least one of the permissions given as parameter (requiredPermissions) belongs + * to the authenticated user, if confirmed then is allowed to use this FilterWidget. + * If the parameter requiredPermissions is NOT given or is not present in the session, + * then NO one is allow to use this FilterWidget + * Wrapper method to permissionlib->hasAtLeastOne + */ + public function isAllowed($requiredPermissions = null) + { + $this->_ci->load->library('PermissionLib'); // Load permission library + + // Gets the required permissions from the session if they are not provided as parameter + $rq = $requiredPermissions; + if ($rq == null) $rq = $this->getSessionElement(self::REQUIRED_PERMISSIONS); + + return $this->_ci->permissionlib->hasAtLeastOne($rq, self::PERMISSION_TABLE_METHOD, self::PERMISSION_TYPE); + } + + /** + * Wrapper method to the session helper funtions to retrieve the whole session for this table widget + */ + public function getSession() + { + return getSessionElement(self::SESSION_NAME, $this->_tableUniqueId); + } + + /** + * Wrapper method to the session helper funtions to retrieve one element from the session of this table widget + */ + public function getSessionElement($name) + { + $session = getSessionElement(self::SESSION_NAME, $this->_tableUniqueId); + + if (isset($session[$name])) + { + return $session[$name]; + } + + return null; + } + + /** + * Wrapper method to the session helper funtions to set the whole session for this table widget + */ + public function setSession($data) + { + setSessionElement(self::SESSION_NAME, $this->_tableUniqueId, $data); + } + + /** + * Wrapper method to the session helper funtions to set one element in the session for this table widget + */ + public function setSessionElement($name, $value) + { + $session = getSessionElement(self::SESSION_NAME, $this->_tableUniqueId); + + $session[$name] = $value; + + setSessionElement(self::SESSION_NAME, $this->_tableUniqueId, $session); // stores the single value + } + + /** + * + */ + public function dropExpiredTableWidgets() + { + // Loads the session for all the table widgets + $tableWidgetsSession = getSession(self::SESSION_NAME); + + // If something is present in session + if ($tableWidgetsSession != null) + { + // Loops in the session for all the table widgets + foreach ($tableWidgetsSession as $tableWidget => $tableWidgetData) + { + // If this table widget is not the currrent used table widget and the it is expired... + if ($this->_tableUniqueId != $tableWidget && $tableWidgetData[self::SESSION_TIMEOUT] <= time()) + { + cleanSessionElement(self::SESSION_NAME, $tableWidget); // ...remove it + } + } + } + } + + /** + * Generate the query to retrieve the dataset for a table widget + */ + public function generateDatasetQuery($query) + { + return 'SELECT * FROM ('.$query.') '.self::DATASET_TABLE_ALIAS; + } + + /** + * Retrieves the dataset from the DB + */ + public function getDataset($datasetQuery) + { + $dataset = null; + + if ($datasetQuery != null) + { + $this->_ci->load->model('system/Filters_model', 'FiltersModel'); + + // Execute the given SQL statement suppressing error messages + $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery); + } + + return $dataset; + } + + /** + * Retrieves metadata from the last executed query + */ + public function getExecutedQueryMetaData() + { + return $this->_ci->FiltersModel->getExecutedQueryMetaData(); + } + + /** + * Retrieves the list of fields from the last executed query + */ + public function getExecutedQueryListFields() + { + return $this->_ci->FiltersModel->getExecutedQueryListFields(); + } + + /** + * Return an unique string that identify this table widget + * NOTE: The default value is the URI where the FilterWidget is called + * If the fhc_controller_id is present then is also used + */ + public function setTableUniqueIdByParams($params) + { + if ($params != null + && is_array($params) + && isset($params[self::TABLE_UNIQUE_ID]) + && !isEmptyString($params[self::TABLE_UNIQUE_ID])) + { + $tableUniqueId = $this->_ci->router->directory.$this->_ci->router->class.'/'. + $this->_ci->router->method.'/'. + $params[self::TABLE_UNIQUE_ID]; + + $this->setTableUniqueId($tableUniqueId); + } + } + + /** + * Set the _tableUniqueId property + */ + public function setTableUniqueId($tableUniqueId) + { + $this->_tableUniqueId = $tableUniqueId; + } +} diff --git a/application/libraries/UDFLib.php b/application/libraries/UDFLib.php index 6166b44a9..bc8552c25 100644 --- a/application/libraries/UDFLib.php +++ b/application/libraries/UDFLib.php @@ -540,7 +540,7 @@ class UDFLib { if (is_object($udfResults) && isset($udfResults->retval)) { - show_error($udfResults->retval); + show_error(getError($udfResults)); } elseif (is_string($udfResults)) { diff --git a/application/libraries/VariableLib.php b/application/libraries/VariableLib.php new file mode 100644 index 000000000..2f038531b --- /dev/null +++ b/application/libraries/VariableLib.php @@ -0,0 +1,131 @@ +_ci =& get_instance(); + + $this->_variables = null; + + $this->_ci->load->model('system/Variable_model', 'VariableModel'); + $this->_ci->load->model('organisation/studiensemester_model', 'StudiensemesterModel'); + + if (isset($loggeduid['uid']) && !isEmptyString($loggeduid['uid'])) + $this->_setVariables($loggeduid['uid']); + else + { + show_error('uid of logged user not passed!'); + } + } + + /** + * Gets an already loaded user variable by variable name. + * @param $name + * @return mixed|null + */ + public function getVar($name) + { + return isset($this->_variables[$name]) ? $this->_variables[$name] : null; + } + + /** + * Changes variables having Studiensemester as value. Sets variable value to next or previous Semester. + * @param $uid variable is set for this user + * @param $name variable name + * @param $change if positive, variable value is set to next semester, negative - previous semester + * @return array if change was successfull, uid and variable name. Infotext otherwise. + */ + public function changeStudiensemesterVar($uid, $name, $change) + { + $result = error('error when setting variable!'); + $notchangedtext = "Studiensemester variable not changed."; + + if (!isEmptyString($uid) && !isEmptyString($name) && is_numeric($change)) + { + $change = (int)$change; + $varres = $this->_ci->VariableModel->getVariables($uid, array($name)); + + if (isSuccess($varres)) + { + if (hasData($varres)) + { + $currStudiensemester = getData($varres); + + if ($change === 0) + { + $result = success($notchangedtext); + } + else + { + if ($change > 0) + { + $changedsem = $this->_ci->StudiensemesterModel->getNextFrom($currStudiensemester[$name]); + } + elseif ($change < 0) + { + $changedsem = $this->_ci->StudiensemesterModel->getPreviousFrom($currStudiensemester[$name]); + } + + if (hasData($changedsem)) + { + $changedsem = getData($changedsem); + + $result = $this->_ci->VariableModel->setVariable($uid, $name, $changedsem[0]->studiensemester_kurzbz); + //update property + $this->_setVariable($uid, $name); + } + else + { + $result = success($notchangedtext); + } + } + } + } + } + return $result; + } + + /** + * "Refreshes" variable value with given name by retrieving current value from db and saving it. + * @param $uid + * @param $name + */ + private function _setVariable($uid, $name) + { + $variable = $this->_ci->VariableModel->getVariables($uid, array($name)); + + if (hasData($variable)) + { + $variable = getData($variable); + $this->_variables[$name] = $variable[$name]; + } + } + + /** + * "Refreshes" all variable values by retrieving current values from db and saving them. + * @param $uid + */ + private function _setVariables($uid) + { + $variables = $this->_ci->VariableModel->getVariables($uid); + if (hasData($variables)) + { + $this->_variables = getData($variables); + } + } +} diff --git a/application/libraries/VorlageLib.php b/application/libraries/VorlageLib.php index d6c9d6a98..9679dff1c 100644 --- a/application/libraries/VorlageLib.php +++ b/application/libraries/VorlageLib.php @@ -188,18 +188,4 @@ class VorlageLib $vorlagetext = $this->ci->VorlageStudiengangModel->update($vorlagestudiengang_id, $data); return $vorlagetext; } - - /** - * parseVorlagetext() - will parse a Vorlagetext. - * - * @param string $text REQUIRED - * @param array $data REQUIRED - * @return string - */ - public function parseVorlagetext($text, $data = array()) - { - if (isEmptyString($text)) return error('Not a valid text'); - - return $this->ci->parser->parse_string($text, $data, true); - } } diff --git a/application/models/CL/Messages_model.php b/application/models/CL/Messages_model.php index 5f3f40e6d..cbb42543f 100644 --- a/application/models/CL/Messages_model.php +++ b/application/models/CL/Messages_model.php @@ -1,11 +1,33 @@ +
+
+ + On %s %s %s wrote: + +
+
+ %s +
'; + + const NO_AUTH_UID = 'online'; // hard coded uid if no authentication is performed + + // Recipients types + const TYPE_PERSONS = 'persons'; + const TYPE_PRESTUDENTS = 'prestudents'; + + const ALT_OE = 'infocenter'; // alternative organisation unit when no one is found for a presetudent + /** * Constructor */ @@ -14,159 +36,618 @@ class Messages_model extends CI_Model parent::__construct(); // Loads the message library - $this->load->library('MessageLib'); - + $this->load->library('MessageLib'); // MessageModel loaded here! // Loads the person log library $this->load->library('PersonLogLib'); + // Loads the widget library + $this->load->library('WidgetLib'); + // Loads model MessageToken_model $this->load->model('system/MessageToken_model', 'MessageTokenModel'); + // Loads model Benutzerrolle_model + $this->load->model('system/Benutzerrolle_model', 'BenutzerrolleModel'); + // Loads model Prestudent_model + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); } + //------------------------------------------------------------------------------------------------------------------ + // Public methods + /** - * Executes message sending - * @param $sender_id - * @return array wether execution was successfull - error or success + * Set a message as read by its id ($message_id + $person_id) */ - public function send($msgVarsData, $relationmessage_id = null, $oe_kurzbz = null, $vorlage_kurzbz = null, $msgVars = null) + public function setMessageRead($message_id, $person_id) { - $subject = $this->input->post('subject'); - $body = $this->input->post('body'); + // Checks parameters + if (!is_numeric($message_id) || !is_numeric($person_id)) return error('Invalid setMessageRead parameters'); - $authUser = $this->getAuthUser(); + // Loads needed models + $this->load->model('system/MsgStatus_model', 'MsgStatusModel'); - if (isError($authUser)) return $authUser; + $statuResult = $this->MsgStatusModel->loadWhere( + array( + 'message_id' => $message_id, + 'person_id' => $person_id, + 'status' => MSG_STATUS_READ + ) + ); - $sender_id = getData($authUser)[0]->person_id; - - // Send message(s) - if (hasData($msgVarsData)) + if (isError($statuResult)) return $statuResult; + if (!hasData($statuResult)) { - for ($i = 0; $i < count(getData($msgVarsData)); $i++) - { - $parsedText = ""; - $msgVarsDataArray = $this->replaceKeys((array)getData($msgVarsData)[$i]); // replaces array keys - - // Send without vorlage - if (isEmptyString($vorlage_kurzbz)) - { - $parsedText = $this->messagelib->parseMessageText($body, $msgVarsDataArray); - $msg = $this->messagelib->sendMessage($sender_id, $msgVarsDataArray['person_id'], $subject, $parsedText, PRIORITY_NORMAL, $relationmessage_id, $oe_kurzbz); - } - // Send with vorlage - else - { - if (is_array($msgVars)) - { - // Additional message variables - foreach ($msgVars as $key => $msgvar) - { - $msgVarsDataArray[$key] = $msgvar; - } - } - $msg = $this->messagelib->sendMessageVorlage($sender_id, $msgVarsDataArray['person_id'], $vorlage_kurzbz, $oe_kurzbz, $msgVarsDataArray); - } - - if (isError($msg)) return $msg; - - // Write log entry - $personLog = $this->personloglib->log( - $msgVarsDataArray['person_id'], - 'Action', - array( - 'name' => 'Message sent', - 'message' => 'Message sent from person '.$sender_id.' to '.$msgVarsDataArray['person_id'].', messageid '.getData($msg), - 'success' => 'true' - ), - 'kommunikation', - 'core', - null, - getAuthUID() - ); - - if (isError($personLog)) return $personLog; - } - - return success('Messages sent successfully'); + // Set date used to insert + return $this->MsgStatusModel->insert( + array( + 'message_id' => $message_id, + 'person_id' => $person_id, + 'status' => MSG_STATUS_READ, + 'insertvon' => getAuthUID() + ) + ); // insert and return result } else { - return $msgVarsData; + return success('Already set as read'); } } /** - * Send a reply + * Prepares data for the view system/messages/ajaxWrite */ - public function sendReply($subject, $body, $persons, $relationmessage_id, $token) + public function prepareAjaxWrite() { - $relationmsg = $this->MessageTokenModel->getMessageByToken($token); - if (!hasData($relationmsg) || $relationmessage_id !== getData($relationmsg)[0]->message_id) - { - show_error('Error while sending reply'); - } + $ouResult = $this->PrestudentModel->getOrganisationunitsByPersonId(getAuthPersonId()); - // Get sender (receiver of previous msg) - $sender_id = getData($relationmsg)[0]->receiver_id; + if (isError($ouResult)) show_error('An error occurred while loading this page, please contact the site administrator'); - // Get message data of persons - $data = $this->MessageTokenModel->getPersonData($persons); - if (hasData($data)) + $ouOptions = ''; + + if (hasData($ouResult)) { - for ($i = 0; $i < count(getData($data)); $i++) + foreach (getData($ouResult) as $ou) { - $dataArray = (array)getData($data)[$i]; - - $msg = $this->messagelib->sendMessage($sender_id, $dataArray['person_id'], $subject, $body, PRIORITY_NORMAL, $relationmessage_id, null); - if (isError($msg)) return $msg; - - // Logs person data - $personLog = $this->personloglib->log( - $sender_id, - 'Action', - array( - 'name' => 'Message sent', - 'message' => 'Message sent from person '.$sender_id.' to '.$dataArray['person_id'].', messageid '.getData($msg), - 'success' => 'true' - ), - 'kommunikation', - 'core', - null, - 'online' + $ouOptions .= sprintf( + "\n".'', + is_numeric($ou->prestudent_id) ? $ou->oe_kurzbz : self::ALT_OE, + $ou->bezeichnung . (is_numeric($ou->prestudent_id) ? '' : ' *') ); - - // Unpark bewerber after he sends message - $personLog = $this->personloglib->unPark($sender_id); - - if (isError($personLog)) return $personLog; } } - return success('Reply sent'); + return array('organisationUnitOptions' => $ouOptions); } /** - * + * Prepares data for the view system/messages/ajaxWriteReply */ - public function getAuthUser() + public function prepareAjaxWriteReply($token) { - $sender_id = null; + if (isEmptyString($token)) show_error('The given token is not valid'); - $this->load->model('person/Person_model', 'PersonModel'); - $authUser = $this->PersonModel->getByUid(getAuthUID()); + // Retrieves message using the given token + $messageResult = $this->MessageTokenModel->getMessageByToken($token); + if (isError($messageResult)) show_error('An error occurred while loading this page, please contact the site administrator'); - if (!hasData($authUser)) $authUser = error('The current logged user person_id is not defined'); + if (hasData($messageResult)) + { + $message = getData($messageResult)[0]; // Found message data - return $authUser; + // Retrieves message sender information + $senderResult = $this->MessageTokenModel->getSenderData($message->sender_id); + if (isError($senderResult)) show_error('An error occurred while loading this page, please contact the site administrator'); + + if (hasData($senderResult)) + { + $sender = getData($senderResult)[0]; // Found sender data + + $replySubject = self::REPLY_SUBJECT_PREFIX.$message->subject; + $replyBody = $this->_getReplyBody($message->body, $sender->vorname, $sender->nachname, $message->sent); + + return array ( + 'receiver' => $sender->vorname.' '.$sender->nachname, // yep! the sender of the sent message is the receiver of the reply message + 'subject' => $replySubject, + 'body' => $replyBody, + 'receiver_id' => $message->sender_id, + 'relationmessage_id' => $message->message_id, + 'token' => $token + ); + } + } } /** - * + * Prepares data for the view system/messages/ajaxRead + * If everything is fine returns a list of received messages (objects) */ - public function replaceKeys($data) + public function prepareAjaxReadReceived() + { + // Retrieves received messages for the logged user and its organisation units + $receivedMessagesResult = $this->RecipientModel->getReceivedMessages( + getAuthPersonId(), + $this->config->item(MessageLib::CFG_OU_RECEIVERS) + ); + // If an error occurred return it + if (isError($receivedMessagesResult)) return $receivedMessagesResult; + + // If data were found + if (hasData($receivedMessagesResult)) + { + $jsonArray = array(); // array that contains all the received messages + + // Collect'em all in the array $jsonArray + foreach (getData($receivedMessagesResult) as $receivedMessage) + { + $jsonRecord = new stdClass(); + $jsonRecord->message_id = $receivedMessage->message_id; + $jsonRecord->subject = $receivedMessage->subject; + $jsonRecord->body = $receivedMessage->body; + $jsonRecord->from = $receivedMessage->vorname.' '.$receivedMessage->nachname; + $sentDate = new DateTime($receivedMessage->sent); + $jsonRecord->sent = $sentDate->format('d/m/Y H:i:s'); + $jsonRecord->status = $receivedMessage->status; + $jsonRecord->statusPersonId = $receivedMessage->statuspersonid; + $jsonRecord->token = $receivedMessage->token; + + $jsonArray[] = $jsonRecord; + } + + return success(json_encode($jsonArray)); // return as an json encoded string + } + + return success('No messages were found'); // NOT a blocking error + } + + /** + * Prepares data for the view system/messages/ajaxRead + * If everything is fine returns a list of sent messages (objects) + */ + public function prepareAjaxReadSent() + { + // Retrieves sent messages from the logged user + $sentMessagesResult = $this->RecipientModel->getSentMessages(getAuthPersonId()); + if (isError($sentMessagesResult)) return $sentMessagesResult; // If an error occurred return it + + if (hasData($sentMessagesResult)) + { + $jsonArray = array();// array that contains all the sent messages + + // Collect'em all in the array $jsonArray + foreach (getData($sentMessagesResult) as $sentMessage) + { + $jsonRecord = new stdClass(); + $jsonRecord->message_id = $sentMessage->message_id; + $jsonRecord->subject = $sentMessage->subject; + $jsonRecord->body = $sentMessage->body; + $sentDate = new DateTime($sentMessage->sent); + $jsonRecord->sent = $sentDate->format('d/m/Y H:i:s'); + $jsonRecord->status = $sentMessage->status; + $jsonRecord->statusPersonId = $sentMessage->statuspersonid; + $jsonRecord->token = $sentMessage->token; + + if ($sentMessage->person_id == $this->config->item(MessageLib::CFG_SYSTEM_PERSON_ID)) + { + $jsonRecord->to = $sentMessage->oe; + } + else + { + $jsonRecord->to = $sentMessage->vorname.' '.$sentMessage->nachname; + } + + $jsonArray[] = $jsonRecord; + } + + return success(json_encode($jsonArray)); // return as an json encoded string + } + + return success('No messages were found'); // NOT a blocking error + } + + /** + * Prepares data for the view system/messages/htmlRead using a token that identifies a single message + */ + public function prepareHtmlRead($token) + { + if (isEmptyString($token)) show_error('The given token is not valid'); + + // Retrieves message using the given token + $messageResult = $this->MessageTokenModel->getMessageByToken($token); + if (isError($messageResult)) show_error(getError($messageResult)); + if (!hasData($messageResult)) show_error('No message found with the given token'); + + $message = getData($messageResult)[0]; // Found message data + + // Set message as read + $srmsbtResult = $this->MessageTokenModel->setReadMessageStatusByToken($token); + if (isError($srmsbtResult)) show_error(getError($srmsbtResult)); + + // Retrieves message sender information + $senderResult = $this->MessageTokenModel->getSenderData($message->sender_id); + if (isError($senderResult)) show_error(getError($senderResult)); + if (!hasData($senderResult)) show_error('No sender information found'); + + $sender = getData($senderResult)[0]; // Found sender data + + // Check if the receiver is an employee + $isEmployee = false; // not by default + $isEmployeeResult = $this->MessageTokenModel->isEmployee($message->receiver_id); + if (isError($isEmployeeResult)) show_error(getError($isEmployeeResult)); + if (hasData($isEmployeeResult)) $isEmployee = true; + + // If the sender is not an employee and are present configurations to reply + $hrefReply = ''; + if (!$isEmployee && !isEmptyString($this->config->item(MessageLib::CFG_REDIRECT_VIEW_MESSAGE_URL))) + { + $hrefReply = $this->config->item(MessageLib::CFG_MESSAGE_SERVER). + $this->config->item(MessageLib::CFG_REDIRECT_VIEW_MESSAGE_URL). + $token; + } + + return array ( + 'sender' => $sender, + 'message' => $message, + 'hrefReply' => $hrefReply + ); + } + + /** + * Prepares data for the view system/messages/htmlWriteReply using a token that identifies a single message + */ + public function prepareHtmlWriteReply($token) + { + if (isEmptyString($token)) show_error('The given token is not valid'); + + // Retrieves message using the given token + $messageResult = $this->MessageTokenModel->getMessageByToken($token); + if (isError($messageResult)) show_error(getError($messageResult)); + if (!hasData($messageResult)) show_error('No message found with the given token'); + + $message = getData($messageResult)[0]; // Found message data + + // Retrieves message sender information + $senderResult = $this->MessageTokenModel->getSenderData($message->sender_id); + if (isError($senderResult)) show_error(getError($senderResult)); + if (!hasData($senderResult)) show_error('No sender information found'); + + $sender = getData($senderResult)[0]; // Found sender data + + $replySubject = self::REPLY_SUBJECT_PREFIX.$message->subject; + $replyBody = $this->_getReplyBody($message->body, $sender->vorname, $sender->nachname, $message->sent); + + return array ( + 'receiver' => $sender->vorname.' '.$sender->nachname, // yep! the sender of the sent message is the receiver of the reply message + 'subject' => $replySubject, + 'body' => $replyBody, + 'receiver_id' => $message->sender_id, + 'relationmessage_id' => $message->message_id, + 'token' => $token + ); + } + + /** + * Prepares data for the view system/messages/htmlWriteTemplate using person ids as main parameter + * Wrap method to _prepareHtmlWriteTemplate + */ + public function prepareHtmlWriteTemplatePersons($persons, $message_id = null, $recipient_id = null) + { + // Retrieves persons information + $msgVarsData = $this->MessageModel->getMsgVarsDataByPersonId($persons); + + return $this->_prepareHtmlWriteTemplate($msgVarsData, $message_id, $recipient_id); + } + + /** + * Prepares data for the view system/messages/htmlWriteTemplate using prestudent ids as main parameter + * Wrap method to _prepareHtmlWriteTemplate + */ + public function prepareHtmlWriteTemplatePrestudents($prestudents, $message_id = null, $recipient_id = null) + { + // Retrieves prestudents information + $msgVarsData = $this->MessageModel->getMsgVarsDataByPrestudentId($prestudents); + + return $this->_prepareHtmlWriteTemplate($msgVarsData, $message_id, $recipient_id); + } + + /** + * Sends a new message or a reply to a message (if $relationmessage_id is given) + * using the template stored in the subject and body + */ + public function sendImplicitTemplate($type, $recipients_ids, $subject, $body, $relationmessage_id = null) + { + // Retrieves the sender id + $sender_id = getAuthPersonId(); + if (!is_numeric($sender_id)) show_error('The current logged user person_id is not defined'); + + $msgVarsData = error('No persons nor prestudents were provided'); + // Retrieves message vars data for the given user/s + if ($type == self::TYPE_PERSONS) // if persons were given + { + $msgVarsData = $this->MessageModel->getMsgVarsDataByPersonId($recipients_ids); + } + elseif ($type == self::TYPE_PRESTUDENTS) // otherwise prestudents were given + { + $msgVarsData = $this->MessageModel->getMsgVarsDataByPrestudentId($recipients_ids); + + // Retrieve organisation unit for the recipients + $organisationUnitsResult = $this->PrestudentModel->getOrganisationunits($recipients_ids); + if (isError($organisationUnitsResult)) return $organisationUnitsResult; + if (hasData($organisationUnitsResult)) $senderOUArray = getData($organisationUnitsResult); + } + if (isError($msgVarsData)) show_error(getError($msgVarsData)); + if (!hasData($msgVarsData)) show_error('No recipients were given'); + + $senderOU = null; // sender organisation unit only for presetudents + $receiversCounter = 0; // a counter + + // Looping on receivers data + foreach (getData($msgVarsData) as $receiver) + { + $msgVarsDataArray = $this->_lowerReplaceSpaceArrayKeys((array)$receiver); // replaces array keys + $parsedSubject = parseText($subject, $msgVarsDataArray); + $parsedBody = parseText($body, $msgVarsDataArray); + + // If exist an organisation unit for this prestudent and it is valid + if (isset($senderOUArray[$receiversCounter]) + && isset($senderOUArray[$receiversCounter]->oe_kurzbz) + && !isEmptyString($senderOUArray[$receiversCounter]->oe_kurzbz)) + { + $senderOU = $senderOUArray[$receiversCounter]->oe_kurzbz; + } + else + { + $senderOU = null; + } + + $message = $this->messagelib->sendMessageUser( + $msgVarsDataArray['person_id'], // receiverPersonId + $parsedSubject, // subject + $parsedBody, // body + $sender_id, // sender_id + $senderOU, // senderOU + $relationmessage_id, // relationmessage_id + MSG_PRIORITY_NORMAL // priority + ); + + if (isError($message)) return $message; + if (!hasData($message)) return error('No messages were saved in database'); + + // Write log entry only if persons were given + if ($type == self::TYPE_PERSONS) + { + $personLog = $this->_personLog($sender_id, $msgVarsDataArray['person_id'], getData($message)[0]); + if (isError($personLog)) return $personLog; + } + + $receiversCounter++; // increment the counter + } + + return success('Messages sent successfully'); + } + + /** + * Sends a new message using the given template and information present in parameter prestudents + * Extra variables can be added using parameter $msgVars + */ + public function sendExplicitTemplate($prestudents, $oe_kurzbz, $vorlage_kurzbz, $msgVars) + { + // Retrieves the sender id + $sender_id = getAuthPersonId(); + if (!is_numeric($sender_id)) show_error('The current logged user person_id is not defined'); + + // Retrieves message vars data for the given user/s + $msgVarsData = $this->MessageModel->getMsgVarsDataByPrestudentId($prestudents); + if (isError($msgVarsData)) show_error(getError($msgVarsData)); + if (!hasData($msgVarsData)) show_error('No recipients were given'); + + $prestudentsData = $this->PrestudentModel->getOrganisationunits($prestudents); + + // Adds the organisation unit to each prestudent + if (isEmptyString($oe_kurzbz) && hasData($msgVarsData) && hasData($prestudentsData)) + { + $this->CLMessagesModel->_addOeToPrestudents($msgVarsData, $prestudentsData); + } + + foreach (getData($msgVarsData) as $receiver) + { + $msgVarsDataArray = $this->_lowerReplaceSpaceArrayKeys((array)$receiver); // replaces array keys + + // Additional message variables + if (is_array($msgVars)) $msgVarsDataArray = array_merge($msgVarsDataArray, $msgVars); + + $message = $this->messagelib->sendMessageUserTemplate( + $msgVarsDataArray['person_id'], // receiversPersonId + $vorlage_kurzbz, // vorlage + $msgVarsDataArray, // parseData + null, // orgform + $sender_id, // sender_id + $oe_kurzbz // senderOU + ); + + if (isError($message)) return $message; + + // Write log entry + $personLog = $this->_personLog($sender_id, $msgVarsDataArray['person_id'], getData($message)[0]); + if (isError($personLog)) return $personLog; + } + + return success('Messages sent successfully'); + } + + /** + * Send a reply to a single recipient for a message identified by a token (no templates are used) + * NOTE: this method could be also called from not authenticated controllers + */ + public function sendReply($receiver_id, $subject, $body, $relationmessage_id, $token) + { + // Retrieves message sender information + $senderResult = $this->MessageTokenModel->getSenderData($receiver_id); + if (isError($senderResult)) show_error(getError($senderResult)); + if (!hasData($senderResult)) show_error('No sender information found'); + + $sender = getData($senderResult)[0]; // Found sender data + + $messageResult = $this->MessageTokenModel->getMessageByToken($token); + if (isError($messageResult)) show_error(getError($messageResult)); + // Security check! It is possible to reply only to a received message!! + if (!hasData($messageResult) || $relationmessage_id != getData($messageResult)[0]->message_id) + { + show_error('An error occurred while sending your message, please contact the site administrator'); + } + + // If the user is logged then use its person id as sender id, otherwise get the receiver id of the previous message + $sender_id = isLogged() ? getAuthPersonId() : getData($messageResult)[0]->receiver_id; + if (!is_numeric($sender_id)) return error('The sender id is not valid'); + + $message = $this->messagelib->sendMessageUser( + $receiver_id, // receiverPersonId + $subject, // subject + $body, // body + $sender_id, // sender_id, the receiver of the previous message is the sender of the current one + null, // senderOU + $relationmessage_id, // relationmessage_id + MSG_PRIORITY_NORMAL // priority + ); + + if (isError($message)) return $message; + if (!hasData($message)) return error('No messages were saved in database'); + + // Write log entry + // NOTE: $receiver_id and $sender_id are switched!!! Currently this is a workaround + $personLog = $this->_personLog($receiver_id, $sender_id, getData($message)[0]); + if (isError($personLog)) return $personLog; + + return success('Messages sent successfully'); + } + + /** + * Send a message to an organisation unit + */ + public function sendToOrganisationUnit($receiverOU, $subject, $body) + { + if (isEmptyString($receiverOU)) return error('Not a valid organisation unit'); + if (isEmptyString($subject)) return error('Subject is an empty string'); + if (isEmptyString($body)) return error('Body is an empty string'); + + $sender_id = getAuthPersonId(); + if (!is_numeric($sender_id)) return error('The current logged user person_id is not defined'); + + $message = $this->messagelib->sendMessageOU( + $receiverOU, // receiverPersonId + $subject, // subject + $body, // body + $sender_id // sender_id + ); + + if (isError($message)) return $message; + if (!hasData($message)) return error('No messages were saved in database'); + + // Write log entry + $personLog = $this->_personLog($sender_id, $this->config->item(MessageLib::CFG_SYSTEM_PERSON_ID), getData($message)[0], $receiverOU); + if (isError($personLog)) return $personLog; + + return success('Messages sent successfully'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods called by controller system/messages/Messages + + /** + * Returns an object that represent a template store in database + * If no templates are found with the given parameter or the given parameter is an empty string, + * then an error is returned + */ + public function getVorlage($vorlage_kurzbz) + { + $getVorlage = error('The given vorlage_kurzbz is not valid'); + + if (!isEmptyString($vorlage_kurzbz)) + { + $this->load->model('system/Vorlagestudiengang_model', 'VorlagestudiengangModel'); + $this->VorlagestudiengangModel->addOrder('version','DESC'); + + $getVorlage = $this->VorlagestudiengangModel->loadWhere(array('vorlage_kurzbz' => $vorlage_kurzbz)); + } + + return $getVorlage; + } + + /** + * Parse the given given text using data from the given user + * Use the CI parser which performs simple text substitution for pseudo-variable + */ + public function parseMessageTextPerson($person_id, $text) + { + $parseMessageText = error('The given person_id is not a valid number'); + + if (is_numeric($person_id)) $parseMessageText = $this->MessageModel->getMsgVarsDataByPersonId($person_id); + + if (hasData($parseMessageText)) + { + $parseMessageText = success( + parseText( + $text, + $this->_lowerReplaceSpaceArrayKeys((array)getData($parseMessageText)[0]) + ) + ); + } + + return $parseMessageText; + } + + /** + * Parse the given given text using data from the given user + * Use the CI parser which performs simple text substitution for pseudo-variable + */ + public function parseMessageTextPrestudent($prestudent_id, $text) + { + $parseMessageText = error('The given prestudent_id is not a valid number'); + + if (is_numeric($prestudent_id)) $parseMessageText = $this->MessageModel->getMsgVarsDataByPrestudentId($prestudent_id); + + if (hasData($parseMessageText)) + { + $parseMessageText = success( + parseText( + $text, + $this->_lowerReplaceSpaceArrayKeys((array)getData($parseMessageText)[0]) + ) + ); + } + + return $parseMessageText; + } + + /** + * Outputs message data for a message (identified my msg id and receiver id) in JSON format + */ + public function getMessageFromIds($message_id, $receiver_id) + { + $getMessageFromIds = error('The given message id or receiver id are not valid'); + + if (is_numeric($message_id) && is_numeric($receiver_id)) + { + $getMessageFromIds = $this->messagelib->getMessage($message_id, $receiver_id); + } + + if (isError($getMessageFromIds) || !hasData($getMessageFromIds)) + { + return array(); + } + else + { + return array(getData($getMessageFromIds)[0]); + } + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Replaces data array keys to a lowercase string with underscores instead of spaces + */ + private function _lowerReplaceSpaceArrayKeys($data) { $tmpData = array(); - // Replaces data array keys to a lowercase without spaces string foreach ($data as $key => $val) { $tmpData[str_replace(' ', '_', strtolower($key))] = $val; @@ -176,9 +657,9 @@ class Messages_model extends CI_Model } /** - * + * Add organisation unit to an array of prestudents (objects) */ - public function addOeToPrestudents(&$msgVarsData, $prestudentsData) + private function _addOeToPrestudents(&$msgVarsData, $prestudentsData) { for ($i = 0; $i < count(getData($msgVarsData)); $i++) { @@ -192,4 +673,171 @@ class Messages_model extends CI_Model } } } + + /** + * Perform a person log after a message is sent + */ + private function _personLog($sender_id, $receiver_id, $message_id, $receiverOU = null) + { + // In case the message is accessed via ViewMessage controller -> no authentication + // If no authentication is performed then use a hard coded uid + $loggedUserUID = isLogged() ? getAuthUID() : self::NO_AUTH_UID; + + $message = 'Message sent from person '.$sender_id.' to '.$receiver_id.', message id: '.$message_id; + if (!isEmptyString($receiverOU)) $message .= ', receiverOU: '.$receiverOU; + + return $this->personloglib->log( + $receiver_id, + 'Action', + array( + 'name' => 'Message sent', + 'message' => $message, + 'success' => 'true' + ), + 'kommunikation', + 'core', + null, + $loggedUserUID + ); + } + + /** + * Quotes the previous message body + */ + private function _getReplyBody($body, $receiverName, $receiverSurname, $sentDate) + { + return sprintf( + self::REPLY_BODY_FORMAT, + date_format(date_create($sentDate), 'd.m.Y H:i'), $receiverName, $receiverSurname, $body + ); + } + + /** + * Prepares data for the view system/messages/htmlWriteTemplate using the given parameters + */ + private function _prepareHtmlWriteTemplate($info, $message_id, $recipient_id) + { + // Checks that info parameter is valid + if (isError($info)) show_error(getError($info)); + if (!hasData($info)) show_error('No recipients were given'); + + // If the message id and recipient id are given, then both they must be valid numbers + if ((is_numeric($message_id) && !is_numeric($recipient_id)) + || (!is_numeric($message_id) && is_numeric($recipient_id))) + { + show_error('If given, message id and recipient id both must be valid numbers'); + } + + // --------------------------------------------------------------------------------------- + // Retrieves the recipients information and builds: + // - recipientsArray: an array that contains objects with id (person_id) and description (Vorname + Nachname) of recipient + // - recipientsList: a string that contains all the recipients descriptions (Vorname + Nachname) separated by ; + // - persons: a string that contains HTML input hidden with alla the receivers id (person_id) + $recipientsArray = array(); + $recipientsList = ''; + $recipients_ids = ''; + + foreach (getData($info) as $receiver) + { + $id = 0; + $recipient = new stdClass(); + $recipient->description = $receiver->Vorname.' '.$receiver->Nachname; + $recipientsList .= $receiver->Vorname.' '.$receiver->Nachname.'; '; + + // If it is a prestudent then + if (isset($receiver->prestudent_id) && is_numeric($receiver->prestudent_id)) + { + $recipient->id = $receiver->prestudent_id; + $id = $receiver->prestudent_id; + } + else // otherwise it is a person + { + $recipient->id = $receiver->person_id; + $id = $receiver->person_id; + } + + $recipients_ids .= ''."\n"; + + $recipientsArray[] = $recipient; + } + + // --------------------------------------------------------------------------------------- + // Retrieves the message to reply to, if it is specified by parameters $message_id and $recipient_id + $replySubject = ''; // message reply subject + $replyBody = ''; // message reply body + $relationmessage = ''; // input hidden that contains the message id to be replied to + // If both are given and they are valid + if (is_numeric($message_id) && is_numeric($recipient_id)) + { + // Retrieves a received message from tbl_msg_recipient + $messageResult = $this->messagelib->getMessage($message_id, $recipient_id); + if (isError($messageResult)) show_error(getError($messageResult)); + if (!hasData($messageResult)) show_error('The selected message does not exist'); + + $message = getData($messageResult)[0]; + + $replySubject = self::REPLY_SUBJECT_PREFIX.$message->subject; + $replyBody = $this->_getReplyBody($message->body, $receiver->Vorname, $receiver->Nachname, $message->sent); + $relationmessage = ''; + } + + // --------------------------------------------------------------------------------------- + // Retrieves message vars from database view vw_msg_vars/vw_msg_vars_person + $variablesResult = null; + $type = ''; + + // If data contains a prestudent id + // NOTE: + // - info is checked at the beginning of this method so it is safe to use getData($info)[0] + // - the provided data inside info are all persons or all prestudents, so it is safe to check only the first one + if (isset(getData($info)[0]->prestudent_id) && is_numeric(getData($info)[0]->prestudent_id)) + { + $variablesResult = $this->messagelib->getMessageVarsPrestudent(); + $type = ''; + } + else + { + $variablesResult = $this->messagelib->getMessageVarsPerson(); + $type = ''; + } + if (isError($variablesResult)) show_error(getError($variablesResult)); + + // Then builds an array that contains objects with id (person_id) and description (Vorname + Nachname) of recipient + $variables = array(); + foreach (getData($variablesResult) as $id => $description) + { + $tmpVar = new stdClass(); + $tmpVar->id = $id; + $tmpVar->description = $description; + + $variables[] = $tmpVar; + } + + // --------------------------------------------------------------------------------------- + // Retrieves the sender id + $sender_id = getAuthPersonId(); + if (!is_numeric($sender_id)) show_error('The current logged user person_id is not defined'); + + // --------------------------------------------------------------------------------------- + // Organisation units and a boolean (true if the sender is administrator) are used to get the templates + $organisationUnits = $this->messagelib->getOeKurzbz($sender_id); + if (isError($organisationUnits)) show_error(getError($organisationUnits)); + $senderIsAdmin = $this->BenutzerrolleModel->isAdminByPersonId($sender_id); + if (isError($senderIsAdmin)) show_error(getError($senderIsAdmin)); + + // --------------------------------------------------------------------------------------- + // Returns data as an array + return array ( + 'recipientsList' => $recipientsList, + 'subject' => $replySubject, + 'body' => $replyBody, + 'variables' => $variables, + 'organisationUnits' => getData($organisationUnits), + 'senderIsAdmin' => getData($senderIsAdmin), + 'recipientsArray' => $recipientsArray, + 'recipients_ids' => $recipients_ids, + 'relationmessage_id' => $relationmessage, + 'type' => $type + ); + } } diff --git a/application/models/accounting/Konto_model.php b/application/models/accounting/Konto_model.php index d76b2bd46..cbd7a6f2d 100644 --- a/application/models/accounting/Konto_model.php +++ b/application/models/accounting/Konto_model.php @@ -22,8 +22,7 @@ class Konto_model extends DB_Model $this->addJoin('wawi.tbl_konto_kostenstelle', 'konto_id'); $konten = $this->loadWhere(array('kostenstelle_id' => $kostenstelle_id)); - if ($konten->error) - return error($konten->retval); + if ($konten->error) return $konten; return $konten; } diff --git a/application/models/accounting/Vertrag_model.php b/application/models/accounting/Vertrag_model.php index cd4b466d6..8725cd98d 100644 --- a/application/models/accounting/Vertrag_model.php +++ b/application/models/accounting/Vertrag_model.php @@ -10,5 +10,324 @@ class Vertrag_model extends DB_Model parent::__construct(); $this->dbTable = 'lehre.tbl_vertrag'; $this->pk = 'vertrag_id'; + + $this->load->model('accounting/Vertragvertragsstatus_model', 'VertragvertragsstatusModel'); + $this->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel'); + $this->load->model('education/Projektbetreuer_model', 'ProjektbetreuerModel'); } + + /** + * Saves Vertrag for a Lehrauftrag and sets Vertragsstatus to 'bestellt'. + * Also updates vertrag_id in tbl_lehreinheitmitarbeiter or tbl_projektbetreuer. + * @param $person_id + * @param $lehrveranstaltung_id + * @param $lehreinheit_id + * @param $projektarbeit_id + * @param $betrag Monetary amount of that Lehreinheit / Projektbetreuung. + * @param $vertragsstunden Working hours of that Lehreinheit / Projektbetreuung. + * @param $studiensemester_kurzbz + * @param $vertragstyp_kurzbz + * @return array|null On success object. On failure null. + */ + public function save($person_id, $mitarbeiter_uid, $lehrveranstaltung_id, $lehreinheit_id, $projektarbeit_id = null, $vertragsstunden, $betrag, $studiensemester_kurzbz) + { + $person_id = (isset($person_id) && is_numeric($person_id)) + ? $person_id + : show_error('peron_id must be set and numeric.'); + $lehreinheit_id = (isset($lehreinheit_id) && is_numeric($lehreinheit_id)) + ? $lehreinheit_id + : show_error('lehreinheit_id must be set and numeric.'); + $lehrveranstaltung_id = (isset($lehrveranstaltung_id) && is_numeric($lehrveranstaltung_id)) + ? $lehrveranstaltung_id + : show_error('lehrveranstaltung_id must be set and numeric.'); + $projektarbeit_id = (isset($projektarbeit_id) && is_numeric($projektarbeit_id)) + ? $projektarbeit_id + : null; + $vertragsstunden = (isset($vertragsstunden) && is_numeric($vertragsstunden)) + ? $vertragsstunden + : 0; + $betrag = (isset($betrag) && is_numeric($betrag)) + ? $betrag + : 0; + $mitarbeiter_uid = (isset($mitarbeiter_uid) && is_string($mitarbeiter_uid)) + ? $mitarbeiter_uid + : show_error('mitarbeiter_uid must be set and a string value.');; + + $vertragstyp_kurzbz = (is_null($projektarbeit_id)) ? 'Lehrauftrag' : 'Betreuung'; + + // First check if Vertrag already exists for that Lehrauftrag or for that Projektbetreuerauftrag + if ($vertragstyp_kurzbz == 'Lehrauftrag') + { + if ($this->LehreinheitmitarbeiterModel->hasVertrag($mitarbeiter_uid, $lehreinheit_id)) + { + return error('Lehrauftrag existiert bereits'); // Exit if Lehrauftrag already has Vertrag + } + } + elseif ($vertragstyp_kurzbz == 'Betreuung') + { + if ($this->ProjektbetreuerModel->hasVertrag($person_id, $projektarbeit_id)) + { + return error('Lehrauftrag existiert bereits'); // Exit if Projektbetreuung already has Vertrag + } + } + + // If Vertrag does not exist, create now + // Vertragsbezeichnung + $bezeichnung = $this->_writeVertragsbezeichung($lehrveranstaltung_id, $studiensemester_kurzbz); + + // Start DB transaction + $this->db->trans_start(false); + + // Insert Vertragsdata + $result = $this->insert( + array( + 'person_id' => $person_id, + 'lehrveranstaltung_id' => $lehrveranstaltung_id, + 'vertragstyp_kurzbz' => $vertragstyp_kurzbz, + 'bezeichnung' => $bezeichnung, + 'betrag' => $betrag, + 'insertamum' => 'NOW()', + 'insertvon' => getAuthUID(), + 'vertragsdatum' => 'NOW()', + 'vertragsstunden' => $vertragsstunden, + 'vertragsstunden_studiensemester_kurzbz' => $studiensemester_kurzbz + ) + ); + + // Retrieve primary key + $vertrag_id = $result->retval; + + // If Vertrag was created successfully, update vertrag_id + if (isSuccess($result)) + { + // if Lehrtätigkeit, update vertrag_id in tbl_lehreinheitmitarbeiter + if ($vertragstyp_kurzbz == 'Lehrauftrag') + { + $this->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel'); + $result = $this->LehreinheitmitarbeiterModel->update( + array( + 'lehreinheit_id' => $lehreinheit_id, + 'mitarbeiter_uid' =>$mitarbeiter_uid + ), + array( + 'vertrag_id' => $vertrag_id + ) + ); + } + // if (Projekt-)Betreuung, update vertrag_id in tbl_projektbetreuer + elseif ($vertragstyp_kurzbz == 'Betreuung') + { + $this->load->model('education/Projektbetreuer_model', 'ProjektbetreuerModel'); + $result = $this->ProjektbetreuerModel->update( + array( + 'person_id' => $person_id, + 'projektarbeit_id' => $projektarbeit_id + ), + array( + 'vertrag_id' => $vertrag_id + ) + ); + } + } + + // If updating vertrag_id was successfully, set Status to 'bestellt' + if (isSuccess($result)) + { + $result = $this->VertragvertragsstatusModel->setStatus($vertrag_id, $mitarbeiter_uid, 'bestellt'); + } + + // Transaction complete! + $this->db->trans_complete(); + + // Check if everything went ok during the transaction + if ($this->db->trans_status() === false || isError($result)) + { + $this->db->trans_rollback(); + return error($result->msg, EXIT_ERROR); + } + else + { + $this->db->trans_commit(); + return success($vertrag_id); + } + } + + /** + * Updates Vertrag and, if resets vertragsstatus as follows: + * - if vertragsstatus 'erteilt': delete status 'erteilt' and update date of status 'bestellt' + * - if vertragsstatus 'bestellt': update date of status 'bestellt' + * @param $vertrag_obj Object with vertrag properties vertrag_id, vertragsstunden, betrag. + * @param $mitarbeiter_uid + */ + public function updateVertrag($vertrag_id, $vertragsstunden, $betrag, $mitarbeiter_uid) + { + $vertrag_id = (isset($vertrag_id) && is_numeric($vertrag_id)) + ? $vertrag_id + : show_error('vertrag_id must be set and numeric.'); + $vertragsstunden = (isset($vertragsstunden) && is_numeric($vertragsstunden)) + ? $vertragsstunden + : 0; + $betrag = (isset($betrag) && is_numeric($betrag)) + ? $betrag + : 0; + $mitarbeiter_uid = (isset($mitarbeiter_uid) && is_string($mitarbeiter_uid)) + ? $mitarbeiter_uid + : show_error('mitarbeiter_uid must be set and a string value.'); + + // Start DB transaction + $this->db->trans_start(false); + + // Update contract + $result = $this->update( + $vertrag_id, + array( + 'vertragsstunden' => $vertragsstunden, + 'betrag' => $betrag, + 'updateamum' => $this->escape('NOW()'), + 'updatevon' => getAuthUID() + ) + ); + + // If last vertragsstatus is 'erteilt', delete the status + if (isSuccess($result)) + { + $result = $this->VertragvertragsstatusModel->getLastStatus($vertrag_id, $mitarbeiter_uid); + + $lastStatus = getData($result)[0]->vertragsstatus_kurzbz; + + if ($lastStatus == 'erteilt') + { + $result = $this->VertragvertragsstatusModel->deleteStatus($vertrag_id, 'erteilt'); + } + } + + // Update date of status 'bestellt' + if (isSuccess($result)) + { + $result = $this->VertragvertragsstatusModel->updateStatus($vertrag_id, 'bestellt'); + } + + // Transaction complete! + $this->db->trans_complete(); + + // Check if everything went ok during the transaction + if ($this->db->trans_status() === false || isError($result)) + { + $this->db->trans_rollback(); + return error($result->msg, EXIT_ERROR); + } + else + { + $this->db->trans_commit(); + return success('Contract successfully updated.'); + } + } + + /** + * Gets Lehreinheit ID corresponding to the contract. + * @param $vertrag_id + * @return array + */ + public function getLehreinheitID($vertrag_id) + { + $vertragstyp_kurzbz = null; + + $this->addSelect('vertragstyp_kurzbz'); + if ($result = getData($this->load($vertrag_id))) + { + $vertragstyp_kurzbz = $result[0]->vertragstyp_kurzbz; + } + else + { + return error('Fehler beim Laden des Vertrags.'); + } + + if ($vertragstyp_kurzbz == 'Lehrauftrag') + { + $this->LehreinheitmitarbeiterModel->addSelect('lehreinheit_id'); + if ($result = $this->LehreinheitmitarbeiterModel->loadWhere(array('vertrag_id' => $vertrag_id))) + { + return success($result->retval); + } + else + { + return error('Fehler beim Ermitteln der Lehreinheit ID'); + } + + } + elseif ($vertragstyp_kurzbz == 'Betreuung') + { + $this->addSelect('lehreinheit_id'); + $this->addJoin('lehre.tbl_projektbetreuer', 'vertrag_id'); + $this->addJoin('lehre.tbl_projektarbeit', 'projektarbeit_id'); + if ($result = $this->loadWhere(array('vertrag_id' => $vertrag_id))) + { + return success($result->retval); + } + else + { + return error('Fehler beim Ermitteln der Lehreinheit ID'); + } + } + } + + /** + * Gets (table) data of lehreinheit_id corresponding to the contract. + * @param integer $vertrag_id + * @param string $select To restrict fields, pass select string. e.g. 'lehrveranstaltung_id'. + * @return array + */ + public function getLehreinheitData($vertrag_id, $select = '*') + { + if ($result = getData($this->getLehreinheitID($vertrag_id))) + { + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + $this->LehreinheitModel->addSelect($select); + + if($result = $this->LehreinheitModel->load($result[0]->lehreinheit_id)) + { + return success($result->retval); + } + else + { + return error('Fehler beim Laden der Lehreinheit'); + } + } + else + { + return error('Fehler beim Ermitteln der Lehreinheit ID'); + } + } + + // ----------------------------------------------------------------------------------------------------------------- + // Private methods + + /** + * Generate contract description. + * Example: WS2017-BEE3-LIA-LAB + * @param $lehrveranstaltung_id + * @param $studiensemester_kurzbz Studiensemester of Lehrauftrag (= when the lector will teach the lehrveranstaltung) + * @return string Returns e.g. WS2017-BBE5-GAP-LAB + */ + private function _writeVertragsbezeichung($lehrveranstaltung_id, $studiensemester_kurzbz) + { + $bezeichnung = ''; + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->LehrveranstaltungModel->addSelect('tbl_lehrveranstaltung.semester, tbl_lehrveranstaltung.kurzbz AS "lv_kurzbz", lehrform_kurzbz, public.tbl_studiengang.typ, public.tbl_studiengang.kurzbz'); + $this->LehrveranstaltungModel->addJoin('lehre.tbl_studienplan_lehrveranstaltung', 'lehrveranstaltung_id'); + $this->LehrveranstaltungModel->addJoin('lehre.tbl_studienplan', 'studienplan_id'); + $this->LehrveranstaltungModel->addJoin('lehre.tbl_studienordnung', 'studienordnung_id'); + $this->LehrveranstaltungModel->addJoin('public.tbl_studiengang', 'public.tbl_studiengang.studiengang_kz = lehre.tbl_studienordnung.studiengang_kz'); + $result = $this->LehrveranstaltungModel->load($lehrveranstaltung_id); + + if (hasData($result)) + { + $bezeichnung = $studiensemester_kurzbz. '-'; + $bezeichnung.= strtoupper($result->retval[0]->typ. $result->retval[0]->kurzbz). $result->retval[0]->semester. '-'; + $bezeichnung.= $result->retval[0]->lv_kurzbz. '-'; + $bezeichnung.= $result->retval[0]->lehrform_kurzbz; + } + + return $bezeichnung; + } } diff --git a/application/models/accounting/Vertragvertragsstatus_model.php b/application/models/accounting/Vertragvertragsstatus_model.php new file mode 100644 index 000000000..609394321 --- /dev/null +++ b/application/models/accounting/Vertragvertragsstatus_model.php @@ -0,0 +1,193 @@ +dbTable = 'lehre.tbl_vertrag_vertragsstatus'; + $this->pk = array('vertragsstatus_kurzbz', 'vertrag_id'); + $this->hasSequence = false; + } + + /** + * Check if Vertrag has the given Vertragsstatus. + * @param integer $vertrag_id + * @param string $mitarbeiter_uid + * @param string $vertragsstatus_kurzbz + * @return array + */ + public function hasStatus($vertrag_id, $mitarbeiter_uid, $vertragsstatus_kurzbz) + { + $this->addSelect('1'); + $this->addLimit(1); + + return $this->loadWhere(array( + 'vertrag_id' => $vertrag_id, + 'uid' => $mitarbeiter_uid, + 'vertragsstatus_kurzbz' => $vertragsstatus_kurzbz + )); + } + + /** + * Get the latest Vertragsstatus for the given Vertrag and Mitarbeiter + * @param integer $vertrag_id + * @param string $mitarbeiter_uid + * @return array + */ + public function getLastStatus($vertrag_id, $mitarbeiter_uid) + { + $this->addSelect('vertragsstatus_kurzbz'); + $this->addOrder('datum', 'DESC'); + $this->addLimit(1); + return $this->loadWhere( + array( + 'vertrag_id' => $vertrag_id, + 'uid' => $mitarbeiter_uid + ) + ); + } + + /** + * Set Vertragsstatus for the given Vertrag and Mitarbeiter. + * @param integer $vertrag_id + * @param string $mitarbeiter_uid + * @param string $vertragsstatus_kurzbz + * @return object On success, return success object. + * If status already exists or earlier status is missing, return error object. + */ + public function setStatus($vertrag_id, $mitarbeiter_uid, $vertragsstatus_kurzbz){ + + // Check if vertrag has already this status + $result = $this->hasStatus($vertrag_id, $mitarbeiter_uid, $vertragsstatus_kurzbz); + + // If status is already set, return error message + if (hasData($result)) + { + return error('Fehler: Status bereits vorhanden.'); + } + + // If new status should be 'akzeptiert', the latest status has to be 'erteilt' + if ($vertragsstatus_kurzbz == 'akzeptiert') + { + $result = $this->getLastStatus($vertrag_id, $mitarbeiter_uid); + $last_status = getData($result)[0]->vertragsstatus_kurzbz; + + // If latest status is not 'erteilt', return error message + if ($last_status != 'erteilt') + { + return error('Fehler: Vor Status \'angenommen\' muss erst Status \'erteilt\' gesetzt sein.'); + } + } + + // Set new status if passed all checks + return $this->insert( + array( + 'vertrag_id' => $vertrag_id, + 'vertragsstatus_kurzbz' => $vertragsstatus_kurzbz, + 'uid' => $mitarbeiter_uid, + 'datum' => $this->escape('NOW()'), + 'insertvon' => getAuthUID(), + 'insertamum' => $this->escape('NOW()') + ) + ); + } + + /** + * Updates the date of the given vertragsstatus. + * @param $vertrag_id + * @param $vertragsstatus_kurzbz + * @return array + */ + public function updateStatus($vertrag_id, $vertragsstatus_kurzbz) + { + $user = getAuthUID(); + return $this->update( + array( + 'vertrag_id' => $vertrag_id, + 'vertragsstatus_kurzbz' => $vertragsstatus_kurzbz + ), + array( + 'datum' => $this->escape('NOW()'), + 'updateamum' => $this->escape('NOW()'), + 'updatevon' => $user, + ) + ); + } + + /** + * Deletes the given vertragsstatus of the contract. + * @param $vertrag_id + * @param $vertragsstatus_kurbz + * @return array + */ + public function deleteStatus($vertrag_id, $vertragsstatus_kurzbz) + { + return $this->delete( + array( + 'vertrag_id' => $vertrag_id, + 'vertragsstatus_kurzbz' => $vertragsstatus_kurzbz + ) + ); + } + + /** + * Get all contracts, where the status had been set to 'bestellt' on given date + * @param string $string_date e.g. '01.11.2019' or special Date/Time inputs like 'YESTERDAY', 'TODAY', 'NOW' + * @param bool $further_processed If true, ALL ordered contracts of that day are retrieved, even if they were + * were ALSO approved/accepted/cancelled (further processed) on that same day. + * @return array + */ + public function getOrdered_fromDate($string_date = 'TODAY', $further_processed = false) + { + $condition = ' + vertragsstatus_kurzbz = \'bestellt\' AND + (datum)::date = date \''. $string_date .'\' + '; + + if (!$further_processed) + { + $condition .= ' + AND + vertrag_id NOT IN ( + SELECT vertrag_id + FROM lehre.tbl_vertrag_vertragsstatus + WHERE vertragsstatus_kurzbz IN (\'erteilt\', \'akzeptiert\', \'storno\') + ) + '; + } + + return $this->loadWhere($condition); + } + + /** + * Get all contracts, where the status had been set to 'erteilt' on given date + * @param string $string_date e.g. '01.11.2019' or special Date/Time inputs like 'YESTERDAY', 'TODAY', 'NOW' + * @param bool $further_processed If true, ALL contracts approved on that day are retrieved, even if they were + * were ALSO accepted/cancelled (further processed) on that same day. + * @return array + */ + public function getApproved_fromDate($string_date = 'TODAY', $further_processed = false) + { + $condition = ' + vertragsstatus_kurzbz = \'erteilt\' AND + (datum)::date = date \''. $string_date .'\' + '; + + if (!$further_processed) + { + $condition .= ' + AND + vertrag_id NOT IN ( + SELECT vertrag_id + FROM lehre.tbl_vertrag_vertragsstatus + WHERE vertragsstatus_kurzbz IN (\'akzeptiert\', \'storno\') + ) + '; + } + + return $this->loadWhere($condition); + } +} diff --git a/application/models/codex/Bisiozweck_model.php b/application/models/codex/Bisiozweck_model.php new file mode 100644 index 000000000..b456f412d --- /dev/null +++ b/application/models/codex/Bisiozweck_model.php @@ -0,0 +1,15 @@ +dbTable = 'bis.tbl_bisio_zweck'; + $this->pk = array('bisio_id', 'zweck_code'); + $this->hasSequence = false; + } +} diff --git a/application/models/codex/Bisverwendung_model.php b/application/models/codex/Bisverwendung_model.php index fa2cf84d0..707e8af36 100644 --- a/application/models/codex/Bisverwendung_model.php +++ b/application/models/codex/Bisverwendung_model.php @@ -11,4 +11,34 @@ class Bisverwendung_model extends DB_Model $this->dbTable = 'bis.tbl_bisverwendung'; $this->pk = 'bisverwendung_id'; } + + /** + * Get latest (active) Verwendung of the user. + * @param string $uid + * @param bool $active If false, returns latest Verwendung no matter if it is still actual. + * @return array + */ + public function getLast($uid, $active = true) + { + $this->addLimit(1); + + if ($active) + { + $condition = ' + mitarbeiter_uid = '. $this->escape($uid). ' + AND ( beginn <= NOW() OR beginn IS NULL ) + AND ( ende >= NOW() OR ende IS NULL ) + ORDER BY ende DESC NULLS FIRST, beginn DESC NULLS LAST + '; + } + else + { + $condition = ' + mitarbeiter_uid = '. $this->escape($uid). ' + ORDER BY ende DESC NULLS FIRST, beginn DESC NULLS LAST + '; + } + + return $this->loadWhere($condition); + } } diff --git a/application/models/crm/Akte_model.php b/application/models/crm/Akte_model.php index b30e175c3..fe9db5330 100644 --- a/application/models/crm/Akte_model.php +++ b/application/models/crm/Akte_model.php @@ -186,8 +186,7 @@ class Akte_model extends DB_Model $dokumente = $this->loadWhere($where); - if($dokumente->error) - return error($dokumente->retval); + if($dokumente->error) return $dokumente; return success($dokumente->retval); } diff --git a/application/models/crm/Prestudent_model.php b/application/models/crm/Prestudent_model.php index 4a9b23ec9..b40897d82 100644 --- a/application/models/crm/Prestudent_model.php +++ b/application/models/crm/Prestudent_model.php @@ -10,6 +10,8 @@ class Prestudent_model extends DB_Model parent::__construct(); $this->dbTable = 'public.tbl_prestudent'; $this->pk = 'prestudent_id'; + + $this->load->model('crm/prestudentstatus_model', 'PrestudentstatusModel'); } /** @@ -208,20 +210,19 @@ class Prestudent_model extends DB_Model return error('prestudent could not be loaded'); //Prestudentstatus - $this->load->model('crm/prestudentstatus_model', 'PrestudentstatusModel'); $lastStatus = $this->PrestudentstatusModel->getLastStatus($prestudent_id); if ($lastStatus->error) { - return error($lastStatus->retval); + return $lastStatus; } if (count($lastStatus->retval) > 0) { - // get Studiengangname from Studienlan and -ordnung + //get Studiengangname from Studienplan and -ordnung $studienordnung = $this->PrestudentstatusModel->getStudienordnungFromPrestudent($prestudent_id); if ($studienordnung->error) - return error($studienordnung->retval); + return $studienordnung; if (count($studienordnung->retval) > 0) { @@ -238,7 +239,7 @@ class Prestudent_model extends DB_Model $language = $this->SpracheModel->load($lastStatus->retval[0]->sprache); if ($language->error) - return error($language->retval); + return $language; if (count($language->retval) > 0) $lastStatus->retval[0]->sprachedetails = $language->retval[0]; @@ -256,7 +257,7 @@ class Prestudent_model extends DB_Model ) ); if ($bewerbungstermin->error) - return error($bewerbungstermin->retval); + return $bewerbungstermin; if (count($bewerbungstermin->retval) > 0) { @@ -310,8 +311,6 @@ class Prestudent_model extends DB_Model if (!hasData($prestudents)) return $bewerbungen; - $this->load->model('crm/prestudentstatus_model', 'PrestudentstatusModel'); - foreach ($prestudents->retval as $prestudent) { $lastStatus = $this->PrestudentstatusModel->getLastStatus($prestudent->prestudent_id, $studiensemester_kurzbz); @@ -424,7 +423,6 @@ class Prestudent_model extends DB_Model if (!hasData($prestudent)) return false; - $this->load->model('prestudentstatus_model', 'PrestudentstatusModel'); $lastStatus = $this->PrestudentstatusModel->getLastStatus($prestudent_id, null, 'Interessent'); if (!hasData($lastStatus)) @@ -523,4 +521,35 @@ class Prestudent_model extends DB_Model } } } + + /** + * Get organisation units for all the prestudents of a person + */ + public function getOrganisationunitsByPersonId($person_id) + { + $query = 'SELECT o.oe_kurzbz, + o.bezeichnung, + (CASE + WHEN sg.typ = \'b\' THEN ps.prestudent_id + WHEN sg.typ = \'m\' THEN p.prestudent_id + ELSE NULL + END) AS prestudent_id + FROM public.tbl_prestudent p + JOIN public.tbl_studiengang sg USING(studiengang_kz) + JOIN public.tbl_organisationseinheit o USING(oe_kurzbz) + LEFT JOIN ( + SELECT prestudent_id + FROM public.tbl_prestudentstatus + WHERE status_kurzbz = \'Bewerber\' + ) ps USING(prestudent_id) + WHERE p.person_id = ? + GROUP BY o.oe_kurzbz, + o.bezeichnung, + sg.typ, + ps.prestudent_id, + p.prestudent_id + ORDER BY o.bezeichnung'; + + return $this->execQuery($query, array($person_id)); + } } diff --git a/application/models/crm/Prestudentstatus_model.php b/application/models/crm/Prestudentstatus_model.php index fb265edbe..d579037e1 100644 --- a/application/models/crm/Prestudentstatus_model.php +++ b/application/models/crm/Prestudentstatus_model.php @@ -19,14 +19,17 @@ class Prestudentstatus_model extends DB_Model public function getLastStatus($prestudent_id, $studiensemester_kurzbz = '', $status_kurzbz = '') { $query = 'SELECT tbl_prestudentstatus.*, - bezeichnung AS studienplan_bezeichnung, - tbl_studienplan.orgform_kurzbz as orgform, + tbl_studienplan.bezeichnung AS studienplan_bezeichnung, + tbl_studienplan.orgform_kurzbz AS orgform, sprache, + tbl_orgform.bezeichnung_mehrsprachig AS bezeichnung_orgform, tbl_status.bezeichnung_mehrsprachig, - tbl_status_grund.bezeichnung_mehrsprachig as bezeichnung_statusgrund - FROM public.tbl_prestudentstatus LEFT JOIN lehre.tbl_studienplan USING (studienplan_id) + tbl_status_grund.bezeichnung_mehrsprachig AS bezeichnung_statusgrund + FROM public.tbl_prestudentstatus + LEFT JOIN lehre.tbl_studienplan USING (studienplan_id) JOIN public.tbl_status USING (status_kurzbz) LEFT JOIN public.tbl_status_grund USING (statusgrund_id) + LEFT JOIN bis.tbl_orgform ON tbl_studienplan.orgform_kurzbz = bis.tbl_orgform.orgform_kurzbz WHERE tbl_status.status_kurzbz = tbl_prestudentstatus.status_kurzbz AND prestudent_id = ?'; @@ -120,7 +123,7 @@ class Prestudentstatus_model extends DB_Model if ($lastStatus->error) { - return error($lastStatus->retval); + return $lastStatus; } if (count($lastStatus->retval) > 0) @@ -155,7 +158,7 @@ class Prestudentstatus_model extends DB_Model if ($lastStatus->error) { - return error($lastStatus->retval); + return $lastStatus; } if (count($lastStatus->retval) > 0) diff --git a/application/models/crm/Reihungstest_model.php b/application/models/crm/Reihungstest_model.php index 6068c246f..ec1982ea6 100644 --- a/application/models/crm/Reihungstest_model.php +++ b/application/models/crm/Reihungstest_model.php @@ -349,6 +349,7 @@ class Reihungstest_model extends DB_Model ps.prestudent_id, rt.datum, rt.uhrzeit, + rt.reihungstest_id, tbl_studienplan.orgform_kurzbz, tbl_prestudentstatus.studienplan_id, tbl_prestudentstatus.ausbildungssemester, diff --git a/application/models/education/Lehreinheit_model.php b/application/models/education/Lehreinheit_model.php index 22778cb6a..10c122b94 100644 --- a/application/models/education/Lehreinheit_model.php +++ b/application/models/education/Lehreinheit_model.php @@ -28,6 +28,7 @@ class Lehreinheit_model extends DB_Model { $lehreinheiten = array(); + $this->addOrder('lehreinheit_id'); $les = $this->loadWhere( array('lehrveranstaltung_id' => $lehrveranstaltung_id, 'studiensemester_kurzbz' => $studiensemester) @@ -62,17 +63,17 @@ class Lehreinheit_model extends DB_Model if (hasData($studiengangresponse)) { $studiengang = $studiengangresponse->retval[0]; - $stgkuerzel = mb_strtoupper($studiengang->typ . $studiengang->kurzbz); + $stgkuerzel = mb_strtoupper($studiengang->typ.$studiengang->kurzbz); - $letoadd->lehreinheitgruppen[] = array( - 'semester' => $lehreinheitgruppe->semester, - 'verband' => $lehreinheitgruppe->verband, - 'gruppe' => $lehreinheitgruppe->gruppe, - 'gruppe_kurzbz' => $lehreinheitgruppe->gruppe_kurzbz, - 'direktinskription' => $lehreinheitgruppe->direktinskription, - 'studiengang_kz' => $lehreinheitgruppe->studiengang_kz, - 'studiengang_kuerzel' => $stgkuerzel - ); + $letoadd->lehreinheitgruppen[] = array( + 'semester' => $lehreinheitgruppe->semester, + 'verband' => $lehreinheitgruppe->verband, + 'gruppe' => $lehreinheitgruppe->gruppe, + 'gruppe_kurzbz' => $lehreinheitgruppe->gruppe_kurzbz, + 'direktinskription' => $lehreinheitgruppe->direktinskription, + 'studiengang_kz' => $lehreinheitgruppe->studiengang_kz, + 'studiengang_kuerzel' => $stgkuerzel + ); } } } diff --git a/application/models/education/Lehreinheitgruppe_model.php b/application/models/education/Lehreinheitgruppe_model.php index 796ae574b..2a6f9571a 100644 --- a/application/models/education/Lehreinheitgruppe_model.php +++ b/application/models/education/Lehreinheitgruppe_model.php @@ -98,8 +98,8 @@ class Lehreinheitgruppe_model extends DB_Model 'semester' => $lvadata->semester, 'bezeichnung' => $bezeichnung, 'aktiv' => true, - 'mailgrp' => false, - 'sichtbar' => true, + 'mailgrp' => true, + 'sichtbar' => false, 'generiert' => false, 'insertamum' => date('Y-m-d H:i:s'), 'insertvon' => $loggedInUser, diff --git a/application/models/education/Lehreinheitmitarbeiter_model.php b/application/models/education/Lehreinheitmitarbeiter_model.php index ee11dcd01..dd5c7c858 100644 --- a/application/models/education/Lehreinheitmitarbeiter_model.php +++ b/application/models/education/Lehreinheitmitarbeiter_model.php @@ -11,4 +11,34 @@ class Lehreinheitmitarbeiter_model extends DB_Model $this->dbTable = 'lehre.tbl_lehreinheitmitarbeiter'; $this->pk = array('mitarbeiter_uid', 'lehreinheit_id'); } + + /** + * Checks if Lehrauftrag has a contract. + * @param $mitarbeiter_uid + * @param $lehreinheit_id + * @return array|bool|int Returns vertrag_id if contract exists. False if doesnt exist. On error array. + */ + public function hasVertrag($mitarbeiter_uid, $lehreinheit_id) + { + if(is_string($mitarbeiter_uid) && is_numeric($lehreinheit_id)) + { + $result = $this->load(array( + 'mitarbeiter_uid' => $mitarbeiter_uid, + 'lehreinheit_id' => $lehreinheit_id + )); + + if (hasData($result)) + { + return (is_null($result->retval[0]->vertrag_id)) ? false : intval($result->retval[0]->vertrag_id); + } + else + { + return error($result->msg, EXIT_ERROR); + } + } + else + { + return error ('Incorrect parameter type'); + } + } } diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 1685ddf81..4941ba9bd 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -10,6 +10,9 @@ class Lehrveranstaltung_model extends DB_Model parent::__construct(); $this->dbTable = 'lehre.tbl_lehrveranstaltung'; $this->pk = 'lehrveranstaltung_id'; + + $this->load->model('organisation/studiengang_model', 'StudiengangModel'); + $this->load->model('organisation/studiensemester_model', 'StudiensemesterModel'); } /** @@ -22,8 +25,6 @@ class Lehrveranstaltung_model extends DB_Model */ public function getLehrveranstaltungGroupNames($studiensemester_kurzbz, $ausbildungssemester = null, $studiengang_kz = null, $lehrveranstaltung_ids = null) { - $this->load->model('organisation/studiengang_model', 'StudiengangModel'); - $studiengang_kz_arr = array(); $ausbildungssemester_arr = array(); $lehrveranstaltung_id_arr = array(); @@ -59,13 +60,12 @@ class Lehrveranstaltung_model extends DB_Model } else { - $this->load->model('organisation/studiensemester_model', 'StudiensemesterModel'); foreach ($studiengang_kz_arr as $studiengang_kz_item) { $result = $this->StudiensemesterModel->getAusbildungssemesterByStudiensemesterAndStudiengang($studiensemester_kurzbz, $studiengang_kz_item); if (isError($result)) - return error($result->retval); + return error(getError($result)); foreach ($result->retval as $semester) { @@ -104,7 +104,7 @@ class Lehrveranstaltung_model extends DB_Model if (count($studiengang_kz_arr) > 0) $query .= " AND tbl_lehrveranstaltung.studiengang_kz IN (". implode(", ", $studiengang_kz_arr).")"; - + if (count($lehrveranstaltung_id_arr) > 0) { $query .= " AND tbl_lehrveranstaltung.lehrveranstaltung_id IN (". implode(', ', $lehrveranstaltung_id_arr).")"; @@ -144,7 +144,7 @@ class Lehrveranstaltung_model extends DB_Model WHERE vw_student_lehrveranstaltung.studiensemester_kurzbz=? AND - vw_student_lehrveranstaltung.lehrveranstaltung_id=? + vw_student_lehrveranstaltung.lehrveranstaltung_id=? ORDER BY nachname, vorname, person_id, tbl_bisio.bis DESC"; return $this->execQuery($query, array($studiensemester_kurzbz, $lehrveranstaltung_id)); @@ -214,8 +214,6 @@ class Lehrveranstaltung_model extends DB_Model */ public function getLvsWithIncomingPlaces($studiensemester_kurzbz) { - $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); - $studsemres = $this->StudiensemesterModel->load($studiensemester_kurzbz); if (!hasData($studsemres)) diff --git a/application/models/education/Projektbetreuer_model.php b/application/models/education/Projektbetreuer_model.php index 32743be82..746e4c052 100644 --- a/application/models/education/Projektbetreuer_model.php +++ b/application/models/education/Projektbetreuer_model.php @@ -11,4 +11,34 @@ class Projektbetreuer_model extends DB_Model $this->dbTable = 'lehre.tbl_projektbetreuer'; $this->pk = array('betreuerart_kurzbz', 'projektarbeit_id', 'person_id'); } + + /** + * Checks if Projektauftrag has a contract. + * @param $person_id + * @param $projektarbeit_id + * @return array|bool|int Returns vertrag_id if contract exists. False if doesnt exist. On error array. + */ + public function hasVertrag($person_id, $projektarbeit_id) + { + if (is_numeric($person_id) && is_numeric($projektarbeit_id)) + { + $result = $this->load(array( + 'person_id' => $person_id, + 'projektarbeit_id' => $projektarbeit_id + )); + + if (hasData($result)) + { + return (is_null($result->retval[0]->vertrag_id)) ? false : intval($result->retval[0]->vertrag_id); + } + else + { + return error($result->msg, EXIT_ERROR); + } + } + else + { + return error ('Incorrect parameter type'); + } + } } diff --git a/application/models/organisation/Organisationseinheit_model.php b/application/models/organisation/Organisationseinheit_model.php index f9353c7b3..6439bc8d6 100644 --- a/application/models/organisation/Organisationseinheit_model.php +++ b/application/models/organisation/Organisationseinheit_model.php @@ -125,12 +125,12 @@ class Organisationseinheit_model extends DB_Model public function getChilds($oe_kurzbz, $includeinactive = false) { $query = " - WITH RECURSIVE oes(oe_kurzbz, oe_parent_kurzbz) as + WITH RECURSIVE oes(oe_kurzbz, oe_parent_kurzbz) as ( - SELECT oe_kurzbz, oe_parent_kurzbz FROM public.tbl_organisationseinheit + SELECT oe_kurzbz, oe_parent_kurzbz FROM public.tbl_organisationseinheit WHERE oe_kurzbz=? %s UNION ALL - SELECT o.oe_kurzbz, o.oe_parent_kurzbz FROM public.tbl_organisationseinheit o, oes + SELECT o.oe_kurzbz, o.oe_parent_kurzbz FROM public.tbl_organisationseinheit o, oes WHERE o.oe_parent_kurzbz=oes.oe_kurzbz %s ) SELECT oe_kurzbz @@ -150,12 +150,12 @@ class Organisationseinheit_model extends DB_Model public function getParents($oe_kurzbz, $includeinactive = false) { $query= - "WITH RECURSIVE oes(oe_kurzbz, oe_parent_kurzbz) as + "WITH RECURSIVE oes(oe_kurzbz, oe_parent_kurzbz) as ( - SELECT oe_kurzbz, oe_parent_kurzbz FROM public.tbl_organisationseinheit + SELECT oe_kurzbz, oe_parent_kurzbz FROM public.tbl_organisationseinheit WHERE oe_kurzbz=? %s UNION ALL - SELECT o.oe_kurzbz, o.oe_parent_kurzbz FROM public.tbl_organisationseinheit o, oes + SELECT o.oe_kurzbz, o.oe_parent_kurzbz FROM public.tbl_organisationseinheit o, oes WHERE o.oe_kurzbz=oes.oe_parent_kurzbz %s ) SELECT oe_kurzbz @@ -165,4 +165,27 @@ class Organisationseinheit_model extends DB_Model return $this->execQuery(sprintf($query, $aktivstring, $aktivstring), array($oe_kurzbz)); } + /** + * Get one parent only. + * Easily retrieve department of a studiengang or fakultät of department etc. + * @param $oe_kurzbz + * @return array|null + */ + public function getParent($oe_kurzbz) + { + if (is_string($oe_kurzbz)) + { + $condition = ' + oe_kurzbz = ( + SELECT + oe_parent_kurzbz + FROM + public.tbl_organisationseinheit + WHERE + oe_kurzbz = \''. $oe_kurzbz. '\' + ) + '; + } + return $this->loadWhere($condition); + } } diff --git a/application/models/organisation/Studienplan_model.php b/application/models/organisation/Studienplan_model.php index 2c3b36c03..0cc23b85d 100644 --- a/application/models/organisation/Studienplan_model.php +++ b/application/models/organisation/Studienplan_model.php @@ -19,7 +19,7 @@ class Studienplan_model extends DB_Model return $this->loadWhere(array("studiengang_kz" => $studiengang_kz)); } - public function getStudienplaeneBySemester($studiengang_kz, $studiensemester_kurzbz, $ausbildungssemester = null, $orgform_kurzbz = null) + public function getStudienplaeneBySemester($studiengang_kz, $studiensemester_kurzbz, $ausbildungssemester = null, $orgform_kurzbz = null, $sprache = null) { $this->addJoin("lehre.tbl_studienordnung", "studienordnung_id"); $this->addJoin("lehre.tbl_studienplan_semester", "studienplan_id"); @@ -40,6 +40,11 @@ class Studienplan_model extends DB_Model $whereArray["orgform_kurzbz"] = $orgform_kurzbz; } + if(!is_null($sprache)) + { + $whereArray["tbl_studienplan.sprache"] = $sprache; + } + return $this->StudienplanModel->loadWhere($whereArray); } diff --git a/application/models/organisation/Studiensemester_model.php b/application/models/organisation/Studiensemester_model.php index 9248b241d..9cdde7a52 100644 --- a/application/models/organisation/Studiensemester_model.php +++ b/application/models/organisation/Studiensemester_model.php @@ -13,6 +13,22 @@ class Studiensemester_model extends DB_Model $this->hasSequence = false; } + // Get next study semester + public function getNext() + { + $query = ' + SELECT * + FROM + public.tbl_studiensemester + WHERE + start > now() + ORDER BY start + LIMIT 1; + '; + + return $this->execQuery($query); + } + /** * getLastOrAktSemester */ @@ -61,7 +77,7 @@ class Studiensemester_model extends DB_Model start, ende FROM public.tbl_studiensemester - WHERE start > ( + WHERE start >= ( SELECT ende FROM public.tbl_studiensemester WHERE studiensemester_kurzbz = ? @@ -72,6 +88,26 @@ class Studiensemester_model extends DB_Model return $this->execQuery($query, array($studiensemester_kurzbz)); } + /** + * getPreviousFrom + */ + public function getPreviousFrom($studiensemester_kurzbz) + { + $query = 'SELECT studiensemester_kurzbz, + start, + ende + FROM public.tbl_studiensemester + WHERE ende <= ( + SELECT start + FROM public.tbl_studiensemester + WHERE studiensemester_kurzbz = ? + ) + ORDER BY start DESC + LIMIT 1'; + + return $this->execQuery($query, array($studiensemester_kurzbz)); + } + /** * getNearest */ diff --git a/application/models/person/Benutzer_model.php b/application/models/person/Benutzer_model.php index 46e5bdb98..a21811bb4 100644 --- a/application/models/person/Benutzer_model.php +++ b/application/models/person/Benutzer_model.php @@ -15,8 +15,22 @@ class Benutzer_model extends DB_Model public function getFromPersonId($person_id) { - /*$this->addSelect('uid, aktiv, alias');*/ - $this->loadWhere(array('person_id' => $person_id)); + return $this->loadWhere(array('person_id' => $person_id, 'aktiv' => true)); } + /** + * + */ + public function getActiveUserByPersonIdAndOrganisationUnit($person_id, $oe_kurzbz) + { + $sql = 'SELECT b.uid + FROM public.tbl_benutzer b + JOIN public.tbl_prestudent ps USING (person_id) + JOIN public.tbl_studiengang sg USING (studiengang_kz) + WHERE ps.person_id = ? + AND sg.oe_kurzbz = ? + AND b.aktiv = TRUE'; + + return $this->execQuery($sql, array($person_id, $oe_kurzbz)); + } } diff --git a/application/models/person/Benutzerfunktion_model.php b/application/models/person/Benutzerfunktion_model.php index 02a27e87a..fb9b51c1a 100644 --- a/application/models/person/Benutzerfunktion_model.php +++ b/application/models/person/Benutzerfunktion_model.php @@ -11,16 +11,20 @@ class Benutzerfunktion_model extends DB_Model $this->dbTable = 'public.tbl_benutzerfunktion'; $this->pk = 'benutzerfunktion_id'; } - + /** * Get the Benutzerfunktion using the person_id */ - public function getByPersonId($person_id) + public function getActiveFunctionsByPersonId($person_id) { - // Join with the table - $this->addJoin('public.tbl_benutzer', 'uid'); - - return $this->loadWhere(array('person_id' => $person_id)); + $query = 'SELECT bf.* + FROM public.tbl_benutzerfunktion bf + JOIN public.tbl_benutzer b USING (uid) + WHERE b.person_id = ? + AND (bf.datum_von IS NULL OR bf.datum_von <= now()) + AND (bf.datum_bis IS NULL OR bf.datum_bis >= now())'; + + return $this->execQuery($query, array($person_id)); } /** @@ -48,7 +52,7 @@ class Benutzerfunktion_model extends DB_Model if (is_string($funktion_kurzbz)) { - $query .= " AND funktion_kurzbz = ".$funktion_kurzbz.")"; + $query .= " AND funktion_kurzbz = '".$funktion_kurzbz."'"; } elseif (is_array($funktion_kurzbz) && count($funktion_kurzbz) > 0) { @@ -104,4 +108,38 @@ class Benutzerfunktion_model extends DB_Model return $this->execQuery($query, $parametersArray); } + + /** + * Get active Studiengangsleitung(en) of the user by UID. + * @param $uid + */ + public function getSTGLByUID($uid) + { + $query = ' + SELECT + uid, + oe_kurzbz, + studiengang_kz, + typ, + tbl_studiengang.bezeichnung + FROM + public.tbl_benutzerfunktion + JOIN public.tbl_studiengang USING (oe_kurzbz) + WHERE + funktion_kurzbz = \'Leitung\' + AND (datum_von IS NULL OR datum_von <= now()) + AND (datum_bis IS NULL OR datum_bis >= now()) + AND uid = ? + ORDER BY + oe_kurzbz + '; + + $parameters_array = array(); + if (is_string($uid)) + { + $parameters_array[] = $uid; + } + + return $this->execQuery($query, $parameters_array); + } } diff --git a/application/models/person/Kontakt_model.php b/application/models/person/Kontakt_model.php index 88a44cbc8..3f27604e8 100644 --- a/application/models/person/Kontakt_model.php +++ b/application/models/person/Kontakt_model.php @@ -8,17 +8,17 @@ class Kontakt_model extends DB_Model public function __construct() { parent::__construct(); - $this->dbTable = "public.tbl_kontakt"; - $this->pk = "kontakt_id"; + $this->dbTable = 'public.tbl_kontakt'; + $this->pk = 'kontakt_id'; } - + public function getWholeKontakt($kontakt_id, $person_id = null, $kontakttyp = null) { $result = null; - - $this->addJoin("public.tbl_standort", "standort_id", "LEFT"); - $this->addJoin("public.tbl_firma", "firma_id", "LEFT"); - + + $this->addJoin('public.tbl_standort', 'standort_id', 'LEFT'); + $this->addJoin('public.tbl_firma', 'firma_id', 'LEFT'); + if (isset($kontakt_id)) { $result = $this->load($kontakt_id); @@ -26,22 +26,37 @@ class Kontakt_model extends DB_Model else { $parametersArray = array(); - + if (!is_null($person_id)) { - $parametersArray["person_id"] = $person_id; + $parametersArray['person_id'] = $person_id; } if (!is_null($kontakttyp)) { - $parametersArray["kontakttyp"] = $kontakttyp; + $parametersArray['kontakttyp'] = $kontakttyp; } - + if (count($parametersArray) > 0) { $result = $this->loadWhere($parametersArray); } } - + return $result; } -} \ No newline at end of file + + /** + * + */ + public function getContactByPersonId($person_id, $kontakttyp) + { + $sql = 'SELECT kontakt + FROM public.tbl_kontakt + WHERE zustellung = TRUE + AND person_id = ? + AND kontakttyp = ? + ORDER BY updateamum, insertamum'; + + return $this->execQuery($sql, array($person_id, $kontakttyp)); + } +} diff --git a/application/models/person/Person_model.php b/application/models/person/Person_model.php index b689f4fcb..d8ddb381c 100644 --- a/application/models/person/Person_model.php +++ b/application/models/person/Person_model.php @@ -10,6 +10,9 @@ class Person_model extends DB_Model parent::__construct(); $this->dbTable = 'public.tbl_person'; $this->pk = 'person_id'; + + $this->load->model('person/kontakt_model', 'KontaktModel'); + $this->load->model('person/adresse_model', 'AdresseModel'); } /** @@ -155,29 +158,24 @@ class Person_model extends DB_Model $person = $this->load($person_id); - if($person->error) - return error($person->retval); + if($person->error) return $person; //return null if not found if(count($person->retval) < 1) return success(null); - $this->load->model('person/kontakt_model', 'KontaktModel'); - $this->load->model('person/adresse_model', 'AdresseModel'); - $this->KontaktModel->addDistinct(); $this->KontaktModel->addSelect('kontakttyp, anmerkung, kontakt, zustellung'); $this->KontaktModel->addOrder('kontakttyp'); $where = $zustellung_only === true ? array('person_id' => $person_id, 'zustellung' => true) : array('person_id' => $person_id); $kontakte = $this->KontaktModel->loadWhere($where); - if($kontakte->error) - return error($kontakte->retval); + if($kontakte->error) return $kontakte; + $where = $zustellung_only === true ? array('person_id' => $person_id, 'zustelladresse' => true) : array('person_id' => $person_id); $this->AdresseModel->addSelect('public.tbl_adresse.*, bis.tbl_nation.kurztext AS nationkurztext'); $this->AdresseModel->addJoin('bis.tbl_nation', 'tbl_adresse.nation = tbl_nation.nation_code', 'LEFT'); $adressen = $this->AdresseModel->loadWhere($where); - if($adressen->error) - return error($adressen->retval); + if($adressen->error) return $adressen; $stammdaten = $person->retval[0]; $stammdaten->kontakte = $kontakte->retval; @@ -207,28 +205,47 @@ class Person_model extends DB_Model */ public function getLanguage($uid) { - $language = DEFAULT_LANGUAGE; - + $this->addSelect('public.tbl_person.sprache'); $this->addJoin('public.tbl_benutzer', 'person_id'); + $this->addJoin('public.tbl_sprache', 'sprache'); $this->addOrder('public.tbl_person.updateamum', 'DESC'); $this->addOrder('public.tbl_person.insertvon', 'DESC'); - $persons = $this->loadWhere(array('uid' => $uid)); + return $this->loadWhere(array('uid' => $uid, 'content' => true)); + } - if (hasData($persons)) + /** + * Checks if a person has a Bewerberstatus and reihungstestangetreten = true + * @param $person_id + * @param $studiensemester_kurzbz + * @return array + */ + public function hasBewerber($person_id, $studiensemester_kurzbz, $studiengangtyp = null) + { + $parametersArray = array($person_id, $studiensemester_kurzbz); + + $qry = "SELECT count(*) AS anzahl_bewerber FROM public.tbl_person + JOIN public.tbl_prestudent USING (person_id) + JOIN public.tbl_prestudentstatus ON tbl_prestudentstatus.prestudent_id = tbl_prestudent.prestudent_id"; + + if (isset($studiengangtyp)) { - for ($i = 0; $i < count($persons->retval); $i++) - { - $person = $persons->retval[$i]; - - if (!isEmptyString($person->sprache)) - { - $language = $person->sprache; - break; - } - } + $qry .= " JOIN lehre.tbl_studienplan USING(studienplan_id) + JOIN lehre.tbl_studienordnung USING(studienordnung_id) + JOIN public.tbl_studiengang ON tbl_studienordnung.studiengang_kz = tbl_studiengang.studiengang_kz"; } - return $language; + $qry .= " WHERE person_id = ? + AND studiensemester_kurzbz = ? + AND tbl_prestudentstatus.status_kurzbz = 'Bewerber' + AND reihungstestangetreten"; + + if (isset($studiengangtyp)) + { + $parametersArray[] = $studiengangtyp; + $qry .= " AND tbl_studiengang.typ = ?"; + } + + return $this->execQuery($qry, $parametersArray); } } diff --git a/application/models/ressource/Mitarbeiter_model.php b/application/models/ressource/Mitarbeiter_model.php index 1e03a0ecd..ccaeacd0d 100644 --- a/application/models/ressource/Mitarbeiter_model.php +++ b/application/models/ressource/Mitarbeiter_model.php @@ -11,4 +11,33 @@ class Mitarbeiter_model extends DB_Model $this->dbTable = 'public.tbl_mitarbeiter'; $this->pk = 'mitarbeiter_uid'; } + + /** + * Checks if the user is a Mitarbeiter. + * @param string $uid + * @param boolean null $fixangestellt + * @return array + */ + public function isMitarbeiter($uid, $fixangestellt = null) + { + $this->addSelect('1'); + + if (is_bool($fixangestellt)) + { + $result = $this->loadWhere(array('mitarbeiter_uid' => $uid, 'fixangestellt' => $fixangestellt)); + } + else // default + { + $result = $this->loadWhere(array('mitarbeiter_uid' => $uid)); + } + + if(hasData($result)) + { + return success(true); + } + else + { + return success(false); + } + } } diff --git a/application/models/system/Benutzerrolle_model.php b/application/models/system/Benutzerrolle_model.php index 13ebf57b6..765ad9bd4 100644 --- a/application/models/system/Benutzerrolle_model.php +++ b/application/models/system/Benutzerrolle_model.php @@ -11,7 +11,7 @@ class Benutzerrolle_model extends DB_Model $this->dbTable = 'system.tbl_benutzerrolle'; $this->pk = 'benutzerberechtigung_id'; } - + /** * Checks if the given user is an admin */ @@ -19,9 +19,9 @@ class Benutzerrolle_model extends DB_Model { // Join with the table tbl_benutzer $this->addJoin('public.tbl_benutzer', 'uid'); - + $result = $this->loadWhere(array('person_id' => $person_id, 'rolle_kurzbz' => 'admin')); - + if (!isError($result)) { if (hasData($result)) @@ -33,7 +33,35 @@ class Benutzerrolle_model extends DB_Model $result = success(false); } } - + return $result; } -} \ No newline at end of file + + /** + * Get user who are authorized with berechtigung and, if given, authorized for the specific organisational unit. + * @param $berechtigung_kurzbz + * @param null $oe_kurzbz + * @return array + */ + public function getBenutzerByBerechtigung($berechtigung_kurzbz, $oe_kurzbz = null) + { + $params = array(); + $query = ' + SELECT + * + FROM + system.vw_berechtigung_nichtrekursiv + WHERE + berechtigung_kurzbz = ?'; + + $params[] = $berechtigung_kurzbz; + + if (!is_null($oe_kurzbz)) + { + $query .= ' AND oe_kurzbz = ?'; + $params[] = $oe_kurzbz; + } + + return $this->execQuery($query, $params); + } +} diff --git a/application/models/system/FAS_UDF_model.php b/application/models/system/FAS_UDF_model.php new file mode 100644 index 000000000..aee49d431 --- /dev/null +++ b/application/models/system/FAS_UDF_model.php @@ -0,0 +1,169 @@ +load->model('person/Person_model', 'PersonModel'); + + $result = $this->load(array('public', 'tbl_person')); + if (isSuccess($result) && count($result->retval) == 1) + { + $jsons = json_decode($result->retval[0]->jsons); + } + + $udfs = $this->_fillMissingTextUDF($udfs, $jsons); + $udfs = $this->_fillMissingChkboxUDF($udfs, $jsons); + $udfs = $this->_fillMissingDropdownUDF($udfs, $jsons); + + $resultPerson = $this->PersonModel->update($person_id, $udfs); + } + + // + if (isset($prestudent_id)) + { + // Load model Prestudent_model + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + $result = $this->load(array('public', 'tbl_prestudent')); + if (isSuccess($result) && count($result->retval) == 1) + { + $jsons = json_decode($result->retval[0]->jsons); + } + + $udfs = $this->_fillMissingTextUDF($udfs, $jsons); + $udfs = $this->_fillMissingChkboxUDF($udfs, $jsons); + $udfs = $this->_fillMissingDropdownUDF($udfs, $jsons); + + $resultPrestudent = $this->PrestudentModel->update($prestudent_id, $udfs); + } + + if (isSuccess($resultPerson) && isSuccess($resultPrestudent)) + { + $result = success(array($resultPerson->retval, $resultPrestudent->retval)); + } + else if(isError($resultPerson)) + { + $result = $resultPerson; + } + else if(isError($resultPrestudent)) + { + $result = $resultPrestudent; + } + + return $result; + } + + /** + * + */ + private function _fillMissingChkboxUDF($udfs, $jsons) + { + $_fillMissingChkboxUDF = $udfs; + + foreach($jsons as $udfDescription) + { + if ($udfDescription->{UDFLib::TYPE} == UDFLib::CHKBOX_TYPE) + { + if (!isset($_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}])) + { + $_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] = false; + } + else + { + if ($_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] == UDF_model::STRING_FALSE) + { + $_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] = false; + } + else if ($_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] == UDF_model::STRING_TRUE) + { + $_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] = true; + } + } + } + } + + return $_fillMissingChkboxUDF; + } + + /** + * + */ + private function _fillMissingDropdownUDF($udfs, $jsons) + { + $_fillMissingDropdownUDF = $udfs; + + foreach($jsons as $udfDescription) + { + if ($udfDescription->{UDFLib::TYPE} == UDF_model::UDF_DROPDOWN_TYPE + || $udfDescription->{UDFLib::TYPE} == UDF_model::UDF_MULTIPLEDROPDOWN_TYPE) + { + if (!isset($_fillMissingDropdownUDF[$udfDescription->{UDFLib::NAME}])) + { + $_fillMissingDropdownUDF[$udfDescription->{UDFLib::NAME}] = null; + } + else if($_fillMissingDropdownUDF[$udfDescription->{UDFLib::NAME}] == UDF_model::STRING_NULL) + { + $_fillMissingDropdownUDF[$udfDescription->{UDFLib::NAME}] = null; + } + } + } + + return $_fillMissingDropdownUDF; + } + + /** + * + */ + private function _fillMissingTextUDF($udfs, $jsons) + { + $_fillMissingTextUDF = $udfs; + + foreach($jsons as $udfDescription) + { + if ($udfDescription->{UDFLib::TYPE} == 'textarea' + || $udfDescription->{UDFLib::TYPE} == 'textfield') + { + if (!isset($_fillMissingTextUDF[$udfDescription->{UDFLib::NAME}])) + { + $_fillMissingTextUDF[$udfDescription->{UDFLib::NAME}] = null; + } + else if(trim($_fillMissingTextUDF[$udfDescription->{UDFLib::NAME}]) == '') + { + $_fillMissingTextUDF[$udfDescription->{UDFLib::NAME}] = null; + } + } + } + + return $_fillMissingTextUDF; + } +} diff --git a/application/models/system/MessageToken_model.php b/application/models/system/MessageToken_model.php index 2398bf57a..cd3d8f7d9 100644 --- a/application/models/system/MessageToken_model.php +++ b/application/models/system/MessageToken_model.php @@ -37,17 +37,7 @@ class MessageToken_model extends DB_Model WHERE r.token = ? LIMIT 1'; - $result = $this->db->query($sql, array(MSG_STATUS_DELETED, $token)); - - // If no errors occurred - if ($result) - { - return success($result->result()); - } - else - { - return error($this->db->error()); - } + return $this->execQuery($sql, array(MSG_STATUS_DELETED, $token)); } /** @@ -74,25 +64,24 @@ class MessageToken_model extends DB_Model WHERE r.token = ? LIMIT 1'; - $msgs = $this->db->query($sql, array(MSG_STATUS_ARCHIVED, $token)); + $msgsResult = $this->execQuery($sql, array(MSG_STATUS_ARCHIVED, $token)); // If no errors occurred - if ($msgs) + if (isSuccess($msgsResult)) { - $msgs_result = $msgs->result(); // If at least a record is present - if (count($msgs_result) > 0) + if (hasData($msgsResult)) { - $msg = $msgs_result[0]; + $msg = getData($msgsResult)[0]; + $msgStatusResult = error(); - $msgStatusResult = false; // pessimistic expectation + $this->load->model('system/MsgStatus_model', 'MsgStatusModel'); // If the status of the message is unread if ($msg->status == MSG_STATUS_UNREAD) { // Insert the read status - $msgStatusResult = $this->db->insert( - 'public.tbl_msg_status', + $msgStatusResult = $this->MsgStatusModel->insert( array( 'message_id' => $msg->message_id, 'person_id' => $msg->receiver_id, @@ -108,31 +97,23 @@ class MessageToken_model extends DB_Model // If the status of the message is read else if ($msg->status == MSG_STATUS_READ) { - // Update updateamum to current date - $this->db->set('updateamum', 'NOW()'); - - $this->db->where('message_id', $msg->message_id); - $this->db->where('person_id', $msg->receiver_id); - $this->db->where('status', MSG_STATUS_READ); - - $msgStatusResult = $this->db->update('public.tbl_msg_status'); + $msgStatusResult = $this->MsgStatusModel->update( + array( + 'message_id' => $msg->message_id, + 'person_id' => $msg->receiver_id, + 'status' => MSG_STATUS_READ + ), + array('updateamum' => 'NOW()') + ); } - // If some of the previous DB manipulation (update or insert) has failed - if (!$msgStatusResult) - { - return error($this->db->error()); - } + return $msgStatusResult; } - - return success($msgs_result); } else { - return error($this->db->error()); + return $msgsResult; } - - return success($result->result()); } /** @@ -152,45 +133,7 @@ class MessageToken_model extends DB_Model LEFT JOIN public.tbl_mitarbeiter m ON(b.uid = m.mitarbeiter_uid) WHERE p.person_id = ?'; - $result = $this->db->query($sql, array($person_id)); - - // If no errors occurred - if ($result) - { - return success($result->result()); - } - else - { - return error($this->db->error()); - } - } - - /** - * Get data of a person - */ - public function getPersonData($person_id) - { - $sql = 'SELECT person_id, - vorname as "Vorname", - nachname as "Nachname", - anrede as "Anrede", - titelpost as "TitelPost", - titelpre as "TitelPre", - vornamen as "Vornamen" - FROM public.tbl_person - WHERE person_id %s ?'; - - $result = $this->db->query(sprintf($sql, is_array($person_id) ? 'IN' : '='), array($person_id)); - - // If no errors occurred - if ($result) - { - return success($result->result()); - } - else - { - return error($this->db->error()); - } + return $this->execQuery($sql, array($person_id)); } /** @@ -200,35 +143,12 @@ class MessageToken_model extends DB_Model { $sql = 'SELECT m.mitarbeiter_uid FROM public.tbl_person p - LEFT JOIN public.tbl_benutzer b USING(person_id) - LEFT JOIN public.tbl_mitarbeiter m ON(b.uid = m.mitarbeiter_uid) + JOIN public.tbl_benutzer b USING(person_id) + JOIN public.tbl_mitarbeiter m ON(b.uid = m.mitarbeiter_uid) WHERE p.person_id = ? AND b.aktiv = TRUE'; - $result = $this->db->query($sql, array($person_id)); - - // If no errors occurred - if ($result) - { - // If data are present - if (is_array($result->result()) && count($result->result()) > 0) - { - $personresults = $result->result(); - $person = $personresults[0]; - - // If it is an employee - if ($person->mitarbeiter_uid != null) - { - return true; - } - } - - return false; - } - else - { - return error($this->db->error()); - } + return $this->execQuery($sql, array($person_id)); } /** @@ -254,28 +174,6 @@ class MessageToken_model extends DB_Model LIMIT 1 '; - $result = $this->db->query($sql, array($oe_kurzbz)); - if ($result) // If no errors occurred - { - $result_arr = $result->result(); - // If data are present - if (is_array($result_arr) - && count($result_arr) > 0 - && is_object($result_arr[0]) - && isset($result_arr[0]->oe_kurzbz)) - { - return success($result_arr[0]->oe_kurzbz); - } - else - { - return error(); - } - } - else - { - return error($this->db->error()); - } - - return $result; + return $this->execQuery($sql, array($oe_kurzbz)); } } diff --git a/application/models/system/PersonLock_model.php b/application/models/system/PersonLock_model.php index 1d106b789..f0aadd327 100644 --- a/application/models/system/PersonLock_model.php +++ b/application/models/system/PersonLock_model.php @@ -29,8 +29,7 @@ class PersonLock_model extends DB_Model $result = $this->loadWhere($lockdata); - if ($result->error) - return error($result->retval); + if ($result->error) return $result; if (count($result->retval) > 0) return success($result->retval); @@ -49,8 +48,7 @@ class PersonLock_model extends DB_Model { $locked = $this->checkIfLocked($person_id, $app); - if ($locked->error) - return error($locked->retval); + if ($locked->error) return $locked; //insert only if not already locked if ($locked->retval === null) @@ -77,8 +75,7 @@ class PersonLock_model extends DB_Model foreach ($locks->retval as $lock) { $result = $this->delete($lock->lock_id); - if ($result->error) - return error($result->retval); + if ($result->error) return $result; $deleted[] = $lock; } diff --git a/application/models/system/Recipient_model.php b/application/models/system/Recipient_model.php index 654a9a883..d74d03243 100644 --- a/application/models/system/Recipient_model.php +++ b/application/models/system/Recipient_model.php @@ -25,7 +25,8 @@ class Recipient_model extends DB_Model ks.kontakt, p.nachname, p.vorname, - b.uid + b.uid, + mr.sent FROM public.tbl_msg_recipient mr INNER JOIN public.tbl_msg_message mm USING (message_id) INNER JOIN public.tbl_person p ON (mm.person_id = p.person_id) LEFT JOIN public.tbl_benutzer b ON (mr.person_id = b.person_id) @@ -56,11 +57,13 @@ class Recipient_model extends DB_Model m.oe_kurzbz, s.status, s.statusinfo, - s.insertamum as statusamum + s.insertamum as statusamum, + b.uid FROM public.tbl_msg_recipient r JOIN public.tbl_msg_message m USING (message_id) JOIN ( SELECT * FROM public.tbl_msg_status WHERE status < ? ORDER BY insertamum DESC, status DESC - ) s ON (r.message_id = s.message_id AND r.person_id = s.person_id) + ) s ON (r.message_id = s.message_id AND r.person_id = s.person_id), + LEFT JOIN public.tbl_benutzer b USING(person_id) WHERE r.token = ? LIMIT 1'; @@ -196,74 +199,24 @@ class Recipient_model extends DB_Model } /** - * getMessages + * Gets all messages for which notice emails are still not sent * - * Gets all the messages to be sent - * - * @param kontaktType specifies the type of the kontakt to get - * @param sent specifies the status of the messages to get (NULL never sent, otherwise the shipping date) - * @param limit specifies the number of messages to get - * @param message_id specifies a single message + * @param kontaktType specifies the type of the kontakt to get (email,...) + * @param limit specifies the max number of messages to get + * @param since specifies from which date messages have to be retrieved */ - public function getMessages($kontaktType, $sent, $limit = null, $message_id = null) + public function getNotSentMessages($limit, $since) { - $query = 'SELECT mm.message_id, - ks.kontakt as sender, - kr.kontakt as receiver, - mu.mitarbeiter_uid as employeeContact, - ms.mitarbeiter_uid as senderemployeeContact, - mr.person_id as receiver_id, - mr.token, - mm.subject, - mm.body, - mr.sentinfo - FROM public.tbl_msg_recipient mr INNER JOIN public.tbl_msg_message mm USING (message_id) - LEFT JOIN ( - SELECT person_id, kontakt FROM public.tbl_kontakt WHERE kontakttyp = ? - ) ks ON (ks.person_id = mm.person_id) - LEFT JOIN ( - SELECT person_id, kontakt FROM public.tbl_kontakt WHERE kontakttyp = ? - ) kr ON (kr.person_id = mr.person_id) - LEFT JOIN ( - SELECT b.person_id, - m.mitarbeiter_uid - FROM public.tbl_benutzer b INNER JOIN public.tbl_mitarbeiter m ON(b.uid = m.mitarbeiter_uid) - WHERE b.aktiv = TRUE - ) mu ON (mu.person_id = mr.person_id) - LEFT JOIN ( - SELECT b.person_id, - m.mitarbeiter_uid - FROM public.tbl_benutzer b INNER JOIN public.tbl_mitarbeiter m ON(b.uid = m.mitarbeiter_uid) - WHERE b.aktiv = TRUE - ) ms ON (ms.person_id = mm.person_id)'; + $query = 'SELECT mm.message_id + FROM public.tbl_msg_recipient mr + JOIN public.tbl_msg_message mm USING (message_id) + WHERE mr.sent IS NULL + AND mr.sentinfo IS NULL + AND mm.insertamum > ? + ORDER BY mr.insertamum ASC + LIMIT ?'; - $parametersArray = array($kontaktType, $kontaktType); - - if (is_null($sent) || $sent == '') - { - $query .= ' WHERE mr.sent IS NULL'; - } - else - { - array_push($parametersArray, $sent); - $query .= ' WHERE mr.sent = ?'; - } - - if (!is_null($message_id)) - { - array_push($parametersArray, $message_id); - $query .= ' AND mm.message_id = ?'; - } - - $query .= ' ORDER BY mr.insertamum ASC'; - - if (!is_null($limit)) - { - $query .= ' LIMIT ?'; - array_push($parametersArray, $limit); - } - - return $this->execQuery($query, $parametersArray); + return $this->execQuery($query, array($since, $limit)); } /** @@ -307,4 +260,137 @@ class Recipient_model extends DB_Model return $this->execQuery($sql, $parametersArray); } + + /** + * - Gets the directly recieved messages using the given person id + * - Gets the recieved messages from an organisation unit where this person plays a role given by the parameter functions + */ + public function getReceivedMessages($person_id, $functions) + { + $sql = '-- Messages sent directly to the person + SELECT mr.message_id, + mm.relationmessage_id, + mm.subject, + mm.body, + mm.insertamum AS sent, + p.vorname, + p.nachname, + MAX(ms.status) AS status, + ms.person_id AS statusPersonId, + mr.token + FROM public.tbl_msg_recipient mr + JOIN public.tbl_msg_message mm ON (mm.message_id = mr.message_id) + JOIN public.tbl_msg_status ms ON (ms.message_id = mr.message_id AND ms.person_id = mr.person_id) + JOIN public.tbl_person p ON (p.person_id = mm.person_id) + WHERE mr.person_id = ? + GROUP BY mr.message_id, + mm.relationmessage_id, + mm.subject, + mm.body, + mm.insertamum, + p.vorname, + p.nachname, + ms.person_id, + mr.token + UNION + -- Messages sent to a person that belongs to the recipient organisation unit + SELECT mrou.message_id, + mm.relationmessage_id, + mm.subject, + mm.body, + mm.insertamum AS sent, + pr.vorname, + pr.nachname, + MAX(ms.status) AS status, + ms.person_id AS statusPersonId, + mrou.token + FROM public.tbl_person p + JOIN public.tbl_benutzer b ON (b.person_id = p.person_id) + JOIN ( + SELECT uid, oe_kurzbz + FROM public.tbl_benutzerfunktion + WHERE (datum_von IS NULL OR datum_von <= NOW()) + AND (datum_bis IS NULL OR datum_bis >= NOW()) + AND funktion_kurzbz IN ? + ) bf ON (bf.uid = b.uid) + JOIN public.tbl_msg_recipient mrou ON (mrou.oe_kurzbz = bf.oe_kurzbz) + JOIN public.tbl_msg_message mm ON (mm.message_id = mrou.message_id) + JOIN public.tbl_msg_status ms ON (ms.message_id = mrou.message_id AND ms.person_id = mrou.person_id) + JOIN public.tbl_person pr ON (pr.person_id = mm.person_id) + WHERE p.person_id = ? + GROUP BY mrou.message_id, + mm.relationmessage_id, + mm.subject, + mm.body, + mm.insertamum, + pr.vorname, + pr.nachname, + ms.person_id, + mrou.token + ORDER BY sent DESC'; + + return $this->execQuery($sql, array($person_id, $functions, $person_id)); + } + + /** + * Gets all the sent message by the given person + */ + public function getSentMessages($person_id) + { + $sql = 'SELECT mm.message_id, + mm.relationmessage_id, + mm.subject, + mm.body, + mm.insertamum AS sent, + p.person_id, + p.vorname, + p.nachname, + MAX(ms.status) AS status, + ms.person_id AS statusPersonId, + oe.bezeichnung AS oe, + mr.token + FROM public.tbl_msg_message mm + JOIN public.tbl_msg_recipient mr ON (mr.message_id = mm.message_id) + JOIN public.tbl_msg_status ms ON (ms.message_id = mm.message_id AND ms.person_id = mr.person_id) + JOIN public.tbl_person p ON (p.person_id = mr.person_id) + LEFT JOIN public.tbl_organisationseinheit oe ON (oe.oe_kurzbz = mr.oe_kurzbz) + WHERE mm.person_id = ? + GROUP BY mm.message_id, + mm.relationmessage_id, + mm.subject, + mm.body, + mm.insertamum, + p.person_id, + p.vorname, + p.nachname, + ms.person_id, + oe.bezeichnung, + mr.token + ORDER BY sent DESC'; + + return $this->execQuery($sql, array($person_id)); + } + + /** + * + */ + public function getMessagesById($messageIds) + { + $sql = 'SELECT mm.message_id, + mm.person_id AS sender_id, + mm.subject, + mm.body, + mm.relationmessage_id, + mm.oe_kurzbz AS sender_ou, + mr.person_id AS receiver_id, + mr.token, + mr.sent, + mr.sentinfo, + mr.oe_kurzbz AS receiver_ou + FROM public.tbl_msg_message mm + JOIN public.tbl_msg_recipient mr ON (mr.message_id = mm.message_id) + WHERE mm.message_id IN ?'; + + return $this->execQuery($sql, array($messageIds)); + } } diff --git a/application/models/system/UDF_model.php b/application/models/system/UDF_model.php index 5efb061d1..6923d1733 100644 --- a/application/models/system/UDF_model.php +++ b/application/models/system/UDF_model.php @@ -2,14 +2,6 @@ class UDF_model extends DB_Model { - // String values of booleans - const STRING_NULL = 'null'; - const STRING_TRUE = 'true'; - const STRING_FALSE = 'false'; - - const UDF_DROPDOWN_TYPE = 'dropdown'; - const UDF_MULTIPLEDROPDOWN_TYPE = 'multipledropdown'; - /** * Constructor */ @@ -38,164 +30,4 @@ class UDF_model extends DB_Model return $udfResults; } - - // ------------------------------------------------------------------------------------ - // These methods work only with the this version of FAS, not with the future versions - - /** - * Methods to save data from FAS - */ - public function saveUDFs($udfs) - { - $result = error('No way man!'); - $resultPerson = success('person'); - $resultPrestudent = success('prestudent'); - - $person_id = null; - if (isset($udfs['person_id'])) $person_id = $udfs['person_id']; - unset($udfs['person_id']); - - $prestudent_id = null; - if (isset($udfs['prestudent_id'])) $prestudent_id = $udfs['prestudent_id']; - unset($udfs['prestudent_id']); - - $jsons = array(); - - // - if (isset($person_id)) - { - // Load model Person_model - $this->load->model('person/Person_model', 'PersonModel'); - - $result = $this->load(array('public', 'tbl_person')); - if (isSuccess($result) && count($result->retval) == 1) - { - $jsons = json_decode($result->retval[0]->jsons); - } - - $udfs = $this->_fillMissingTextUDF($udfs, $jsons); - $udfs = $this->_fillMissingChkboxUDF($udfs, $jsons); - $udfs = $this->_fillMissingDropdownUDF($udfs, $jsons); - - $resultPerson = $this->PersonModel->update($person_id, $udfs); - } - - // - if (isset($prestudent_id)) - { - // Load model Prestudent_model - $this->load->model('crm/Prestudent_model', 'PrestudentModel'); - - $result = $this->load(array('public', 'tbl_prestudent')); - if (isSuccess($result) && count($result->retval) == 1) - { - $jsons = json_decode($result->retval[0]->jsons); - } - - $udfs = $this->_fillMissingTextUDF($udfs, $jsons); - $udfs = $this->_fillMissingChkboxUDF($udfs, $jsons); - $udfs = $this->_fillMissingDropdownUDF($udfs, $jsons); - - $resultPrestudent = $this->PrestudentModel->update($prestudent_id, $udfs); - } - - if (isSuccess($resultPerson) && isSuccess($resultPrestudent)) - { - $result = success(array($resultPerson->retval, $resultPrestudent->retval)); - } - else if(isError($resultPerson)) - { - $result = $resultPerson; - } - else if(isError($resultPrestudent)) - { - $result = $resultPrestudent; - } - - return $result; - } - - /** - * - */ - private function _fillMissingChkboxUDF($udfs, $jsons) - { - $_fillMissingChkboxUDF = $udfs; - - foreach($jsons as $udfDescription) - { - if ($udfDescription->{UDFLib::TYPE} == UDFLib::CHKBOX_TYPE) - { - if (!isset($_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}])) - { - $_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] = false; - } - else - { - if ($_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] == UDF_model::STRING_FALSE) - { - $_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] = false; - } - else if ($_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] == UDF_model::STRING_TRUE) - { - $_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] = true; - } - } - } - } - - return $_fillMissingChkboxUDF; - } - - /** - * - */ - private function _fillMissingDropdownUDF($udfs, $jsons) - { - $_fillMissingDropdownUDF = $udfs; - - foreach($jsons as $udfDescription) - { - if ($udfDescription->{UDFLib::TYPE} == UDF_model::UDF_DROPDOWN_TYPE - || $udfDescription->{UDFLib::TYPE} == UDF_model::UDF_MULTIPLEDROPDOWN_TYPE) - { - if (!isset($_fillMissingDropdownUDF[$udfDescription->{UDFLib::NAME}])) - { - $_fillMissingDropdownUDF[$udfDescription->{UDFLib::NAME}] = null; - } - else if($_fillMissingDropdownUDF[$udfDescription->{UDFLib::NAME}] == UDF_model::STRING_NULL) - { - $_fillMissingDropdownUDF[$udfDescription->{UDFLib::NAME}] = null; - } - } - } - - return $_fillMissingDropdownUDF; - } - - /** - * - */ - private function _fillMissingTextUDF($udfs, $jsons) - { - $_fillMissingTextUDF = $udfs; - - foreach($jsons as $udfDescription) - { - if ($udfDescription->{UDFLib::TYPE} == 'textarea' - || $udfDescription->{UDFLib::TYPE} == 'textfield') - { - if (!isset($_fillMissingTextUDF[$udfDescription->{UDFLib::NAME}])) - { - $_fillMissingTextUDF[$udfDescription->{UDFLib::NAME}] = null; - } - else if(trim($_fillMissingTextUDF[$udfDescription->{UDFLib::NAME}]) == '') - { - $_fillMissingTextUDF[$udfDescription->{UDFLib::NAME}] = null; - } - } - } - - return $_fillMissingTextUDF; - } } diff --git a/application/models/system/Variable_model.php b/application/models/system/Variable_model.php index 9800999fe..875fc8876 100644 --- a/application/models/system/Variable_model.php +++ b/application/models/system/Variable_model.php @@ -10,5 +10,93 @@ class Variable_model extends DB_Model parent::__construct(); $this->dbTable = 'public.tbl_variable'; $this->pk = array('uid', 'name'); + $this->hasSequence = false; + + $this->load->model('system/Variablenname_model', 'VariablennameModel'); + } + + /** + * Gets user variables and values for a uid. + * If no value found in tbl_variable, default as defined in variablename_model is retrieved. + * @param $uid + * @param null $names optionally get only certain variables + * @return array + */ + public function getVariables($uid, $names = null) + { + if (isEmptyString($uid)) + $result = error('wrong parameters passed'); + else + { + $vardata = array(); + $parametersArray = array($uid); + + $qry = "SELECT name, wert FROM public.tbl_variable WHERE uid = ?"; + + if (!isEmptyArray($names)) + { + $qry .= " AND name IN ?"; + $parametersArray[] = $names; + } + $qry .= ";"; + + $varresults = $this->execQuery($qry, $parametersArray); + + if (hasData($varresults)) + { + $varresults = getData($varresults); + foreach ($varresults as $varresult) + { + if (isset($varresult->wert)) + $vardata[$varresult->name] = $varresult->wert; + } + } + + $vardefaults = $this->VariablennameModel->getDefaults($names); + + if (hasData($vardefaults)) + { + $vardefaults = getData($vardefaults); + + foreach ($vardefaults as $vardefault) + { + if (!isset($vardata[$vardefault->name]) && isset($vardefault->defaultwert)) + { + $vardata[$vardefault->name] = $vardefault->defaultwert; + } + } + } + $result = success($vardata); + } + + return $result; + } + + /** + * Sets a variable value for a uid. Adds new entry if not present, updates entry otherwise. + * @param $uid + * @param $name + * @param $wert + * @return array + */ + public function setVariable($uid, $name, $wert) + { + $result = error('error when setting variable!'); + if (!isEmptyString($uid) && !isEmptyString($name) && !isEmptyString($wert)) + { + $varres = $this->loadWhere(array('uid' => $uid, 'name' => $name)); + + if (isSuccess($varres)) + { + if (hasData($varres)) + { + $result = $this->VariableModel->update(array('uid' => $uid, 'name' => $name), array('wert' => $wert)); + } + else + $result = $this->VariableModel->insert(array('uid' => $uid, 'name' => $name, 'wert' => $wert)); + } + } + + return $result; } } diff --git a/application/models/system/Variablenname_model.php b/application/models/system/Variablenname_model.php new file mode 100644 index 000000000..7b2a2cf88 --- /dev/null +++ b/application/models/system/Variablenname_model.php @@ -0,0 +1,78 @@ + 'SELECT studiensemester_kurzbz FROM public.tbl_studiensemester WHERE ende>now() ORDER BY start LIMIT 1', + 'infocenter_studiensemester' => 'SELECT studiensemester_kurzbz FROM ( + SELECT DISTINCT ON (studienjahr_kurzbz) start, studiensemester_kurzbz + FROM public.tbl_studiensemester + ORDER BY studienjahr_kurzbz, start + ) sem + WHERE start > now() + LIMIT 1;' + ); + + /** + * Constructor + */ + public function __construct() + { + parent::__construct(); + $this->dbTable = 'public.tbl_variablenname'; + $this->pk ='name'; + } + + /** + * Gets defaults for user variables. + * If no default value present in table, SQL can be executed for retrieving the value. + * @param $names optionally get only defaults for certain variables + * @return array + */ + public function getDefaults($names = null) + { + $defaults = array(); + + $qry = "SELECT name, defaultwert FROM public.tbl_variablenname"; + + if (!isEmptyArray($names)) + { + $qry .= " WHERE name IN ?"; + } + $qry .= ";"; + + $defaultsres = $this->execQuery($qry, array('name' => $names)); + + if (hasData($defaultsres)) + { + $defaults = getData($defaultsres); + + foreach ($defaults as $default) + { + if (!isset($default->defaultwert)) + { + if (isset($this->_dynamic_defaults[$default->name])) + { + $dyndefault = $this->execQuery($this->_dynamic_defaults[$default->name]); + if (hasData($dyndefault)) + { + $dyndefault = getData($dyndefault); + + if (count($dyndefault) === 1) + { + foreach ($dyndefault[0] as $value) + { + $default->defaultwert = $value; + break; + } + } + } + } + } + } + } + + return success($defaults); + } +} diff --git a/application/models/system/Webservicelog_model.php b/application/models/system/Webservicelog_model.php index dc45b13a7..a5b23a396 100644 --- a/application/models/system/Webservicelog_model.php +++ b/application/models/system/Webservicelog_model.php @@ -1,13 +1,14 @@ dbTable = 'system.tbl_webservicelog'; $this->pk = 'webservicelog_id'; } diff --git a/application/views/crm/statusEdit.php b/application/views/crm/statusEdit.php index 5fee3ee92..5f0353acf 100644 --- a/application/views/crm/statusEdit.php +++ b/application/views/crm/statusEdit.php @@ -1,89 +1,89 @@ -load->view('templates/header', array('title' => 'StatusEdit')); - - $s = $status; -?> - -
-
-

Status: status_kurzbz; ?>

-
- - - - - - - - - - - - - - - - - - - - - - -
- beschreibung:

-
-
-   -
- Anmerkung:

-
-
-   -
- Bezeichnung mehrsprachig:

- - - - - sprache; ?>:
- bezeichnung_mehrsprachig[$i])) - { - $val = ''; - } - else - { - $val = $s->bezeichnung_mehrsprachig[$i]; - } - $i++; - ?> -
- - -
-   -
- -
- -
-
-
- - - - - - - +load->view('templates/header', array('title' => 'StatusEdit')); + + $s = $status; +?> + +
+
+

Status: status_kurzbz; ?>

+
+ + + + + + + + + + + + + + + + + + + + + + +
+ beschreibung:

+
+
+   +
+ Anmerkung:

+
+
+   +
+ Bezeichnung mehrsprachig:

+ + + + + sprache; ?>:
+ bezeichnung_mehrsprachig[$i])) + { + $val = ''; + } + else + { + $val = $s->bezeichnung_mehrsprachig[$i]; + } + $i++; + ?> +
+ + +
+   +
+ +
+ +
+
+
+ + + + + + + diff --git a/application/views/crm/statusgrund.php b/application/views/crm/statusgrund.php index e79fa5d05..d4a31aa53 100644 --- a/application/views/crm/statusgrund.php +++ b/application/views/crm/statusgrund.php @@ -1,32 +1,32 @@ - - - - - VileSci - Statusgrund - - - - - - - <body bgcolor="#FFFFFF"> - This application works only with a frames-enabled browser.<br /> - </body> - - - - - <body bgcolor="#FFFFFF"> - This application works only with a frames-enabled browser.<br /> - </body> - - - - <body bgcolor="#FFFFFF"> - This application works only with a frames-enabled browser.<br /> - </body> - - - - - + + + + + VileSci - Statusgrund + + + + + + + <body bgcolor="#FFFFFF"> + This application works only with a frames-enabled browser.<br /> + </body> + + + + + <body bgcolor="#FFFFFF"> + This application works only with a frames-enabled browser.<br /> + </body> + + + + <body bgcolor="#FFFFFF"> + This application works only with a frames-enabled browser.<br /> + </body> + + + + + diff --git a/application/views/crm/statusgrundEdit.php b/application/views/crm/statusgrundEdit.php index ddbd1ff0a..9fa91b6d5 100644 --- a/application/views/crm/statusgrundEdit.php +++ b/application/views/crm/statusgrundEdit.php @@ -1,107 +1,107 @@ -load->view('templates/header', array('title' => 'StatusgrundEdit')); - - $sg = $statusgrund; -?> - -
-
-

Statusgrund: status_kurzbz; ?>

-
"> - - - - - - - - - - - - - - - - - - - - - - - -
- Bezeichnung mehrsprachig:

- - - sprache; ?>:
- bezeichnung_mehrsprachig[$i])) - { - $val = ""; - } - else - { - $val = $sg->bezeichnung_mehrsprachig[$i]; - } - $i++; - ?> -
- - -
-   -
- Beschreibung:

- - - sprache; ?>:
- beschreibung[$i])) - { - $val = ""; - } - else - { - $val = $sg->beschreibung[$i]; - } - $i++; - ?> -
- -
-   -
- Aktiv: - - aktiv) && $sg->aktiv === true ? "checked" : ""; ?> /> -
-   -
- -
- " /> -
-
-
- - - - - - - +load->view('templates/header', array('title' => 'StatusgrundEdit')); + + $sg = $statusgrund; +?> + +
+
+

Statusgrund: status_kurzbz; ?>

+
"> + + + + + + + + + + + + + + + + + + + + + + + +
+ Bezeichnung mehrsprachig:

+ + + sprache; ?>:
+ bezeichnung_mehrsprachig[$i])) + { + $val = ""; + } + else + { + $val = $sg->bezeichnung_mehrsprachig[$i]; + } + $i++; + ?> +
+ + +
+   +
+ Beschreibung:

+ + + sprache; ?>:
+ beschreibung[$i])) + { + $val = ""; + } + else + { + $val = $sg->beschreibung[$i]; + } + $i++; + ?> +
+ +
+   +
+ Aktiv: + + aktiv) && $sg->aktiv === true ? "checked" : ""; ?> /> +
+   +
+ +
+ " /> +
+
+
+ + + + + + + diff --git a/application/views/crm/statusgrundNew.php b/application/views/crm/statusgrundNew.php index bd2ebe7d7..ffcd18429 100644 --- a/application/views/crm/statusgrundNew.php +++ b/application/views/crm/statusgrundNew.php @@ -1,66 +1,66 @@ -load->view('templates/header', array('title' => 'StatusgrundNew')); -?> - -
-
-

Neuer Statusgrund

-
"> - - - - - - - - - - - - - - - - - - - - - - - -
- Bezeichnung mehrsprachig:

- - - sprache; ?>:
-
- - -
-   -
- Beschreibung:

- - - sprache; ?>:
-
- -
-   -
- Aktiv: - - -
-   -
- -
- -
-
-
- - - +load->view('templates/header', array('title' => 'StatusgrundNew')); +?> + +
+
+

Neuer Statusgrund

+
"> + + + + + + + + + + + + + + + + + + + + + + + +
+ Bezeichnung mehrsprachig:

+ + + sprache; ?>:
+
+ + +
+   +
+ Beschreibung:

+ + + sprache; ?>:
+
+ +
+   +
+ Aktiv: + + +
+   +
+ +
+ +
+
+
+ + + diff --git a/application/views/home.php b/application/views/home.php index d00b98f81..79669dd88 100644 --- a/application/views/home.php +++ b/application/views/home.php @@ -3,6 +3,7 @@ $this->load->view('templates/FHC-Header', array( 'title' => 'FH-Complete', 'jquery' => true, + 'jqueryui' => true, 'bootstrap' => true, 'fontawesome' => true, 'sbadmintemplate' => true, diff --git a/application/views/lehre/lehrauftrag/Dashboard.php b/application/views/lehre/lehrauftrag/Dashboard.php new file mode 100644 index 000000000..a14cefa7a --- /dev/null +++ b/application/views/lehre/lehrauftrag/Dashboard.php @@ -0,0 +1,38 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Lehrauftrag bestellen', + 'jquery' => true, + 'jqueryui' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'sbadmintemplate' => true, + 'ajaxlib' => true, + 'dialoglib' => true, + 'navigationwidget' => true, + 'addons' => true, + ) +); +?> + + + widgetlib->widget('NavigationWidget'); ?> +
+
+ +
+
+ +
+
+ +
+ +
+
+ + +load->view('templates/FHC-Footer'); ?> diff --git a/application/views/lehre/lehrauftrag/LehrendeUebersicht.php b/application/views/lehre/lehrauftrag/LehrendeUebersicht.php new file mode 100644 index 000000000..1ad295392 --- /dev/null +++ b/application/views/lehre/lehrauftrag/LehrendeUebersicht.php @@ -0,0 +1,39 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Lehrauftrag bestellen', + 'jquery' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'sbadmintemplate' => true, + 'ajaxlib' => true, + 'navigationwidget' => true, + ) +); +?> + + +widgetlib->widget('NavigationWidget'); ?> +
+
+ +
+
+ +
+
+ +
+ +
+ +
+
+ + +load->view('templates/FHC-Footer'); ?> diff --git a/application/views/lehre/lehrauftrag/acceptLehrauftrag.php b/application/views/lehre/lehrauftrag/acceptLehrauftrag.php new file mode 100644 index 000000000..a4116e8d0 --- /dev/null +++ b/application/views/lehre/lehrauftrag/acceptLehrauftrag.php @@ -0,0 +1,200 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Lehrauftrag annehmen', + 'jquery' => true, + 'jqueryui' => true, + 'jquerycheckboxes' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'sbadmintemplate' => false, + 'tabulator' => true, + 'momentjs' => true, + 'ajaxlib' => true, + 'dialoglib' => true, + 'tablewidget' => true, + 'phrases' => array( + 'global' => array('lehrauftraegeAnnehmen'), + ), + 'customJSs' => array( + 'public/js/bootstrapper.js', + 'public/js/lehre/lehrauftrag/acceptLehrauftrag.js') + ) +); + +?> + + +
+
+ + +
+ +
+ + +
+
+
+

Wie nehme ich Lehraufträge an?

+
+ Sobald Ihnen ein oder mehrere Lehraufträge erteilt wurden, können Sie diese annehmen. +
    +
  1. Klicken Sie unten auf das Status-Icon 'Nur erteilte anzeigen' oder 'Alle anzeigen'
  2. +
  3. Wählen Sie die Lehraufträge, die Sie annehmen möchten, selbst oder alle über den Button 'Alle auswählen'.
  4. +
  5. Geben Sie Ihr CIS-Passwort ein und klicken auf Lehrauftrag annehmen.
  6. +
+
+
+ +

Warum kann ich manche Lehraufträge nicht auswählen?

+
+ Nur Lehraufträge mit dem Status 'erteilt' können gewählt werden.
+ Angenommene Lehraufträge oder Lehraufträge in Bearbeitung werden nur zu Ihrer Information angezeigt. +
+
+ +

Filter

+
+
+ + + + + + + + + + + +
Alle
Alle Lehraufträge mit jedem Status
Erteilt
Nur erteilte UND geänderte Lehraufträge, die in Bearbeitung sind
Angenommen
Nur von Ihnen angenommene Lehraufträge
+
+
+
+ +

Auswahl

+
+
    +
  • Einzeln auswählen: Strg + Klick auf einzelne Zeile(n)
  • +
  • Bereich auswählen: Shift + Klick auf Anfangs- und Endzeile
  • +
  • Alle auswählen: Button 'Alle auswählen'
  • +
+
+
+ +

Ansicht

+
+ Spaltenbreite verändern +

+ Um die Spaltenbreite zu verändern, fährt man im Spaltenkopf langsam mit dem Mauszeiger auf + den rechten Rand der entprechenden Spalte.
+ Sobald sich der Mauszeiger in einen Doppelpfeil verwandelt, wird die Maustaste geklickt und + mit gedrückter Maustaste die Spalte nach rechts erweitert oder nach links verkleinert. +

+
+
+
+
+
+ + +
+
+
+
+ widgetlib->widget( + 'Studiensemester_widget', + array( + DropdownWidget::SELECTED_ELEMENT => $studiensemester_selected + ), + array( + 'name' => 'studiensemester', + 'id' => 'studiensemester' + ) + ); + ?> +
+ +
+
+
+ + +
+
+ load->view('lehre/lehrauftrag/acceptLehrauftragData.php'); ?> +
+
+
+ + +
+
+ +
+
+
+ + + + + +
+
+
+
+
+ + +
+
+

+ p->t('global', 'stornierteLehrauftraege')); ?>: + + + + + +

+
+
+ load->view('lehre/lehrauftrag/cancelledLehrauftragData.php'); ?> +
+
+
+
+
+
+
+
+ + +load->view('templates/FHC-Footer'); ?> diff --git a/application/views/lehre/lehrauftrag/acceptLehrauftragData.php b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php new file mode 100644 index 000000000..6ac3abbdc --- /dev/null +++ b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php @@ -0,0 +1,399 @@ + $query, + 'tableUniqueId' => 'acceptLehrauftrag', + 'requiredPermissions' => 'lehre/lehrauftrag_akzeptieren', + 'datasetRepresentation' => 'tabulator', + 'columnsAliases' => array( // TODO: use phrasen + 'Status', // alias for row_index, because row_index is formatted to display the status icons + 'LV-Teil', + 'LV-ID', + 'PA-ID', + 'Studiensemester', + 'Studiengang-KZ', + 'Studiengang', + 'Semester', + 'OrgForm', + 'Person-ID', + 'Typ', + 'LV- / Projektbezeichnung', + 'Organisationseinheit', + 'Gruppe', + 'Stunden', + 'Betrag', + 'Vertrag-ID', + 'Vertrag-Stunden', + 'Vertrag-Betrag', + 'UID', + 'Bestellt', + 'Erteilt', + 'Angenommen', + 'Bestellt von', + 'Erteilt von', + 'Angenommen von' + ), + 'datasetRepOptions' => '{ + height: 550, + layout: "fitColumns", // fit columns to width of table + responsiveLayout: "hide", // hide columns that dont fit on the table + movableColumns: true, // allows changing column + placeholder: func_placeholder(), + headerFilterPlaceholder: " ", + index: "row_index", // assign specific column as unique id (important for row indexing) + selectable: true, // allow row selection + selectableRangeMode: "click", // allow range selection using shift end click on end of range + selectablePersistence:false, // deselect previously selected rows when table is filtered, sorted or paginated + selectableCheck: function(row){ + return func_selectableCheck(row); + }, + footerElement: func_footerElement(), + rowUpdated:function(row){ + func_rowUpdated(row); + }, + rowSelectionChanged:function(data, rows){ + func_rowSelectionChanged(data, rows); + }, + rowFormatter:function(row){ + func_rowFormatter(row); + }, + tableBuilt: function(){ + func_tableBuilt(this); + }, + renderComplete:function(){ + func_renderComplete(this); + }, + renderStarted:function(){ + func_renderStarted(this); + } + }', // tabulator properties + 'datasetRepFieldsDefs' => '{ + row_index: {visible:false}, // necessary for row indexing + lehreinheit_id: {headerFilter:"input", bottomCalc:"count", bottomCalcFormatter:function(cell){return "Anzahl: " + cell.getValue();}, width: "7%"}, + lehrveranstaltung_id: {headerFilter:"input", width: "5%"}, + projektarbeit_id: {visible: false}, + studiensemester_kurzbz: {visible: false}, + studiengang_kz: {visible: false}, + stg_typ_kurzbz: {headerFilter:"input", width: "5%"}, + semester: {headerFilter:"input"}, + orgform_kurzbz: {headerFilter:"input"}, + person_id: {visible: false}, + typ: {headerFilter:"input", width: "7%"}, + auftrag: {headerFilter:"input", width: "15%"}, + lv_oe_kurzbz: {headerFilter:"input", width: "8%"}, + gruppe: {headerFilter:"input", width: "5%"}, + stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, + headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, + bottomCalc:"sum", bottomCalcParams:{precision:1}, width: "5%"}, + betrag: {align:"right", width: "6%", formatter: form_formatNulltoStringNumber, + headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, + bottomCalc:"sum", bottomCalcParams:{precision:2}, bottomCalcFormatter:"money", bottomCalcFormatterParams:{decimal: ",", thousand: ".", symbol:"€"}, + width: "8%"}, + vertrag_id: {visible: false}, + vertrag_stunden: {visible: false}, + vertrag_betrag: {visible: false}, + mitarbeiter_uid: {visible: false}, + bestellt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: bestellt_tooltip, width: "8%"}, + erteilt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: erteilt_tooltip, width: "8%"}, + akzeptiert: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: akzeptiert_tooltip, width: "8%"}, + bestellt_von: {visible: false}, + erteilt_von: {visible: false}, + akzeptiert_von: {visible: false} + }', // col properties +); + +echo $this->widgetlib->widget('TableWidget', $filterWidgetArray); + +?> diff --git a/application/views/lehre/lehrauftrag/approveLehrauftrag.php b/application/views/lehre/lehrauftrag/approveLehrauftrag.php new file mode 100644 index 000000000..f36ae7dc7 --- /dev/null +++ b/application/views/lehre/lehrauftrag/approveLehrauftrag.php @@ -0,0 +1,240 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Lehrauftrag erteilen', + 'jquery' => true, + 'jqueryui' => true, + 'jquerycheckboxes' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'sbadmintemplate' => true, + 'tabulator' => true, + 'momentjs' => true, + 'ajaxlib' => true, + 'dialoglib' => true, + 'tablewidget' => true, + 'navigationwidget' => true, + 'phrases' => array( + 'global' => array('lehrauftraegeErteilen'), + ), + 'customJSs' => array( + 'public/js/bootstrapper.js', + 'public/js/lehre/lehrauftrag/approveLehrauftrag.js' + ) + ) +); + +?> + + + widgetlib->widget('NavigationWidget'); ?> +
+
+ + +
+ +
+ + +
+
+
+ +

Lehrauftrag Standard-Bestellprozess

+
+ + + + + + + + + + + + + + + +
BESTELLEN
(Studiengangsleitung)
ERTEILEN
(Department-/Kompetenzfeldleitung)
ANNEHMEN
(LektorIn)
+
+
+ +

Lehraufträge erteilen

+
+ Sobald Lehraufträge bestellt wurden, können Sie diese hier erteilen.
+ Erteilte Lehraufträge können von den Lehrenden angenommen werden.
+
    +
  1. Klicken Sie unten auf das Status-Icon 'Nur bestellte anzeigen' oder 'Alle anzeigen'
  2. +
  3. Wählen Sie die zu erteilenden Lehraufträge selbst oder alle über den Button 'Alle auswählen'.
  4. +
  5. Klicken Sie auf Lehrauftrag erteilen.
  6. +
+
+
+ +

Geänderte Lehraufträge

+
+ Im FAS können Änderungen an Stunden/Stundensatz eines Lehrauftrags durchgeführt werden, solange dieser nicht vom Lehrenden angenommen wurde.
+ Wenn Änderungen an bereits bestellten oder erteilten Lehraufträgen vorgenommen wurden, müssen diese vom Studiengang erneut bestellt werden.
+ Bei bereits erteilten Lehraufträgen wird zusätzlich der Status 'erteilt' zurückgesetzt. +
+
+ +

Warum kann ich manche Lehraufträge nicht auswählen?

+
+ Nur Lehraufträge mit dem Status 'bestellt' können gewählt werden.
+ Neue, Bestellte, Akzeptierte oder geänderte Lehraufträge werden nur zu Ihrer Information angezeigt und sind daher NICHT wählbar. +
+
+ +

Filter

+
+ + + + + + + + + + + + + + + + + + + + +
Alle
Alle Lehraufträge mit jedem Status, auch geänderte und Dummy-Aufträge
Neu
Nur Lehraufträge, die im FAS über die Zuteilung eines Lehrenden zu einer Lehreinheit/einem Projekt angelegt und noch nicht bestellt worden sind
Bestellt
Nur bestellte UND geänderte bestellte Lehraufträge
Erteilt
Nur erteilte UND geänderte erteilte Lehraufträge
Angenommen
Nur vom Lehrenden angenommene Lehraufträge
Geändert
Nur Lehraufträge, die geändert wurden, nachdem sie bereits bestellt oder erteilt worden sind
Dummies
Nur Lehraufträge, die mit einem Dummylektor angelegt sind
+
+
+ +

Auswahl

+
+
    +
  • Einzeln auswählen: Strg + Klick auf einzelne Zeile(n)
  • +
  • Bereich auswählen: Shift + Klick auf Anfangs- und Endzeile
  • +
  • Alle auswählen: Button 'Alle auswählen'
  • +
+
+
+ +

Ansicht

+
+ Spaltenbreite verändern +

+ Um die Spaltenbreite zu verändern, fährt man im Spaltenkopf langsam mit dem Mauszeiger auf + den rechten Rand der entprechenden Spalte.
+ Sobald sich der Mauszeiger in einen Doppelpfeil verwandelt, wird die Maustaste geklickt und + mit gedrückter Maustaste die Spalte nach rechts erweitert oder nach links verkleinert. +

+
+
+ +
+
+
+ + +
+
+
+
+ widgetlib->widget( + 'Studiensemester_widget', + array( + DropdownWidget::SELECTED_ELEMENT => $studiensemester_selected + ), + array( + 'name' => 'studiensemester', + 'id' => 'studiensemester' + ) + ); + ?> +
+
+ widgetlib->widget( + 'Organisationseinheit_widget', + array( + DropdownWidget::SELECTED_ELEMENT => $organisationseinheit_selected, + 'organisationseinheit' => $organisationseinheit + ), + array( + 'name' => 'organisationseinheit', + 'id' => 'organisationseinheit' + ) + ); + ?> +
+
+ widgetlib->widget( + 'Ausbildungssemester_widget', + array( + DropdownWidget::SELECTED_ELEMENT => $ausbildungssemester_selected, + 'number_semester' => 6 + ), + array( + 'name' => 'ausbildungssemester', + 'id' => 'ausbildungssemester' + ) + ); + ?> +
+ +
+
+
+ + +
+
+ load->view('lehre/lehrauftrag/approveLehrauftragData.php'); ?> +
+
+
+ + +
+
+ + +
+
+ +
+
+
+ + +load->view('templates/FHC-Footer'); ?> diff --git a/application/views/lehre/lehrauftrag/approveLehrauftragData.php b/application/views/lehre/lehrauftrag/approveLehrauftragData.php new file mode 100644 index 000000000..1da65a0b8 --- /dev/null +++ b/application/views/lehre/lehrauftrag/approveLehrauftragData.php @@ -0,0 +1,419 @@ + $query, + 'tableUniqueId' => 'approveLehrauftrag', + 'requiredPermissions' => 'lehre/lehrauftrag_erteilen', + 'datasetRepresentation' => 'tabulator', + 'columnsAliases' => array( // TODO: use phrasen + 'Status', // alias for row_index, because row_index is formatted to display the status icons + 'Personalnummer', + 'LV-Teil', + 'LV-ID', + 'LV', + 'PA-ID', + 'Studiensemester', + 'Studiengang-KZ', + 'Studiengang', + 'Semester', + 'OrgForm', + 'Person-ID', + 'Typ', + 'LV- / Projektbezeichnung', + 'Organisationseinheit', + 'Gruppe', + 'Lektor', + 'Stunden', + 'Betrag', + 'Vertrag-ID', + 'Vertrag-Stunden', + 'Vertrag-Betrag', + 'UID', + 'Bestellt', + 'Erteilt', + 'Angenommen', + 'Bestellt von', + 'Erteilt von', + 'Angenommen von' + ), + 'datasetRepOptions' => '{ + height: 700, + layout: "fitColumns", // fit columns to width of table + responsiveLayout: "hide", // hide columns that dont fit on the table + movableColumns: true, // allows changing column + placeholder: func_placeholder(), + headerFilterPlaceholder: " ", + groupBy:"lehrveranstaltung_id", + groupToggleElement:"header", //toggle group on click anywhere in the group header + groupHeader: function(value, count, data, group){ + return func_groupHeader(data); + }, + columnCalcs:"both", // show column calculations at top and bottom of table and in groups + index: "row_index", // assign specific column as unique id (important for row indexing) + selectable: true, // allow row selection + selectableRangeMode: "click", // allow range selection using shift end click on end of range + selectablePersistence:false, // deselect previously selected rows when table is filtered, sorted or paginated + selectableCheck: function(row){ + return func_selectableCheck(row); + }, + initialFilter: func_initialFilter(), + footerElement: func_footerElement(), + rowUpdated:function(row){ + func_rowUpdated(row); + }, + rowSelectionChanged:function(data, rows){ + func_rowSelectionChanged(data, rows); + }, + rowFormatter:function(row) + { + func_rowFormatter(row); + }, + renderStarted:function(){ + func_renderStarted(this); + }, + tableBuilt: function(){ + func_tableBuilt(this); + } + }', // tabulator properties + 'datasetRepFieldsDefs' => '{ + // column status is built dynamically in funcTableBuilt(), + row_index: {visible:false}, // necessary for row indexing + personalnummer: {visible: false}, + lehreinheit_id: {headerFilter:"input", bottomCalc:"count", width: "7%", + bottomCalcFormatter:function(cell){return "Anzahl: " + cell.getValue();},}, + lehrveranstaltung_id: {headerFilter:"input"}, + lv_bezeichnung: {visible: false}, + projektarbeit_id: {visible: false}, + studiensemester_kurzbz: {headerFilter:"input"}, + studiengang_kz: {visible: false}, + stg_typ_kurzbz: {headerFilter:"input", width: "5%"}, + semester: {headerFilter:"input"}, + orgform_kurzbz: {headerFilter:"input"}, + person_id: {visible: false}, + typ: {headerFilter:"input"}, + auftrag: {headerFilter:"input", width:"20%"}, + lv_oe_kurzbz: {headerFilter:"input"}, + gruppe: {headerFilter:"input"}, + lektor: {headerFilter:"input", widthGrow: 3}, + stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, + headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, + bottomCalc:"sum", bottomCalcParams:{precision:1}}, + betrag: {align:"right", width: "8%", formatter: form_formatNulltoStringNumber, + headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, + bottomCalc:"sum", bottomCalcParams:{precision:2}, bottomCalcFormatter:"money", bottomCalcFormatterParams:{decimal: ",", thousand: ".", symbol:"€"}}, + vertrag_id: {visible: false}, + vertrag_stunden: {visible: false}, + vertrag_betrag: {visible: false}, + mitarbeiter_uid: {visible: false}, + bestellt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: bestellt_tooltip, width: "8%"}, + erteilt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: erteilt_tooltip, width: "8%"}, + akzeptiert: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: akzeptiert_tooltip, width: "8%"}, + bestellt_von: {visible: false}, + erteilt_von: {visible: false}, + akzeptiert_von: {visible: false}, + }', // col properties +); + +echo $this->widgetlib->widget('TableWidget', $filterWidgetArray); + +?> diff --git a/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php b/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php new file mode 100644 index 000000000..d5af1b081 --- /dev/null +++ b/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php @@ -0,0 +1,104 @@ + $query, + 'tableUniqueId' => 'cancelledLehrauftrag', + 'requiredPermissions' => 'lehre/lehrauftrag_akzeptieren', + 'datasetRepresentation' => 'tabulator', + 'columnsAliases' => array( // TODO: use phrasen + 'Status', + 'Studiensemester', + 'Typ', + 'LV- / Projektbezeichnung', + 'Stunden', + 'Betrag', + 'Storniert am' + ), + 'datasetRepOptions' => '{ + layout: "fitColumns", // fit columns to width of table + responsiveLayout: "hide", // hide columns that dont fit on the table + movableColumns: true, // allows changing column + placeholder: func_placeholder(), + rowFormatter:function(row){ + func_rowFormatter(row); + }, + selectableCheck: function(row){ + return func_selectableCheck(row); + }, + renderComplete:function(){ + func_renderComplete(this); + }, + tableBuilt: function(){ + func_tableBuilt(this); + } + }', // tabulator properties + 'datasetRepFieldsDefs' => '{ + vertrag_id: {visible: false}, + vertragsstunden_studiensemester_kurzbz: {visible: false}, + vertragstyp_kurzbz: {widthGrow: 2}, + bezeichnung: {widthGrow: 2}, + vertragsstunden: { + align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, + bottomCalc:"sum", bottomCalcParams:{precision:1} + }, + betrag: { + align:"right", formatter: form_formatNulltoStringNumber, + bottomCalc:"sum", bottomCalcParams:{precision:2}, bottomCalcFormatter:"money", bottomCalcFormatterParams:{decimal: ",", thousand: ".", symbol:"€"} + }, + storniert: {align:"center", mutator: mut_formatStringDate, tooltip: storniert_tooltip}, + storniert_von: {visible: false}, + letzterStatus_vorStorniert: {visible: false} + }', // col properties +); + +echo $this->widgetlib->widget('TableWidget', $tableWidgetArray); + +?> diff --git a/application/views/lehre/lehrauftrag/orderLehrauftrag.php b/application/views/lehre/lehrauftrag/orderLehrauftrag.php new file mode 100644 index 000000000..b04aa7985 --- /dev/null +++ b/application/views/lehre/lehrauftrag/orderLehrauftrag.php @@ -0,0 +1,242 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Lehrauftrag bestellen', + 'jquery' => true, + 'jqueryui' => true, + 'jquerycheckboxes' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'sbadmintemplate' => true, + 'tabulator' => true, + 'momentjs' => true, + 'ajaxlib' => true, + 'dialoglib' => true, + 'tablewidget' => true, + 'navigationwidget' => true, + 'phrases' => array( + 'global' => array('lehrauftraegeBestellen'), + ), + 'customJSs' => array( + 'public/js/bootstrapper.js', + 'public/js/lehre/lehrauftrag/orderLehrauftrag.js' + ) + ) +); +?> + + + widgetlib->widget('NavigationWidget'); ?> +
+
+ + +
+ +
+ + +
+
+
+ +

Lehrauftrag Standard-Bestellprozess

+
+ + + + + + + + + + + + + + + +
BESTELLEN
(Studiengangsleitung)
ERTEILEN
(Department-/Kompetenzfeldleitung)
ANNEHMEN
(LektorIn)
+
+
+ +

Lehraufträge bestellen

+
+ Sobald im FAS ein Lehrauftrag/eine Projektbetreuung angelegt wurde, können Sie diese hier bestellen.
+ Bestellte Lehraufträge sind zur Erteilung freigegeben.
+
    +
  1. Klicken Sie unten auf das Status-Icon 'Nur neue anzeigen', 'Nur geänderte anzeigen' oder 'Alle anzeigen'
  2. +
  3. Wählen Sie die zu bestellenden Lehraufträge selbst oder über den Button 'Alle auswählen'.
  4. +
  5. Klicken Sie auf Lehrauftrag bestellen.
  6. +
+ Für jeden bestellten Lehrauftrag legt das System einen Vertrag an. +
+
+ +

Geänderte Lehraufträge

+
+ Im FAS können Änderungen an Stunden/Stundensatz eines Lehrauftrags durchgeführt werden, solange dieser nicht vom Lehrenden angenommen wurde.
+ Diese müssen dann erneut bestellt werden.

+ Wenn Änderungen an bereits bestellten oder erteilten Lehraufträgen vorgenommen wurden, werden diese in einem tooltip angezeigt.
+ Fahren Sie dazu mit der Maus über dem Status-Icon am Beginn der Zeile.
+
+
+ +

Warum kann ich manche Lehraufträge nicht auswählen?

+
+ Nur Lehraufträge mit dem Status 'neu' und 'geändert' können bestellt werden.
+ Erteilte oder akzeptierte Lehraufträge werden nur zu Ihrer Information angezeigt und sind daher NICHT wählbar. +
+
+ +

Filter

+
+ + + + + + + + + + + + + + + + + + + + +
Alle
Alle Lehraufträge mit jedem Status, auch geänderte und Dummy-Aufträge
Neu
Nur Lehraufträge, die im FAS über die Zuteilung eines Lehrenden zu einer Lehreinheit/einem Projekt angelegt und noch nicht bestellt worden sind
Bestellt
Nur bestellte UND geänderte bestellte Lehraufträge
Erteilt
Nur erteilte UND geänderte erteilte Lehraufträge
Angenommen
Nur vom Lehrenden angenommene Lehraufträge
Geändert
Nur Lehraufträge, die geändert wurden, nachdem sie bereits bestellt oder erteilt worden sind
Dummies
Nur Lehraufträge, die mit einem Dummylektor angelegt sind
+
+
+ +

Auswahl

+
+
    +
  • Einzeln auswählen: Strg + Klick auf einzelne Zeile(n)
  • +
  • Bereich auswählen: Shift + Klick auf Anfangs- und Endzeile
  • +
  • Alle auswählen: Button 'Alle auswählen'
  • +
+
+
+ +

Ansicht

+
+ Spaltenbreite verändern +

+ Um die Spaltenbreite zu verändern, fährt man im Spaltenkopf langsam mit dem Mauszeiger auf + den rechten Rand der entprechenden Spalte.
+ Sobald sich der Mauszeiger in einen Doppelpfeil verwandelt, wird die Maustaste geklickt und + mit gedrückter Maustaste die Spalte nach rechts erweitert oder nach links verkleinert. +

+
+
+ +
+
+
+ + +
+
+
+
+ widgetlib->widget( + 'Studiensemester_widget', + array( + DropdownWidget::SELECTED_ELEMENT => $studiensemester_selected + ), + array( + 'name' => 'studiensemester', + 'id' => 'studiensemester' + ) + ); + ?> +
+
+ widgetlib->widget( + 'Studiengang_widget', + array( + DropdownWidget::SELECTED_ELEMENT => $studiengang_selected, + 'studiengang' => $studiengang + ), + array( + 'name' => 'studiengang', + 'id' => 'studiengang' + ) + ); + ?> +
+
+ widgetlib->widget( + 'Ausbildungssemester_widget', + array( + DropdownWidget::SELECTED_ELEMENT => $ausbildungssemester_selected, + 'number_semester' => 6 + ), + array( + 'name' => 'ausbildungssemester', + 'id' => 'ausbildungssemester' + ) + ); + ?> +
+ +
+
+
+ + +
+
+ load->view('lehre/lehrauftrag/orderLehrauftragData.php'); ?> +
+
+
+ + +
+
+ + +
+
+ +
+
+
+ + +load->view('templates/FHC-Footer'); ?> diff --git a/application/views/lehre/lehrauftrag/orderLehrauftragData.php b/application/views/lehre/lehrauftrag/orderLehrauftragData.php new file mode 100644 index 000000000..afe41b641 --- /dev/null +++ b/application/views/lehre/lehrauftrag/orderLehrauftragData.php @@ -0,0 +1,457 @@ + $query, + 'tableUniqueId' => 'orderLehrauftrag', + 'requiredPermissions' => 'lehre/lehrauftrag_bestellen', + 'datasetRepresentation' => 'tabulator', + 'columnsAliases' => array( // TODO: use phrasen + 'Status', // alias for row_index, because row_index is formatted to display the status icons + 'Personalnummer', + 'LV-Teil', + 'LV-ID', + 'LV', + 'PA-ID', + 'Studiensemester', + 'Studiengang-KZ', + 'Studiengang', + 'Semester', + 'Studienplan', + 'OrgForm', + 'Person-ID', + 'Typ', + 'LV- / Projektbezeichnung', + 'Organisationseinheit', + 'Gruppe', + 'Lektor', + 'Stunden', + 'Stundensatz', + 'Betrag', + 'Vertrag-ID', + 'Vertrag-Stunden', + 'Vertrag-Betrag', + 'UID', + 'Bestellt', + 'Erteilt', + 'Angenommen', + 'Bestellt von', + 'Erteilt von', + 'Angenommen von' + ), + 'datasetRepOptions' => '{ + height: 700, + layout:"fitColumns", // fit columns to width of table + responsiveLayout:"hide", // hide columns that dont fit on the table + movableColumns: true, // allows changing column + placeholder: func_placeholder(), + headerFilterPlaceholder: " ", + groupBy:"lehrveranstaltung_id", + groupToggleElement:"header", //toggle group on click anywhere in the group header + groupHeader: function(value, count, data, group){ + return func_groupHeader(data); + }, + footerElement: func_footerElement(), + columnCalcs:"both", // show column calculations at top and bottom of table and in groups + index: "row_index", // assign specific column as unique id (important for row indexing) + selectable: true, // allows row selection + selectableRangeMode: "click", // allows range selection using shift end click on end of range + selectablePersistence:false, // deselect previously selected rows when table is filtered, sorted or paginated + selectableCheck: function(row){ + return func_selectableCheck(row); + }, + rowUpdated:function(row){ + func_rowUpdated(row); + }, + rowSelectionChanged:function(data, rows){ + func_rowSelectionChanged(data, rows); + }, + rowFormatter:function(row){ + func_rowFormatter(row); + }, + renderStarted:function(){ + func_renderStarted(this); + }, + tableBuilt: function(){ + func_tableBuilt(this); + }, + dataLoaded: function(data){ + func_dataLoaded(data, this); + }, + }', // tabulator properties + 'datasetRepFieldsDefs' => '{ + // column status is built dynamically in funcTableBuilt() + row_index: {visible: false}, + personalnummer: {visible: false}, + lehreinheit_id: {headerFilter:"input", bottomCalc:"count", width: "7%", + bottomCalcFormatter:function(cell){return "Anzahl: " + cell.getValue();}}, + lehrveranstaltung_id: {headerFilter:"input"}, + lv_bezeichnung: {visible: false}, + projektarbeit_id: {visible: false}, + studiensemester_kurzbz: {headerFilter:"input"}, + studiengang_kz: {visible: false}, + stg_typ_kurzbz: {headerFilter:"input", width: "5%"}, + semester: {headerFilter:"input"}, + studienplan_bezeichnung: {headerFilter:"input", width: "7%"}, + orgform_kurzbz: {headerFilter:"input"}, + person_id: {visible: false}, + typ: {headerFilter:"input"}, + auftrag: {headerFilter:"input", width:"15%"}, + lv_oe_kurzbz: {headerFilter:"input"}, + gruppe: {headerFilter:"input"}, + lektor: {headerFilter:"input", widthGrow: 3}, + stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, + headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, + bottomCalc:"sum", bottomCalcParams:{precision:1}}, + stundensatz: {visible: false}, + betrag: {align:"right", width: "8%", formatter: form_formatNulltoStringNumber, + headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, + bottomCalc:"sum", bottomCalcParams:{precision:2}, bottomCalcFormatter:"money", + bottomCalcFormatterParams:{decimal: ",", thousand: ".", symbol:"€"}}, + vertrag_id: {visible: false}, + vertrag_stunden: {visible: false}, + vertrag_betrag: {visible: false}, + mitarbeiter_uid: {visible: false}, + bestellt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: bestellt_tooltip, width: "8%"}, + erteilt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: erteilt_tooltip, width: "8%"}, + akzeptiert: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: akzeptiert_tooltip, width: "8%"}, + bestellt_von: {visible: false}, + erteilt_von: {visible: false}, + akzeptiert_von: {visible: false} + }', // col properties +); + +echo $this->widgetlib->widget('TableWidget', $filterWidgetArray); + +?> diff --git a/application/views/organisation/reihungstest/ReihungstestUebersichtData.php b/application/views/organisation/reihungstest/ReihungstestUebersichtData.php index 719370ab3..f532e8af5 100644 --- a/application/views/organisation/reihungstest/ReihungstestUebersichtData.php +++ b/application/views/organisation/reihungstest/ReihungstestUebersichtData.php @@ -140,6 +140,10 @@ { $datasetRaw->{'anmeldefrist'} = '-'; } + else + { + $datasetRaw->{'anmeldefrist'} = date_format(date_create($datasetRaw->{'anmeldefrist'}), 'd.m.Y'); + } if ($datasetRaw->{'max_plaetze'} == null) { $datasetRaw->{'max_plaetze'} = '-'; diff --git a/application/views/organisation/studienjahrEdit.php b/application/views/organisation/studienjahrEdit.php index 4a23217b1..df0397cdf 100644 --- a/application/views/organisation/studienjahrEdit.php +++ b/application/views/organisation/studienjahrEdit.php @@ -7,7 +7,7 @@ $this->load->view('templates/header', array('title' => 'StudienjahrEdit', 'jquer

Studienjahr bearbeiten: studienjahr_kurzbz; ?>

-
"> + "> diff --git a/application/views/organisation/studiensemesterEdit.php b/application/views/organisation/studiensemesterEdit.php index 9f0abc0cb..98c4ca243 100644 --- a/application/views/organisation/studiensemesterEdit.php +++ b/application/views/organisation/studiensemesterEdit.php @@ -8,7 +8,7 @@ $this->load->view('templates/header', array('title' => 'StudiensemesterEdit', 'd

Studiensemester bearbeiten: studiensemester_kurzbz; ?>

"> + action="">
diff --git a/application/views/person/gradelist/course.php b/application/views/person/gradelist/course.php index 4b4b41d0f..a4dfaa0fb 100644 --- a/application/views/person/gradelist/course.php +++ b/application/views/person/gradelist/course.php @@ -3,16 +3,27 @@ if(isset($course['note']) && isset($grades[$course['note']])) $gradeclass = ($grades[$course['note']]['positiv']?'gradelist_row_grade_positiv':'gradelist_row_grade_negativ'); else $gradeclass = ''; + +// Only Display the Course if the person is assigned to the course +// (no additional elective courses are displayed) +if(isset($course['zugeordnet']) && $course['zugeordnet'] === true) +{ ?> + + + - + diff --git a/application/views/person/gradelist/gradelist.php b/application/views/person/gradelist/gradelist.php index c6aaaa2f8..9ae485c02 100644 --- a/application/views/person/gradelist/gradelist.php +++ b/application/views/person/gradelist/gradelist.php @@ -31,11 +31,14 @@
- p->t('lehre', 'notendurchschnitt'); ?>: + p->t('lehre', 'notendurchschnitt'); ?> + :
- p->t('lehre', 'gewichteternotendurchschnitt'); ?>: + p->t('lehre', 'gewichteternotendurchschnitt'); ?> + :
- p->t('lehre', 'ects'); ?>: + p->t('lehre', 'ects'); ?> + :

+ + + - + + + @@ -58,6 +58,9 @@ + + + + + + @@ -84,13 +101,13 @@ + + + - + + + @@ -107,8 +124,14 @@ + + + + + + @@ -120,8 +143,10 @@ diff --git a/application/views/system/udf.php b/application/views/system/fas_udf.php similarity index 92% rename from application/views/system/udf.php rename to application/views/system/fas_udf.php index 10ba15698..3efc61abc 100644 --- a/application/views/system/udf.php +++ b/application/views/system/fas_udf.php @@ -1,150 +1,150 @@ -load->view("templates/header", array("title" => "UDF", "widgetsCSS" => true)); ?> - - - - -
- Saved! -
- -
- -
- Error while saving! -
-
-
-retval; - if(is_array($errors)) - { - foreach ($errors as $error) - { - foreach ($error as $fieldError) - { - echo $fieldError->code . ': ' . $fieldError->retval . '
'; - } - } - } - else - echo $result->retval; -?> -
- -
-
-
- - - -
-
-
- Zusatzfelder -
-
-
-
-   -
-
-
- -
- udflib->UDFWidget( - array( - UDFLib::SCHEMA_ARG_NAME => 'public', - UDFLib::TABLE_ARG_NAME => 'tbl_person', - UDFLib::UDFS_ARG_NAME => $personUdfs - ) - ); - ?> -
-
-   -
- - -
- udflib->UDFWidget( - array( - UDFLib::SCHEMA_ARG_NAME => 'public', - UDFLib::TABLE_ARG_NAME => 'tbl_prestudent', - UDFLib::UDFS_ARG_NAME => $prestudentUdfs - ) - ); - ?> -
- -
-
-
-   -
-
-
- -
-   -
-
-   -
- -
- -
-
-
- - - - - - - - - - - - -load->view("templates/footer"); ?> +load->view("templates/header", array("title" => "UDF", "widgetsCSS" => true)); ?> + + + + +
+ Saved! +
+ +
+ +
+ Error while saving! +
+
+
+retval; + if(is_array($errors)) + { + foreach ($errors as $error) + { + foreach ($error as $fieldError) + { + echo $fieldError->code . ': ' . $fieldError->retval . '
'; + } + } + } + else + echo $result->retval; +?> +
+ +
+
+
+ + + +
+
+
+ Zusatzfelder +
+
+
+
+   +
+
+
+ +
+ udflib->UDFWidget( + array( + UDFLib::SCHEMA_ARG_NAME => 'public', + UDFLib::TABLE_ARG_NAME => 'tbl_person', + UDFLib::UDFS_ARG_NAME => $personUdfs + ) + ); + ?> +
+
+   +
+ + +
+ udflib->UDFWidget( + array( + UDFLib::SCHEMA_ARG_NAME => 'public', + UDFLib::TABLE_ARG_NAME => 'tbl_prestudent', + UDFLib::UDFS_ARG_NAME => $prestudentUdfs + ) + ); + ?> +
+ +
+
+
+   +
+
+
+ +
+   +
+
+   +
+ +
+ +
+
+
+ + + + + + + + + + + + +load->view("templates/footer"); ?> diff --git a/application/views/system/infocenter/infocenter.php b/application/views/system/infocenter/infocenter.php index ebc99ba93..4005518a1 100644 --- a/application/views/system/infocenter/infocenter.php +++ b/application/views/system/infocenter/infocenter.php @@ -18,7 +18,7 @@ 'global' => array('mailAnXversandt'), 'ui' => array('bitteEintragWaehlen') ), - 'customCSSs' => 'public/css/sbadmin2/tablesort_bootstrap.css', + 'customCSSs' => array('public/css/sbadmin2/tablesort_bootstrap.css', 'public/css/infocenter/infocenterPersonDataset.css'), 'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/infocenterPersonDataset.js') ) ); diff --git a/application/views/system/infocenter/infocenterData.php b/application/views/system/infocenter/infocenterData.php index 7841b7b12..0c7030059 100644 --- a/application/views/system/infocenter/infocenterData.php +++ b/application/views/system/infocenter/infocenterData.php @@ -7,19 +7,14 @@ $TAETIGKEIT_KURZBZ = '\'bewerbung\', \'kommunikation\''; $LOGDATA_NAME = '\'Login with code\', \'Login with user\', \'New application\', \'Interessent rejected\''; $LOGDATA_NAME_PARKED = '\'Parked\''; + $LOGDATA_NAME_ONHOLD = '\'Onhold\''; $LOGTYPE_KURZBZ = '\'Processstate\''; $STATUS_KURZBZ = '\'Wartender\', \'Bewerber\', \'Aufgenommener\', \'Student\''; $ADDITIONAL_STG = '10021,10027'; + $AKTE_TYP = '\'identity\', \'zgv_bakk\''; + $STUDIENSEMESTER = '\''.$this->variablelib->getVar('infocenter_studiensemester').'\''; $query = ' - WITH currentOrNextStudiensemester AS ( - SELECT ss.studiensemester_kurzbz - FROM public.tbl_studiensemester ss - WHERE ss.ende > NOW() - ORDER BY ss.ende - LIMIT 3 - ) - SELECT p.person_id AS "PersonId", p.vorname AS "Vorname", @@ -30,6 +25,7 @@ pl.zeitpunkt AS "LockDate", pl.lockuser AS "LockUser", pd.parkdate AS "ParkDate", + ohd.onholddate AS "OnholdDate", ( SELECT l.zeitpunkt FROM system.tbl_log l @@ -48,6 +44,14 @@ ORDER BY l.zeitpunkt DESC LIMIT 1 ) AS "LastActionType", + ( + SELECT count(akte_id) + FROM public.tbl_akte a + WHERE + a.person_id = p.person_id + AND + a.dokument_kurzbz in ('.$AKTE_TYP.') + ) AS "AnzahlAkte", ( SELECT l.insertvon FROM system.tbl_log l @@ -91,13 +95,14 @@ OR sg.studiengang_kz in('.$ADDITIONAL_STG.') ) - AND pss.studiensemester_kurzbz IN (SELECT cnss.studiensemester_kurzbz FROM currentOrNextStudiensemester cnss) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' AND NOT EXISTS ( SELECT 1 FROM tbl_prestudentstatus spss WHERE spss.prestudent_id = pss.prestudent_id AND spss.status_kurzbz = '.$REJECTED_STATUS.' - AND spss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende > NOW()) + AND spss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende > + (SELECT start FROM public.tbl_studiensemester sss WHERE studiensemester_kurzbz = '.$STUDIENSEMESTER.')) ) ORDER BY pss.datum DESC, pss.insertamum DESC, pss.ext_id DESC LIMIT 1 @@ -116,13 +121,14 @@ OR sg.studiengang_kz in('.$ADDITIONAL_STG.') ) - AND pss.studiensemester_kurzbz IN (SELECT cnss.studiensemester_kurzbz FROM currentOrNextStudiensemester cnss) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' AND NOT EXISTS ( SELECT 1 FROM tbl_prestudentstatus spss WHERE spss.prestudent_id = pss.prestudent_id AND spss.status_kurzbz = '.$REJECTED_STATUS.' - AND spss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende > NOW()) + AND spss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende > + (SELECT start FROM public.tbl_studiensemester sss WHERE studiensemester_kurzbz = '.$STUDIENSEMESTER.')) ) LIMIT 1 ) AS "AnzahlAbgeschickt", @@ -134,19 +140,20 @@ JOIN lehre.tbl_studienplan sp USING(studienplan_id) WHERE pss.status_kurzbz = '.$INTERESSENT_STATUS.' AND pss.bewerbung_abgeschicktamum IS NOT NULL - AND pss.bestaetigtam IS NULL + -- AND pss.bestaetigtam IS NULL AND ps.person_id = p.person_id AND (sg.typ IN ('.$STUDIENGANG_TYP.') OR sg.studiengang_kz in('.$ADDITIONAL_STG.') ) - AND pss.studiensemester_kurzbz IN (SELECT cnss.studiensemester_kurzbz FROM currentOrNextStudiensemester cnss) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' AND NOT EXISTS ( SELECT 1 FROM tbl_prestudentstatus spss WHERE spss.prestudent_id = pss.prestudent_id AND spss.status_kurzbz = '.$REJECTED_STATUS.' - AND spss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende > NOW()) + AND spss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende > + (SELECT start FROM public.tbl_studiensemester sss WHERE studiensemester_kurzbz = '.$STUDIENSEMESTER.')) ) LIMIT 1 ) AS "StgAbgeschickt", @@ -164,13 +171,15 @@ OR sg.studiengang_kz in('.$ADDITIONAL_STG.') ) - AND pss.studiensemester_kurzbz IN (SELECT cnss.studiensemester_kurzbz FROM currentOrNextStudiensemester cnss) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' + AND NOT EXISTS ( SELECT 1 FROM tbl_prestudentstatus spss WHERE spss.prestudent_id = pss.prestudent_id AND spss.status_kurzbz = '.$REJECTED_STATUS.' - AND spss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende > NOW()) + AND spss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende > + (SELECT start FROM public.tbl_studiensemester sss WHERE studiensemester_kurzbz = '.$STUDIENSEMESTER.')) ) LIMIT 1 ) AS "StgNichtAbgeschickt", @@ -187,13 +196,14 @@ OR sg.studiengang_kz in('.$ADDITIONAL_STG.') ) - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.start >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' AND NOT EXISTS ( SELECT 1 FROM tbl_prestudentstatus spss WHERE spss.prestudent_id = pss.prestudent_id AND spss.status_kurzbz = '.$REJECTED_STATUS.' - AND spss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende > NOW()) + AND spss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende > + (SELECT start FROM public.tbl_studiensemester sss WHERE studiensemester_kurzbz = '.$STUDIENSEMESTER.')) ) LIMIT 1 ) AS "StgAktiv", @@ -220,6 +230,14 @@ AND l.logdata->>\'name\' = '.$LOGDATA_NAME_PARKED.' AND l.zeitpunkt >= NOW() ) pd USING(person_id) + LEFT JOIN ( + SELECT l.person_id, + l.zeitpunkt AS onholddate + FROM system.tbl_log l + WHERE l.logtype_kurzbz = '.$LOGTYPE_KURZBZ.' + AND l.logdata->>\'name\' = '.$LOGDATA_NAME_ONHOLD.' + AND l.zeitpunkt >= NOW() + ) ohd USING(person_id) WHERE EXISTS ( SELECT 1 @@ -243,7 +261,7 @@ WHERE spss.prestudent_id = sps.prestudent_id AND spss.status_kurzbz = '.$INTERESSENT_STATUS.' AND spss.bestaetigtam IS NULL - AND spss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende > NOW()) + AND spss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' ) ) ORDER BY "LastAction" ASC'; @@ -256,7 +274,6 @@ 'filter_id' => $this->input->get('filter_id'), 'requiredPermissions' => 'infocenter', 'datasetRepresentation' => 'tablesorter', - 'reloadDataset' => ($this->input->get('reloadDataset')=='true'?true:false), 'customMenu' => true, 'checkboxes' => 'PersonId', 'additionalColumns' => array('Details'), @@ -270,8 +287,10 @@ ucfirst($this->p->t('global', 'sperrdatum')), ucfirst($this->p->t('global', 'gesperrtVon')), ucfirst($this->p->t('global', 'parkdatum')), + ucfirst($this->p->t('global', 'rueckstelldatum')), ucfirst($this->p->t('global', 'letzteAktion')), 'Aktionstyp', + 'AnzahlAktePflicht', ucfirst($this->p->t('global', 'letzterBearbeiter')), ucfirst($this->p->t('lehre', 'studiensemester')), ucfirst($this->p->t('global', 'gesendetAm')), @@ -331,6 +350,11 @@ $datasetRaw->{'ParkDate'} = '-'; } + if ($datasetRaw->{'OnholdDate'} == null) + { + $datasetRaw->{'OnholdDate'} = '-'; + } + if ($datasetRaw->{'StgAbgeschickt'} == null) { $datasetRaw->{'StgAbgeschickt'} = '-'; @@ -367,6 +391,11 @@ $mark = FilterWidget::DEFAULT_MARK_ROW_CLASS; } + if ($datasetRaw->OnholdDate != null) + { + $mark = "onhold"; + } + // Parking has priority over locking if ($datasetRaw->ParkDate != null) { diff --git a/application/views/system/infocenter/infocenterDetails.php b/application/views/system/infocenter/infocenterDetails.php index 9e708d076..11b8ef094 100644 --- a/application/views/system/infocenter/infocenterDetails.php +++ b/application/views/system/infocenter/infocenterDetails.php @@ -22,7 +22,7 @@ 'customJSs' => array( 'public/js/bootstrapper.js', 'public/js/tablesort/tablesort.js', - 'public/js/messaging/messageList.js', + 'public/js/infocenter/messageList.js', 'public/js/infocenter/infocenterDetails.js' ), 'phrases' => array( @@ -34,7 +34,14 @@ 'nichtsZumAusparken', 'fehlerBeimAusparken', 'fehlerBeimParken', - 'bewerberGeparktBis' + 'bewerberGeparktBis', + 'bewerberOnHold', + 'bewerberOnHoldEntfernen', + 'bewerberOnHoldBis', + 'nichtsZumEntfernen', + 'fehlerBeimEntfernen', + 'rueckstelldatumUeberschritten', + 'parkenZurueckstellenInfo' ), 'ui' => array( 'gespeichert', @@ -147,7 +154,7 @@
load->view('system/messages/messageList.php', $messages); + $this->load->view('system/infocenter/messageList.php', $messages); ?>
@@ -176,7 +183,7 @@
-
+
load->view('system/infocenter/logs.php'); ?>
diff --git a/application/views/system/infocenter/infocenterFreigegeben.php b/application/views/system/infocenter/infocenterFreigegeben.php index 40f69528d..15e73f1b6 100644 --- a/application/views/system/infocenter/infocenterFreigegeben.php +++ b/application/views/system/infocenter/infocenterFreigegeben.php @@ -18,7 +18,7 @@ 'global' => array('mailAnXversandt'), 'ui' => array('bitteEintragWaehlen') ), - 'customCSSs' => 'public/css/sbadmin2/tablesort_bootstrap.css', + 'customCSSs' => array('public/css/sbadmin2/tablesort_bootstrap.css', 'public/css/infocenter/infocenterPersonDataset.css'), 'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/infocenterPersonDataset.js') ) ); diff --git a/application/views/system/infocenter/infocenterFreigegebenData.php b/application/views/system/infocenter/infocenterFreigegebenData.php index 554d00fef..729fabb04 100644 --- a/application/views/system/infocenter/infocenterFreigegebenData.php +++ b/application/views/system/infocenter/infocenterFreigegebenData.php @@ -6,7 +6,9 @@ $TAETIGKEIT_KURZBZ = '\'bewerbung\', \'kommunikation\''; $LOGDATA_NAME = '\'Login with code\', \'Login with user\', \'New application\''; $REJECTED_STATUS = '\'Abgewiesener\''; - $ADDITIONAL_STG = '10021,10027'; + $ADDITIONAL_STG = '10021,10027,10002'; + $STATUS_KURZBZ = '\'Wartender\', \'Bewerber\', \'Aufgenommener\', \'Student\''; + $STUDIENSEMESTER = '\''.$this->variablelib->getVar('infocenter_studiensemester').'\''; $query = ' SELECT @@ -57,7 +59,7 @@ sg.studiengang_kz in('.$ADDITIONAL_STG.') ) AND pss.bestaetigtam is not null - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' ORDER BY pss.datum DESC, pss.insertamum DESC, pss.ext_id DESC LIMIT 1 ) AS "Studiensemester", @@ -73,7 +75,7 @@ OR sg.studiengang_kz in('.$ADDITIONAL_STG.') ) - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' ORDER BY pss.datum DESC, pss.insertamum DESC, pss.ext_id DESC LIMIT 1 ) AS "SendDate", @@ -89,7 +91,7 @@ OR sg.studiengang_kz in('.$ADDITIONAL_STG.') ) - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' AND NOT EXISTS ( SELECT 1 FROM tbl_prestudentstatus spss @@ -111,9 +113,33 @@ OR sg.studiengang_kz in('.$ADDITIONAL_STG.') ) - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' LIMIT 1 ) AS "StgAbgeschickt", + ( + SELECT ARRAY_TO_STRING(ARRAY_AGG(DISTINCT UPPER(sg.typ || sg.kurzbz) || \':\' || sp.orgform_kurzbz), \', \') + FROM public.tbl_prestudentstatus pss + JOIN public.tbl_prestudent ps USING(prestudent_id) + JOIN public.tbl_studiengang sg USING(studiengang_kz) + JOIN lehre.tbl_studienplan sp USING(studienplan_id) + WHERE pss.status_kurzbz IN ('.$STATUS_KURZBZ.') + + AND ps.person_id = p.person_id + AND (sg.typ IN ('.$STUDIENGANG_TYP.') + OR + sg.studiengang_kz in('.$ADDITIONAL_STG.') + ) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' + AND NOT EXISTS ( + SELECT 1 + FROM tbl_prestudentstatus spss + WHERE spss.prestudent_id = pss.prestudent_id + AND spss.status_kurzbz = '.$REJECTED_STATUS.' + AND spss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende > + (SELECT start FROM public.tbl_studiensemester sss WHERE studiensemester_kurzbz = '.$STUDIENSEMESTER.')) + ) + LIMIT 1 + ) AS "StgAktiv", ( SELECT ARRAY_TO_STRING(ARRAY_AGG(DISTINCT UPPER(sg.bezeichnung_mehrsprachig[1])), \', \') FROM public.tbl_prestudentstatus pss @@ -121,7 +147,7 @@ LEFT JOIN public.tbl_status_grund sg USING(statusgrund_id) WHERE pss.status_kurzbz = '.$INTERESSENT_STATUS.' AND ps.person_id = p.person_id - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' LIMIT 1 ) AS "Statusgrund", ( @@ -138,7 +164,7 @@ ) rtp ON(rtp.person_id = ps.person_id AND rtp.studiensemester_kurzbz = pss.studiensemester_kurzbz) WHERE pss.status_kurzbz = '.$INTERESSENT_STATUS.' AND ps.person_id = p.person_id - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' ORDER BY pss.datum DESC, pss.insertamum DESC, pss.ext_id DESC LIMIT 1 ) AS "ReihungstestAngetreten", @@ -155,7 +181,7 @@ ) rtp ON(rtp.person_id = ps.person_id AND rtp.studiensemester_kurzbz = pss.studiensemester_kurzbz) WHERE pss.status_kurzbz = '.$INTERESSENT_STATUS.' AND ps.person_id = p.person_id - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' ORDER BY pss.datum DESC, pss.insertamum DESC, pss.ext_id DESC LIMIT 1 ) AS "ReihungstestApplied", @@ -180,6 +206,7 @@ FROM public.tbl_prestudent ps JOIN public.tbl_studiengang sg USING(studiengang_kz) WHERE ps.person_id = p.person_id + AND ps.reihungstestangetreten = FALSE AND (sg.typ IN ('.$STUDIENGANG_TYP.') OR sg.studiengang_kz in('.$ADDITIONAL_STG.') @@ -191,7 +218,7 @@ AND pss.status_kurzbz = '.$INTERESSENT_STATUS.' AND pss.bestaetigtam IS NOT NULL AND pss.bewerbung_abgeschicktamum IS NOT NULL - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' AND NOT EXISTS ( SELECT 1 FROM tbl_prestudentstatus spss @@ -227,6 +254,7 @@ 'GesendetAm', 'NumAbgeschickt', 'Studiengänge', + 'Stg aktiv', 'Statusgrund', 'Reihungstest angetreten', 'Reihungstest angemeldet', @@ -287,6 +315,11 @@ $datasetRaw->{'Nation'} = '-'; } + if ($datasetRaw->{'StgAktiv'} == null) + { + $datasetRaw->{'StgAktiv'} = '-'; + } + if ($datasetRaw->{'ReihungstestAngetreten'} == 'true') { $datasetRaw->{'ReihungstestAngetreten'} = 'Ja'; diff --git a/application/views/system/infocenter/infocenterReihungstestAbsolviert.php b/application/views/system/infocenter/infocenterReihungstestAbsolviert.php index d40b7a572..79f75885b 100644 --- a/application/views/system/infocenter/infocenterReihungstestAbsolviert.php +++ b/application/views/system/infocenter/infocenterReihungstestAbsolviert.php @@ -18,7 +18,7 @@ 'global' => array('mailAnXversandt'), 'ui' => array('bitteEintragWaehlen') ), - 'customCSSs' => 'public/css/sbadmin2/tablesort_bootstrap.css', + 'customCSSs' => array('public/css/sbadmin2/tablesort_bootstrap.css', 'public/css/infocenter/infocenterPersonDataset.css'), 'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/infocenterPersonDataset.js') ) ); diff --git a/application/views/system/infocenter/infocenterReihungstestAbsolviertData.php b/application/views/system/infocenter/infocenterReihungstestAbsolviertData.php index ff488b6dc..22b122bb0 100644 --- a/application/views/system/infocenter/infocenterReihungstestAbsolviertData.php +++ b/application/views/system/infocenter/infocenterReihungstestAbsolviertData.php @@ -6,6 +6,7 @@ $TAETIGKEIT_KURZBZ = '\'bewerbung\', \'kommunikation\''; $LOGDATA_NAME = '\'Login with code\', \'Login with user\', \'New application\''; $ADDITIONAL_STG = '10021,10027'; + $STUDIENSEMESTER = '\''.$this->variablelib->getVar('infocenter_studiensemester').'\''; $query = ' SELECT @@ -46,7 +47,7 @@ OR sg.studiengang_kz in('.$ADDITIONAL_STG.') ) - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' ORDER BY pss.datum DESC, pss.insertamum DESC, pss.ext_id DESC LIMIT 1 ) AS "Studiensemester", @@ -62,7 +63,7 @@ OR sg.studiengang_kz in('.$ADDITIONAL_STG.') ) - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' ORDER BY pss.datum DESC, pss.insertamum DESC, pss.ext_id DESC LIMIT 1 ) AS "SendDate", @@ -78,7 +79,7 @@ OR sg.studiengang_kz in('.$ADDITIONAL_STG.') ) - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' LIMIT 1 ) AS "AnzahlAbgeschickt", ( @@ -93,7 +94,7 @@ OR sg.studiengang_kz in('.$ADDITIONAL_STG.') ) - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' LIMIT 1 ) AS "StgAbgeschickt", ( @@ -103,7 +104,7 @@ LEFT JOIN public.tbl_status_grund sg USING(statusgrund_id) WHERE pss.status_kurzbz = '.$INTERESSENT_STATUS.' AND ps.person_id = p.person_id - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' LIMIT 1 ) AS "Statusgrund", ( @@ -120,7 +121,7 @@ ) rtp ON(rtp.person_id = ps.person_id AND rtp.studiensemester_kurzbz = pss.studiensemester_kurzbz) WHERE pss.status_kurzbz = '.$INTERESSENT_STATUS.' AND ps.person_id = p.person_id - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' ORDER BY pss.datum DESC, pss.insertamum DESC, pss.ext_id DESC LIMIT 1 ) AS "ReihungstestAngetreten", @@ -137,7 +138,7 @@ ) rtp ON(rtp.person_id = ps.person_id AND rtp.studiensemester_kurzbz = pss.studiensemester_kurzbz) WHERE pss.status_kurzbz = '.$INTERESSENT_STATUS.' AND ps.person_id = p.person_id - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' ORDER BY pss.datum DESC, pss.insertamum DESC, pss.ext_id DESC LIMIT 1 ) AS "ReihungstestApplied", @@ -155,7 +156,7 @@ ) rtp ON(rtp.person_id = ps.person_id AND rtp.studiensemester_kurzbz = pss.studiensemester_kurzbz) WHERE pss.status_kurzbz = '.$INTERESSENT_STATUS.' AND ps.person_id = p.person_id - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' ORDER BY pss.datum DESC, pss.insertamum DESC, pss.ext_id DESC LIMIT 1 ) AS "ReihungstestDatum", @@ -191,7 +192,7 @@ AND pss.status_kurzbz = '.$INTERESSENT_STATUS.' AND pss.bestaetigtam IS NOT NULL AND pss.bewerbung_abgeschicktamum IS NOT NULL - AND pss.studiensemester_kurzbz IN (SELECT ss.studiensemester_kurzbz FROM public.tbl_studiensemester ss WHERE ss.ende >= NOW()) + AND pss.studiensemester_kurzbz = '.$STUDIENSEMESTER.' ) ) ORDER BY "LastAction" DESC'; diff --git a/application/views/system/infocenter/logs.php b/application/views/system/infocenter/logs.php index de97d5055..8005bf4f7 100644 --- a/application/views/system/infocenter/logs.php +++ b/application/views/system/infocenter/logs.php @@ -1,19 +1,19 @@ -
+
p->t('lehre','lehrveranstaltung');?>p->t('lehre','kurzbz');?>p->t('lehre','semester');?>p->t('lehre','lehrform');?> p->t('lehre','ects');?>p->t('lehre','sws');?>p->t('lehre','pflichtfach');?>p->t('lehre','zeugnis');?> p->t('lehre','note');?>
+ +
p->t('lehre','lehrveranstaltung');?>p->t('lehre','kurzbz');?>p->t('lehre','semester');?>p->t('lehre','lehrform');?> p->t('lehre','ects');?>p->t('lehre','sws');?>p->t('lehre','pflichtfach');?>p->t('lehre','zeugnis');?> p->t('lehre','note');?>
- - - - - - - - - - - - - - - - +
p->t('global', 'datum')) ?>p->t('global', 'aktivitaet')) ?>User
zeitpunkt), 'd.m.Y H:i:s') ?>logdata->name) ? $log->logdata->name : '' ?>insertvon ?>
+ + + + + + + + + + + + + + + +
p->t('global', 'datum')) ?>p->t('global', 'aktivitaet')) ?>User
zeitpunkt), 'd.m.Y H:i:s') ?>logdata->name) ? $log->logdata->name : '' ?>insertvon ?>
\ No newline at end of file diff --git a/application/views/system/messages/messageList.php b/application/views/system/infocenter/messageList.php similarity index 97% rename from application/views/system/messages/messageList.php rename to application/views/system/infocenter/messageList.php index d666e32fe..18b859314 100644 --- a/application/views/system/messages/messageList.php +++ b/application/views/system/infocenter/messageList.php @@ -1,37 +1,37 @@ - 0; -$widthColumn = $msgExists === true ? 8 : 12; -?> -
- - - - - - - - - - - - - - - - - - - - - -
p->t('global','gesendetAm')) ?>p->t('global','sender')) ?>p->t('global','empfaenger')) ?>p->t('global','betreff')) ?>p->t('global','gelesenAm')) ?>
insertamum) ? date_format(date_create($message->insertamum), 'd.m.Y H:i:s') : '' ?>sevorname.' '.$message->senachname ?>revorname.' '.$message->renachname ?>subject ?>statusamum) ? date_format(date_create($message->statusamum), 'd.m.Y H:i:s') : '' ?>
-
- -
-
-
-
- -
-
- + 0; +$widthColumn = $msgExists === true ? 8 : 12; +?> +
+ + + + + + + + + + + + + + + + + + + + + +
p->t('global','gesendetAm')) ?>p->t('global','sender')) ?>p->t('global','empfaenger')) ?>p->t('global','betreff')) ?>p->t('global','gelesenAm')) ?>
insertamum) ? date_format(date_create($message->insertamum), 'd.m.Y H:i:s') : '' ?>sevorname.' '.$message->senachname ?>revorname.' '.$message->renachname ?>subject ?>statusamum) ? date_format(date_create($message->statusamum), 'd.m.Y H:i:s') : '' ?>
+
+ +
+
+
+
+ +
+
+ diff --git a/application/views/system/infocenter/notizen.php b/application/views/system/infocenter/notizen.php index 13f7bb6e1..b28f7939a 100644 --- a/application/views/system/infocenter/notizen.php +++ b/application/views/system/infocenter/notizen.php @@ -1,20 +1,20 @@ - - - - - - - - - - - - - - - - - - +
p->t('global', 'datum')) ?>p->t('global', 'notiz')) ?>User
insertamum), 'd.m.Y H:i:s') ?>titel) ?>verfasser_uid ?>
+ + + + + + + + + + + + + + + + +
p->t('global', 'datum')) ?>p->t('global', 'notiz')) ?>User
insertamum), 'd.m.Y H:i:s') ?>titel) ?>verfasser_uid ?>
\ No newline at end of file diff --git a/application/views/system/infocenter/stammdaten.php b/application/views/system/infocenter/stammdaten.php index 2b481692e..a80439bfe 100644 --- a/application/views/system/infocenter/stammdaten.php +++ b/application/views/system/infocenter/stammdaten.php @@ -113,7 +113,7 @@
-
+  p->t('ui','nachrichtSenden'); ?> diff --git a/application/views/system/logs/logsViewer.php b/application/views/system/logs/logsViewer.php new file mode 100644 index 000000000..96790b479 --- /dev/null +++ b/application/views/system/logs/logsViewer.php @@ -0,0 +1,47 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Logs viewer', + 'jquery' => true, + 'jqueryui' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'sbadmintemplate' => true, + 'tablesorter' => true, + 'ajaxlib' => true, + 'filterwidget' => true, + 'navigationwidget' => true, + 'phrases' => array( + 'global' => array('mailAnXversandt'), + 'ui' => array('bitteEintragWaehlen') + ), + 'customCSSs' => 'public/css/sbadmin2/tablesort_bootstrap.css', + 'customJSs' => array('public/js/bootstrapper.js') + ) + ); +?> + + +
+ + widgetlib->widget('NavigationWidget'); ?> + +
+
+
+
+ +
+
+
+ load->view('system/logs/logsViewerData.php'); ?> +
+
+
+
+ + +load->view('templates/FHC-Footer'); ?> diff --git a/application/views/system/logs/logsViewerData.php b/application/views/system/logs/logsViewerData.php new file mode 100644 index 000000000..13a4207ab --- /dev/null +++ b/application/views/system/logs/logsViewerData.php @@ -0,0 +1,65 @@ + ' + SELECT wsl.webservicelog_id AS "LogId", + wsl.request_id AS "RequestId", + wsl.execute_time AS "ExecutionTime", + wsl.execute_user AS "ExecutedBy", + wsl.beschreibung AS "Description", + wsl.request_data AS "Data", + wsl.webservicetyp_kurzbz AS "WebserviceType" + FROM system.tbl_webservicelog wsl + ORDER BY wsl.execute_time DESC + ', + 'requiredPermissions' => 'admin', + 'datasetRepresentation' => 'tablesorter', + 'columnsAliases' => array( + 'Log id', + 'Request id', + 'Execution time', + 'Executed by', + 'Producer', + 'Data', + 'Webservice type' + ), + 'formatRow' => function($datasetRaw) { + + $datasetRaw->ExecutionTime = date_format(date_create($datasetRaw->ExecutionTime), 'd.m.Y H:i:s'); + + return $datasetRaw; + }, + 'markRow' => function($datasetRaw) { + + $mark = ''; + + if ($datasetRaw->RequestId == 'Cronjob error') + { + $mark = 'text-red'; + } + + if ($datasetRaw->RequestId == 'Cronjob info') + { + $mark = 'text-green'; + } + + if ($datasetRaw->RequestId == 'Cronjob warning') + { + $mark = 'text-orange'; + } + + if ($datasetRaw->RequestId == 'Cronjob debug') + { + $mark = 'text-info'; + } + + return $mark; + } + ); + + $filterWidgetArray['app'] = 'core'; + $filterWidgetArray['datasetName'] = 'logs'; + $filterWidgetArray['filter_id'] = $this->input->get('filter_id'); + + echo $this->widgetlib->widget('FilterWidget', $filterWidgetArray); +?> diff --git a/application/views/system/messages/ajaxRead.php b/application/views/system/messages/ajaxRead.php new file mode 100644 index 000000000..1ed1b7f40 --- /dev/null +++ b/application/views/system/messages/ajaxRead.php @@ -0,0 +1,61 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Read personal messages', + 'jquery' => true, + 'jqueryui' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'sbadmintemplate' => true, + 'momentjs' => true, + 'tabulator' => true, + 'ajaxlib' => true, + 'dialoglib' => true, + 'tinymce' => true, + 'phrases' => array('global', 'ui'), + 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/message.css'), + 'customJSs' => array('public/js/bootstrapper.js', 'public/js/messaging/read.js') + ) + ); +?> + + +
+ + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+ + + +load->view("templates/FHC-Footer"); ?> diff --git a/application/views/system/messages/ajaxWrite.php b/application/views/system/messages/ajaxWrite.php new file mode 100644 index 000000000..fe9b9e897 --- /dev/null +++ b/application/views/system/messages/ajaxWrite.php @@ -0,0 +1,100 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Write a new message', + 'jquery' => true, + 'jqueryui' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'sbadmintemplate' => true, + 'ajaxlib' => true, + 'dialoglib' => true, + 'tinymce' => true, + 'phrases' => array('global', 'ui'), + 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/message.css'), + 'customJSs' => array('public/js/bootstrapper.js', 'public/js/messaging/write.js') + ) + ); +?> + +
+
+
+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+   +
+ +
+
+
+
+
+
+ + + +
+ +
+ + p->t('ui', 'altRecipientNote'); ?> + +
+
+
+
+
+
+ +
+
+
+
+
+ + +load->view("templates/FHC-Footer"); ?> diff --git a/application/views/system/messages/ajaxWriteReply.php b/application/views/system/messages/ajaxWriteReply.php new file mode 100644 index 000000000..3721565e9 --- /dev/null +++ b/application/views/system/messages/ajaxWriteReply.php @@ -0,0 +1,101 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Reply to a message', + 'jquery' => true, + 'jqueryui' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'sbadmintemplate' => true, + 'ajaxlib' => true, + 'dialoglib' => true, + 'tinymce' => true, + 'phrases' => array('global', 'ui'), + 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/message.css'), + 'customJSs' => array('public/js/bootstrapper.js', 'public/js/messaging/writeReply.js') + ) + ); +?> + +
+
+
+
+
+ +
+
+
+
+
+ +
+
+ + + +
+
+
+
+
+
+ +
+   +
+ + + +
+
+
+
+
+
+ + +
+
+
+
+
+ + + + + + +
+
+
+
+
+ + +load->view("templates/FHC-Footer"); ?> diff --git a/application/views/system/messages/messageReplySent.php b/application/views/system/messages/htmlMessageSentError.php similarity index 59% rename from application/views/system/messages/messageReplySent.php rename to application/views/system/messages/htmlMessageSentError.php index 88fc945b0..90191fcf0 100644 --- a/application/views/system/messages/messageReplySent.php +++ b/application/views/system/messages/htmlMessageSentError.php @@ -2,12 +2,12 @@ $this->load->view( 'templates/FHC-Header', array( - 'title' => 'MessageSent', + 'title' => 'Message sent failure - Fehler beim Senden der Nachricht', 'jquery' => true, 'bootstrap' => true, 'fontawesome' => true, 'sbadmintemplate' => true, - 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/messageSent.css') + 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/message.css') ) ); ?> @@ -20,47 +20,31 @@
- +
- +
+
- Message sent successfully! + An error occurred while sending your message, please try later.
- Nachricht erfolgreich versandt! + Beim Senden Ihrer Nachricht ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut.
+
-
-
- - Thank you for your message. - - - We will get back to you shortly. - -
-
- - Herzlichen Dank für Ihre Nachricht. - - - Wir werden uns schnellstmöglich um Ihr Anliegen kümmern. - -
-

@@ -72,18 +56,12 @@ Sie können dieses Fenster schließen.
+
-
-
- Your InfoCenter@FHTW Team -
-
- Ihr InfoCenter@FHTW Team -
-
-
+
+

@@ -93,6 +71,7 @@

+
diff --git a/application/views/system/messages/messageSent.php b/application/views/system/messages/htmlMessageSentSuccess.php similarity index 92% rename from application/views/system/messages/messageSent.php rename to application/views/system/messages/htmlMessageSentSuccess.php index 674ccd5a0..48409a5f4 100644 --- a/application/views/system/messages/messageSent.php +++ b/application/views/system/messages/htmlMessageSentSuccess.php @@ -2,12 +2,12 @@ $this->load->view( 'templates/FHC-Header', array( - 'title' => 'MessageSent', + 'title' => 'Message sent successfully - Nachricht erfolgreich versandt!', 'jquery' => true, 'bootstrap' => true, 'fontawesome' => true, 'sbadmintemplate' => true, - 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/messageSent.css') + 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/message.css') ) ); ?> @@ -17,11 +17,6 @@
- -
@@ -79,11 +74,6 @@
- - -
diff --git a/application/views/system/messages/messageHTML.php b/application/views/system/messages/htmlRead.php similarity index 65% rename from application/views/system/messages/messageHTML.php rename to application/views/system/messages/htmlRead.php index 0ae6c3866..5413af9f4 100644 --- a/application/views/system/messages/messageHTML.php +++ b/application/views/system/messages/htmlRead.php @@ -1,75 +1,104 @@ - load->view( - 'templates/FHC-Header', - array( - 'title' => 'MessageSent', - 'jquery' => true, - 'bootstrap' => true, - 'fontawesome' => true, - 'sbadmintemplate' => true, - 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/messageReply.css') - ) - ); - ?> - -
-
-
-
-
- -
-
-
-
-
-
- subject; ?> -
-
- - - - - - - - - - - - - -
- From: - - vorname.' '.$sender->nachname; ?> -
- Subject: - - subject; ?> -
- Message: - - body; ?> -
-
- -
-
-
-
-
-
- - load->view("templates/FHC-Footer"); ?> \ No newline at end of file +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Read message - Lies die Nachricht', + 'jquery' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'sbadmintemplate' => true, + 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/message.css') + ) + ); +?> + +
+
+
+
+
+ +
+
+
+
+
+
+ + subject; ?> + +
+
+ + + + + + + + + + + + + +
+ + + p->t('ui', 'from')); ?>: + + + + + vorname.' '.$sender->nachname; ?> + +
+ + + p->t('global', 'betreff')); ?>: + + + + + subject; ?> + +
+ + + p->t('global', 'nachricht')); ?>: + + + + + body; ?> + +
+
+ +
+
+
+
+
+
+ + +load->view("templates/FHC-Footer"); ?> diff --git a/application/views/system/messages/htmlWriteReply.php b/application/views/system/messages/htmlWriteReply.php new file mode 100644 index 000000000..fa3390bfa --- /dev/null +++ b/application/views/system/messages/htmlWriteReply.php @@ -0,0 +1,93 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Reply to a message', + 'jquery' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'tinymce' => true, + 'sbadmintemplate' => true, + 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/message.css'), + 'customJSs' => array('public/js/bootstrapper.js', 'public/js/messaging/messageWriteReply.js') + ) + ); +?> + +
+
+
+
+
+ +
+
+ +
+
+
+ +
+
+ + + +
+
+
+
+
+
+ +
+   +
+ +
+
+
+
+
+
+ + +
+
+
+
+
+ +
+
+ + + + + + +
+
+
+ + +load->view("templates/FHC-Footer"); ?> diff --git a/application/views/system/messages/htmlWriteTemplate.php b/application/views/system/messages/htmlWriteTemplate.php new file mode 100644 index 000000000..b6876dc91 --- /dev/null +++ b/application/views/system/messages/htmlWriteTemplate.php @@ -0,0 +1,170 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Write a new message or reply using templates', + 'jquery' => true, + 'jqueryui' => true, + 'bootstrap' => true, + 'ajaxlib' => true, + 'fontawesome' => true, + 'tinymce' => true, + 'sbadmintemplate' => true, + 'dialoglib' => true, + 'widgets' => true, + 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/message.css'), + 'customJSs' => array('public/js/bootstrapper.js', 'public/js/messaging/messageWrite.js') + ) + ); +?> + +
+ + +load->view("templates/FHC-Footer"); ?> diff --git a/application/views/system/messages/messageForm.php b/application/views/system/messages/messageForm.php deleted file mode 100644 index d1436a492..000000000 --- a/application/views/system/messages/messageForm.php +++ /dev/null @@ -1,81 +0,0 @@ -
-
-
- -
-
- 1 && $i % 10 == 0) - { - echo '
'; - } - echo $receiver->Vorname." ".$receiver->Nachname."; "; - } - ?> -
-
-
-
-
-
- -
  - subject; - } - ?> -
- -
-
-
-
-
-
- -

On '.date_format(date_create($message->sent), 'd.m.Y H:i').' '.$receivers[0]->Vorname.' '.$receivers[0]->Nachname.' wrote:'.'
'; - $body .= '
'; - $body .= $message->body.'
'; - } - ?> - -
- -
-
- - -
-
- -
-
-
-
- -
-
\ No newline at end of file diff --git a/application/views/system/messages/messageWrite.php b/application/views/system/messages/messageWrite.php deleted file mode 100644 index 93caaf861..000000000 --- a/application/views/system/messages/messageWrite.php +++ /dev/null @@ -1,183 +0,0 @@ -load->view( - 'templates/FHC-Header', - array( - 'title' => 'Write a message', - 'jquery' => true, - 'jqueryui' => true, - 'bootstrap' => true, - 'ajaxlib' => true, - 'fontawesome' => true, - 'tinymce' => true, - 'sbadmintemplate' => true, - 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/messageWrite.css'), - 'customJSs' => array('public/js/bootstrapper.js', 'public/js/messaging/messageWrite.js') - ) -); -?> - -
- - -load->view("templates/FHC-Footer"); ?> diff --git a/application/views/system/messages/messageWriteReply.php b/application/views/system/messages/messageWriteReply.php deleted file mode 100644 index 344871b2d..000000000 --- a/application/views/system/messages/messageWriteReply.php +++ /dev/null @@ -1,63 +0,0 @@ -load->view( - 'templates/FHC-Header', - array( - 'title' => 'MessageReply', - 'jquery' => true, - 'bootstrap' => true, - 'fontawesome' => true, - 'tinymce' => true, - 'sbadmintemplate' => true, - 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/messageWrite.css'), - 'customJSs' => array('public/js/bootstrapper.js', 'public/js/messaging/messageWriteReply.js') - ) -); -?> - - -
-
-
-
-
- -
-
-
- load->view('system/messages/messageForm.php'); - - for ($i = 0; $i < count($receivers); $i++) - { - $receiver = $receivers[$i]; - $receiverid = $receiver->person_id; - $fieldname = 'persons[]'; - - echo ''."\n"; - } - ?> - - - - - - - -
-
-
-
- - -load->view("templates/FHC-Footer"); ?> diff --git a/application/views/system/phrases/phrases.php b/application/views/system/phrases/phrases.php index 2409fcc83..f884cd04e 100644 --- a/application/views/system/phrases/phrases.php +++ b/application/views/system/phrases/phrases.php @@ -1,20 +1,20 @@ - - - - - VileSci - Phrasen - - - - - - - - <body bgcolor="#FFFFFF"> - This application works only with a frames-enabled browser.<br /> - <a href="PhrasesList">Use without frames</a> - </body> - - - - + + + + + VileSci - Phrasen + + + + + + + + <body bgcolor="#FFFFFF"> + This application works only with a frames-enabled browser.<br /> + <a href="PhrasesList">Use without frames</a> + </body> + + + + diff --git a/application/views/system/phrases/phrasesEdit.php b/application/views/system/phrases/phrasesEdit.php index d967dee83..19710b957 100644 --- a/application/views/system/phrases/phrasesEdit.php +++ b/application/views/system/phrases/phrasesEdit.php @@ -1,17 +1,17 @@ -load->view('templates/header', array('title' => 'PhrasesEdit')); -?> -
-
-

Phrase: phrase_id; ?>

-
- Bezeichnung: - - -
- -
-
- - - +load->view('templates/header', array('title' => 'PhrasesEdit')); +?> +
+
+

Phrase: phrase_id; ?>

+
+ Bezeichnung: + + +
+ +
+
+ + + diff --git a/application/views/system/phrases/phrasesinhaltList.php b/application/views/system/phrases/phrasesinhaltList.php index f212d440f..5f496a503 100644 --- a/application/views/system/phrases/phrasesinhaltList.php +++ b/application/views/system/phrases/phrasesinhaltList.php @@ -1,54 +1,54 @@ -load->view('templates/header', array('title' => 'PhrasenInhaltList', 'tablesort' => true, 'tableid' => 't1', 'headers' => '5:{sorter:false}')); -?> - -
-
-

Phrase Inhalt -

-
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
IDSpracheOrgEinheitOrgFormTextBeschreibung
phrasentext_id; ?>sprache; ?>orgeinheit_kurzbz; ?>orgform_kurzbz; ?>text; ?>description; ?>edit - delete -
-
-
- - -load->view('templates/footer'); -?> +load->view('templates/header', array('title' => 'PhrasenInhaltList', 'tablesort' => true, 'tableid' => 't1', 'headers' => '5:{sorter:false}')); +?> + +
+
+

Phrase Inhalt -

+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
IDSpracheOrgEinheitOrgFormTextBeschreibung
phrasentext_id; ?>sprache; ?>orgeinheit_kurzbz; ?>orgform_kurzbz; ?>text; ?>description; ?>edit + delete +
+
+
+ + +load->view('templates/footer'); +?> diff --git a/application/views/system/vorlage/templates.php b/application/views/system/vorlage/templates.php index c2130c267..7767962ce 100644 --- a/application/views/system/vorlage/templates.php +++ b/application/views/system/vorlage/templates.php @@ -1,20 +1,20 @@ - - - - - VileSci - Vorlage - - - - - - - - <body bgcolor="#FFFFFF"> - This application works only with a frames-enabled browser.<br /> - <a href="VorlageList">Use without frames</a> - </body> - - - - + + + + + VileSci - Vorlage + + + + + + + + <body bgcolor="#FFFFFF"> + This application works only with a frames-enabled browser.<br /> + <a href="VorlageList">Use without frames</a> + </body> + + + + diff --git a/application/views/system/vorlage/templatetextPreview.php b/application/views/system/vorlage/templatetextPreview.php index 2f53868a9..1f5b6948d 100644 --- a/application/views/system/vorlage/templatetextPreview.php +++ b/application/views/system/vorlage/templatetextPreview.php @@ -1,3 +1,3 @@ - \ No newline at end of file diff --git a/application/views/templates/FHC-Header.php b/application/views/templates/FHC-Header.php index 43112dd7b..5eec10f43 100644 --- a/application/views/templates/FHC-Header.php +++ b/application/views/templates/FHC-Header.php @@ -18,6 +18,7 @@ $addons = isset($addons) ? $addons : false; $ajaxlib = isset($ajaxlib) ? $ajaxlib : false; $bootstrap = isset($bootstrap) ? $bootstrap : false; + $captcha = isset($captcha) ? $captcha : false; $dialoglib = isset($dialoglib) ? $dialoglib : false; $filterwidget = isset($filterwidget) ? $filterwidget : false; $fontawesome = isset($fontawesome) ? $fontawesome : false; @@ -25,11 +26,15 @@ $jqueryui = isset($jqueryui) ? $jqueryui : false; $jquerycheckboxes = isset($jquerycheckboxes) ? $jquerycheckboxes : false; $jquerytreetable = isset($jquerytreetable) ? $jquerytreetable : false; + $momentjs = isset($momentjs) ? $momentjs : false; $navigationwidget = isset($navigationwidget) ? $navigationwidget : false; $pivotui = isset($pivotui) ? $pivotui : false; $sbadmintemplate = isset($sbadmintemplate) ? $sbadmintemplate : false; $tablesorter = isset($tablesorter) ? $tablesorter : false; + $tablewidget = isset($tablewidget) ? $tablewidget : false; + $tabulator = isset($tabulator) ? $tabulator : false; $tinymce = isset($tinymce) ? $tinymce : false; + $widgets = isset($widgets) ? $widgets : false; ?> @@ -60,10 +65,7 @@ if ($fontawesome === true) generateCSSsInclude('vendor/components/font-awesome/css/font-awesome.min.css'); // PivotUI CSS - if ($pivotui === true) - { - generateCSSsInclude('vendor/nicolaskruchten/pivottable/dist/pivot.min.css'); - } + if ($pivotui === true) generateCSSsInclude('vendor/nicolaskruchten/pivottable/dist/pivot.min.css'); // SB Admin 2 template CSS if ($sbadmintemplate === true) @@ -72,6 +74,9 @@ generateCSSsInclude('vendor/BlackrockDigital/startbootstrap-sb-admin-2/dist/css/sb-admin-2.min.css'); } + // Securimage CSS + if ($captcha === true) generateCSSsInclude('vendor/dapphp/securimage/securimage.css'); + // Table sorter CSS if ($tablesorter === true) { @@ -79,6 +84,16 @@ generateCSSsInclude('vendor/mottie/tablesorter/dist/css/jquery.tablesorter.pager.min.css'); } + // Tabulator CSS + if ($tabulator === true) + { + generateCSSsInclude('vendor/olifolkerd/tabulator/dist/css/bootstrap/tabulator_bootstrap.min.css'); + generateCSSsInclude('public/css/Tabulator.css'); + } + + // Tinymce CSS + if ($tinymce === true) generateCSSsInclude('public/css/TinyMCE.css'); + // -------------------------------------------------------------------------------------------------------- // From public folder @@ -94,9 +109,13 @@ // NavigationWidget CSS if ($navigationwidget === true) generateCSSsInclude('public/css/NavigationWidget.css'); + // HTML Widget CSS + if ($widgets === true) generateCSSsInclude('public/css/Widgets.css'); + // Eventually required CSS generateCSSsInclude($customCSSs); // Eventually required CSS + // -------------------------------------------------------------------------------------------------------- // Javascripts @@ -122,34 +141,14 @@ } // jQuery checkboxes - if ($jquerycheckboxes === true) - { - generateJSsInclude('vendor/rmariuzzo/jquery-checkboxes/dist/jquery.checkboxes-1.0.7.min.js'); - } - - // Bootstrap JS - if ($bootstrap === true) generateJSsInclude('vendor/twbs/bootstrap/dist/js/bootstrap.min.js'); - + // NOTE: keep it after jQuery includes + if ($jquerycheckboxes === true) generateJSsInclude('vendor/rmariuzzo/jquery-checkboxes/dist/jquery.checkboxes-1.0.7.min.js'); // jQuery treetable // NOTE: keep it after jQuery includes if ($jquerytreetable === true) generateJSsInclude('vendor/ludo/jquery-treetable/jquery.treetable.js'); - // PivotUI CSS - if ($pivotui === true) - { - generateJSsInclude('vendor/nicolaskruchten/pivottable/dist/pivot.min.js'); - } - - // Table sorter JS - if ($tablesorter === true) - { - generateJSsInclude('vendor/mottie/tablesorter/dist/js/jquery.tablesorter.min.js'); - generateJSsInclude('vendor/mottie/tablesorter/dist/js/jquery.tablesorter.widgets.min.js'); - generateJSsInclude('vendor/mottie/tablesorter/dist/js/extras/jquery.tablesorter.pager.min.js'); - } - - // Tinymce JS - if ($tinymce === true) generateJSsInclude('vendor/tinymce/tinymce/tinymce.min.js'); + // Bootstrap JS + if ($bootstrap === true) generateJSsInclude('vendor/twbs/bootstrap/dist/js/bootstrap.min.js'); // SB Admin 2 template JS if ($sbadmintemplate === true) @@ -160,6 +159,38 @@ generateBackwardCompatibleJSMsIe('vendor/scottjehl/Respond/dest/respond.min.js'); } + // Securimage JS + if ($captcha === true) generateJSsInclude('vendor/dapphp/securimage/securimage.js'); + + // Moment JS + if ($momentjs === true) + { + generateJSsInclude('vendor/moment/momentjs/min/moment.min.js'); + generateJSsInclude('vendor/moment/momentjs/locale/de-at.js'); + generateJSsInclude('vendor/moment/momentjs/locale/en-ie.js'); + } + + // PivotUI JS + if ($pivotui === true) generateJSsInclude('vendor/nicolaskruchten/pivottable/dist/pivot.min.js'); + + // Table sorter JS + if ($tablesorter === true) + { + generateJSsInclude('vendor/mottie/tablesorter/dist/js/jquery.tablesorter.min.js'); + generateJSsInclude('vendor/mottie/tablesorter/dist/js/jquery.tablesorter.widgets.min.js'); + generateJSsInclude('vendor/mottie/tablesorter/dist/js/extras/jquery.tablesorter.pager.min.js'); + } + + // Tabulator JS + if ($tabulator === true) + { + generateJSsInclude('vendor/olifolkerd/tabulator/dist/js/tabulator.min.js'); + generateJSsInclude('vendor/olifolkerd/tabulator/dist/js/jquery_wrapper.min.js'); + } + + // Tinymce JS + if ($tinymce === true) generateJSsInclude('vendor/tinymce/tinymce/tinymce.min.js'); + // -------------------------------------------------------------------------------------------------------- // From public folder @@ -179,6 +210,9 @@ // PhrasesLib JS if ($phrases != null) generateJSsInclude('public/js/PhrasesLib.js'); + // TableWidget JS + if ($tablewidget === true) generateJSsInclude('public/js/TableWidget.js'); + // Load addon hooks JS // NOTE: keep it as the latest but one if ($addons === true) generateAddonsJSsInclude($calledPath.'/'.$calledMethod); diff --git a/application/views/templates/header.php b/application/views/templates/header.php index 063351e07..fa2cc127a 100644 --- a/application/views/templates/header.php +++ b/application/views/templates/header.php @@ -18,28 +18,26 @@ isset($title) ? $title = 'VileSci - '.$title : $title = 'VileSci'; !isset($widgetsCSS) ? $widgetsCSS = false : $widgetsCSS = $widgetsCSS; !isset($datepicker) ? $datepicker = false : $datepicker = $datepicker; -if ($tablesort || $jquery_checkboxes || $jquery_custom) - $jqueryV1 = true; +if ($tablesort || $jquery_checkboxes || $jquery_custom) $jqueryV1 = true; -if($datepicker) - $jqueryui = true; +if($datepicker) $jqueryui = true; -if($jqueryui) - $jqueryV2 = true; +if($jqueryui) $jqueryV2 = true; -if($jqueryV1 && $jqueryV2) - show_error("Two JQuery versions used: composer and include folder version"); +if($jqueryV1 && $jqueryV2) show_error("Two JQuery versions used: composer and include folder version"); ?> + <?php echo $title; ?> - + + - + @@ -62,7 +60,7 @@ if($jqueryV1 && $jqueryV2) - + @@ -99,17 +97,21 @@ if($jqueryV1 && $jqueryV2) + + + + diff --git a/application/views/templates/mailHTML.php b/application/views/templates/mailHTML.php index c2e072f68..32d544c5a 100644 --- a/application/views/templates/mailHTML.php +++ b/application/views/templates/mailHTML.php @@ -1,12 +1,12 @@ - This is not the email template, this is a tribute + Notification of personal message reception
diff --git a/application/views/templates/mailTXT.php b/application/views/templates/mailTXT.php index cd55aeb06..09634e6ae 100644 --- a/application/views/templates/mailTXT.php +++ b/application/views/templates/mailTXT.php @@ -1,3 +1,7 @@ -Follow the following link to read the message. +Notification of personal message reception -{href} \ No newline at end of file +A new message is available + +Click here to view the message + +{href} diff --git a/application/views/templates/vilesci.php b/application/views/templates/vilesci.php index 0d55734c7..4f54a9dc8 100644 --- a/application/views/templates/vilesci.php +++ b/application/views/templates/vilesci.php @@ -1,42 +1,42 @@ - - - - <?php echo $this->template->title->default("Default title"); ?> - - - - template->meta; ?> - template->stylesheet; ?> - - - -template->widget("navigation", array('title' => 'Project name')); -?> - -
- - template->content; - ?> - -
- -
-

- template->footer->prepend("© Special Company 2012 - "); - ?> -

-
- -
- - -template->javascript; ?> - - + + + + <?php echo $this->template->title->default("Default title"); ?> + + + + template->meta; ?> + template->stylesheet; ?> + + + +template->widget("navigation", array('title' => 'Project name')); +?> + +
+ + template->content; + ?> + +
+ +
+

+ template->footer->prepend("© Special Company 2012 - "); + ?> +

+
+ +
+ + +template->javascript; ?> + + \ No newline at end of file diff --git a/application/views/widgets/dropdown.php b/application/views/widgets/dropdown.php index c1bdbf5c8..d9faf1978 100644 --- a/application/views/widgets/dropdown.php +++ b/application/views/widgets/dropdown.php @@ -11,7 +11,7 @@ $align = "valign-top"; } ?> -
+