Compare commits

..

64 Commits

Author SHA1 Message Date
ma0048 8ef418e5c5 abfrage is_array hinzugefuegt 2025-07-31 09:12:16 +02:00
Harald Bamberger c89b88ec1b prevent loading huge list of lvs when deleting an lv 2025-07-11 17:46:54 +02:00
Harald Bamberger 2262169699 filter component set default height only if no height attribute is set in tabulatoroptions. remove reactivedata default setting and old todo comments 2025-07-07 15:47:34 +02:00
kindlm 411fd8d056 Merge remote-tracking branch 'origin/master' 2025-07-07 14:25:47 +02:00
kindlm ca9eea6134 Merge branch 'TesttoolAdminOptimierungen' 2025-07-07 14:25:26 +02:00
kindlm b1ab0ddf18 Zeilenumbruch, wenn Fragen-Liste zu lang 2025-07-07 14:23:59 +02:00
Harald Bamberger cfe76e09b1 AntragJob StglSammelmail an alle Stgleiter senden 2025-07-07 11:47:06 +02:00
kindlm d47fd105ed Merge remote-tracking branch 'origin/master' 2025-07-03 17:37:27 +02:00
kindlm a0e4c3d93b GUI-Optimierung Testtool-Admin Seite
- Vorschau vs. Derzeit
- Tab-Zeichen wird bei Tab-Taste eingefügt
- Parse-Error wird bei nicht-wohlgeformtem XML angezeigt
- Button um MathML größer anzuzeigen
2025-07-03 17:37:16 +02:00
Harald Bamberger 014a034ce8 add VB function to get last vb stunden before altersteilzeit 2025-07-03 14:53:53 +02:00
Andreas Österreicher d64f5610c9 Merge branch 'feature-55989/micro_degree_vorlage_im_fas_hinterlegen' 2025-06-26 08:13:27 +02:00
Andreas Österreicher 444f7aec48 Merge branch 'master' into feature-55989/micro_degree_vorlage_im_fas_hinterlegen 2025-06-26 08:12:13 +02:00
Andreas Österreicher 4dbffc3527 Projektliste zieht die Pflichtpuase nicht mehr automatisch ab wenn keine
Pause manuell gebucht wurde. (Task 62601)
2025-06-25 17:48:09 +02:00
kindlm 45b9bae0b0 Merge remote-tracking branch 'origin/master' 2025-06-11 13:40:01 +02:00
kindlm 77ccfa46de Task #62440 Ampelsystem Benutzercount 2025-06-11 13:39:50 +02:00
Andreas Österreicher a52fcf1570 Merge branch 'feature-61601/Issue_Liste_hartcoded_eingeschraenkt' 2025-05-26 13:00:23 +02:00
Alexei Karpenko 5d241b050a issue list: renamed config 2025-05-26 11:16:50 +02:00
Alexei Karpenko 660f195c57 issue list: removed empty space and removed const which was moved to config 2025-05-26 11:03:33 +02:00
Andreas Österreicher 9b0e0fe135 Merge branch 'feature-61751/infocenter_absage_fuer_alle' 2025-05-26 10:59:38 +02:00
Andreas Österreicher 867afa4411 Merge branch 'master' into feature-61751/infocenter_absage_fuer_alle 2025-05-26 10:41:40 +02:00
Alexei Karpenko 94f0d43c4a issues config: removed empty lines 2025-05-23 09:59:13 +02:00
Alexei Karpenko 80faf92dc2 made issue list configurable (apps, status, functions) 2025-05-22 18:41:26 +02:00
Cristina c3e978b56e Adapted Input.js radio/checkbox label to accept HTML 2025-05-21 18:10:03 +02:00
Cristina 7e83df51a8 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2025-05-21 18:05:40 +02:00
Andreas Österreicher d677cee1f9 Merge branch 'feature-56330/Digi-Anw-Feedback' 2025-05-21 15:27:31 +02:00
Andreas Österreicher 8786b60c4c Merge branch 'master' into feature-56330/Digi-Anw-Feedback 2025-05-21 14:11:50 +02:00
Andreas Österreicher 9b9351fe9b Merge branch 'bug-62088/dummy_std_beim_reinziehen_im_fas_zu_einer_lv_kommt_eine_fehlermeldung_130_std_und_zuordnung_funktioniert_nicht' 2025-05-21 10:49:49 +02:00
ma0048 02701dc0c5 fixed bug stundengrenze hinweis beim hinzufuegen eines dummy lektors 2025-05-21 10:47:55 +02:00
Harald Bamberger e9a373afb8 Merge branch 'feature-61758/stv_kontakte_get_funktionen_null_abfangen' 2025-05-21 07:11:18 +02:00
Harald Bamberger 1222d33e6e Merge branch 'master' into feature-61758/stv_kontakte_get_funktionen_null_abfangen 2025-05-21 07:10:47 +02:00
Andreas Österreicher 2db7f812ab Fehlerkurzbz korrigiert 2025-05-20 11:31:28 +02:00
Andreas Österreicher 8b89d6f1cb Merge branch 'feature-48553/UHSTAT_Meldung_fuer_Privatuniversitaeten' 2025-05-20 11:11:39 +02:00
Harald Bamberger 310bd08648 Merge branch 'feature-40430/updateamum_von_im_AntragLib' 2025-05-19 10:51:05 +02:00
Harald Bamberger bc4514b2a0 Merge branch 'master' into feature-40430/updateamum_von_im_AntragLib 2025-05-19 10:29:28 +02:00
Harald Bamberger 3c08bc12cd Merge branch 'feature-61748/FHC-Alert-Plugin_EMail-Address' 2025-05-14 09:20:47 +02:00
ma0048 6e56de1790 null werte abgefangen 2025-05-14 08:33:25 +02:00
ma0048 2417d1549e absage bewerbung abgeschickt beide fuer einzelne studiengaenge ermoeglicht 2025-05-14 08:12:47 +02:00
Andreas Österreicher a72dcdf8b0 Merge branch 'bug-61306/addfaktor_entfernen' 2025-05-13 15:31:20 +02:00
ma0048 419341f496 absage fuer alle und rueckstellung ueber infocenter uebersicht 2025-05-12 12:53:16 +02:00
Harald Bamberger 4bceddcc82 add systemerror_mailto ci config, render systemerror_mailto to FHC_JS_DATA_STORAGE_OBJECT, use FHC_JS_DATA_STORAGE_OBJECT.systemerror_mailto in FhcAlert Plugins 2025-05-09 13:58:14 +02:00
Andreas Österreicher 7030d5b822 Merge branch 'feature-54827/internationalisierungsmassnahmen_optimierungen' 2025-05-05 11:32:18 +02:00
Andreas Österreicher 6dfa7089e7 Merge branch 'master' into feature-54827/internationalisierungsmassnahmen_optimierungen 2025-05-05 11:08:25 +02:00
Johann Hoffmann 47917e42c3 compare datetime timestamp for n-workdays ago calculation; more eager check on change of kontrollzeiten/termine if they match a termin; added missing phrase; fetch uploaddatum in same format as von/bis for entschuldigungen so date headerfilter can work as intended; zugangscode zeitlich abgelaufen show error message; 2025-04-17 12:07:54 +02:00
Johann Hoffmann 3f607ec241 phrasen 2025-04-15 18:03:51 +02:00
Johann Hoffmann 5abc48f568 Merge branch 'master' into feature-56330/Digi-Anw-Feedback 2025-04-15 17:56:31 +02:00
ma0048 1888c51a48 master gemerged
phrase bugfix
2025-04-15 11:09:59 +02:00
ma0048 ad93a0a84c Merge branch 'refs/heads/master' into feature-54827/internationalisierungsmassnahmen_optimierungen 2025-04-15 11:09:05 +02:00
Johann Hoffmann 6b6ec311c7 Merge branch 'master' into feature-56330/Digi-Anw-Feedback 2025-04-14 15:23:31 +02:00
Johann Hoffmann 8218c915d5 anw phrasen 2025-04-14 15:14:49 +02:00
Johann Hoffmann 4ee239dd62 entschuldigung upload without file; changed dropdowns; 2025-04-11 15:53:18 +02:00
ma0048 bcc712e900 addfaktor beim hinzuefuegen einer lv entfernt 2025-04-09 14:27:37 +02:00
Cristina 8788cf17e2 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2025-04-09 12:14:51 +02:00
ma0048 f826c20949 lv_id beim zeugnis.rdf.php hinzugefuegt
auf die ersten 2 lvs im microdegree eingeschränkt
2025-04-04 08:42:20 +02:00
Alexei Karpenko b4b2d8da49 added UHSTAT issue resolvers, bugfix getuhstatdata: check for empty array 2025-03-30 23:38:35 +02:00
Johann Hoffmann ba806c13fb assistenz edit entschuldigung modal for editing von/bis date (on open excuse notes) & textarea for notiz - which is still limited to 255 characters; added student semester column to assistenz table; removed column width constraints & layout changed to fitData, persistence option is TRUE now; WIP von/bis/uplaoddate headerfilter; automatically send email to students on entschuldigungn status changed; added minimum time range for Kontrolle to be at least the length of 1 teaching unit(per config) - currently 45minutes; start new kontrolle modal more clearly shows when time & date values have been read from stundenplan; increased qr degeneration timer from 200 to 5000ms to avoid "missed" checkins due to network time; lektor can retrieve all entschuldigungen ranges & statuses of students when hovering their row; lektor can show anw qr window seperately now; into externalzuordnung admin/person_id fix in deleteEntschuldigung; moved fetch semesterinfo into global setup; fixed some vue template warnings; 2025-03-27 17:15:37 +01:00
Cristina 0113c9d97a Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2025-03-27 13:42:48 +01:00
ma0048 45b7a56c3a - zeugnis vorlage fuer micro degree 2025-03-24 14:00:14 +01:00
Cristina 92db886a9f Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2025-03-24 11:18:53 +01:00
Johann Hoffmann a3e22da633 calcEntschuldigungen minDate as workdays in config; updatevon/um anwCheckIn; Orgform dual in sancho mail; zusatz (d.d.i)/(d.d.o) & (o) auch wenn bis datum leer ist aber von bereits eingetragen 2025-03-20 17:21:42 +01:00
Alexei Karpenko fb2f8d5c53 added function for getting UHSTAT1 person data (centralizing...) 2025-03-20 14:41:28 +01:00
Cristina 19fdefc398 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2025-03-18 10:42:15 +01:00
ma0048 30c4245861 - international skills -> diplomasupp
- notenuebernahme mail
- student uebersicht ueberarbeitet
- phrases angepasst
2025-02-27 08:35:05 +01:00
ma0048 b079d22e8d - filter hinzugefuegt
- db index hinzugefuegt
- sqls optimiert
- diplomand wird nun auch angezeigt
2025-01-27 09:37:02 +01:00
cgfhtw c0e2cec556 s&d 2024-08-14 15:51:27 +02:00
59 changed files with 2180 additions and 708 deletions
+11
View File
@@ -0,0 +1,11 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
// apps for which issues should be displayed
$config['issues_list_apps'] = array('core', 'dvuh');
// functions which enable users to see issues
$config['issues_list_functions'] = array('ass');
// functions which enable users to see issues
$config['issues_list_status'] = array('Aufgenommener', 'Student', 'Incoming', 'Diplomand', 'Abbrecher', 'Unterbrecher', 'Absolvent');
+3 -1
View File
@@ -4,4 +4,6 @@ if (! defined('BASEPATH')) exit('No direct script access allowed');
// use vuejs dev version
$config['use_vuejs_dev_version'] = false;
// use bundled javascript
$config['use_bundled_javascript'] = false;
$config['use_bundled_javascript'] = false;
// systemerror_mailto use in FHC-Alert Plugin - if empty Link will not be rendered
$config['systemerror_mailto'] = '';
-7
View File
@@ -1,7 +0,0 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
// broaden the allowed URI characters just for tests
$config['permitted_uri_chars'] = 'a-z A-Z 0-9~%.:_\-';
// ensure we read REQUEST_URI
$config['uri_protocol'] = 'REQUEST_URI';
@@ -17,27 +17,6 @@
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* @SWG\Info(
* title="Bookmark API",
* version="1.0.0"
* )
*/
/**
* @SWG\Swagger(
* schemes={"https"},
* basePath="/fhcompletecis4/cis.php/api/frontend/v1/Bookmark/"
* )
*/
/**
* @SWG\SecurityScheme(
* securityDefinition="basicAuth",
* type="basic"
* )
*/
class Bookmark extends FHCAPI_Controller
{
@@ -52,7 +31,6 @@ class Bookmark extends FHCAPI_Controller
'delete' => self::PERM_LOGGED,
'insert' => self::PERM_LOGGED,
'update' => self::PERM_LOGGED,
'test_true' => self::PERM_LOGGED
]);
$this->load->model('dashboard/Bookmark_model', 'BookmarkModel');
@@ -70,21 +48,6 @@ class Bookmark extends FHCAPI_Controller
* gets the bookmarks associated to a user
* @access public
* @return void
* @SWG\Get(
* path="/getBookmarks",
* security={{"basicAuth":{}}},
* tags={"bookmarks"},
* summary="Get user's bookmarks",
* description="Returns all bookmarks associated with the authenticated user.",
* @SWG\Response(
* response=200,
* description="List of bookmarks"
* ),
* @SWG\Response(
* response=401,
* description="Unauthorized"
* )
* )
*/
public function getBookmarks()
{
@@ -100,31 +63,6 @@ class Bookmark extends FHCAPI_Controller
* deletes bookmark from associated user
* @access public
* @return void
* @SWG\Post(
* path="/delete/{bookmark_id}",
* security={{"basicAuth":{}}},
* tags={"bookmarks"},
* summary="Delete a bookmark",
* description="Deletes a bookmark if the user is the owner or an admin.",
* @SWG\Parameter(
* name="bookmark_id",
* in="path",
* required=true,
* type="integer"
* ),
* @SWG\Response(
* response=200,
* description="Bookmark deleted successfully"
* ),
* @SWG\Response(
* response=403,
* description="Forbidden - not the owner"
* ),
* @SWG\Response(
* response=404,
* description="Bookmark not found"
* )
* )
*/
public function delete($bookmark_id)
{
@@ -149,44 +87,6 @@ class Bookmark extends FHCAPI_Controller
* inserts new bookmark into the bookmark table
* @access public
* @return void
* @SWG\Post(
* path="/insert",
* security={{"basicAuth":{}}},
* tags={"bookmarks"},
* summary="Insert a new bookmark",
* @SWG\Parameter(
* name="body",
* in="body",
* required=true,
* @SWG\Schema(
* type="object",
* required={"url", "title"},
* @SWG\Property(
* property="url",
* type="string",
* example="https://github.com/swagger-api/swagger-codegen"
* ),
* @SWG\Property(
* property="title",
* type="string",
* example="Swagger Codegen"
* ),
* @SWG\Property(
* property="tag",
* type="string",
* example="API"
* )
* )
* ),
* @SWG\Response(
* response=201,
* description="Bookmark created"
* ),
* @SWG\Response(
* response=400,
* description="Validation error"
* )
* )
*/
public function insert()
{
@@ -209,47 +109,9 @@ class Bookmark extends FHCAPI_Controller
}
/**
* @SWG\Post(
* path="/update/{bookmark_id}",
* security={{"basicAuth":{}}},
* tags={"bookmarks"},
* summary="Update a bookmark",
* description="Updates a bookmark's URL and title for the given ID.",
* @SWG\Parameter(
* name="bookmark_id",
* in="path",
* required=true,
* type="integer",
* description="ID of the bookmark to update"
* ),
* @SWG\Parameter(
* name="body",
* in="body",
* required=true,
* @SWG\Schema(
* type="object",
* required={"url", "title"},
* @SWG\Property(
* property="url",
* type="string",
* example="https://updated-url.com"
* ),
* @SWG\Property(
* property="title",
* type="string",
* example="Updated Title"
* )
* )
* ),
* @SWG\Response(
* response=200,
* description="Bookmark updated"
* ),
* @SWG\Response(
* response=400,
* description="Validation error"
* )
* )
* updates bookmark in the bookmark table
* @access public
* @return void
*/
public function update($bookmark_id)
{
@@ -85,7 +85,10 @@ class Kontakt extends FHCAPI_Controller
|| $this->router->method == 'addNewBankverbindung'
) {
$person_id = current(array_slice($this->uri->rsegments, 2));
if (is_null($person_id) || !ctype_digit((string)$person_id))
$this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$this->checkPermissionsForPerson($person_id, $permsMa, $permsStud);
} elseif ($this->router->method == 'loadAddress'
|| $this->router->method == 'loadContact'
@@ -119,6 +122,9 @@ class Kontakt extends FHCAPI_Controller
$model = 'person/Bankverbindung_model';
}
if (!isset($id) || !ctype_digit((string)$id))
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$this->load->model($model, 'TempModel');
$result = $this->TempModel->load($id);
$data = $this->getDataOrTerminateWithError($result);
@@ -387,8 +393,11 @@ class Kontakt extends FHCAPI_Controller
$this->terminateWithSuccess(getData($result) ?: []);
}
public function getFirmen($searchString)
public function getFirmen($searchString = null)
{
if (is_null($searchString))
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$this->load->model('ressource/firma_model', 'FirmaModel');
$result = $this->FirmaModel->searchFirmen($searchString);
@@ -398,8 +407,11 @@ class Kontakt extends FHCAPI_Controller
$this->terminateWithSuccess($result ?: []);
}
public function getStandorte($searchString)
public function getStandorte($searchString = null)
{
if (is_null($searchString))
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$this->load->model('organisation/standort_model', 'StandortModel');
$result = $this->StandortModel->searchStandorte($searchString);
@@ -409,8 +421,11 @@ class Kontakt extends FHCAPI_Controller
$this->terminateWithSuccess($data);
}
public function getStandorteByFirma($firma_id)
public function getStandorteByFirma($firma_id = null)
{
if (is_null($firma_id) || !ctype_digit((string)$firma_id))
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$this->load->model('organisation/standort_model', 'StandortModel');
$result = $this->StandortModel->getStandorteByFirma($firma_id);
@@ -652,6 +667,9 @@ class Kontakt extends FHCAPI_Controller
$bic = $this->input->post('bic');
$blz = $this->input->post('blz');
$kontonr = $this->input->post('kontonr');
$iban = $this->input->post('iban');
$typ = $this->input->post('typ');
$verrechnung = $this->input->post('verrechnung');
$result = $this->BankverbindungModel->insert(
[
@@ -659,13 +677,13 @@ class Kontakt extends FHCAPI_Controller
'name' => $name,
'anschrift' => $anschrift,
'bic' => $bic,
'iban' => $_POST['iban'],
'iban' => $iban,
'blz' => $blz,
'kontonr' => $kontonr,
'insertvon' => 'uid',
'insertamum' => date('c'),
'typ' => $_POST['typ'],
'verrechnung' => $_POST['verrechnung'],
'typ' => $typ,
'verrechnung' => $verrechnung,
'ext_id' => $ext_id,
'oe_kurzbz' => $oe_kurzbz,
'orgform_kurzbz' => $orgform_kurzbz
+7 -4
View File
@@ -95,12 +95,15 @@ class AntragJob extends JOB_Controller
continue;
}
$leitung = current(getData($result));
if (!isset($stgLeitungen[$leitung->uid]))
$leitungen = getData($result);
foreach ($leitungen as $leitung)
{
$stgLeitungen[$leitung->uid] = [ 'Details' => $leitung, 'stgs' => [] ];
if (!isset($stgLeitungen[$leitung->uid]))
{
$stgLeitungen[$leitung->uid] = ['Details' => $leitung, 'stgs' => []];
}
$stgLeitungen[$leitung->uid]['stgs'][] = $antrag->studiengang_kz;
}
$stgLeitungen[$leitung->uid]['stgs'][] = $antrag->studiengang_kz;
$result = $this->StudierendenantragModel->getStgAndSem($antrag->studierendenantrag_id);
if (isError($result))
@@ -48,7 +48,9 @@ class IssueResolver extends IssueResolver_Controller
'CORE_PERSON_0001' => 'CORE_PERSON_0001',
'CORE_PERSON_0002' => 'CORE_PERSON_0002',
'CORE_PERSON_0003' => 'CORE_PERSON_0003',
'CORE_PERSON_0004' => 'CORE_PERSON_0004'
'CORE_PERSON_0004' => 'CORE_PERSON_0004',
'CORE_PERSON_0005' => 'CORE_PERSON_0005',
'CORE_PERSON_0006' => 'CORE_PERSON_0006'
);
// fehler which are resolved by the job the same way as they are produced
@@ -2375,16 +2375,50 @@ class InfoCenter extends Auth_Controller
if ($statusgrund === 'null' || $studiengang === 'null' || $abgeschickt === 'null' || empty($personen))
$this->terminateWithJsonError("Bitte füllen Sie alle Felder aus");
foreach($personen as $person)
if ($studiengang === 'all' && $abgeschickt === 'all')
{
$prestudent = $this->PrestudentModel->getPrestudentByStudiengangAndPerson($studiengang, $person, $studienSemester, $abgeschickt);
foreach($personen as $person)
{
$prestudenten = $this->PrestudentModel->getByPersonWithoutLehrgang($person, $studienSemester);
if (!hasData($prestudent))
continue;
if (!hasData($prestudenten))
continue;
$prestudentData = getData($prestudent);
$prestudentenData = getData($prestudenten);
foreach ($prestudentenData as $prestudent)
{
$this->saveAbsage($prestudent->prestudent_id, $statusgrund);
}
}
}
else
{
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
$this->StudienplanModel->addSelect('1');
$this->StudienplanModel->addJoin('lehre.tbl_studienordnung so', 'studienordnung_id');
$escaped = $this->StudienplanModel->db->escape(strtoupper($studiengang));
$this->StudienplanModel->db->where("UPPER(so.studiengangkurzbzlang || ':' || tbl_studienplan.orgform_kurzbz) = $escaped");
$this->StudienplanModel->addLimit(1);
$studiengangResult = $this->StudienplanModel->load();
if (hasData($studiengangResult))
{
foreach($personen as $person)
{
$prestudent = $this->PrestudentModel->getPrestudentByStudiengangAndPerson($studiengang, $person, $studienSemester, $abgeschickt, $abgeschickt === 'all');
if (!hasData($prestudent))
continue;
$prestudentData = getData($prestudent);
$this->saveAbsage($prestudentData[0]->prestudent_id, $statusgrund);
}
}
else
$this->terminateWithJsonError("Falschen Studiengang übergeben!");
$this->saveAbsage($prestudentData[0]->prestudent_id, $statusgrund);
}
$this->outputJsonSuccess("Success");
@@ -14,7 +14,8 @@ class Rueckstellung extends Auth_Controller
'get' => array('infocenter:r', 'lehre/zgvpruefung:r'),
'set' => array('infocenter:r', 'lehre/zgvpruefung:r'),
'delete' => array('infocenter:r', 'lehre/zgvpruefung:r'),
'getStatus' => array('infocenter:rw', 'lehre/zgvpruefung:rw')
'getStatus' => array('infocenter:rw', 'lehre/zgvpruefung:rw'),
'setForPersonen' => array('infocenter:rw', 'lehre/zgvpruefung:rw'),
)
);
@@ -79,7 +80,34 @@ class Rueckstellung extends Auth_Controller
$this->outputJson($result);
}
public function setForPersonen()
{
$personen = $this->input->post('personen');
$datum_bis = $this->input->post('datum_bis');
$status_kurzbz = $this->input->post('status_kurzbz');
foreach ($personen as $person)
{
$rueckstellung = $this->_ci->RueckstellungModel->loadWhere(array('person_id' => $person));
if (hasData($rueckstellung))
continue;
$result = $this->_ci->RueckstellungModel->insert(
array('person_id' => $person,
'status_kurzbz' => $status_kurzbz,
'datum_bis' => date_format(date_create($datum_bis), 'Y-m-d'),
'insertvon' => $this->_uid
)
);
if (isError($result))
$this->terminateWithJsonError(getError($result));
$this->_log($person, $status_kurzbz);
}
$this->outputJsonSuccess("Erfolgreich gespeichert!");
}
public function delete()
{
$person_id = $this->input->post('person_id');
@@ -6,7 +6,6 @@ class Issues extends Auth_Controller
{
private $_uid;
const FUNKTION_KURZBZ = 'ass'; // user having this funktion can see issues for oes assigned with this funktion
const BERECHTIGUNG_KURZBZ = 'system/issues_verwalten'; // user having this permission can see issues for oes assigned with this permission
public function __construct()
@@ -28,6 +27,9 @@ class Issues extends Auth_Controller
$this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
$this->load->model('system/Sprache_model', 'SpracheModel');
// load config
$this->load->config('issueList');
$this->loadPhrases(
array(
'global',
@@ -47,10 +49,12 @@ class Issues extends Auth_Controller
{
$oes_for_issues = $this->_getOesForIssues();
$language_index = $this->_getLanguageIndex();
$apps = $this->config->item('issues_list_apps');
$status = $this->config->item('issues_list_status');
$this->load->view(
'system/issues/issues',
array_merge($oes_for_issues, array('language_index' => $language_index))
array_merge($oes_for_issues, array('language_index' => $language_index, 'apps' => $apps, 'status' => $status))
);
}
@@ -121,6 +125,8 @@ class Issues extends Auth_Controller
$oe_kurzbz_for_funktion = array();
$benutzerfunktionRes = $this->BenutzerfunktionModel->getBenutzerFunktionByUid($this->_uid, null, date('Y-m-d'), date('Y-m-d'));
$functions = $this->config->item('issues_list_functions');
if (isError($benutzerfunktionRes))
show_error(getError($benutzerfunktionRes));
@@ -130,8 +136,8 @@ class Issues extends Auth_Controller
{
$all_funktionen_oe_kurzbz[$benutzerfunktion->oe_kurzbz][] = $benutzerfunktion->funktion_kurzbz;
// separate oes for the additional funktion which enables displaying issues
if ($benutzerfunktion->funktion_kurzbz == self::FUNKTION_KURZBZ)
// separate oes for the additional functions which enables displaying issues
if (in_array($benutzerfunktion->funktion_kurzbz, $functions))
{
$oe_kurzbz_for_funktion[] = $benutzerfunktion->oe_kurzbz;
@@ -95,6 +95,9 @@ function generateJSDataStorageObject($indexPage, $calledPath, $calledMethod)
}, $server_language);
$user_language = getUserLanguage();
$ci->load->config('javascript');
$systemerror_mailto = $ci->config->item('systemerror_mailto');
$FHC_JS_DATA_STORAGE_OBJECT = array(
'app_root' => APP_ROOT,
'ci_router' => $indexPage,
@@ -103,6 +106,7 @@ function generateJSDataStorageObject($indexPage, $calledPath, $calledMethod)
'server_languages' => $server_language,
'user_language' => $user_language,
'timezone' => date_default_timezone_get(),
'systemerror_mailto' => $systemerror_mailto,
);
$toPrint = "\n";
+7 -2
View File
@@ -77,7 +77,9 @@ class AntragLib
'studiensemester_kurzbz'=>$prestudentstatus->studiensemester_kurzbz,
'ausbildungssemester'=>$prestudentstatus->ausbildungssemester
], [
'statusgrund_id' => null
'statusgrund_id' => null,
'updateamum' => date('c'),
'updatevon' => $insertvon
]);
}
}
@@ -335,7 +337,10 @@ class AntragLib
'status_kurzbz'=>$prestudentstatus->status_kurzbz,
'studiensemester_kurzbz'=>$prestudentstatus->studiensemester_kurzbz,
'ausbildungssemester'=>$prestudentstatus->ausbildungssemester
], []);
], [
'updateamum' => $insertam,
'updatevon' => $insertvon
]);
if (isError($result))
{
$errors[] = getError($result);
@@ -13,7 +13,7 @@ class PlausicheckResolverLib
private $_ci; // ci instance
private $_extensionName; // name of extension
private $_codeLibMappings = []; // mappings for issues which explicitly defined resolver
private $_codeProducerLibMappings = []; // mappings for issues which are resolved as produced
private $_codeProducerLibMappings = []; // mappings for issues which are resolved with the same check as they are produced
public function __construct($params = null)
{
@@ -99,10 +99,11 @@ class PlausicheckResolverLib
$issueResolved = getData($issueResolvedRes) === true;
}
}
elseif (isset($this->_codeProducerLibMappings[$issue->fehlercode]))
elseif (isset($this->_codeProducerLibMappings[$issue->fehlercode])) // check if it is an issue without explicit resolver, "self-resolving"
{
$libName = $this->_codeProducerLibMappings[$issue->fehlercode];
// execute same check as used for issue production
$issueResolvedRes = $this->_ci->plausicheckproducerlib->producePlausicheckIssue(
$libName,
$issue->fehler_kurzbz,
@@ -0,0 +1,36 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Geburtsnation missing
*/
class CORE_PERSON_0005 implements IIssueResolvedChecker
{
public function checkIfIssueIsResolved($params)
{
if (!isset($params['issue_person_id']) || !is_numeric($params['issue_person_id']))
return error('Person Id missing, issue_id: '.$params['issue_id']);
$this->_ci =& get_instance(); // get code igniter instance
$this->_ci->load->model('person/Person_model', 'PersonModel');
// load geburtsnation for the given person
$this->_ci->PersonModel->addSelect('geburtsnation');
$personRes = $this->_ci->PersonModel->load($params['issue_person_id']);
if (isError($personRes)) return $personRes;
if (hasData($personRes))
{
// get person data
$personData = getData($personRes)[0];
// if geburtsnation present, issue is resolved
return success(!isEmptyString($personData->geburtsnation));
}
else
return success(false); // if no person found, not resolved
}
}
@@ -0,0 +1,37 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Geburtsnation missing
*/
class CORE_PERSON_0006 implements IIssueResolvedChecker
{
public function checkIfIssueIsResolved($params)
{
if (!isset($params['issue_person_id']) || !is_numeric($params['issue_person_id']))
return error('Person Id missing, issue_id: '.$params['issue_id']);
$this->_ci =& get_instance(); // get code igniter instance
$this->_ci->load->model('codex/Uhstat1daten_model', 'UhstatModel');
$personRes = $this->_ci->UhstatModel->getUHSTAT1PersonData([$params['issue_person_id']]);
if (isError($personRes)) return $personRes;
if (hasData($personRes))
{
// get person data
$personData = getData($personRes)[0];
// if person identification data present, issue is resolved
return success(
!isEmptyString($personData->ersatzkennzeichen)
|| (!isEmptyString($personData->vbpkAs) && !isEmptyString($personData->vbpkBf))
);
}
else
return success(false); // if no person found, not resolved
}
}
@@ -131,6 +131,11 @@ class VertragsbestandteilLib
return $this->VertragsbestandteilModel->getVertragsbestandteil($vertragsbestandteil_id);
}
public function fetchLastVertragsbestandteilStundenBeforeAltersteilzeit($dienstverhaeltnis_id)
{
return $this->VertragsbestandteilModel->getLastVertragsbestanteilStundenBeforeAltersteilzeit($dienstverhaeltnis_id);
}
public function storeDienstverhaeltnis(Dienstverhaeltnis $dv)
{
if( intval($dv->getDienstverhaeltnis_id()) > 0 )
@@ -11,4 +11,44 @@ class Uhstat1daten_model extends DB_Model
$this->dbTable = 'bis.tbl_uhstat1daten';
$this->pk = 'uhstat1daten_id';
}
/**
* Gets person data needed for sending as UHSTAT1 data.
* @param array $person_id_arr
* @param string $studiensemester
* @param array $status_kurzbz
* @return object success with prestudents or error
*/
public function getUHSTAT1PersonData($person_id_arr)
{
if (!isset($person_id_arr) || isEmptyArray($person_id_arr)) return success([]);
$params = array($person_id_arr);
$prstQry = "SELECT
DISTINCT ON (pers.person_id)
pers.person_id, uhstat_daten.uhstat1daten_id, pers.svnr, pers.ersatzkennzeichen, pers.geburtsnation,
uhstat_daten.mutter_geburtsstaat, uhstat_daten.mutter_bildungsstaat, uhstat_daten.mutter_geburtsjahr,
uhstat_daten.mutter_bildungmax, uhstat_daten.vater_geburtsstaat, uhstat_daten.vater_bildungsstaat,
uhstat_daten.vater_geburtsjahr, uhstat_daten.vater_bildungmax,
kzVbpkAs.inhalt AS \"vbpkAs\", kzVbpkBf.inhalt AS \"vbpkBf\"
FROM
public.tbl_person pers
JOIN public.tbl_prestudent ps USING (person_id)
JOIN public.tbl_studiengang stg USING (studiengang_kz)
JOIN bis.tbl_uhstat1daten uhstat_daten USING (person_id)
LEFT JOIN public.tbl_kennzeichen kzVbpkAs ON kzVbpkAs.kennzeichentyp_kurzbz = 'vbpkAs'AND kzVbpkAs.person_id = pers.person_id AND kzVbpkAs.aktiv
LEFT JOIN public.tbl_kennzeichen kzVbpkBf ON kzVbpkBf.kennzeichentyp_kurzbz = 'vbpkBf'AND kzVbpkBf.person_id = pers.person_id AND kzVbpkBf.aktiv
WHERE
ps.bismelden
AND stg.melderelevant
AND pers.person_id IN ?
ORDER BY
pers.person_id";
return $this->execReadOnlyQuery(
$prstQry,
$params
);
}
}
+28 -8
View File
@@ -677,7 +677,7 @@ class Prestudent_model extends DB_Model
));
}
public function getPrestudentByStudiengangAndPerson($studiengang, $person, $studienSemester, $abgeschickt)
public function getPrestudentByStudiengangAndPerson($studiengang, $person, $studienSemester, $abgeschickt, $ignoreAbgeschickt = false)
{
$query = "SELECT ps.prestudent_id
FROM public.tbl_prestudentstatus pss
@@ -687,22 +687,42 @@ class Prestudent_model extends DB_Model
JOIN lehre.tbl_studienordnung so USING(studienordnung_id)
WHERE ps.person_id = ?
AND UPPER(so.studiengangkurzbzlang || ':' || sp.orgform_kurzbz) = ?
AND pss.studiensemester_kurzbz = ?
AND";
AND pss.studiensemester_kurzbz = ?";
if ($abgeschickt === 'true')
$query .= " EXISTS";
else
$query .= " NOT EXISTS";
if (!$ignoreAbgeschickt)
{
$query .= "AND";
$query .= " (SELECT 1 FROM public.tbl_prestudentstatus spss
if ($abgeschickt === 'true')
$query .= " EXISTS";
else
$query .= " NOT EXISTS";
$query .= " (SELECT 1 FROM public.tbl_prestudentstatus spss
JOIN public.tbl_prestudent sps USING(prestudent_id)
WHERE sps.prestudent_id = ps.prestudent_id
AND spss.bewerbung_abgeschicktamum IS NOT NULL)";
}
return $this->execQuery($query, array($person, $studiengang, $studienSemester));
}
public function getByPersonWithoutLehrgang($person, $studienSemester)
{
$query = "SELECT DISTINCT(ps.prestudent_id)
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)
JOIN lehre.tbl_studienordnung so USING(studienordnung_id)
WHERE ps.person_id = ?
AND (sg.typ = 'b' OR sg.typ = 'm')
AND pss.studiensemester_kurzbz = ?";
return $this->execQuery($query, array($person, $studienSemester));
}
/**
* Gets förderrelevant flag for a prestudent, from prestudent, or, if not set on prestudent level, from studiengang
* @param int $prestudent_id
@@ -183,6 +183,46 @@ EOSQL;
return $vbcount[0]->overlappingvbs;
}
public function getLastVertragsbestanteilStundenBeforeAltersteilzeit($dienstverhaeltnis_id)
{
$sql = <<<EOATZSQL
select
*
from
hr.tbl_vertragsbestandteil vb
join
hr.tbl_vertragsbestandteil_stunden vbs USING(vertragsbestandteil_id)
where
vb.dienstverhaeltnis_id = ?
and (
vbs.teilzeittyp_kurzbz != 'altersteilzeit'
or
vbs.teilzeittyp_kurzbz is NULL
)
order by
vb.bis desc
limit 1
EOATZSQL;
$query = $this->execReadOnlyQuery($sql, array($dienstverhaeltnis_id));
$data = getData($query);
if ($data == null)
{
return null;
}
$vertragsbestandteil = null;
try
{
$vertragsbestandteil = VertragsbestandteilFactory::getVertragsbestandteil($data[0], true);
}
catch (Exception $ex)
{
echo $ex->getMessage() . "\n";
}
return $vertragsbestandteil;
}
/**
* Checks if sap sync table exists.
* @return bool
@@ -14,12 +14,13 @@
'navigationwidget' => true,
'dialoglib' => true,
'phrases' => array(
'infocenter' => array('statusAuswahl'),
'person' => array('vorname', 'nachname'),
'global' => array('mailAnXversandt'),
'ui' => array('bitteEintragWaehlen')
),
'customCSSs' => array('public/css/sbadmin2/tablesort_bootstrap.css', 'public/css/infocenter/infocenterPersonDataset.css'),
'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/infocenterPersonDataset.js')
'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/rueckstellung.js', 'public/js/infocenter/infocenterPersonDataset.js')
);
$this->load->view('templates/FHC-Header', $includesArray);
@@ -20,7 +20,7 @@
'ui' => array('bitteEintragWaehlen')
),
'customCSSs' => array('public/css/sbadmin2/tablesort_bootstrap.css', 'public/css/infocenter/infocenterPersonDataset.css'),
'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/infocenterPersonDataset.js')
'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/rueckstellung.js', 'public/js/infocenter/infocenterPersonDataset.js')
)
);
?>
@@ -20,7 +20,7 @@
'ui' => array('bitteEintragWaehlen')
),
'customCSSs' => array('public/css/sbadmin2/tablesort_bootstrap.css', 'public/css/infocenter/infocenterPersonDataset.css'),
'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/infocenterPersonDataset.js')
'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/rueckstellung.js', 'public/js/infocenter/infocenterPersonDataset.js')
)
);
?>
@@ -20,7 +20,7 @@
'ui' => array('bitteEintragWaehlen')
),
'customCSSs' => array('public/css/sbadmin2/tablesort_bootstrap.css', 'public/css/infocenter/infocenterPersonDataset.css'),
'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/infocenterPersonDataset.js')
'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/rueckstellung.js', 'public/js/infocenter/infocenterPersonDataset.js')
)
);
?>
@@ -20,7 +20,7 @@
'ui' => array('bitteEintragWaehlen')
),
'customCSSs' => array('public/css/sbadmin2/tablesort_bootstrap.css', 'public/css/infocenter/infocenterPersonDataset.css'),
'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/infocenterPersonDataset.js')
'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/rueckstellung.js', 'public/js/infocenter/infocenterPersonDataset.js')
)
);
?>
@@ -43,12 +43,15 @@
<td>
<select id="buergerschaft" disabled>
<?php
foreach ($all_nations as $nation)
if (is_array($all_nations))
{
$selected = '';
if ($nation->nation_code === $stammdaten->staatsbuergerschaft_code)
$selected = 'selected';
echo "<option value='". $nation->nation_code ."' " . $selected . ">". $nation->langtext . "</option>";
foreach ($all_nations as $nation)
{
$selected = '';
if ($nation->nation_code === $stammdaten->staatsbuergerschaft_code)
$selected = 'selected';
echo "<option value='". $nation->nation_code ."' " . $selected . ">". $nation->langtext . "</option>";
}
}
?>
</select>
@@ -61,12 +64,15 @@
?>
<select id="geschlecht" disabled>
<?php
foreach ($all_genders as $gender)
if (is_array($all_genders))
{
$selected = '';
if ($gender->geschlecht === $stammdaten->geschlecht)
$selected = 'selected';
echo "<option value='". $gender->geschlecht ."' " . $selected . ">". ucfirst($gender->bezeichnung_mehrsprachig[$language]) . "</option>";
foreach ($all_genders as $gender)
{
$selected = '';
if ($gender->geschlecht === $stammdaten->geschlecht)
$selected = 'selected';
echo "<option value='". $gender->geschlecht ."' " . $selected . ">". ucfirst($gender->bezeichnung_mehrsprachig[$language]) . "</option>";
}
}
?>
</select>
@@ -79,12 +85,15 @@
<select id="gebnation" disabled>
<?php
foreach ($all_nations as $nation)
if (is_array($all_nations))
{
$selected = '';
if ($nation->nation_code === $stammdaten->geburtsnation_code)
$selected = 'selected';
echo "<option value='". $nation->nation_code ."' " . $selected . ">". $nation->langtext . "</option>";
foreach ($all_nations as $nation)
{
$selected = '';
if ($nation->nation_code === $stammdaten->geburtsnation_code)
$selected = 'selected';
echo "<option value='". $nation->nation_code ."' " . $selected . ">". $nation->langtext . "</option>";
}
}
?>
</select>
@@ -154,12 +163,15 @@
<?php if (isset($adresse->nationkurztext)): ?>
<select id="nation_<?php echo $adresse->adresse_id ?>" disabled>
<?php
foreach ($all_nations as $nation)
if (is_array($all_nations))
{
$selected = '';
if ($nation->nation_code === $adresse->nation)
$selected = 'selected';
echo "<option value='". $nation->nation_code ."' " . $selected . ">". $nation->langtext . "</option>";
foreach ($all_nations as $nation)
{
$selected = '';
if ($nation->nation_code === $adresse->nation)
$selected = 'selected';
echo "<option value='". $nation->nation_code ."' " . $selected . ">". $nation->langtext . "</option>";
}
}
?>
</select>
+48 -34
View File
@@ -1,11 +1,21 @@
<?php
$PERSON_ID = getAuthPersonId();
// all oe kurzbz for which logged user has a funktion
$ALL_FUNKTIONEN_OE_KURZBZ = "('" . implode("','", array_keys($all_funktionen_oe_kurzbz)) . "')";
$ALL_FUNKTIONEN_OE_KURZBZ = isEmptyArray($all_funktionen_oe_kurzbz) ? "(NULL)"
: "(" . implode(",", array_map(function($string) { return $this->db->escape($string); }, array_keys($all_funktionen_oe_kurzbz))) . ")";
// all oes for which logged user has issues permissions, including permissions for "special" issue funktion
$ALL_OE_KURZBZ_BERECHTIGT = "('" . implode("','", $all_oe_kurzbz_berechtigt) . "')";
$RELEVANT_PRESTUDENT_STATUS = "('Aufgenommener', 'Student', 'Incoming', 'Diplomand', 'Abbrecher', 'Unterbrecher', 'Absolvent')";
$ALL_OE_KURZBZ_BERECHTIGT = isEmptyArray($all_oe_kurzbz_berechtigt) ? "(NULL)"
: "(" . implode(",", array_map(function($string) { return $this->db->escape($string); }, $all_oe_kurzbz_berechtigt)) . ")";
// app apps for which issues should be displayed
$APPS = isEmptyArray($apps) ? "" : "(" . implode(",", array_map(function($string) { return $this->db->escape($string); }, $apps)) . ")";
// all prestudent status for which issues should be displayed
$RELEVANT_PRESTUDENT_STATUS = isEmptyArray($status) ? ""
: "(" . implode(",", array_map(function($string) { return $this->db->escape($string); }, $status)) . ")";
// get issues for the oes of the logged user or for the persons (students, oe-zuordnung) of the oes
$query = "WITH zustaendigkeiten AS (
@@ -37,8 +47,8 @@ $query .= "
SELECT
issue_id, fehlercode AS \"Fehlercode\", fehler_kurzbz AS \"Fehler Kurzbezeichnung\", iss.fehlercode_extern AS \"Fehlercode extern\", datum AS \"Datum\",
inhalt AS \"Inhalt\", inhalt_extern AS \"Inhalt extern\", iss.person_id AS \"PersonId\", iss.oe_kurzbz AS \"OE\",
ftyp.bezeichnung_mehrsprachig[".$language_index."] AS \"Fehlertyp\",
stat.bezeichnung_mehrsprachig[".$language_index."] AS \"Fehlerstatus\",
ftyp.bezeichnung_mehrsprachig[".$this->db->escape($language_index)."] AS \"Fehlertyp\",
stat.bezeichnung_mehrsprachig[".$this->db->escape($language_index)."] AS \"Fehlerstatus\",
verarbeitetvon AS \"Verarbeitet von\",verarbeitetamum AS \"Verarbeitet am\", fr.app AS \"Applikation\",
fr.fehlertyp_kurzbz AS \"Fehlertypcode\", iss.status_kurzbz AS \"Statuscode\",
pers.vorname AS \"Vorname\", pers.nachname AS \"Nachname\",
@@ -118,44 +128,48 @@ $query .= "
JOIN system.tbl_issue_status stat USING (status_kurzbz)
LEFT JOIN public.tbl_person pers ON iss.person_id = pers.person_id
WHERE
fr.app IN ('core', 'dvuh')
AND (
(
EXISTS ( /* if oe or person is specified in fehler_zustaendigkeiten */
SELECT 1 FROM zustaendigkeiten
WHERE fehlercode = iss.fehlercode
AND zustaendig = TRUE)";
// show issue if it is assigend to oe of logged in user or to student of oe of logged in user
if (!isEmptyArray($all_oe_kurzbz_berechtigt))
{
$query .= " OR iss.oe_kurzbz IN $ALL_OE_KURZBZ_BERECHTIGT /* if issue is for oe */";
$query .= " OR iss.oe_kurzbz IN $ALL_OE_KURZBZ_BERECHTIGT /* if issue is for oe */";
$query .= " OR (iss.oe_kurzbz IS NULL AND EXISTS ( /* if person_id of issue is a student of studiengang oe */
SELECT 1 FROM public.tbl_prestudent ps
JOIN public.tbl_prestudentstatus pss USING (prestudent_id)
JOIN public.tbl_studiengang stg USING (studiengang_kz)
WHERE person_id = iss.person_id
AND stg.oe_kurzbz IN ".$ALL_OE_KURZBZ_BERECHTIGT;
if (!isEmptyString($RELEVANT_PRESTUDENT_STATUS)) $query .= " AND pss.status_kurzbz IN ".$RELEVANT_PRESTUDENT_STATUS;
$query .= " AND NOT EXISTS (SELECT 1 /* irrelevant if already finished studies and studied a while ago */
FROM public.tbl_prestudentstatus ps_finished
JOIN public.tbl_studiensemester sem_finished USING (studiensemester_kurzbz)
WHERE prestudent_id = ps.prestudent_id
AND status_kurzbz IN ('Absolvent','Abbrecher','Abgewiesener')
AND datum::date + interval '2 months' < NOW()
AND EXISTS (SELECT 1 FROM public.tbl_prestudent /* if more recent prestudent exists, still display the issue */
JOIN public.tbl_prestudentstatus USING (prestudent_id)
JOIN public.tbl_studiensemester USING (studiensemester_kurzbz)
WHERE person_id = ps.person_id
AND prestudent_id <> ps_finished.prestudent_id
AND tbl_studiensemester.start::date > sem_finished.start::date";
if (!isEmptyString($RELEVANT_PRESTUDENT_STATUS)) $query .= " AND tbl_prestudentstatus.status_kurzbz IN ".$RELEVANT_PRESTUDENT_STATUS;
$query .= ")
)
)
)";
$query .= " OR (iss.oe_kurzbz IS NULL AND EXISTS ( /* if person_id of issue is a student of studiengang oe */
SELECT 1 FROM public.tbl_prestudent ps
JOIN public.tbl_prestudentstatus pss USING (prestudent_id)
JOIN public.tbl_studiengang stg USING (studiengang_kz)
WHERE person_id = iss.person_id
AND stg.oe_kurzbz IN $ALL_OE_KURZBZ_BERECHTIGT
AND pss.status_kurzbz IN $RELEVANT_PRESTUDENT_STATUS
AND NOT EXISTS (SELECT 1 /* irrelevant if already finished studies and studied a while ago */
FROM public.tbl_prestudentstatus ps_finished
JOIN public.tbl_studiensemester sem_finished USING (studiensemester_kurzbz)
WHERE prestudent_id = ps.prestudent_id
AND status_kurzbz IN ('Absolvent','Abbrecher','Abgewiesener')
AND datum::date + interval '2 months' < NOW()
AND EXISTS (SELECT 1 FROM public.tbl_prestudent /* if more recent prestudent exists, still display the issue */
JOIN public.tbl_prestudentstatus USING (prestudent_id)
JOIN public.tbl_studiensemester USING (studiensemester_kurzbz)
WHERE tbl_prestudentstatus.status_kurzbz IN $RELEVANT_PRESTUDENT_STATUS
AND person_id = ps.person_id
AND prestudent_id <> ps_finished.prestudent_id
AND tbl_studiensemester.start::date > sem_finished.start::date)
)
)
)";
}
$query .= ") ";
if (!isEmptyString($APPS)) $query .= " AND fr.app IN ".$APPS;
$query .= " ORDER BY
CASE
WHEN fehlertyp_kurzbz = '".IssuesLib::ERRORTYPE_CODE."' THEN 0
@@ -384,17 +384,6 @@ for ($i = 0; $i < count($ztaufdata); $i++)
}
}
//worktime with no break greater 6 -> compulsory break of half an hour
if ($pauseSubtracted < 0.5 && !$lehreExternExists)
{
if ($projektlines[$day]->arbeitszeit >= 6.5)
$projektlines[$day]->arbeitszeit -= 0.5;
//ensure that no worktime gets smaller than 6 hours because of compulsory break
elseif ($projektlines[$day]->arbeitszeit > 6)
$projektlines[$day]->arbeitszeit -= $projektlines[$day]->arbeitszeit - 6;
}
$projektlines[$day]->arbeitszeit = round($projektlines[$day]->arbeitszeit, 2);
//calculate sums
+307 -55
View File
@@ -65,7 +65,7 @@ if (isset($_GET['nummer']))
}
else
{
$nummer = '';
$nummer = '0';
}
if (isset($_GET['frage_id']))
@@ -102,29 +102,175 @@ echo '<?xml version="1.0" encoding="UTF-8"?>';
<link href="../../../skin/style.css.php" rel="stylesheet" type="text/css" />
<script language="Javascript">
//Vorschau anzeigen
function preview()
{
document.getElementById('vorschau').innerHTML = document.getElementById('text').value;
function preview(input) {
const xmlText = document.getElementById('text_'+input).value;
const vorschau = document.getElementById('vorschau_'+input);
// Zurücksetzen der Styles
vorschau.style.textAlign = 'center';
vorschau.style.backgroundColor = 'initial';
vorschau.style.color = 'initial';
// Prüfen ob überhaupt Inhalt vorhanden ist
if (!xmlText.trim()) {
vorschau.innerHTML = '';
return;
}
// Prüfe ob HTML/XML-Tags vorhanden sind
const hatTags = xmlText.indexOf('&lt;') != -1 &amp;&amp; xmlText.indexOf('&gt;') != -1;
if (!hatTags) {
// Kein HTML/XML - zeige als normalen Text
vorschau.innerText = xmlText;
return;
}
// Versuche HTML/MathML zu rendern
try {
// Erstelle einen temporären Container für die Validierung
const tempDiv = document.createElement('div');
tempDiv.innerHTML = xmlText;
// Prüfe auf MathML-Elemente und stelle sicher, dass sie korrekt sind
const mathElements = tempDiv.querySelectorAll('math');
let mathmlValid = true;
// Verwende eine while-Schleife statt for-Schleife um XML-Probleme zu vermeiden
let i = 0;
while (i &lt; mathElements.length) {
const mathEl = mathElements[i];
// Prüfe ob das MathML-Element den korrekten Namespace hat
if (!mathEl.hasAttribute('xmlns')) {
mathEl.setAttribute('xmlns', 'http://www.w3.org/1998/Math/MathML');
}
// Grundlegende MathML-Validierung
const mathmlContent = mathEl.innerHTML;
if (mathmlContent.trim() === '') {
mathmlValid = false;
break;
}
i++;
}
if (mathmlValid) {
// Wenn alles ok ist, zeige den Inhalt an
vorschau.innerHTML = xmlText;
// Versuche MathML zu rendern falls MathJax verfügbar ist
if (typeof MathJax != 'undefined' &amp;&amp; MathJax.typesetPromise) {
MathJax.typesetPromise([vorschau]).catch(function (err) {
console.log('MathJax-Fehler:', err.message);
});
}
} else {
throw new Error('Ungültiges MathML');
}
} catch (error) {
// HTML-Parsing fehlgeschlagen - prüfe ob es sich um reines XML handelt
const startetMitTag = xmlText.trim().charAt(0) === '&lt;';
const endetMitTag = xmlText.trim().charAt(xmlText.trim().length - 1) === '&gt;';
const hatNurTags = xmlText.indexOf('&lt;') === 0 &amp;&amp; xmlText.lastIndexOf('&gt;') === xmlText.length - 1;
if (startetMitTag &amp;&amp; endetMitTag &amp;&amp; hatNurTags) {
// Versuche XML-Parsing
try {
const parser = new DOMParser();
const parsed = parser.parseFromString(xmlText, 'application/xml');
const parsererror = parsed.getElementsByTagName('parsererror');
if (parsererror.length &gt; 0) {
let fehlertext = parsererror[0].textContent;
const zeileninfoStart = fehlertext.indexOf("Zeile Nr.");
if (zeileninfoStart != -1) {
const zeileninfo = fehlertext.substring(zeileninfoStart);
fehlertext = 'XML-Verarbeitungsfehler:\n' + zeileninfo;
}
vorschau.innerText = fehlertext;
vorschau.style.textAlign = 'left';
vorschau.style.backgroundColor = 'lightyellow';
vorschau.style.color = 'red';
return;
} else {
// XML ist gültig
vorschau.innerText = xmlText;
return;
}
} catch (xmlError) {
// XML-Parsing fehlgeschlagen
vorschau.innerText = 'XML-Formatfehler: ' + xmlError.message;
vorschau.style.textAlign = 'left';
vorschau.style.backgroundColor = 'lightyellow';
vorschau.style.color = 'red';
return;
}
} else {
// Gemischter Inhalt oder HTML mit Fehlern - zeige Fehlermeldung
vorschau.innerText = 'HTML/MathML-Formatfehler: ' + error.message;
vorschau.style.textAlign = 'left';
vorschau.style.backgroundColor = 'lightyellow';
vorschau.style.color = 'red';
}
}
}
function previewvorschlag()
{
document.getElementById('vorschauvorschlag').innerHTML = document.getElementById('text_vorschlag').value;
function previewvorschlag() {
const xmlText = document.getElementById('text_vorschlag').value;
const vorschau = document.getElementById('vorschauvorschlag');
const parser = new DOMParser();
const parsed = parser.parseFromString(xmlText, 'application/xml');
const parsererror = parsed.getElementsByTagName('parsererror');
if (parsererror.length > 0) {
var fehlertext = parsererror[0].textContent;
const zeileninfoStart = fehlertext.indexOf("Zeile Nr.");
if (zeileninfoStart !== -1) {
const zeileninfo = fehlertext.substring(zeileninfoStart);
fehlertext = 'XML-Verarbeitungsfehler:\n ' + zeileninfo;
} else {
fehlertext = fehlertext; // Fallback
}
vorschau.innerText = fehlertext;
vorschau.style.textAlign = 'left';
vorschau.style.backgroundColor = 'lightyellow';
} else {
// Zeige XML als Text (nicht als HTML rendern!)
vorschau.innerHTML = xmlText;
vorschau.style.textAlign = 'center';
vorschau.style.backgroundColor = 'initial';
}
}
function insertfrage(aTag, eTag)
{
var input = document.forms['formular_frage'].elements['text'];
var input = document.forms['formular_frage'].elements['text_frage'];
input.focus();
/* Einfügen des Formatierungscodes */
var start = input.selectionStart;
var end = input.selectionEnd;
var insText = input.value.substring(start, end);
input.value = input.value.substr(0, start) + aTag + insText + eTag + input.value.substr(end);
if (eTag)
{
input.value = input.value.substr(0, start) + aTag + insText + eTag + input.value.substr(end);
}
else
{
input.value = input.value.substr(0, start) + aTag + input.value.substr(end);
}
/* Anpassen der Cursorposition */
var pos;
if (insText.length == 0) {
pos = start + aTag.length;
} else {
pos = start + aTag.length + insText.length + eTag.length;
} else
{
if (eTag) {
pos = start + aTag.length + insText.length + eTag.length;
}
else {
pos = start + aTag.length + insText.length;
}
}
input.selectionStart = pos;
input.selectionEnd = pos;
@@ -137,13 +283,25 @@ function insertvorschlag(aTag, eTag)
var start = input.selectionStart;
var end = input.selectionEnd;
var insText = input.value.substring(start, end);
input.value = input.value.substr(0, start) + aTag + insText + eTag + input.value.substr(end);
if (eTag)
{
input.value = input.value.substr(0, start) + aTag + insText + eTag + input.value.substr(end);
}
else
{
input.value = input.value.substr(0, start) + aTag + input.value.substr(end);
}
/* Anpassen der Cursorposition */
var pos;
if (insText.length == 0) {
pos = start + aTag.length;
} else {
pos = start + aTag.length + insText.length + eTag.length;
if (eTag) {
pos = start + aTag.length + insText.length + eTag.length;
}
else {
pos = start + aTag.length + insText.length;
}
}
input.selectionStart = pos;
input.selectionEnd = pos;
@@ -153,6 +311,14 @@ function confirmDeleteFrage()
{
return confirm('Wollen Sie diese Frage wirklich löschen?');
}
function increaseMATHML()
{
const mathTags = document.querySelectorAll('math');
mathTags.forEach(tag => {
tag.style.fontSize = '200%';
});
}
</script>
<style type="text/css">
@@ -778,44 +944,83 @@ if (($anzahl !== 0) || ($stg_kz == '-1') && ($stg_kz !== ''))
<a href="'.$PHP_SELF.'?gebiet_id='.$gebiet_id.'&amp;stg_kz='.$stg_kz.'&amp;nummer='.$nummer.'&amp;filter=aktiv">
<input type="checkbox" name="inaktiv" '.$inaktivchecked.' onclick="window.location.assign(\''.$PHP_SELF.'?gebiet_id='.$gebiet_id.'&amp;stg_kz='.$stg_kz.'&amp;nummer='.$nummer.'&amp;filter=aktiv\');"/>inaktiv</a>';
}
echo '<br/><table class="nummern" style="display: inline-table;"><tbody><tr>
<td>Nummer:</td>';
foreach ($resultArray AS $key=>$value)
{
if ($nummer == '')
$nummer = $value['nummer'];
echo '<br/>';
$style = '';
if ($db->db_parse_bool($value['aktiv']) == false)
$style = 'style="color: lightgrey"';
$counter = 0;
$maxPerTable = 50;
$totalItems = count($resultArray);
$styleSelected = '';
if ($nummer == $value['nummer'])
{
$styleSelected = 'style="background-color: lightblue"';
}
// Erste Tabelle öffnen
echo '<table class="nummern" style="display: inline-table; margin-bottom: 10px;"><tbody><tr>
<td>Nummer:</td>';
echo '<td class="nummern" '.$styleSelected.'><a href="'.$PHP_SELF.'?gebiet_id='.$gebiet_id.'&amp;stg_kz='.$stg_kz.'&amp;nummer='.$value['nummer'].'&amp;filter='.$filter.'" '.$style.'>'.$value['nummer'].'</a></td>';
foreach ($resultArray AS $key=>$value) {
// Neue Tabelle starten, wenn 50 Einträge erreicht sind
if ($counter > 0 && $counter % $maxPerTable == 0) {
// Aktuelle Tabelle schließen
echo '</tr><tr><td>Level:</td>';
// Level-Zeile für die vorherigen Einträge
$startIndex = $counter - $maxPerTable;
$endIndex = $counter;
$tempArray = array_slice($resultArray, $startIndex, $maxPerTable, true);
foreach ($tempArray AS $tempKey=>$tempValue) {
$leveltext = '';
if ($tempValue['level'] == '') {
$leveltext = '-';
} else {
$leveltext = $tempValue['level'];
if ($tempValue['demo'] == 't') {
$leveltext .= '*';
}
}
echo '<td class="nummern" style="color: grey">'.$leveltext.'</td>';
}
echo '</tr></tbody></table><br/>';
// Neue Tabelle starten
echo '<table class="nummern" style="display: inline-table; margin-bottom: 10px;"><tbody><tr>
<td>Nummer:</td>';
}
if ($nummer == '')
$nummer = $value['nummer'];
$style = '';
if ($db->db_parse_bool($value['aktiv']) == false)
$style = 'style="color: lightgrey"';
$styleSelected = '';
if ($nummer == $value['nummer']) {
$styleSelected = 'style="background-color: lightblue"';
}
echo '<td class="nummern" '.$styleSelected.'><a href="'.$PHP_SELF.'?gebiet_id='.$gebiet_id.'&amp;stg_kz='.$stg_kz.'&amp;nummer='.$value['nummer'].'&amp;filter='.$filter.'" '.$style.'>'.$value['nummer'].'</a></td>';
$counter++;
}
echo '</tr><tr>
<td>Level:</td>';
$leveltext = '';
foreach ($resultArray AS $key=>$value)
{
if ($value['level'] == '')
{
$leveltext = '-';
}
else
{
$leveltext = $value['level'];
if ($value['demo'] == 't')
{
$leveltext .= '*';
}
}
echo '<td class="nummern" style="color: grey">'.$leveltext.'</td>';
// Letzte Tabelle schließen
echo '</tr><tr><td>Level:</td>';
// Level-Zeile für die letzten Einträge
$remainingItems = $counter % $maxPerTable;
if ($remainingItems == 0) $remainingItems = $maxPerTable;
$startIndex = $counter - $remainingItems;
$tempArray = array_slice($resultArray, $startIndex, $remainingItems, true);
foreach ($tempArray AS $tempKey=>$tempValue) {
$leveltext = '';
if ($tempValue['level'] == '') {
$leveltext = '-';
} else {
$leveltext = $tempValue['level'];
if ($tempValue['demo'] == 't') {
$leveltext .= '*';
}
}
echo '<td class="nummern" style="color: grey">'.$leveltext.'</td>';
}
echo '</tr></tbody></table>';
echo " <a href='$PHP_SELF?gebiet_id=$gebiet_id&amp;stg_kz=$stg_kz&amp;type=neuefrage&amp;filter=$filter' class='Item'>neue Frage hinzufuegen</a>";
$frage_obj = new frage();
@@ -931,7 +1136,7 @@ if ($frage_id != '')
//Bei Aenderungen im Textfeld werden diese sofort in der Vorschau angezeigt
//Wenn beim Speichern der Text kein Gueltiges XML ist, wird der vorige Text erneut angezeigt
echo "<tr valign='top'><td colspan='2'>\n<textarea name='text' id='text' cols='50' rows='27' oninput='preview()' ".($frage->aktiv == false?'disabled="disabled"':'')."><![CDATA[".(isset($frage_error_text)?$frage_error_text:$frage->text)."]]></textarea>\n</td>";
echo "<tr valign='top'><td colspan='2'>\n<textarea name='text' id='text_frage' cols='50' rows='27' oninput='preview(\"frage\")' ".($frage->aktiv == false?'disabled="disabled"':'')."><![CDATA[".(isset($frage_error_text)?$frage_error_text:$frage->text)."]]></textarea>\n</td>";
echo "<table><tr><td><input type='button' value='br' onclick='insertfrage(\"&lt;br/&gt;\", \"\")' />";
echo "<input type='button' value='F' style='font-weight:bold' onclick='insertfrage(\"&lt;strong&gt;\", \"&lt;/strong&gt;\")' />";
echo "<input type='button' value='K' style='font-style:italic' onclick='insertfrage(\"&lt;i&gt;\", \"&lt;/i&gt;\")' /><br/><br/>";
@@ -948,8 +1153,14 @@ if ($frage_id != '')
echo "<input type='button' value='msqrt' onclick='insertfrage(\"&lt;msqrt&gt;\", \"&lt;/msqrt&gt;\")' title='Wurzel' /><br/>";
echo "<input type='button' value='munderover' onclick='insertfrage(\"&lt;munderover&gt;&lt;mo movablelimits=\&quot;false\&quot;&gt;Das steht mittig&lt;/mo&gt;&lt;mo&gt;Das steht unten&lt;/mo&gt;&lt;mo&gt;Das steht oben&lt;/mo&gt;&lt;/munderover&gt;\", \"\")' title='Oben und unten' /><br/>";
echo "<input type='button' value='mtext' onclick='insertfrage(\"&lt;mtext&gt;\", \"&lt;/mtext&gt;\")' title='Text' /><br/>";
echo "Operatoren:<br/>π<br/>·<br/>∑<br/>∫<br/><a href='http://de.selfhtml.org/html/referenz/zeichen.htm#benannte_iso8859_1' target='blank'>Weitere</a>";
echo "</td>";
echo "Operatoren:<p>";
echo "<button type='button' onclick='insertfrage(\"&lt;mo&gt;π&lt;/mo&gt;\")'>π</button>&nbsp;";
echo "<button type='button' onclick='insertfrage(\"&lt;mo&gt;·&lt;/mo&gt;\")'>·</button>&nbsp;";
echo "<button type='button' onclick='insertfrage(\"&lt;mo&gt;∑&lt;/mo&gt;\")'>∑</button>&nbsp;";
echo "<button type='button' onclick='insertfrage(\"&lt;mo&gt;∫&lt;/mo&gt;\")'>∫</button>";
echo "<p><a href='http://de.selfhtml.org/html/referenz/zeichen.htm#benannte_iso8859_1' target='blank'>Weitere</a></p>";
echo "<button type='button' onclick='increaseMATHML()'>MathML größer</button>";
echo "</p></td>";
echo "</tr></table></tr>";
echo "<tr><td>Demo <input type='checkbox' name='demo' ".($frage->demo?'checked="true"':'')." />
Level <input type='text' name='level' value='$frage->level' size='1' />
@@ -960,7 +1171,10 @@ if ($frage_id != '')
echo "</form>";
echo "</td></tr>";
//Vorschau fuer das Text-Feld
echo "<tr><td colspan='2'>Vorschau:<br /><div id='vorschau' style='border: 1px solid black' align='center'>$frage->text</div></td></tr>";
echo "<tr><td style='width: 50%'>Vorschau:<br />
<div id='vorschau_frage' style='border: 1px solid black' align='center'>$frage->text</div></td>
<td style='width: 50%'>Derzeit:<br /><div id='aktuell' style='border: 1px solid black' align='center'>$frage->text</div>
</td></tr>";
echo "</table>";
echo '</td><td style="border-left: 1px solid black" valign="top">';
@@ -1022,7 +1236,7 @@ if ($frage_id != '')
echo "<input type='button' value='+1/2' style='background-color:#C5FFBF' onclick='document.getElementById(\"punkte\").value=\"0.5\";' /></td>";
echo '</tr>';
echo '<tr valign="top">';
echo '<td>Text:</td><td><textarea name="text" id="text_vorschlag" rows="25" cols="45" oninput="previewvorschlag()" '.($vorschlag->aktiv == true || is_null($vorschlag->aktiv)?'':'disabled="disabled"').'><![CDATA['.$vorschlag->text."]]></textarea>\n</td>";
echo '<td>Text:</td><td><textarea name="text" id="text_vorschlag" rows="25" cols="45" oninput="preview(\'vorschlag\')" '.($vorschlag->aktiv == true || is_null($vorschlag->aktiv)?'':'disabled="disabled"').'><![CDATA['.$vorschlag->text."]]></textarea>\n</td>";
echo "<td><input type='button' value='br' onclick='insertvorschlag(\"&lt;br/&gt;\", \"\")' />";
echo "<input type='button' value='F' style='font-weight:bold' onclick='insertvorschlag(\"&lt;strong&gt;\", \"&lt;/strong&gt;\")' />";
echo "<input type='button' value='K' style='font-style:italic' onclick='insertvorschlag(\"&lt;i&gt;\", \"&lt;/i&gt;\")' /><br/><br/>";
@@ -1039,8 +1253,12 @@ if ($frage_id != '')
echo "<input type='button' value='msqrt' onclick='insertvorschlag(\"&lt;msqrt&gt;\", \"&lt;/msqrt&gt;\")' title='Wurzel' /><br/>";
echo "<input type='button' value='munderover' onclick='insertvorschlag(\"&lt;munderover&gt;&lt;mo movablelimits=\&quot;false\&quot;&gt;Das steht mittig&lt;/mo&gt;&lt;mo&gt;Das steht unten&lt;/mo&gt;&lt;mo&gt;Das steht oben&lt;/mo&gt;&lt;/munderover&gt;\", \"\")' title='Oben und unten' /><br/>";
echo "<input type='button' value='mtext' onclick='insertvorschlag(\"&lt;mtext&gt;\", \"&lt;/mtext&gt;\")' title='Text' /><br/>";
echo "Operatoren:<br/>π<br/>·<br/>∑<br/>∫<br/><a href='http://de.selfhtml.org/html/referenz/zeichen.htm#benannte_iso8859_1' target='blank'>Weitere</a>";
echo "</td>";
echo "Operatoren:<p>";
echo "<button type='button' onclick='insertvorschlag(\"&lt;mo&gt;π&lt;/mo&gt;\")'>π</button>&nbsp;";
echo "<button type='button' onclick='insertvorschlag(\"&lt;mo&gt;·&lt;/mo&gt;\")'>·</button>&nbsp;";
echo "<button type='button' onclick='insertvorschlag(\"&lt;mo&gt;∑&lt;/mo&gt;\")'>∑</button>&nbsp;";
echo "<button type='button' onclick='insertvorschlag(\"&lt;mo&gt;∫&lt;/mo&gt;\")'>∫</button>";
echo "</p></td>";
echo '</tr><tr valign="top">';
//Upload Feld fuer Bild
echo "<td>Bild:</td><td><input type='file' name='bild' /></td>";
@@ -1062,10 +1280,10 @@ if ($frage_id != '')
echo "/></td></tr>";
echo "<tr><td colspan='2' align='right'><input type='submit' name='submitvorschlag' value='Speichern' />".($vorschlag_id != ''?"<input type='button' value='Abbrechen' onclick=\"document.location.href='$PHP_SELF?gebiet_id=$gebiet_id&amp;stg_kz=$stg_kz&amp;nummer=$nummer&amp;frage_id=$frage->frage_id'\" />":'')."</td></tr>";
//Vorschau fuer das Text-Feld
echo "<tr><td colspan='2'>Vorschau:<br /><div id='vorschauvorschlag' style='border: 1px solid black' align='center'>$vorschlag->text</div></td></tr>";
echo "<tr><td colspan='2'>Vorschau:<br /><div id='vorschau_vorschlag' style='border: 1px solid black' align='center'>$vorschlag->text</div>
Derzeit:<br /><div id='aktuellvorschlag' style='border: 1px solid black' align='center'>$vorschlag->text</div></td></tr>";
echo "</table>";
echo "</form>";
echo '</td></tr></table>';
$vorschlag = new vorschlag();
@@ -1115,6 +1333,40 @@ if ($frage_id != '')
echo '<tr><td><input type="hidden" name="allevorschlaege" value="'.$allevorschlaege.'" />Summe:</td><td align="left">'.number_format(array_sum($a), 2, ".", "").'&nbsp;&nbsp;</td><td></td><td></td><td></td><td></td><td></td><td><input type="submit" value="Speichern"/></td></tr>';
echo '</table></form><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>';
}
echo "<script>
document.getElementById('text_vorschlag').addEventListener('keydown', function(e)
{
if (e.key === 'Tab') {
e.preventDefault();
const textarea = e.target;
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
// Tabulator-Zeichen einfügen
textarea.value = textarea.value.substring(0, start) + '\t' + textarea.value.substring(end);
// Cursor hinter den Tab setzen
textarea.selectionStart = textarea.selectionEnd = start + 1;
}
});
document.getElementById('text_frage').addEventListener('keydown', function(e)
{
if (e.key === 'Tab') {
e.preventDefault();
const textarea = e.target;
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
// Tabulator-Zeichen einfügen
textarea.value = textarea.value.substring(0, start) + '\t' + textarea.value.substring(end);
// Cursor hinter den Tab setzen
textarea.selectionStart = textarea.selectionEnd = start + 1;
}
});
</script>";
}
+1 -2
View File
@@ -481,7 +481,6 @@
"phpmd/phpmd": "2.*",
"phpmetrics/phpmetrics": "2.*",
"sebastian/phpcpd": "3.*",
"phpunit/phpunit": "^6",
"zircote/swagger-php": "^2.0"
"phpunit/phpunit": "^6"
}
}
@@ -634,6 +634,7 @@ if(!$error)
JOIN public.tbl_studiengang USING(studiengang_kz)
WHERE
mitarbeiter_uid=".$db->db_add_param($lem->mitarbeiter_uid)." AND
lower(mitarbeiter_uid) NOT LIKE '_dummy%' AND
studiensemester_kurzbz=".$db->db_add_param($le->studiensemester_kurzbz)." AND
bismelden";
+42
View File
@@ -575,5 +575,47 @@ class ampel extends basis_db
}
}
/**
* Zählt die Anzahl der UIDs, welche mit einer Ampel adressiert werden
* @param $ampel_id integer ID der Ampel, die geladen werden soll
*/
public function getAnzahlUserAmpel($ampel_id)
{
// Ampel laden
$qry_ampel = "SELECT benutzer_select FROM public.tbl_ampel WHERE ampel_id=".$this->db_add_param($ampel_id, FHC_INTEGER);
if($result_ampel = $this->db_query($qry_ampel))
{
// Anzahl User laden
if ($row_ampel = $this->db_fetch_object($result_ampel))
{
$qry_user = "SELECT count(*) AS anzahl FROM (SELECT uid FROM public.tbl_benutzer WHERE uid IN (".$row_ampel->benutzer_select."))subquery";
}
if ($result = $this->db_query($qry_user))
{
if ($row = $this->db_fetch_object($result))
{
return $row->anzahl;
}
else
{
$this->errormsg = 'Anzahl UIDs konnte nicht geladen werden';
return false;
}
}
else
{
$this->errormsg = 'Anzahl UIDs konnte nicht geladen werden';
return false;
}
}
else
{
$this->errormsg = 'Fehler beim Laden der Ampel';
return false;
}
}
}
?>
+18 -6
View File
@@ -200,7 +200,7 @@ class LehreListHelper
//Studierende der LV laden und in ein Array schreiben
$qry = 'SELECT
distinct on(nachname, vorname, person_id) vorname, nachname, wahlname, matrikelnr, public.tbl_student.student_uid,
distinct on(nachname, vorname, public.tbl_benutzer.person_id) vorname, nachname, wahlname, matrikelnr, public.tbl_student.student_uid,
tbl_studentlehrverband.semester, tbl_studentlehrverband.verband, tbl_studentlehrverband.gruppe,
(SELECT status_kurzbz FROM public.tbl_prestudentstatus
WHERE prestudent_id=tbl_student.prestudent_id
@@ -209,7 +209,8 @@ class LehreListHelper
tbl_note.lkt_ueberschreibbar, tbl_note.anmerkung, tbl_mitarbeiter.mitarbeiter_uid, tbl_person.matr_nr, tbl_person.geschlecht, tbl_studiengang.kurzbzlang,
tbl_mobilitaet.mobilitaetstyp_kurzbz, tbl_zeugnisnote.note,
(CASE WHEN bis.tbl_mobilitaet.studiensemester_kurzbz = vw_student_lehrveranstaltung.studiensemester_kurzbz THEN 1 ELSE 0 END) as doubledegree,
(tbl_bisio.bis::timestamp - tbl_bisio.von::timestamp) as daysout
(tbl_bisio.bis::timestamp - tbl_bisio.von::timestamp) as daysout,
public.tbl_prestudent.gsstudientyp_kurzbz as ddtype
FROM
campus.vw_student_lehrveranstaltung
JOIN public.tbl_benutzer USING(uid)
@@ -223,6 +224,7 @@ class LehreListHelper
LEFT JOIN bis.tbl_bisio ON(uid=tbl_bisio.student_uid)
LEFT JOIN public.tbl_studiengang ON(tbl_student.studiengang_kz=tbl_studiengang.studiengang_kz)
LEFT JOIN bis.tbl_mobilitaet USING(prestudent_id)
LEFT JOIN public.tbl_prestudent USING(prestudent_id)
WHERE
vw_student_lehrveranstaltung.lehrveranstaltung_id='.$this->db->db_add_param($this->lvid, FHC_INTEGER).' AND
vw_student_lehrveranstaltung.studiensemester_kurzbz='.$this->db->db_add_param($this->studiensemester);
@@ -231,7 +233,7 @@ class LehreListHelper
if($this->lehreinheit!='')
$qry.=' AND vw_student_lehrveranstaltung.lehreinheit_id='.$this->db->db_add_param($this->lehreinheit, FHC_INTEGER);
$qry.=' ORDER BY nachname, vorname, person_id, daysout DESC, doubledegree DESC';
$qry.=' ORDER BY nachname, vorname, public.tbl_benutzer.person_id, daysout DESC, doubledegree DESC';
$stsem_obj = new studiensemester();
$stsem_obj->load($this->studiensemester);
@@ -263,8 +265,13 @@ class LehreListHelper
//Outgoing
if($row->bisio_id != '' && $row->status != 'Incoming' && ($row->bis > $stsemdatumvon || $row->bis == '')
&& $row->von < $stsemdatumbis && (anzahlTage($row->von, $row->bis) >= 30))
&& $row->von < $stsemdatumbis && (anzahlTage($row->von, $row->bis) >= 30)) {
$zusatz .= '(o)(ab '.$datum->formatDatum($row->von, 'd.m.Y').')';
} else if ($row->bisio_id != '' && $row->status != 'Incoming' && ($row->von > $stsemdatumvon || $row->von == '')) {
// if bis datum is not yet known but von is available already
$zusatz .= '(o)(ab '.$datum->formatDatum($row->von, 'd.m.Y').')';
}
if($row->lkt_ueberschreibbar == 'f') // angerechnet / intern angerechnet / nicht zugelassen
$zusatz.= '('. $row->anmerkung. ')';
@@ -275,8 +282,13 @@ class LehreListHelper
if($row->stg_kz_student==$a_o_kz) //Außerordentliche Studierende
$zusatz.='(a.o.)';
if(($row->mobilitaetstyp_kurzbz != '') && ($row->doubledegree == 1)) //Double Degree Student
$zusatz .= '(d.d.)';
if(($row->mobilitaetstyp_kurzbz != '') && ($row->doubledegree == 1)) {
//Double Degree Student
$zusatz .= '(d.d.';
if($row->ddtype == 'Intern') $zusatz .= 'i.)';
else if ($row->ddtype == 'Extern') $zusatz .='o.)';
else $zusatz .= ')';
}
if(($row->wahlname != ''))
{
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<phpunit bootstrap="index.ci.php">
<testsuites>
<testsuite name="UnitTests">
<directory>system/UnitTests/vertragsbestandteil/gui</directory>
</testsuite>
</testsuites>
<php>
<ini name="display_errors" value="1"/>
<ini name="display_startup_errors" value="1" />
<const name="PHPUNIT_TEST" value="1" />
</php>
</phpunit>
+1 -1
View File
@@ -8,7 +8,7 @@ export default {
},
delete: function (bookmark_id) {
return this.$fhcApi.post(
return this.$fhcApi.get(
`/api/frontend/v1/Bookmark/delete/${bookmark_id}`
,{}
);
+1 -1
View File
@@ -24,7 +24,7 @@ export default {
},
delete(bookmark_id) {
return {
method: 'post',
method: 'get',
url: `/api/frontend/v1/Bookmark/delete/${bookmark_id}`
};
},
+1
View File
@@ -119,6 +119,7 @@ export default {
<div class="modal-content">
<div v-if="$slots.title" class="modal-header">
<h5 class="modal-title"><slot name="title"/></h5>
<slot name="popoutButton"></slot>
<button v-if="!noCloseBtn" type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" :class="bodyClass">
+1 -1
View File
@@ -318,7 +318,7 @@ export default {
>
<slot></slot>
</component>
<label v-if="label && (lcType == 'radio' || lcType == 'checkbox')" :for="idCmp" :class="!noAutoClass && 'form-check-label'">{{label}}</label>
<label v-if="label && (lcType == 'radio' || lcType == 'checkbox')" :for="idCmp" :class="!noAutoClass && 'form-check-label'" v-html="label"></label>
<div v-if="valid !== undefined && feedback.length && !noFeedback" :class="feedbackClass">
<template v-for="(msg, i) in feedback" :key="i">
<hr v-if="i" class="m-0">
+5 -1
View File
@@ -20,6 +20,10 @@ export default {
accept: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
}
},
methods: {
@@ -88,7 +92,7 @@ export default {
},
template: `
<div class="form-upload-dms">
<input ref="upload" class="form-control" :accept="accept" :class="inputClass" :id="id" :name="name" :multiple="multiple" type="file" @change="addFiles">
<input ref="upload" class="form-control" :disabled="disabled" :accept="accept" :class="inputClass" :id="id" :name="name" :multiple="multiple" type="file" @change="addFiles">
<ul v-if="modelValue.length && multiple && !noList" :accept="accept" class="list-unstyled m-0">
<dms-item
v-for="(file, index) in modelValue"
+11 -6
View File
@@ -75,7 +75,7 @@ export const CoreFilterCmpt = {
newBtnDisabled: Boolean,
newBtnLabel: String,
uniqueId: String,
// TODO soll im master kommen?
idField: String,
parentIdField: String,
countOnly: Boolean
@@ -216,17 +216,22 @@ export const CoreFilterCmpt = {
}
// Define a default tabulator options in case it was not provided
let tabulatorOptions = {...{
height: 500,
layout: "fitDataStretchFrozen",
movableColumns: true,
columnDefaults:{
tooltip: true
},
placeholder,
reactiveData: true,
persistence: this.persistence,
}, ...(this.tabulatorOptions || {})};
// set default height if no height property is set
if (tabulatorOptions.height === undefined &&
tabulatorOptions.minHeight === undefined &&
tabulatorOptions.maxHeight === undefined) {
tabulatorOptions.height = 500;
}
if (!this.tableOnly) {
tabulatorOptions.data = this.filteredData;
tabulatorOptions.columns = this.filteredColumns;
@@ -234,7 +239,7 @@ export const CoreFilterCmpt = {
if (tabulatorOptions.selectable || (tabulatorOptions.columns && tabulatorOptions.columns.filter(el => el.formatter == 'rowSelection').length))
this.tabulatorHasSelector = true;
// TODO check ob im core bleiben soll
if (this.idField) {
// enable nested tabulator if parent Id given
if (this.parentIdField) tabulatorOptions.dataTree = true;
@@ -258,7 +263,7 @@ export const CoreFilterCmpt = {
this.tabulator.on("rowSelectionChanged", data => {
this.selectedData = data;
});
// TODO check ob im core so bleiben soll
// if nested tabulator, restructure data
if (this.parentIdField && this.idField) {
this.tabulator.on("dataLoading", data => {
@@ -575,7 +580,7 @@ export const CoreFilterCmpt = {
this.getFilter
);
},
// TODO check ob im core so bleiben soll
// append child to it's parent
appendChild(data, child) {
// get parent id
@@ -50,12 +50,21 @@ var InfocenterPersonDataset = {
'</select>' +
'<select class="form-control auswahlAbsageAbgeschickt" style="width:auto; float:left;">' +
'<option value="null" selected="selected"> Bewerbung abgeschickt? </option>' +
'<option value="all"> Beide </option>' +
'<option value="true"> Ja </option>' +
'<option value="false"> Nein </option>' +
'</select>' +
'<button class="btn btn-default auswahlAbsageBtn" style="float:left"> Absage </button>';
let rueckstellung = '<br />' +
'<select id="rueckstellungtype" class="form-control" style="width:auto; float:left;">' +
'<option disabled value="null" selected>' + FHC_PhrasesLib.t('infocenter', 'statusAuswahl') + '</option>' +
'</select>' +
'<input id="rueckstellungdate" type="text" class="form-control" style="width:auto; float:left;" placeholder="Parkdatum">' +
'<button class="form-control btn btn-default rueckstellBtn" style="width:auto; float:left"> Zurückstellen </button>';
InfocenterPersonDataset.getAbsageData();
Rueckstellung.getStatus()
var studienSemesterHtml = '<button class="btn btn-default btn-xs decStudiensemester">' +
'<i class="fa fa-chevron-left"></i>' +
@@ -98,10 +107,22 @@ var InfocenterPersonDataset = {
"<div class='row'>"+
"<div class='col-xs-12'>"+auswahlAbsageToggle+"</div>"+
"<div class='col-xs-12' id='absagePunkte' style='display:none'>"+auswahlAbsage+"</div>"+
"<div class='col-xs-12' id='rueckstellung' style='display:none'>"+rueckstellung+"</div>"+
"</div>" +
"<div class='h-divider'></div>" +
"<hr class='studiensemesterline'>"
)
let rueckstelldate = new Date();
rueckstelldate.setDate(rueckstelldate.getDate() + 14);
$('#rueckstellungdate').attr("value", $.datepicker.formatDate("dd.mm.yy", rueckstelldate));
$("#rueckstellungdate").datepicker({
"dateFormat": "dd.mm.yy",
"minDate": 1
});
$("button.incStudiensemester").click(function() {
InfocenterPersonDataset.changeStudiensemesterUservar(1);
});
@@ -123,6 +144,29 @@ var InfocenterPersonDataset = {
$(".absageModalForAll").modal("show");
});
$('button.rueckstellBtn').click(function()
{
let idsel = $("#filterTableDataset input:checked[name=PersonId\\[\\]]");
if(idsel.length <= 0)
return FHC_DialogLib.alertInfo("Bitte wählen Sie die Personen aus.");
let type = $('#rueckstellungtype').val()
if (type === null)
return FHC_DialogLib.alertInfo("Bitte ein Rückstellgrund auswählen.");
let personen = [];
for (let i = 0; i < idsel.length; i++)
{
personen.push($(idsel[i]).val());
}
let date = $("#rueckstellungdate").val();
Rueckstellung.setForPersons(personen, type, date)
});
$('#saveAbsageForAll').click(function()
{
InfocenterPersonDataset.saveAbsageForAll();
@@ -131,6 +175,7 @@ var InfocenterPersonDataset = {
$('a.absageToggle').click(function()
{
$('#absagePunkte').toggle();
$('#rueckstellung').toggle();
})
var personcount = 0;
@@ -356,6 +401,11 @@ var InfocenterPersonDataset = {
text: value.bezeichnung_mehrsprachig[0]
}))
})
$('.auswahlAbsageStg').append($("<option/>", {
value: 'all',
text: 'Alle'
}))
$.each(data.studiengaenge, function(key, value){
$('.auswahlAbsageStg').append($("<option/>", {
value: value.studiengang,
+27
View File
@@ -87,6 +87,33 @@ var Rueckstellung = {
}
);
},
setForPersons: function(personen, type, date)
{
if (type === null)
return false;
FHC_AjaxClient.ajaxCallPost(
CONTROLLER_RUECKSTELLUNG_URL + '/setForPersonen',
{
"personen": personen,
"datum_bis": date,
"status_kurzbz": type,
},
{
successCallback: function(data, textStatus, jqXHR) {
if (FHC_AjaxClient.isError(data))
FHC_DialogLib.alertError(FHC_AjaxClient.getError(data));
if (FHC_AjaxClient.hasData(data))
FHC_DialogLib.alertSuccess("Erfolgreich gespeichert.")
},
errorCallback: function(jqXHR, textStatus, errorThrown) {
FHC_DialogLib.alertError(textStatus);
},
veilTimeout: 0
}
);
},
delete: function(personid, status = null)
{
FHC_AjaxClient.ajaxCallPost(
+7 -1
View File
@@ -117,7 +117,7 @@ const helperApp = Vue.createApp({
},
methods: {
mailToUrl(slotProps) {
let mailTo = 'noreply@technikum-wien.at'; // TODO domain anpassen
let mailTo = FHC_JS_DATA_STORAGE_OBJECT.systemerror_mailto;
let subject = 'Meldung%20Systemfehler';
let body = `
Danke, dass Sie uns den Fehler melden. %0D%0A %0D%0A
@@ -141,6 +141,11 @@ const helperApp = Vue.createApp({
unmounted() {
helperAppContainer.parentElement.removeChild(helperAppContainer);
},
computed: {
showmaillink: function() {
return FHC_JS_DATA_STORAGE_OBJECT.systemerror_mailto !== '';
}
},
template: `
<pv-toast ref="toast" class="fhc-alert" :base-z-index="99999"></pv-toast>
<pv-toast ref="alert" class="fhc-alert" :base-z-index="99999" position="center">
@@ -162,6 +167,7 @@ const helperApp = Vue.createApp({
Fehler anzeigen
</a>
<a
v-if="showmaillink"
class="btn btn-primary flex-fill"
target="_blank"
:href="mailToUrl(slotProps)"
+7 -1
View File
@@ -109,7 +109,7 @@ const helperApp = Vue.createApp({
},
methods: {
mailToUrl(slotProps) {
let mailTo = 'noreply@technikum-wien.at'; // TODO domain anpassen
let mailTo = FHC_JS_DATA_STORAGE_OBJECT.systemerror_mailto;
let subject = 'Meldung%20Systemfehler';
let body = `
Danke, dass Sie uns den Fehler melden. %0D%0A %0D%0A
@@ -133,6 +133,11 @@ const helperApp = Vue.createApp({
unmounted() {
helperAppContainer.parentElement.removeChild(helperAppContainer);
},
computed: {
showmaillink: function() {
return FHC_JS_DATA_STORAGE_OBJECT.systemerror_mailto !== '';
}
},
template: `
<pv-toast ref="toast" class="fhc-alert" :base-z-index="99999"></pv-toast>
<pv-toast ref="alert" class="fhc-alert" :base-z-index="99999" position="center">
@@ -154,6 +159,7 @@ const helperApp = Vue.createApp({
Fehler anzeigen
</a>
<a
v-if="showmaillink"
class="btn btn-primary flex-fill"
target="_blank"
:href="mailToUrl(slotProps)"
+52
View File
@@ -386,6 +386,7 @@ if (isset($_REQUEST["xmlformat"]) && $_REQUEST["xmlformat"] == "xml")
echo ' <titel_en>'.$titel_en.'</titel_en>';
$praktikum = false;
$auslandssemester = false;
$internationalskills = false;
$qry = "SELECT
projektarbeit_id
FROM
@@ -403,6 +404,56 @@ if (isset($_REQUEST["xmlformat"]) && $_REQUEST["xmlformat"] == "xml")
}
}
if ($row->typ === 'b')
{
//check if extension international skills is active
$qry = "SELECT 1
FROM information_schema.tables
WHERE table_schema = 'extension' AND table_name = 'tbl_internat_massnahme'";
if($result = $db->db_query($qry))
{
if ($db->db_num_rows($result) === 1)
{
$qry = "SELECT bezeichnung_mehrsprachig[1] as \"internationalskill_deutsch\",
bezeichnung_mehrsprachig[2] as \"internationalskill_english\"
FROM extension.tbl_internat_massnahme_zuordnung zuordnung
JOIN extension.tbl_internat_massnahme massnahme ON zuordnung.massnahme_id = massnahme.massnahme_id
JOIN extension.tbl_internat_massnahme_zuordnung_status zstatus ON zuordnung.massnahme_zuordnung_id = zstatus.massnahme_zuordnung_id
JOIN tbl_prestudent ON zuordnung.prestudent_id = tbl_prestudent.prestudent_id
JOIN tbl_student ON tbl_prestudent.prestudent_id = tbl_student.prestudent_id
WHERE zstatus.massnahme_status_kurzbz = 'confirmed'
AND tbl_student.student_uid = ".$db->db_add_param($uid_arr[$i])."
AND zstatus.massnahme_zuordnung_status_id = (
SELECT MAX(sub_zstatus.massnahme_zuordnung_status_id)
FROM extension.tbl_internat_massnahme_zuordnung_status sub_zstatus
WHERE sub_zstatus.massnahme_zuordnung_id = zuordnung.massnahme_zuordnung_id
)
GROUP BY zuordnung.massnahme_zuordnung_id, tbl_student.student_uid, tbl_prestudent.prestudent_id, tbl_prestudent.studiengang_kz, bezeichnung_mehrsprachig;";
if($db->db_query($qry))
{
if($db->db_num_rows() > 0)
{
$internationalskills = true;
echo "<internationalskills>";
while($row1 = $db->db_fetch_object())
{
echo "<internationalskillsdeutsch>";
echo "<internationalskilldeutsch><![CDATA[$row1->internationalskill_deutsch]]></internationalskilldeutsch>";
echo "</internationalskillsdeutsch>";
echo "<internationalskillsenglisch>";
echo "<internationalskillenglish><![CDATA[$row1->internationalskill_english]]></internationalskillenglish>";
echo "</internationalskillsenglisch>";
}
echo "</internationalskills>";
}
}
}
}
}
$qry = "SELECT tbl_bisio.bisio_id, von, bis, lehreinheit_id,
(SELECT STRING_AGG (
tbl_zweck.bezeichnung,
@@ -461,6 +512,7 @@ if (isset($_REQUEST["xmlformat"]) && $_REQUEST["xmlformat"] == "xml")
$abschlusspruefungsdatum = '';
$abschlussbeurteilung='';
$pruefungstyp_kurzbz='';
$abschlussbeurteilung_deutsch = '';
if($db->db_query($qry))
{
+21 -1
View File
@@ -35,6 +35,7 @@ require_once('../include/studiengang.class.php');
require_once('../include/mitarbeiter.class.php');
require_once('../include/anrechnung.class.php');
require_once('../include/prestudent.class.php');
require_once('../include/nation.class.php');
$datum = new datum();
$db = new basis_db();
@@ -107,7 +108,7 @@ if (isset($_REQUEST["xmlformat"]) && $_REQUEST["xmlformat"] == "xml")
tbl_studiengang.bezeichnung, tbl_studiengang.english, tbl_studentlehrverband.semester,
tbl_person.vorname, tbl_person.vornamen, tbl_person.nachname,tbl_person.gebdatum,tbl_person.titelpre,
tbl_person.titelpost, tbl_person.anrede, tbl_studiensemester.bezeichnung as sembezeichnung,
tbl_studiensemester.studiensemester_kurzbz as stsem, tbl_student.prestudent_id, tbl_studiengang.max_semester
tbl_studiensemester.studiensemester_kurzbz as stsem, tbl_student.prestudent_id, tbl_studiengang.max_semester, tbl_person.gebort, tbl_person.geburtsnation, tbl_person.geschlecht
FROM tbl_person, tbl_student, tbl_studiengang, tbl_benutzer, tbl_studentlehrverband, tbl_studiensemester
WHERE tbl_student.studiengang_kz = tbl_studiengang.studiengang_kz
AND tbl_student.student_uid = tbl_benutzer.uid AND tbl_benutzer.person_id = tbl_person.person_id
@@ -187,6 +188,10 @@ if (isset($_REQUEST["xmlformat"]) && $_REQUEST["xmlformat"] == "xml")
else
$studiengang_kz = sprintf("%04s", abs($row->studiengang_kz));
$nation = new nation($row->geburtsnation);
$geburtsnation = $nation->kurztext;
$xml .= " <studiengang_art><![CDATA[".$bezeichnung."]]></studiengang_art>";
$xml .= " <studiengang_kz><![CDATA[".$studiengang_kz."]]></studiengang_kz>";
$xml .= "\n <anrede><![CDATA[".$row->anrede."]]></anrede>";
@@ -195,6 +200,9 @@ if (isset($_REQUEST["xmlformat"]) && $_REQUEST["xmlformat"] == "xml")
$xml .= " <name><![CDATA[".trim($row->titelpre.' '.trim($row->vorname.' '.$row->vornamen).' '.$row->nachname.($row->titelpost!=''?', '.$row->titelpost:''))."]]></name>";
$gebdatum = date('d.m.Y',strtotime($row->gebdatum));
$xml .= " <gebdatum><![CDATA[".$gebdatum."]]></gebdatum>";
$xml .= " <gebort><![CDATA[".$row->gebort."]]></gebort>";
$xml .= " <geburtsnation><![CDATA[".$geburtsnation."]]></geburtsnation>";
$xml .= " <geschlecht><![CDATA[".$row->geschlecht."]]></geschlecht>";
$xml .= " <matrikelnr><![CDATA[".trim($row->matrikelnr)."]]></matrikelnr>";
$xml .= " <studiengangsleiter><![CDATA[".$stgl."]]></studiengangsleiter>";
$datum_aktuell = date('d.m.Y');
@@ -267,6 +275,15 @@ if (isset($_REQUEST["xmlformat"]) && $_REQUEST["xmlformat"] == "xml")
if ($lastPrestudentStatus)
$showAllNoten = $prestudent->status_kurzbz === 'Incoming';
$lastBenotungsdatum = '';
$dates = array_column($obj->result, 'benotungsdatum');
if (!empty($dates))
{
$lastBenotungsdatum = max($dates);
$xml .= "<last_benotungsdatum><![CDATA[".date('d.m.Y', strtotime($lastBenotungsdatum))."]]></last_benotungsdatum>";
}
foreach ($obj->result as $row)
{
if($showAllNoten || $row->zeugnis)
@@ -390,12 +407,15 @@ if (isset($_REQUEST["xmlformat"]) && $_REQUEST["xmlformat"] == "xml")
}
}
$xml .= "\n <unterrichtsfach>";
$xml .= " <benotungsdatum><![CDATA[".date('d.m.Y', strtotime($row->benotungsdatum))."]]></benotungsdatum>";
$xml .= " <bezeichnung><![CDATA[".$bezeichnung."]]></bezeichnung>";
$xml .= " <bezeichnung_englisch><![CDATA[".$bezeichnung_englisch."]]></bezeichnung_englisch>";
$xml .= " <note_positiv><![CDATA[".$row->note_positiv."]]></note_positiv>";
$xml .= " <note><![CDATA[".$note2."]]></note>";
$xml .= " <sws><![CDATA[".($row->semesterstunden==0?'':number_format(sprintf('%.1F',$row->semesterstunden/$wochen),1))."]]></sws>";
$xml .= " <sws_lv><![CDATA[".($row->sws==0?'':number_format(sprintf('%.1F',$row->sws),1))."]]></sws_lv>";
$xml .= " <lv_id><![CDATA[".$row->lehrveranstaltung_id."]]></lv_id>";
$ectspunkte='';
$anrechnung = new anrechnung();
-123
View File
@@ -1,123 +0,0 @@
<?php
function lineBreak()
{
return IS_CLI ? PHP_EOL : '<br>';
}
function preFormat($text)
{
if (IS_CLI) {
return $text; // Plain text in CLI
} else {
return "<pre>$text</pre>"; // HTML preformatted in browser
}
}
function colorText($text, $color)
{
if (IS_CLI) {
// ANSI color codes
$colors = [
'red' => "\033[31m",
'green' => "\033[32m",
'reset' => "\033[0m",
];
return $colors[$color] . $text . $colors['reset'];
} else {
// HTML styles
$styles = [
'red' => "<b style='color:red;'>$text</b>",
'green' => "<b style='color:green;'>$text</b>",
];
return $styles[$color];
}
}
function assertEqual($expected, $actual, $message = '')
{
if ($expected !== $actual) {
echo colorText('❌ Assertion failed:', 'red') . ' ' . $message . lineBreak();
echo "Expected: " . preFormat(var_export($expected, true)) . lineBreak();
echo "Actual: " . preFormat(var_export($actual, true)) . lineBreak();
return false;
} else {
echo colorText('✅ Passed:', 'green') . ' ' . $message . lineBreak();
return true;
}
}
function assertTrue($condition, $message = '')
{
return assertEqual(true, $condition, $message ?: 'Expected condition to be true');
}
function assertFalse($condition, $message = '')
{
return assertEqual(false, $condition, $message ?: 'Expected condition to be false');
}
function assertNull($value, $message = '')
{
return assertEqual(null, $value, $message ?: 'Expected value to be null');
}
function assertNotNull($value, $message = '')
{
if ($value === null) {
echo colorText('❌ Assertion failed:', 'red') . ' ' . $message . lineBreak();
echo 'Value is null' . lineBreak();
return false;
} else {
echo colorText('✅ Passed:', 'green') . ' ' . $message . lineBreak();
return true;
}
}
function assertIsArray($value, $message = '')
{
return assertEqual(true, is_array($value), $message ?: 'Expected value to be an array');
}
function assertIsObject($value, $message = '')
{
return assertEqual(true, is_object($value), $message ?: 'Expected value to be an object');
}
function assertIsString($value, $message = '')
{
return assertEqual(true, is_string($value), $message ?: 'Expected value to be a string');
}
function assertIsInt($value, $message = '')
{
return assertEqual(true, is_int($value), $message ?: 'Expected value to be an integer');
}
function assertIsFloat($value, $message = '')
{
return assertEqual(true, is_float($value), $message ?: 'Expected value to be a float');
}
function assertIsBool($value, $message = '')
{
return assertEqual(true, is_bool($value), $message ?: 'Expected value to be a boolean');
}
function assertArrayHasKey($key, $array, $message = '')
{
return assertEqual(true, array_key_exists($key, $array), $message ?: "Expected key '$key' in array");
}
function assertObjectHasProperty($property, $object, $message = '')
{
return assertEqual(true, property_exists($object, $property), $message ?: "Expected property '$property' in object");
}
function assertCount($expectedCount, $arrayOrCountable, $message = '')
{
return assertEqual($expectedCount, count($arrayOrCountable), $message ?: "Expected count of $expectedCount");
}
@@ -1,214 +0,0 @@
<?php
function getParam($name, $default = null)
{
if (php_sapi_name() === 'cli') { // Parse CLI args for --key=value style
// php ./system/UnitTests/api/BookmarkTest/BookmarkTest.php
// --server=https://cis40.dev.technikum-wien.at --user=if23b236 --pw=FHCompleteDemo42!
global $argv;
foreach ($argv as $arg) {
if (strpos($arg, '--' . $name . '=') === 0) {
return substr($arg, strlen($name) + 3);
}
}
return $default;
} else {// Browser: use $_GET
// https://c3p0.ma0646.technikum-wien.at/fhcompletecis4/system/UnitTests/api/BookmarkTest
// /BookmarkTest.php?server=https://c3p0.ma0646.technikum-wien.at&user=if23b236&pw=FHCompleteDemo42!
return isset($_GET[$name]) ? $_GET[$name] : $default;
}
}
define('IS_CLI', php_sapi_name() === 'cli');
define('LINE_BREAK', IS_CLI ? PHP_EOL : '<br>');
define('PROJECT_ROOT', realpath(__DIR__ . '/../../../../'));
echo "Test Suite Bookmark start".LINE_BREAK;
if (!IS_CLI) echo "<pre>";
require_once(PROJECT_ROOT . '/config/cis.config.inc.php');
require_once(PROJECT_ROOT . '/vendor/nategood/httpful/bootstrap.php');
require_once(PROJECT_ROOT . '/system/UnitTests/AssertionHelpers.php');
echo "Requirements loaded".LINE_BREAK;
$server = getParam('server', APP_ROOT);
echo $server.LINE_BREAK;
$TEST_USER = getParam('user', 'defaultuser'); //if23b236
echo $TEST_USER.LINE_BREAK;
$TEST_PW = getParam('pw', 'defaultpass'); //FHCompleteDemo42!
echo $TEST_PW.LINE_BREAK;
// "Unit Test" Script to Test API Controller frontend/v1/Bookmark.php by calling methods with curated inputs and checking
// for the expected output
$URL = $server.'/cis.php/api/frontend/v1/Bookmark/';
testGetBookmarks($URL, 'getBookmarks', $TEST_USER, $TEST_PW);
$id = testInsertBookmark($URL, 'insert', $TEST_USER, $TEST_PW);
$id = testUpdateBookmark($URL, 'update', $TEST_USER, $TEST_PW, $id);
testDeleteBookmark($URL, 'delete', $TEST_USER, $TEST_PW, $id);
if (!IS_CLI) echo "<pre>";
function testGetBookmarks($url, $method, $user, $pw)
{
echo LINE_BREAK.LINE_BREAK."Test '".$method."' start ".LINE_BREAK;
try {
$resultPost = \Httpful\Request::get($url.$method)
->expectsJson()
->authenticateWith($user, $pw)
->send();
} catch(\Httpful\Exception\ConnectionErrorException $cee) // Httpful exception
{
echo $cee;
}
catch (Exception $e) // any other exception
{
echo $e;
}
$assertions = [];
$assertions[] = assertIsArray($resultPost->body->data);
$assertions[] = assertIsString($resultPost->body->meta->status);
$assertions[] = assertEqual($resultPost->body->meta->status, "success", "Response Status Success");
if(allTrue($assertions)) {
echo "Test '".$method."' finished SUCCESS".LINE_BREAK;
} else {
echo "Test '".$method."' finished FAIL".LINE_BREAK;
printResponse($resultPost);
}
}
function testInsertBookmark($url, $method, $user, $pw)
{
echo LINE_BREAK.LINE_BREAK."Test '".$method."' start ".LINE_BREAK;
echo LINE_BREAK;
try {
$bodyTitle = 'orf';
$bodyUrl = 'https://orf.at';
$resultPost = \Httpful\Request::post($url.$method)
->expectsJson()
->authenticateWith($user, $pw)
->sendsJson()
->body('{"title": "'.$bodyTitle.'", "url": "'.$bodyUrl.'"}')
->send();
} catch(\Httpful\Exception\ConnectionErrorException $cee) // Httpful exception
{
echo $cee;
}
catch (Exception $e) // any other exception
{
echo $e;
}
$assertions = [];
$assertions[] = assertIsInt($resultPost->body->data);
$assertions[] = assertIsString($resultPost->body->meta->status);
$assertions[] = assertEqual("success", $resultPost->body->meta->status, "Response Status Success");
if(allTrue($assertions)) {
echo "Test '".$method."' finished SUCCESS".LINE_BREAK;
} else {
echo "Test '".$method."' finished FAIL".LINE_BREAK;
printResponse($resultPost);
}
return $resultPost->body->data;
}
function testDeleteBookmark($url, $method, $user, $pw, $id)
{
echo LINE_BREAK.LINE_BREAK."Test '".$method."' start ".LINE_BREAK;
try {
$resultPost = \Httpful\Request::post($url.$method.'/'.$id)
->expectsJson()
->authenticateWith($user, $pw)
->sendsJson()
->send();
} catch(\Httpful\Exception\ConnectionErrorException $cee) // Httpful exception
{
echo $cee;
}
catch (Exception $e) // any other exception
{
echo $e;
}
$assertions = [];
$assertions[] = assertIsString($resultPost->body->data);
$assertions[] = assertIsString($resultPost->body->meta->status);
$assertions[] = assertEqual("success", $resultPost->body->meta->status, "Response Status Success");
if(allTrue($assertions)) {
echo "Test '".$method."' finished SUCCESS".LINE_BREAK;
} else {
echo "Test '".$method."' finished FAIL".LINE_BREAK;
printResponse($resultPost);
}
}
function testUpdateBookmark($url, $method, $user, $pw, $id)
{
echo LINE_BREAK.LINE_BREAK."Test '".$method."' start ".LINE_BREAK;
try {
$bodyTitle = 'orf title updated';
$bodyUrl = 'https://orf.at';
$resultPost = \Httpful\Request::post($url.$method.'/'.$id)
->expectsJson()
->authenticateWith($user, $pw)
->body('{"title": "'.$bodyTitle.'", "url": "'.$bodyUrl.'"}')
->sendsJson()
->send();
} catch(\Httpful\Exception\ConnectionErrorException $cee) // Httpful exception
{
echo $cee;
}
catch (Exception $e) // any other exception
{
echo $e;
}
$assertions = [];
$assertions[] = assertIsString($resultPost->body->data);
$assertions[] = assertIsString($resultPost->body->meta->status);
$assertions[] = assertEqual("success", $resultPost->body->meta->status, "Response Status Success");
if(allTrue($assertions)) {
echo "Test '".$method."' finished SUCCESS".LINE_BREAK;
} else {
echo "Test '".$method."' finished FAIL".LINE_BREAK;
printResponse($resultPost);
}
return $resultPost->body->data;
}
function printResponse($resultPost)
{
echo LINE_BREAK;
echo "Response Body:";
echo preFormat(var_export($resultPost->body, true));
echo LINE_BREAK;
echo "Raw Response:";
echo preFormat(var_export($resultPost->raw_body, true));
echo LINE_BREAK;
echo "Status Code:";
echo preFormat(var_export($resultPost->code, true));
echo LINE_BREAK;
echo "Headers:";
echo preFormat(var_export($resultPost->headers, true));
echo LINE_BREAK;
}
function allTrue($arr)
{
return count(array_filter($arr, function ($v) {
return $v === true;
})) === count($arr);
}
+16
View File
@@ -324,6 +324,22 @@ $fehlerArr = array(
'fehlertext' => 'Es sind mehrere oder keine Zustelladressen eingetragen',
'fehlertyp_kurzbz' => 'error',
'app' => 'core'
),
array(
'fehlercode' => 'CORE_PERSON_0005',
'fehler_kurzbz' => 'geburtsnationFehlt',
'fehlercode_extern' => null,
'fehlertext' => 'Geburtsnation nicht vorhanden',
'fehlertyp_kurzbz' => 'error',
'app' => 'core'
),
array(
'fehlercode' => 'CORE_PERSON_0006',
'fehler_kurzbz' => 'uhstatPersonkennungFehltCore',
'fehlercode_extern' => null,
'fehlertext' => 'Personkennung fehlt (vBpk AS, vBpk BF oder Ersatzkennzeichen fehlt)',
'fehlertyp_kurzbz' => 'error',
'app' => 'core'
)
/** Plausichecks end **/
);
+491 -11
View File
@@ -18428,6 +18428,26 @@ array(
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'studentstatus',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Studentstatus',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Student status',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
@@ -19331,13 +19351,33 @@ array(
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Maßnahmen - geplant',
'text' => 'Maßnahme - geplant',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Measures - planned',
'text' => 'Measure - planned',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'geplanteMassnahmenDesc',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Die Maßhname wurde geplant.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'The measure was planned.',
'description' => '',
'insertvon' => 'system'
)
@@ -19391,13 +19431,13 @@ array(
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Maßnahmen - durchgeführt',
'text' => 'Maßnahme - durchgeführt',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Measures - performed',
'text' => 'Measure - performed',
'description' => '',
'insertvon' => 'system'
)
@@ -19431,13 +19471,13 @@ array(
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Maßnahmen - abgelehnt',
'text' => 'Maßnahme - abgelehnt',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Measures - declined',
'text' => 'Measure - declined',
'description' => '',
'insertvon' => 'system'
)
@@ -19531,13 +19571,13 @@ array(
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Anmerkung - Studiengangsleitung',
'text' => 'Begründung - Studiengangsleitung',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Note - Study course Director',
'text' => 'Reason - Study course Director',
'description' => '',
'insertvon' => 'system'
)
@@ -19563,6 +19603,26 @@ array(
)
)
),
array(
'app' => 'international',
'category' => 'international',
'phrase' => 'stgtodo',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Nur offene Massnahmen',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'only open measures',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'international',
'category' => 'international',
@@ -30024,6 +30084,26 @@ array(
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'entschuldigungStatusUpdateAutoEmailBetreff',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Entschuldigung Status Update.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Excuse note status update.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
@@ -31352,7 +31432,7 @@ array(
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Termine laut Stundenplan',
'text' => 'Unterricht laut Stundenplan',
'description' => '',
'insertvon' => 'system'
),
@@ -31364,6 +31444,26 @@ array(
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'unterrichtDauer',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Unterricht Dauer',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Lesson Duration',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
@@ -31432,13 +31532,13 @@ array(
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Keine zugeteilten Studenten gefunden!',
'text' => 'Keine zugeteilten Studenten gefunden für den gewählten LV-Teil gefunden!',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'No assigned students found!',
'text' => 'No assigned students for the selected teaching unit found!',
'description' => '',
'insertvon' => 'system'
)
@@ -31744,6 +31844,86 @@ array(
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'kontrollDauerUnterMindestwert',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Kontrolle muss für eine Unterrichtsdauer von mindestens {0} Minuten gelten.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Attendance check must apply for a lesson duration of at least {0} minutes.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'zeitNichtAusStundenplanBeginn',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Unterrichtbeginn entspricht keinem Unterrichtstermin laut Stundenplan.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Lecture Begin Time does not match a lesson as per timetable.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'zeitNichtAusStundenplanEnde',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Unterrichtende entspricht keinem Unterrichtstermin laut Stundenplan.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Lecture End Time does not match a lesson as per timetable.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'datumNichtAusStundenplan',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Datum entspricht keinem Stundenplan Termin.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Date does not match a lesson as per timetable.',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
@@ -31940,6 +32120,306 @@ array(
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'anwTimeline',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Digitale Anwesenheiten Timeline',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Digital Attendances Timeline',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'entschuldigungEdit',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Entschuldigung bearbeiten',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Excuse Note Edit',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'excuseUploadNoFile',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Dokument wird nachgereicht',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Document will be submitted later',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'entschuldigungEditieren',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Entschuldigung bearbeiten',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Edit Excuse Note',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'missingEntschuldigungFile',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Fehlendes Dokument!',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Missing Document!',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'anwKontrolleVon',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Unterricht von',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Lesson from',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'anwKontrolleBis',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Unterricht bis',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Lesson until',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'termineAusStundenplan',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Unterricht Termine laut Stundenplan',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Lesson dates according to timetable',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'tooltipUnterrichtZeitCustom',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Unterrichtszeiten werden aus dem Stundenplan geladen, überschreiben Sie diese nur falls Ihre tatsächliche Unterrichtszeiten davon abweichen!',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Lesson times are loaded from the timetable, only overwrite them if your actual lesson times differ!',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'tooltipUnterrichtDatumCustom',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Unterrichtsdaten werden aus dem Stundenplan geladen, überschreiben Sie dieses nur falls Ihr tatsächliches Unterrichtsdatum abweicht!',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Class dates are loaded from the timetable, only overwrite this if your actual class date differs!',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'unterrichtzeit',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Unterrichtszeiten',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Lesson Times',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'statusLegende',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Status Legende',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Status Legend',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'download',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Herunterladen',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Download',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'upload',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Hochladen',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Upload',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'providedDateTooOld',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Angegebenes Datum ist älter als erlaubt.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Provided date is older than allowed date',
'description' => '',
'insertvon' => 'system'
)
)
),
//
// DIGITALE ANWESENHEITEN PHRASEN END
//
@@ -0,0 +1,143 @@
<?php
/**
* Verifies that properties are declared correctly.
*
* NOTE: It simply overrides the method processMemberVar of the Standards\PSR2\Sniffs\Classes\PropertyDeclarationSniff class
*
*/
namespace PHP_CodeSniffer\Standards\FHComplete\Sniffs\Classes;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\AbstractVariableSniff;
use PHP_CodeSniffer\Util\Tokens;
use PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes\PropertyDeclarationSniff;
class FHCPropertyDeclarationSniff extends PropertyDeclarationSniff
{
/**
* Processes the function tokens within the class.
*
* NOTE: it does not check if the property name starts with an underscore "_"
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found.
* @param int $stackPtr The position where the token was found.
*
* @return void
*/
protected function processMemberVar(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
// Detect multiple properties defined at the same time. Throw an error
// for this, but also only process the first property in the list so we don't
// repeat errors.
$find = Tokens::$scopeModifiers;
$find[] = T_VARIABLE;
$find[] = T_VAR;
$find[] = T_SEMICOLON;
$find[] = T_OPEN_CURLY_BRACKET;
$prev = $phpcsFile->findPrevious($find, ($stackPtr - 1));
if ($tokens[$prev]['code'] === T_VARIABLE) {
return;
}
if ($tokens[$prev]['code'] === T_VAR) {
$error = 'The var keyword must not be used to declare a property';
$phpcsFile->addError($error, $stackPtr, 'VarUsed');
}
$next = $phpcsFile->findNext([T_VARIABLE, T_SEMICOLON], ($stackPtr + 1));
if ($next !== false && $tokens[$next]['code'] === T_VARIABLE) {
$error = 'There must not be more than one property declared per statement';
$phpcsFile->addError($error, $stackPtr, 'Multiple');
}
try {
$propertyInfo = $phpcsFile->getMemberProperties($stackPtr);
if (empty($propertyInfo) === true) {
return;
}
} catch (\Exception $e) {
// Turns out not to be a property after all.
return;
}
if ($propertyInfo['type'] !== '') {
$typeToken = $propertyInfo['type_end_token'];
$error = 'There must be 1 space after the property type declaration; %s found';
if ($tokens[($typeToken + 1)]['code'] !== T_WHITESPACE) {
$data = ['0'];
$fix = $phpcsFile->addFixableError($error, $typeToken, 'SpacingAfterType', $data);
if ($fix === true) {
$phpcsFile->fixer->addContent($typeToken, ' ');
}
} else if ($tokens[($typeToken + 1)]['content'] !== ' ') {
$next = $phpcsFile->findNext(T_WHITESPACE, ($typeToken + 1), null, true);
if ($tokens[$next]['line'] !== $tokens[$typeToken]['line']) {
$found = 'newline';
} else {
$found = $tokens[($typeToken + 1)]['length'];
}
$data = [$found];
$nextNonWs = $phpcsFile->findNext(Tokens::$emptyTokens, ($typeToken + 1), null, true);
if ($nextNonWs !== $next) {
$phpcsFile->addError($error, $typeToken, 'SpacingAfterType', $data);
} else {
$fix = $phpcsFile->addFixableError($error, $typeToken, 'SpacingAfterType', $data);
if ($fix === true) {
if ($found === 'newline') {
$phpcsFile->fixer->beginChangeset();
for ($x = ($typeToken + 1); $x < $next; $x++) {
$phpcsFile->fixer->replaceToken($x, '');
}
$phpcsFile->fixer->addContent($typeToken, ' ');
$phpcsFile->fixer->endChangeset();
} else {
$phpcsFile->fixer->replaceToken(($typeToken + 1), ' ');
}
}
}
}//end if
}//end if
if ($propertyInfo['scope_specified'] === false) {
$error = 'Visibility must be declared on property "%s"';
$data = [$tokens[$stackPtr]['content']];
$phpcsFile->addError($error, $stackPtr, 'ScopeMissing', $data);
}
if ($propertyInfo['scope_specified'] === true && $propertyInfo['is_static'] === true) {
$scopePtr = $phpcsFile->findPrevious(Tokens::$scopeModifiers, ($stackPtr - 1));
$staticPtr = $phpcsFile->findPrevious(T_STATIC, ($stackPtr - 1));
if ($scopePtr < $staticPtr) {
return;
}
$error = 'The static declaration must come after the visibility declaration';
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'StaticBeforeVisibility');
if ($fix === true) {
$phpcsFile->fixer->beginChangeset();
for ($i = ($scopePtr + 1); $scopePtr < $stackPtr; $i++) {
if ($tokens[$i]['code'] !== T_WHITESPACE) {
break;
}
$phpcsFile->fixer->replaceToken($i, '');
}
$phpcsFile->fixer->replaceToken($scopePtr, '');
$phpcsFile->fixer->addContentBefore($staticPtr, $propertyInfo['scope'].' ');
$phpcsFile->fixer->endChangeset();
}
}//end if
}//end processMemberVar()
}//end class
@@ -0,0 +1,101 @@
<?php
/**
* Ensures classes are in camel caps, and the first letter is capitalised.
*
* NOTE:
* - it simply overrides the method process of the Standards\Squiz\Sniffs\Classes\ValidClassNameSniff class
* - it contains a new implementation of PHP_CodeSniffer\Util\Common::isCamelCaps
*
*/
namespace PHP_CodeSniffer\Standards\FHComplete\Sniffs\Classes;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Util\Common;
use PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes\ValidClassNameSniff;
class FHCValidClassNameSniff extends ValidClassNameSniff
{
/**
* Processes this test, when one of its tokens is encountered.
*
* NOTE: it does not check if the class name contains an underscore "_"
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being processed.
* @param int $stackPtr The position of the current token in the
* stack passed in $tokens.
*
* @return void
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
if (isset($tokens[$stackPtr]['scope_opener']) === false) {
$error = 'Possible parse error: %s missing opening or closing brace';
$data = [$tokens[$stackPtr]['content']];
$phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data);
return;
}
// Determine the name of the class or interface. Note that we cannot
// simply look for the first T_STRING because a class name
// starting with the number will be multiple tokens.
$opener = $tokens[$stackPtr]['scope_opener'];
$nameStart = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), $opener, true);
$nameEnd = $phpcsFile->findNext(T_WHITESPACE, $nameStart, $opener);
if ($nameEnd === false) {
$name = $tokens[$nameStart]['content'];
} else {
$name = trim($phpcsFile->getTokensAsString($nameStart, ($nameEnd - $nameStart)));
}
// Check for PascalCase format.
$valid = $this->isCamelCaps($name);
if ($valid === false) {
$type = ucfirst($tokens[$stackPtr]['content']);
$error = '%s name "%s" is not in PascalCase format';
$data = [
$type,
$name,
];
$phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data);
$phpcsFile->recordMetric($stackPtr, 'PascalCase class name', 'no');
} else {
$phpcsFile->recordMetric($stackPtr, 'PascalCase class name', 'yes');
}
}//end process()
/**
* Returns true if the specified string is in the camel caps format.
*
* NOTE:
* - it does not allow the string to start with an underscore "_"
* - it does allow that the string contains an underscore "_"
* - the string must starts with a capitol letter
*
* @param string $string The string the verify.
*
* @return boolean
*/
private function isCamelCaps($string)
{
$legalFirstChar = '[A-Z]';
if (preg_match("/^$legalFirstChar/", $string) === 0) {
return false;
}
// Check that the name only contains legal characters.
$legalChars = 'a-zA-Z0-9_';
if (preg_match("|[^$legalChars]|", substr($string, 1)) > 0) {
return false;
}
return true;
}//end isCamelCaps()
}//end class
@@ -0,0 +1,154 @@
<?php
/**
* Verifies that control statements conform to their coding standards.
*
* NOTE: It simply overrides the method process of the PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\ControlSignatureSniff class
*
*/
namespace PHP_CodeSniffer\Standards\FHComplete\Sniffs\ControlStructures;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Util\Tokens;
use PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\ControlSignatureSniff;
class FHCControlSignatureSniff extends ControlSignatureSniff
{
/**
* Processes this test, when one of its tokens is encountered.
*
* NOTE:
* - Does not force to have whitespaces after the brackets
* - Allows to have a bracket at newline after a control structure, ex:
*
* if (condition)
* {
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
* @param int $stackPtr The position of the current token in the
* stack passed in $tokens.
*
* @return void
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true);
if ($nextNonEmpty === false) {
return;
}
$isAlternative = false;
if (isset($tokens[$stackPtr]['scope_opener']) === true
&& $tokens[$tokens[$stackPtr]['scope_opener']]['code'] === T_COLON
) {
$isAlternative = true;
}
// Single newline after opening brace.
if (isset($tokens[$stackPtr]['scope_opener']) === true) {
$opener = $tokens[$stackPtr]['scope_opener'];
for ($next = ($opener + 1); $next < $phpcsFile->numTokens; $next++) {
$code = $tokens[$next]['code'];
if ($code === T_WHITESPACE
|| ($code === T_INLINE_HTML
&& trim($tokens[$next]['content']) === '')
) {
continue;
}
// Skip all empty tokens on the same line as the opener.
if ($tokens[$next]['line'] === $tokens[$opener]['line']
&& (isset(Tokens::$emptyTokens[$code]) === true
|| $code === T_CLOSE_TAG)
) {
continue;
}
// We found the first bit of a code, or a comment on the
// following line.
break;
}//end for
if ($tokens[$next]['line'] === $tokens[$opener]['line']) {
$error = 'Newline required after opening brace';
$fix = $phpcsFile->addFixableError($error, $opener, 'NewlineAfterOpenBrace');
if ($fix === true) {
$phpcsFile->fixer->beginChangeset();
for ($i = ($opener + 1); $i < $next; $i++) {
if (trim($tokens[$i]['content']) !== '') {
break;
}
// Remove whitespace.
$phpcsFile->fixer->replaceToken($i, '');
}
$phpcsFile->fixer->addContent($opener, $phpcsFile->eolChar);
$phpcsFile->fixer->endChangeset();
}
}//end if
} else if ($tokens[$stackPtr]['code'] === T_WHILE) {
// Zero spaces after parenthesis closer, but only if followed by a semicolon.
$closer = $tokens[$stackPtr]['parenthesis_closer'];
$nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($closer + 1), null, true);
if ($nextNonEmpty !== false && $tokens[$nextNonEmpty]['code'] === T_SEMICOLON) {
$found = 0;
if ($tokens[($closer + 1)]['code'] === T_WHITESPACE) {
if (strpos($tokens[($closer + 1)]['content'], $phpcsFile->eolChar) !== false) {
$found = 'newline';
} else {
$found = $tokens[($closer + 1)]['length'];
}
}
if ($found !== 0) {
$error = 'Expected 0 spaces before semicolon; %s found';
$data = [$found];
$fix = $phpcsFile->addFixableError($error, $closer, 'SpaceBeforeSemicolon', $data);
if ($fix === true) {
$phpcsFile->fixer->replaceToken(($closer + 1), '');
}
}
}
}//end if
// Only want to check multi-keyword structures from here on.
if ($tokens[$stackPtr]['code'] === T_WHILE) {
if (isset($tokens[$stackPtr]['scope_closer']) !== false) {
return;
}
$closer = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true);
if ($closer === false
|| $tokens[$closer]['code'] !== T_CLOSE_CURLY_BRACKET
|| $tokens[$tokens[$closer]['scope_condition']]['code'] !== T_DO
) {
return;
}
} else if ($tokens[$stackPtr]['code'] === T_ELSE
|| $tokens[$stackPtr]['code'] === T_ELSEIF
|| $tokens[$stackPtr]['code'] === T_CATCH
|| $tokens[$stackPtr]['code'] === T_FINALLY
) {
if (isset($tokens[$stackPtr]['scope_opener']) === true
&& $tokens[$tokens[$stackPtr]['scope_opener']]['code'] === T_COLON
) {
// Special case for alternate syntax, where this token is actually
// the closer for the previous block, so there is no spacing to check.
return;
}
$closer = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true);
if ($closer === false || $tokens[$closer]['code'] !== T_CLOSE_CURLY_BRACKET) {
return;
}
} else {
return;
}//end if
}//end process()
}//end class
@@ -0,0 +1,129 @@
<?php
/**
* Checks that the method declaration is correct.
*
* NOTE: It simply overrides the method processTokenWithinScope of the Standards\PSR2\Sniffs\Methods\MethodDeclarationSniff class
*
*/
namespace PHP_CodeSniffer\Standards\FHComplete\Sniffs\Methods;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\AbstractScopeSniff;
use PHP_CodeSniffer\Util\Tokens;
use PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\MethodDeclarationSniff;
class FHCMethodDeclarationSniff extends MethodDeclarationSniff
{
/**
* Processes the function tokens within the class.
*
* NOTE: it does not check if the method name starts with an underscore "_"
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found.
* @param int $stackPtr The position where the token was found.
* @param int $currScope The current scope opener token.
*
* @return void
*/
protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope)
{
$tokens = $phpcsFile->getTokens();
// Determine if this is a function which needs to be examined.
$conditions = $tokens[$stackPtr]['conditions'];
end($conditions);
$deepestScope = key($conditions);
if ($deepestScope !== $currScope) {
return;
}
$methodName = $phpcsFile->getDeclarationName($stackPtr);
if ($methodName === null) {
// Ignore closures.
return;
}
$visibility = 0;
$static = 0;
$abstract = 0;
$final = 0;
$find = (Tokens::$methodPrefixes + Tokens::$emptyTokens);
$prev = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true);
$prefix = $stackPtr;
while (($prefix = $phpcsFile->findPrevious(Tokens::$methodPrefixes, ($prefix - 1), $prev)) !== false) {
switch ($tokens[$prefix]['code']) {
case T_STATIC:
$static = $prefix;
break;
case T_ABSTRACT:
$abstract = $prefix;
break;
case T_FINAL:
$final = $prefix;
break;
default:
$visibility = $prefix;
break;
}
}
$fixes = [];
if ($visibility !== 0 && $final > $visibility) {
$error = 'The final declaration must precede the visibility declaration';
$fix = $phpcsFile->addFixableError($error, $final, 'FinalAfterVisibility');
if ($fix === true) {
$fixes[$final] = '';
$fixes[($final + 1)] = '';
if (isset($fixes[$visibility]) === true) {
$fixes[$visibility] = 'final '.$fixes[$visibility];
} else {
$fixes[$visibility] = 'final '.$tokens[$visibility]['content'];
}
}
}
if ($visibility !== 0 && $abstract > $visibility) {
$error = 'The abstract declaration must precede the visibility declaration';
$fix = $phpcsFile->addFixableError($error, $abstract, 'AbstractAfterVisibility');
if ($fix === true) {
$fixes[$abstract] = '';
$fixes[($abstract + 1)] = '';
if (isset($fixes[$visibility]) === true) {
$fixes[$visibility] = 'abstract '.$fixes[$visibility];
} else {
$fixes[$visibility] = 'abstract '.$tokens[$visibility]['content'];
}
}
}
if ($static !== 0 && $static < $visibility) {
$error = 'The static declaration must come after the visibility declaration';
$fix = $phpcsFile->addFixableError($error, $static, 'StaticBeforeVisibility');
if ($fix === true) {
$fixes[$static] = '';
$fixes[($static + 1)] = '';
if (isset($fixes[$visibility]) === true) {
$fixes[$visibility] .= ' static';
} else {
$fixes[$visibility] = $tokens[$visibility]['content'].' static';
}
}
}
// Batch all the fixes together to reduce the possibility of conflicts.
if (empty($fixes) === false) {
$phpcsFile->fixer->beginChangeset();
foreach ($fixes as $stackPtr => $content) {
$phpcsFile->fixer->replaceToken($stackPtr, $content);
}
$phpcsFile->fixer->endChangeset();
}
}//end processTokenWithinScope()
}//end class
+93
View File
@@ -0,0 +1,93 @@
<?xml version="1.0"?>
<ruleset name="FHComplete">
<description>FHComplete's coding standard</description>
<!-- Ignored directories -->
<exclude-pattern>\.git</exclude-pattern>
<exclude-pattern>vendor</exclude-pattern>
<exclude-pattern>tests</exclude-pattern>
<exclude-pattern>application/controllers/api/v1</exclude-pattern>
<exclude-pattern>application/extensions</exclude-pattern>
<exclude-pattern>addons</exclude-pattern>
<!-- This ruleset is based mainly on the PSR2 standard ruleset, exluding the following rules: -->
<rule ref="PSR2">
<!-- Forces the use of namespaces -->
<exclude name="PSR1.Classes.ClassDeclaration" />
<!-- Forbids the use of underscores at the beginning of properties name -->
<exclude name="PSR2.Classes.PropertyDeclaration" />
<!-- Forbids the use of classes name that contain underscores -->
<exclude name="Squiz.Classes.ValidClassName" />
<!-- Forbids the use inline control structure (ex. an if statement on one line) -->
<exclude name="Generic.ControlStructures.InlineControlStructure" />
<!-- Forces to have the bracket on the same line of the statement -->
<exclude name="Squiz.ControlStructures.ControlSignature" />
<!-- Forces to have in a single file only a class declaration, an if statement outside the class is forbidden -->
<exclude name="PSR1.Files.SideEffects" />
<!-- Forbids to have an empty line at the end of the file -->
<exclude name="PSR2.Files.EndFileNewline" />
<!-- Forbids the use of underscores at the beginning of methods name -->
<exclude name="PSR2.Methods.MethodDeclaration" />
<!-- Forbids the use of tabs -->
<exclude name="Generic.WhiteSpace.DisallowTabIndent" />
</rule>
<!-- Do not prompt any warning about the line length -->
<!-- Prompt an error if the line length is more than 150 -->
<rule ref="Generic.Files.LineLength">
<properties>
<property name="lineLimit" value="9999"/>
<property name="absoluteLineLimit" value="150"/>
</properties>
<exclude-pattern>application/phrases/</exclude-pattern>
</rule>
<!-- No white spaces are allowed in array declaration between brackets -->
<rule ref="Squiz.Arrays.ArrayBracketSpacing"/>
<!-- Ensures all class keywords are lowercase -->
<rule ref="Squiz.Classes.LowercaseClassKeywords"/>
<!-- Forbids the use of TODO in the comments -->
<rule ref="Generic.Commenting.Todo"/>
<!-- Tests that the stars in a doc comment align correctly -->
<rule ref="Squiz.Commenting.DocCommentAlignment"/>
<!-- Ensures the file ends with a newline character -->
<rule ref="Generic.Files.EndFileNewline"/>
<!-- Ensures there is no space after cast tokens -->
<rule ref="Generic.Formatting.NoSpaceAfterCast"/>
<!-- Ensures logical operators 'and' and 'or' are not used -->
<rule ref="Squiz.Operators.ValidLogicalOperators"/>
<!-- Ensure cast statements don't contain whitespace -->
<rule ref="Squiz.WhiteSpace.CastSpacing"/>
<!-- Verifies that operators have valid spacing surrounding them -->
<rule ref="Squiz.WhiteSpace.LogicalOperatorSpacing"/>
<!-- Checks that control structures are defined and indented correctly -->
<!-- The listed tokens are ignored: comment, doc comment open tag, php close tag -->
<rule ref="Generic.WhiteSpace.ScopeIndent">
<properties>
<property name="ignoreIndentationTokens" type="array">
<element value="T_COMMENT"/>
<element value="T_DOC_COMMENT_OPEN_TAG"/>
<element value="T_CLOSE_TAG"/>
</property>
</properties>
</rule>
<!-- Ensure there is no whitespace before a semicolon -->
<rule ref="Squiz.WhiteSpace.SemicolonSpacing"/>
<!-- All rules in ./Sniffs are included automatically -->
<!-- FHComplete sniffs:
- Classes/FHCPropertyDeclarationSniff: class properties checks, it does not check if the property name starts with an underscore "_"
- Classes/FHCValidClassNameSniff: class names checks, it does not check if the class name contains an underscore "_"
- ControlStructures/FHCControlSignatureSniff:
- Does not force to have whitespaces after the brackets
- Allows to have a bracket at newline after a control structure
- Methods/FHCMethodDeclarationSniff: it does not check if the method name starts with an underscore "_"
-->
</ruleset>
+23
View File
@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<ruleset name="Strictly necessary PHPMD rule set"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation=" http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>
Performs the DevelopmentCodeFragment check before the code can be merged into the main branch and then deployed to production
</description>
<!-- Ignored directories -->
<exclude-pattern>\.git</exclude-pattern>
<exclude-pattern>vendor</exclude-pattern>
<exclude-pattern>tests</exclude-pattern>
<exclude-pattern>application/controllers/api/v1</exclude-pattern>
<exclude-pattern>application/extensions</exclude-pattern>
<exclude-pattern>addons</exclude-pattern>
<!-- Import the DevelopmentCodeFragment rule from the design rule set -->
<rule ref="rulesets/design.xml/DevelopmentCodeFragment" />
</ruleset>
+30
View File
@@ -0,0 +1,30 @@
<?xml version="1.0"?>
<ruleset name="Strictly necessary PHPMD rule set"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation=" http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>
Performs the strictly necessary checks before the code can be merged into the main branch and then deployed to production
</description>
<!-- Ignored directories -->
<exclude-pattern>\.git</exclude-pattern>
<exclude-pattern>vendor</exclude-pattern>
<exclude-pattern>tests</exclude-pattern>
<exclude-pattern>application/controllers/api/v1</exclude-pattern>
<exclude-pattern>application/extensions</exclude-pattern>
<exclude-pattern>addons</exclude-pattern>
<!-- Import the clean code rule set -->
<rule ref="rulesets/cleancode.xml">
<!-- Exclude the ElseExpression rule -->
<exclude name="ElseExpression" />
</rule>
<!-- Import the entire unused code rule set -->
<rule ref="rulesets/unusedcode.xml" />
<!-- Import the DevelopmentCodeFragment rule from the design rule set -->
<rule ref="rulesets/design.xml/DevelopmentCodeFragment" />
</ruleset>
+2
View File
@@ -550,6 +550,8 @@ if($orgform_kurzbz != -1)
if($lehrveranstaltung_id != '')
$sql_query.= " AND tbl_lehrveranstaltung.lehrveranstaltung_id=".$db->db_add_param($lehrveranstaltung_id, FHC_INTEGER);
elseif(isset($_GET['delete_lvid']))
$sql_query.= " AND tbl_lehrveranstaltung.lehrveranstaltung_id=".$db->db_add_param(intval($_GET['delete_lvid']), FHC_INTEGER);
if($lehrveranstaltung_name != '')
{
@@ -30,8 +30,6 @@
require_once('../../include/lehrmodus.class.php');
require_once('../../include/benutzerberechtigung.class.php');
require_once('../../include/studienplan.class.php');
require_once('../../include/lehrveranstaltung_faktor.class.php');
require_once('../../include/studiensemester.class.php');
if (!$db = new basis_db())
die('Es konnte keine Verbindung zum Server aufgebaut werden.');
@@ -141,31 +139,6 @@
$reloadstr .= " window.location.href='".$_SERVER['PHP_SELF']."?stg_kz=$lv->studiengang_kz&semester=$lv->semester&neu=true';";
}
$reloadstr .= "</script>\n";
if (in_array($lv->lehrtyp_kurzbz, array('tpl', 'lv')) && $lv->new === true)
{
$lv_faktor = new lehrveranstaltung_faktor();
$studiensemester = new studiensemester();
$studiensemester_von = $studiensemester->getLastOrAktSemester();
if ($lv->lehrtyp_kurzbz === 'lv' && $_POST['lehrveranstaltung_template_id'] !== '')
{
$lv_faktor->getAkt($_POST['lehrveranstaltung_template_id']);
//TODO Faktor in eine Config
if (is_null($lv_faktor->faktor))
$lv_faktor->addFaktor($lv->lehrveranstaltung_id, 2, $studiensemester_von);
else
$lv_faktor->addFaktor($lv->lehrveranstaltung_id, $lv_faktor->faktor, $studiensemester_von);
}
else
{
$lv_faktor->loadByLV($lv->lehrveranstaltung_id);
if (empty($lv_faktor->lv_faktoren))
{
$lv_faktor->addFaktor($lv->lehrveranstaltung_id, 2, $studiensemester_von);
}
}
}
}
}
+14 -2
View File
@@ -192,6 +192,15 @@ $datum_obj = new datum();
die('Invalid Action');
break;
}
if(isset($ampel_id) && $ampel->benutzer_select != '')
{
$anzahlUser = $ampel->getAnzahlUserAmpel($ampel_id);
}
else
{
$anzahlUser = 0;
}
echo '<form action="'.$_SERVER['PHP_SELF'].'?action=save" method="POST">
<input type="hidden" name="new" value="'.htmlspecialchars($new).'">
@@ -207,8 +216,11 @@ $datum_obj = new datum();
<td><input type="text" class="datepicker_datum" name="deadline" size="10" maxlength="10" value="'.htmlspecialchars($datum_obj->formatDatum($ampel->deadline,'Y-m-d')).'" required></td>
</tr>
<tr valign="top">
<td rowspan="3">Benutzer Select</td>
<td rowspan="3"><textarea name="benutzer_select" cols="60" rows="5" required>'.htmlspecialchars($ampel->benutzer_select).'</textarea></td>
<td rowspan="3">Benutzer*innen Select</td>
<td rowspan="3">
<textarea name="benutzer_select" cols="60" rows="5" required>'.htmlspecialchars($ampel->benutzer_select).'</textarea>
<br>Anzahl Benutzer*innen: '.$anzahlUser.'
</td>
<td></td>
<td valign="middle">Vorlaufzeit (in Tagen)&nbsp
<i class="fa fa-info-circle fa-lg" aria-hidden="true" data-toggle="tooltip" data-placement="left" title="Anzahl der Tage VOR der Deadline, an denen die Ampel gezeigt werden soll.&#013Wenn keine Angabe, dann wird die Ampel gleich nach ihrer Erstellung angezeigt."></i>