/**
  * Palauttaa html-lomakkeen, jonka avulla voidaan tallentaa uuden
  * kokonaisuuden tiedot tietokantaan tai muokata vanhoja. Lomakkeen html-id on
  * 'kokonaisuuslomake'.
  *
  * @param <type> $id_kokon
  * @param <type> $omaid
  * @param <type> $uusi
  * @param <type> $ilmoitus_kokon
  * @param Tietokantaolio $tietokantaolio
  * @param <type> $oppiaine_kokon
  * @param <type> $otsikko_kokon
  * @param <type> $tiivis_kokon
  * @param <type> $selitys_kokon
  * @param <type> $taso_kokon
  * @param <type> $jarjestysnro_kokon
  * @param <type> $laajennetun_id_kokon
  * @param <type> $ylakokonaisuuden_id_kokon
  * @param <type> $kieli_id
  * @param <type> $toiminnan_name_arvo
  * @param Kokonaisuuskontrolleri $kokonaisuuskontrolleri Tämä vähän
  * suurellinen, mutten äkkiä parempaa keinoa keksinyt (15.1.2015)
  * @param int $kaavakieli viittaa käytettävään matematiikan kaavakieleen
  * (28.11.2015)
  * @param Elementti $elementti on Elementti-luokan olio, johon tämä
  * kokonaisuus kuuluu, tai sitten Elementti::$MUUTTUJAA_EI_MAARITELTY,
  * ellei tulla koosteesta.
  * (20.2.2016)
  * @return <type>
  */
 function nayta_kokonaisuuslomake($id_kokon, $omaid, $uusi, $ilmoitus_kokon, $tietokantaolio, &$oppiaine_kokon, &$otsikko_kokon, &$tiivis_kokon, &$selitys_kokon, &$taso_kokon, &$jarjestysnro_kokon, &$laajennetun_id_kokon, &$ylakokonaisuuden_id_kokon, &$kieli_id, &$nakyvyys_kokon, $toiminnan_name_arvo, $kokonaisuuskontrolleri, $kaavakieli, $elementti, $elemryhma)
 {
     $mj = "";
     // Lomakkeen html-koodi.
     $otsikon_maxpituus = 150;
     $submitnappi = "";
     $perunappi = "";
     $uusi_kuva_tiivis = "";
     $uusi_kuva_seli = "";
     $tulo_koosteesta = false;
     // True, if coming from Kooste (Package).
     $kokonaisuus = "";
     // Tämä haetaan tietokannasta.
     /*$uusi_kuva_tiivis = "";
       $uusi_kuva_seli = "";*/
     $submit_kesken_nappi = "<input type='submit'" . "name='{$toiminnan_name_arvo}'" . "value='" . Painikkeet::$TALLENNA_KESKEN_KOKON_VALUE . "' " . "title='" . Painikkeet::$TALLENNA_KESKEN_KOKON_TITLE . "'/>";
     $esikatselunappi = "<button type='button' " . "onclick='nayta_kokonaisuuden_esikatselu(" . $id_kokon . ")'" . "title='" . Painikkeet::$ESIKATSELU_TITLE . "'/>" . Painikkeet::$ESIKATSELU_VALUE . "</button>";
     $elementtitiedot = "";
     // urliin lisättävät koosteen ja elementin idt
     if ($uusi) {
         $submitnappi = "<input type='submit'\n            name='{$toiminnan_name_arvo}'" . "value='" . Painikkeet::$TALLENNA_UUSI_KOKON_VALUE . "'/>";
         $perunappi = "<input type='submit'\n                    name='{$toiminnan_name_arvo}'" . "value='" . Painikkeet::$PERU_UUDEN_KOKON_TALLENNUS_VALUE . "'/>";
     } else {
         // Haetaan ajantasalla olevat tiedot tietokannasta. Aiemmin
         // tiedot tuotiin kiinteästi painikelomakkeeseen, mutta tällöin
         // tämän jälkeen olioon tehdyt muutokset eivät näkyneet, jos
         // alkoi tehdä muutoksia olioon.
         $kokonaisuus = new Kokonaisuusolio($id_kokon, $tietokantaolio);
         if ($kokonaisuus->olio_loytyi_tietokannasta) {
             $oppiaine_kokon = $kokonaisuus->getOppiaine();
             // Alla ovat tärkeitä, jotta esim. JS-koodi toimii, eikä
             // ala kehittämään mitään ylimääräistä muokatessa. Huom:
             // stripslash pilaa latex-koodin, eikä ilm tarpeellinen.
             $otsikko_kokon = htmlspecialchars($kokonaisuus->getOtsikko(), ENT_QUOTES, "UTF-8", true);
             $tiivis_kokon = htmlspecialchars($kokonaisuus->getTiivis(), ENT_QUOTES, "UTF-8", true);
             $selitys_kokon = htmlspecialchars($kokonaisuus->getSelitys(), ENT_QUOTES, "UTF-8", true);
             /*$otsikko_kokon = stripslashes($kokonaisuus->getOtsikko());
               $tiivis_kokon = stripslashes($kokonaisuus->getTiivis());
               $selitys_kokon = stripslashes($kokonaisuus->getSelitys());*/
             $taso_kokon = $kokonaisuus->getTaso();
             $jarjestysnro_kokon = $kokonaisuus->getJarjestysnro();
             $laajennetun_id_kokon = $kokonaisuus->getLaajennetun_id();
             $ylakokonaisuuden_id_kokon = $kokonaisuus->getYlakokonaisuuden_id();
             $nakyvyys_kokon = $kokonaisuus->getNakyvyys();
             $submitnappi = "<input type='submit'" . "name='{$toiminnan_name_arvo}'" . "value='" . Painikkeet::$TALLENNA_MUOKKAUS_KOKON_VALUE . "'" . "title='" . Painikkeet::$TALLENNA_MUOKKAUS_KOKON_TITLE . "'/>";
             $perunappi = "<input type='submit'\n                    name='{$toiminnan_name_arvo}'" . "value='" . Painikkeet::$PERU_KOKON_MUUTOSTEN_TALLENNUS_VALUE . "'/>";
             //==============================================================
             // Täällä katsotaan, onko käyttäjä tulossa koosteesta ja
             // mahdollistetaan kätevä paluu takaisin.=======================
             if ($elementti instanceof Elementti) {
                 $kooste_id = $elementti->get_arvo(Elementti::$sarakenimi_kooste_id);
                 $elem_id = $elementti->get_id();
                 //$koostenakymat = new Koostenakymat();
                 //$perunappi = $koostenakymat->
                 //        nayta_inputpainike_paluu_koosteeseen_no_form();
                 $elementtitiedot = "&" . Koostekontrolleri::$kooste_name_id . "=" . $kooste_id . "&" . Koostekontrolleri::$elementti_name_id . "=" . $elem_id;
                 $tulo_koosteesta = true;
             }
             if ($elemryhma instanceof Elementtiryhma) {
                 $elemryhma_id = $elemryhma->get_id();
                 $elementtitiedot .= "&" . Koostekontrolleri::$elemryhma_name_id . "=" . $elemryhma_id . "&";
                 $tulo_koosteesta = true;
             }
             //========= Kuvan lisäyspainikkeet: paluu vanhaan ideaan ===========
             /* Uuden kuvan lisäyspainike tiivistelmään*/
             $uusi_kuva_tiivis = "<input type='submit'" . "name='{$toiminnan_name_arvo}'" . "value='" . Painikkeet::$LISAA_KUVA_MANUAALI_TIIVIS_KOKON_VALUE . "'" . "title='" . Painikkeet::$LISAA_KUVA_MANUAALI_TIIVIS_KOKON_TITLE . "'/>";
             /* Uuden kuvan lisäyspainike selitykseen:*/
             $uusi_kuva_seli = "<input type='submit'" . "name='{$toiminnan_name_arvo}'" . "value='" . Painikkeet::$LISAA_KUVA_MANUAALI_SELITYS_KOKON_VALUE . "'" . "title='" . Painikkeet::$LISAA_KUVA_MANUAALI_SELITYS_KOKON_TITLE . "'/>";
             //==================================================================
         } else {
             $this->lisaa_virheilmoitus(Tekstit::$ilm_kokon_ei_loytynyt);
             return $this->tulosta_virheilmoitukset() . $perunappi;
         }
     }
     // End of päivitetään vanhaa.
     // NÄkyvyysvalikko: ====================================================
     $oletusarvo = $nakyvyys_kokon;
     $nakyvyydet = new Nakyvyys();
     $select_maaritteet = array(Attr::name(Kokonaisuuskontrolleri::$kokon_name_nakyvyys), Attr::title(Tekstit::$nakyvyys_valikko_otsikko_title));
     $option_maaritteet = array();
     $nakyvyysvalikko = $nakyvyydet->luo_pudotusvalikko($select_maaritteet, $option_maaritteet, $oletusarvo, Tekstit::$nakyvyys_valikko_otsikko);
     //======================================================================
     // Ilmoitus otetaan mukaan, jos ei tyhjä:
     if ($ilmoitus_kokon != "") {
         $ilmoitus_kokon = "<span class='kokonaisuuslomakeilmoitus'>" . $ilmoitus_kokon . "</span><br />";
     }
     $oppiainehtml = Tekstit::$oppiainevalikko_otsikko . ": <b>" . Oppiaineet::hae_oppiaineen_nimi($oppiaine_kokon) . "</b>";
     $koulutasohtml = Tekstit::$tasovalikko_otsikko . ": <b>" . Koulutasot::hae_koulutason_nimi($taso_kokon, false) . "</b>";
     // Kielivalintavalikko: VALINTA POISTETTU toimintavaikeuksien takia!
     //$kielivalintahtml = nayta_kielivalikko($kieli_id);
     $kielivalintahtml = Tekstit::$kielivalikko_otsikko . ": <b>" . Kielet::hae_kielen_nimi($kieli_id) . "</b>";
     // Ylempi kokonaisuustaso
     $ylakokonvalikko = $this->nayta_ylakokonaisuusvalikko($id_kokon, $tietokantaolio, $ylakokonaisuuden_id_kokon, $oppiaine_kokon, $kieli_id, $taso_kokon, $uusi, $omaid, $kokonaisuuskontrolleri);
     // Tekstinmuokkaus tiivistelmää varten:
     $muokattavan_elementin_id_tii = "tiivis_tekstiruutu";
     $alasvetovalikon_id = "merkit1_tiivis";
     $tekstityokaluolio = new Tekstityokalupalkki($muokattavan_elementin_id_tii, $alasvetovalikon_id);
     // Nykyään nämä toimii sekä tiivistelmälle että selitykselle.
     // Lomake osaa huomata, kunpaa ollaan muokkaamassa:
     $tekstimuokkauspainikkeet = $tekstityokaluolio->luo_painikkeet(Tekstityokalupalkki::$PERUSPAINIKKEET_JA_MATEMAATTISET, $kaavakieli);
     // Tekstinmuokkaus selitystä varten:
     $muokattavan_elementin_id_sel = "selitys_tekstiruutu";
     // Kaavakielivalikko:==================================================
     $kaavakielet = new Kaavakieli();
     $select_maaritteet = array(Attr::onchange("muuta_kaavakieli", array("this.value", Yleiset_arvot::$kaavakieli_name, $muokattavan_elementin_id_tii, $alasvetovalikon_id)));
     $option_maaritteet = array();
     $kaavakielivalikko = $kaavakielet->luo_pudotusvalikko($select_maaritteet, $option_maaritteet, $kaavakieli, Tekstit::$kaavakieli_otsikko);
     //=====================================================================
     if ($uusi) {
         // Ellei id-kokon-arvoa määritellä täällä, tulee sessiomuuttujasta vanha.
         $id_kokon = Kokonaisuusolio::$kokon_ei_maaritelty;
     }
     // Vanha ylakokon_id otetaan talteen, jotta lapsiasiat pysyvät
     // oikealla tolalla. Haetaan mahdollisimman tuoreet tiedot.
     $ylakokonaisuuden_id_vanha = $ylakokonaisuuden_id_kokon;
     if ($kokonaisuus instanceof Kokonaisuusolio) {
         $ylakokonaisuuden_id_vanha = $kokonaisuus->getYlakokonaisuuden_id();
     }
     /*lisaaTagit(elementin_id, elementin_tunnus, class_arvo, id_arvo*/
     // Sitten palat yhteen:
     $mj = "<form align='left' method='post' id='kokonaisuuslomake'" . "action='index.php?id_kokon=" . $id_kokon . "&ylakokonaisuuden_id_vanha=" . $ylakokonaisuuden_id_vanha . "&taso_kokon=" . $taso_kokon . "&kieli_id=" . $kieli_id . "&uusi=" . $uusi . $elementtitiedot . "'/>" . $ilmoitus_kokon . "<b>" . Tekstit::$kokonlomake_ohje . "</b>" . $esikatselunappi . "<table summary='uudet_tiedot'>" . "<tr><td>" . Tekstit::$kokonlomake_otsikko . ": </td><td><input type='text'\n            size='55' maxlength='{$otsikon_maxpituus}'" . "name='otsikko_kokon' value='{$otsikko_kokon}'" . "id='otsikkotekstikentta'" . "title='" . Tekstit::$kokonlomake_otsikkotitle . "'/>" . "</tr>" . "<tr><td></td>" . "<td>" . " " . $ylakokonvalikko . " " . $nakyvyysvalikko . "</td>" . "</tr>" . "<tr><td></td><td>" . $kaavakielivalikko . " " . $oppiainehtml . " " . $koulutasohtml . " " . $kielivalintahtml . "</td></tr>" . "<tr><td></td><td colspan='2'>" . $tekstimuokkauspainikkeet . "</td></tr>" . "<tr><td>" . Tekstit::$kokonlomake_tiivis . ":</td>" . "<td colspan='2'><textarea cols='80' rows='18' maxlength = '10000'\n            id='" . $muokattavan_elementin_id_tii . "' name='tiivis_kokon' \n            onfocus='kirjoituskentta_onfocus(\"tiivis_tekstiruutu\")'>" . $tiivis_kokon . "</textarea></td></tr>" . "<tr><td>" . Tekstit::$kokonlomake_selitys . ":</td>" . "<td colspan='2'><textarea cols='80' rows='9' maxlength = '10000'\n            id='" . $muokattavan_elementin_id_sel . "' name='selitys_kokon'\n            onfocus='kirjoituskentta_onfocus(\"selitys_tekstiruutu\")'>" . $selitys_kokon . "</textarea></td></tr>" . "<tr><td></td><td align='left'>" . $submitnappi . $submit_kesken_nappi . $uusi_kuva_tiivis . $uusi_kuva_seli . $perunappi . "</td></tr>" . "</table>" . "</form>";
     return $mj;
 }
 /**
  * Näyttää linkit liittyen kokonaisuuksiin. Jos kokonaisuusvektori on tyhjä
  * tai ei ole määritelty, palautetaan tyhjä merkkijono. 
  *
  * Kuhunkin linkkiin liittyy session-muuttuja, joka määrittelee, näytetäänkö
  * linkin jälkeläiset. Muuttujan nimi on kokonaisuuden id ja arvona "auki" tai
  * "kiinni". Huomaa, että arvo liittyy nimenomaan jälkeläisten näyttämiseen,
  * ei kyseisen kokonaisuuden näyttämiseen! 
  *
  *
  * @param Parametrit $parametriolio
  * @param bool $nayta_kiintolinkit
  * @return <type>
  */
 function hae_kokonaisuuslinkit($parametriolio, $nayta_kiintolinkit)
 {
     $kokonaisuudet = $parametriolio->kokonaisuusoliot;
     $id_kokon = $parametriolio->id_kokon;
     // Klikattu / aukaistava kokonaisuus
     $linkki_html = "";
     $tietokantaolio = $parametriolio->get_tietokantaolio();
     $on_kirjautunut = Henkilo::on_kirjautunut($parametriolio->get_omaid(), $tietokantaolio);
     if ($nayta_kiintolinkit) {
         //$linkki_html .=
         //     Html::luo_a_linkto('../index.php',
         //                         Tekstit::$linkki_kokon_etusivu,
         //                         array());
     }
     // Jos tullaan sivun ulkopuolisesta linkistä (siis urlin kautta), pitää
     // aukaista kaikki kokonaisuudet, jotka ovat näytettävän kokonaisuuden
     // yläpuolella, jotta koko linkkipuu on näkyvissä näytettävään kokonai-
     // suuteen asti.
     if ($parametriolio->naytto_urlin_mukaan()) {
         $id_avattava = $id_kokon;
         $kokon_avattava = new Kokonaisuusolio($id_avattava, $tietokantaolio);
         $ylakokon_id_avattava = $kokon_avattava->getYlakokonaisuuden_id();
         do {
             if ($kokon_avattava instanceof Kokonaisuusolio) {
                 $muuttujanimi = Parametrit::linkkisessiomuuttujan_nimi($kokon_avattava->get_id());
                 $_SESSION[$muuttujanimi] = Kokonaisuusolio::$LINKKI_AUKI;
                 // Haetaan yläkokonaisuus:
                 $kokon_avattava = new Kokonaisuusolio($ylakokon_id_avattava, $tietokantaolio);
                 // Ja uusi yläkokon_id
                 $ylakokon_id_avattava = $kokon_avattava->getYlakokonaisuuden_id();
             }
         } while ($kokon_avattava->olio_loytyi_tietokannasta);
     }
     if (isset($kokonaisuudet) && is_array($kokonaisuudet)) {
         if (!empty($kokonaisuudet)) {
             $linkki_html .= "<table>";
             $rajataso = 0;
             $piilotus_kaynnissa = false;
             // Näytetäänkö linkit vai ei.
             foreach ($kokonaisuudet as $kokon) {
                 if ($kokon instanceof Kokonaisuusolio) {
                     $taso = $kokon->getOtsikkotaso();
                     if ($taso > 8) {
                         $taso = 8;
                         /* Enempää tasoja ei ole tyyleissä */
                     }
                     // Tarkistetaan tässä, ollaanko tultu pois piilotettavien
                     // alilinkkien joukosta
                     if ($piilotus_kaynnissa && $kokon->getOtsikkotaso() <= $rajataso) {
                         $piilotus_kaynnissa = false;
                     }
                     // Muotoillaan linkkielementin alkutagi=====================
                     // Linkkielementin alkutagin alku:
                     $linkki_id = "linkki" . $kokon->get_id();
                     $rivin_alku = "<tr class='linkkielementti'" . "id='" . $linkki_id . "'";
                     // Session-muuttuja sanelee näyttämisen.
                     // HUOM! Linkki_kiinni/linkki_auki vaikuttaa lapsilinkkeihin, ei
                     // varsinaisen linkin näkymiseen! Tämän avulla muistetaan
                     // puurakenne.
                     // Idea: kokonaisuuslista käydään läpi. Jokaisen kohdalla
                     // tarkistetaan onko auki. Jos kiinni, käydään läpi alilinkit
                     // ja poistetaan näkyvistä. Samalla tarkistetaan sessio-
                     // muuttuja ja asetetaan ei-määritellyt kiinni-oleviksi,
                     // jolloin linkistö on avatessa mahdollisimman kiinni.
                     $linkkielem_style = " ";
                     $muuttujanimi = Parametrit::linkkisessiomuuttujan_nimi($kokon->get_id());
                     // Eka kerralla ja ryhmän vaihdon yhteydessä suljetaan
                     // kaikki linkit. Poikkeus: kun tullaan linkin kautta,
                     // on järkevää avata kyseisen kokonaisuuden aliotsikot.
                     // Kokonaisuusryhmän_vaihto on oletusarvoisesti false.
                     if (!isset($_SESSION[$muuttujanimi]) || $parametriolio->kokonaisuusryhman_vaihto) {
                         $_SESSION[$muuttujanimi] = Kokonaisuusolio::$LINKKI_KIINNI;
                         // Käsitellään tässä tulo linkin kautta, jolloin
                         // määritellään sessioarvo näytettävän alikoko-
                         // suudelle:
                         if ($parametriolio->naytto_urlin_mukaan() && $id_kokon == $kokon->getYlakokonaisuuden_id()) {
                             // Linkki kiinni -> näkyy vain yksi taso alemma.
                             // (tämä ei kyllä sitä rajoita, mutta asettaa
                             // plussan oikein)
                             $_SESSION[$muuttujanimi] = Kokonaisuusolio::$LINKKI_KIINNI;
                         } else {
                             // Eka taso näytetään aina, mutta muita ei.
                             if ($taso > 1) {
                                 $linkkielem_style = " style='display:none;'";
                             }
                         }
                     } else {
                         if ($piilotus_kaynnissa) {
                             $linkkielem_style = " style='display:none;'";
                         } else {
                             if (!$piilotus_kaynnissa && $kokon->on_naytettavia_lapsia($parametriolio->get_omaid()) && $_SESSION[$muuttujanimi] == Kokonaisuusolio::$LINKKI_KIINNI) {
                                 $piilotus_kaynnissa = true;
                                 // Rajataso muutetaan tämän tasoksi, jolloin
                                 // tiedetään, milloin tullaan ylemmäksi taas.
                                 $rajataso = $kokon->getOtsikkotaso();
                             } else {
                                 //Ellei lapsia tai linkki auki -> näytetään seuraava
                                 // Ei lisätä tyyliä
                             }
                         }
                     }
                     // Linkkielementin alkutagin loppuosa:
                     $rivin_alku .= $linkkielem_style . ">";
                     //==========================================================
                     // Plus lisätään, jos kokonaisuudella on jälkeläisiä ja
                     // linkki on kiinni.
                     if ($kokon->on_naytettavia_lapsia($parametriolio->get_omaid()) && $_SESSION[$muuttujanimi] == Kokonaisuusolio::$LINKKI_KIINNI) {
                         $plus = "+ ";
                     } else {
                         if ($kokon->on_naytettavia_lapsia($parametriolio->get_omaid()) && $_SESSION[$muuttujanimi] == Kokonaisuusolio::$LINKKI_AUKI) {
                             $plus = "− ";
                         } else {
                             $plus = "";
                         }
                     }
                     $risuaita_id = "";
                     if ($parametriolio->get_kokonaisuuksien_nayttotapa() == Kokonaisuuksien_nayttotavat::$kokonaisuudet_nayta_kaikki_arvo) {
                         $risuaita_id = "#" . $kokon->get_id();
                     }
                     // Jos näytetään pelkästään tämä kokonaisuus, merkitään
                     // se linkeissä eri ulkonäöllä, ellei ole kyseessä
                     // kokonaisuusryhmän vaihto:
                     if ($parametriolio->get_kokonaisuuksien_nayttotapa() == Kokonaisuuksien_nayttotavat::$kokonaisuudet_nayta_yksi_kerrallaan_arvo && !$parametriolio->kokonaisuusryhman_vaihto && $kokon->get_id() == $id_kokon) {
                         $valitun_id = "id='valittu_kokon'";
                     } else {
                         $valitun_id = "";
                     }
                     $etumerkin_html = "<td class='linkin_etumerkki'" . "id='etumerkki" . $kokon->get_id() . "'" . "onmouseover='hiiri_paalla(this)'" . "onmouseout='hiiri_pois_paalta(this)'" . "onclick='vaihda_etumerkki(this.id," . $kokon->get_id() . ",\"kokonaisuudet\")'>{$plus}</td>";
                     /* Otsikon klikkaaminen avaa aliotsikot (jos on). */
                     if (!empty($plus)) {
                         $onclick = " onclick='aukaise_aliotsikot(" . $kokon->get_id() . ")'";
                     } else {
                         $onclick = "";
                     }
                     $linkin_alku = "<td class='linkkisolu'><a class='taso" . $taso . "' " . $valitun_id . $onclick . " href=index.php" . "?id_kokon=" . $kokon->get_id() . $risuaita_id . ">";
                     $linkin_loppu = "</a></td>";
                     $rivin_loppu = "</tr>";
                     // Linkkielementin lopputagi
                     // Otsikkonumeroita ei näytetä tietyn tason jälkeen:
                     if ($taso > Kokonaisuusolio::$max_otsikkonron_nayttotaso) {
                         $otsikkonro = "";
                     } else {
                         $otsikkonro = $kokon->getOtsikkomerkinta() . " ";
                     }
                     // Julkiset näytetään ilman mukinoita:
                     if ($kokon->getNakyvyys() + 0 === Nakyvyys::$JULKINEN) {
                         $linkki_html .= $rivin_alku;
                         $linkki_html .= $etumerkin_html . $linkin_alku;
                         $linkki_html .= $otsikkonro;
                         $linkki_html .= $kokon->getOtsikko();
                         $linkki_html .= $linkin_loppu;
                         $linkki_html .= $rivin_loppu;
                     } else {
                         if ($kokon->getNakyvyys() + 0 === Nakyvyys::$VAIN_OTSIKKO) {
                             $linkki_html .= $rivin_alku;
                             $linkki_html .= $etumerkin_html . $linkin_alku;
                             $linkki_html .= "<span class='piilotettu'>";
                             $linkki_html .= $otsikkonro;
                             $linkki_html .= $kokon->getOtsikko();
                             $linkki_html .= "</span>";
                             $linkki_html .= $linkin_loppu;
                             $linkki_html .= $rivin_loppu;
                         } else {
                             if ($on_kirjautunut) {
                                 // Jos näkyvyys ei ole julkinen, tarkistetaan olion
                                 // kohdeoikeudet. Tätä ei tehdä julkisille, jottei
                                 // hidasta menoa liikaa:
                                 /*======================== käyttäjän oikeudet ====*/
                                 $kohdeoikeudet = Henkilo::hae_kayttajan_kohdeoikeudet($kokon->getHenkiloId(), $this->get_parametriolio()->get_omaid(), Oliotyyppi::$KOKONAISUUS, $kokon->get_id(), $tietokantaolio);
                                 /*===============================================*/
                                 // Jos on vähintään muokkausoikeudet, näytetään
                                 // linkki sopivasti muotoiltuna:
                                 if ($kohdeoikeudet >= Lisavaltuudet::$SAA_MUOKATA_EI_POISTAA) {
                                     if ($kokon->getNakyvyys() + 0 === Nakyvyys::$YKSITYINEN) {
                                         $class_arvo = "yksityinen";
                                     } else {
                                         if ($kokon->getNakyvyys() + 0 === Nakyvyys::$VAIN_KOOSTEESSA) {
                                             $class_arvo = "vain_koosteessa";
                                         } else {
                                             $class_arvo = "tuntematon";
                                         }
                                     }
                                     $linkki_html .= $rivin_alku;
                                     $linkki_html .= $etumerkin_html . $linkin_alku;
                                     $linkki_html .= "<span class='" . $class_arvo . "'>";
                                     $linkki_html .= $otsikkonro;
                                     $linkki_html .= $kokon->getOtsikko();
                                     $linkki_html .= "</span>";
                                     $linkki_html .= $linkin_loppu;
                                     $linkki_html .= $rivin_loppu;
                                 }
                             } else {
                                 // Ei näytetä linkkiä!
                             }
                         }
                     }
                 }
             }
             $linkki_html .= "</table>";
         }
     }
     return $linkki_html;
 }
 /**
  * Metodi, joka tallentaa muokatun kokonaisuuden tiedot tietokantaan.
  * Palauttaa arvon Malliluokkapohja::$VIRHE, jos tallennus epäonnistuu,
  * muuten arvon Malliluokkapohja::$OPERAATIO_ONNISTUI.
  *
  * Ajaa Malliluokkapohjan vastaavan metodin yli.
  * 
  * Seuraavat arvot asetetaan täällä automaattisesti, joten niistä ei
  * tarvitse muualla huolehtia: 
  * 
  *   ed_muutos_sek
  * 
  * luomishetki_sek-arvoa ei ole syytä muuttaa, vaikka sitä ei estetä täällä.  
  * 
  * Huolehtii myös isikokonaisuuksien on_lapsia-arvojen päivittämisestä silloin, kun
  * isikokonaisuutta vaihdetaan. Tällöin sekä uuden että vanhan isi-
  * kokonaisuuden on_lapsia-arvot tarkistetaan ja päivitetään.
  * 
  * @return int Palauttaa normaalin Malliluokkapohja::$VIRHE tai 
  * Malliluokkapohja::$OPERAATIO_ONNISTUI -arvon.
  * */
 function tallenna_muutokset()
 {
     $this->set_arvo(time(), Kokonaisuusolio::$sarakenimi_ed_muutos_sek);
     // Haetaan tietokannassa olevan olion ylakokonaisuuden_id, koska tämän
     // olion arvoja on jo saatettu muuttaa:
     $vanha = new Kokonaisuusolio($this->get_id(), $this->tietokantaolio);
     $ylakokonaisuuden_id_vanha = $vanha->getYlakokonaisuuden_id();
     $tallennus = parent::tallenna_muutokset();
     if ($tallennus === Malliluokkapohja::$OPERAATIO_ONNISTUI) {
         // Päivitetään on_lapsia, jos kokonaisuus on linkitetty johonkin muuhun:
         $ylakokonaisuuden_id = $this->getYlakokonaisuuden_id();
         if ($ylakokonaisuuden_id != $ylakokonaisuuden_id_vanha) {
             // Jos uusi yläkokonaisuus on olemassaolevan kokonaisuus,
             // varmistetaan, että sillä on lapsia.
             if ($ylakokonaisuuden_id > 0) {
                 $ylakok = new Kokonaisuusolio($ylakokonaisuuden_id, $this->tietokantaolio);
                 if ($ylakok->olio_loytyi_tietokannasta) {
                     $on_lapsia = 1;
                     $onnistuminen = $ylakok->tallenna_on_lapsia_muutos_kokon($on_lapsia);
                     if ($onnistuminen === Kokonaisuusolio::$VIRHE) {
                         $this->lisaa_virheilmoitus(Tekstit::$virheilm_kokon_muutostallennus_lapsimuutos_eiok);
                     }
                 } else {
                     $this->lisaa_virheilmoitus(Tekstit::$ilm_kokon_ei_loytynyt);
                 }
             }
             // Mahdollinen entinen yläkokonaisuus pitää myös tarkistaa, onko
             // sillä vielä lapsia vai ei.  Mutta vain jos id > 0, koska
             // muuten kokonaisuudella ei ennen ollut yläkokonaisuuksia.
             if ($ylakokonaisuuden_id_vanha > 0) {
                 $ylakok_vanha = new Kokonaisuusolio($ylakokonaisuuden_id_vanha, $this->tietokantaolio);
                 if ($ylakok_vanha->olio_loytyi_tietokannasta) {
                     if ($ylakok_vanha->on_lapsia_kokon()) {
                         $on_lapsia = 1;
                     } else {
                         $on_lapsia = 0;
                     }
                     $onnistuminen = $ylakok_vanha->tallenna_on_lapsia_muutos_kokon($on_lapsia);
                     if ($onnistuminen === Kokonaisuusolio::$VIRHE) {
                         $this->lisaa_virheilmoitus(Tekstit::$virheilm_kokon_muutostallennus_lapsimuutos_eiok);
                     }
                 } else {
                     $this->lisaa_virheilmoitus(Tekstit::$ilm_kokon_ei_loytynyt);
                 }
             }
         }
     }
     return $tallennus;
 }
 /**
  * Palauttaa elementtilistan yhden kokonaisuuden + näytettävien tehtävien
  * muodostaman html-koodin.
  * 
  * HUOM: hiukan hämäävästi kokonaisuus tekee yhden taulukkorivin ja 
  * kukin tehtävä yhden lisää, eli tämä voi palauttaa useammankin 
  * taulukkorivin html:n.
  * 
  * @param Kokonaisuusolio $kokon
  * @param type $rajataso huomaa &!
  * @param type $piilotuskaynnissa huomaa &!
  * @param boolean $on_kirjautunut false - ei kirjautunut käyttäjä, true -
  * käyttäjä on kirjautunut ja hänellä voi olla enemmän oikeuksia.
  */
 private function luo_elementtilistan_kokonrivi($kokon, &$rajataso, &$piilotus_kaynnissa, $on_kirjautunut)
 {
     $parametriolio = $this->get_parametriolio();
     $tietokantaolio = $this->get_tietokantaolio();
     $tyhja_taul = array();
     $palautus_html = "";
     if ($kokon instanceof Kokonaisuusolio) {
         $id_kokon = $kokon->get_id();
         $teht_naytto_nimi = Parametrit::sessiomuut_nimi_kokontehtnaytto_koostelomake($id_kokon);
         $taso = $kokon->getOtsikkotaso();
         if ($taso > 8) {
             $taso = 8;
             /* Enempää tasoja ei ole tyyleissä */
         }
         // Tarkistetaan tässä, ollaanko tultu pois piilotettavien
         // alilinkkien joukosta
         if ($piilotus_kaynnissa && $kokon->getOtsikkotaso() <= $rajataso) {
             $piilotus_kaynnissa = false;
         }
         // Muotoillaan linkkielementin alkutagi=====================
         // Linkkielementin alkutagin alku:
         $linkki_id = "linkki" . $kokon->get_id();
         $rivin_alku = "<tr class='kooste_elementti'" . "id='" . $linkki_id . "'";
         // Session-muuttuja sanelee näyttämisen.
         // HUOM! Linkki_kiinni/linkki_auki vaikuttaa lapsilinkkeihin, ei
         // varsinaisen linkin näkymiseen! Tämän avulla muistetaan
         // puurakenne.
         // Idea: kokonaisuuslista käydään läpi. Jokaisen kohdalla
         // tarkistetaan onko auki. Jos kiinni, käydään läpi alilinkit
         // ja poistetaan näkyvistä. Samalla tarkistetaan sessio-
         // muuttuja ja asetetaan ei-määritellyt kiinni-oleviksi,
         // jolloin linkistö on avatessa mahdollisimman kiinni.
         $linkkielem_style = " ";
         $muuttujanimi = Parametrit::linkkisessiomuuttujan_nimi($kokon->get_id());
         // Eka kerralla ja ryhmän vaihdon yhteydessä suljetaan
         // kaikki linkit. Poikkeus: kun tullaan linkin kautta,
         // on järkevää avata kyseisen kokonaisuuden aliotsikot.
         // Kokonaisuusryhmän_vaihto on oletusarvoisesti false.
         if (!isset($_SESSION[$muuttujanimi]) || $parametriolio->kokonaisuusryhman_vaihto) {
             $_SESSION[$muuttujanimi] = Kokonaisuusolio::$LINKKI_KIINNI;
             // Käsitellään tässä tulo linkin kautta, jolloin
             // määritellään sessioarvo näytettävän alikoko-
             // suudelle:
             if ($parametriolio->naytto_urlin_mukaan() && $id_kokon == $kokon->getYlakokonaisuuden_id()) {
                 // Linkki kiinni -> näkyy vain yksi taso alemma.
                 // (tämä ei kyllä sitä rajoita, mutta asettaa
                 // plussan oikein)
                 $_SESSION[$muuttujanimi] = Kokonaisuusolio::$LINKKI_KIINNI;
             } else {
                 // Eka taso näytetään aina, mutta muita ei.
                 if ($taso > 1) {
                     $linkkielem_style = " style='display:none;'";
                 }
             }
         } else {
             if ($piilotus_kaynnissa) {
                 $linkkielem_style = " style='display:none;'";
             } else {
                 if (!$piilotus_kaynnissa && $kokon->on_naytettavia_lapsia($parametriolio->get_omaid()) && $_SESSION[$muuttujanimi] == Kokonaisuusolio::$LINKKI_KIINNI) {
                     $piilotus_kaynnissa = true;
                     // Rajataso muutetaan tämän tasoksi, jolloin
                     // tiedetään, milloin tullaan ylemmäksi taas.
                     $rajataso = $kokon->getOtsikkotaso();
                 } else {
                     //Ellei lapsia tai linkki auki -> näytetään seuraava
                     // Ei lisätä tyyliä
                 }
             }
         }
         // Linkkielementin alkutagin loppuosa:
         $rivin_alku .= $linkkielem_style . ">";
         //==========================================================
         // Plus lisätään, jos kokonaisuudella on jälkeläisiä ja
         // linkki on kiinni.
         if ($kokon->on_naytettavia_lapsia($parametriolio->get_omaid()) && $_SESSION[$muuttujanimi] == Kokonaisuusolio::$LINKKI_KIINNI) {
             $plus = "+ ";
         } else {
             if ($kokon->on_naytettavia_lapsia($parametriolio->get_omaid()) && $_SESSION[$muuttujanimi] == Kokonaisuusolio::$LINKKI_AUKI) {
                 $plus = "− ";
             } else {
                 $plus = "";
             }
         }
         $etumerkin_html = "<td class='linkin_etumerkki'" . "id='etumerkki" . $kokon->get_id() . "'" . "onmouseover='hiiri_paalla(this)'" . "onmouseout='hiiri_pois_paalta(this)'" . "onclick='vaihda_etumerkki(this.id," . $kokon->get_id() . ",\"koostelomake\")'>{$plus}</td>";
         $valruutusolu = $this->luo_elementtilistan_valintaruutusolu($kokon, true);
         // Preview button:
         $value = $this->luo_valittulistan_valintaruudun_value($kokon);
         $preview_button = $this->koostenakymat->create_button_show_preview($value);
         $preview_button_cell = Html::luo_tablesolu($preview_button, $tyhja_taul);
         //=============== Lisätään tehtävien näyttöpainike, jos
         // niitä kokonaisuudella on: ===========================
         // Ensin haetaan tehtävät, joita tarvitaan mahdollisesti
         // myöhemmin (vain tehtävät, joihin oikeudet):
         $tehtavat = Tehtava::hae_tehtavat_koostelomake($kokon->get_id(), $tietokantaolio, $this->get_parametriolio()->get_omaid());
         // Tarkistetaan, ovatko tehtävät jo koosteessa ja lisätään vastaava
         // muuttujan arvo (jos kysymys muokkauksesta):
         $nyk_kooste = $this->get_olio();
         if ($nyk_kooste instanceof Kooste) {
             $elementit = $nyk_kooste->hae_elementit();
             $this->merkitse_valitut($tehtavat, $elementit);
             $kooste_id = $nyk_kooste->get_id();
         } else {
             $kooste_id = Kooste::$MUUTTUJAA_EI_MAARITELTY;
         }
         $teht_lkm = sizeof($tehtavat);
         $nappi_id = "tehtavanappi_" . $kokon->get_id();
         if ($teht_lkm > 0) {
             if (isset($_SESSION[$teht_naytto_nimi]) && $_SESSION[$teht_naytto_nimi] == Kokonaisuusolio::$TEHT_NAYTA) {
                 // Tehtävät näkyvissä, joten mahdollistetaan piilotus:
                 $show = false;
             } else {
                 // Tehtävät piilossa, joten mahdollistetaan näyttö:
                 $show = true;
             }
             $tehtnappi = $this->koostenakymat->create_button_showhide_problems_in_summaryform($show, $kooste_id, $kokon->get_id(), $nappi_id);
         } else {
             $tehtnappi = "";
         }
         // Luodaan solu kuitenkin aina:
         $tehtnappisolu = Html::luo_tablesolu($tehtnappi, array());
         //===================== Rivin lopputagi ================
         $rivin_loppu = "</tr>";
         // Otsikkonumeroita ei näytetä tietyn tason jälkeen:
         if ($taso > Kokonaisuusolio::$max_otsikkonron_nayttotaso) {
             $otsikkonro = "";
         } else {
             $otsikkonro = $kokon->getOtsikkomerkinta() . " ";
         }
         $ruudun_id = $this->luo_elementtilistan_valintaruudun_id($kokon);
         /* Otsikon klikkaaminen paivittää valittujen listan. */
         $elem_otsikko = $this->luo_elementtilistan_otsikkosolu($ruudun_id, $otsikkonro, "", $taso, $kokon->getOtsikko(), $kokon->get_id());
         // Julkiset näytetään ilman mukinoita:
         if ($kokon->getNakyvyys() + 0 === Nakyvyys::$JULKINEN) {
             $palautus_html .= $rivin_alku . $etumerkin_html . $elem_otsikko . $valruutusolu . $preview_button_cell . $tehtnappisolu . $rivin_loppu;
         } else {
             if ($on_kirjautunut) {
                 // Jos näkyvyys ei ole julkinen, tarkistetaan olion
                 // kohdeoikeudet. Tätä ei tehdä julkisille, jottei
                 // hidasta menoa liikaa:
                 /*======================== käyttäjän oikeudet ====*/
                 $kohdeoikeudet = Henkilo::hae_kayttajan_kohdeoikeudet($kokon->getHenkiloId(), $this->get_parametriolio()->get_omaid(), Oliotyyppi::$KOKONAISUUS, $kokon->get_id(), $tietokantaolio);
                 /*===============================================*/
                 // Jos on vähintään muokkausoikeudet, näytetään
                 // linkki sopivasti muotoiltuna:
                 if ($kohdeoikeudet >= Lisavaltuudet::$SAA_MUOKATA_EI_POISTAA) {
                     if ($kokon->getNakyvyys() + 0 === Nakyvyys::$YKSITYINEN) {
                         $class_arvo = "yksityinen";
                     } else {
                         if ($kokon->getNakyvyys() + 0 === Nakyvyys::$VAIN_KOOSTEESSA) {
                             $class_arvo = "vain_koosteessa";
                         } else {
                             if ($kokon->getNakyvyys() + 0 === Nakyvyys::$VAIN_OTSIKKO) {
                                 $class_arvo = "piilotettu";
                             } else {
                                 $class_arvo = "outo";
                             }
                         }
                     }
                     $elem_otsikko = $this->luo_elementtilistan_otsikkosolu($ruudun_id, $otsikkonro, $class_arvo, $taso, $kokon->getOtsikko(), $kokon->get_id());
                     $palautus_html .= $rivin_alku;
                     $palautus_html .= $etumerkin_html;
                     $palautus_html .= $elem_otsikko;
                     $palautus_html .= $valruutusolu;
                     $palautus_html .= $preview_button_cell;
                     $palautus_html .= $tehtnappisolu;
                     $palautus_html .= $rivin_loppu;
                 }
             } else {
                 // Ei näytetä linkkiä!
             }
         }
         // Täällä on aika tarkistaa, näytetäänkö kokonaisuuden
         // tehtävät täällä ja myönteisessä tapauksessa näytetään.
         if (isset($_SESSION[$teht_naytto_nimi]) && $_SESSION[$teht_naytto_nimi] == Kokonaisuusolio::$TEHT_NAYTA) {
             foreach ($tehtavat as $teht) {
                 $palautus_html .= $this->luo_elemlistan_tehtavarivi($teht, true);
             }
         } else {
             // Varmistetaan arvo:
             $_SESSION[$teht_naytto_nimi] = Kokonaisuusolio::$TEHT_PIILOSSA;
         }
     }
     return $palautus_html;
 }