/**
  * Hakee ne kokonaisuudet oikeassa järjestyksessä
  * jotka ovat $kokon_id-kokonaisuuden alakokonaisuuksia (alipuu).
  * Kokonaisuuspuun juurta vastaa $kokon_id (sitä ei erikseen liitetä
  * palautustaulukkoon).
  *
  * Palauttaa kokonaisuusoliot (MySQL-kutsun tulos käärittynä Kokonaisuusolio-
  * luokan olion sisään) taulukossa. Voi palauttaa tyhjän taulukon, mutta aina siis taulukon.
  *
  * Mukaan otetaan kaikki julkiset sekä muista ne, joihin on riittävät 
  * oikeudet. 
  * 
  * Huom! &-merkit ovat välttämättömiä, jotta tiedot välittyvät sisäkkäisistä
  * funktiokutsuista.
  *
  * @param array $kokonaisuudet Taulukko, johon kerätään järjestetyt kokonaisuudet.
  * @param string $otsikkonro juuriotsikon otsikkonumero merkinta, esim. '1.2.1'.
  * Se on eka kierroksella tyhjä, koska silloin ei ole tunnettua juuriotsikkoa.
  * @param int $otsikkotaso samoin kuin html:ssä.
  * @param <type> $kieli
  * @param <type> $aine
  * @param <type> $taso
  * @param <type> $kokon_id
  * @param Tietokantaolio $tietokantaolio
  * @return array Palauttaa kokonaisuustaulukon (Kokonaisuus-olioita)
  */
 function hae_kokonaisuusoliopuu(&$kokonaisuudet, &$otsikkonro, &$otsikkotaso, $kieli, $aine, $taso, $kokon_id, $tietokantaolio, $omaid)
 {
     // Tätä tarvitaan jatkossa:
     $on_kirjautunut = Henkilo::on_kirjautunut($omaid, $tietokantaolio);
     // Koostelomakkeessa voi olla poikkeava näyttötapa:
     $kohde_koostelomake = false;
     if ($this->get_parametriolio()->naytettava === Palaute::$NAYTETTAVA_OLIOTYYPPI_KOOSTELOMAKE) {
         $kohde_koostelomake = true;
     }
     $laskuri = 1;
     $otsikkomerkinta = "";
     /* Jokainen kutsu nostaa otsikkotasoa yhdellä:*/
     $otsikkotaso++;
     // Ellei käyttäjä kirjautunut, haetaan vain julkiset kokonaisuudet sekä
     // puoliksi piilotetut, joista siis otsikko näytetään,
     // jolloin säästetään monta työvaihetta:
     if (!$on_kirjautunut) {
         $yksityisrajaus = " AND (nakyvyys=" . Nakyvyys::$JULKINEN . " OR nakyvyys=" . Nakyvyys::$VAIN_OTSIKKO . ") ";
     } else {
         // Muuten haetaan kaikki, joista myöhemmin karsitaan sellaiset pois,
         // joihin ei ole riittäviä oikeuksia.
         $yksityisrajaus = "";
     }
     /* Haetaan kokonaisuusoliot yhdeltä otsikkotasolta (eri kuin vaikeustaso!) 
      * eli joilla sama $ylakokonaisuuden_id.
      */
     $hakulause = "SELECT *\n                        FROM kokonaisuudet\n                        WHERE ylakokonaisuuden_id = {$kokon_id}\n                        AND kieli = {$kieli}\n                        AND taso = {$taso}\n                        AND oppiaine = {$aine}\n                        {$yksityisrajaus}\n                        ORDER BY jarjestysnro";
     // Huomaa taulukkomuoto, joka käy parametriksi nouki_arvot_...-metodiin.
     $osumat = $tietokantaolio->tee_omahaku_taulukkopalautteella($hakulause);
     //======================= karsinta tässä tasossa kirjautuneelle ========
     // Muille karsintaa ei tarvita, koska näytetään vain julkiset.
     if ($on_kirjautunut) {
         $karsitut = array();
         // Käydään läpi kaikki osumat ja otetaan mukaan julkiset ja ne,
         // joihin oikeudet:
         for ($i = 0; $i < sizeof($osumat); $i++) {
             // Yhden kokonaisuuden tiedot eli sitä vastaava tietokantarivi:
             $kokonaisuustiedot = $osumat[$i];
             if ($kokonaisuustiedot[Kokonaisuusolio::$sarakenimi_nakyvyys] + 0 === Nakyvyys::$JULKINEN) {
                 array_push($karsitut, $kokonaisuustiedot);
             } else {
                 if ($kokonaisuustiedot[Kokonaisuusolio::$sarakenimi_nakyvyys] + 0 === Nakyvyys::$VAIN_OTSIKKO) {
                     // Koostelomakkeeseen ei oteta keskeneräisiä:
                     //if(!$kohde_koostelomake){
                     array_push($karsitut, $kokonaisuustiedot);
                     //}
                 } else {
                     /*======================== käyttäjän oikeudet ================*/
                     $kohdeoikeudet = Henkilo::hae_kayttajan_kohdeoikeudet($kokonaisuustiedot[Kokonaisuusolio::$sarakenimi_henkilo_id], $omaid, Oliotyyppi::$KOKONAISUUS, $kokonaisuustiedot[Kokonaisuusolio::$SARAKENIMI_ID], $tietokantaolio);
                     /*============================================================*/
                     // Näkemisoikeudella pääsee näkemään! Muuten poistetaan!
                     if ($kohdeoikeudet >= Lisavaltuudet::$SAA_NAHDA_EI_MUOKATA_EI_POISTAA) {
                         array_push($karsitut, $kokonaisuustiedot);
                     }
                 }
             }
         }
         // Asetetaan osumiksi vain karsitut:
         $osumat = $karsitut;
     }
     //======================= karsinta tästä tasosta loppu =================
     $kokon_lkm = sizeof($osumat);
     // Käydään läpi jokaisen osuman alipuu erikseen ja liitetään mukaan:
     for ($i = 0; $i < $kokon_lkm; $i++) {
         // Yhden kokonaisuuden tiedot eli sitä vastaava tietokantarivi:
         $kokonaisuus = $osumat[$i];
         // Nämä liittyvät saman tason kokonaisuuksiin järjestyksen
         // vaihtoa ajatellen:
         $ed_id = Kokonaisuusolio::$kokon_edellista_ei_ole;
         $seur_id = Kokonaisuusolio::$kokon_seuraavaa_ei_ole;
         //Haetaan tämän tason edellisen ja seuraavan kokonaisuudet id:t järjestyksen
         //vaihtoa varten. Eka ja vika käsitellään ensin erikseen.
         if ($i == 0) {
             // Edellistä ei ole tässä tasossa
             if ($kokon_lkm > 1) {
                 $seur_id = $osumat[1]["id"];
                 // Toimii, testattu on.
             }
         } else {
             if ($i == $kokon_lkm - 1) {
                 // Tason viimeinen kokonaisuus
                 $ed_id = $osumat[$i - 1]["id"];
                 // Toimii, testattu on.
             } else {
                 $ed_id = $osumat[$i - 1]["id"];
                 $seur_id = $osumat[$i + 1]["id"];
             }
         }
         // Muotoillaan otsikkonumerointi:
         if ($kokonaisuus["ylakokonaisuuden_id"] == -1) {
             $otsikkomerkinta = $laskuri;
         } else {
             $otsikkomerkinta = $otsikkonro . "." . $laskuri;
         }
         // Luodaan tyhjä kokonaisuusolio:
         $kokonolio = new Kokonaisuusolio(Kokonaisuusolio::$MUUTTUJAA_EI_MAARITELTY, $this->get_tietokantaolio());
         // Haetaan arvot oliolle jo haetusta taulukosta:
         $kokonolio->nouki_arvot_tk_osumataulukosta($kokonaisuus);
         // Lisätään tiedot, joita ei tietokannassa tms:
         $kokonolio->setOtsikkomerkinta($otsikkomerkinta);
         $kokonolio->setOtsikkotaso($otsikkotaso);
         $kokonolio->setEdellisenId_taso($ed_id);
         $kokonolio->setSeuraavanId_taso($seur_id);
         array_push($kokonaisuudet, $kokonolio);
         // Sitten tutkitaan mukaan otetun kokonaisuuden perilliset. Jos
         // näytettäviä perillisiä eli sellaisia alikokonaisuuksia, joihin
         // on riittävät oikeudet, on olemassa, suoritetaan rekursiivinen
         // kutsu seuraavalle tasolle.
         if ($kokonolio->on_naytettavia_lapsia($omaid)) {
             $kokon_id_uusi = $kokonaisuus["id"];
             if ($otsikkonro == "") {
                 $otsikkonro_uusi = $laskuri . "";
             } else {
                 $otsikkonro_uusi = $otsikkonro . "." . $laskuri;
             }
             // Rekursiivinen kutsu!
             $this->hae_kokonaisuusoliopuu($kokonaisuudet, $otsikkonro_uusi, $otsikkotaso, $kieli, $aine, $taso, $kokon_id_uusi, $tietokantaolio, $omaid);
         }
         /* Jos kysymyksessä on otsikkotason viimeinen kokonaisuus,
          * vähennetään otsikkotasosta 1 (vaikea ymmärtää, mutta näyttää
          * toimivan :): */
         if ($kokonaisuus["id"] == $osumat[sizeof($osumat) - 1]["id"]) {
             $otsikkotaso--;
         }
         /* Kasvatetaan laskuria. */
         $laskuri++;
     }
     return $kokonaisuudet;
 }