IMPORTANT: Per accedir als fitxer de subversion: http://acacha.org/svn (sense password). Poc a poc s'aniran migrant els enllaços. Encara però funciona el subversion de la farga però no se sap fins quan... (usuari: prova i la paraula de pas 123456)

Contingut

Introducció

Manual d'usuari

PROGRAMACIÓ WEB

– Modificacions en l'aplicació webfaltes –

Marc Grau Benaiges

Preparació de l'entorn d'explotació

  • És necessari tindre una màquina d'Ubuntu Server instal·lada.
  • Té que tindre instal·lat el servidor LAMP.

Instal·lar el LAMP Server

Si no tenim instal·lat el tasksel:

$ sudo apt-get install tasksel


Per a instal·lar el servidor LAMP:

$ sudo tasksel install lamp-server

Obtenir l'aplicació Webfaltes

Obtindrem el codi font a partir del subversion:

$ sudo apt-get install subversion
$ cd
$ sudo svn co http://www.iesebre.com/subversion/projectes/webfaltes/trunk webfaltes
$ cd webfaltes
$ sudo make install

NOTA: No us cal utilitzar cap usuari específic de subversion per a obtenir el codi. Al no indicar cap usuari esteu utilitzant l'usuari anònim amb accés de només lectura

Configurar el servidor Web Apache

Configurarem el servidor web Apache habilitant un lloc Web per al programari Webfaltes.

$ sudo nano /etc/apache2/sites-available/webfaltes

NOTA: L'aplicació webfaltes intenta seguir les indicacions de l'estàndard FHS i per aquesta raó la carpeta escollida per als fitxers estàtics és /usr/share/webfaltes

Afegirem les següents línies a l'arxiu:


Alias /webfaltes /usr/share/webfaltes


php_admin_flag register_globals off



Veure: Configuració alternativa. Exemple www.iesebre.com per a altres configuracions.


Alia farà que quan s'escrigui la URL: http://localhost/webfaltes

es mostrin els fitxers de la següent direcció dins del servidor: /usr/share/webfaltes

NOTA: Per defecte els fitxers a mostrar són els index. Podem establir un ordre de prioritat dels fitxers "index", per defecte, primer agafarà el "index.html" i si aquest no existeix, el "index.php", que serà el nostre cas.


Per activar el lloc web que hem definit anteriorment, executarem la següent comanda:

$ sudo a2ensite webfaltes


Tornarem a carregar els fitxers de configuració sense tindre que apagar el servidor:

$ sudo service apache2 reload


També podem utilitzar la següent comanda:

$ sudo /etc/init.d/apache2 reload


Per aplicar els canvis al servidor web. L'ordre a2ensite activa un site ( lloc web ) definit, en canvi l'ordre a2dissite desactiva el site:

$ sudo a2dissite webfaltes

Instal·lació de LDAP

Per a realitzar l'instal·lació en un servidor Ubuntu 12.04 executem les següents comandes:

$ sudo apt-get install slapd ldap-utils
S'està configurant slapd (2.4.28-1.1ubuntu4)…
  Moving old database directory to /var/backups:
  - directory unknown... done.
  Creating initial configuration... done.
  Creating LDAP directory... done.
 * Starting OpenLDAP slapd                                                       [ OK ] 
S'està configurant ldap-utils (2.4.28-1.1ubuntu4)…
S'estan processant els activadors per a libc-bin…
ldconfig deferred processing now taking place


Re-configurarem el servidor:

$ sudo dpkg-reconfigure slapd
 * Stopping OpenLDAP slapd                                                       [ OK ] 
  Moving old database directory to /var/backups:
  - directory unknown... done.
  Creating initial configuration... done.
  Creating LDAP directory... done.
 * Starting OpenLDAP slapd  
  • Quan l'assistent ens pregunti: "Voleu ometre la configuració del servidor OpenLDAP?" li direm que no.
  • Nom del domini DNS: iesebre.com .
  • Nom de l'organització: iesebre.com .
  • Contrasenya i repetició d'aquesta.
  • Motor: HDB ( És el recomanat ).
  • Li diem que no s'elimini la base de dades.
  • Li diem que mogui la base de dades.
  • Li diem que no permetrem l'ús del protocol LDAPv2.


Esquemes

Afegir els esquemes del gosa per poder importar les dades de la Demo de informàtica.

$ sudo -s
# cd /etc/ldap/slapd.d/cn=config/cn=schema
# rm -rf *
# wget http://acacha.org/~sergi/gosa/gosa-2.7-ldifs.tar.gz 
# tar xvzf gosa-2.7-ldifs.tar.gz

NOTA: La diferència entre sudo -s i sudo su és que el primer no canvia les variables d'entorn, per exemple, sudo su canvia la variable "HOME": "/root" .


Tots els esquemes hauràn de ser de l'usuari openldap

# chown openldap:openldap -R *

I reiniciarem el servei LDAP.

# exit
$ sudo /etc/init.d/slapd restart


Creació de l'usuari LDAP ( Aquest punt és informatiu i no es te que du a terme )

Degut al bolcat de la base de dades de demostració que es realitzarà més endavant, aquest usuari ja existirà, per tant, a menys que no es realitzi el bolcat, aquest pas no es te que realitzar.


Es necessari crear un usuari que permeti a l'aplicació accedir a la base de dades Ldap en mode només lectura, per raons de seguretat.

NOTA: Es podria utilitzar el admindn per a connectar-se al servidor Ldap però representaria un problema de seguretat. A més l'aplicació no necessita accés d'escriptura a l'arbre Ldap, només de lectura


Per tal de crear aquest usuari podeu utilitzar el següent fitxer "usuari.ldif".

NOTA: L'exemple està pensat per al domini iesebre.com! És important que canvieu les dades per adaptar-se a les vostres necessitats.

$ nano usuari.ldif
dn: cn=webfaltes,dc=iesebre,dc=com
objectClass: inetOrgPerson
cn: webfaltes
sn: webfaltes
uid: webfaltes
userPassword: {MD5}sac43R48I+13VCvWpQribA==

Per generar la contrasenya realitzarem els següents passos:

$ slappasswd -h {MD5}
New password: 
Re-enter new password: 
{MD5}sac43R48I+13VCvWpQribA==

Modifica l'script anterior amb la paraula de pas generada i després executa el ldapadd per afegir les modificacions corresponents.

# ldapadd -x -D "cn=admin,dc=iesebre,dc=com" -W -f usuari.ldif 
Enter LDAP Password: 
adding new entry "cn=webfaltes,dc=iesebre,dc=com"

On:

-f : Indica el fitxer ldif
-D : Indica el dn
-W : Per a que demane la paraula de pas

O també es pot afegir utilitzant alguna eina gràfica de gestió del servidor Ldap com per exemple ADS (per exemple es pot fer a mà o amb un import del fitxer ldif que us proporcionem).


Configuració de MySQL

