From 80c35f4b6b367ffc82d11e2e2efb6131d5cb6c9d Mon Sep 17 00:00:00 2001 From: Stefan Puraner Date: Thu, 7 Apr 2016 10:57:03 +0200 Subject: [PATCH 1/5] =?UTF-8?q?Anpassungen=20f=C3=BCr=20KU=20Linz;=20Studi?= =?UTF-8?q?enblatt,=20LV=20Zeugnis,=20Anzeige=20von=20Noten=20kompatibler?= =?UTF-8?q?=20LVs=20im=20Studienplan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + cis/private/lehre/pruefung/pruefung.js | 46 +- .../pruefung/pruefungsanmeldungen_liste.php | 10 +- .../pruefung/pruefungstermin_festlegen.php | 6 +- cis/private/profile/studienplan.php | 40 +- content/fasoverlay.js.php | 3 +- include/anrechnung.class.php | 14 +- rdf/lehrveranstaltungszeugnis_ktu.rdf.php | 49 +- rdf/studienblatt.xml.php | 677 +++++++++--------- 9 files changed, 481 insertions(+), 365 deletions(-) diff --git a/.gitignore b/.gitignore index 599468937..b7cf21913 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ documents/ .settings .project .buildpath +bin diff --git a/cis/private/lehre/pruefung/pruefung.js b/cis/private/lehre/pruefung/pruefung.js index 55fb18bab..8708d574f 100644 --- a/cis/private/lehre/pruefung/pruefung.js +++ b/cis/private/lehre/pruefung/pruefung.js @@ -373,7 +373,7 @@ function showPruefungsDetails(prfId, lvId) { var p = e.pruefung; var l = e.lehrveranstaltung - $("#prfTyp").html(p.pruefungstyp_kurzbz); +// $("#prfTyp").html(p.pruefungstyp_kurzbz); $("#prfMethode").html(p.methode); $("#prfBeschreibung").html(p.beschreibung); if(p.einzeln === true) @@ -689,6 +689,7 @@ function showAnmeldungen(pruefungstermin_id, lehrveranstaltung_id) function writeAnmeldungen(data) { + console.log(data); if(data.error === 'false') { var terminId = data.result.anmeldungen[0].pruefungstermin_id; @@ -755,6 +756,7 @@ function writeAnmeldungen(data) $("#kommentar").empty(); $("#kommentarSpeichernButton").empty(); $("#raumLink").empty(); + $("#listeDrucken").empty(); messageBox("message", data.errormsg, "red", "highlight", 1000); } } @@ -1091,7 +1093,7 @@ function savePruefungstermin() unmarkMissingFormEntry(); var studiensemester_kurzbz = $("#studiensemester").val(); var pruefungsfenster_id = $("#pruefungsfenster").val(); - var pruefungstyp_kurzbz = $("#pruefungsTyp").val(); +// var pruefungstyp_kurzbz = $("#pruefungsTyp").val(); var titel = $("#titel").val(); var beschreibung = $("#beschreibung").val(); var methode = $("#methode").val(); @@ -1168,11 +1170,11 @@ function savePruefungstermin() error = true; markMissingFormEntry("pruefungsfenster"); } - if(is_null(pruefungstyp_kurzbz) || is_undefined(pruefungstyp_kurzbz) || is_empty_String(pruefungstyp_kurzbz) || (pruefungstyp_kurzbz === "undefiniert")) - { - error = true; - markMissingFormEntry("pruefungsTyp"); - } +// if(is_null(pruefungstyp_kurzbz) || is_undefined(pruefungstyp_kurzbz) || is_empty_String(pruefungstyp_kurzbz) || (pruefungstyp_kurzbz === "undefiniert")) +// { +// error = true; +// markMissingFormEntry("pruefungsTyp"); +// } if(is_null(titel) || is_undefined(titel) || is_empty_String(titel)) { error = true; @@ -1188,12 +1190,18 @@ function savePruefungstermin() error = true; markMissingFormEntry("methode"); } - + if(lehrveranstaltungen.length === 0) { error = true; markMissingFormEntry("lvDropdowns"); } + + if(is_null(termine) || is_undefined(termine) || is_empty_String(termine)) + { + error = true; + markMissingFormEntry("prfTermin"); + } if(error) { @@ -1209,7 +1217,7 @@ function savePruefungstermin() method: "savePruefungstermin", studiensemester_kurzbz: studiensemester_kurzbz, pruefungsfenster_id: pruefungsfenster_id, - pruefungstyp_kurzbz: pruefungstyp_kurzbz, +// pruefungstyp_kurzbz: pruefungstyp_kurzbz, titel: titel, beschreibung: beschreibung, methode: methode, @@ -1378,7 +1386,7 @@ function loadPruefungsDetails(prfId) $("#beschreibung").val(result.pruefung.beschreibung); $("#studiensemester").val(result.pruefung.studiensemester_kurzbz); $("#pruefungsfenster").val(result.pruefung.pruefungsfenster_id); - $("#pruefungsTyp").val(result.pruefung.pruefungstyp_kurzbz); +// $("#pruefungsTyp").val(result.pruefung.pruefungstyp_kurzbz); $("#methode").val(result.pruefung.methode); var i = 0; $("#termin1").closest("tr").remove(); @@ -1491,7 +1499,7 @@ function updatePruefung(prfId) unmarkMissingFormEntry(); var studiensemester_kurzbz = $("#studiensemester").val(); var pruefungsfenster_id = $("#pruefungsfenster").val(); - var pruefungstyp_kurzbz = $("#pruefungsTyp").val(); +// var pruefungstyp_kurzbz = $("#pruefungsTyp").val(); var titel = $("#titel").val(); var beschreibung = $("#beschreibung").val(); var methode = $("#methode").val(); @@ -1602,11 +1610,11 @@ function updatePruefung(prfId) error = true; markMissingFormEntry("pruefungsfenster"); } - if(is_null(pruefungstyp_kurzbz) || is_undefined(pruefungstyp_kurzbz) || is_empty_String(pruefungstyp_kurzbz) || (pruefungstyp_kurzbz === "undefiniert")) - { - error = true; - markMissingFormEntry("pruefungsTyp"); - } +// if(is_null(pruefungstyp_kurzbz) || is_undefined(pruefungstyp_kurzbz) || is_empty_String(pruefungstyp_kurzbz) || (pruefungstyp_kurzbz === "undefiniert")) +// { +// error = true; +// markMissingFormEntry("pruefungsTyp"); +// } if(is_null(titel) || is_undefined(titel) || is_empty_String(titel)) { error = true; @@ -1643,7 +1651,7 @@ function updatePruefung(prfId) pruefung_id: prfId, studiensemester_kurzbz: studiensemester_kurzbz, pruefungsfenster_id: pruefungsfenster_id, - pruefungstyp_kurzbz: pruefungstyp_kurzbz, +// pruefungstyp_kurzbz: pruefungstyp_kurzbz, titel: titel, beschreibung: beschreibung, methode: methode, @@ -1807,7 +1815,7 @@ function loadAllPruefungen() }); tableRow+=""; tableRow += ""+e.methode+""; - tableRow += ""+e.pruefungstyp_kurzbz+""; +// tableRow += ""+e.pruefungstyp_kurzbz+""; tableRow += ""+e.einzeln+""; tableRow += ""+e.mitarbeiter_uid+""; tableRow += ""+e.storniert+""; @@ -1896,7 +1904,7 @@ function resetPruefungsverwaltung() loadAllPruefungen(); $("#titel").val(""); $("#beschreibung").val(""); - loadPruefungstypen("false"); +// loadPruefungstypen("false"); loadStudiensemester(); $("#methode").val(""); resetLehrveranstaltungen(); diff --git a/cis/private/lehre/pruefung/pruefungsanmeldungen_liste.php b/cis/private/lehre/pruefung/pruefungsanmeldungen_liste.php index 43d750df5..2f0412fba 100644 --- a/cis/private/lehre/pruefung/pruefungsanmeldungen_liste.php +++ b/cis/private/lehre/pruefung/pruefungsanmeldungen_liste.php @@ -208,7 +208,7 @@ $rechte->getBerechtigungen($uid); $einzeln = TRUE; $pruefungsintervall = $pruefung->pruefungsintervall; } - } + ?> Lehrveranstaltung: bezeichnung?>
Studiensemester: bezeichnung?>
@@ -255,6 +255,14 @@ $rechte->getBerechtigungen($uid); ?> + + Keine bestätigten Anmeldungen vorhanden.
+ diff --git a/cis/private/lehre/pruefung/pruefungstermin_festlegen.php b/cis/private/lehre/pruefung/pruefungstermin_festlegen.php index bfc11ec1f..29310073f 100644 --- a/cis/private/lehre/pruefung/pruefungstermin_festlegen.php +++ b/cis/private/lehre/pruefung/pruefungstermin_festlegen.php @@ -199,14 +199,14 @@ if(empty($lehrveranstaltung->lehrveranstaltungen) && !$rechte->isBerechtigt('leh - + + - + --> Methode: diff --git a/cis/private/profile/studienplan.php b/cis/private/profile/studienplan.php index cf9b3e306..64d85dfdb 100755 --- a/cis/private/profile/studienplan.php +++ b/cis/private/profile/studienplan.php @@ -431,7 +431,7 @@ function drawTree($tree, $depth) echo $icon." ".$termine." lehrveranstaltung_id&language=$sprache','Lehrveranstaltungsinformation','width=700,height=750,resizable=yes,menuebar=no,toolbar=no,status=yes,scrollbars=yes');\">".$row_tree->kurzbz.' - '.$row_tree->bezeichnung.""; else // Bezeichnung der Lehrveranstaltung - echo $icon." ".$termine." ".$row_tree->kurzbz.' - '.$row_tree->bezeichnung; + echo $icon." ".$termine." ".$row_tree->kurzbz.' - '.$row_tree->bezeichnung.'('.$row_tree->lehrveranstaltung_id.')'; echo $bende.''; // Semester @@ -445,6 +445,10 @@ function drawTree($tree, $depth) echo ''; // Note zu dieser LV vorhanden? + + $lv_kompatibel = new lehrveranstaltung(); + $kompatibleLVs = $lv_kompatibel->loadLVkompatibel($row_tree->lehrveranstaltung_id); + if(isset($noten_arr[$row_tree->lehrveranstaltung_id])) { // Positive Note fuer diese LV vorhanden? @@ -460,6 +464,27 @@ function drawTree($tree, $depth) else echo ''.$p->t('studienplan/negativ').''; } + //check if compatible course has grade + elseif(count($kompatibleLVs) > 0) + { + foreach($kompatibleLVs as $komp) + { + if(isset($noten_arr[$komp])) + { + $positiv=false; + foreach($noten_arr[$komp] as $note) + { + if($note_pruef_arr[$note]->positiv) + $positiv=true; + } + + if($positiv) + echo ''.$p->t('studienplan/abgeschlossen').''; + else + echo ''.$p->t('studienplan/negativ').''; + } + } + } else { if($abgeschlossen) @@ -495,6 +520,19 @@ function drawTree($tree, $depth) else $tdinhalt .= ''.$note_pruef_arr[$noten_arr[$row_tree->lehrveranstaltung_id][$stsem]]->anmerkung.''; } + elseif(count($kompatibleLVs) > 0) + { + foreach($kompatibleLVs as $komp) + { + if(isset($noten_arr[$komp][$stsem])) + { + if($note_pruef_arr[$noten_arr[$komp][$stsem]]->positiv) + $tdinhalt .= ''.$note_pruef_arr[$noten_arr[$komp][$stsem]]->anmerkung.''; + else + $tdinhalt .= ''.$note_pruef_arr[$noten_arr[$komp][$stsem]]->anmerkung.''; + } + } + } else { // Angebot der LV und der Kompatiblen pruefen diff --git a/content/fasoverlay.js.php b/content/fasoverlay.js.php index 7a66b2318..4a4b036d9 100644 --- a/content/fasoverlay.js.php +++ b/content/fasoverlay.js.php @@ -1766,6 +1766,7 @@ function PrintZutrittskarte() function PrintStudienblatt(event) { var tree = document.getElementById('student-prestudent-tree-rolle'); + var ss = document.getElementById('statusbarpanel-semester').label; try { @@ -1838,7 +1839,7 @@ function PrintStudienblatt(event) { if(error>0) alert(error+' der ausgewaehlten Personen haben keinen Account'); - action = 'content/pdfExport.php?xsl=Studienblatt&xml=studienblatt.xml.php&output='+output+'&&uid='+data; + action = 'content/pdfExport.php?xsl=Studienblatt&xml=studienblatt.xml.php&output='+output+'&&uid='+data+"&ss="+ss; window.open(action,'Studienblatt','height=520,width=500,left=350,top=350,hotkeys=0,resizable=yes,status=no,scrollbars=yes,toolbar=no,location=no,menubar=no,dependent=yes'); } else diff --git a/include/anrechnung.class.php b/include/anrechnung.class.php index 1e4f6db1e..122e587fa 100644 --- a/include/anrechnung.class.php +++ b/include/anrechnung.class.php @@ -186,13 +186,25 @@ class anrechnung extends basis_db * @param $prestudent_id * @return true wenn ok, false im Fehlerfall */ - public function getAnrechnungPrestudent($prestudent_id) + public function getAnrechnungPrestudent($prestudent_id, $lehrveranstaltung_id=null, $lehrveranstaltung_id_kompatibel=null) { $qry = "SELECT anrechnung_id, prestudent_id, lehrveranstaltung_id, begruendung_id, bezeichnung AS begruendung, " . "lehrveranstaltung_id_kompatibel, genehmigt_von , insertamum, insertvon, updateamum, updatevon " . "FROM lehre.tbl_anrechnung " . "JOIN lehre.tbl_anrechnung_begruendung USING (begruendung_id) " . "WHERE prestudent_id = " . $this->db_add_param($prestudent_id); + + if($lehrveranstaltung_id != NULL) + { + $qry .= " AND lehrveranstaltung_id=".$this->db_add_param($lehrveranstaltung_id); + } + + if($lehrveranstaltung_id_kompatibel != NULL) + { + $qry .= " AND lehrveranstaltung_id_kompatibel=".$this->db_add_param($lehrveranstaltung_id_kompatibel); + } + + $qry .= ";"; if ($this->db_query($qry)) { diff --git a/rdf/lehrveranstaltungszeugnis_ktu.rdf.php b/rdf/lehrveranstaltungszeugnis_ktu.rdf.php index cc47cb5dc..dde2cc71a 100755 --- a/rdf/lehrveranstaltungszeugnis_ktu.rdf.php +++ b/rdf/lehrveranstaltungszeugnis_ktu.rdf.php @@ -36,6 +36,7 @@ require_once('../include/studienplan.class.php'); require_once('../include/student.class.php'); require_once('../include/prestudent.class.php'); require_once('../include/organisationseinheit.class.php'); +require_once('../include/anrechnung.class.php'); $datum = new datum(); $db = new basis_db(); @@ -314,14 +315,60 @@ if (isset($_REQUEST["xmlformat"]) && $_REQUEST["xmlformat"] == "xml") $xml .= " ".$leiter_titel." ".$leiter_vorname." ".$leiter_nachname.($leiter_titelpost!=''?', '.$leiter_titelpost:'').""; $xml .= " "; $xml .= " "; + $lehrveranstaltung->getLVkompatibel($lehrveranstaltung_id); foreach($lehrveranstaltung->lehrveranstaltungen as $lv_kompatibel) { $xml .= "".$lv_kompatibel->bezeichnung.""; } + $xml .= " "; - $return = $lehrveranstaltung->getLVFromStudienplanByLehrtyp($studienplan_id, "modul"); + $anrechnung = new anrechnung(); + +// var_dump($lehrveranstaltung_id); + $anrechnung->getAnrechnungPrestudent($student->prestudent_id, null, $lehrveranstaltung_id); + + $xml .= ""; + $lehrveranstaltung_id_kompatibel = ""; + if(count($anrechnung->result) === 1) + { + $lehrveranstaltung_id_kompatibel = $anrechnung->result[0]->lehrveranstaltung_id; + $xml .= $anrechnung->result[0]->lehrveranstaltung_bez; + } + $xml .= ""; + + $lehrveranstaltung->loadLehrveranstaltungStudienplan($studienplan_id); + + $studienplan_lehrveranstaltung_id = ""; + foreach($lehrveranstaltung->lehrveranstaltungen as $lv) + { + if(($lv->lehrveranstaltung_id == $lehrveranstaltung_id) || ($lv->lehrveranstaltung_id == $lehrveranstaltung_id_kompatibel)) + { + $studienplan_lehrveranstaltung_id = $lv->studienplan_lehrveranstaltung_id; + break; + } + } + + $studienplan = new studienplan(); + if($studienplan_lehrveranstaltung_id != "") + { + $studienplan->loadStudienplanLehrveranstaltung($studienplan_lehrveranstaltung_id); + $lv = new lehrveranstaltung(); + while($lv->lehrtyp_kurzbz != "modul") + { + $lv->load($studienplan->lehrveranstaltung_id); + $studienplan->loadStudienplanLehrveranstaltung($studienplan->studienplan_lehrveranstaltung_id_parent); + } + $lehrveranstaltung->lehrveranstaltungen = array(0 => $lv); + } + else + { + $lehrveranstaltung->lehrveranstaltungen = array(); + } + +// $return = $lehrveranstaltung->getLVFromStudienplanByLehrtyp($studienplan_id, "modul"); + $xml .= " "; //Variable wird zur korrekten Darstellung im Dokument benötigt diff --git a/rdf/studienblatt.xml.php b/rdf/studienblatt.xml.php index 3bf916d13..f057865f6 100644 --- a/rdf/studienblatt.xml.php +++ b/rdf/studienblatt.xml.php @@ -1,339 +1,340 @@ - - * Karl Burkhart - * Manfred Kindl - */ -header("Content-type: application/xhtml+xml"); -require_once('../config/vilesci.config.inc.php'); -require_once('../include/functions.inc.php'); -require_once('../include/studiengang.class.php'); -require_once('../include/student.class.php'); -require_once('../include/prestudent.class.php'); -require_once('../include/adresse.class.php'); -require_once('../include/lehrveranstaltung.class.php'); -require_once('../include/akadgrad.class.php'); -require_once('../include/studiensemester.class.php'); -require_once('../include/nation.class.php'); -require_once('../include/studienordnung.class.php'); -require_once('../include/studienplan.class.php'); -require_once('../include/mitarbeiter.class.php'); -require_once('../include/organisationsform.class.php'); -require_once('../include/zgv.class.php'); -require_once('../include/konto.class.php'); - -$uid_arr = (isset($_REQUEST['uid'])?$_REQUEST['uid']:null); - -$uid_arr = explode(";",$uid_arr); - -echo "\n"; -echo "\n"; - -$uid = isset($uid_arr[1])?$uid_arr[1]:$uid_arr[0]; - -$konto = new konto(); -$student_help = new student(); -// an 2ter stelle da im Aufruf vom FAS ;; der erste immer '' ist -if($student_help->load($uid)) -{ - $studiengang = new studiengang(); - $studiengang->load($student_help->studiengang_kz); - switch($studiengang->typ) - { - case 'b': - $studTyp = 'Bachelor'; - $titel_kurzbz = 'BSc'; - break; - case 'm': - $studTyp = 'Master'; - $titel_kurzbz ='MSc'; - break; - case 'd': - $studTyp = 'Diplom'; - break; - case 'l': - $studTyp = 'Lehrgang'; - break; - case 'k': - $studTyp = 'Kurzstudium'; - break; - default: - $studTyp =''; - $titel_kurzbz = ''; - } - echo "\t".$studTyp."\n"; - echo "\t".$studiengang->bezeichnung."\n"; -} - -foreach($uid_arr as $uid) -{ - if($uid=='') - continue; - - echo "\t\n"; - - $student = new student(); - if($student->load($uid)) - { - $datum_aktuell = date('d.m.Y'); - $gebdatum = date('d.m.Y',strtotime($student->gebdatum)); - $prestudent = new prestudent($student->prestudent_id); - $prestudent->getLastStatus($student->prestudent_id,null,'Student'); - $studienordnung = new studienordnung(); - $studienordnung->getStudienordnungFromStudienplan($prestudent->studienplan_id); - $studiengang = new studiengang(); - $studiengang->load($studienordnung->studiengang_kz); - $studienplan = new studienplan(); - $studienplan->loadStudienplan($prestudent->studienplan_id); - $staatsbuergerschaft = new nation(); - $staatsbuergerschaft->load($student->staatsbuergerschaft); - - - $svnr = ($student->svnr == '')?'Ersatzkennzeichen: '.$student->ersatzkennzeichen:$student->svnr; - - switch($student->geschlecht) - { - case 'm': - $geschlecht = 'Männlich'; - break; - case 'w': - $geschlecht = 'Weiblich'; - break; - case 'u': - $geschlecht = 'Unbekannt'; - break; - default: - $geschlecht =''; - } - - //Wenn Lehrgang, dann Erhalter-KZ vor die Studiengangs-Kz hängen - if ($studienordnung->studiengang_kz<0) - { - $stg = new studiengang(); - $stg->load($studienordnung->studiengang_kz); - - $studiengang_kz = sprintf("%03s", $stg->erhalter_kz).sprintf("%04s", abs($studienordnung->studiengang_kz)); - } - else - $studiengang_kz = sprintf("%04s", abs($studienordnung->studiengang_kz)); - - echo "\t\t1\n"; - echo "\t\t".$uid."\n"; - echo "\t\t".$geschlecht."\n"; - echo "\t\t".$student->anrede."\n"; - echo "\t\t".$student->vorname." ".$student->vornamen."\n"; - echo "\t\t".$student->vornamen."\n"; - echo "\t\t".$student->nachname."\n"; - echo "\t\t".$student->titelpre."\n"; - echo "\t\t".$student->titelpost."\n"; - echo "\t\t".$gebdatum."\n"; - echo "\t\t".$student->gebort."\n"; - echo "\t\t".$staatsbuergerschaft->langtext."\n"; - echo "\t\t".$svnr."\n"; - echo "\t\t".trim($student->matrikelnr)."\n"; - echo "\t\t".$studienordnung->studiengangbezeichnung."\n"; - echo "\t\t".$studienordnung->studiengangbezeichnung_englisch."\n"; - echo "\t\t".$studienordnung->studiengangkurzbzlang."\n"; - echo "\t\t".$studiengang_kz."\n"; - echo "\t\t".$studienplan->sprache.""; - echo "\t\t".$studienordnung->ects.""; - echo "\t\t".($studienplan->regelstudiendauer!=0?$studienordnung->ects/$studienplan->regelstudiendauer:0).""; - - echo "\t\t".date('Y').""; - - echo "\t\t".$prestudent->ausbildungssemester.""; - - $studiensemester_aktuell = new studiensemester(); - $studiensemester_aktuell->load($prestudent->studiensemester_kurzbz); - - echo "\t\t".$studiensemester_aktuell->bezeichnung.""; - - // check ob Oeh-Beitrag bezahlt wurde - $oehbeitrag = $konto->getOehBeitragGesamt($uid, $studiensemester_aktuell->studiensemester_kurzbz); - echo "\t\t".str_replace('.', ',', $oehbeitrag).""; - - // check ob Quereinsteiger - $ausbildungssemester = ($prestudent->getFirstStatus($student->prestudent_id, 'Student'))?$prestudent->ausbildungssemester:''; - echo "\t\t".$ausbildungssemester.""; - - $studiensemester_beginn = new studiensemester(); - $studienbeginn = ($prestudent->getFirstStatus($student->prestudent_id, 'Student'))?$prestudent->studiensemester_kurzbz:''; - $studiensemester_beginn->load($studienbeginn); - - echo "\t\t".$studiensemester_beginn->bezeichnung.""; - echo "\t\t".date('d.m.Y',strtotime($studiensemester_beginn->start)).""; - - $prestudent->getLastStatus($student->prestudent_id,null,'Student'); - $studiensemester_abschluss = new studiensemester(); - $abschluss = $studiensemester_abschluss->jump($prestudent->studiensemester_kurzbz, $studienplan->regelstudiendauer-$prestudent->ausbildungssemester); - $studiensemester_abschluss->load($abschluss); - echo "\t\t".$studiensemester_abschluss->bezeichnung.""; - echo "\t\t".date('d.m.Y',strtotime($studiensemester_abschluss->ende)).""; - - $studiensemester_endedatum = new studiensemester(); - $studiensemester_endedatum->load($studiensemester_endedatum->getaktorNext(1)); - - echo "\t\t".date('d.m.Y',strtotime($studiensemester_endedatum->ende)).""; - - $status_aktuell = ($prestudent->getLastStatus($student->prestudent_id,null,null))?$prestudent->status_kurzbz:''; - - switch($status_aktuell) - { - case 'Student': - $studierendenstatus_aktuell = 'Aktive/r StudentIn'; - break; - case 'Unterbrecher': - $studierendenstatus_aktuell = 'UnterbrecherIn'; - break; - case 'Absolvent': - $studierendenstatus_aktuell = 'AbsolventIn'; - break; - case 'Diplomand': - $studierendenstatus_aktuell = 'DiplomandIn'; - break; - case 'Abbrecher': - $studierendenstatus_aktuell = 'AbbrecherIn'; - break; - default: - $studierendenstatus_aktuell =''; - } - - echo "\t\t".$studierendenstatus_aktuell."\n"; - echo "\t\t".$prestudent->zgvdatum."\n"; - $zgv = new zgv($prestudent->zgv_code); - echo "\t\t".$zgv->zgv_kurzbz."\n"; - echo "\t\t".$studienplan->bezeichnung."\n"; - echo "\t\tanmerkung]]>\n"; - - $titel_kurzbz = ''; - switch($studiengang->typ) - { - case 'b': - $studTyp = 'Bachelor'; - $titel_kurzbz = 'BSc'; - break; - case 'm': - $studTyp = 'Master'; - $titel_kurzbz ='MSc'; - break; - case 'd': - $studTyp = 'Diplom'; - break; - case 'l': - $studTyp = 'Lehrgang'; - break; - case 'k': - $studTyp = 'Kurzstudium'; - break; - default: - $studTyp =''; - $titel_kurzbz = ''; - } - - echo "\t\t".$titel_kurzbz."\n"; - echo "\t\t".$studTyp."\n"; - echo "\t\t".$studienplan->sprache."\n"; - echo "\t\t".$studienplan->regelstudiendauer."\n"; - - $akadgrad = new akadgrad(); - $akadgrad->getAkadgradStudent($student->uid); - - echo "\t\t".$akadgrad->titel."\n"; - echo "\t\t".$akadgrad->akadgrad_kurzbz."\n"; - - //für ao. Studierende wird die StgKz der Lehrveranstaltungen benötigt, die sie besuchen - $lv_studiengang_kz=''; - $lv_studiengang_bezeichnung=''; - $lv_studiengang_typ=''; - - $stg_typ=new studiengang(); - $lv=new lehrveranstaltung(); - $lv->load_lva_student($student->uid); - if(count($lv->lehrveranstaltungen)>0) - { - $lv_studiengang_kz=$lv->lehrveranstaltungen[0]->studiengang_kz; - $lv_studiengang=new studiengang(); - $lv_studiengang->load($lv_studiengang_kz); - $lv_studiengang_bezeichnung=$lv_studiengang->bezeichnung; - $stg_typ->getStudiengangTyp($lv_studiengang->typ); - $lv_studiengang_typ=$stg_typ->bezeichnung; - } - - echo "\t\t".sprintf('%04s', $lv_studiengang_kz).""; - echo "\t\t$lv_studiengang_typ"; - echo "\t\t$lv_studiengang_bezeichnung"; - - echo "\t\t".$datum_aktuell."\n"; - - $adresse = new adresse(); - $adresse->load_pers($student->person_id); - - foreach($adresse->result as $row_adresse) - { - if($row_adresse->zustelladresse) - { - echo "\t\tstrasse]]>\n"; - echo "\t\t".$row_adresse->plz." ".$row_adresse->ort."\n"; - echo "\t\t".$row_adresse->nation."\n"; - break; - } - } - foreach($adresse->result as $row_adresse) - { - if($row_adresse->heimatadresse) - { - echo "\t\tstrasse]]>\n"; - echo "\t\t".$row_adresse->plz." ".$row_adresse->ort."\n"; - echo "\t\t".$row_adresse->nation."\n"; - break; - } - } - $prestudent = new prestudent(); - $prestudent->getLastStatus($student->prestudent_id, null, 'Student'); - - if($prestudent->orgform_kurzbz!='') - $orgform = $prestudent->orgform_kurzbz; - else - $orgform = $studienplan->orgform_kurzbz; - - $orgform_bez = new organisationsform(); - $orgform_bez->load($orgform); - - echo "\t\t".$orgform."\n"; - echo "\t\t".$orgform_bez->bezeichnung."\n"; - - //Studiengangsleiter auslesen - $stg_oe_obj = new studiengang($studienordnung->studiengang_kz); - if ($studienordnung->studiengang_kz=='') - $stgleiter = $stg_oe_obj->getLeitung($student_help->studiengang_kz); - else - $stgleiter = $stg_oe_obj->getLeitung($studienordnung->studiengang_kz); - $stgl=''; - foreach ($stgleiter as $stgleiter_uid) - { - $stgl_ma = new mitarbeiter($stgleiter_uid); - $stgl .= trim($stgl_ma->titelpre.' '.$stgl_ma->vorname.' '.$stgl_ma->nachname.' '.$stgl_ma->titelpost); - } - - echo "\t\t$stgl\n"; - } - echo "\t\n"; -} -echo ""; - + + * Karl Burkhart + * Manfred Kindl + */ +header("Content-type: application/xhtml+xml"); +require_once('../config/vilesci.config.inc.php'); +require_once('../include/functions.inc.php'); +require_once('../include/studiengang.class.php'); +require_once('../include/student.class.php'); +require_once('../include/prestudent.class.php'); +require_once('../include/adresse.class.php'); +require_once('../include/lehrveranstaltung.class.php'); +require_once('../include/akadgrad.class.php'); +require_once('../include/studiensemester.class.php'); +require_once('../include/nation.class.php'); +require_once('../include/studienordnung.class.php'); +require_once('../include/studienplan.class.php'); +require_once('../include/mitarbeiter.class.php'); +require_once('../include/organisationsform.class.php'); +require_once('../include/zgv.class.php'); +require_once('../include/konto.class.php'); + +$uid_arr = (isset($_REQUEST['uid'])?$_REQUEST['uid']:null); +$studiensemester = (isset($_REQUEST['ss'])?$_REQUEST['ss']:null); + +$uid_arr = explode(";",$uid_arr); + +echo "\n"; +echo "\n"; + +$uid = isset($uid_arr[1])?$uid_arr[1]:$uid_arr[0]; + +$konto = new konto(); +$student_help = new student(); +// an 2ter stelle da im Aufruf vom FAS ;; der erste immer '' ist +if($student_help->load($uid)) +{ + $studiengang = new studiengang(); + $studiengang->load($student_help->studiengang_kz); + switch($studiengang->typ) + { + case 'b': + $studTyp = 'Bachelor'; + $titel_kurzbz = 'BSc'; + break; + case 'm': + $studTyp = 'Master'; + $titel_kurzbz ='MSc'; + break; + case 'd': + $studTyp = 'Diplom'; + break; + case 'l': + $studTyp = 'Lehrgang'; + break; + case 'k': + $studTyp = 'Kurzstudium'; + break; + default: + $studTyp =''; + $titel_kurzbz = ''; + } + echo "\t".$studTyp."\n"; + echo "\t".$studiengang->bezeichnung."\n"; +} + +foreach($uid_arr as $uid) +{ + if($uid=='') + continue; + + echo "\t\n"; + + $student = new student(); + if($student->load($uid)) + { + $datum_aktuell = date('d.m.Y'); + $gebdatum = date('d.m.Y',strtotime($student->gebdatum)); + $prestudent = new prestudent($student->prestudent_id); + $prestudent->getLastStatus($student->prestudent_id,$studiensemester,'Student'); + $studienordnung = new studienordnung(); + $studienordnung->getStudienordnungFromStudienplan($prestudent->studienplan_id); + $studiengang = new studiengang(); + $studiengang->load($studienordnung->studiengang_kz); + $studienplan = new studienplan(); + $studienplan->loadStudienplan($prestudent->studienplan_id); + $staatsbuergerschaft = new nation(); + $staatsbuergerschaft->load($student->staatsbuergerschaft); + + + $svnr = ($student->svnr == '')?'Ersatzkennzeichen: '.$student->ersatzkennzeichen:$student->svnr; + + switch($student->geschlecht) + { + case 'm': + $geschlecht = 'Männlich'; + break; + case 'w': + $geschlecht = 'Weiblich'; + break; + case 'u': + $geschlecht = 'Unbekannt'; + break; + default: + $geschlecht =''; + } + + //Wenn Lehrgang, dann Erhalter-KZ vor die Studiengangs-Kz hängen + if ($studienordnung->studiengang_kz<0) + { + $stg = new studiengang(); + $stg->load($studienordnung->studiengang_kz); + + $studiengang_kz = sprintf("%03s", $stg->erhalter_kz).sprintf("%04s", abs($studienordnung->studiengang_kz)); + } + else + $studiengang_kz = sprintf("%04s", abs($studienordnung->studiengang_kz)); + + echo "\t\t1\n"; + echo "\t\t".$uid."\n"; + echo "\t\t".$geschlecht."\n"; + echo "\t\t".$student->anrede."\n"; + echo "\t\t".$student->vorname." ".$student->vornamen."\n"; + echo "\t\t".$student->vornamen."\n"; + echo "\t\t".$student->nachname."\n"; + echo "\t\t".$student->titelpre."\n"; + echo "\t\t".$student->titelpost."\n"; + echo "\t\t".$gebdatum."\n"; + echo "\t\t".$student->gebort."\n"; + echo "\t\t".$staatsbuergerschaft->langtext."\n"; + echo "\t\t".$svnr."\n"; + echo "\t\t".trim($student->matrikelnr)."\n"; + echo "\t\t".$studienordnung->studiengangbezeichnung."\n"; + echo "\t\t".$studienordnung->studiengangbezeichnung_englisch."\n"; + echo "\t\t".$studienordnung->studiengangkurzbzlang."\n"; + echo "\t\t".$studiengang_kz."\n"; + echo "\t\t".$studienplan->sprache.""; + echo "\t\t".$studienordnung->ects.""; + echo "\t\t".($studienplan->regelstudiendauer!=0?$studienordnung->ects/$studienplan->regelstudiendauer:0).""; + + echo "\t\t".date('Y').""; + + echo "\t\t".$prestudent->ausbildungssemester.""; + + $studiensemester_aktuell = new studiensemester(); + $studiensemester_aktuell->load($studiensemester); + + echo "\t\t".$studiensemester_aktuell->bezeichnung.""; + + // check ob Oeh-Beitrag bezahlt wurde + $oehbeitrag = $konto->getOehBeitragGesamt($uid, $studiensemester_aktuell->studiensemester_kurzbz); + echo "\t\t".str_replace('.', ',', $oehbeitrag).""; + + // check ob Quereinsteiger + $ausbildungssemester = ($prestudent->getFirstStatus($student->prestudent_id, 'Student'))?$prestudent->ausbildungssemester:''; + echo "\t\t".$ausbildungssemester.""; + + $studiensemester_beginn = new studiensemester(); + $studienbeginn = ($prestudent->getFirstStatus($student->prestudent_id, 'Student'))?$prestudent->studiensemester_kurzbz:''; + $studiensemester_beginn->load($studienbeginn); + + echo "\t\t".$studiensemester_beginn->bezeichnung.""; + echo "\t\t".date('d.m.Y',strtotime($studiensemester_beginn->start)).""; + + $prestudent->getLastStatus($student->prestudent_id,$studiensemester,'Student'); + $studiensemester_abschluss = new studiensemester(); + $abschluss = $studiensemester_abschluss->jump($prestudent->studiensemester_kurzbz, $studienplan->regelstudiendauer-$prestudent->ausbildungssemester); + $studiensemester_abschluss->load($abschluss); + echo "\t\t".$studiensemester_abschluss->bezeichnung.""; + echo "\t\t".date('d.m.Y',strtotime($studiensemester_abschluss->ende)).""; + + $studiensemester_endedatum = new studiensemester(); + $studiensemester_endedatum->load($studiensemester_endedatum->getaktorNext(1)); + + echo "\t\t".date('d.m.Y',strtotime($studiensemester_endedatum->ende)).""; + + $status_aktuell = ($prestudent->getLastStatus($student->prestudent_id,null,null))?$prestudent->status_kurzbz:''; + + switch($status_aktuell) + { + case 'Student': + $studierendenstatus_aktuell = 'Aktive/r StudentIn'; + break; + case 'Unterbrecher': + $studierendenstatus_aktuell = 'UnterbrecherIn'; + break; + case 'Absolvent': + $studierendenstatus_aktuell = 'AbsolventIn'; + break; + case 'Diplomand': + $studierendenstatus_aktuell = 'DiplomandIn'; + break; + case 'Abbrecher': + $studierendenstatus_aktuell = 'AbbrecherIn'; + break; + default: + $studierendenstatus_aktuell =''; + } + + echo "\t\t".$studierendenstatus_aktuell."\n"; + echo "\t\t".$prestudent->zgvdatum."\n"; + $zgv = new zgv($prestudent->zgv_code); + echo "\t\t".$zgv->zgv_kurzbz."\n"; + echo "\t\t".$studienplan->bezeichnung."\n"; + echo "\t\tanmerkung]]>\n"; + + $titel_kurzbz = ''; + switch($studiengang->typ) + { + case 'b': + $studTyp = 'Bachelor'; + $titel_kurzbz = 'BSc'; + break; + case 'm': + $studTyp = 'Master'; + $titel_kurzbz ='MSc'; + break; + case 'd': + $studTyp = 'Diplom'; + break; + case 'l': + $studTyp = 'Lehrgang'; + break; + case 'k': + $studTyp = 'Kurzstudium'; + break; + default: + $studTyp =''; + $titel_kurzbz = ''; + } + + echo "\t\t".$titel_kurzbz."\n"; + echo "\t\t".$studTyp."\n"; + echo "\t\t".$studienplan->sprache."\n"; + echo "\t\t".$studienplan->regelstudiendauer."\n"; + + $akadgrad = new akadgrad(); + $akadgrad->getAkadgradStudent($student->uid); + + echo "\t\t".$akadgrad->titel."\n"; + echo "\t\t".$akadgrad->akadgrad_kurzbz."\n"; + + //für ao. Studierende wird die StgKz der Lehrveranstaltungen benötigt, die sie besuchen + $lv_studiengang_kz=''; + $lv_studiengang_bezeichnung=''; + $lv_studiengang_typ=''; + + $stg_typ=new studiengang(); + $lv=new lehrveranstaltung(); + $lv->load_lva_student($student->uid); + if(count($lv->lehrveranstaltungen)>0) + { + $lv_studiengang_kz=$lv->lehrveranstaltungen[0]->studiengang_kz; + $lv_studiengang=new studiengang(); + $lv_studiengang->load($lv_studiengang_kz); + $lv_studiengang_bezeichnung=$lv_studiengang->bezeichnung; + $stg_typ->getStudiengangTyp($lv_studiengang->typ); + $lv_studiengang_typ=$stg_typ->bezeichnung; + } + + echo "\t\t".sprintf('%04s', $lv_studiengang_kz).""; + echo "\t\t$lv_studiengang_typ"; + echo "\t\t$lv_studiengang_bezeichnung"; + + echo "\t\t".$datum_aktuell."\n"; + + $adresse = new adresse(); + $adresse->load_pers($student->person_id); + + foreach($adresse->result as $row_adresse) + { + if($row_adresse->zustelladresse) + { + echo "\t\tstrasse]]>\n"; + echo "\t\t".$row_adresse->plz." ".$row_adresse->ort."\n"; + echo "\t\t".$row_adresse->nation."\n"; + break; + } + } + foreach($adresse->result as $row_adresse) + { + if($row_adresse->heimatadresse) + { + echo "\t\tstrasse]]>\n"; + echo "\t\t".$row_adresse->plz." ".$row_adresse->ort."\n"; + echo "\t\t".$row_adresse->nation."\n"; + break; + } + } + $prestudent = new prestudent(); + $prestudent->getLastStatus($student->prestudent_id, null, 'Student'); + + if($prestudent->orgform_kurzbz!='') + $orgform = $prestudent->orgform_kurzbz; + else + $orgform = $studienplan->orgform_kurzbz; + + $orgform_bez = new organisationsform(); + $orgform_bez->load($orgform); + + echo "\t\t".$orgform."\n"; + echo "\t\t".$orgform_bez->bezeichnung."\n"; + + //Studiengangsleiter auslesen + $stg_oe_obj = new studiengang($studienordnung->studiengang_kz); + if ($studienordnung->studiengang_kz=='') + $stgleiter = $stg_oe_obj->getLeitung($student_help->studiengang_kz); + else + $stgleiter = $stg_oe_obj->getLeitung($studienordnung->studiengang_kz); + $stgl=''; + foreach ($stgleiter as $stgleiter_uid) + { + $stgl_ma = new mitarbeiter($stgleiter_uid); + $stgl .= trim($stgl_ma->titelpre.' '.$stgl_ma->vorname.' '.$stgl_ma->nachname.' '.$stgl_ma->titelpost); + } + + echo "\t\t$stgl\n"; + } + echo "\t\n"; +} +echo ""; + ?> \ No newline at end of file From 9c9d862bc8cb08a2dbb86ed7a007d1672ea626e5 Mon Sep 17 00:00:00 2001 From: Stefan Puraner Date: Thu, 7 Apr 2016 11:59:22 +0200 Subject: [PATCH 2/5] validation before printing studienblatt --- content/fasoverlay.js.php | 23 +++++++++++++++++++++-- rdf/lehrveranstaltungszeugnis_ktu.rdf.php | 6 ++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/content/fasoverlay.js.php b/content/fasoverlay.js.php index 4a4b036d9..6c969b15a 100644 --- a/content/fasoverlay.js.php +++ b/content/fasoverlay.js.php @@ -1767,10 +1767,20 @@ function PrintStudienblatt(event) { var tree = document.getElementById('student-prestudent-tree-rolle'); var ss = document.getElementById('statusbarpanel-semester').label; + + var items = tree.view.rowCount; try { - var studienplan_id = getTreeCellText(tree, "student-prestudent-tree-rolle-studienplan_id", 0); + var studienplan_id = ""; + for (var v=0; v < items; v++) + { + var stsem = getTreeCellText(tree, 'student-prestudent-tree-rolle-studiensemester_kurzbz', v); + if(stsem == ss) + { + studienplan_id = getTreeCellText(tree, 'student-prestudent-tree-rolle-studienplan_id', v); + } + } } catch(e) { @@ -1854,10 +1864,19 @@ function PrintStudienblatt(event) function PrintStudienblattEnglisch(event) { var tree = document.getElementById('student-prestudent-tree-rolle'); + var items = tree.view.rowCount; try { - var studienplan_id = getTreeCellText(tree, "student-prestudent-tree-rolle-studienplan_id", 0); + var studienplan_id = ""; + for (var v=0; v < items; v++) + { + var stsem = getTreeCellText(tree, 'student-prestudent-tree-rolle-studiensemester_kurzbz', v); + if(stsem == ss) + { + studienplan_id = getTreeCellText(tree, 'student-prestudent-tree-rolle-studienplan_id', v); + } + } } catch(e) { diff --git a/rdf/lehrveranstaltungszeugnis_ktu.rdf.php b/rdf/lehrveranstaltungszeugnis_ktu.rdf.php index dde2cc71a..b8f4020f9 100755 --- a/rdf/lehrveranstaltungszeugnis_ktu.rdf.php +++ b/rdf/lehrveranstaltungszeugnis_ktu.rdf.php @@ -37,6 +37,7 @@ require_once('../include/student.class.php'); require_once('../include/prestudent.class.php'); require_once('../include/organisationseinheit.class.php'); require_once('../include/anrechnung.class.php'); +require_once('../include/lehrform.class.php'); $datum = new datum(); $db = new basis_db(); @@ -153,6 +154,8 @@ if (isset($_REQUEST["xmlformat"]) && $_REQUEST["xmlformat"] == "xml") $lvbezeichnung = $lehrveranstaltung->bezeichnung; $lvstg = $lehrveranstaltung->studiengang_kz; $lehrform_kurzbz=$lehrveranstaltung->lehrform_kurzbz; + $lehrform = new lehrform($lehrform_kurzbz); + $lehrform_bezeichnung = $lehrform->bezeichnung; $organisationseinheit = new organisationseinheit($lehrveranstaltung->oe_kurzbz); $lehreinheit=new lehreinheit(); @@ -310,6 +313,7 @@ if (isset($_REQUEST["xmlformat"]) && $_REQUEST["xmlformat"] == "xml") $xml .= " ".$datum->formatDatum($benotungsdatum,'d.m.Y').""; $xml .= " ".$datum->formatDatum($uebernahmedatum,'d.m.Y').""; $xml .= " ".$lehrform_kurzbz.""; + $xml .= " ".$lehrform_bezeichnung.""; $xml .= " ".($sws==0?'':number_format(sprintf('%.1F',$sws),1)).""; $xml .= " ".number_format($ects,1).""; $xml .= " ".$leiter_titel." ".$leiter_vorname." ".$leiter_nachname.($leiter_titelpost!=''?', '.$leiter_titelpost:'').""; @@ -325,8 +329,6 @@ if (isset($_REQUEST["xmlformat"]) && $_REQUEST["xmlformat"] == "xml") $xml .= " "; $anrechnung = new anrechnung(); - -// var_dump($lehrveranstaltung_id); $anrechnung->getAnrechnungPrestudent($student->prestudent_id, null, $lehrveranstaltung_id); $xml .= ""; From 6283e923394694099f5136ee122a7e5ee859ef68 Mon Sep 17 00:00:00 2001 From: Gerald Raab Date: Fri, 8 Apr 2016 16:37:00 +0200 Subject: [PATCH 3/5] Codesniffer FHC-Standard --- composer.json | 9 + .../Commenting/DocBlockAlignmentSniff.php | 59 +++ .../Commenting/FunctionCommentSniff.php | 487 ++++++++++++++++++ .../Commenting/FunctionCommentTypeSniff.php | 87 ++++ .../ControlSignatureSniff.php | 58 +++ .../ElseIfDeclarationSniff.php | 48 ++ .../WhileStructuresSniff.php | 56 ++ .../Sniffs/Formatting/OneClassPerUseSniff.php | 48 ++ .../UseInAlphabeticalOrderSniff.php | 142 +++++ .../Functions/ClosureDeclarationSniff.php | 35 ++ ...unctionDeclarationArgumentSpacingSniff.php | 26 + .../CamelCapsMethodNameSniff.php | 98 ++++ .../UpperCaseConstantNameSniff.php | 223 ++++++++ .../ValidClassBracketsSniff.php | 47 ++ .../ValidFunctionNameSniff.php | 138 +++++ .../NamingConventions/ValidTraitNameSniff.php | 48 ++ .../ValidVariableNameSniff.php | 171 ++++++ .../Sniffs/PHP/DisallowShortOpenTagSniff.php | 53 ++ .../Sniffs/PHP/TypeCastingSniff.php | 74 +++ .../Strings/ConcatenationSpacingSniff.php | 48 ++ .../Sniffs/WhiteSpace/CommaSpacingSniff.php | 54 ++ .../WhiteSpace/FunctionCallSpacingSniff.php | 53 ++ .../FunctionClosingBraceSpaceSniff.php | 69 +++ .../FunctionOpeningBraceSpaceSniff.php | 62 +++ .../WhiteSpace/FunctionSpacingSniff.php | 129 +++++ .../WhiteSpace/ObjectOperatorSpacingSniff.php | 42 ++ .../WhiteSpace/OperatorSpacingSniff.php | 185 +++++++ .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 280 ++++++++++ .../Sniffs/WhiteSpace/TabAndSpaceSniff.php | 63 +++ tests/codesniffer/FHComplete/ruleset.xml | 92 ++++ .../tests/FHCompletePHPStandardTest.php | 67 +++ .../FHComplete/tests/TestHelper.php | 54 ++ .../FHComplete/tests/bootstrap.php | 2 + .../tests/files/FHComplete/throws_pass.php | 36 ++ .../FHComplete/tests/files/bad_trait_name.php | 4 + .../tests/files/class_brackets_fail1.php | 4 + .../tests/files/class_brackets_fail2.php | 4 + .../tests/files/class_brackets_fail3.php | 5 + .../files/class_underscore_prefix_pass.php | 18 + .../files/control_structure_brackets_pass.php | 19 + .../tests/files/control_structure_dowhile.php | 6 + .../tests/files/control_structure_elseif.php | 6 + .../files/control_structure_indentation.php | 4 + .../files/control_structure_nobrackets.php | 4 + .../tests/files/control_structure_nospace.php | 4 + .../tests/files/control_structure_while.php | 4 + .../files/control_structures_no_newline.php | 5 + .../tests/files/docblock_align_fail.php | 32 ++ .../tests/files/docblock_align_flat_pass.php | 24 + .../tests/files/docblock_align_pass.php | 29 ++ .../FHComplete/tests/files/double_space.php | 2 + .../tests/files/for_function_comment_pass.php | 15 + .../function_comment_opening_line_fail.php | 13 + .../function_comment_opening_line_pass.php | 14 + .../files/function_comment_type_fail.php | 14 + .../files/function_comment_type_pass.php | 49 ++ .../tests/files/function_spacing.php | 5 + .../FHComplete/tests/files/mixing_indent.php | 6 + .../FHComplete/tests/files/multiple_use.php | 6 + .../tests/files/multiple_use_pass.php | 9 + .../tests/files/operator_spacing_pass.php | 25 + .../tests/files/short_open_tags_fail.php | 9 + .../tests/files/short_open_tags_pass.php | 6 + .../FHComplete/tests/files/space_tab.php | 2 + .../FHComplete/tests/files/tab_space.php | 2 + .../tests/files/traits_no_order.php | 11 + .../FHComplete/tests/files/traits_pass.php | 15 + .../tests/files/type_casting_fail.php | 4 + .../tests/files/type_casting_pass.php | 4 + .../files/use_class_and_closure_pass.php | 22 + .../tests/files/use_closure_pass.php | 8 + .../FHComplete/tests/files/use_no_order.php | 8 + .../FHComplete/tests/files/use_ok_pass.php | 10 + .../tests/files/use_with_commas.php | 7 + .../tests/files/variable_name_pass.php | 45 ++ .../tests/files/whitespace_comma.php | 2 + .../tests/files/whitespace_comma_before.php | 2 + .../tests/files/whitespace_comma_pass.php | 2 + .../codesniffer/FHComplete/tests/ruleset.xml | 52 ++ 79 files changed, 3684 insertions(+) mode change 100644 => 100755 composer.json create mode 100755 tests/codesniffer/FHComplete/Sniffs/Commenting/DocBlockAlignmentSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/Commenting/FunctionCommentSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/Commenting/FunctionCommentTypeSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/ControlStructures/ControlSignatureSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/ControlStructures/ElseIfDeclarationSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/ControlStructures/WhileStructuresSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/Formatting/OneClassPerUseSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/Formatting/UseInAlphabeticalOrderSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/Functions/ClosureDeclarationSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/NamingConventions/CamelCapsMethodNameSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidClassBracketsSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidFunctionNameSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidTraitNameSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidVariableNameSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/PHP/DisallowShortOpenTagSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/PHP/TypeCastingSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/Strings/ConcatenationSpacingSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/WhiteSpace/CommaSpacingSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionCallSpacingSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionSpacingSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/WhiteSpace/OperatorSpacingSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/WhiteSpace/ScopeIndentSniff.php create mode 100755 tests/codesniffer/FHComplete/Sniffs/WhiteSpace/TabAndSpaceSniff.php create mode 100755 tests/codesniffer/FHComplete/ruleset.xml create mode 100755 tests/codesniffer/FHComplete/tests/FHCompletePHPStandardTest.php create mode 100755 tests/codesniffer/FHComplete/tests/TestHelper.php create mode 100755 tests/codesniffer/FHComplete/tests/bootstrap.php create mode 100755 tests/codesniffer/FHComplete/tests/files/FHComplete/throws_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/bad_trait_name.php create mode 100755 tests/codesniffer/FHComplete/tests/files/class_brackets_fail1.php create mode 100755 tests/codesniffer/FHComplete/tests/files/class_brackets_fail2.php create mode 100755 tests/codesniffer/FHComplete/tests/files/class_brackets_fail3.php create mode 100755 tests/codesniffer/FHComplete/tests/files/class_underscore_prefix_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/control_structure_brackets_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/control_structure_dowhile.php create mode 100755 tests/codesniffer/FHComplete/tests/files/control_structure_elseif.php create mode 100755 tests/codesniffer/FHComplete/tests/files/control_structure_indentation.php create mode 100755 tests/codesniffer/FHComplete/tests/files/control_structure_nobrackets.php create mode 100755 tests/codesniffer/FHComplete/tests/files/control_structure_nospace.php create mode 100755 tests/codesniffer/FHComplete/tests/files/control_structure_while.php create mode 100755 tests/codesniffer/FHComplete/tests/files/control_structures_no_newline.php create mode 100755 tests/codesniffer/FHComplete/tests/files/docblock_align_fail.php create mode 100755 tests/codesniffer/FHComplete/tests/files/docblock_align_flat_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/docblock_align_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/double_space.php create mode 100755 tests/codesniffer/FHComplete/tests/files/for_function_comment_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/function_comment_opening_line_fail.php create mode 100755 tests/codesniffer/FHComplete/tests/files/function_comment_opening_line_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/function_comment_type_fail.php create mode 100755 tests/codesniffer/FHComplete/tests/files/function_comment_type_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/function_spacing.php create mode 100755 tests/codesniffer/FHComplete/tests/files/mixing_indent.php create mode 100755 tests/codesniffer/FHComplete/tests/files/multiple_use.php create mode 100755 tests/codesniffer/FHComplete/tests/files/multiple_use_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/operator_spacing_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/short_open_tags_fail.php create mode 100755 tests/codesniffer/FHComplete/tests/files/short_open_tags_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/space_tab.php create mode 100755 tests/codesniffer/FHComplete/tests/files/tab_space.php create mode 100755 tests/codesniffer/FHComplete/tests/files/traits_no_order.php create mode 100755 tests/codesniffer/FHComplete/tests/files/traits_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/type_casting_fail.php create mode 100755 tests/codesniffer/FHComplete/tests/files/type_casting_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/use_class_and_closure_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/use_closure_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/use_no_order.php create mode 100755 tests/codesniffer/FHComplete/tests/files/use_ok_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/use_with_commas.php create mode 100755 tests/codesniffer/FHComplete/tests/files/variable_name_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/files/whitespace_comma.php create mode 100755 tests/codesniffer/FHComplete/tests/files/whitespace_comma_before.php create mode 100755 tests/codesniffer/FHComplete/tests/files/whitespace_comma_pass.php create mode 100755 tests/codesniffer/FHComplete/tests/ruleset.xml diff --git a/composer.json b/composer.json old mode 100644 new mode 100755 index 32278e8dc..a64b8607b --- a/composer.json +++ b/composer.json @@ -5,5 +5,14 @@ "components/bootstrap": "3.3.5", "michelf/php-markdown": "1.5.0" + }, + "require-dev": + { + "squizlabs/php_codesniffer": "2.*", + "fzaninotto/faker": "1.*" + }, + "config": + { + "bin-dir": "bin" } } diff --git a/tests/codesniffer/FHComplete/Sniffs/Commenting/DocBlockAlignmentSniff.php b/tests/codesniffer/FHComplete/Sniffs/Commenting/DocBlockAlignmentSniff.php new file mode 100755 index 000000000..94b5a3e66 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/Commenting/DocBlockAlignmentSniff.php @@ -0,0 +1,59 @@ +getTokens(); + $leftWall = array( + T_CLASS, + T_NAMESPACE, + T_INTERFACE, + T_TRAIT, + T_USE + ); + $oneIndentation = array( + T_FUNCTION, + T_VARIABLE, + T_CONST + ); + $allTokens = array_merge($leftWall, $oneIndentation); + $notFlatFile = $phpcsFile->findNext(T_NAMESPACE, 0); + $next = $phpcsFile->findNext($allTokens, $stackPtr + 1); + + if ($next && $notFlatFile) { + $notWalled = (in_array($tokens[$next]['code'], $leftWall) && $tokens[$stackPtr]['column'] !== 1); + $notIndented = (in_array($tokens[$next]['code'], $oneIndentation) && $tokens[$stackPtr]['column'] !== 5); + if ($notWalled || $notIndented) { + $phpcsFile->addError('Expected docblock to be aligned with code.', $stackPtr, 'NotAllowed'); + } + } + + return; + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/Commenting/FunctionCommentSniff.php b/tests/codesniffer/FHComplete/Sniffs/Commenting/FunctionCommentSniff.php new file mode 100755 index 000000000..34ea7e796 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/Commenting/FunctionCommentSniff.php @@ -0,0 +1,487 @@ + + * @author Marc McIntyre + * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @link http://pear.php.net/package/PHP_CodeSniffer + */ + +if (class_exists('PEAR_Sniffs_Commenting_FunctionCommentSniff', true) === false) { + throw new PHP_CodeSniffer_Exception('Class PEAR_Sniffs_Commenting_FunctionCommentSniff not found'); +} + +/** + * Parses and verifies the doc comments for functions. + * + * Verifies that : + *
    + *
  • A comment exists
  • + *
  • There is a blank newline after the short description
  • + *
  • There is a blank newline between the long and short description
  • + *
  • There is a blank newline between the long description and tags
  • + *
  • Parameter names represent those in the method
  • + *
  • Parameter comments are in the correct order
  • + *
  • Parameter comments are complete
  • + *
  • A type hint is provided for array and custom class
  • + *
  • Type hint matches the actual variable/class type
  • + *
  • A blank line is present before the first and after the last parameter
  • + *
  • A return type exists
  • + *
  • Any throw tag must have a comment
  • + *
  • The tag order and indentation are correct
  • + *
+ * + * @category PHP + * @package PHP_CodeSniffer + * @author Greg Sherwood + * @author Marc McIntyre + * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class FHComplete_Sniffs_Commenting_FunctionCommentSniff extends PEAR_Sniffs_Commenting_FunctionCommentSniff +{ + /** + * Is the comment an inheritdoc? + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return boolean True if the comment is an inheritdoc + */ + protected function isInheritDoc(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + $start = $phpcsFile->findPrevious(T_DOC_COMMENT_OPEN_TAG, $stackPtr - 1); + $end = $phpcsFile->findNext(T_DOC_COMMENT_CLOSE_TAG, $start); + $content = $phpcsFile->getTokensAsString($start, ($end - $start)); + return preg_match('#{@inheritDoc}#', $content) === 1; + } // end isInheritDoc() + + /** + * Process the return comment of this function comment. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processReturn(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart) + { + if ($this->isInheritDoc($phpcsFile, $stackPtr)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + // Skip constructor and destructor. + $className = ''; + foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condition) { + if ($condition === T_CLASS || $condition === T_INTERFACE) { + $className = $phpcsFile->getDeclarationName($condPtr); + $className = strtolower(ltrim($className, '_')); + } + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + $isSpecialMethod = ($methodName === '__construct' || $methodName === '__destruct'); + if ($methodName !== '_') { + $methodName = strtolower(ltrim($methodName, '_')); + } + + $return = null; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@return') { + if ($return !== null) { + $error = 'Only 1 @return tag is allowed in a function comment'; + $phpcsFile->addError($error, $tag, 'DuplicateReturn'); + return; + } + + $return = $tag; + } + } + + if ($isSpecialMethod === true) { + return; + } + + if ($return !== null) { + $content = $tokens[($return + 2)]['content']; + if (empty($content) === true || $tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) { + $error = 'Return type missing for @return tag in function comment'; + $phpcsFile->addError($error, $return, 'MissingReturnType'); + } else { + // Check return type (can be multiple, separated by '|'). + $typeNames = explode('|', $content); + $suggestedNames = array(); + foreach ($typeNames as $i => $typeName) { + if ($typeName === 'integer') { + $suggestedName = 'int'; + } elseif ($typeName === 'boolean') { + $suggestedName = 'bool'; + } elseif (in_array($typeName, array('int', 'bool'))) { + $suggestedName = $typeName; + } else { + $suggestedName = PHP_CodeSniffer::suggestType($typeName); + } + if (in_array($suggestedName, $suggestedNames) === false) { + $suggestedNames[] = $suggestedName; + } + } + + $suggestedType = implode('|', $suggestedNames); + if ($content !== $suggestedType) { + $error = 'Function return type "%s" is invalid'; + $error = 'Expected "%s" but found "%s" for function return type'; + $data = array( + $suggestedType, + $content, + ); + $phpcsFile->addError($error, $return, 'InvalidReturn', $data); + } + + // If the return type is void, make sure there is + // no return statement in the function. + if ($content === 'void') { + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $endToken = $tokens[$stackPtr]['scope_closer']; + for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) { + if ($tokens[$returnToken]['code'] === T_CLOSURE) { + $returnToken = $tokens[$returnToken]['scope_closer']; + continue; + } + + if ($tokens[$returnToken]['code'] === T_RETURN) { + break; + } + } + + if ($returnToken !== $endToken) { + // If the function is not returning anything, just + // exiting, then there is no problem. + $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); + if ($tokens[$semicolon]['code'] !== T_SEMICOLON) { + $error = 'Function return type is void, but function contains return statement'; + $phpcsFile->addWarning($error, $return, 'InvalidReturnVoid'); + } + } + }//end if + } elseif (!preg_match('/^mixed/', $content)) { + // If return type is not void, there needs to be a return statement + // somewhere in the function that returns something. + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $endToken = $tokens[$stackPtr]['scope_closer']; + $returnToken = $phpcsFile->findNext(T_RETURN, $stackPtr, $endToken); + if ($returnToken === false) { + $error = 'Function return type is not void, but function has no return statement'; + $phpcsFile->addWarning($error, $return, 'InvalidNoReturn'); + } elseif (!preg_match('/void/', $content)) { + $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); + if ($tokens[$semicolon]['code'] === T_SEMICOLON) { + $error = 'Function return type is not void, but function is returning void here'; + $phpcsFile->addWarning($error, $returnToken, 'InvalidReturnNotVoid'); + } + } + } + }//end if + }//end if + } else { + $error = 'Missing @return tag in function comment'; + $phpcsFile->addWarning($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn'); + }//end if + + }//end processReturn() + + + /** + * Process any throw tags that this function comment has. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processThrows(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + $throws = array(); + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($tokens[$tag]['content'] !== '@throws') { + continue; + } + + $exception = null; + $comment = null; + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = array(); + preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[($tag + 2)]['content'], $matches); + $exception = $matches[1]; + if (isset($matches[2]) === true) { + $comment = $matches[2]; + } + } + + if ($exception === null) { + $error = 'Exception type and comment missing for @throws tag in function comment'; + $phpcsFile->addWarning($error, $tag, 'InvalidThrows'); + } elseif ($comment === null) { + $error = 'Comment missing for @throws tag in function comment'; + $phpcsFile->addWarning($error, $tag, 'EmptyThrows'); + } else { + // Any strings until the next tag belong to this comment. + if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) { + $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; + } else { + $end = $tokens[$commentStart]['comment_closer']; + } + + for ($i = ($tag + 3); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + $comment .= ' '.$tokens[$i]['content']; + } + } + + // Starts with a capital letter and ends with a fullstop. + $firstChar = $comment{0}; + if (strtoupper($firstChar) !== $firstChar) { + $error = '@throws tag comment must start with a capital letter'; + $phpcsFile->addWarning($error, ($tag + 2), 'ThrowsNotCapital'); + } + + $lastChar = substr($comment, -1); + if ($lastChar !== '.') { + $error = '@throws tag comment must end with a full stop'; + $phpcsFile->addWarning($error, ($tag + 2), 'ThrowsNoFullStop'); + } + }//end if + }//end foreach + + }//end processThrows() + + + /** + * Process the function parameter comments. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart) + { + if ($this->isInheritDoc($phpcsFile, $stackPtr)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $params = array(); + $maxType = 0; + $maxVar = 0; + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($tokens[$tag]['content'] !== '@param') { + continue; + } + + $type = ''; + $typeSpace = 0; + $var = ''; + $varSpace = 0; + $comment = ''; + $commentLines = array(); + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = array(); + preg_match('/([^$&]+)(?:((?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches); + + $typeLen = strlen($matches[1]); + $type = trim($matches[1]); + $typeSpace = ($typeLen - strlen($type)); + $typeLen = strlen($type); + if ($typeLen > $maxType) { + $maxType = $typeLen; + } + + if (isset($matches[2]) === true) { + $var = $matches[2]; + $varLen = strlen($var); + if ($varLen > $maxVar) { + $maxVar = $varLen; + } + + if (isset($matches[4]) === true) { + $varSpace = strlen($matches[3]); + $comment = $matches[4]; + $commentLines[] = array( + 'comment' => $comment, + 'token' => ($tag + 2), + 'indent' => $varSpace, + ); + + // Any strings until the next tag belong to this comment. + if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) { + $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; + } else { + $end = $tokens[$commentStart]['comment_closer']; + } + + for ($i = ($tag + 3); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + $indent = 0; + if ($tokens[($i - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) { + $indent = strlen($tokens[($i - 1)]['content']); + } + + $comment .= ' '.$tokens[$i]['content']; + $commentLines[] = array( + 'comment' => $tokens[$i]['content'], + 'token' => $i, + 'indent' => $indent, + ); + } + } + } else { + $error = 'Missing parameter comment'; + $phpcsFile->addError($error, $tag, 'MissingParamComment'); + $commentLines[] = array('comment' => ''); + }//end if + } else { + $error = 'Missing parameter name'; + $phpcsFile->addError($error, $tag, 'MissingParamName'); + }//end if + } else { + $error = 'Missing parameter type'; + $phpcsFile->addError($error, $tag, 'MissingParamType'); + }//end if + + $params[] = array( + 'tag' => $tag, + 'type' => $type, + 'var' => $var, + 'comment' => $comment, + 'commentLines' => $commentLines, + 'type_space' => $typeSpace, + 'var_space' => $varSpace, + ); + }//end foreach + + $realParams = $phpcsFile->getMethodParameters($stackPtr); + $foundParams = array(); + + foreach ($params as $pos => $param) { + // If the type is empty, the whole line is empty. + if ($param['type'] === '') { + continue; + } + + // Check the param type value. + $typeNames = explode('|', $param['type']); + foreach ($typeNames as $typeName) { + if ($typeName === 'integer') { + $suggestedName = 'int'; + } elseif ($typeName === 'boolean') { + $suggestedName = 'bool'; + } elseif (in_array($typeName, array('int', 'bool'))) { + $suggestedName = $typeName; + } else { + $suggestedName = PHP_CodeSniffer::suggestType($typeName); + } + + if ($typeName !== $suggestedName) { + $error = 'Expected "%s" but found "%s" for parameter type'; + $data = array( + $suggestedName, + $typeName, + ); + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'IncorrectParamVarName', $data); + if ($fix === true) { + $content = $suggestedName; + $content .= str_repeat(' ', $param['type_space']); + $content .= $param['var']; + $content .= str_repeat(' ', $param['var_space']); + $content .= $param['commentLines'][0]['comment']; + $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + } + } + }//end foreach + + if ($param['var'] === '') { + continue; + } + + $foundParams[] = $param['var']; + + // Make sure the param name is correct. + if (isset($realParams[$pos]) === true) { + $realName = $realParams[$pos]['name']; + if ($realName !== $param['var']) { + $code = 'ParamNameNoMatch'; + $data = array( + $param['var'], + $realName, + ); + + $error = 'Doc comment for parameter %s does not match '; + if (strtolower($param['var']) === strtolower($realName)) { + $error .= 'case of '; + $code = 'ParamNameNoCaseMatch'; + } + + $error .= 'actual variable name %s'; + + $phpcsFile->addWarning($error, $param['tag'], $code, $data); + } + } elseif (substr($param['var'], -4) !== ',...') { + // We must have an extra parameter comment. + $error = 'Superfluous parameter comment'; + $phpcsFile->addError($error, $param['tag'], 'ExtraParamComment'); + }//end if + + if ($param['comment'] === '') { + continue; + } + + // Param comments must start with a capital letter and end with the full stop. + $firstChar = $param['comment']{0}; + if (preg_match('|\p{Lu}|u', $firstChar) === 0) { + $error = 'Parameter comment must start with a capital letter'; + $phpcsFile->addWarning($error, $param['tag'], 'ParamCommentNotCapital'); + } + + $lastChar = substr($param['comment'], -1); + if ($lastChar !== '.') { + $error = 'Parameter comment must end with a full stop'; + $phpcsFile->addWarning($error, $param['tag'], 'ParamCommentFullStop'); + } + }//end foreach + + $realNames = array(); + foreach ($realParams as $realParam) { + $realNames[] = $realParam['name']; + } + + // Report missing comments. + $diff = array_diff($realNames, $foundParams); + foreach ($diff as $neededParam) { + $error = 'Doc comment for parameter "%s" missing'; + $data = array($neededParam); + $phpcsFile->addWarning($error, $commentStart, 'MissingParamTag', $data); + } + + }//end processParams() +}//end class diff --git a/tests/codesniffer/FHComplete/Sniffs/Commenting/FunctionCommentTypeSniff.php b/tests/codesniffer/FHComplete/Sniffs/Commenting/FunctionCommentTypeSniff.php new file mode 100755 index 000000000..722661165 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/Commenting/FunctionCommentTypeSniff.php @@ -0,0 +1,87 @@ +getTokens(); + + // We are only interested in function/class/interface doc block comments. + $nextToken = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true); + $ignore = array( + T_CLASS, + T_INTERFACE, + T_FUNCTION, + T_PUBLIC, + T_PRIVATE, + T_PROTECTED, + T_STATIC, + T_ABSTRACT, + ); + + if (in_array($tokens[$nextToken]['code'], $ignore) === false) { + // Could be a file comment. + $prevToken = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prevToken]['code'] !== T_OPEN_TAG) { + return; + } + } + + $types = array( + 'boolean' => 'bool', + 'integer' => 'int', + ); + foreach ($types as $from => $to) { + $this->_check($phpcsFile, $stackPtr, $from, $to); + } + } + + /** + * MyFHComplete_Sniffs_Commenting_DocBlockTypeSniff::_check() + * + * @param int $stackPtr + * @param string $from + * @param string $to + * @return void + */ + protected function _check(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $from, $to) + { + $tokens = $phpcsFile->getTokens(); + $content = $tokens[$stackPtr]['content']; + + $matches = array(); + if (preg_match('/\@(\w+)\s+([\w\\|\\\\]*?)' . $from . '\b/i', $content, $matches) === 0) { + return; + } + + $error = 'Please use "' . $to . '" instead of "' . $from . '" for types in doc blocks.'; + $phpcsFile->addWarning($error, $stackPtr, 'WrongType'); + } + +} diff --git a/tests/codesniffer/FHComplete/Sniffs/ControlStructures/ControlSignatureSniff.php b/tests/codesniffer/FHComplete/Sniffs/ControlStructures/ControlSignatureSniff.php new file mode 100755 index 000000000..b78202cec --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/ControlStructures/ControlSignatureSniff.php @@ -0,0 +1,58 @@ + + * @author Marc McIntyre + * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class FHComplete_Sniffs_ControlStructures_ControlSignatureSniff extends PHP_CodeSniffer_Standards_AbstractPatternSniff +{ + + /** + * If true, comments will be ignored if they are found in the code. + * + * @var boolean + */ + public $ignoreComments = true; + + + /** + * Returns the patterns that this test wishes to verify. + * + * @return string[] + */ + protected function getPatterns() + { + return array( + 'try {EOL...}\s+catch (...)EOL...{EOL...EOL...}', + 'do+EOL...{EOL...EOL...} while (...);EOL', + 'while (...)EOL...{EOL', + 'for (...) {EOL', + 'if (...)EOL...{EOL', + 'foreach (...)EOL...{EOL', + '}EOL...\s+else if (...)EOL...{EOL', + '}EOL...\s+elseif (...)EOL...{EOL', + '}EOL...\s+else+EOL...{EOL', + 'do+EOL...{EOL', + ); + + }//end getPatterns() + + +}//end class diff --git a/tests/codesniffer/FHComplete/Sniffs/ControlStructures/ElseIfDeclarationSniff.php b/tests/codesniffer/FHComplete/Sniffs/ControlStructures/ElseIfDeclarationSniff.php new file mode 100755 index 000000000..1ef2f2aaf --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/ControlStructures/ElseIfDeclarationSniff.php @@ -0,0 +1,48 @@ +getTokens(); + + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$nextToken]['code'] !== T_IF) { + return; + } + + $error = 'Usage of ELSE IF not allowed; use ELSEIF instead'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + } + +} diff --git a/tests/codesniffer/FHComplete/Sniffs/ControlStructures/WhileStructuresSniff.php b/tests/codesniffer/FHComplete/Sniffs/ControlStructures/WhileStructuresSniff.php new file mode 100755 index 000000000..421f86ba6 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/ControlStructures/WhileStructuresSniff.php @@ -0,0 +1,56 @@ +getTokens(); + + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$nextToken]['code'] === T_OPEN_PARENTHESIS) { + $closer = $tokens[$nextToken]['parenthesis_closer']; + $diff = $closer - $stackPtr; + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + $diff + 1), null, true); + } + + if ($tokens[$stackPtr]['code'] === T_WHILE && $tokens[$nextToken]['code'] === T_SEMICOLON) { + /* This while is probably part of a do-while construction, skip it .. */ + return; + } + if ($tokens[$nextToken]['code'] !== T_OPEN_CURLY_BRACKET && $tokens[$nextToken]['code'] !== T_COLON) { + $error = 'Curly brackets required in a do-while or while loop'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + } + } + +} diff --git a/tests/codesniffer/FHComplete/Sniffs/Formatting/OneClassPerUseSniff.php b/tests/codesniffer/FHComplete/Sniffs/Formatting/OneClassPerUseSniff.php new file mode 100755 index 000000000..2b2ee37e6 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/Formatting/OneClassPerUseSniff.php @@ -0,0 +1,48 @@ +getTokens(); + $i = 2; // Ignore use word and whitespace + $filename = $phpcsFile->getFilename(); + + while (in_array($tokens[$stackPtr + $i]['code'], array(T_STRING, T_NS_SEPARATOR, T_WHITESPACE, T_AS))) { + $i++; + } + + if ($tokens[$stackPtr + $i]['code'] === T_COMMA) { + $error = 'Only one class is allowed per use'; + $phpcsFile->addError($error, $stackPtr, 'OneClassPerUse', array()); + } + } + +} diff --git a/tests/codesniffer/FHComplete/Sniffs/Formatting/UseInAlphabeticalOrderSniff.php b/tests/codesniffer/FHComplete/Sniffs/Formatting/UseInAlphabeticalOrderSniff.php new file mode 100755 index 000000000..43da15876 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/Formatting/UseInAlphabeticalOrderSniff.php @@ -0,0 +1,142 @@ +_processed[$phpcsFile->getFilename()])) { + return; + } + $filename = $phpcsFile->getFilename(); + + $this->_uses = array(); + $next = $stackPtr; + + while ($next !== false) { + $this->_checkUseToken($phpcsFile, $next); + $next = $phpcsFile->findNext(T_USE, $next + 1); + } + + // Prevent multiple uses in the same file from entering + $this->_processed[$phpcsFile->getFilename()] = true; + + foreach ($this->_uses as $scope => $used) { + $defined = $sorted = array_keys($used); + + natcasesort($sorted); + $sorted = array_values($sorted); + if ($sorted === $defined) { + continue; + } + + foreach ($defined as $i => $name) { + if ($name !== $sorted[$i]) { + $error = 'Use classes must be in alphabetical order. Was expecting ' . $sorted[$i]; + $phpcsFile->addError($error, $used[$name], 'UseInAlphabeticalOrder', array()); + } + } + } + } + +/** + * Check all the use tokens in a file. + * + * @param PHP_CodeSniffer_File $phpcsFile The file to check. + * @param integer $stackPtr The index of the first use token. + * @return void + */ + protected function _checkUseToken($phpcsFile, $stackPtr) { + // If the use token is for a closure we want to ignore it. + $isClosure = $this->_isClosure($phpcsFile, $stackPtr); + if ($isClosure) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + // Only one USE declaration allowed per statement. + $next = $phpcsFile->findNext(array(T_COMMA, T_SEMICOLON), ($stackPtr + 1)); + if ($tokens[$next]['code'] === T_COMMA) { + $error = 'There must be one USE keyword per declaration'; + $phpcsFile->addError($error, $stackPtr, 'MultipleDeclarations'); + } + + $content = ''; + $end = $phpcsFile->findNext(array(T_SEMICOLON, T_OPEN_CURLY_BRACKET), $stackPtr); + $useTokens = array_slice($tokens, $stackPtr, $end - $stackPtr, true); + + foreach ($useTokens as $index => $token) { + if ($token['code'] === T_STRING || $token['code'] === T_NS_SEPARATOR) { + $content .= $token['content']; + } + } + + // Check for class scoping on use. Traits should be + // ordered independently. + $scope = 0; + if (!empty($token['conditions'])) { + $scope = key($token['conditions']); + } + $this->_uses[$scope][$content] = $stackPtr; + } + +/** + * Check if the current stackPtr is a use token that is for a closure. + * + * @param PHP_CodeSniffer_File $phpcsFile + * @param integer $stackPtr + * @return boolean + */ + protected function _isClosure($phpcsFile, $stackPtr) { + return $phpcsFile->findPrevious( + array(T_CLOSURE), + ($stackPtr - 1), + null, + false, + null, + true + ); + } + +} diff --git a/tests/codesniffer/FHComplete/Sniffs/Functions/ClosureDeclarationSniff.php b/tests/codesniffer/FHComplete/Sniffs/Functions/ClosureDeclarationSniff.php new file mode 100755 index 000000000..6582d3011 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/Functions/ClosureDeclarationSniff.php @@ -0,0 +1,35 @@ +getTokens(); + $spaces = 0; + + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $spaces = strlen($tokens[($stackPtr + 1)]['content']); + } + + if ($spaces !== 1) { + $error = 'Expected 1 space after closure\'s function keyword; %s found'; + $data = array($spaces); + $phpcsFile->addError($error, $stackPtr, 'SpaceAfterFunction', $data); + } + } + +} diff --git a/tests/codesniffer/FHComplete/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php b/tests/codesniffer/FHComplete/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php new file mode 100755 index 000000000..260ad1c10 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php @@ -0,0 +1,26 @@ + + * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @link http://pear.php.net/package/PHP_CodeSniffer + */ + +if (class_exists('Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff', true) === false) { + throw new PHP_CodeSniffer_Exception('Class Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff not found'); +} + +/** + * PSR1_Sniffs_Methods_CamelCapsMethodNameSniff. + * + * Ensures method names are defined using camel case. + * + * @category PHP + * @package PHP_CodeSniffer + * @author Greg Sherwood + * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class FHComplete_Sniffs_NamingConventions_CamelCapsMethodNameSniff extends Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff +{ + + + /** + * Processes the tokens within the scope. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) + { + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null + || substr($methodName,-4) === '_get' + || substr($methodName,-5) === '_post' + || substr($methodName,-4) === '_put' + || substr($methodName,-6) === '_patch' + || substr($methodName,-7) === '_delete' + ) + // Ignore closures. + return; + + // Ignore magic methods. + if (preg_match('|^__|', $methodName) !== 0) { + $magicPart = strtolower(substr($methodName, 2)); + if (isset($this->magicMethods[$magicPart]) === true + || isset($this->methodsDoubleUnderscore[$magicPart]) === true + ) { + return; + } + } + + $testName = ltrim($methodName, '_'); + if ($testName !== '' && PHP_CodeSniffer::isCamelCaps($testName, false, true, false) === false) { + $error = 'Method name "%s" is not in camel caps format'; + $className = $phpcsFile->getDeclarationName($currScope); + $errorData = array($className.'::'.$methodName); + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'yes'); + } + + }//end processTokenWithinScope() + + + /** + * Processes the tokens outside the scope. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + +}//end class diff --git a/tests/codesniffer/FHComplete/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php b/tests/codesniffer/FHComplete/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php new file mode 100755 index 000000000..3137ea8cf --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php @@ -0,0 +1,223 @@ + + * @author Marc McIntyre + * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @version Release: 1.5.0RC3 + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class FHComplete_Sniffs_NamingConventions_UpperCaseConstantNameSniff implements PHP_CodeSniffer_Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return array(T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param integer $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $constName = $tokens[$stackPtr]['content']; + + // If this token is in a heredoc, ignore it. + if ($phpcsFile->hasCondition($stackPtr, T_START_HEREDOC) === true) { + return; + } + + // Special case for PHPUnit. + if ($constName === 'PHPUnit_MAIN_METHOD') { + return; + } + + // If the next non-whitespace token after this token + // is not an opening parenthesis then it is not a function call. + $openBracket = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { + $functionKeyword = $phpcsFile->findPrevious( + array( + T_WHITESPACE, + T_COMMA, + T_COMMENT, + T_STRING, + T_NS_SEPARATOR, + ), + ($stackPtr - 1), + null, + true + ); + + $declarations = array( + T_FUNCTION, + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_IMPLEMENTS, + T_EXTENDS, + T_INSTANCEOF, + T_NEW, + T_NAMESPACE, + T_USE, + T_AS, + T_GOTO, + T_INSTEADOF, + T_PROTECTED, + T_PRIVATE, + T_PUBLIC + ); + + if (in_array($tokens[$functionKeyword]['code'], $declarations) === true) { + // This is just a declaration; no constants here. + return; + } + + if ($tokens[$functionKeyword]['code'] === T_CONST) { + // This is a class constant. + if (strtoupper($constName) !== $constName) { + $error = 'Class constants must be uppercase; expected %s but found %s'; + $data = array( + strtoupper($constName), + $constName, + ); + $phpcsFile->addError($error, $stackPtr, 'ClassConstantNotUpperCase', $data); + } + + return; + } + + // Is this a class name? + $nextPtr = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$nextPtr]['code'] === T_DOUBLE_COLON) { + return; + } + + // Is this a namespace name? + if ($tokens[$nextPtr]['code'] === T_NS_SEPARATOR) { + return; + } + + // Is this an insteadof name? + if ($tokens[$nextPtr]['code'] === T_INSTEADOF) { + return; + } + + // Is this an as name? + if ($tokens[$nextPtr]['code'] === T_AS) { + return; + } + + // Is this a type hint? + if ($tokens[$nextPtr]['code'] === T_VARIABLE + || $phpcsFile->isReference($nextPtr) === true + ) { + return; + } + + // Is this a member var name? + $prevPtr = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prevPtr]['code'] === T_OBJECT_OPERATOR) { + return; + } + + // Is this a variable name, in the form ${varname} ? + if ($tokens[$prevPtr]['code'] === T_OPEN_CURLY_BRACKET) { + $nextPtr = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$nextPtr]['code'] === T_CLOSE_CURLY_BRACKET) { + return; + } + } + + // Is this a namespace name? + if ($tokens[$prevPtr]['code'] === T_NS_SEPARATOR) { + return; + } + + // Is this an instance of declare() + $prevPtrDeclare = $phpcsFile->findPrevious( + array(T_WHITESPACE, T_OPEN_PARENTHESIS), + ($stackPtr - 1), + null, + true + ); + if ($tokens[$prevPtrDeclare]['code'] === T_DECLARE) { + return; + } + + // Is this a goto label target? + if ($tokens[$nextPtr]['code'] === T_COLON) { + if (in_array($tokens[$prevPtr]['code'], array(T_SEMICOLON, T_OPEN_CURLY_BRACKET, T_COLON), true)) { + return; + } + } + + // This is a real constant. + if (strtoupper($constName) !== $constName) { + $error = 'Constants must be uppercase; expected %s but found %s'; + $data = array( + strtoupper($constName), + $constName, + ); + $phpcsFile->addError($error, $stackPtr, 'ConstantNotUpperCase', $data); + } + + } elseif (strtolower($constName) === 'define' || strtolower($constName) === 'constant') { + /* + This may be a "define" or "constant" function call. + */ + // Make sure this is not a method call. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR + || $tokens[$prev]['code'] === T_DOUBLE_COLON + ) { + return; + } + + // The next non-whitespace token must be the constant name. + $constPtr = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), null, true); + if ($tokens[$constPtr]['code'] !== T_CONSTANT_ENCAPSED_STRING) { + return; + } + + $constName = $tokens[$constPtr]['content']; + + // Check for constants like self::CONSTANT. + $prefix = ''; + $splitPos = strpos($constName, '::'); + if ($splitPos !== false) { + $prefix = substr($constName, 0, ($splitPos + 2)); + $constName = substr($constName, ($splitPos + 2)); + } + + if (strtoupper($constName) !== $constName) { + $error = 'Constants must be uppercase; expected %s but found %s'; + $data = array( + $prefix . strtoupper($constName), + $prefix . $constName, + ); + $phpcsFile->addError($error, $stackPtr, 'ConstantNotUpperCase', $data); + } + } + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidClassBracketsSniff.php b/tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidClassBracketsSniff.php new file mode 100755 index 000000000..a43ac59d0 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidClassBracketsSniff.php @@ -0,0 +1,47 @@ +getTokens(); + + $found = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, $stackPtr); + if ($tokens[$found - 1]['code'] != T_WHITESPACE) { + $error = 'Expected 1 space after class declaration, found 0'; + $phpcsFile->addError($error, $found - 1, 'InvalidSpacing', array()); + return; + } + + if (strlen($tokens[$found - 1]['content']) > 1 || $tokens[$found - 2]['code'] == T_WHITESPACE) { + $error = 'Expected 1 space after class declaration, found ' . strlen($tokens[$found - 1]['content']); + $phpcsFile->addError($error, $found - 1, 'InvalidSpacing', array()); + } + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidFunctionNameSniff.php b/tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidFunctionNameSniff.php new file mode 100755 index 000000000..3281d83f9 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidFunctionNameSniff.php @@ -0,0 +1,138 @@ +getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + $className = $phpcsFile->getDeclarationName($currScope); + $errorData = array($className . '::' . $methodName); + + // PHP4 constructors are allowed to break our rules. + if ($methodName === $className) { + return; + } + + // PHP4 destructors are allowed to break our rules. + if ($methodName === '_' . $className) { + return; + } + + // Ignore magic methods + if (preg_match('/^__(' . implode('|', $this->_magicMethods) . ')$/', $methodName)) { + return; + } + + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + if ($methodProps['scope_specified'] === false) { + // Let another sniffer take care of that + return; + } + + $isPublic = $methodProps['scope'] === 'public'; + $isProtected = $methodProps['scope'] === 'protected'; + $isPrivate = $methodProps['scope'] === 'private'; + $scope = $methodProps['scope']; + + if ($isPublic === true) { + if ($methodName[0] === '_') { + $error = 'Public method name "%s" must not be prefixed with underscore'; + $phpcsFile->addError($error, $stackPtr, 'PublicWithUnderscore', $errorData); + return; + } + // Underscored public methods in controller are allowed to break our rules. + if (substr($className, -10) === 'Controller') { + return; + } + // Underscored public methods in shells are allowed to break our rules. + if (substr($className, -5) === 'Shell') { + return; + } + // Underscored public methods in tasks are allowed to break our rules. + if (substr($className, -4) === 'Task') { + return; + } + } elseif ($isPrivate === true) { + if (substr($methodName, 0, 2) !== '__') { + $error = 'Private method name "%s" must be prefixed with 2 underscores'; + $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $errorData); + return; + } else { + $filename = $phpcsFile->getFilename(); + if (strpos($filename, '/lib/Cake/') === true) { + $warning = 'Private method name "%s" in FHComplete core is discouraged'; + $phpcsFile->addWarning($warning, $stackPtr, 'PrivateMethodInCore', $errorData); + } + } + } else { + if ($methodName[0] !== '_' || substr($methodName, 0, 2) === '__') { + $error = 'Protected method name "%s" must be prefixed with one underscore'; + $phpcsFile->addError($error, $stackPtr, 'ProtectedNoUnderscore', $errorData); + return; + } + } + } + +/** + * Processes the tokens outside the scope. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being processed. + * @param integer $stackPtr The position where this token was found. + * @return void + */ + protected function processTokenOutsideScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { + } + +} diff --git a/tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidTraitNameSniff.php b/tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidTraitNameSniff.php new file mode 100755 index 000000000..5364eab07 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidTraitNameSniff.php @@ -0,0 +1,48 @@ +getTokens(); + $traitName = $tokens[$stackPtr + 2]['content']; + + if (substr($traitName, -5) !== 'Trait') { + $error = 'Traits must have a "Trait" suffix.'; + $phpcsFile->addError($error, $stackPtr, 'InvalidTraitName', array()); + } + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidVariableNameSniff.php b/tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidVariableNameSniff.php new file mode 100755 index 000000000..bce627331 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -0,0 +1,171 @@ +getTokens(); + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + + $phpReservedVars = array( + '_SERVER', + '_GET', + '_POST', + '_REQUEST', + '_SESSION', + '_ENV', + '_COOKIE', + '_FILES', + 'GLOBALS', + ); + + // If it's a php reserved var, then its ok. + if (in_array($varName, $phpReservedVars) === true) { + return; + } + + // There is no way for us to know if the var is public or private, + // so we have to ignore a leading underscore if there is one and just + // check the main part of the variable name. + $originalVarName = $varName; + if (substr($varName, 0, 1) === '_') { + $objOperator = $phpcsFile->findPrevious(array(T_WHITESPACE), ($stackPtr - 1), null, true); + if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON) { + // The variable lives within a class, and is referenced like + // this: MyClass::$_variable, so we don't know its scope. + $inClass = true; + } else { + $inClass = $phpcsFile->hasCondition($stackPtr, array(T_TRAIT, T_CLASS, T_INTERFACE)); + } + + if ($inClass === true) { + $varName = ltrim($varName, '_'); + } + } + + // $title_for_layout is allowed on controllers + $fileName = basename($phpcsFile->getFilename(), '.php'); + if ((substr($fileName, -10) === 'Controller') && ($varName == 'title_for_layout')) { + return; + } + + if ($this->_isValidVar($varName) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = array($originalVarName); + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); + } + } + +/** + * Processes class member variables. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param integer $stackPtr The position of the current token in the + * stack passed in $tokens. + * @return void + */ + protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { + } + +/** + * Processes the variable found within a double quoted string. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param integer $stackPtr The position of the double quoted string. + * @return void + */ + protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { + $tokens = $phpcsFile->getTokens(); + + $phpReservedVars = array( + '_SERVER', + '_GET', + '_POST', + '_REQUEST', + '_SESSION', + '_ENV', + '_COOKIE', + '_FILES', + 'GLOBALS', + ); + + if (preg_match_all('|[^\\\]\$([a-zA-Z0-9_]+)|', $tokens[$stackPtr]['content'], $matches) !== 0) { + foreach ($matches[1] as $varName) { + // If it's a php reserved var, then its ok. + if (in_array($varName, $phpReservedVars) === true) { + continue; + } + + // There is no way for us to know if the var is public or private, + // so we have to ignore a leading underscore if there is one and just + // check the main part of the variable name. + $originalVarName = $varName; + if (substr($varName, 0, 1) === '_') { + if ($phpcsFile->hasCondition($stackPtr, array(T_CLASS, T_INTERFACE)) === true) { + $varName = substr($varName, 1); + } + } + + if ($this->_isValidVar($varName) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = array($originalVarName); + $phpcsFile->addError($error, $stackPtr, 'StringVarNotCamelCaps', $data); + } + } + } + } + +/** + * Check that a variable is a valid shape. + * + * Variables in FHComplete can either be $fooBar, $FooBar, $_fooBar, or $_FooBar. + * + * @param string $string The variable to check. + * @param boolea $public Whether or not the variable is public. + * @return boolean + */ + protected function _isValidVar($string, $public = true) { + $firstChar = '[a-zA-Z]'; + if (!$public) { + $firstChar = '[_]{1,2}' . $firstChar; + } + if (preg_match("|^$firstChar|", $string) === 0) { + return false; + } + $firstStringCount = 1; + if (preg_match("|^__|", $string)) { + $firstStringCount = 2; + } + // Check that the name only contains legal characters. + $legalChars = 'a-zA-Z0-9'; + if (preg_match("|[^$legalChars]|", substr($string, $firstStringCount)) > 0) { + return false; + } + return true; + } + +} diff --git a/tests/codesniffer/FHComplete/Sniffs/PHP/DisallowShortOpenTagSniff.php b/tests/codesniffer/FHComplete/Sniffs/PHP/DisallowShortOpenTagSniff.php new file mode 100755 index 000000000..cd3b8598e --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/PHP/DisallowShortOpenTagSniff.php @@ -0,0 +1,53 @@ +getTokens(); + $openTag = $tokens[$stackPtr]; + + if (trim($openTag['content']) === 'addError($error, $stackPtr, 'Found', $data); + } + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/PHP/TypeCastingSniff.php b/tests/codesniffer/FHComplete/Sniffs/PHP/TypeCastingSniff.php new file mode 100755 index 000000000..2595c4f56 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/PHP/TypeCastingSniff.php @@ -0,0 +1,74 @@ +getTokens(); + + // Process !! casts + if ($tokens[$stackPtr]['code'] == T_BOOLEAN_NOT) { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if (!$nextToken) { + return; + } + if ($tokens[$nextToken]['code'] != T_BOOLEAN_NOT) { + return; + } + $error = 'Usage of !! cast is not allowed. Please use (bool) to cast.'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + + return; + } + + // Only allow short forms if both short and long forms are possible + $matching = array( + '(boolean)' => '(bool)', + '(integer)' => '(int)', + ); + $content = $tokens[$stackPtr]['content']; + $key = strtolower($content); + if (isset($matching[$key])) { + $error = 'Please use ' . $matching[$key] . ' instead of ' . $content . '.'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + return; + } + if ($content !== $key) { + $error = 'Please use ' . $key . ' instead of ' . $content . '.'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + return; + } + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/Strings/ConcatenationSpacingSniff.php b/tests/codesniffer/FHComplete/Sniffs/Strings/ConcatenationSpacingSniff.php new file mode 100755 index 000000000..59eaaf974 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/Strings/ConcatenationSpacingSniff.php @@ -0,0 +1,48 @@ +getTokens(); + if ($tokens[($stackPtr - 1)]['code'] == T_WHITESPACE) { + $message = 'Expected 0 spaces before ., but 1 found'; + $phpcsFile->addError($message, $stackPtr, 'FoundBefore'); + } + + if ($tokens[($stackPtr + 1)]['code'] == ' ') + { + $message = 'Expected 0 spaces after ., but 1 found'; + $phpcsFile->addError($message, $stackPtr, 'FoundAfter'); + } + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/CommaSpacingSniff.php b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/CommaSpacingSniff.php new file mode 100755 index 000000000..7506abe9f --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/CommaSpacingSniff.php @@ -0,0 +1,54 @@ +getTokens(); + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + + if ($tokens[$next]['code'] !== T_WHITESPACE && ($next !== $stackPtr + 2)) { + // Last character in a line is ok. + if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Missing space after comma'; + $phpcsFile->addError($error, $next); + } + } + + $previous = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + + if ($tokens[$previous]['code'] !== T_WHITESPACE && ($previous !== $stackPtr - 1)) { + $error = 'Space before comma, expected none, though'; + $phpcsFile->addError($error, $next); + } + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionCallSpacingSniff.php b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionCallSpacingSniff.php new file mode 100755 index 000000000..8a3cbc8e0 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionCallSpacingSniff.php @@ -0,0 +1,53 @@ +getTokens(); + + // Find the next non-empty token. + $openBracket = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { + // Not a function call. + return; + } + + // Look for funcName ( + if (($stackPtr + 1) !== $openBracket) { + $error = 'Space before opening parenthesis of function call not allowed'; + $phpcsFile->addError($error, $stackPtr, 'SpaceBeforeOpenBracket'); + } + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php new file mode 100755 index 000000000..83e7ac73e --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php @@ -0,0 +1,69 @@ +getTokens(); + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Probably an interface method. + return; + } + + $closeBrace = $tokens[$stackPtr]['scope_closer']; + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), null, true); + + $braceLine = $tokens[$closeBrace]['line']; + $prevLine = $tokens[$prevContent]['line']; + + $found = ($braceLine - $prevLine - 1); + if ($phpcsFile->hasCondition($stackPtr, T_FUNCTION) === true + || isset($tokens[$stackPtr]['nested_parenthesis']) === true + ) { + // Nested function. + if ($found < 0) { + $error = 'Closing brace of nested function must be on a new line'; + $phpcsFile->addError($error, $closeBrace, 'ContentBeforeClose'); + } elseif ($found > 0) { + $error = 'Expected 0 blank lines before closing brace of nested function; %s found'; + $data = array($found); + $phpcsFile->addError($error, $closeBrace, 'SpacingBeforeNestedClose', $data); + } + } else { + if ($found !== 0) { + $error = 'Expected 0 blank lines before closing function brace; %s found'; + $data = array($found); + $phpcsFile->addError($error, $closeBrace, 'SpacingBeforeClose', $data); + } + } + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php new file mode 100755 index 000000000..d202e760a --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php @@ -0,0 +1,62 @@ +getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + // Probably an interface method. + return; + } + + $openBrace = $tokens[$stackPtr]['scope_opener']; + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($openBrace + 1), null, true); + + if ($nextContent === $tokens[$stackPtr]['scope_closer']) { + // The next bit of content is the closing brace, so this + // is an empty function and should have a blank line + // between the opening and closing braces. + return; + } + + $braceLine = $tokens[$openBrace]['line']; + $nextLine = $tokens[$nextContent]['line']; + + $found = ($nextLine - $braceLine - 1); + if ($found > 0) { + $error = 'Expected 0 blank lines after opening function brace; %s found'; + $data = array($found); + $phpcsFile->addError($error, $openBrace, 'SpacingAfter', $data); + } + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionSpacingSniff.php b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionSpacingSniff.php new file mode 100755 index 000000000..09f6a55b0 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/FunctionSpacingSniff.php @@ -0,0 +1,129 @@ +getTokens(); + + /* + Check the number of blank lines + after the function. + */ + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Must be an interface method, so the closer is the semi-colon. + $closer = $phpcsFile->findNext(T_SEMICOLON, $stackPtr); + } else { + $closer = $tokens[$stackPtr]['scope_closer']; + } + + // There needs to be 1 blank lines after the closer. + $nextLineToken = null; + for ($i = $closer; $i < $phpcsFile->numTokens; $i++) { + if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) === false) { + continue; + } else { + $nextLineToken = ($i + 1); + break; + } + } + + if ($nextLineToken === null) { + // Never found the next line, which means + // there are 0 blank lines after the function. + $foundLines = 0; + } else { + $nextContent = $phpcsFile->findNext(array(T_WHITESPACE), ($nextLineToken + 1), null, true); + if ($nextContent === false) { + // We are at the end of the file. That is acceptable as well. + $foundLines = 1; + } else { + $foundLines = ($tokens[$nextContent]['line'] - $tokens[$nextLineToken]['line']); + } + } + + /* + Check the number of blank lines + before the function. + */ + + $prevLineToken = null; + for ($i = $stackPtr; $i > 0; $i--) { + if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) === false) { + continue; + } else { + $prevLineToken = $i; + break; + } + } + + if ($prevLineToken === null) { + // Never found the previous line, which means + // there are 0 blank lines before the function. + $foundLines = 0; + } else { + $prevContent = $phpcsFile->findPrevious(array(T_WHITESPACE, T_DOC_COMMENT), $prevLineToken, null, true); + + // Before we throw an error, check that we are not throwing an error + // for another function. We don't want to error for no blank lines after + // the previous function and no blank lines before this one as well. + $currentLine = $tokens[$stackPtr]['line']; + $prevLine = ($tokens[$prevContent]['line'] - 1); + $i = ($stackPtr - 1); + $foundLines = 0; + while ($currentLine !== $prevLine && $currentLine > 1 && $i > 0) { + if (isset($tokens[$i]['scope_condition']) === true) { + $scopeCondition = $tokens[$i]['scope_condition']; + if ($tokens[$scopeCondition]['code'] === T_FUNCTION) { + // Found a previous function. + return; + } + } elseif ($tokens[$i]['code'] === T_FUNCTION) { + // Found another interface function. + return; + } + + $currentLine = $tokens[$i]['line']; + if ($currentLine === $prevLine) { + break; + } + + if ($tokens[($i - 1)]['line'] < $currentLine && $tokens[($i + 1)]['line'] > $currentLine) { + // This token is on a line by itself. If it is whitespace, the line is empty. + if ($tokens[$i]['code'] === T_WHITESPACE) { + $foundLines++; + } + } + $i--; + } + } + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php new file mode 100755 index 000000000..a52680736 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php @@ -0,0 +1,42 @@ +getTokens(); + + $nextType = $tokens[($stackPtr + 1)]['code']; + if (in_array($nextType, PHP_CodeSniffer_Tokens::$emptyTokens) === true) { + $error = 'Space found after object operator'; + $phpcsFile->addError($error, $stackPtr, 'After'); + } + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/OperatorSpacingSniff.php b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/OperatorSpacingSniff.php new file mode 100755 index 000000000..efeef023a --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/OperatorSpacingSniff.php @@ -0,0 +1,185 @@ +getTokens(); + + // Skip default values in function declarations. + if ($tokens[$stackPtr]['code'] === T_EQUAL + || $tokens[$stackPtr]['code'] === T_MINUS + ) { + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $parenthesis = array_keys($tokens[$stackPtr]['nested_parenthesis']); + $bracket = array_pop($parenthesis); + if (isset($tokens[$bracket]['parenthesis_owner']) === true) { + $function = $tokens[$bracket]['parenthesis_owner']; + if ($tokens[$function]['code'] === T_FUNCTION) { + return; + } + } + } + } + + if ($tokens[$stackPtr]['code'] === T_EQUAL) { + // Skip for '=&' case. + if (isset($tokens[($stackPtr + 1)]) === true && $tokens[($stackPtr + 1)]['code'] === T_BITWISE_AND) { + return; + } + } + + if ($tokens[$stackPtr]['code'] === T_BITWISE_AND) { + // If its not a reference, then we expect one space either side of the + // bitwise operator. + if (!$phpcsFile->isReference($stackPtr) && !$this->isVariable($stackPtr, $tokens, $phpcsFile)) { + // Check there is one space before the & operator. + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space before "&" operator; 0 found'; + $phpcsFile->addError($error, $stackPtr, 'NoSpaceBeforeAmp'); + } + + // Check there is one space after the & operator. + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after "&" operator; 0 found'; + $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfterAmp'); + } + } + } else { + if ($tokens[$stackPtr]['code'] === T_MINUS) { + // Skip declaration of negative value in new array format; eg. $arr = [-1]. + if ($tokens[($stackPtr - 1)]['code'] === T_OPEN_SHORT_ARRAY) { + return; + } + + // Check minus spacing, but make sure we aren't just assigning + // a minus value or returning one. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_RETURN) { + // Just returning a negative value; eg. return -1. + return; + } + + if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$operators) === true) { + // Just trying to operate on a negative value; eg. ($var * -1). + return; + } + + if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$comparisonTokens) === true) { + // Just trying to compare a negative value; eg. ($var === -1). + return; + } + + // A list of tokens that indicate that the token is not + // part of an arithmetic operation. + $invalidTokens = array( + T_COMMA, + T_OPEN_PARENTHESIS, + T_OPEN_SQUARE_BRACKET, + T_DOUBLE_ARROW, + T_COLON, + T_INLINE_THEN, + T_INLINE_ELSE, + T_CASE, + ); + + if (in_array($tokens[$prev]['code'], $invalidTokens) === true) { + // Just trying to use a negative value; eg. myFunction($var, -2). + return; + } + if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens) === true) { + // Just trying to assign a negative value; eg. ($var = -1). + return; + } + } + + $operator = $tokens[$stackPtr]['content']; + + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = "Expected 1 space before \"$operator\"; 0 found"; + $phpcsFile->addError($error, $stackPtr, 'NoSpaceBefore'); + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = "Expected 1 space after \"$operator\"; 0 found"; + $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfter'); + } + } + } + + /** + * Check if the current token is inside an array. + * + * @param int $stackPtr The current token offset. + * @param array $phpcsFile The current token list. + * @return bool + */ + protected function isVariable($stackPtr, $tokens, $phpcsFile) + { + $tokenAfter = $phpcsFile->findNext( + PHP_CodeSniffer_Tokens::$emptyTokens, + ($stackPtr + 1), + null, + true + ); + $tokenBefore = $phpcsFile->findNext( + PHP_CodeSniffer_Tokens::$emptyTokens, + ($stackPtr - 1), + null, + true + ); + + if ($tokens[$tokenAfter]['code'] === T_VARIABLE && + ( + $tokens[$tokenBefore]['code'] === T_OPEN_PARENTHESIS || + $tokens[$tokenBefore]['code'] === T_COMMA || + $tokens[$tokenBefore]['code'] === T_OPEN_SHORT_ARRAY + ) + ) { + return true; + } + return false; + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/ScopeIndentSniff.php b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/ScopeIndentSniff.php new file mode 100755 index 000000000..b3e998ed4 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -0,0 +1,280 @@ +getTokens(); + + // If this is an inline condition (ie. there is no scope opener), then + // return, as this is not a new scope. + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + if ($tokens[$stackPtr]['code'] === T_ELSE) { + $next = $phpcsFile->findNext( + PHP_CodeSniffer_Tokens::$emptyTokens, + ($stackPtr + 1), + null, + true + ); + + // We will handle the T_IF token in another call to process. + if ($tokens[$next]['code'] === T_IF) { + return; + } + } + + // Find the first token on this line. + $firstToken = $stackPtr; + for ($i = $stackPtr; $i >= 0; $i--) { + // Record the first code token on the line. + if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) { + $firstToken = $i; + } + + // It's the start of the line, so we've found our first php token. + if ($tokens[$i]['column'] === 1) { + break; + } + } + + // Based on the conditions that surround this token, determine the + // indent that we expect this current content to be. + $expectedIndent = $this->calculateExpectedIndent($tokens, $firstToken); + + $scopeOpener = $tokens[$stackPtr]['scope_opener']; + $scopeCloser = $tokens[$stackPtr]['scope_closer']; + + // Some scopes are expected not to have indents. + if (in_array($tokens[$firstToken]['code'], $this->nonIndentingScopes) === false) { + $indent = ($expectedIndent + $this->indent); + } else { + $indent = $expectedIndent; + } + + $newline = false; + $commentOpen = false; + $inHereDoc = false; + + // Only loop over the content beween the opening and closing brace, not + // the braces themselves. + for ($i = ($scopeOpener + 1); $i < $scopeCloser; $i++) { + // If this token is another scope, skip it as it will be handled by + // another call to this sniff. + if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$scopeOpeners) === true) { + if (isset($tokens[$i]['scope_opener']) === true) { + $i = $tokens[$i]['scope_closer']; + + // If the scope closer is followed by a semi-colon, the semi-colon is part + // of the closer and should also be ignored. This most commonly happens with + // CASE statements that end with "break;", where we don't want to stop + // ignoring at the break, but rather at the semi-colon. + $nextToken = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($i + 1), null, true); + if ($tokens[$nextToken]['code'] === T_SEMICOLON) { + $i = $nextToken; + } + } else { + // If this token does not have a scope_opener indice, then + // it's probably an inline scope, so let's skip to the next + // semicolon. Inline scopes include inline if's, abstract + // methods etc. + $nextToken = $phpcsFile->findNext(T_SEMICOLON, $i, $scopeCloser); + if ($nextToken !== false) { + $i = $nextToken; + } + } + continue; + } + + // If this is a HEREDOC then we need to ignore it as the + // whitespace before the contents within the HEREDOC are + // considered part of the content. + if ($tokens[$i]['code'] === T_START_HEREDOC) { + $inHereDoc = true; + continue; + } elseif ($inHereDoc === true) { + if ($tokens[$i]['code'] === T_END_HEREDOC) { + $inHereDoc = false; + } + continue; + } + + if ($tokens[$i]['column'] === 1) { + // We started a newline. + $newline = true; + } + + if ($newline === true && $tokens[$i]['code'] !== T_WHITESPACE) { + // If we started a newline and we find a token that is not + // whitespace, then this must be the first token on the line that + // must be indented. + $newline = false; + $firstToken = $i; + + $column = $tokens[$firstToken]['column']; + + // Special case for non-PHP code. + if ($tokens[$firstToken]['code'] === T_INLINE_HTML) { + $trimmedContentLength = strlen(ltrim($tokens[$firstToken]['content'])); + if ($trimmedContentLength === 0) { + continue; + } + + $contentLength = strlen($tokens[$firstToken]['content']); + $column = ($contentLength - $trimmedContentLength + 1); + } + + // If we're starting a new PHP block that has the scope closer + // as the next token we'll skip the remaining checks as the scope is closed. + if ($tokens[$firstToken]['code'] === T_OPEN_TAG && + $scopeCloser == $firstToken + 1 + ) { + continue; + } + + // Check to see if this constant string spans multiple lines. + // If so, then make sure that the strings on lines other than the + // first line are indented appropriately, based on their whitespace. + if (in_array($tokens[$firstToken]['code'], PHP_CodeSniffer_Tokens::$stringTokens) === true) { + if (in_array($tokens[($firstToken - 1)]['code'], PHP_CodeSniffer_Tokens::$stringTokens) === true) { + // If we find a string that directly follows another string + // then its just a string that spans multiple lines, so we + // don't need to check for indenting. + continue; + } + } + + // This is a special condition for T_DOC_COMMENT and C-style + // comments, which contain whitespace between each line. + $comments = array( + T_COMMENT, + T_DOC_COMMENT + ); + + $isDocComment = false; + if (in_array($tokens[$firstToken]['code'], $comments) === true) { + $content = trim($tokens[$firstToken]['content']); + if (preg_match('|^/\*|', $content) !== 0) { + // Check to see if the end of the comment is on the same line + // as the start of the comment. If it is, then we don't + // have to worry about opening a comment. + if (preg_match('|\*/$|', $content) === 0) { + // We don't have to calculate the column for the + // start of the comment as there is a whitespace + // token before it. + $commentOpen = true; + $isDocComment = (substr($content, 0, 3) === '/**'); + } + } elseif ($commentOpen === true) { + if ($content === '') { + // We are in a comment, but this line has nothing on it + // so let's skip it. + continue; + } + + $contentLength = strlen($tokens[$firstToken]['content']); + $trimmedContentLength = strlen(ltrim($tokens[$firstToken]['content'])); + + $column = ($contentLength - $trimmedContentLength + 1); + if (preg_match('|\*/$|', $content) !== 0) { + $commentOpen = false; + } + } + } + } + } + } + + /** + * Calculates the expected indent of a token. + * + * @param array $tokens The stack of tokens for this file. + * @param int $stackPtr The position of the token to get indent for. + * @return int + */ + protected function calculateExpectedIndent(array $tokens, $stackPtr) + { + $conditionStack = array(); + + // Empty conditions array (top level structure). + if (empty($tokens[$stackPtr]['conditions']) === true) { + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true + && empty($tokens[$stackPtr]['nested_parenthesis']) === false + ) { + // Wrapped in parenthesis means it is probably in a + // function call (like a closure) so we have to assume indent + // is correct here and someone else will check it more + // carefully in another sniff. + return $tokens[$stackPtr]['column']; + } else { + return 1; + } + } + + $tokenConditions = $tokens[$stackPtr]['conditions']; + foreach ($tokenConditions as $id => $condition) { + // If it's an indenting scope ie. it's not in our array of + // scopes that don't indent, add it to our condition stack. + if (in_array($condition, $this->nonIndentingScopes) === false) { + $conditionStack[$id] = $condition; + } + } + return ((count($conditionStack) * $this->indent) + 1); + } +} diff --git a/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/TabAndSpaceSniff.php b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/TabAndSpaceSniff.php new file mode 100755 index 000000000..0c2593aa1 --- /dev/null +++ b/tests/codesniffer/FHComplete/Sniffs/WhiteSpace/TabAndSpaceSniff.php @@ -0,0 +1,63 @@ +getTokens(); + + $line = $tokens[$stackPtr]['line']; + if ($stackPtr > 0 && $tokens[($stackPtr - 1)]['line'] !== $line) { + return; + } + + if (strpos($tokens[$stackPtr]['content'], " \t") !== false) { + $error = 'Space and tab found'; + $phpcsFile->addError($error, $stackPtr); + } + if (strpos($tokens[$stackPtr]['content'], "\t ") !== false) { + $error = 'Tab and space found'; + $phpcsFile->addError($error, $stackPtr); + } + } +} diff --git a/tests/codesniffer/FHComplete/ruleset.xml b/tests/codesniffer/FHComplete/ruleset.xml new file mode 100755 index 000000000..6673d18fe --- /dev/null +++ b/tests/codesniffer/FHComplete/ruleset.xml @@ -0,0 +1,92 @@ + + + FHComplete's coding standard + + \.git + */Config/*.ini.php + /*/tmp/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + */tests/* + + + */tests/* + + + + + diff --git a/tests/codesniffer/FHComplete/tests/FHCompletePHPStandardTest.php b/tests/codesniffer/FHComplete/tests/FHCompletePHPStandardTest.php new file mode 100755 index 000000000..8c933aa95 --- /dev/null +++ b/tests/codesniffer/FHComplete/tests/FHCompletePHPStandardTest.php @@ -0,0 +1,67 @@ +helper)) { + $this->helper = new TestHelper(); + } + } + +/** + * testFiles + * + * Run simple syntax checks, if the filename ends with pass.php - expect it to pass + */ + public static function testProvider() { + $tests = array(); + + $standard = dirname(dirname(__FILE__)); + + $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(dirname(__FILE__) . '/files')); + foreach ($iterator as $dir) { + if ($dir->isDir()) { + continue; + } + + $file = $dir->getPathname(); + $expectPass = (substr($file, -8) === 'pass.php'); + $tests[] = array( + $file, + $standard, + $expectPass + ); + } + return $tests; + } + +/** + * _testFile + * + * @dataProvider testProvider + * + * @param string $file + * @param string $standard + * @param boolean $expectPass + */ + public function testFile($file, $standard, $expectPass) { + $outputStr = $this->helper->runPhpCs($file); + if ($expectPass) { + $this->assertNotRegExp( + "/FOUND \d+ ERROR/", + $outputStr, + basename($file) . ' - expected to pass with no errors, some were reported. ' + ); + } else { + $this->assertRegExp( + "/FOUND \d+ ERROR/", + $outputStr, + basename($file) . ' - expected failures, none reported. ' + ); + } + } + +} diff --git a/tests/codesniffer/FHComplete/tests/TestHelper.php b/tests/codesniffer/FHComplete/tests/TestHelper.php new file mode 100755 index 000000000..4d86b5fe4 --- /dev/null +++ b/tests/codesniffer/FHComplete/tests/TestHelper.php @@ -0,0 +1,54 @@ +_phpcs = new PHP_CodeSniffer_CLI(); + } + +/** + * Run PHPCS on a file. + * + * @param string $file to run. + * @return string The output from phpcs. + */ + public function runPhpCs($file) { + $defaults = $this->_phpcs->getDefaults(); + $standard = dirname(__FILE__) . '/ruleset.xml'; + if ( + defined('PHP_CodeSniffer::VERSION') && + version_compare(PHP_CodeSniffer::VERSION, '1.5.0') != -1 + ) { + $standard = array($standard); + } + $options = array( + 'encoding' => 'utf-8', + 'files' => array($file), + 'standard' => $standard, + 'showSources' => true, + ) + $defaults; + + // New PHPCS has a strange issue where the method arguments + // are not stored on the instance causing weird errors. + $reflection = new ReflectionProperty($this->_phpcs, 'values'); + $reflection->setAccessible(true); + $reflection->setValue($this->_phpcs, $options); + + ob_start(); + $this->_phpcs->process($options); + $result = ob_get_contents(); + ob_end_clean(); + return $result; + } + +} diff --git a/tests/codesniffer/FHComplete/tests/bootstrap.php b/tests/codesniffer/FHComplete/tests/bootstrap.php new file mode 100755 index 000000000..b6ef51c7c --- /dev/null +++ b/tests/codesniffer/FHComplete/tests/bootstrap.php @@ -0,0 +1,2 @@ + 100) { + echo 'i > 100'; +} + +while (false) { + echo 'false'; +} + +do { + echo 'dowhile test'; +} while (false); diff --git a/tests/codesniffer/FHComplete/tests/files/control_structure_dowhile.php b/tests/codesniffer/FHComplete/tests/files/control_structure_dowhile.php new file mode 100755 index 000000000..54b2190d4 --- /dev/null +++ b/tests/codesniffer/FHComplete/tests/files/control_structure_dowhile.php @@ -0,0 +1,6 @@ +something ('testing'); +fail_whale (); diff --git a/tests/codesniffer/FHComplete/tests/files/mixing_indent.php b/tests/codesniffer/FHComplete/tests/files/mixing_indent.php new file mode 100755 index 000000000..0400dd514 --- /dev/null +++ b/tests/codesniffer/FHComplete/tests/files/mixing_indent.php @@ -0,0 +1,6 @@ + 'after 2 tabs' + ); +} diff --git a/tests/codesniffer/FHComplete/tests/files/multiple_use.php b/tests/codesniffer/FHComplete/tests/files/multiple_use.php new file mode 100755 index 000000000..b239a6419 --- /dev/null +++ b/tests/codesniffer/FHComplete/tests/files/multiple_use.php @@ -0,0 +1,6 @@ + + + + +passingPublic = 'changed'; + $this->underscored = 'has value now'; + $this->doubleUnderscore = 'not recommended'; + } + + /** + * [setStatics description] + * + * @return void + */ + public static function setStatics() + { + self::$publicStatic = true; + self::$protectedStatic = true; + self::$privateStatic = true; + } +} diff --git a/tests/codesniffer/FHComplete/tests/files/whitespace_comma.php b/tests/codesniffer/FHComplete/tests/files/whitespace_comma.php new file mode 100755 index 000000000..78e43d5f0 --- /dev/null +++ b/tests/codesniffer/FHComplete/tests/files/whitespace_comma.php @@ -0,0 +1,2 @@ + + + FH-Complete coding standard + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ccf79afdd09a3e00eae4b57e5340f75802967dd8 Mon Sep 17 00:00:00 2001 From: oesi Date: Fri, 8 Apr 2016 16:51:37 +0200 Subject: [PATCH 4/5] FAS Lehrveranstaltungen verwenden Studienplanmatrix statt Studienordnungsmatrix --- include/studienordnung.class.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/studienordnung.class.php b/include/studienordnung.class.php index 5a341570c..7a203568f 100644 --- a/include/studienordnung.class.php +++ b/include/studienordnung.class.php @@ -155,9 +155,10 @@ class studienordnung extends basis_db } else { - $qry = 'SELECT sto.*, s.bezeichnung as status_bezeichnung, sem.* FROM lehre.tbl_studienordnung sto + $qry = 'SELECT distinct sto.*, s.bezeichnung as status_bezeichnung, sem.* FROM lehre.tbl_studienordnung sto JOIN lehre.tbl_studienordnungstatus s USING(status_kurzbz) - LEFT JOIN lehre.tbl_studienordnung_semester sem USING (studienordnung_id) + LEFT JOIN lehre.tbl_studienplan USING(studienordnung_id) + LEFT JOIN lehre.tbl_studienplan_semester sem USING (studienplan_id) WHERE studiengang_kz='.$this->db_add_param($studiengang_kz, FHC_INTEGER, false); if (!is_null($studiensemester_kurzbz)) @@ -200,7 +201,8 @@ class studienordnung extends basis_db { $obj->studiensemester_kurzbz = $row->studiensemester_kurzbz; $obj->semester = $row->semester; - $obj->studienordnung_semester_id = $row->studienordnung_semester_id; + //$obj->studienordnung_semester_id = $row->studienordnung_semester_id; + $obj->studienplan_semester_id = $row->studienplan_semester_id; } $this->result[] = $obj; } From 53b68ff7c713a78122cd3d949cd08a4fb3db2612 Mon Sep 17 00:00:00 2001 From: oesi Date: Mon, 11 Apr 2016 09:02:07 +0200 Subject: [PATCH 5/5] =?UTF-8?q?Fehlende=20Attribute=20beim=20Laden=20der?= =?UTF-8?q?=20Lehrveranstaltung=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/lehrveranstaltung.class.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/lehrveranstaltung.class.php b/include/lehrveranstaltung.class.php index 6c163e8df..1c238da44 100755 --- a/include/lehrveranstaltung.class.php +++ b/include/lehrveranstaltung.class.php @@ -1258,6 +1258,12 @@ class lehrveranstaltung extends basis_db if ($obj->bezeichnung_arr['English'] == '') $obj->bezeichnung_arr['English'] = $obj->bezeichnung_arr['German']; + $obj->sws = $row->sws; + $obj->lvs = $row->lvs; + $obj->alvs = $row->alvs; + $obj->lvps = $row->lvps; + $obj->las = $row->las; + $obj->stpllv_semester = $row->stpllv_semester; $obj->stpllv_pflicht = $this->db_parse_bool($row->stpllv_pflicht); $obj->stpllv_koordinator = $row->stpllv_koordinator; @@ -1312,7 +1318,7 @@ class lehrveranstaltung extends basis_db } return $childs; } - + /** * Generiert die Subtrees des Lehrveranstaltungstrees */ @@ -1335,7 +1341,7 @@ class lehrveranstaltung extends basis_db { return false; } - + } /**