El servidor MySQL se suposa que ja està instal·lat des de el moment que s'ha instal·lat un sistema LAMP.


Podem realitzar l'instal·lació amb un script automàtic o de forma manual.

Instal·lació automàtica ( Les dades que utilitza el script estan desactualitzades - No recomanable )

$ sudo -s
# /usr/share/doc/webfaltes/examples/database/installdatabase.sh

Ens demanarà la contrasenya d'accés a MySQL, crearà un usuari d'accés i la base de dades anomenada "webfaltes", instal·larà l'esquema de les taules i per acabar omplirà la base de dades.

Instal·lació manual

Per poder utilitzar la base de dades que utilitza el projecte, l'haurem de crear de la següent manera:

Primer accedirem dins al mysql amb (la contrasenya ens l'ha demanat a la instal·lació):

$ mysql -u root -p

NOTA: La -p s'haurà de posar per a que ens demani la contrasenya de MySQL al entrar, si no la posem ens podria donar un error.


Una vegada hem entrat dins del MySQL haurem de crear la base de dades buida copiant aquesta comanda SQL:

mysql> CREATE DATABASE webfaltes;
mysql> exit;

A continuació li passarem l'esquema de la base de dades.

$ mysql -u root -p webfaltes < /usr/share/doc/webfaltes/examples/database/webfaltes-schema.sql

NOTA: La ultima versió ens la podem baixar aquí.


I li afegim les dades amb la següent comanda:

$ wget http://www.iesebre.com/subversion/projectes/webfaltes/trunk/usr/share/doc/webfaltes/sql/demo_bdsql_infor_dep/webfaltesDEMO_DEP_INFO.sql
$ mysql -u root -p webfaltes < webfaltesDEMO_DEP_INFO.sql


I ara ens farem l'usuari entrant al MySQL i posant el següent:


$ mysql -u root -p
mysql> CREATE USER 'webfaltes'@'localhost' IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON webfaltes.* TO 'webfaltes'@'localhost' WITH GRANT OPTION;
mysql> FLUSH PRIVILEGES;
mysql> exit

IMPORTANT: La paraula usuari i password s'hauran de canviar per l'usuari i la contrasenya de MySQL que vulgueu posar.

NOTA: En cas de voler eliminar l'usuari utilitzeu: DROP USER 'webfaltes'@'localhost';

Instal·lació de la Base de dades de demostració

Base de Dades Ldap

La base de dades de demostració només conté dades fictícies de la família d'informàtica (professors,alumnes,grups) i les dades del usuari administrador de l'institut i del usuari webfaltes. Totes les paraules de pas són la mateixa : gosa. Menys la de l'usuari webfaltes. Aquesta base de dades està emmagatzemada en un fitxer .ldif que es troba a l'enllaç següent :


Base de dades de demostració


Suposant que a l'Apache Directory Studio ja tinguéssim creada la connexió i que la base de dades ldap estigui buida ja podrem passar a instal·lar-ho. Per a fer això haurem d'anar a la línia d'ordres del terminal i executar el següent :


Primer aturarem el servidor LDAP amb :

$ sudo /etc/init.d/slapd stop


Per a comprovar que està aturat podem executar :

$ ps aux | grep slapd
  • Surtida de la comanda anterior amb el servidor LDAP encés i apagat:
[email protected]:~$ ps aux | grep slapd
 openldap  5616  0.0  0.8  29872  4392 ?        Ssl  20:59   0:00 /usr/sbin/slapd -h ldap:/// ldapi:/// -g openldap -u openldap -F /etc/ldap/slapd.d
 1000      5628  0.0  0.1   4384   832 pts/3    S+   21:00   0:00 grep --color=auto slapd

[email protected]:~$ sudo /etc/init.d/slapd stop
 * Stopping OpenLDAP slapd                                                                                                                   [ OK ] 

[email protected]:~$ ps aux | grep slapd
 1000      5645  0.0  0.1   4384   832 pts/3    S+   21:01   0:00 grep --color=auto slapd


Ens baixem la base de dades de mostra:

$ wget http://acacha.org/mediawiki/upload/3/3a/Ldap_demo.tar.gz


I descomprimim:

$ tar -xzvf Ldap_demo.tar.gz


Llavors ja podrem passar a restaurar o importar la base de dades amb:

$ sudo slapadd -c -l informàtica.ldif


I per últim tornarem a arrancar el servidor LDAP :

$ sudo /etc/init.d/slapd start


A l'Apache Directory Studio hauria d'aparèixer el següent :

Bdl ldap demo inf.jpg

Configuració de l'aplicació webfaltes

Configuració de l'accés a Mysql. webfaltes_con.php

Cal modificar el fitxer:

$ sudo nano /etc/webfaltes/webfaltes_mysql_con.php

I dins de aquest arxiu hi ha això, on haurem de canviar les dades:

<?php
$MM_ConTut_HOSTNAME = "Aquí anirà el nom de la màquina o la Ip del servidor"; 
$MM_ConTut_DBTYPE   = "El tipus de la base de dades";     // Triarem MySQL
$MM_ConTut_DATABASE = "Nom de la base de dades";   // Suposadament es diu webfaltes
$MM_ConTut_USERNAME = "posa_aqui_el_teu_usuari";      // Usuari per accedir a la BD
$MM_ConTut_PASSWORD = "posa_aqui_el_teu_password";    // Contrasenya per accés a la BD      
$QUB_Caching = false;


$ConTut = &ADONewConnection($MM_ConTut_DBTYPE);

// Petits ajustos per connectar-nos a Acces o ODBC /IBASE / i altres.
if($MM_ConTut_DBTYPE == "access" || $MM_ConTut_DBTYPE == "odbc"){
        $ConTut->Connect($MM_ConTut_DATABASE, $MM_ConTut_USERNAME,
        $MM_ConTut_PASSWORD);        
} else if($MM_ConTut_DBTYPE == "ibase") {                
        $ConTut->Connect($MM_ConTut_HOSTNAME.":".$MM_ConTut_DATABASE,                
        $MM_ConTut_USERNAME,$MM_ConTut_PASSWORD);                        
} else {                                
        $ConTut->Connect($MM_ConTut_HOSTNAME,$MM_ConTut_USERNAME,                                
        $MM_ConTut_PASSWORD,$MM_ConTut_DATABASE);                                      
}                                              
?>

Per exemple:

<?php
$MM_ConTut_HOSTNAME = "localhost"; // Nom de la màquina o IP servidor
$MM_ConTut_DBTYPE   = "mysql";     // Tipus de base de dades
$MM_ConTut_DATABASE = "webfaltes";   // Nom de la base de dades
$MM_ConTut_USERNAME = "root";      // Usuari per accedir a la BD
$MM_ConTut_PASSWORD = "1234";    // Contrasenya per accés a la BD      
$QUB_Caching = false;


$ConTut = &ADONewConnection($MM_ConTut_DBTYPE);

// Petits ajustos per connectar-nos a Acces o ODBC /IBASE / i altres.
if($MM_ConTut_DBTYPE == "access" || $MM_ConTut_DBTYPE == "odbc"){
        $ConTut->Connect($MM_ConTut_DATABASE, $MM_ConTut_USERNAME,
        $MM_ConTut_PASSWORD);        
} else if($MM_ConTut_DBTYPE == "ibase") {                
        $ConTut->Connect($MM_ConTut_HOSTNAME.":".$MM_ConTut_DATABASE,                
        $MM_ConTut_USERNAME,$MM_ConTut_PASSWORD);                        
} else {                                
        $ConTut->Connect($MM_ConTut_HOSTNAME,$MM_ConTut_USERNAME,                                
        $MM_ConTut_PASSWORD,$MM_ConTut_DATABASE);                                      
} 

Configuració de l'accés a Ldap. webfaltes_ldap_con.php

Cal modificar el fitxer:

$ sudo nano /etc/webfaltes/webfaltes_ldap_con.php


I dins d'aquest arxiu hi ha això, on haurem de canviar les dades:

<?php
define("_LDAP_SERVER", "Aquí anirà el nom de la màquina o la Ip del servidor");
define("_LDAP_PORT", NULL);
define("_LDAP_USER", "Usuari del ldap(El cn)");
define("_LDAP_PASSWORD", "Contrasenya del ldap");
define("_LDAP_GROUP", "physicaldeliveryofficename");
define("_LDAP_USER_ID", "employeenumber");
define("_LDAP_STUDENT_BASE_DN", "ou=Alumnes,ou=All,dc=iesebre,dc=com");
define("_LDAP_TEACHER_BASE_DN", "ou=Profes,ou=All,dc=iesebre,dc=com");
?>


Per exemple:

<?php
define("_LDAP_SERVER", "localhost");
define("_LDAP_PORT", NULL);
define("_LDAP_USER", "cn=webfaltes,ou=people,ou=acls,dc=iesebre,dc=com");
define("_LDAP_PASSWORD", "1234");
define("_LDAP_GROUP", "physicaldeliveryofficename");
define("_LDAP_USER_ID", "employeenumber");
define("_LDAP_STUDENT_BASE_DN", "ou=Alumnes,ou=All,dc=iesebre,dc=com");
define("_LDAP_TEACHER_BASE_DN", "ou=Profes,ou=All,dc=iesebre,dc=com");
?>


Configuració d'Smarty

Per tal que funcioni ens hem d'assegurar que existeixin els següents directoris d'Smarty:

$ sudo mkdir /var/spool/webfaltes

A continuació hem de donar les permisos correctes a les carpetes. Bàsicament el que es fa és fer que algunes de les carpetes sigui propietat de l'usuari que executa el servidor web (suposem que és tracta de l'usuari www-data - usuari típic en distribucions Linux de la família Debian amb servidors Apache -):

$ sudo chown www-data:www-data /var/spool/webfaltes
$ sudo chmod 775 /var/spool/webfaltes

Possible error

A continuació si anem a la url: http://localhost/webfaltes ens surt el següent error:

Warning: require_once(/usr/share/gosa/include/utils/class_msgPool.inc): failed to open stream: No such file or directory in /usr/share/webfaltes/setup/functions.inc on line 159 Fatal error: require_once(): Failed opening required '/usr/share/gosa/include/utils/class_msgPool.inc' (include_path='.:/usr/share/webfaltes/include:/usr/share/webfaltes/include/utils/excel:/usr/share/php') in /usr/share/webfaltes/setup/functions.inc on line 159 

Per solucionar el problema crearem el següent fitxer buit:

$ sudo touch /etc/webfaltes/webfaltes.conf

Fitxer de configuració general. config.inc.php

TODO

Configuració del període acadèmic

Instal·lar dependències

$ sudo apt-get install imagemagick php5-ldap libphp-adodb smarty smarty-gettext php-gettext libphp-phpmailer php-fpdf

NOTA: També podeu utilitzar la versió 3 d'smarty: $sudo apt-get install smarty3 smarty3-gettext. Smarty3 només està disponible als repositoris de Gosa o a partir de la versió 11.04 d'Ubuntu.

  • imagemagick: L'aplicació webfaltes utilitzar l'ordre convert per transformar les imatges. Bàsicament s'utilitza per tal d'eliminar el canal alfa de les imatges PNG ja que la llibreria FPDF no suporta aquest canal per a aquest format d'imatges.
  • php5-ldap: L'aplicació treballa amb bases de dades Ldap i necessita la llibreria de PHP per a Ldap. Consulteu PHP i Ldap.
  • libphp-adodb: Llibreria de PHP per a adodb, serveix per a fer les connexions a la base de dades MySQL.
  • smarty: llibreria de PHP per treballar amb plantilles i poder així separar el codi de la presentació.
  • smarty-gettext: TODO. Cal afegir-lo a la taula de requeriments
  • php-gettext: TODO. Cal afegir-lo a la taula de requeriments
  • libphp-phpmailer: TODO. Cal afegir-lo a la taula de requeriments. NOTA: Pendent d'activar
  • php-fpdf: llibreria que permet crear documents PDF de forma dinàmica amb PHP.

Preparació de l'entorn de desenvolupament

  • És necessari tindre una màquina d'Ubuntu Desktop instal·lada.
  • És necessari openjdk per a fer funcionar l'entorn de desenvolupament eclipse i el ADS ( Apache Directory Studio ).
  $ sudo apt-get install openjdk-6-jre openjdk-6-jdk


Instal·lar el LAMP Server

Configurar el servidor Web Apache

Instal·lació de LDAP

Configuració de MySQL

Instal·lació de la Base de dades de demostració

Instal·lar dependències

Instal·lació de PHPMyAdmin

Per a instal·lar el phpmyadmin executarem la següent comanda:

$ sudo apt-get install phpmyadmin

Instal·lar ADS ( Apache Directory Estudio )

Primer ens baixem el paquet:

$ sudo wget http://apache.rediris.es//directory/studble/1.5.3.v20100330/ApacheDirectoryStudio-linux-x86-1.5.3.v20100330.tar.gz


Tot seguit el descomprimim:

$ sudo  tar -xzvf ApacheDirectoryStudio-linux-x86-1.5.3.v20100330.tar.gz


I li donem permisos d'execució:

$ sudo  chmod +x -R ApacheDirectoryStudio-linux-x86-1.5.3.v20100330


Per a iniciar-lo realitzem:

ApacheDirectoryStudio-linux-x86-1.5.3.v20100330/ApacheDirectoryStudio

o

./ApacheDirectoryStudio

Instal·lació d'Eclipse

Instal·lem el paquet per a l'eclipse:

$ sudo apt-get install eclipse

Instal·lació del plugin per a PHP

Primer de tot iniciarem l'eclipse.


Marcgrau-eclipse1.png

Un cop iniciat l'eclipse, anirem al menú "Help" > "Install new software".


Marcgrau-eclipse2.png

En el menú d'instal·lació de software nou, clicarem en el triangle invers per a mostrar el menú desplegable i seleccionarem l'opció "Indigo Update Site".


Marcgrau-eclipse3.png

En la casella inferior del menú desplegable escriurem el text "php" per a cercar el plugin per a desenvolupar en PHP.

Un cop ens el mostri, seleccionarem la primera casella i premerem el botó "Next".


Marcgrau-eclipse4.png

Premerem un altre cop el botó "Next".


Marcgrau-eclipse5.png

Acceptarem els termes de la llicència i premerem el botó "Finish".


Marcgrau-eclipse6.png

Per acabar, premerem en el botó "Restart Now" per aplicar els canvis.

Instal·lació del plugin subclipse

Marcgrau-eclipse1.png

Un cop iniciat l'eclipse, anirem al menú "Help" > "Install new software".


Marcgrau-eclipse7.png

Premem el botó "Add...", li donem un nom al plugin que ens anem a baixar i indiquem la següent URL: "http://subclipse.tigris.org/update_1.8.x" .


Marcgrau-eclipse8.png

Seleccionem totes les caselles i premem en el botó "Next" .


Marcgrau-eclipse9.png

Premerem un altre cop el botó "Next".


Marcgrau-eclipse10.png

Acceptarem els termes de la llicència i premerem el botó "Finish".


Marcgrau-eclipse6.png

Per acabar, premerem en el botó "Restart Now" per aplicar els canvis.


Obtenir l'aplicació amb eclipse + subclipse

Marcgrau-subclipse1.png

Primer de tot, anirem al menú "Window" > "Open perspective" > "Other" .


Marcgrau-subclipse2.png

Seleccionarem "SVN Repository Exploring" i premerem en el botó OK.


Marcgrau-subclipse3.png

Farem un clic dret en el espai buit del "SVN Repository Exploring" i seleccionarem el menú "New" > "Repository Location ..." .


Marcgrau-subclipse4.png

Afegirem la URL: http://www.iesebre.com/subversion/projectes/webfaltes/trunk/ i premerem en el botó "Finish" .


Marcgrau-subclipse5.png

Ens tindrà que mostrar per pantalla una estructura de fitxers com la que és mostra en la imatge.


Marcgrau-subclipse6.png

Una vegada tenim el repositori hem de baixar-nos una còpia en local, aquesta acció s'anomena checkout. Per fer-la hem de fer botó dret del ratolí a la URL i seleccionar el menú Checkout.


Marcgrau-subclipse7.png

En aquesta finestra que se mostra per pantalla, marcarem la casella que diu: "Check out as a project in the workspace"


Marcgrau-subclipse8.png

En la imatge podem observar com se realitza la còpia en local.

Problema en les llibreries de Java en Eclipse

En Ubuntu, les llibreries java s'instal·len en una ubicació estàndard.

El problema que ens dona és el següent, al connectar-nos a un SVN remot:

Failed to load JavaHL Library.
These are the errors that were encountered:
no libsvnjavahl-1 in java.library.path
no svnjavahl-1 in java.library.path
no svnjavahl in java.library.path
java.library.path = /usr/lib/jvm/java-6-openjdk-i386/jre/lib/i386/client:/usr/lib/jvm/java-6-openjdk-i386/jre/lib/i386::/usr/java/packages/lib/i386:/usr/lib/i386-linux-gnu/jni:/lib/i386-linux-gnu:/usr/lib/i386-linux-gnu:/usr/lib/jni:/lib:/usr/lib


El problema que causa, és que al baixar-nos el projecte remot, no crea una estructura de directoris SVN.


Per a solucionar-lo tenim varies opcions, com canviar la ruta de aquestes llibreries java en el fitxer /etc/eclipse.ini o copiar les llibreries al directori estàndard.


Encara que solucionem aquest problema, llavors ens dirà que la llibreria està obsoleta i que necessitem una versió 1.7 o superior, quan en la informació de la instal·lació de l'eclipse ens diu que tenim la versió 1.7.

Solució del problema en les llibreries de Java en Eclipse

La solució fàcil a sigut trobada en el següent perfil de Google+.

Consisteix en seguir els següents pasos d'una instal·lació alternativa del subversion:

$ sudo apt-get install libsvn-java
$ sudo apt-add-repository ppa:dominik-stadler/subversion-1.7
$ sudo apt-get update
$ sudo apt-get upgrade 
$ sudo apt-get install subversion

Instal·lació de l'aplicació utilitzant Makefile

Suposem que hem seguit les passes per tal d'obtenir el codi font de l'aplicació webfaltes a partir del subversion i que ho hem fet utilitzant Eclipse i el plugin d'Eclipse Subclipse (suposem que hem baixat el trunk de l'aplicació) . Suposem a més que l'entorn de treball (workspace) el tenim a la nostre HOME, per exemple:

/home/webfaltes/workspace/trunk

Aleshores per instal·lar l'aplicació a la carpeta que pertoca segons l'estàndard FHS i per tal de poder provar-la només ens cal seguir els següents passos:


Instal·lació del subversion

$ cd /home/webfaltes/workspace/trunk
$ sudo make install

Això ens instal·larà l'aplicació a /usr/share/webfaltes i també configurarà l'Apache si encara no ho havíem fet.

Per últim tindrem de crear el fitxer /etc/webfaltes/webfaltes.conf buit:

sudo touch /etc/webfaltes/webfaltes.conf

Fitxers modificats

Tots els fitxers amb les seves modificacions

Taula estat_alumne

Podeu crear la taula utilitzant aquesta consulta.

CREATE TABLE IF NOT EXISTS `estat_alumne` (
  `codi_estat` int(10) NOT NULL AUTO_INCREMENT,
  `codi_alumne` varchar(11) COLLATE utf8_unicode_ci NOT NULL,
  `codi_professor` varchar(3) COLLATE utf8_unicode_ci NOT NULL,
  `codi_assignatura` varchar(11) COLLATE utf8_unicode_ci NOT NULL,
  `estat` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`codi_estat`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=45 ;

sql_querys_inc.php

Dades afegides al fitxer "sql_querys_inc.php":

/**
 * 
 * @var array
 * @see insereix_est.php
 * Consulta de selecció dels alumnes corresponents a l'assignatura per 
 * a l'estat dels alumnes
 * @author Marc Grau Benaiges
 */
$RSRC['CONSULTA_ESTAT'] = <<<EOF
SELECT * 
FROM estat_alumne
WHERE codi_estat = '{$VALS['codi_estat']}' 
EOF;


/**
 * 
 * @var array
 * @see insereix_est.php
 * Consulta d'inserció de les dades dels alumnes corresponents a l'assignatura per 
 * a l'estat dels alumnes
 * @author Marc Grau Benaiges
 */
$RSRC['INSEREIX_ESTAT'] = <<<EOF
INSERT INTO estat_alumne (
	codi_estat, codi_alumne, codi_professor, codi_assignatura, estat
	) VALUES (
		NULL,
		'{$VALS['codi_alumne']}',
		'{$VALS['codi_professor']}',
		'{$VALS['codi_assignatura']}',
		'{$VALS['estat']}'
	);
EOF;


/**
 * 
 * @var array
 * @see insereix_est.php
 * Consulta de actualització dels alumnes corresponents a l'assignatura per 
 * a l'estat dels alumnes
 * @author Marc Grau Benaiges
 */
$RSRC['MODIFICA_ESTAT'] = <<<EOF
UPDATE estat_alumne
SET
	estat='{$VALS['estat']}'
WHERE
	codi_estat='{$VALS['codi_estat']}';
EOF;


/**
 * consulta SQL per a consultar l'estat d'un alumne
 * @var array
 * @author Marc Grau Benaiges
 */
$RSRC['consulta_estat2'] = <<<EOF
	SELECT DISTINCT estat_alumne.codi_alumne, estat_alumne.estat, estat_alumne.codi_estat
	FROM classe INNER JOIN (estat_alumne)
	ON estat_alumne.codi_assignatura = classe.codi_assignatura
	WHERE classe.codi_professor = '{$VALS['teacher_code']}'
	AND estat_alumne.codi_alumne = '{$VALS['student_code']}';
EOF;

insereix_est.php

<?php
/*
 * webfaltes - https://sourceforge.net/projects/webfaltes/
 * Copyright (c) 2010, Sergi Tur Badenas _Carles Añó
 * Coautors: Ester Almela Sánchez, Marc Grau Benaiges
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 * 
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 * http://www.fsf.org/licensing/licenses/lgpl.txt
 * $Id$
 */

// Iniciem (recuperem) la sessió (cal posar-ho al capdamunt de cada script)	
session_start();
// Incloem els fitxers necessaris: ADODB, seguretat, connexió, configuració i funcions	
include_once("config.inc.php");	
include_once("seguretat.inc.php");

$utils = new utils();

$RSRC = array();
$VALS = array();

//Recuperem variables de sessió i les simplifiquem per a més comoditat	
$usuari = $_SESSION['S_usuari'];
$codi_estat = $_GET['codi_estat'];
$codi_alumne = $_GET['codi_alumne'];
$codi_professor = $_SESSION['codi_professor'];	
echo $codi_alumne;
$codi_assignatura = $_GET['codi_assignatura'];
//echo $codi_assignatura;
$estat = $_GET['estat'];

//echo $estat;


  $VALS['codi_estat']= $codi_estat;
  
  $utils->get_global_resources($RSRC, "db/sql_querys_inc.php", $VALS);
  $utils->p_dbg($RSRC, "Prova log");				
  

  // Execució de la consulta. Si hi ha error, es mostra missatge
  $result = $ConTut->Execute($RSRC['CONSULTA_ESTAT']) or die($ConTut->ErrorMsg());
  if (!$result->EOF)
  { 		
    $codi_estat =  $result->Fields('codi_estat');
  }
  
  $result->Close();
  
  
  // Si està buit, inserim una nova entrada
  if ($codi_estat == "")
  {
  	
		$VALS['codi_alumne']= $codi_alumne;
		$VALS['codi_professor']= $codi_professor;
		$VALS['codi_assignatura']= $codi_assignatura;
		$VALS['estat']=$estat;
			
	    $utils->get_global_resources($RSRC, "db/sql_querys_inc.php", $VALS);
		$utils->p_dbg($RSRC, "Prova log");
		
		$sql2=$RSRC['INSEREIX_ESTAT'];
  }	

  // Si existeix, l'actualitzem
  else
  {
		$VALS['codi_estat']= $codi_estat;
		$VALS['estat']=$estat;
		
		$utils->get_global_resources($RSRC, "db/sql_querys_inc.php", $VALS);
		$utils->p_dbg($RSRC, "Prova log");
		
		$sql2=$RSRC['MODIFICA_ESTAT'];
  }
// Execució de la consulta. Si hi ha error, es mostra missatge	
//Aquest possible error s'ha de consultar en logs/php_error.log		

echo "\n";
//echo $sql2;
$result2 = $ConTut->Execute($sql2) or die($ConTut->ErrorMsg());	
$result2->Close();	
//$sql3 .= "COMMIT" 	
//$result3 = $ConTut->Execute($sql3) or die($ConTut->ErrorMsg());
?>


selecalum.php

<?php
/*
 * webfaltes - https://sourceforge.net/projects/webfaltes/
 * Copyright (c) 2010, Sergi Tur Badenas _Carles Añó
 * Coautors: Miquel Àngel Sebastià López
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 * 
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 * http://www.fsf.org/licensing/licenses/lgpl.txt
 * $Id: selecalum.php 826 2010-05-24 22:02:21Z joseprmz $
 */

/**
 * @author Carles Añó, Miquel Àngel Sebastià López, Marc Grau Benaiges
 * @name selecalum.php
 * @desc Check Attendance
 */


// Session managment
session_start();

// Includes
include_once("config.inc.php");
include_once("seguretat.inc.php");
	

//We load here common header application
require_once _INCLUDES.'common-header.php';


$utils = new utils();

$RSRC = array();
$VALS = array();

// Agafem la variable booleana passada per la funcio ajax "recargar"
// Identifica si el php està mostrant els alumnes ocults o no
$boolean=$_POST['variable'];

//Obtain session variables
$teacher_code = $_SESSION['codi_professor'];
$teacher_name = $_SESSION['nom_professor'];
$teacher_surname = $_SESSION['cognom1_professor'];
$group_code = $_GET['codi_grup'];
$roles = $_SESSION['roles'];

echo $roles;

$role_sms=0;
$role_mail=0;

$aux=split(",",$roles);
//print_r($aux);


      for($i=0;$i<count($aux);$i++)
      {
      	if($aux[$i]=="SMS")
		{
			$role_sms=1;
		}
		if($aux[$i]=="MAIL")
		{
			$role_mail=1;
		}
      }


$j=0;
$k=1;
$students=array();
$students_names=array();
$students_codes=array();
$students_jpegPhoto=array();
$students_dni=array();

$dngrup = cercaGrup($group_code);

//echo "dngroup: $dngrup\n";

$ldapconfig['host'] = _LDAP_SERVER;
#Només cal indicar el port si es diferent del port per defecte
$ldapconfig['port'] = _LDAP_PORT;
$ldapconfig['basedn'] = $dngrup;
		
$ds=ldap_connect($ldapconfig['host'], $ldapconfig['port']);
		
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
		
$password=_LDAP_PASSWORD;
		#$dn="cn=admin,".$ldapconfig['basedn'];
$dn=_LDAP_USER;
		
	
if ($bind=ldap_bind($ds, $dn, $password)) {
	if ($bind=ldap_bind($ds)) {
		
		$filter = "(objectClass=inetOrgPerson)";
		
//		echo "<br/>basedn: ". $ldapconfig['basedn'] ."<br/><br/>";		
//		echo "filter: $filter </br><br/>";
		
		if (!([email protected]_search($ds, $ldapconfig['basedn'], $filter))) {
		    echo("Unable to search ldap server<br>");
		    echo("msg:'".ldap_error($ds)."'</br>");#check the message again
		} else {
		    $number_returned = ldap_count_entries($ds,$search);
		    ldap_sort($ds, $search, "sn"); 
		    $info = ldap_get_entries($ds, $search);
		    $entry = ldap_first_entry($ds, $search);
		    for ($i=0; $i<$info["count"];$i++) {
		      	$students[]=$k;
				$students_names[$i]=$info[$j]['cn'][0];
				$students_codes[$i]=$info[$j][_LDAP_USER_ID][0];
				//$students_jpegPhoto[$i]=$info[$j]['jpegphoto'][0];
				//echo $info[$j]['jpegphoto'][0];
				
				//$entry = $info[$i];
				$jpeg_data = ldap_get_values_len($ds, $entry, "jpegphoto");
				//print_r($jpeg_data);
				/*$photo_filename="/tmp/".$students_codes[$i].".png";
				$outphoto = fopen ($photo_filename,"wb");*/
				$jpeg_filename="/tmp/".$students_codes[$i].".png";
				$jpeg_file[$i]=$students_codes[$i].".png";
		    for( $l=0; $l<$jpeg_data['count']; $l++ ) {
					$outjpeg = fopen($jpeg_filename, "wb");
					fwrite($outjpeg, $jpeg_data[$l]);
					fclose ($outjpeg);
					$jpeg_data_size = filesize( $jpeg_filename );
					if( $jpeg_data_size < 6 ) {
					echo "jpegPhoto contains errors<br />";
					echo '<a href="javascript:deleteJpegPhoto();" style="color:red; font-size: 75%">Delete Photo</a>';
					continue;
				}
		    }
				
				
				/*fwrite($outphoto,filesize($jpeg_data[0]));
				fclose ($outphoto);*/
				
				$j=$j+1;
				$entry = ldap_next_entry($ds, $entry);
     		}
	}	    
	} else {
		echo("Unable to bind anonymously<br>");
		echo("msg:".ldap_error($ds)."<br>");
	}
} else {
	echo("Unable to bind to server.</br>");
		
	echo("msg:'".ldap_error($ds)."'</br>");#check if the message isn't: Can't contact LDAP server :)
		  #if it say something about a cn or user then you are trying with the wrong $dn pattern i found this by looking at OpenLDAP source code :)
		  #we can figure out the right pattern by searching the user tree
		  #remember to turn on the anonymous search on the ldap server		  
}
		// Usuari i contrasenya vàlids (Control seguretat 1)
ldap_close($ds);
//$nom_alumne=$aux[1]." ".$aux[0];

//Obtain get variables
$day_code = $_GET['codi_dia'];
$hour_code = $_GET['codi_hora'];
$group_code = $_GET['codi_grup'];
$subject_code = $_GET['codi_ass'];
$time_interval= $_GET['time_interval'];
$date=date('Y-m-d', $_SESSION['int_data']);

$date1=date('d-m-Y', $_SESSION['int_data']);

$subject_code_backup = $_GET['codi_ass'];

//Obtain student data from selected subject at selected day of week, hour & date


//print_r ($students_codes);
/*foreach ($students_codes as $student_code)
{
	$VALS['student_code']=$students_codes;
	//print_r ($VALS['student_code']);
	
	$utils->get_global_resources($RSRC, "db/sql_querys_inc.php", $VALS);
	$utils->p_dbg($RSRC, "Prova log");
	// Execució de la consulta. Si hi ha error, es mostra missatge
	
	$result1 = $ConTut->Execute($RSRC['CONSULTA_ALUMNES']) or die($ConTut->ErrorMsg());
	//echo $RSRC['CONSULTA_ALUMNES'];
	$estat=$result1->fields['estat'];
	
	if ($estat != '1')
	{
		
		/*unset($students_names);
		unset($students_codes);
		unset($jpeg_data);
		
		$number_returned=$number_returned-1;
	}
	
}*/

$results=array();
$k=1;
for($l=0;$l<$number_returned;$l++) {

   	$sc=$students_codes[$l];
	$tc=$_SESSION['S_codi_prof'];
	$VALS['group_code'] = $group_code;
	$VALS['int_data_inc'] = $date;
	$VALS['hour_code'] = $hour_code;
	$VALS['day_code'] = $day_code;
	$VALS['subject_code'] = $subject_code;
	$VALS['teacher_code'] = $tc;
	$VALS['student_code']=$sc;
	

	$utils->get_global_resources($RSRC, "db/sql_querys_inc.php", $VALS);
	$utils->p_dbg($RSRC, "Prova log");
	// Execució de la consulta. Si hi ha error, es mostra missatge
	$result = $ConTut->Execute($RSRC['consulta_incidencia']) or die($ConTut->ErrorMsg());
	//Reasons Vector initialization
	$incident_code="";
	$reason="";
	if (!$result->EOF){
		$incident_code  = $result->Fields('codi_incidencia');
		$reason = $result->Fields('motiu_incidencia');
		$result->Close();
	}
	settype($reason, "integer");
	for ($i=0;$i<=5;$i++) {
		$selected[$i]="";
	}
	
	//Per que quant es carregi la web per passar llista surti si ja ha estat enviat el mail, el sms o tots dos
	/*if($mail_enviat==1)
	{
		$selec=2;
	}
	if($sms_enviat==1)
	{
		$selec=1;
	}
	if($sms_enviat==1 and $mail_enviat==1)
	{
		$selec=3;
	}
	if($sms_enviat==0 and $mail_enviat==0)
	{
		$selec=0;
	}
	*/
	/*settype($selec, "integer");
	for ($a=0;$a<=3;$a++) {
		$selected_mail[$a]="";
	}*/
	// Reason codes:
	// 0 -> NULL, 1 -> f, 2 -> fj, 3 -> r, 4 -> rj, 5 -> e
	if ($reason=='') {
		$i=0;
	}else {
		$i = $reason;
	}
	/*if ($selec=='') {
		$a=0;
	}else {
		$a = $selec;
	}*/

	$selected[$i] = "selected";
	/*$selected_mail[$a] = "selected";*/
	
	
	$url1 =  "insereix_inc.php?codi_incidencia=".$incident_code;
	$url1 .= "&codi_alumne=".$students_codes[$l];
	$url1 .= "&codi_dia=".$day_code;
	$url1 .= "&codi_hora=".$hour_code;
	$url1 .= "&codi_assignatura=".$subject_code;
	$url1 .= "&data_incidencia=".$date;
	$url1 .= "&motiu_incidencia=";
/*	$url1_mail =  "./select_option_avis_pares.php?codi_incidencia=".$incident_code;
	$url1_mail .= "&codi_alumne=".$student_code;
	$url1_mail .= "&codi_dia=".$day_code;
	$url1_mail .= "&codi_hora=".$hour_code;
	$url1_mail .= "&codi_assignatura=".$subject_code;
	$url1_mail .= "&data_incidencia=".$date;
	$url1_mail .= "&opcio_select=";*/
	
	
	
	//Here we include selected reason
	$url2 = "&justificant=";
	if (isset($justificant)) {
		$url2 .= $justificant;
	} else {
		$url2 .= "";
	}
	$url2 .= "&observacions=";
	if (isset($observacions)) {
		$url2 .= $observacions;
	} else {
		$url2 .= "";
	}

	$url2 .= "&nom_professor=".$teacher_name;
	$url2 .= "&cognom1_professor=". $teacher_surname;
	$url2 .= "&codi_professor=". $teacher_code;
	
	
	/*
	 * @desc INICI DEL CODI RELACIONAT EN L'ESTAT DEL ALUMNE 
	 * @autor Marc Grau Benaiges
	 */
	
	$utils->get_global_resources($RSRC, "db/sql_querys_inc.php", $VALS);
	$utils->p_dbg($RSRC, "Prova log");
	
	// Execució de la consulta. Si hi ha error, es mostra missatge
	$result_state = $ConTut->Execute($RSRC['consulta_estat2']) or die($ConTut->ErrorMsg());
	
	$state="";
	$state_code="";
	if (!$result_state->EOF){
		$state_code  = $result_state->Fields('codi_estat');
		$state  = $result_state->Fields('estat');
		$result_state->Close();
	}
	
	settype($state, "integer");
	for ($i=0;$i<=5;$i++) {
		$selected_state[$i]="";
	}
	
	if ($state=='') {
		$i=0;
	}else {
		$i = $state;
	}
	
	$selected_state[$i] = "selected";
	
	// Passem variables per la URL
	$url3 = "insereix_est.php?estat=";
	
	$url4 = "&codi_alumne=".$students_codes[$l];
	$url4 .= "&codi_assignatura=".$subject_code;
	$url4 .= "&codi_professor=".$teacher_code;
	$url4 .= "&codi_estat=".$state_code;

/*
 * @desc FI DEL CODI RELACIONAT EN L'ESTAT DEL ALUMNE
 * 
*/

	//CALCULAR L'EDAT DE CADA ALUMNE
/*	if($data_neixement)
	{
		//fecha actual
		$dia=date(j);
		$mes=date(n);
		$ano=date(Y);
	 
		//fecha de nacimiento
		$dianaz=strftime("%d",strtotime("$data_neixement"));
		$mesnaz=strftime("%m",strtotime("$data_neixement"));
		$anonaz=strftime("%Y",strtotime("$data_neixement"));
	
	 
	 
		//si el mes es el mismo pero el día inferior aun no ha cumplido años, le quitaremos un año al actual
		 
		if (($mesnaz == $mes) && ($dianaz > $dia)) {
		$ano=($ano-1); }
		 
		 
		//si el mes es superior al actual tampoco habrá cumplido años, por eso le quitamos un año al actual
		 
		if ($mesnaz > $mes) {
		$ano=($ano-1);}
		 
		 
		//ya no habría mas condiciones, ahora simplemente restamos los años y mostramos el resultado como su edad
		 
		$edat=($ano-$anonaz);
		 
		//print $edat;
	}
	else
	{
		$edat=0;
	}
	
	//CONSULTA QUE MIRA SI ALGUN DELS PARES VOL NOTIFICACIO
	$VALS['codi_alumne']= $student_code;
	$utils->p_dbg($RSRC, "num_pares_vol_notificacio");
	$utils->get_global_resources($RSRC, "db/sql_querys_inc.php", $VALS);
	$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
	$result_noti = $ConTut->Execute($RSRC['num_pares_vol_notificacio']) or die($ConTut->ErrorMsg());

	$pares_a_notificar=$result_noti->fields['count( pare.codi_pare )'];
*/	
	//$url3 = "insereix_est.php?estat=";
	//$url4 = "&codi_assignatura=".$subject_code;
	//$url4 .="&codi_alumne=".$students_codes[$l];


	if(!$state > 0 || $boolean=="1"){
		

	$results[]=array('url1' => $url1,
                     'url2' => $url2,
					 'url3' => $url3,
					 'url4' => $url4,
	                 'selected' => $selected,
	                 'i' => $k,
					 'selected_state' => $selected_state,
                     'student_name' => $students_names[$l],
	                 'student_code' => $students_codes[$l],
					 'student_jpegPhotoName' => $jpeg_file[$l],
					 'boolean' => $boolean);

					
//	$results2[]=array('url1' => $url1,
//                     'url2' => $url2,
//	                 'selected' => $selected,
//	                 'i' => $k,
//                    'student_name' => $students_names[$l],
//	                 'student_code' => $students_codes[$l],
//					 'student_jpegPhotoName' => $jpeg_file[$l]);
//'url1_mail' => $url1_mail,
//'pares_a_notificar' => $pares_a_notificar,
//'selected_mail' => $selected_mail,	
	$k++;
	//$h++;
    $result->MoveNext();
	}
    
}

//Form returns to main page

//Impresio dels vector que contenen els alumnes i els seus codis 
//NOTA: Nomes descomentar per a debugar)
//print_r($students_names);
//print_r($students_codes);

$smarty->assign('ACTION_URL','index.php');
	
$smarty->assign('GROUP_CODE',$group_code);
$smarty->assign('SUBJECT',$subject_code_backup);
$smarty->assign('N_GROUP_STUDENTS',$number_returned);
	
$smarty->assign('SELECTED_DATE',$date1);
$smarty->assign('SELECTED_TIME_INTERVAL',$time_interval);
$smarty->assign('results', $results );
	
	
//$smarty->assign('role_sms', $role_sms );
//$smarty->assign('role_mail', $role_mail );
	
$smarty->display('selecalumn.tpl');
	
//We load here common foot application
$smarty->display('foot.tpl');

?>


selecalumn.tpl

{******************************************************************************* 
selecalumn Template 
@ author: [email protected], Marc Grau Benaiges
@ maintainer: [email protected]
Variables 
 @ ACTION_URL			  Action form URL 
 @ GROUP_CODE		      Group's name
 @ SUBJECT		      	  Subject
 @ N_GROUP_STUDENTS		  Number of students at group 
 @ SELECTED_DATE		  Selected date
 @ SELECTED_TIME_INTERVAL Selected time interval
 @ results				  Associative array with student data
  @ results.url1          First part of URL to insert incident
  @ results.url2          Second part of URL to insert incident
  @ results.selected      Array with options to select
  @ results.i             Number of student (alfabetical order)
  @ results.student_name  Students name
  @ results.student_code  Student database code 
*******************************************************************************}

<link rel="stylesheet" type="text/css" href="css/styles.css" />
<div class="contenedor_pestañes">
<div align="right"><a class="imatge" target="_blank" href="http://www.iesebre.com/webfaltes_wiki/index.php/Projectes_de_s%C3%ADntesi/sms_correus#Enviar_correus_electr.C3.B2nics_i.2Fo_sms_al_passar_llista.2A"><img src="/webfaltes/imatges/Ajuda.gif" border="0"></img></a></div>
<div align="center"><h4><a class="titol_taronja" href="reports/Llistat_alumnes_grup.php?codi_grup={$GROUP_CODE}">{t}List of all students in this group (with photo){/t}</a></h4></div>
<div align="center"><h4><a class="titol_taronja" href="reports/Llistat_alumnes_grup_sense_foto.php?codi_grup={$GROUP_CODE}">{t}List of all students in this group (without photo){/t}</a></h4></div>
<div align="center"><h4><a class="titol_taronja" href="reports/Llencol_estudiants_grup.php?codi_grup={$GROUP_CODE}">{t}Sheet of this group of students{/t}</a></h4></div>

<br></br><form name="form1" method="post" action="{$ACTION_URL}">
	 <center>   <table width="550" >
	    <thead>
		 <tr>

          <th colspan="2">{t}Check Attendance{/t}.
		   	<br>
		    {t}Group{/t}: {$GROUP_CODE} {$SUBJECT} ({$N_GROUP_STUDENTS} {t}students{/t})
		    <br>
		    {t}Date{/t}: {$SELECTED_DATE} ({$SELECTED_TIME_INTERVAL})
		  	<br><!-- Botons d'ocultar i mostrar -->
		  	<input class="button" value="Ocultar" type="button" onclick="javascript:recargar(0)">
		  	<input class="button" value="Mostrar" type="button" onclick="javascript:recargar(1)">
		 </tr>
		 </thead>
      <tbody>
		 {foreach from=$results item=i}
          <tr class="{cycle values='tr0,tr1'}">
		   <td> <label>
            <select name="tipus_incidencia" 
           onChange="javascript:ProcessXML('{$i.url1}'+this.value+'{$i.url2}')">
			               
				<option value="0" {$i.selected[0]} > </option>
				<option value="1" {$i.selected[1]} >F</option>
				<option value="2" {$i.selected[2]} >FJ</option>
				<option value="3" {$i.selected[3]} >R</option>
				<option value="4" {$i.selected[4]} >RJ</option>
				<option value="5" {$i.selected[5]} >E</option>
		    </select> {if $i.student_jpegPhotoName eq NULL}<img alt="Foto Perfil" title="Foto Perfil" src="imatges/default_small.jpg" height="32px" width="32px"></img> {else}<img alt="Foto Perfil" title="Foto Perfil" src="view_jpeg_photo.php?file={$i.student_jpegPhotoName}" height="61px" width="48px"></img>{/if} <a href="profile_student.php?codi_alumne={$i.student_code}">{$i.i}. {$i.student_name} ({$i.student_code})</a> </label>
		    </td>
		   <td> <label>
			
			<!-- Ocultar alumnes -->
			<center>
		 	<select name="estat_alumne" onchange="javascript:ProcessXML('{$i.url3}'+this.value+'{$i.url4}')">
		 		
		 		<option value="0" {$i.selected_state[0]} onclick="{if $i.boolean != 1}javascript:recargar(0){else}javascript:recargar(1){/if}">  </option>
		 		<option value="1" {$i.selected_state[1]} onclick="{if $i.boolean != 1}javascript:recargar(0){else}javascript:recargar(1){/if}"> Aprovat </option>
		 		<option value="2" {$i.selected_state[2]} onclick="{if $i.boolean != 1}javascript:recargar(0){else}javascript:recargar(1){/if}"> Falta </option>
		 		<option value="3" {$i.selected_state[3]} onclick="{if $i.boolean != 1}javascript:recargar(0){else}javascript:recargar(1){/if}"> Convalida </option>
		 		<option value="4" {$i.selected_state[4]} onclick="{if $i.boolean != 1}javascript:recargar(0){else}javascript:recargar(1){/if}"> Oculta </option>
		 	</select>
		 	</center>
		 	</label></td>
		 <!--  
		 	
		 	</td>
		   {if $role_sms eq 1 or $role_mail eq 1}
			   {if $i.pares_a_notificar != 0}
				   {if $i.edat lt 18}
				   <td align="center">
				    <select id="opt_{$i.student_code}" name="tipus_enviament" onChange="javascript:ProcessXMLmail('{$i.url1_mail}'+this.value+'{$i.url2}','opt_{$i.student_code}')">
					              
						<option value="0" {$i.selected_mail[0]}> </option>  --> 
						<!-- {if $role_sms eq 1}<option value="1" {$i.selected_mail[1]}>SMS</option>{/if} -->
						<!--  {if $role_mail eq 1}<option value="2" {$i.selected_mail[2]}>E-MAIL</option>{/if}-->
						<!-- {if $role_sms eq 1 and $role_mail eq 1}<option value="3" {$i.selected_mail[3]}>SMS/E-MAIL</option>{/if} -->
				   <!--</select>
				   </td>
				   {else}
						<td align="center"><font color="#fa6714">L'alumne és major d'edat</font></td>
				   {/if}
			   {else}
			   		<td align="center"><font color="#fa6714">Els pares no volen notificacions</font></td>
			   {/if}
		   {/if}
		  </tr>-->
		 </tr>

		 {/foreach}
		 </tbody>
		 <tfoot>
		 <tfoot>
		
		<tr>
				<th colspan="7" align="center">
				<input type="submit" name="enviat"
			value="{t}Return{/t}">
				</th>
			</tr>
		</tfoot>
		 </tfoot> 
		</table></center>
</form></div>

ajax_insert_absence.js

Dades afegides al fitxer "ajax_insert_absence.js":

function recargar(boolean){   
    /// Enviarem la variable "boolean" a un script en php amb el métode post
 if(boolean == 1){ // "1" vol dir cert
	 var variable_post="1"; 
 }else{
	 var variable_post="0";
 }
 
 // Desem en una variable la URL actual
 var url = $(location).attr('href');
 

 // Per evitar que surti primer de la cua d'events al ser cridat des de un mateix item
 // en retardem la surtida, en cas contrari, per exemple, primer s'actualitza i llavors s'executa la consulta SQL
 // Amb el firebug, he calculat que el temps segur era de 160 milisegons
 setTimeout(function() {
	 $.post(url, { variable: variable_post }, function(data){
			 // Recarguem l'element "body" 
			 $(document.body).html(data);
		 });   
}, 160);
 
     
}

styles.css

Dades afegides al fitxer "styles.css":

.button {
	float: right;
}