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)

Vegeu també gosa i:


Per a l'Institut de l'Ebre (i també el d'Amposta- --acacha 19:29, 5 feb 2011 (UTC)) he modificat el codi per tal d'adaptar gosa a les necessitats d'aquests Instituts. En aquest apartat indicarem els passos.


Alert.png Aquesta wiki forma part dels materials d'un curs
Curs: SambasobreLDAP, LinuxAdministracioAvancada
Fitxers: Sessio8.pdf
Repositori SVN: https://[email protected]/svn/iceupc/SambaSobreLDAP
Usuari: anonymous
Paraula de pas: sense paraula de pas
Autors: Sergi Tur Badenas

Contingut

Codi font de gosa

Està en un repositori Subversion

https://oss.gonicus.de/repositories/gosa/trunk/

Conceptes

Gosa ofereix tota un sèrie d'eines per facilitar la creació de nous plugins i eines relacionades. Per tal de desenvolupar aplicacions amb Gosa és important tenir clars els següents conceptes:

  • Plugin de gestió
  • Plugin normal
TODO: Fer una taula/gràfic de conceptes i relacionar-los entre si
Plugin -- (constructor genera llista)-> 1 llista
1 llista --> 1 filtre
1 llista --> n accions

Plugin

Característiques

  • Path: /usr/share/gosa/plugins
  • Path dels plugins de gestió: /usr/share/gosa/plugins/admin
  • Path dels plugins normals (addons): /usr/share/gosa/plugins/addons
  • Classe PHP:
  • Plugin normal (addon): TODO
  • Plugin de gestió: TODO
TODO: Per que existeixen altres carpetes tipus?
/usr/share/gosa/plugins
         generic  gofax  gofon personal ???

Tipus de plugins. Regular and managment plugins

D'una pregunta realitzada a les llistes:

There are plugins that are used to extend objects (like i.e. the samba
or posix Plugins extend the user objects). And there are plugins that
just show a list of objects (like the "user" plugins which lists
information). I'd call the first kind "regular" and the second
"management". Maybe they're just plugins, though ;-)

Llistes (lists)

Fitxa de Característiques:

  • Path de la classe: /usr/share/gosa/include/class_listing.inc
  • Fitxer XML de configuració : el fitxer pot tenir el nom que vulgueu. El nom es defineix al constructor del plugin de gestió que al seu torn quan crea un objecte listing al constructor de listing un dels paràmetres és el fitxer XML. Es recomano però:
  • Path: /usr/share/gosa/plugins/admin/NOMPLUGIN/
  • Nom: NOMPLUGIN.list.xml. Es carreguen amb el constructor de la classe listing
  • Plantilla Smarty: /usr/share/gosa/plugins/admin/NOMPLUGIN/NOMPLUGIN.list.tpl. Es defineix al fitxer XML de configuració
  • A les llistes se'ls hi apliquen Filtres Gosa

Les llistes tenen les següents característiques/capacitats:

  • Cada Plugin de gestió té una llista relacionada.
  • Les llistes són configurables en temps d'execució (de forma dinàmica sense haver de canviar codi) utilitzant un fitxer XML.
  • Tenen capacitat per ordenar per diferents camps
  • Es separa la presentació del codi. S'utilitzen plantilles Smarty. La plantilla es pot canviar en temps d'execució ja que s'indica quina plantilla utilitzar al fitxer XML.
  • Entre d'altres es pot configurar:
  • Els atributs a mostrar dels objectes Ldap
  • La plantilla Smarty a utilitzar
  • Es pot definir un layout amb la mida de les diferents columnes

Les llistes defineixen la pàgina principal (la que apareix al entrar) a cada plugin. Les següents captures de pantalla mostren alguns exemples de llistes:

TODO posar 3 de captures de pantalla de llistes diferents i indicar a quina objectes pertanyen

Les línies claus de cada plugin a on es crea la llista i se li aplica un filtre:

 // Build headpage
       $headpage = new listing(get_template_path("sudo-list.xml", true));
       $headpage->setFilter($filter);
Plantilla genèrica per a llistes

Com podeu veure a la plantilla es defineix la capçalera de la llista i s'insereix la llista en temps dinàmic (variable smarty {$LIST}). La funció execute del plugin ha de crear la llista de forma dinàmica i passar-la a Smarty.

$ cat NOMPLUGIN-list.tpl
<div id="mainlist">

  <div class="mainlist-header">
   <p>{$HEADLINE} {$SIZELIMIT}</p>
   <div class="mainlist-nav">
    <table summary="{$HEADLINE}">
     <tr>
      <td>{$ROOT}</td>
      <td>{$BACK}</td>
      <td>{$HOME}</td>
      <td>{$RELOAD}</td>
      <td class="left-border">{t}Base{/t} {$BASE}</td>
      <td class="left-border">{$ACTIONS}</td>
      <td class="left-border">{$FILTER}</td>
     </tr>
    </table>
   </div>
  </div>

  {$LIST}
</div>

<input type="hidden" name="ignore">


Fitxer XML de configuració dinàmica. NOMPLUGIN.list.xml

Vegem un exemple:

<list>
  <definition>
    <departmentBrowser>true</departmentBrowser>
    <departmentRootVisible>false</departmentRootVisible>
    <baseMode>true</baseMode>
    <multiSelect>true</multiSelect>
    <template>stuff-list.tpl</template>
    <module>stuff</module>
    <label>List of stuff (prova)</label>
    <defaultSortColumn>1</defaultSortColumn>

    <objectType>
      <label>Stuff</label>
      <objectClass>stuff</objectClass>
      <category>stuff</category>
      <class>stuff</class>
      <image>plugins/sudo/images/select_sudo.png</image>
    </objectType>

  </definition>

  <table>
    <layout>|20px;c|150px|250px||170px;r|</layout>

    <department>
      <value>%{filter:objectType(dn,objectClass)}</value>
    </department>

    <department>
      <value>%{filter:departmentLink(row,dn,description)}</value>
      <span>3</span>
    </department>

    <column>
      <value>%{filter:objectType(dn,objectClass)}</value>
    </column>

    <column>
      <label>ID</label>
      <sortAttribute>stuffID</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",stuffID)}</value>
      <export>true</export>
    </column>

    <column>
      <label>Name</label>
      <sortAttribute>stuffName</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",stuffName)}</value>
      <export>true</export>
    </column>

        <column>
      <label>Description</label>
      <sortAttribute>stuffDesc</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",stuffDesc)}</value>
      <export>true</export>
    </column>

    <column>
      <label>Actions</label>
      <value>%{filter:actions(dn,row,objectClass)}</value>
    </column>

  </table>

  <actionmenu>

    <action>
     <type>sub</type>
     <image>images/lists/element.png[new]</image>
     <label>Create</label>

     <action>
      <name>new_stuff</name>
      <type>entry</type>
      <image>plugins/sudo/images/select_sudo.png</image>
      <label>Default</label>
     </action>

    </action>

    <action>
      <type>separator</type>
    </action>

    <action>
      <name>remove</name>
      <type>entry</type>
      <image>images/lists/trash.png</image>
      <label>Remove</label>
    </action>

    <action>
      <type>exporter</type>
    </action>

    <action>
      <type>separator</type>
    </action>

    <action>
      <type>copypaste</type>
    </action>

    <action>
      <type>snapshot</type>
    </action>

  </actionmenu>

  <actiontriggers snapshot="true" copypaste="true">

    <action>
      <name>cp</name>
      <type>copypaste</type>
    </action>

    <action>
      <name>edit</name>
      <type>entry</type>
      <image>images/lists/edit.png</image>
      <label>Edit stuff</label>
    </action>

    <action>
      <name>snapshot</name>
      <type>snapshot</type>
    </action>

    <action>
      <name>remove</name>
      <type>entry</type>
      <image>images/lists/trash.png</image>
      <acl>sudo/sudo[d]</acl>
      <label>Remove stuff</label>
    </action>

  </actiontriggers>

</list>

Les llistes es defineixen amb el suport de fitxers XML. Hi ha tres parts (elements XML) principals:

Definition:

  • departmentBrowser: Booleà. Es mostren els departament a la llista? Si es mostren els departaments cal que definiu les dues següents columnes:
    <department>
      <value>%{filter:objectType(dn,objectClass)}</value>
    </department>

    <department>
      <value>%{filter:departmentLink(row,dn,description)}</value>
      <span>3</span>
    </department>

NOTA: Compte amb el valor de la columna span que haurà de ser major o menor depenent del nombre de columnes que esteu mostrant a la llista

  • departmentRootVisible: Booleà. ???
  • baseMode: Booleà. ???
  • multiSelect: Booleà. Es permet seleccionar múltiples elements de la llista al mateix temps
  • baseMode: Booleà. ???
  • template: Path relatiu de la plantilla d'Smarty. El path és relatiu a la carpeta on està el fitxer XML de definició de la llista (carpeta arrel del plugin). Les plantilles han d'estar a la mateixa carpeta arrel del plugin
  • module: Mòdul/Plugin al que pertany la llista.
  • label: Descripció de la llista. Text que apareix a la capçalera de la llista.
  • defaultSortColumn: Numèric. Quina columna s'utilitza per defecte per tal d'ordenar.

Definition/objectType

  • Permet definir el tipus d'objecte Ldap
  • label:
  • objectClass: ObjectClass de l'objecte. Només es mostraran els objectes que siguin d'aquest tipus
  • category: ???????????
  • class: ???????????
  • image: És la imatge que surt al menú d'accions al intentar crear un dispositiu d'aquest tipus (TODO: Sistemes: Múltiples botons??? com?)

table

  • Permet definir el layout de la taula amb la llista de objectes a mostrar
  • layout: Permet indicar la mida de les columnes. Per exemple: |20px;c|||150px;r|
  • deparment: com mostrar els departaments????
  • column: TODO

actionmenu

  • Permet definir el que apareixerà al menú Action (Accions)

actiontriggers

  • ?????

Un exemple (la llista de dispositius del plugin devices):

 $ cat device-list.xml
<?xml version="1.0" encoding="UTF-8"?>

<list>
  <definition>
    <departmentBrowser>true</departmentBrowser>
    <departmentRootVisible>false</departmentRootVisible>
    <baseMode>true</baseMode>
    <multiSelect>true</multiSelect>
    <template>device-list.tpl</template>
    <module>devices</module>
    <label>List of devices</label>
    <defaultSortColumn>1</defaultSortColumn>

    <objectType>
      <label>Device</label>
      <objectClass>gotoDevice</objectClass>
      <category>devices</category>
      <class>deviceGeneric</class>
      <image>plugins/goto/images/select_device.png</image>
    </objectType>

  </definition>

  <table>
    <layout>|20px;c|||150px;r|</layout>

    <department>
      <value>%{filter:objectType(dn,objectClass)}</value>
    </department>

    <department>
      <value>%{filter:departmentLink(row,dn,description)}</value>
      <span>2</span>
    </department>

    <column>
      <value>%{filter:objectType(dn,objectClass)}</value>
    </column>

    <column>
      <label>Name</label>
      <sortAttribute>cn</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",cn)}</value>
      <export>true</export>
    </column>

    <column>
      <label>Description</label>
      <sortAttribute>description</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",description)}</value>
      <export>true</export>
    </column>

    <column>
      <label>Actions</label>
      <value>%{filter:actions(dn,row,objectClass)}</value>
    </column>

  </table>

  <actionmenu>

    <action>
     <type>sub</type>
     <image>images/lists/element.png[new]</image>
     <label>Create</label>

     <action>
      <name>new</name>
      <type>entry</type>
      <image>plugins/goto/images/select_device.png[new]</image>
      <label>Device</label>
     </action>
    </action>

    <action>
      <type>separator</type>
    </action>

    <action>
      <name>remove</name>
      <type>entry</type>
      <image>images/lists/trash.png</image>
      <label>Remove</label>
    </action>

    <action>
      <type>exporter</type>
    </action>

    <action>
      <type>separator</type>
    </action>

    <action>
      <type>copypaste</type>
    </action>

    <action>
      <type>snapshot</type>
    </action>

  </actionmenu>

  <actiontriggers snapshot="true" copypaste="true">

    <action>
      <name>cp</name>
      <type>copypaste</type>
    </action>

    <action>
      <name>edit</name>
      <type>entry</type>
      <image>images/lists/edit.png</image>
      <label>Edit device</label>
    </action>

    <action>
      <name>snapshot</name>
      <type>snapshot</type>
    </action>

    <action>
      <name>remove</name>
      <type>entry</type>
      <image>images/lists/trash.png</image>
      <acl>devices/deviceGeneric[d]</acl>
      <label>Remove device</label>
    </action>

  </actiontriggers>

</list>

Com podeu veure l'element arrel XML sempre és list

Es llegeix la part configurable/dinàmica d'un fitxer XML que defineix les característiques de la llista.

La classe listing carrega tot el XML a la variable xmlData. Un cop carregades totes les dades les podem utilitzar amb:

$this->xmlData['definition']['template']

Això segons el següent extracte de l'exemple anterior:

<list>
 <definition>
   ...
   <template>device-list.tpl</template>

Ha de retornar el valor:

device-list.tpl

Accions (Actions)

TODO: Fer similar a l'apartat de llistes

Fitxa de Característiques:

  • Path de la classe: /usr/share/gosa/include/class_listing.inc
  • Fitxer XML de configuració : /usr/share/gosa/plugins/admin/NOMPLUGIN/NOMPLUGIN.list.xml. Es carreguen amb el constructor de la classe listing
  • Plantilla Smarty: /usr/share/gosa/plugins/admin/NOMPLUGIN/NOMPLUGIN.list.tpl. Es defineix al fitxer XML de configuració
  • A les llistes se'ls hi apliquen Filtres Gosa

Les llistes tenen les següents característiques/capacitats:

  • Cada Plugin de gestió té una llista relacionada.
  • Les llistes són configurables en temps d'execució (de forma dinàmica sense haver de canviar codi) utilitzant un fitxer XML.
  • Tenen capacitat per ordenar per diferents camps
  • Es separa la presentació del codi. S'utilitzen plantilles Smarty. La plantilla es pot canviar en temps d'execució ja que s'indica quina plantilla utilitzar al fitxer XML.
  • Entre d'altres es pot configurar:
  • Els atributs a mostrar dels objectes Ldap
  • La plantilla Smarty a utilitzar
  • Es pot definir un layout amb la mida de les diferents columnes

Les llistes defineixen la pàgina principal (la que apareix al entrar) a cada plugin. Les següents captures de pantalla mostren alguns exemples de llistes:

TODO posar 3 de captures de pantalla de llistes diferents i indicar a quina objectes pertanyen

Les línies claus de cada plugin a on es crea la llista i se li aplica un filtre:

 // Build headpage
       $headpage = new listing(get_template_path("sudo-list.xml", true));
       $headpage->setFilter($filter);
Gestió de les accions. class_managment.inc

La funció execute de les classes managment és la funció principal encarregada de mostrar els plugins de gestió. Normalment l'execute s'executa a la classe:

main.inc

La línia clau és:

$str = $this->handleActions($this->detectPostActions());

Com podeu veure hi ha dos funcions:

detectPostActions() --> Detecta l'acció
handleActions       --> Execute l'acció

detectPostActions() gestiona les accions que s'executen per post (per exemple normalment editar un objecte). El que retorna aquesta funció és una array amb dos parts diferenciandes:

  • targets: conté el dn o dns dels objectes a modificar
  • action: l'acció a realitzar. Hi ha un vector de d'accions que relaciona noms d'accions amb funcions. Per exemple edit -> editEntry()
/*! \brief  Calls the registered method for a given action/event.
   */
  function handleActions($action)
  {
	//print_a($action);  
	// Start action  
    if(isset($this->actions[$action['action']])){
      $func = $this->actions[$action['action']];
      //echo "func:".$this->actions[$action['action']];
      if(!isset($action['targets']))$action['targets']= array(); 

      // Create statistic table entry 
      stats::log('management', $class = get_class($this), $this->getAclCategories(),  $action['action'],
              $amount = count($action['targets']), $duration = (microtime(TRUE) - $this->initTime));

      return($this->$func($action['action'],$action['targets'],$action));
    }
  }

$this->dn

set_object_info($this->dn) i get_object_info()

Aquesta funció es troba a /usr/share/gosa/include/functions.inc:

$ grep -n "set_object_info" -r /usr/share/gosa
... 
/usr/share/gosa/include/functions.inc:3343:function set_object_info($str = "")
function set_object_info($str = "")
{
  session::set('objectinfo',$str);
}

És a dir hi ha una variable de sessió que conté la informació bàsica del objecte Ldap, de fet el que té és el DN del objecte a partir del qual (fent consultes Ldap) podem obtenir tota la informació

A functions també teniu la funció get_object_info():

function get_object_info()
{
  return(session::get('objectinfo'));
}
Fitxer XML de configuració dinàmica. NOMPLUGIN.list.xml
TODO


Les llistes es defineixen amb el suport de fitxers XML. Hi ha tres parts (elements XML) principals:

Definition:

  • template: Path relatiu de la plantilla d'Smarty. El path és relatiu a la carpeta on està el fitxer XML de definició de la llista (carpeta arrel del plugin)
  • module: Mòdul/Plugin al que pertany la llista.
  • label: Descripció de la llista
  • departmentBrowser: Booleà. Es mostren els departament a la llista?
  • departmentRootVisible: Booleà. ???
  • baseMode: Booleà. ???
  • multiSelect: Booleà. Es permet seleccionar múltiples elements de la llista al mateix temps
  • baseMode: Booleà. ???
  • defaultSortColumn: Numèric. Quina columna s'utilitza per defecte per tal d'ordenar.

Definition/objectType

  • Permet definir el tipus d'objecte Ldap
  • label:
  • objectClass: ObjectClass Ldap de l'objecte. Només es mostraran els objectes ldap que siguin d'aquest tipus (cal tenir definit l'esquema al servidor Ldap)
  • category: ???????????
  • class: ???????????
  • image: És la imatge que surt al menú d'accions al intentar crear un dispositiu d'aquest tipus (TODO: Sistemes: Múltiples botons??? com?)

table

  • Permet definir el layout de la taula amb la llista de objectes a mostrar
  • layout: Permet indicar la mida de les columnes. Per exemple: |20px;c|||150px;r|
  • deparment: com mostrar els departaments????
  • column: TODO

actionmenu

  • Permet definir el que apareixerà al menú Action (Accions)

actiontriggers

  • ?????

Un exemple (la llista de dispositius del plugin devices):

 $ cat device-list.xml
<?xml version="1.0" encoding="UTF-8"?>

<list>
  <definition>
    <departmentBrowser>true</departmentBrowser>
    <departmentRootVisible>false</departmentRootVisible>
    <baseMode>true</baseMode>
    <multiSelect>true</multiSelect>
    <template>device-list.tpl</template>
    <module>devices</module>
    <label>List of devices</label>
    <defaultSortColumn>1</defaultSortColumn>

    <objectType>
      <label>Device</label>
      <objectClass>gotoDevice</objectClass>
      <category>devices</category>
      <class>deviceGeneric</class>
      <image>plugins/goto/images/select_device.png</image>
    </objectType>

  </definition>

  <table>
    <layout>|20px;c|||150px;r|</layout>

    <department>
      <value>%{filter:objectType(dn,objectClass)}</value>
    </department>

    <department>
      <value>%{filter:departmentLink(row,dn,description)}</value>
      <span>2</span>
    </department>

    <column>
      <value>%{filter:objectType(dn,objectClass)}</value>
    </column>

    <column>
      <label>Name</label>
      <sortAttribute>cn</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",cn)}</value>
      <export>true</export>
    </column>

    <column>
      <label>Description</label>
      <sortAttribute>description</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",description)}</value>
      <export>true</export>
    </column>

    <column>
      <label>Actions</label>
      <value>%{filter:actions(dn,row,objectClass)}</value>
    </column>

  </table>

  <actionmenu>

    <action>
     <type>sub</type>
     <image>images/lists/element.png[new]</image>
     <label>Create</label>

     <action>
      <name>new</name>
      <type>entry</type>
      <image>plugins/goto/images/select_device.png[new]</image>
      <label>Device</label>
     </action>
    </action>

    <action>
      <type>separator</type>
    </action>

    <action>
      <name>remove</name>
      <type>entry</type>
      <image>images/lists/trash.png</image>
      <label>Remove</label>
    </action>

    <action>
      <type>exporter</type>
    </action>

    <action>
      <type>separator</type>
    </action>

    <action>
      <type>copypaste</type>
    </action>

    <action>
      <type>snapshot</type>
    </action>

  </actionmenu>

  <actiontriggers snapshot="true" copypaste="true">

    <action>
      <name>cp</name>
      <type>copypaste</type>
    </action>

    <action>
      <name>edit</name>
      <type>entry</type>
      <image>images/lists/edit.png</image>
      <label>Edit device</label>
    </action>

    <action>
      <name>snapshot</name>
      <type>snapshot</type>
    </action>

    <action>
      <name>remove</name>
      <type>entry</type>
      <image>images/lists/trash.png</image>
      <acl>devices/deviceGeneric[d]</acl>
      <label>Remove device</label>
    </action>

  </actiontriggers>

</list>

Com podeu veure l'element arrel XML sempre és list

Es llegeix la part configurable/dinàmica d'un fitxer XML que defineix les característiques de la llista.

La classe listing carrega tot el XML a la variable xmlData. Un cop carregades totes les dades les podem utilitzar amb:

$this->xmlData['definition']['template']

Això segons el següent extracte de l'exemple anterior:

<list>
 <definition>
   ...
   <template>device-list.tpl</template>

Ha de retornar el valor:

device-list.tpl

Filtres (Filters)

TODO: Fer similar a l'apartat de llistes

IMPORTANT: Els filtres determinen quins objectes es mostraran a les llistes, cal tenir en compte el filtre per defecte!

Es modifiquen amb XML, user-filter.xml:

...
 <element>
    <type>textfield</type>
    <tag>DNI</tag>
    <size>10</size>
    <maxlength>20</maxlength>
    <default></default>
    <unset></unset>
    '''<set>(|(irisPersonalUniqueID=*$*))</set>'''               <-- Dos parèntesi al final!!!!
    <alphabet>true</alphabet>
    <autocomplete>
      <backend>LDAP</backend>
      <filter>(&(objectClass=gosaAccount)(|(irisPersonalUniqueID=*$DNI*)))</filter>
      <attribute>irisPersonalUniqueID</attribute>
      <frequency>0.5</frequency>
      <characters>3</characters>
    </autocomplete>
  </element>

  <element>
    <type>textfield</type>
    <tag>NAME</tag>
    <size>20</size>
    <maxlength>60</maxlength>
    <default></default>
    <unset></unset>
    <set>(|(cn=*$*)(sn=*$*)(givenName=*$*)(uid=*$*))</set>
    <alphabet>true</alphabet>
    <autocomplete>
      <backend>LDAP</backend>
      <filter>(&(objectClass=gosaAccount)(|(cn=*$NAME*)(sn=*$NAME*)(givenName=*$NAME*)(uid=*$NAME*)))</filter>
      <attribute>cn</attribute>
      <attribute>uid</attribute>
      <frequency>0.5</frequency>
      <characters>3</characters>
    </autocomplete>
  </element>
  
  <element>
    <type>textfield</type>
    <tag>INTERNAL_ID</tag>
    <size>10</size>
    <maxlength>20</maxlength>
    <default></default>
    <unset></unset>
    <set>(|(employeeNumber=*$*))</set>
    <alphabet>true</alphabet>
    <autocomplete>
      <backend>LDAP</backend>
      <filter>(&(objectClass=gosaAccount)(|(employeeNumber=*$INTERNAL_ID*)))</filter>
      <attribute>employeeNumber</attribute>
      <frequency>0.5</frequency>
      <characters>3</characters>
    </autocomplete>
  </element>

A la plantilla només cal:

<table summary="" style="width:100%;border-top:1px solid #B0B0B0;">
  <tr>
   <td>
    <label for="NAME">
     <img src="images/lists/search.png" align=middle> Name
    </label>
   </td>
   <td>
    {$NAME}
   </td>
  </tr>
  <tr>
   <td>
    <label for="DNI">
     <img src="images/lists/search.png" align=middle> DNI
    </label>
   </td>
   <td>
    {$DNI}
   </td>
  </tr>
  <tr>
   <td>
    <label for="INTERNAL_ID">
     <img src="images/lists/search.png" align=middle> Internal ID
    </label>
   </td>
   <td>
    {$INTERNAL_ID}
   </td>
  </tr>
 </table>


Cal sortir i tornar a entrar de la sessió per aplicar els canvis!.

Tabs (pestanyes)

Modificar el /etc/gosa/gosa.conf:

  • Crear la sección a la izquierda (debe ponerse dentro de <menu>):
    <section name="Personal">
      <plugin acl="Prueba" class="dummyplug" />
    </section> -->
  • Definir las pestañas:
  <dummyplugtabs>
    <tab class="tab1" name="Correos de Profesores" />
    <tab class="tab2" name="Estadisticas Cursos" />
    <tab class="tab3" name="Lista de Logons y Homes" />
  </dummyplugtabs>


NOTA: Las definiciones de Class tienen que hacerse antes del Class donde empieza el Plugin

NOTA: Hay que quitar el require del Smarty o petará!!!

NOTA: Hay que cambiar el código para crear una plantilla Smarty nueva por este:

$smarty= get_smarty();

NOTA: Hay que cambiar el código para imprimir la plantilla por este:

return ($smarty->fetch (get_template_path('tab1.tpl', TRUE)));

NOTA: No se puede definir "Class Group" porque ya existe una que se llama así!!!

Ejemplo "Correos Profes"

main.inc
<?php

/* Remove locks created by this plugin.
 *
 */
if ($remove_lock){
  if(session::is_set('dummyplug')){
    // Nothing to unlock here
  }
}


/* Cleanup is 'true' if the user selects another plugin from the GOsa menu.
 * This plugin will then no longer be required an can be removed from the session.
 */
if ( $cleanup ){
  session::un_set('dummyplug');
}else{


    /* All plugin objects get stored inside the PHP session. Here we create the object if it doesn't
     *  exist yet. It is recreated if "reset" is set.
     */
    if (!session::is_set('dummyplug')){

        /* The second parameter is null, due to the fact that we do not want to edit an ldap object right now. 
         * If you are going to write a plugin for the 'MyAccount' section of GOSa then you should pass '$ui->dn' 
         *  as parameter, $ui->dn is the dn of the currently logged in user. 
         * Your plugin can then use this dn to initialize your plugin with the objects attributes.
         */ 
        session::set('dummyplug',new dummyplug($config, null));
    }
    $dummyplug = session::get('dummyplug');


    /* The function 'save_object' is used to act on HTML _POST and _GET variables.
     * E.g. The plugin may provide an input field.
     */
    $display= $dummyplug->save_object();


    /* Execute plugin. This calls your plugin class and appends its output to the display variable.
     */
    $display= $dummyplug->execute ();


    /* GOsa avoids switching plugins until the user has saved it's modifications.
     * We ignore this check for the current plugin.
     */
    $display.= "<input type=\"hidden\" name=\"ignore\">\n";


    /* print_header generates the page header including the headline and the icon, get template
     * path looks for eventually overloaded files. You don't have to take care of this - it's only important
     * for theming artists. Copy the icon (as .png) to the html/images directory, if you don't care about
     * the image, just copy the personal.png to dummy.png.


     */
    $display= print_header(get_template_path('plugins/propertyEditor/images/plugin.png'), _("Estadístiques")).$display;


    /* After executing the plugin, some data may have changed, so we need to put the plugin back
     *  to the session.
     */
    session::set('dummyplug',$dummyplug);
}

?>
class_dummy.inc
<?php

/* Create a class (name must be unique inside GOsa) which extends plugin. The plugin base
 *  class contains all methods that are used by GOsa and it provides the mechanism to load data
 *  from LDAP to local variables and prepare the save to ldap routine for you. 
 */
class dummyplug extends plugin
{

  /* These contain attributes to be loaded. We're not creating an LDAP plugin currently, so we don't
   *  care... 
   */
  var $attributes= array();
  var $objectclasses= array();

  var $plHeadline = "Scripts Míos";
  var $plDescription = "Dummy plugin";
  var $plIcon = "plugins/propertyEditor/images/plugin.png";
  var $tabs;
  
  

  /* The constructor just saves a copy of the config. You may add what ever you need. 
   */
  public function dummyplug ($config, $dn= NULL)
  {
        /* Include config object 
         */
        $this->config= $config;
        
        $this->tabs= new dummyplugtabs($config, $config->data['TABS']['DUMMYPLUGTABS'], "");
  }


  /* Execute is the function all plugins need. It fills the plugin with life and produces the output. 
   */
  function execute()
  {
        /* Initialize the smarty engine.
         */
  //      $smarty= get_smarty();

        /* Let smarty fetch and process the page. Always seperate PHP and HTML as much as
         * you can. 
         * If you've problems telling smarty the correct location of your template file
         *  try to use it the this way 'get_template_path('contents.tpl', TRUE, dirname(__FILE__))'
         *  the template will then be found in the current folder too.
         */
    //    $smarty->assign("usuari","Sergi");
    //    return ($smarty->fetch (get_template_path('contents.tpl', TRUE)));
    
        /* Call parent execute */
        plugin::execute();

        /* Show main page */
        return ($this->tabs->execute());
    
  }

 
}
?>
tabs_dummyplug.inc
<?php

/* Create a class (name must be unique inside GOsa) which extends plugin. The plugin base
 *  class contains all methods that are used by GOsa and it provides the mechanism to load data
 *  from LDAP to local variables and prepare the save to ldap routine for you. 
 */
class dummyplug extends plugin
{

  /* These contain attributes to be loaded. We're not creating an LDAP plugin currently, so we don't
   *  care... 
   */
  var $attributes= array();
  var $objectclasses= array();

  var $plHeadline = "Scripts Míos";
  var $plDescription = "Dummy plugin";
  var $plIcon = "plugins/propertyEditor/images/plugin.png";
  var $tabs;
  
  

  /* The constructor just saves a copy of the config. You may add what ever you need. 
   */
  public function dummyplug ($config, $dn= NULL)
  {
        /* Include config object 
         */
        $this->config= $config;
        
        $this->tabs= new dummyplugtabs($config, $config->data['TABS']['DUMMYPLUGTABS'], "");
  }


  /* Execute is the function all plugins need. It fills the plugin with life and produces the output. 
   */
  function execute()
  {
        /* Initialize the smarty engine.
         */
  //      $smarty= get_smarty();

        /* Let smarty fetch and process the page. Always seperate PHP and HTML as much as
         * you can. 
         * If you've problems telling smarty the correct location of your template file
         *  try to use it the this way 'get_template_path('contents.tpl', TRUE, dirname(__FILE__))'
         *  the template will then be found in the current folder too.
         */
    //    $smarty->assign("usuari","Sergi");
    //    return ($smarty->fetch (get_template_path('contents.tpl', TRUE)));
    
        /* Call parent execute */
        plugin::execute();

        /* Show main page */
        return ($this->tabs->execute());
    
  }

 
}
?>
class_tab1.inc
<?php

/* Create a class (name must be unique inside GOsa) which extends plugin. The plugin base
 *  class contains all methods that are used by GOsa and it provides the mechanism to load data
 *  from LDAP to local variables and prepare the save to ldap routine for you. 
 */
class dummyplug extends plugin
{

  /* These contain attributes to be loaded. We're not creating an LDAP plugin currently, so we don't
   *  care... 
   */
  var $attributes= array();
  var $objectclasses= array();

  var $plHeadline = "Scripts Míos";
  var $plDescription = "Dummy plugin";
  var $plIcon = "plugins/propertyEditor/images/plugin.png";
  var $tabs;
  
  

  /* The constructor just saves a copy of the config. You may add what ever you need. 
   */
  public function dummyplug ($config, $dn= NULL)
  {
        /* Include config object 
         */
        $this->config= $config;
        
        $this->tabs= new dummyplugtabs($config, $config->data['TABS']['DUMMYPLUGTABS'], "");
  }


  /* Execute is the function all plugins need. It fills the plugin with life and produces the output. 
   */
  function execute()
  {
        /* Initialize the smarty engine.
         */
  //      $smarty= get_smarty();

        /* Let smarty fetch and process the page. Always seperate PHP and HTML as much as
         * you can. 
         * If you've problems telling smarty the correct location of your template file
         *  try to use it the this way 'get_template_path('contents.tpl', TRUE, dirname(__FILE__))'
         *  the template will then be found in the current folder too.
         */
    //    $smarty->assign("usuari","Sergi");
    //    return ($smarty->fetch (get_template_path('contents.tpl', TRUE)));
    
        /* Call parent execute */
        plugin::execute();

        /* Show main page */
        return ($this->tabs->execute());
    
  }

 
}
?>
tab1.tpl
<html>
<head>
<title>Correus de Professors</title>
<meta name="tipo_contenido"  content="text/html;" http-equiv="content-type" charset="utf-8">
</head>
<body>
<table border="1">
<tr>
<th>Codi</th>
<th>Professor</th>
<th>Correu electrònic</th>
</tr>

{foreach from = $Correus item = correu}
    <tr>
    <td>{$correu->codi}</td>
        <td>{$correu->name}</td>
        <td><a href="mailto:{$correu->mail}" >{$correu->mail}</a></td>
     </tr>
{/foreach}

</table>


</body>
</html>

Formularis

TODO

ACLs

Les ACL es guarden a la base de dades associades als objecte Ldap.

Vegem el cas de l'objecte arrel:

dn: dc=todo,dc=openfpnet,dc=guifi,dc=net
objectClass: dcObject
objectClass: gosaAcl
objectClass: gosaDepartment
objectClass: organization
objectClass: top
dc: todo
description: todo
gosaAclEntry: 0:psub:Y249U3lzdGVtIEFkbWluaXN0cmF0b3ItYWRtaW4sb3U9cGVvcGxlLGR
jPXRvZG8sZGM9b3BlbmZwbmV0LGRjPWd1aWZpLGRjPW5ldA==:all/all;cmdrw
o: todo
ou: todo

El atribut gosaAclEntry forma part de l'objecte ldap gosaAcl. De fet gosaAclEntry és l'únic atribut de de l'objecte gosaAcl i és mandatory.

Les entrada ACL estan separades per :. A l'exemple tenim els valors

0 --> 0. És el número de ACL
1 --> psub --> És el camp acl type --> permanent subtree
2 --> Y249U3lzdGVtIEFkbWluaXN0cmF0b3ItYWRtaW4sb3U9cGVvcGxlLGR
jPXRvZG8sZGM9b3BlbmZwbmV0LGRjPWd1aWZpLGRjPW5ldA== --> Membres de la ACL: DNs en md5sum per permetre caràcters extranys
3 --> all/all --> ??? 
4 --> cmdrw   --> Permisos

A l'exemple l'usuari és:

$ base64 -d
Y249U3lzdGVtIEFkbWluaXN0cmF0b3ItYWRtaW4sb3U9cGVvcGxlLGRjPXRvZG8sZGM9b3BlbmZwbmV0LGRjPWd1aWZpLGRjPW5ldA==   <-- Premeu Ctrl+d
cn=System Administrator-admin,ou=people,dc=todo,dc=openfpnet,dc=guifi,dc=net

Classes i objectes principals de gosa

Les trobareu principalment a:

/usr/share/gosa/include

class_plugin.inc. Class Plugin

Classe pare de qualsevol plugin normal (que no sigui de gestió).

class_management.inc

Classe pare de qualsevol plugin de gestió.

class_ldap.inc. Classe Ldap

Funcions bàsiques de ldap.

TODO

class_listing.inc. Class listing

/usr/share/gosa/include/class_listing.inc

Consulteu llistes

functions.inc

Funcions genèriques útils per a Gosa en general.

class_tabs.inc

Classe pare per a qualsevol objecte de tipus pestanya.

Funcionament general de Gosa

Gosa és una aplicació LAMP. Si observem el fitxer de configuració d'Apache per a Gosa veurem:

$ cat /etc/apache2/conf.d/gosa.conf
# Include GOsa to your web service
Alias /gosa /usr/share/gosa/html
...

És a dir que quan els usuaris accedeixen a la URL:

http://localhost/gosa

Es mostren els fitxers de la carpeta:

/usr/share/gosa/html

La configuració per defecte d'Apache fa que si no indiqueu cap fitxer especific es mostri el fitxer:

/usr/share/gosa/html/index.php

Aquest és el fitxer principal a partir del qual s'accedirà a tots els plugins i apartats que té Gosa. Des de la perspectiva del disseny MVC podríem dir que aquesta és la classe controladora que gestiona el flux de treball de l'aplicació (depenen de les accions executades per l'usuari s'executa un plugin o un altre una acció o un altre,etc). Tot el codi de gosa passa prèviament per aquest fitxer.


Workflow

El fitxer index.php fa un include del fitxer

main.inc

Del plugin seleccionat en cada moment (la QUERY STRING plug determina el número de plugin, sempre en l'ordre que apareixen al fitxer de configuració /etc/gosa/gosa.conf )

El main sempre té la mateixa estructura:

  • Controls previs:
  • Gestió de locks de Gosa
  • Hi ha una variable anomenada cleanup que força la eliminació de l'objecte managment de la sessió.
  • S'espera que a la sessió hi haguí un objecte de tipus managment (fill de la classe managment).
  • El objecte es guarda sencer a la sessió amb un string que el descriu. Per exemple "HighSchoolUserManagement" (sol ser el mateix nom de la classe)
  • Constructor: Estableix el filtre de l'objecte managment i la llista. També s'estableixen les accions
  • Important!: no s'estableixen els objectes tabs ni res similar. Això es fa en accions especifiques com per exemple newEntry.
  • Si no existeix l'objecte managment a la sessió s'executa el constructor del objecte HighSchoolUserManagement i un cop creat es guarda a la sessió
  • S'obté el objecte de la sessió (sempre estarà per què al pas anterior si no existia s'haurà creat i carregat) i s'executa el mètode execute.
  • important: Sovint la classe executa no cal definir-la als objectes fills, se sol executar la funció execute de l'objecte managment
Funció execute
  • Control previs
  • PathNavigator,Executar CopyPasteHandler si existeix, update filter
  • Sinó hi ha cap acció especifica executada o especials com CopyPaste aleshores es mostra la llista
  • Gestió de les accionshandleActions i 'detectPostActions
  • 2 tipus d'accions
postActions: es gestionen a la funció detectPostActions. Són accions que s'executen a partir de l'existència d'algun item de formulari (botons clicats, etc.)
  • Accions definides al XML de la llista i registrades al constructor del objecte managment. Són les que apareixen al menú accions de la llista.
  • S'executa l'acció que pertoca. Per exemple: newStudent() (acció a mida filla de newUser i newEntry)
  • Al crear un nou objecte de tipus tab es llegeixen els subojectes de cada plantilla del fitxer de configuració gosa.conf
  • S'executen els constructors
  • Objectes complexes amb tabs (pestanyes) --> Cal definir-los com a fills de la classe tabs
  • Aquesta classe s'encarrega de guardar tots els objectes de cada pestanya.
  • El atribut by_object conté un array dels objecte tipus plugin que hi ha a cada tab (pestanya)
  • Preparar les plantilles d'smarty i mostrar-les
Les accions simplement poden finalitzar havent establert un objecte de tipus tab o un objecte de tipus dialeg. Al retornar a la funció execute s'executaran les funcions execute del objecte tab o del objecte dialeg.

Save

  • Dos funcions:
  • save_object(): Hi ha funció tant de l'objecte tab que inclou diversos plugins com el save_object de cada plugin. Aquestes funcions
  • save(): Guarda el objecte a ldap. Molts atributs s'obtenen automàticament dels camps post (això ho fa la funció saveobject() dels objectes pare), altres especials cal controlar-los a la funció save_object()
  • Entre el save_objec() i el save s'executa la funció check() que comprova que tot estigui correcte abans d'intentar. Serveix per fer la validació de formularis d'entrada de dades.

L'estructura de fitxers/objectes és:

  • main.inc
  • Objecte managment

Desenvolupament de plugins

Els passos necessaris per a desenvolupar un plugin són els indicats en les següents seccions:

  1. Preparació de la base de dades Ldap. Crear un esquema Ldap propi

Preparació de la base de dades Ldap. Crear un esquema Ldap propi

Gosa treball principalment amb Ldap com a backend per emmagatzemar les dades. Per tant si aneu a definir un nou plugin haureu de crear un nou esquema Ldap.

Consulteu Ldap#Com_crear_un_esquema_propi_.28extendre_esquema_Ldap.29

TODO: Un exemple d'objecte molt senzill amb 4 atributs
TODO: Indicar com s'instal·la l'esquema

Recursos relacionats:

Creació del codi bàsic del plugin

Quins fitxers ha de tenir el plugin (de managment)?, s'indica a:

Desenvolupament_a_mida_de_Gosa#Plugin_de_gesti.C3.B3

Eines útils per a desenvolupar amb Gosa

Logging

El logging us permet tenir més informació sobre l'execució de gosa. Útil quan estem intentant buscar les raons d'un error.

Funciona si s'activa al fitxer /etc/gosa/gosa.conf:

 <main default="default"
        logging="true"
 ...

Els missatges de lo s'envien a syslog. Els podeu consultar amb:

$ sudo cat /var/log/syslog | grep GOsa

Podeu consultar els missatges en temps real amb l'ordre tail:

$ sudo tail -f /var/log/syslog | grep GOsa

Es mostraran més o menys missatges segons el nivell de depuració (debug), paràmetre debugLevel que és un AND dels següents valors

      DEBUG_TRACE   = 1
      DEBUG_LDAP    = 2
      DEBUG_MYSQL   = 4
      DEBUG_SHELL   = 8
      DEBUG_POST    = 16
      DEBUG_SESSION = 32
      DEBUG_CONFIG  = 64
      DEBUG_ACL     = 128
      DEBUG_SI      = 256
      DEBUG_MAIL    = 512
      TOT           = 1023

Aquests valors es trobe definits al fitxer class_core.inc


./class_core.inc:558:DEBUG_TRACE   = 1
./class_core.inc:559:DEBUG_LDAP    = 2
./class_core.inc:560:DEBUG_MYSQL   = 4
./class_core.inc:561:DEBUG_SHELL   = 8
./class_core.inc:562:DEBUG_POST    = 16 
./class_core.inc:563:DEBUG_SESSION = 32
./class_core.inc:564:DEBUG_CONFIG  = 64
./class_core.inc:565:DEBUG_ACL     = 128
./class_core.inc:566:DEBUG_SI      = 256"),

I a functions.inc:

./functions.inc:66:define('DEBUG',false);
./functions.inc:81:define ("DEBUG_TRACE",   1); /*! Debug level for tracing of common actions (save, check, etc.) */
./functions.inc:82:define ("DEBUG_LDAP",    2); /*! Debug level for LDAP queries */
./functions.inc:83:define ("DEBUG_MYSQL",   4); /*! Debug level for mysql operations */
./functions.inc:84:define ("DEBUG_SHELL",   8); /*! Debug level for shell commands */
./functions.inc:85:define ("DEBUG_POST",   16); /*! Debug level for POST content */
./functions.inc:86:define ("DEBUG_SESSION",32); /*! Debug level for SESSION content */
./functions.inc:87:define ("DEBUG_CONFIG", 64); /*! Debug level for CONFIG information */
./functions.inc:88:define ("DEBUG_ACL",    128); /*! Debug level for ACL infos */
./functions.inc:89:define ("DEBUG_SI",     256); /*! Debug level for communication with gosa-si */
./functions.inc:90:define ("DEBUG_MAIL",   512); /*! Debug level for all about mail (mailAccounts, imap, sieve etc.) */
./functions.inc:91:define ("DEBUG_FAI",   1024); // FAI (incomplete)
./functions.inc:92:define ("DEBUG_RPC",   2048); /*! Debug level for communication with remote procedures */


El paràmetre també es troba a la secció main del fitxer /etc/gosa/gosa.conf.

IMPORTANT: Per activar la depuració cal sortir de la sessió (sortir de l'usuari)

Fer logging durant el desenvolupament

Pel fitxer de log

Exemple (funció SaveChanges):


//Log internatID
        $current_id=$this->getNextInternalID();
		$current_id=$this->ACADEMIC_PERIOD."-".$current_id;
		@DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dns,"current_id: ".$current_id);
		@DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dns,"employeeNumber: ".$this->employeeNumber);
		
		if ($current_id == $this->employeeNumber) {
			$this->incrementNextInternalID();
			new log("modify","users/".get_class($this),$this->dn,array(),"Incremented next internal ID to ".$this->getNextInternalID());
		}
Per l'aplicació web

Cal utilitzar la funció @DEBUG

@DEBUG (DEBUG_ACL, __LINE__, __FUNCTION__, __FILE__,"".$base."","ACL-Base: ");

A l'exemple estem posant un missatge del nivell DEBUG_ACL.

Creació d'un paquet Debian. dh-make-gosa

Del manual:

$ man dh-make-gosa
...
      dh-make-gosa - Debianizes the source of a given gosa plugin

SYNOPSIS
      dh-make-gosa [OPTION]...  SOURCE

Example usage
      # Check out a plugin from SVN
      svn co https://oss.gonicus.de/repositories/gosa/trunk/gosa-plugins/samba /tmp/samba

      # Debianize the tree
      cd /tmp
      dh-make-gosa --email [email protected] --release etch --section web samba

      # Build debian package
      cd samba
      dpkg-buildpackage -uc -us -rfakeroot

      To build everything from the subversion repository which is GOsa related, please take a look at the contributed make-gosa-package script.

Us permet convertir un plugin Gosa a un paquet Debian. L'ordre es proporcionada pel paquet gosa-dev:

$ which dh-make-gosa
/usr/bin/dh-make-gosa
$ dpkg -S /usr/bin/dh-make-gosa
gosa-dev: /usr/bin/dh-make-gosa

TODO (documentar l'ús)

Vegeu també:

Autoload

Gosa utilitzant l'ordre update-gosa té un mecanisme que permet carregar automàticament les classes de Gosa a PHP. Bàsicament el programador l'únic que ha de fer es definir les classes en fitxers que tinguin la extensió .inc o .php a la carpeta o subcarpetes:

/usr/share/gosa

La funció encarregada de actualitzar les classes (es troba dins del fitxer udpate-gosa) és:

function rescan_classes()

Bàsicament el que fa és buscar totes les classes que hi ha a les carpetes o subcarpetes /usr/share/gosa. La funció encarregada és get_classes. La llista de clases localitzades es guarda al fitxer:

/var/cache/gosa/class.cache

NOTA: També update-gosa conprova que el fitxer existeixi i que no sigui modificable (no tingui permisos d'escriptura)

Al fitxer:

$ cat /usr/share/gosa/include/functions.inc
/*! \brief Does autoloading for classes used in GOsa.
 *
 *  Takes the list generated by 'update-gosa' and loads the
 *  file containing the requested class.
 *
 *  \param  string 'class_name' The currently requested class
 */
function __gosa_autoload($class_name) {
    global $class_mapping, $BASE_DIR;

    if ($class_mapping === NULL){
	    echo sprintf(_("Fatal error: no class locations defined - please run %s to fix this"), bold("update-gosa"));
	    exit;
    }

    if (isset($class_mapping["$class_name"])){
      require_once($BASE_DIR."/".$class_mapping["$class_name"]);
    } else {
      echo sprintf(_("Fatal error: cannot instantiate class %s - try running %s to fix this"), bold($class_name), bold("update-gosa"));
      exit;
    }
}

spl_autoload_register('__gosa_autoload');

Hi la funció encarregada de carregar les classes.

L'última línia és el mecanisme que té PHP per indicar quina funció és l'encarregada de carregar les classes sota demanda (autoload). Fixeu-vos que les classes es busquen a un array anomenat:

$class_mapping

Aquest array es troba emmagatzemat a la cache de gosa (/var/cache/gosa), concretament al fitxer /var/cache/gosa/class.cache:

$ sudo head /var/cache/gosa/class.cache
<?php
$class_mapping= array(
               "Step_Finish" => "setup/class_setupStep_Finish.inc",
               "Step_Feedback" => "setup/class_setupStep_Feedback.inc",
               "Step_Schema" => "setup/class_setupStep_Schema.inc",
               "Step_Migrate" => "setup/class_setupStep_Migrate.inc",
               "Step_Language" => "setup/class_setupStep_Language.inc",
               "Step_Ldap" => "setup/class_setupStep_Ldap.inc",
               "Step_License" => "setup/class_setupStep_License.inc",
               "setup_step" => "setup/class_setupStep.inc",
...

Aquest fitxer i l'array que conté son generats per la funció update-gosa, update-gosa sense més opcions realitza diverses tasques una d'elles és precisament localitzar classes (update-gosa rescan-classes), el codi és:

function rescan_classes()
 { 
 	echo "Updating class cache...\n"; 
	$class_mapping= get_classes("/usr/share/gosa");
	$filename= "/var/cache/gosa/class.cache";

	/* Sanity checks */
	if (!file_exists($filename) || is_writable($filename)) {

	    if (!$handle= fopen($filename, 'w')) {
		 echo "Cannot open file \"$filename\" - aborted\n";
		 exit (1);
	    }

	} else {
	    echo "File \"$filename\" is not writable - aborted\n";
	    exit (2);
	}

	fwrite ($handle, "<?php\n\$class_mapping= array(\n");
	foreach ($class_mapping as $key => $value){
	  fwrite ($handle, "                \"$key\" => \"$value\",\n");
	}
	fwrite ($handle, " );\n");

	fclose($handle);
}

Les classes es busquen amb la funció get_classes:

 /* Function to include all class_ files starting at a given directory base */
function get_classes($folder= ".")
{
  static $base_dir= "";
  static $result= array();

  if ($base_dir == ""){
    if ($folder == "."){
      $base_dir= getcwd();
    } else {
      $base_dir= $folder;
    }
  }

  $currdir=getcwd();
  if ($folder){
    chdir("$folder");
  }

  $dh = opendir(".");
  while(is_resource($dh) && false !== ($file = readdir($dh))){

    if (preg_match("/.*\.svn.*/", $file) ||
        preg_match("/.*smarty.*/i",$file) ||
        preg_match("/.*\.tpl.*/",$file) ||
        ($file==".") ||($file =="..")){
      continue;
    }

    /* Recurse through all "common" directories */
    if (is_dir($file) && !file_exists("{$file}/excludeFromAutoLoad")){
      get_classes($file);
      continue;
    }

    /* Only take care about .inc and .php files... */
    if (!(preg_match('/\.php$/', $file) || preg_match('/\.inc$/', $file))){
      continue;
    }

    /* Include existing class_ files */
    $contents= file($file);
    foreach($contents as $line){
      $line= chop($line);
      if (preg_match('/^\s*class\s*\w.*$/', $line)){
        $class= preg_replace('/^\s*class\s*(\w+).*$/', '\1', $line);
        $result[$class]= preg_replace("%$base_dir/%", "", "$currdir/$folder/$file");
      }
    }
  }

  @closedir($dh);
  chdir($currdir);

  return ($result);
}

No esta mal el codi! Busca recursivament a tots els fitxer amb extensió .inc i .php i afegeix les classes que hi trobi al seu interior!

/usr/sbin/update-gosa

$ sudo update-gosa help
Error: Supplied command not known

update-gosa - class cache updated and plugin manager for GOsa
Usage: update-gosa install dsc     Install the plugin using the dsc information
                                   placed in the plugin source directory.

      update-gosa remove plugin   Remove the plugin named "plugin" from
                                  the current configuration.

      update-gosa list           Lists installed plugins

      update-gosa rescan-i18n     Rebuilds the translations

      update-gosa rescan-images   Rebuilds the themes master image

      update-gosa rescan-classes  Rebuilds the class list
      
      update-gosa                 Shortcut for rescan-classes and rescan-i18n

El path complet és /usr/sbin/update-gosa

Exemples

Crear un nou plugin

Hi ha dos tipus de plugins:

  • Normals
  • Plugins de gestió

definir el plugin a /etc/gosa/gosa.conf

$ sudo joe /etc/gosa/gosa.conf

Afegiu:

   <section name="prova INS Ebre">
		<plugin acl="ldapmanager" class="ldif" />
   </section>

Per aplicar un canvi només cal:

$ sudo update-gosa

IMPORTANT: les seccions buides no es mostren

Plugin normal (addons)

IMPORTANT: En aquest apartat estem suposant el tot moment que Gosa està instal·lat a la carpeta /usr/share/gosa. Com a referència comentar també que els exemples s'han desenvolupat amb un Gosa 2.7

Creem el directori dummyplug a /usr/share/gosa/plugins/addons

$ cd /usr/share/gosa/plugins/addons/
$ sudo mkdir dummyplug && cd dummyplug

Creem el fitxer main.inc. Ens permet controlar el cicle de vida del plugin, restaurar-lo i establir variables relacionades amb la acl

<?php

/* Remove locks created by this plugin.
 *
 */
if ($remove_lock){
  if(session::is_set('dummyplug')){
    // Nothing to unlock here
  }
}


/* Cleanup is 'true' if the user selects another plugin from the GOsa menu.
 * This plugin will then no longer be required an can be removed from the session.
 */
if ( $cleanup ){
  session::un_set('dummyplug');
}else{


    /* All plugin objects get stored inside the PHP session. Here we create the object if it doesn't
     *  exist yet. It is recreated if "reset" is set.
     */
    if (!session::is_set('dummyplug')){

        /* The second parameter is null, due to the fact that we do not want to edit an ldap object right now. 
         * If you are going to write a plugin for the 'MyAccount' section of GOSa then you should pass '$ui->dn' 
         *  as parameter, $ui->dn is the dn of the currently logged in user. 
         * Your plugin can then use this dn to initialize your plugin with the objects attributes.
         */ 
        session::set('dummyplug',new dummyplug($config, null));
    }
    $dummyplug = session::get('dummyplug');


    /* The function 'save_object' is used to act on HTML _POST and _GET variables.
     * E.g. The plugin may provide an input field.
     */
    $display= $dummyplug->save_object();


    /* Execute plugin. This calls your plugin class and appends its output to the display variable.
     */
    $display= $dummyplug->execute ();


    /* GOsa avoids switching plugins until the user has saved it's modifications.
     * We ignore this check for the current plugin.
     */
    $display.= "<input type=\"hidden\" name=\"ignore\">\n";


    /* print_header generates the page header including the headline and the icon, get template
     * path looks for eventually overloaded files. You don't have to take care of this - it's only important
     * for theming artists. Copy the icon (as .png) to the html/images directory, if you don't care about
     * the image, just copy the personal.png to dummy.png.


     */
    $display= print_header(get_template_path('plugins/log/images/plugin.png'), _("System log view")).$display;


    /* After executing the plugin, some data may have changed, so we need to put the plugin back
     *  to the session.
     */
    session::set('dummyplug',$dummyplug);
}

?>

Funcions de l'script:

  • Elimina els bloqueigs (locks) que pugui generar el plugin
  • Es fa un clean (neteja) un cop l'usuari ha seleccionat un altre plugin
  • Executa el plugin.
  • Genera una capçalera amb el text que nosaltres vulguem, en aquest cas és la frase System log view

La línia més important és:

$display= $dummyplug->execute ();

Que és la que executa el plugin.

IMPORTANT: Fixeu-vos que s'evita escriure directament a la sortida. L'única variable que es pinta a la sortida és $display, així s'eviten els típics errors de headers alredy sent. Consulteu l'apartat logging per tal de veure com es pot depurar sense necessitat d'escriure a la sortida

Creem el fitxer class_dummy.inc al directori /usr/share/gosa/plugins/addons/dummyplug.

<?php

/* Create a class (name must be unique inside GOsa) which extends plugin. The plugin base
 *  class contains all methods that are used by GOsa and it provides the mechanism to load data
 *  from LDAP to local variables and prepare the save to ldap routine for you. 
 */
class dummyplug extends plugin
{

  /* These contain attributes to be loaded. We're not creating an LDAP plugin currently, so we don't
   *  care... 
   */
  var $attributes= array();
  var $objectclasses= array();

  var $plHeadline = "Dummy plugin";
  var $plDescription = "Dummy plugin";

  /* The constructor just saves a copy of the config. You may add what ever you need. 
   */
  public function __construct ($config, $dn= NULL)
  {
        /* Include config object 
         */
        $this->config= $config;
  }


  /* Execute is the function all plugins need. It fills the plugin with life and produces the output. 
   */
  function execute()
  {
        /* Initialize the smarty engine.
         */
        $smarty= get_smarty();

        /* Let smarty fetch and process the page. Always seperate PHP and HTML as much as
         * you can. 
         * If you've problems telling smarty the correct location of your template file
         *  try to use it the this way 'get_template_path('contents.tpl', TRUE, dirname(__FILE__))'
         *  the template will then be found in the current folder too.
         */
        return ($smarty->fetch (get_template_path('contents.tpl', TRUE)));
  }

 
}
?>


Creem el fitxer contents.tpl al directori /usr/share/gosa/plugins/addons/dummyplug. Aquest fitxer guarda el codi i la informació que mostrarà al gosa.

NOTA: Gosa utilitza Smarty (concretament Gosa 2.7 utilitza Smarty 3). Smarty és un sistema de plantilles que permet separar el codi PHP de la presentació (codi HTML, CSS, etc.)

En aquest cas, quan entrem al plugin dummyplug del gosa mostrarà la frase Hellow world i una descripció

<h2>{t}Hello World{/t}</h2>
<p>
  {t}This is a dummy plugin. It really does nothing. The tags around this text do automatic translations to the desired         language. Please don't include linefeeds here, or it will not work at all!{/t}
</p>

<p class="plugbottom">
   
</p>


Editem el fitxer gosa.conf situat a /etc/gosa per a inserir el plugin creat al nostre gosa.

Dintre de l'apartat dels Adons inserim el següent codi per a que aparegui el plugin als Adons del gosa

<plugin acl="dummyplug" class="dummyplug" />

Reiniciem el servei gosa

$sudo update-gosa

Addons dummyplug.jpg

Contingut dummyplug.jpg


Posar una icona al plugin

Icona que utilitzarem:

Icona dummyplug.png

Per afegir una icona al nostre plugin, hem de seguir els següents pasos;

  • Primer hem de crear dos carpetes, el primer és troba a '/usr/share/gosa/html/plugins', i dins d'aquesta carpeta hem de crear un altra carpeta anomenada 'images'. Aqui és on col·locarem la imatge .png que utilitzarem per la icona.
  • Per aquest exemple he anomenat el fitxer dummy.png (l'imatge ha de ser de 56x56 píxels).
sudo mkdir /usr/share/gosa/html/plugins/dummyplug
sudo mkdir /usr/share/gosa/html/plugins/dummyplug/images
  • El cami final del imatge serà així;
/usr/share/gosa/html/plugins/dummyplug/images/dummy.png
  • Ara hem de navegar a la carpeta del nostre plugin i editar un fitxer que vam crear als pasos anteriors.
    • El fitxer que hem de modificar és el següent;
sudo geany /usr/share/gosa/plugins/addons/dummyplug/class_dummy.inc
    • Dins d'aquest fitxer hem d'afegir la següent línia, la col·locarem abans del public_function;
var $plIcon  = "plugins/dummyplug/images/dummy.png"
  • Ara reinuicieu els servei gosa, amb la següent ordre;
sudo update-gosa
  • Ara podeu veure que teniu una icona al costat del plugin.

Podeu descarregar la estructura del fitxer i un makefile a la següent URL:

Subversion amb exemples de plugins gosa

Fer que el plugin dummyplug pugui inserir i visualitzar el contingut d'una base de dades LDAP
  • Editem el fitxer class_dummyplug.inc
<?php

/* Create a class (name must be unique inside GOsa) which extends plugin. The plugin base
 *  class contains all methods that are used by GOsa and it provides the mechanism to load data
 *  from LDAP to local variables and prepare the save to ldap routine for you. 
 */
class dummyplug extends plugin
{

  /* These contain attributes to be loaded. We're not creating an LDAP plugin currently, so we don't
   *  care... 
   */
  var $attributes= array();
  var $objectclasses= array();

  var $plHeadline = "Dummy plugin";
  var $plDescription = "Dummy plugin";
  var $plIcon = "plugins/dummyplug/images/dummyplug.png";


  /* The constructor just saves a copy of the config. You may add what ever you need. 
   */
  public function __construct ($config, $dn= NULL)
  {
        /* Include config object 
         */
        $this->config= $config;
  }


  /* Execute is the function all plugins need. It fills the plugin with life and produces the output. 
   */
  function execute()
  {
		//Exemple de lectura de la base de dades LDAP
		/* Get an ldap handle and set the initial context to the ldap base. 
		 */
		$ldap = $this->config->get_ldap_link();
		//Anem a la basde de la base de dades LDAP
		$ldap->cd($this->config->current['BASE']);

		/* Search for all objects, recursive, that match the given ldap filter.
		 */
		//Consulta a la base de dades LDAP (base) que busca els ObjectClass gosaAccount i el person
		//i guardem els uid i cn
		$ldap->search("(&(objectClass=gosaAccount)(objectClass=person))",array("uid","cn"));

		/* Print out each returned object.
		 * print_a is a debugging function and is not for productive use!
		 */
		 //Al debug mostrem les dades extretes de la consulta anterior
		 //La funció print_a està creada al fitxer /include/functions_debug.inc a la línia 93
		 //Comanda per saber a quin fitxer s'ha creat la funció print_a:
		 //[email protected]:/usr/share/gosa$ grep -n "function print_a" -r .
		while($attrs = $ldap->fetch()){
		  print_a($attrs);
		}
		
		//Exemple d'escriptura de la base de dades LDAP
		/* Get an ldap handle and set the initial context to the ldap base.
		*/
	   $ldap = $this->config->get_ldap_link();
	   $ldap->cd($this->config->current['BASE']);

	   /* the dummy user object
		*/
		//Creem el array on guardarem les dades del nou usuari
	   $user = array();
	   $user['objectClass'] = array("top","person","organizationalPerson","inetOrgPerson","gosaAccount");
	   $user['sn'] = "Wusel";
	   $user['givenName'] = "Herbert";
	   $user['cn']   = "Herbert Wusel";
	   $user['uid']  = "herb123";
	   //Especifiquem el dn del nou usuari
	   $user_dn = "cn=".$user['cn'].",".get_people_ou().$this->config->current['BASE'];

	   /* Ensure that the organizational structure is created if needed.
		* In this case we want to write a new user to 'ou=people,...',
		*  create_missing_trees now ensures that the organizationalUnit 'ou=people' is
		*  available.
		*/
	   $ldap->create_missing_trees(preg_replace("/^[^,]+,/","",$user_dn));

	   /* Create the new user
		*/
		//Anem al dn de l'usuari
	   $ldap->cd($user_dn);
	   //Creem el nou usuari
	   $ldap->add($user);

	   echo $ldap->get_error();


        /* Initialize the smarty engine.
         */
        $smarty= get_smarty();

        /* Let smarty fetch and process the page. Always seperate PHP and HTML as much as
         * you can. 
         * If you've problems telling smarty the correct location of your template file
         *  try to use it the this way 'get_template_path('contents.tpl', TRUE, dirname(__FILE__))'
         *  the template will then be found in the current folder too.
         */
        return ($smarty->fetch (get_template_path('contents.tpl', TRUE)));
    
  }
 
}
?>


Parts de la funció execute:

  • Es crea un enllaç a la base de dades LDAP amb la variable $ldap
  • Accedim a la base del LDAP
  • Lectura de dades en una base de dades LDAP:
    • Fem una consulta a la base de dades LDAP que busca els ObjectClass gosaAccount i person i guardem les dades del uid i cn
    • Fem un bucle per a visualitzar totes les dades extretes de la consulta anterior. Aquestes dades sols seran visibles si està activat el mode DEBUG
    • Per a visualitzar les dades utilitza una funció anomenada print_a que s'ha creat al fitxer /include/functions_debug.inc

NOTA: Comanda per saber on s'ha creat la funció print_a: grep -n "function print_a" -r .

  • Escriptura de dades en una base de dades LDAP:
    • Tronem a crear l'enllaç a la base de dades LDAP amb la variable $ldap i ens posem a la base de la bd
    • Creem un array a la variable $user on posarem les dades que volem inserir a la base de dades.
    • A la variable $user_dn especifiquem el dn del nou usuari.
    • Ens posem al dn de l'usuari que volem crear
    • Creem l'usuari


Plugin per comprovar dades d'un formulari

Editem el fitxer contents.tpl per a demana a l'usuari que introdueixi un correu electrònic i un comentari

<h2>{t}Hello World{/t}</h2>
<p>
 {t}Mail{/t} <input type="text" name="mail" value="{$mail}">
</p>
<p>
 {t}Description{/t} <input type="text" name="description" value="{$description}">
</p>
<input type='submit' name='submit' value='{t}Reload{/t}'>
<input type='submit' name='save_dummyplug' value='{t}Save{/t}'>

<p class="plugbottom">
   
</p>


Editem el fitxer class_dummy.inc per a que comprovi si el correu electrònic introduït sigui el correcte. Si no ho és guarda en una variable un missatge d'error.

<?php

/* Create a class (name must be unique inside GOsa) which extends plugin. The plugin base
 *  class contains all methods that are used by GOsa and it provides the mechanism to load data
 *  from LDAP to local variables and prepare the save to ldap routine for you. 
 */
class dummyplug extends plugin
{

  /* These contain attributes to be loaded. We're not creating an LDAP plugin currently, so we don't
   *  care... 
   */
   
   /*
    * Creem una variable, attributes, que és un array i guardem les dades del formulari (contents.tpl)
    * */
  var $attributes= array("mail","description");
  var $objectclasses= array();

  var $plHeadline = "Dummy plugin";
  var $plDescription = "Dummy plugin";

	/*
	 * Especifiquem les variables que guardaran les dades del formularai del contents.tpl
	 * Crearem una variable per cada valor que volem guardar.
	 * En aquest exemple guardem el correu i una descripció
	 * */
  var $mail = "";
  var $description = "";
  
  var $ignore_account = TRUE;

  /* The constructor just saves a copy of the config. You may add what ever you need. 
   */
   /*
    * Creem el constructor
    * */
  public function __construct ($config, $dn= NULL)
  {
    /* Include config object 
     */
     /*
      * Creem un enllaç al fitxer de configuració
      * */
    $this->config= $config;
    /*
     * Carguem el pare de la clase, dummyplug. En aquest cas el pare és plugin.
     * */
    plugin::plugin($config,$dn);
  }


  /* Execute is the function all plugins need. It fills the plugin with life and produces the output. 
   */
  function execute()
  {

    /* Initialize the smarty engine.
      */
    $smarty= get_smarty();
    /*
     * Creem un bucle que recorrerà tots els atributs (correu i comentari)
     * */
    foreach($this->attributes as $attr){
		/*
		 * Omplim la plantilla assignant els valors a partir dels atributs anteriors.
		 * */
      $smarty->assign($attr,$this->$attr);
    }
    return ($smarty->fetch (get_template_path('contents.tpl', TRUE)));
  }


  /* Validate user input 
   */
  function check()
  {
    $messages = plugin::check();
    /*
     * Si el correu que hem introduït és incorrecte guardarem un missatge
     * d'error a una variable
     * */
    if(!tests::is_email($this->mail)){
      $messages[] = msgPool::invalid($this->mail,"","","[email protected]");
    }
    /*
     * Retornem ela variable $messages, variable on tenim guardat el missatge d'error
     * */
    return($messages);
  }  


  /* Save attribute modifications back to the ldap
   */
  function save()
  {
    /* Call the save method of the mother plugin, to generate a new ldap entry
     */
    plugin::save();

    /* Write modifications bak to the ldap, uncomment these lines to save to the ldap database.
     */
	/*$ldap = $this->config->get_ldap_link();
	*$ldap->cd($this->dn);
	*$ldap->modify($this->attrs);
	*if($ldap->success()){
	*	"Ok!";
	*}else{
	*	msgPool::ldaperror($ldap->get_error(), $this->dn,LDAP_MOD, get_class());
	*}
	*/
  }
  
}
// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
?>

  • Creem una variable array anomenada $atributes on guardarem les dades del formulari, en aquest cas les úniques dades del formulari són mail i descripcio
  • Creem una variable per a cada dada que volem guardar del formulari. En aquest cas dos, mail i descripcio
  • Creem el constructor (funció --construct) on farem l'enllaç al fitxer de configuració del GOSA i carregarem el pare de la clase dummyplug, en aquest cas plugin
  • Funció execute(): inicialitzem el $smarty per crear una plantilla, creem un bucle que recorrerà pel formulari i guardarà les dades al array atributes, omplim la plantilla assignant els valors extrets anteriorment
  • Funció check(): Comprovem que el correu introduït al formulari estigui escrit correctament, si no ho està guardarem a $mesages un missatge d'error que serà retornat.
  • Funció save(): Guardem el plugin.

Editem el fitxer main.inc Per a comprovar si la variable que retorna dummyplug->check() té un missatge d'error o no. Si té el missatge el mostra per pantalla i si no guarda les dades del formulari del fitxer contents.tpl.

...
...
/* The function 'save_object' is used to act on HTML _POST and _GET variables.
     * E.g. The plugin may provide an input field.
     */
    $display= $dummyplug->save_object();

		
	/* Save plugin was requested 
     */
	if(isset($_POST['save_dummyplug'])){
		/*
		 * Guardem a la variable $msg el resultat d'executar la funció check del nostre plugin
		 * */
		$msgs = $dummyplug->check();
		/*
		 * Si a la variable $msgs no té el missatge d'error guardarem les dades del formulari del plugin.
		 * Si està el missatge d'error a la variable $msgs el mostrarem per pantalla.
		 * */
		if(!count($msgs)){
			$dummyplug->save();
		}else{
			msg_dialog::displayChecks($msgs);
		}
	}

    /* Execute plugin. This calls your plugin class and appends its output to the display variable. 
     */
    $display= $dummyplug->execute ();
...
...

  • Executem la funció check() del fitxer class_dummy.inc i guardem el resultat a la variable array $msgs
  • Mirem si l'array $msgs està buida, si ho està executarem la funció save() del fitxer class_dummy.inc.
  • Si a l'array $msgs hi han dades les mostrarem per pantalla
  • Executem el plugin.

Plugin de gestió

TODO: posar enllaços a les comandes
Repetirem l'exemple amb un plugin que no repliqui usuaris sinó l'exemple bàsic que ha de fer Alan Culvi
No fer-ho tot com llistes!
Falta l'exemple amb l'enllaç al subversion

TODO:

Explicar els fitxers bàsics d'un plugin:

  • class_NOMPLUGINManagement.inc: p.ex. class_dummyManagement.inc
  • NOMPLUGIN-list.tpl:configuració dinpamica de les llistes, per exemple dummy-list.tpl
  • NOMPLUGIN-list.xml: plantilla d'Smarty per a la llista, per exemple dummy-list.xml
  • NOMPLUGIN-filter.xml: Configuració dinàmica dels filtres, per exemple dummy-filter.xml

TODO: Provar el class_DummyManagement.inc a partir del sudoManagment, que només té una acció i el constructor (més simple que el de usuaris)

IMPORTANT: L'objectiu d'aquest apartat es crear un Plugin tonto (exemple inicial) de gestió. Si voleu fer un plugin de Gosa que no sigui de gestió consulteu l'apartat Plugin Normal

Aquí crearem un plugin de gestió basat en el plugin de ususaris. Tindrà el mateix format i la mateixa funcionalitat;

  • Creació del Directori;

Per crear un plugin tonto de gestió, utilitzarem els fitxers del plugin "Users" de plantilla. Els fitxers del nostre plugin els situarem a;

/usr/share/gosa/plugins/admin

Dins d'aquesta carpeta haurem de crear una carpeta per el nostre plugin. Per aquest exemple l'anomenarem "dummy"

$ sudo mkdir dummy && cd dummy
  • Creació dels Fitxers de Configuració;

Una vegada dins de la carpeta "dummy" hem de copiar els fitxers del plugin "Users". Aquests fitxers és troben situats a:

/usr/share/gosa/plugins/users
  • class_dummyManagement.inc
controla les accions del plugin

El primer fitxer que hem de copiar és el fitxer class_dummyManagement.inc. Se fa amb l'ordre;

 $ sudo cp /usr/share/gosa/plugins/users/class_dummyManagement.inc /usr/share/gosa/plugins/dummy

Ara que tenim una copia del fitxer hem de modificar les dades bàsiques. El codi més complex el deixarem tal com esta.

$ sudo geany /usr/share/gosa/plugins/dummy/class_dummyManagement.inc

Aqui trobareu una copia del fitxer modificat;

-Enllaç al Subversió; class_dummyManagement.inc

Primer hem de modificar la línia:

class userManagement extends management --> El Canviem a --> class dummyManagement extends management

Ara hem de modificar les línies següents;

$filter = new filter(get_template_path("user-filter.xml", true)); --> El Canviem a --> $filter = new  filter(get_template_path("dummy-filter.xml", true));

Totes les línies dins de l'apartat "// Build headpage" que començen amb $headpage hem de canviar;

userManagement --> El canviem a --> dummyManagement
  • main.inc
Controla la execucio i el temps de vida del plugin.
$ sudo cp /usr/share/gosa/plugins/users/main.inc /usr/share/gosa/plugins/dummy

Aqui trobareu una copia del fitxer modificat;

-Enllaç al Subversió; main.inc

Dins d'aquesta fitxer hem de canviar les entrades següents;

Totes les entrades userManagement --> les canviem a --> dummyManagement
  • dummy-filter.xml
Defineix els filtres disponibles que podem aplicar a les llistes accessibles per el nostre plugin

El següent fitxer que hem de copiar és el fitxer user-filter.xml i canviarem el nom a dummy-filter.xml;

$ sudo cp /usr/share/gosa/plugins/users/user-filter.xml /usr/share/gosa/plugins/dummy/dummy-filter.xml

En aquest cas no hem de modificar el contingut d'aquest fitxer.

-Enllaç al Subversió; dummy-filter.xml
  • dummy-list.xml
Plantilla que divideix com s'ha de mostrar i el que s'ha de mostrar a la part del plugin
  • El següent fitxer que hem de copiar és el fitxer user-list.xml i canviarem el nom a dummy-list.xml;
$ sudo cp /usr/share/gosa/plugins/users/user-list.xml /usr/share/gosa/plugins/dummy/dummy-list.xml

En aquest fitxer hem de canviar la línia següent;

<template>dummy-list.tpl</template> --> És troba a l'apartat "<definition>"
 -Enllaç al Subversió; dummy-list.xml
  • dummy-list.tpl
és un plantilla on especifique on es mostra les accions que pot fer l'usuari.

Ara copiem fitxer user-list.tpl i canviarem el nom a dummy-list.tpl;

$ sudo cp /usr/share/gosa/plugins/users/user-list.tpl /usr/share/gosa/plugins/dummy/dummy-list.tpl

En aquest cas no hem de modificar el contingut d'aquest fitxer.

  -Enllaç al Subversió; dummy-list.tpl
  • template.tpl

Ara copiem fitxer template.tpl(En aquest cas podem deixar el nom original);

$ sudo cp /usr/share/gosa/plugins/users/template.tpl /usr/share/gosa/plugins/dummy

En aquest cas no hem de modificar el contingut d'aquest fitxer.

  -Enllaç al Subversió; template.tpl
  • Modificar gosa.conf

Per implementar el plugin; Hem de modificar el fitxer;

geany /etc/gosa/gosa.conf.

Hem d'afegir la línia següent a l'apartat de "Addons";

<plugin acl="dummyManagement" class="dummyManagement" />
Exemple HighSchoolUserManagement

En el cas de plugin de gestió, el que he fet ha estat crear un plugin copia del de gestió d'usuaris anomenat:

HighSchoolUserManagement

Un cop és té la copia a:

/usr/share/gosa/plugins/admin/HighSchoolUsers         <-- Copia de /usr/share/gosa/plugins/admin/users

Per activar-lo es posa gosa.conf:

   <plugin acl="users/environment,users/posixAccount,users/kolabAccount,users/phpscheduleitAccount,users/proxyAccount,users/connectivity,users/pureftpdAccount...
           class="HighSchoolUserManagement" />

Creació d'un plugin "Management" bàsic

  • Creació de fitxers.

Primer cal crear el directori del plugin.

$ sudo mkdir -p /usr/share/gosa/plugins/admin/stuff/
  • Ara hem de crear els fitxers de configuració per el nostre plugin;
  • Fitxer main.inc controla la execucio i el temps de vida del plugin.

Per crear el fitxer main.inc executarem l'ordre següent:

sudo geany /usr/share/gosa/plugins/admin/stuff/main.inc

Ara copiarem el codi següent dins del fitxer buit;

<?php
/*
 * This code is part of GOsa (http://www.gosa-project.org)
 * Copyright (C) 2003-2008 GONICUS GmbH
 *
 * ID: $$Id: main.inc 14740 2009-11-04 09:41:16Z hickert $$
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/* Remove locks created by this plugin
 */
if ($remove_lock){
    if(session::is_set('stuffManagement')){
        $macl = session::get('stuffManagement');
        $macl->remove_lock();
    }
}

/* Remove this plugin from session
 */
if ( $cleanup ){
    session::un_set('stuffManagement');
}else{

    /* Create rolemanagement object on demand */
    if (!session::is_set('stuffManagement')){
        $stuffManagement= new stuffManagement ($config, $ui);
        session::set('stuffManagement',$stuffManagement);
    }
    $stuffManagement = session::get('stuffManagement');
    $display= $stuffManagement->execute();

    /* Reset requested? */
    if (isset($_GET['reset']) && $_GET['reset'] == 1){
        session::un_set ('stuffManagement');
    }

    /* Show and save dialog */
    session::set('stuffManagement',$stuffManagement);
}

// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
?>
  • Fitxer stuff-list.tpl és un plantilla on especifique on es mostra les accions que pot fer l'usuari.

Per crear el fitxer stuff-list.tpl executarem l'ordre següent:

sudo geany /usr/share/gosa/plugins/admin/stuff/stuff-list.tpl
<div id="mainlist">

  <div class="mainlist-header">
   <p>{$HEADLINE} {$SIZELIMIT}</p>
   <div class="mainlist-nav">
    <table summary="{$HEADLINE}">
     <tr>
      <td>{$ROOT}</td>
      <td>{$BACK}</td>
      <td>{$HOME}</td>
      <td>{$RELOAD}</td>
      <td class="left-border">{t}Base{/t} {$BASE}</td>
      <td class="left-border">{$ACTIONS}</td>
      <td class="left-border">{$FILTER}</td>
     </tr>
    </table>
   </div>
  </div>

  {$LIST}
</div>

<div class="clear"></div>

<input type="hidden" name="ignore">
  • Fitxer stuff-list.xml, plantilla que divideix com s'ha de mostrar i el que s'ha de mostrar a la part del plugin

Per crear el fitxer stuff-list.xml executarem l'ordre següent:

sudo geany /usr/share/gosa/plugins/admin/stuff/stuff-list.xml
<?xml version="1.0" encoding="UTF-8"?>

<list>
  <definition>
    <departmentBrowser>true</departmentBrowser>
    <departmentRootVisible>false</departmentRootVisible>
    <baseMode>false</baseMode>
    <multiSelect>true</multiSelect>
    <template>stuff-list.tpl</template>
    <module>stuff</module>
    <label>List of stuff (prova)</label>
    <defaultSortColumn>1</defaultSortColumn>

    <objectType>
      <label>Stuff</label>
      <objectClass>stuff</objectClass>
      <category>stuff</category>
      <class>stuff</class>
      <image>plugins/sudo/images/select_sudo.png</image>
    </objectType>

  </definition>

  <table>
    <layout>|20px;c|150px|250px||170px;r|</layout>
    
    <department>
      <value>%{filter:objectType(dn,objectClass)}</value>
    </department>
  
    <department>
      <value>%{filter:departmentLink(row,dn,description)}</value>
      <span>3</span>
    </department>
      

    <column>
      <value>%{filter:objectType(dn,objectClass)}</value>
    </column>

    <column>
      <label>ID</label>
      <sortAttribute>stuffID</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",stuffID)}</value>
      <export>true</export>
    </column>

    <column>
      <label>Name</label>
      <sortAttribute>stuffName</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",stuffName)}</value>
      <export>true</export>
    </column>

	<column>
      <label>Description</label>
      <sortAttribute>stuffDesc</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",stuffDesc)}</value>
      <export>true</export>
    </column>
    
    <column>
      <label>Actions</label>
      <value>%{filter:actions(dn,row,objectClass)}</value>
    </column>

  </table>

  <actionmenu>

    <action>
     <type>sub</type>
     <image>images/lists/element.png[new]</image>
     <label>Create</label>

     <action>
      <name>new_stuff</name>
      <type>entry</type>
      <image>plugins/sudo/images/select_sudo.png</image>
      <label>Default</label>
     </action>

    </action>

    <action>
      <type>separator</type>
    </action>

    <action>
      <name>remove</name>
      <type>entry</type>
      <image>images/lists/trash.png</image>
      <label>Remove</label>
    </action>

    <action>
      <type>exporter</type>
    </action>

    <action>
      <type>separator</type>
    </action>

    <action>
      <type>copypaste</type>
    </action>

    <action>
      <type>snapshot</type>
    </action>

  </actionmenu>

  <actiontriggers snapshot="true" copypaste="true">

    <action>
      <name>cp</name>
      <type>copypaste</type>
    </action>

    <action>
      <name>edit</name>
      <type>entry</type>
      <image>images/lists/edit.png</image>
      <label>Edit stuff</label>
    </action>

    <action>
      <name>snapshot</name>
      <type>snapshot</type>
    </action>

    <action>
      <name>remove</name>
      <type>entry</type>
      <image>images/lists/trash.png</image>
      <acl>sudo/sudo[d]</acl>
      <label>Remove stuff</label>
    </action>

  </actiontriggers>

</list>

  • Fitxer stuff-filter.xml defineix els filtres disponibles que podem aplicar a les llistes accessibles per el nostre plugin.

Per crear el fitxer stuff-filter.xml executarem l'ordre següent:

sudo geany /usr/share/gosa/plugins/admin/stuff/stuff-filter.xml
<?xml version="1.0" encoding="UTF-8"?>

<filterdef>

  <definition>
    <category>stuff</category>
    <initial>true</initial>
    <default>default</default>
    <scope>auto</scope>
    <attribute></attribute>
    <attribute>objectClass</attribute>
    <attribute>stuffID</attribute>
    <attribute>stuffDesc</attribute>
    <attribute>stuffName</attribute>
  </definition>

  <search>
    <tag>default</tag>
    <label>Default filter</label>
    <query>
      <backend>LDAP</backend>
      <filter>(&(objectClass=stuff)(stuffID=$))</filter>
    </query>
    <autocomplete>
      <attribute>stuffID</attribute>
      <frequency>0.5</frequency>
      <characters>3</characters>
    </autocomplete>
  </search>                                                                                                      

</filterdef>

Per crear el fitxer class_stuffManagement.inc executarem l'ordre següent:

sudo geany /usr/share/gosa/plugins/admin/stuff/class_stuffManagement.inc
<?php
/*
 * This code is part of GOsa (http://www.gosa-project.org)
 * Copyright (C) 2003-2008 GONICUS GmbH
 *
 * ID: $$Id: class_roleManagement.inc 14742 2009-11-04 13:18:33Z hickert $$
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

class stuffManagement extends management
{
    var $plHeadline     = "Stuff rules";
    var $plDescription  = "Manage stuffs";
    var $plIcon  = "plugins/sudo/images/sudo.png";

    // Tab definition 
    //protected $tabClass = "stufftabs";
    //protected $tabType = "STUFFTABS";
    //protected $aclCategory = "stuff";
    //protected $aclPlugin   = "stuff";
    protected $objectName   = "stuff";

    function __construct($config,$ui)
    {
        $this->config = $config;
        $this->ui = $ui;

        $this->storagePoints = array(get_ou("stuff", "stuffID"));

        // Build filter
        if (session::global_is_set(get_class($this)."_filter")){
            $filter= session::global_get(get_class($this)."_filter");
        } else {
            $filter = new filter(get_template_path("stuff-filter.xml", true));
            $filter->setObjectStorage($this->storagePoints);
        }
        $this->setFilter($filter);

        // Build headpage
        $headpage = new listing(get_template_path("stuff-list.xml", true));
        $headpage->setFilter($filter);

        // Add copy&paste and snapshot handler.
        if ($this->config->boolValueIsTrue("core", "copyPaste")){
            $this->cpHandler = new CopyPasteHandler($this->config);
        }
        if($this->config->get_cfg_value("core","enableSnapshots") == "true"){
            $this->snapHandler = new SnapshotHandler($this->config);
        }
        $this->registerAction("new_default", "newEntry");
        parent::__construct($config, $ui, "stuff", $headpage);
    }

    function newEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="")
    {
        $str = management::newEntry($action,$target,$all,$altTabClass,$altTabType,$altAclCategory);

        /* This entry will become the default entry */
        if($action == "new_stuff"){
            $this->tabObject->set_default(TRUE);
        }
        if(!empty($str)) return($str);
    }
} 
// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
?>

Per modificar el fitxer gosa.conf executarem l'ordre següent:

sudo geany /etc/gosa/gosa.conf
 <section name="INS Ebre">
  <plugin acl="stuff" class="stuffManagement" />
 </section>

  • O afegir el plugin a una altra secció només afegint dintre de la secció
 <plugin acl="stuff" class="stuffManagement" />
Makefile per l'instal·lació d'un plugin "Management" bàsic

# Makefile de Stuff
# 
# Aquest Makefile conté les ordres bàsiques per a instal·lar i desinstal·lar el plugin dummyplug.

PLUGINNAME=stuff
OWNER=root
GROUP=root
INSTALL=/usr/bin/install

#HTMLDIR=usr/share/gosa/html/plugins/$(PLUGINNAME)
PLUGINSDIR=usr/share/gosa/plugins/admin/$(PLUGINNAME)

MAKE=/usr/bin/make

clean:
	


install: clean
#	mkdir -p $(DESTDIR)/$(HTMLDIR)
#	mkdir -p $(DESTDIR)/$(HTMLDIR)/images
	mkdir -p $(DESTDIR)/$(PLUGINSDIR)
	
#	$(INSTALL) -o $(OWNER) -g $(GROUP) -m 755 $(HTMLDIR)/images/* $(DESTDIR)/$(HTMLDIR)/images
	$(INSTALL) -o $(OWNER) -g $(GROUP) -m 755 $(PLUGINSDIR)/* $(DESTDIR)/$(PLUGINSDIR)
	
        $(MAKE)update

uninstall:
	rm -f $(DESTDIR)/$(HTMLDIR)/images/*
	rm -rf $(DESTDIR)/$(HTMLDIR)/images/
	rm -rf $(DESTDIR)/$(HTMLDIR)/
	rm -f $(DESTDIR)/$(PLUGINSDIR)/*
	rm -rf $(DESTDIR)/$(PLUGINSDIR)/
	

update:
	update-gosa
        /etc/init.d/apache2 restart

Creació del Plugin iesebreinventory

Funció del plugin iesebreinventory:

  • Mostrar en una taula amb totes les dades que hi han guardades a la base de dades LDAP de l'obectClass iesebreinventory
  • Al editar cada element de la taula ens executi un altre plugin per a que ens mostre un formulari amb els atributs a editar i els puguem editar.
  • Guardar a la base de dades LDAP les modificacions fetes anteriorment.
  • Crear una acció per a inserir noves dades a la base de dades LDAP.

Passos:

  • Creació del directori de fitxers.
Primer cal crear el directori on guardarem el plugin.
$ sudo mkdir -p /usr/share/gosa/plugins/admin/iesebreinventory/
  • Ara hem de crear els fitxers de configuració per el nostre plugin;
  • Fitxer main.inc controla la execucio i el temps de vida del plugin.
Per crear el fitxer main.inc executarem l'ordre següent:
sudo geany /usr/share/gosa/plugins/admin/iesebreinventory/main.inc
Ara copiarem el codi següent dins del fitxer buit;
<?php
/*
 * This code is part of GOsa (http://www.gosa-project.org)
 * Copyright (C) 2003-2008 GONICUS GmbH
 *
 * ID: $$Id: main.inc 14740 2009-11-04 09:41:16Z hickert $$
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 *  	
 */

/* Eliminem els bloquejos que pugui haver creat el plugin
 */
if ($remove_lock){
    if(session::is_set('iesebreinventoryManagement')){
        $macl = session::get('iesebreinventoryManagement');
        $macl->remove_lock();
    }
}

/* Eliminar el plugin de la sessio
 */
if ( $cleanup ){
    session::un_set('iesebreinventoryManagement');
}else{

    /* Create rolemanagement object on demand */
    if (!session::is_set('iesebreinventoryManagement')){
        $iesebreinventoryManagement= new iesebreinventoryManagement ($config, $ui);
        session::set('iesebreinventoryManagement',$iesebreinventoryManagement);
    }
    $iesebreinventoryManagement = session::get('iesebreinventoryManagement');
    $display= $iesebreinventoryManagement->execute();

    /* Reset requested? */
    if (isset($_GET['reset']) && $_GET['reset'] == 1){
        session::un_set ('iesebreinventoryManagement');
    }

    /* Show and save dialog */
    session::set('iesebreinventoryManagement',$iesebreinventoryManagement);
}

// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
?>



Per crear el fitxer iesebreinventory-list.tpl executarem l'ordre següent:

sudo geany /usr/share/gosa/plugins/admin/iesebreinventory-list/iesebreinventory-list.tpl
<div id="mainlist">

  <div class="mainlist-header">
   <p>{$HEADLINE} {$SIZELIMIT}</p>
   <div class="mainlist-nav">
    <table summary="{$HEADLINE}">
     <tr>
      <td>{$ROOT}</td>
      <td>{$BACK}</td>
      <td>{$HOME}</td>
      <td>{$RELOAD}</td>
      <td class="left-border">{$ACTIONS}</td>
      <td class="left-border">{$FILTER}</td>
     </tr>
    </table>
   </div>
  </div>

  {$LIST}
</div>

<div class="clear"></div>

<input type="hidden" name="ignore">


  • Fitxer iesebreinventory-list.xml, plantilla on especifiquem l'estructura que tindrà el nostre plugin, la forma en que es mostrarà a l'usuari.

Per crear el fitxer iesebreinventory-list.xml executarem l'ordre següent:

sudo geany /usr/share/gosa/plugins/admin/iesebreinventory/iesebreinventory-list.xml
<?xml version="1.0" encoding="UTF-8"?>

<list>
  <definition>
    <departmentBrowser>true</departmentBrowser>
    <departmentRootVisible>false</departmentRootVisible>
    <baseMode>false</baseMode>
    <multiSelect>true</multiSelect>
    <template>iesebreinventory-list.tpl</template>
    <module>iesebreinventory</module>
    <label>List of iesebreInventory roles</label>
    <defaultSortColumn>1</defaultSortColumn>

    <objectType>
      <label>iesebreinventory</label>
      <objectClass>iesebreinventory</objectClass>
      <category>iesebreinventory</category>
      <class>iesebreinventory</class>
      <image>plugins/sudo/images/select_sudo.png</image>
    </objectType>

  </definition>

	<!--Taula principal del plugin -->
  <table>
    <layout>|20px;c|200px|200px|200px|200px|170px;r|</layout>

	<department>
      <value>%{filter:objectType(dn,objectClass)}</value>
    </department>

    <department>
      <value>%{filter:departmentLink(row,dn,description)}</value>
      <span>4</span>
    </department>
    
    <column>
      <value>%{filter:objectType(dn,objectClass)}</value>
    </column>
	<!-- Columna on mostrem el codi de departament -->
    <column>
      <label>Departament Code</label>
      <sortAttribute>iesebreDepartamentCode</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",iesebreDepartamentCode)}</value>
      <export>true</export>
    </column>
	<!-- Columna on mostrem el codi del material -->
	<column>
	  <label>Material Code</label>
      <sortAttribute>iesebreMaterialCode</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",iesebreMaterialCode)}</value>
      <export>true</export>
	</column>
	<!-- Columna on mostrem el codi del tipus de material -->
	<column>
	  <label>Material Type Code</label>
      <sortAttribute>iesebreMaterialTypeCode</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",iesebreMaterialTypeCode)}</value>
      <export>true</export>
	</column>
    <!-- Columna on mostrem el nom de l'objecte -->
    <column>
      <label>Object Name</label>
      <sortAttribute>iesebreObjectName</sortAttribute>
      <sortType>string</sortType>
      <value>%{filter:link(row,dn,"%s",iesebreObjectName)}</value>
      <export>true</export>
    </column>
	<!-- Columna on mostrem les accions que podem fer a les dades anteriors.
	Editar i elmiminar -->
    <column>
      <label>Actions</label>
      <value>%{filter:actions(dn,row,objectClass)}</value>
    </column>

  </table>
	<!-- Creem el menu d'accions. -->
  <actionmenu>
	<!-- Opció per a crear un nou element a la base de dades -->
    <action>
     <type>sub</type>
     <image>images/lists/element.png[new]</image>
     <label>Create</label>
	<!-- Subopció de Create on podem incertar un nou Role -->
     <action>
      <name>new</name>
      <type>entry</type>
      <image>plugins/sudo/images/select_sudo.png[new]</image>
      <label>Role</label>
     </action>
	<!-- Subopció de Create on podem incertar un nova entrada-->
     <action>
      <name>new_default</name>
      <type>entry</type>
      <image>plugins/sudo/images/select_sudo.png</image>
      <label>Default</label>
     </action>

    </action>
	<!-- Separador, linia entre Create i Remove -->
    <action>
      <type>separator</type>
    </action>
	<!-- Opció per eliminar un element de la taula -->
    <action>
      <name>remove</name>
      <type>entry</type>
      <image>images/lists/trash.png</image>
      <label>Remove</label>
    </action>
	<!-- Opció per exportar un o varis elements de la taula -->
    <action>
      <type>exporter</type>
    </action>
	<!-- Serparador entre l'opció exportar i copiar-pegar -->
    <action>
      <type>separator</type>
    </action>
	<!-- Opció per a copiar i pegar dades -->
    <action>
      <type>copypaste</type>
    </action>
	<!-- Opció per fer una captura de pantalla -->
    <action>
      <type>snapshot</type>
    </action>

  </actionmenu>

  <actiontriggers snapshot="true" copypaste="true">

    <action>
      <name>cp</name>
      <type>copypaste</type>
    </action>

    <action>
      <name>edit</name>
      <type>entry</type>
      <image>images/lists/edit.png</image>
      <label>Edit iesebreinventory role</label>
    </action>

    <action>
      <name>snapshot</name>
      <type>snapshot</type>
    </action>

    <action>
      <name>remove</name>
      <type>entry</type>
      <image>images/lists/trash.png</image>
      <acl>sudo/sudo[d]</acl>
      <label>Remove Sudo role</label>
    </action>

  </actiontriggers>

</list>


Taula amb 6 columnes:
  • Columna 1: Selecciona un element o varis
  • Columna 2: Mostrar el codi departament
  • Columna 3: Mostrar el codi material
  • Columna 4: Mostrar el codi de tipus material
  • Columna 5: Mostrar el nom de l'objecte
  • Columna 6: Accions que podem fer sobre l'element, editar o eliminar.
Menú d'accions amb:
  • Opció per crear element:
  • Crear un nou rol.
  • Crear una nova entrada.
  • Opció per eliminar un o varis elements de la taula
  • Opció per extreure un o varis element de la taula
  • Opció per copiar i pegar.
  • Opció per fer una captura de pantalla.


Per crear el fitxer iesebreinventory-filter.xml executarem l'ordre següent:

sudo geany /usr/share/gosa/plugins/admin/iesebreinventory/iesebreinventory-filter.xml
<?xml version="1.0" encoding="UTF-8"?>

<filterdef>

  <definition>
    <category>iesebreinventory</category>
    <initial>true</initial>
    <default>default</default>
    <scope>one</scope>
    <attribute>objectClass</attribute>
    <attribute>iesebreDepartamentCode</attribute>
    <attribute>iesebreMaterialCode</attribute>
    <attribute>iesebreMaterialTypeCode</attribute>
    <attribute>iesebreObjectName</attribute>
  </definition>

  <search>
    <tag>default</tag>
    <label>Default filter</label>
    <query>
      <backend>LDAP</backend>
      <filter>(&(objectClass=iesebreinventory)(iesebreDepartamentCode=$))</filter>
    </query>
    <autocomplete>
      <attribute>iesebreDepartamentCode</attribute>
      <frequency>0.5</frequency>
      <characters>3</characters>
    </autocomplete>
  </search>

</filterdef>


Per crear el fitxer class_iesebreinventoryManagement.inc executarem l'ordre següent:

sudo geany /usr/share/gosa/plugins/admin/iesebreinventory/class_iesebreinventoryManagement.inc
<?php

<?php

class iesebreinventoryManagement extends management
{
    var $plHeadline     = "iesebreInventory";
    var $plDescription  = "IES Ebre inventory";
    var $plIcon  = "plugins/iesebreInventory/images/inventory.png";

    // Definim els tabs
    protected $tabClass = "iesebreinventorytabs";
    protected $tabType = "IESEBREINVENTORYTABS";
    //protected $aclCategory = "sudo";
    //protected $aclPlugin   = "sudo";
    //Definim l'objecte
    protected $objectName   = "iesebreinventory";

    function __construct($config,$ui)
    {
    	//Carguem la configuració del gosa, arxiu gosa.conf
        $this->config = $config;
        $this->ui = $ui;

        $this->storagePoints = array(get_ou("iesebreinventory", "iesebreObjectCode"));

        // Creem el filtratge a partir del fitxer iesebreinventory-filter.xml
        if (session::global_is_set(get_class($this)."_filter")){
            $filter= session::global_get(get_class($this)."_filter");
        } else {
            $filter = new filter(get_template_path("iesebreinventory-filter.xml", true));
            $filter->setObjectStorage($this->storagePoints);
        }
        $this->setFilter($filter);

        // Build headpage
        $headpage = new listing(get_template_path("iesebreinventory-list.xml", true));
        $headpage->setFilter($filter);

        // Add copy&paste and snapshot handler.
        if ($this->config->boolValueIsTrue("core", "copyPaste")){
            $this->cpHandler = new CopyPasteHandler($this->config);
        }
        if($this->config->get_cfg_value("core","enableSnapshots") == "true"){
            $this->snapHandler = new SnapshotHandler($this->config);
        }
        $this->registerAction("new_default", "newEntry");
        parent::__construct($config, $ui, "sudo", $headpage);
    }
}

?>


Creem una nova classe anomenada iesebreinventoryManagement i el seu pare es management.
Definim els tabs i el objectName per al plugin que utilitzarem a l'hora de editar un element de la taula.
Executem el constructor.
  • Guardem la configuració del fitxer /etc/gosa/gosa.conf
  • Creem un filtratge a partir del fitxer iesebreinventory-filter.xml creat anteriorment.


  • Editem el fitxer /etc/gosa/gosa.conf especificant una nova classe anomenada iesebreinventoryManagement.
<plugin acl="department" class="iesebreinventoryManagement"/>

Sub-plugin dintre de iesebreinventory per a mostrar un formulari a l'hora d'editar un element de la taula iesebreinventory

  • Editar el fitxer /etc/gosa/gosa.conf
Editem el fitxer gosa.conf per afegir el nou plugin i els tabs corresponents.
  • Afegir el plugin:
<plugin acl="iesebreinventory" class="iesebreinventoryManagement"/>

  • Afegir els tabs
<!--iesebre dialog-->
  <iesebreinventorytabs>
  <tab class="iesebreinventory" name="Generic"/>
  </iesebreinventorytabs>

  • Crear el fitxer class_iesebreinventoryGeneric.inc
<?php

/* Create a class (name must be unique inside GOsa) which extends plugin. The plugin base
 *  class contains all methods that are used by GOsa and it provides the mechanism to load data
 *  from LDAP to local variables and prepare the save to ldap routine for you. 
 */
class iesebreinventory extends plugin
{

  /* These contain attributes to be loaded. We're not creating an LDAP plugin currently, so we don't
   *  care... 
   */
	
  var $plHeadline = "iesebreinventory plugin";
  var $plDescription = "iesebreinventory plugin";
    
  var $ignore_account = TRUE;

  /* Creem el construct utilitzant la configuració del pare i ho guardem en la variable config
  */
  public function __construct ($config, $dn= NULL)
  {
    /* Include config object 
     */
    $this->config= $config;
  }
  
  function execute()
  {
        /* Inicialitzem el smarty, per a processar les plantilles
         */
        $smarty= get_smarty();

        /* Let smarty fetch and process the page. Always seperate PHP and HTML as much as
         * you can. 
         * If you've problems telling smarty the correct location of your template file
         *  try to use it the this way 'get_template_path('contents.tpl', TRUE, dirname(__FILE__))'
         *  the template will then be found in the current folder too.
         */
        
         /*echo "ou=iesebreInventory,ou=All,".$this->config->current['BASE'];
        echo "<br>";*/
        /*Creem un enllaç al ldap*/
        $ldap = $this->config->get_ldap_link();
		
		/*Anem a l'apartat del nostre objecte, iesebreinventory*/
        $ldap->cd("ou=iesebreInventory,ou=All,".$this->config->current['BASE']);
		
		/*Fem una consulta al objectClass iesebreinventory agafant totes les dades a 
		 * partir de l'atribut iesebreObjectCode
		 * */
		$ldap->search("(&(objectClass=iesebreinventory)(iesebreObjectCode=1))",array("cn", "iesebreLocation1Name", "iesebreDepartamentCode", "iesebreFinalCode", "iesebreMaterialCode", "iesebreMaterialTypeCode", "iesebreLocation1Code", "iesebreDepartmentName", "iesebreMaterialName", "iesebreOriginCode", "iesebreOriginName", "iesebreLocation2Code", "iesebreLocation2Name", "iesebreTypeMaterialName", "iesebreVendorCode", "iesebreDescription", "iesebreComputerBusiness", "iesebreDate"));
		//echo "Elements retornats: " .$ldap->count();
		//Guardem el resultat de la consulta a l'array attributes
		
		/* Print out each returned object.
     	* print_a is a debugging function and is not for productive use!
     	*/
    	
		/*while($attrs = $ldap->fetch()){
      		print_a($attrs);
	    }*/
		
		/*@DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,"prova!");
		@DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,print_r($this->attributes_return));
		print_a($this->attributes_return);
		*/
		//$atributs= array();
		/*$atributs= $ldap->fetch();
		echo "Elements retornats: " .count($atributs);
	    */
		
	    while($atributs= $ldap->fetch()){
			/*
			 * Omplim la plantilla assignant els valors a partir de l'array.
			 * */
	    	//@DEBUG (DEBUG_ERROR, __LINE__, __FUNCTION__, __FILE__,"attr: ".print_r($atribut));
	    	
	    	//print_a($atributs);
	    	//echo "<br>";
	    	foreach ($atributs as $key => $value) {
	    		$smarty->assign($key,$value[0]);
	    	}
	    	
	    }
	    
         /*OBLIGATORIS*/
         
         /*
         $smarty->assign ("iesebreDepartamentCode","ies");
         $smarty->assign ("iesebreFinalCode","ies");
         $smarty->assign ("iesebreMaterialCode","ies");
         $smarty->assign ("iesebreMaterialTypeCode","ies");
         $smarty->assign ("iesebreObjectName","ies");
         */
         /*OPCIONALS*/
         $smarty->assign ("iesebreLocation1Name","");
         $smarty->assign ("iesebreDepartmentName","ies");
         $smarty->assign ("iesebreMaterialName","ies");
         $smarty->assign ("iesebreOriginCode","ies");
         //$smarty->assign ("iesebreOriginName","ies");
         $smarty->assign ("iesebreLocation2Code","ies");
         $smarty->assign ("iesebreLocation2Name","ies");
         $smarty->assign ("iesebreProvidorID","ies");
         $smarty->assign ("iesebreTypeMaterialName","ies");
         $smarty->assign ("iesebreVendorCode","ies");
         
         /*NOUS*/
         //$smarty->assign ("iesebreDescription","ies");
         $smarty->assign ("iesebreLocation1Code","ies");
         $smarty->assign ("iesebreLocation1Name","ies");
         $smarty->assign ("macAddress","ies");
         $smarty->assign ("ipHostNumber","ies");
         $smarty->assign ("iesebreProvidorName","ies");
         $smarty->assign ("iesebreCenterCode","ies");
        
         /*DEFINICIÓ DELS MENÚS DESPLEGABLES*/
         
			/*Departments*/
         
			 $smarty->assign('DepartmentCodes', array(
									07=> 'Edificació i Obra Civil',
									08 => 'Electricitat i Electrònica',
									02=> 'Administració',
									06 => 'Comerç i Marquèting',
									09 => 'Fusta i Moble (Casa oficis)',
									14 => 'Fabricació Mecànica',
									16 => 'Sanitat',
									17 => 'Serveis Sòcioculturals a la comunitat',
									19 => 'Manteniment i Serveis a la producció',
									20 => 'Familia Informàtica',
									62 => 'Formació i orientació laboral',
									70 => 'Anglès',
									71 => 'Castellà',
									72 => 'Català',
									73 => 'Ciències Experimentals',
									74 => 'Ciències Socials',
									75 => 'Educació Física',				
									76 => 'Matemàtiques',
									77 => 'Música',
									78 => 'Tecnologia',
									79 => 'Vísual i Plàstica',								
									80 => 'Pintura (Casa oficis)',
									81 => 'Orientació Psicopedagògica',
									99 => 'Centre')
									
									);
									
									
			$smarty->assign('DefaultDepartment', 20);
			
			
			
			
			/*Materials*/
			
			$smarty->assign('MaterialCodes', array(
									35=> 'Audiovisuals-Comunicació',
									34 => 'Material de cuina',
									31 => 'Multimèdia',
									33 => 'Reprografia',
									30 => 'Llibres i revistes',
									37 => 'Material Oficina',
									36 => 'Material Didàctic',
									38 => 'Il·luminació',
									39 => 'Mobiliari',
									40 => 'Equipament',
									41 => 'Màquines escriure',
									42 => 'Climatització',
									43 => 'Material contra incendis',
									44 => 'Material Seguretat',
									68 => 'Informàtica programari',
									69 => 'Informàtica maquinari')				
									);
									
									
			$smarty->assign('DefaultMaterial', 69);
			
			
			
			
			/*Material Type*/
			
			$smarty->assign('MaterialTypeCodes', array(
									12=> 'TAMBURET',
									11 => 'CADIRES I BANCS',
									14 => 'PRESTATGES',
									15 => 'PISSARRES',
									13 => 'ARMARIS-GUIXETES ("TAQUILLES")',
									10 => 'CDROM',
									16 => 'PENJADORS',
									17 => 'ARXIVADORS',
									18 => 'PERSIANES-CORTINES',
									19 => 'MOBILIARI ALTRE',
									20 => 'TAULELLS ANUNCIS',
									10 => 'TAULES',
									10 => 'ORDINADOR',
									11 => 'IMPRESSORES',
									11 => 'DVD',
									12 => 'SWITCH',
									13 => 'SCANNER',
									14 => 'MULTIPLEXOR',
									15 => 'SAI',
									16 => 'ROUTER',
									17 => 'JETDIRECT',
									21 => 'PEN DRIVE',
									22 => 'H.D. EXTRAIBLE',
									23 => 'MP3')
									);
									
									
			$smarty->assign('DefaultMaterialType', 12);
			
			
			
			
			
			/*Origin Code*/
			
			$smarty->assign('OriginCodes', array(
			
									06 => 'C. OCUPACIONAL',
									07 => 'CENTRE',
									08 => 'DEP. ENSENYAMENT',
									09 => 'AMPA',
									10 => 'NS/NC',
									11 => 'GENERALITAT CATALUNYA',
									12 => 'LA CAIXA')
									);
									
									
			$smarty->assign('DefaultOrigin', 01);
		
			
			/*Vendor Code*/
			
			$smarty->assign('VendorCodes', array(
			
									51429 => 'ENSENYAMENT',
									51431 => 'NS/NC',
									51434 => 'ISLASOFT',
									51435 => 'MECASOFT PRO',
									51436 => 'ACNIELSEN',
									51437 => 'GRUPO ZETA MULTIMEDIA',
									51438 => 'BARCELONA MULTIMEDIA',
									51440 => 'DIPUTACIO BARCELONA',
									51441 => 'MICROSOFT',
									51442 => 'NUTRIBEN',
									51443 => 'AUTODESK',
									51444 => 'PC PLUS',
									51445 => 'JASC SOFTWARE',
									51446 => 'ADOBE',
									51447 => 'DAPP',
									51448 => 'CYPE',
									51449 => 'GENIUS',
									51450 => 'COREL',
									51451 => 'ASUNICAD',
									51452 => 'DAISA',
									51453 => 'GENERALITAT DE CATALUNYA',
									51454 => 'UNIVERSITATS',
									51455 => 'EDIT. CARROGGIO DURVAN',
									51456 => 'EDIT. HERDER',
									51457 => 'IRIS',
									51458 => 'ALECOP',
									51459 => 'KODAK',
									51460 => 'COMPAQ',
									51461 => 'SYMANTEC',
									51462 => 'ACD SYSTEMS',
									51463 => 'MACROMEDIA',
									51464 => 'PINNACLE SYSTEMS',
									51465 => 'PERIODICO',
									51466 => 'AHEAD',
									51467 => 'HACHETTE  MULTIMRDIA',
									51468 => 'PARSEC',
									51469 => 'JOSTENS LEARNING',
									51470 => 'PROA',
									51471 => 'ESPASA',
									51472 => 'DIVERCAT',
									51473 => 'MICRONET',
									51474 => 'SCANSOFT',
									51475 => 'WOLFRAM',
									51476 => 'FATEK',
									51477 => 'FAMIC',
									51478 => 'PASSPORT',
									51479 => 'LEX NOVA',
									51480 => 'MINISTERIO DE CIENCIA Y TECNO',
									51481 => 'CLONIC',
									51482 => 'AGI',
									51483 => 'BEEP',
									51484 => 'COMELTA',
									51485 => 'TELEFONICA',
									51486 => 'SAUTER IBERICA',
									51487 => 'CAMINERO',
									51488 => 'EMCO',
									51489 => 'PANDA',
									51490 => 'HYPER TECHNOLOGIES',
									51491 => 'OSCAR CASTELL',
									51492 => 'JUVINTER',
									51493 => 'ID_GROUP',
									51494 => 'APD',
									51495 => 'SOFTCATALA',
									51496 => 'MC GRAW HILL',
									51497 => 'LA CAIXA',
									51498 => 'XARXA.NET',
									51499 => 'EDIT.SANTILLANA',
									51500 => 'EDIT.EDEBE')
									);
									
									
			$smarty->assign('DefaultVendor', 07);
			
			/*Location1 Code*/
			
			$smarty->assign('Location1Codes', array(

								10		=> '10 		| Aula CAD 1PM',
								11		=> '11 		| Lab.Sanitari 1',
								12		=> '12 		| Lab.Sanitari 2',
								13		=> '13 		| Lab. Física-Química',
								14		=> '14 		| Lab.Farmàcia',
								15		=> '15 		| Aula Música',
								16		=> '16 		| 4T ESO A',
								17		=> '17 		| 4T ESO B',
								18		=> '18 		| Lab. Ciències',
								19.1	=> '19.1 	|', 	
								19.2	=> '19.2 	|',	
								20.1	=> '20.1 	|', 	
								20.2	=> '20.2 	| INFORMÀTICA',
								20.3 	=> '20.3 	| INFORMÀTICA',
								20.4 	=> '20.4 	| INFORMÀTICA',
								20.5	=> '20.5 	| 2n Projectes Construcció',
								20.5	=> '20.5 	| bis	Magatzem Projectes',
								20.6	=> '20.6 	|',
								21		=> '21 		| 2n C. Salut-Científic',
								22 		=> '22 		| 1r C. Salut',
								23 		=> '23 		| 1r Econòmic',
								24 		=> '24 		| 2n Econòmic',
								25		=> '25 		| 2n Humanitats',
								26		=> '26 		| 2n Tecnològic',
								27		=> '27 		|',
								28 		=> '28 		| 4t ESO D',
								29		=> '29 		| 1r Humanitats',
								30		=> '30 		| Secretariat',
								31		=> '31 		| Administració i Finances',
								32 		=> '32 		| Gestió Administrativa',
								33 		=> '33 		| Aula Informàtica',
								34		=> '34 		| Educació Infantil 1',
								35 		=> '35 		| Educació Infantil 2',
								36 		=> '36 		| Gestió Comercial i Màrqueting',
								36.2	=> '36.2	| Magatzem Comerç',
								ADM		=> 'ADM 	| Administració',
								AF		=> 'AF  	| Aula Fotografia',
								AL1		=> 'AL1 	| Altell 1 Electricitat',
								AL1-1	=> 'AL1bxs1 | Altell 1 baixos 1',
								AL1-2	=> 'AL1bxs2	| Altell 1 baixos 2',
								AL2		=> 'AL2 	| Altell 2 Electricitat',
								AM		=> 'AM  	| Aula Meteorologia',
								ANTD	=> 'ANTD 	| Anterior direcció',
								AS1		=> 'AS1 	| Serveis dones planta baixa',
								AS10	=> 'AS10 	| Serveis professors planta 1ª',
								AS11	=> 'AS11 	| Serveis homes planta 1ª',
								AS12	=> 'AS12 	| Serveis professors planta 1ª',
								AS13	=> 'AS13 	| Serveis dones planta   1ª',
								AS14	=> 'AS14 	| Serveis homes planta 1ª',
								AS15	=> 'AS15	| Serveis homes planta 1ª',
								AS2		=> 'AS2	 	| Serveis homes planta baixa',
								AS20	=> 'AS20 	| Serveis homes planta 2ª',
								AS21	=> 'AS21 	| Serveis dones planta 2ª',
								AS30	=> 'AS30 	| Serveis dones planta 3ª',
								AV		=> 'AV 		| Aula Vídeo',
								BI		=> 'BI 		| Biblioteca',
								CAPE	=> 'CAPE 	| Cap Estudis',
								CONS	=> 'CONS 	| Consergeria',
								COOP	=> 'COOP 	| Cooperativa',
								DEPADC	=> 'DEPADC 	| Dep. Administració i Comerç',
								DEPCAS	=> 'DEPCAS 	| Dep. Castellà',
								DEPCAT	=> 'DEPCAT 	| Dep. Català',
								DEPCIE	=> 'DEPCIE 	| Dep.Magatzem',
								DEPCIE1	=> 'DEPCIE1 | Dep. Ciències',
								DEPEDIFI=> 'DEPEDIFI| OBRESCIVIL	',
								DEPINF	=> 'DEPINF 	| Dep. Informàtica',
								DEPLES	=> 'DEPLES 	| Dep. Llengues estrangeres',
								DEPMUS	=> 'DEPMUS 	| Dep. Música',
								DEPSOCI	=> 'DEPSOCI | dep. socials',
								DEPSSC	=> 'DEPSSC 	| Dep. Serv. Soc. a la Comunitat',
								DIR		=> 'DIR	 	| Direcció',
								E1		=> 'E1 		| 3R ESO A',
								E10		=> 'E10 	| 2N ESO B',
								E10BIS	=> 'E10BIS 	| Dep. FOL',
								E11		=> 'E11	 	| 2N ESO C',
								E12		=> 'E12 	| Taller Electrònica',
								E12BIS	=> 'E12BIS 	| Taller Electrònica 2',
								E13		=> 'E13 	| 3R ESO D',
								E14		=> 'E14 	| Aula CMC',
								E15		=> 'E15 	| Laboratori Mecànica',
								E15BIS	=> 'E15BIS 	| Laboratori Pneumàtica/Hidràulica',
								E16		=> 'E16 	| Laboratori ESO',
								E17		=> 'E17 	| Aula Informàtica',
								E18		=> 'E18 	| 4T ESO C',
								E2		=> 'E2 		| 3R ESO B',
								E3		=> 'E3 		| 3R ESO C',
								E4		=> 'E4 		| 1R ESO A',
								E5		=> 'E5 		| 1R ESO D',
								E6		=> 'E6 		| 1R ESO B',
								E7		=> 'E7 		| 1R ESO C',
								E8		=> 'E8 		| 2N ESO D',
								E9		=> 'E9 		| 2N ESO A',
								FORA	=> 'FORA 	| CENTRE CESSIO',
								G1		=> 'G1 		| Gimnàs centre',
								G2		=> 'G2 		| Estadi 1',
								G3		=> 'G3 		| Estadi 2',
								MANT.INFOR	=> 'MANT.INFOR | MANT. INFORMATICA',
								PAS-0	=> 'PAS-0 	| Passadís planta baixa',
								PAS-1	=> 'PAS-1 	| Passadís planta 1ª',
								PAS-2	=> 'PAS-2 	| Passadís planta 2ª',
								PAS-3	=> 'PAS-3 	| Passadís planta 3ª',
								PSI		=> 'PSI 	| Despatx Psicòlegs',
								SCC 	=> 'SCC 	| Servei Català de Col·locació',
								SD		=> 'SD 		| Sala Actes',
								SDbis	=> 'SDbis 	| Cabina Sala Actes',
								SEC		=> 'SEC 	| Secretaria',
								SPRO	=> 'SPRO 	| Sala Professors',
								SR1		=> 'SR1 	| Sala Reunions 1',
								SR2		=> 'SR2 	| Sala Reunions 2',
								SV1		=> 'SV1 	| Sala Visites 1',
								SV2		=> 'SV2 	| Sala Visites 2',
								TE1		=> 'TE1 	| Taller Electricitat',
								TE2		=> 'TE2 	| Taller Electricitat',
								TE3		=> 'TE3 	| Taller Electricitat',
								TE4		=> 'TE4 	| Taller Electricitat',
								TE4MAT	=> 'TE4MAT	| Taller Elect. Manteniment',
								TE5		=> 'TE5 	| Taller Electricitat',
								TEMAG	=> 'TEMAG 	| Magatzem Taller Elect.',
								TF		=> 'TF 		| Taller fusta',
								TM1		=> 'TM1 	| Taller Metall 1',
								TM2		=> 'TM2 	| Taller Metall 2 soldadura')
								);
									
									
			$smarty->assign('DefaultLocation1', 07);
			
			/*Location2 Code*/
			
			$smarty->assign('Location2Codes', array(
									01=> 'Armari 1',
									02 => 'Armari2',
									03 => 'Aula',
									04 => 'Despatx',
									05 => 'Pas-2',
									06 => 'Pas-1',
									07 => 'Pas-3')
									);
									
									
			$smarty->assign('DefaultLocation2', 07);
         
        return ($smarty->fetch (get_template_path('generic.tpl', TRUE)));
  		
  }

}

?>

  • Crear el fitxer tabs_iesebreinventory.inc
<?php
/*
 * This code is part of GOsa (http://www.gosa-project.org)
 * Copyright (C) 2003-2008 GONICUS GmbH
 *
 * ID: $$Id: tabs_group.inc 9275 2008-03-04 07:29:22Z cajus $$
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

class iesebreinventorytabs extends tabs
{
  function iesebreinventorytabs($config, $data, $dn)
  {
    tabs::tabs($config, $data, $dn,"iesebreinventory");
    $this->addSpecialTabs();
  }

  function set_default($state)
  {
    if(isset($this->by_object['iesebreinventory'])){
      $this->by_object['iesebreinventory']->set_default($state);
    }
  }

  function save($ignore_account= FALSE)
  {
    //$baseobject= $this->by_object['iesebreinventory'];

    /* Check for new 'dn', in order to propagate the
       'dn' to all plugins */
    //$cn      = preg_replace('/,/', '\,', $baseobject->get_cn()); 
    //$cn      = preg_replace('/"/', '\"', $cn); 
    //$new_dn= 'cn='.$cn.','.iesebreinventory::get_iesebreinventoryers_ou($baseobject->config);

    /* Move group? */
    //if ($this->dn != $new_dn){

      /* Write entry on new 'dn' */
      //if ($this->dn != "new"){
        //$baseobject->update_acls($this->dn,$new_dn);
        //$baseobject->move($this->dn, $new_dn);
        //$this->by_object['iesebreinventory']= $baseobject;
      //}

      /* Happen to use the new one */
      //$this->dn= $new_dn;
    //}
    //$ret= tabs::save();
    //return $ret;*/
  }
}
// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
?>

  • Crear el fitxer generic.tpl
<head>

<!--SCRIPT UPDATE

Script en JavaScript que actualitzarà el Camp centercode, quan és 
tria una opció d'un menú desplegable o és modifica el camp iesebreFinalCode

L'script s'ha de col·locar entre "literal" perque sinò, Smarty interpreta 
el codi de manera incorrecta-->

<SCRIPT TYPE="text/javascript">

{literal}
function updateCode(){
	document.getElementById('centercode').value=document.getElementById('depcode').value + "-" + document.getElementById('matcode').value + "-" + document.getElementById('mattypecode').value + "-" + document.getElementById('fincode').value;
}
		

{/literal}

</SCRIPT>

</head>

<body onload="updateCode();">



<!--TÍTOL: Títol Principal del Formulari-->

<h3>{t}Generic{/t} - {t}global defaults{/t}</h3>
 <tr><td style="width:100%;"colspan="2"><hr></td></tr>

<!--TAULA: Taula on se situarà tot els camps del Formulari-->
<table style="width:100%;" summary="{t}Generic{/t} - {t}global defaults{/t}">

<!--CENTER CODE:-->

<!--1a Definició dels Títols dels camps del Center Code:-->
<tr>
	<th align="left">Center Code: </th>
	<th align="left" colspan="1">Department Code{$must}</th>
	<th align="left" colspan="1">Material Type Code{$must}</th>
	<th align="left" colspan="1">Center Code</th>
	
</tr>

<!--1a Definició dels Menús desplegables relacionats amb els apartats definits dins de l'apartat de Center Code-->

<tr>

		<td></td>
	
		<td>{html_options id="depcode" name=Departments options=$DepartmentCodes selected=$iesebreDepartamentCode onChange="updateCode();"}</td>
	
		<td>{html_options id="matcode" name=MaterialTypes options=$MaterialTypeCodes selected=$iesebreMaterialTypeCode onChange="updateCode();"}</td>
		
		
		<!--Camp que mostra els valors Introduïts als camps del Codi del Centre-->
		<td><input type="text" id="centercode" name="centercode" readonly></td>
	
</tr>

<!--2a Definició dels Títols dels camps del Center Code:-->

<tr>
	<th></th>
	<th align="left" colspan="1">Material Code{$must}</th>
	<th align="left" colspan="1">Final Code{$must}</th></tr>
	
<tr></tr>

<!--2a Definició dels Menús desplegables relacionats amb els apartats definits dins de l'apartat de Center Code-->


<tr>
	<td></td>
	
	<!--Menú Desplegable amb una llista de Codis de Materials-->
	
	<td>{html_options id="mattypecode" name=Materials options=$MaterialCodes selected=$iesebreMaterialCode onChange="updateCode();"}</td>
	
	<td><input type="text" id="fincode" size="10" name="iesebreFinalCode"  value="{$iesebreFinalCode}" onChange="updateCode();"}></td></tr>
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>


<!--OBJECTNAME:-->	

<!--Títol apartat ObjectName-->

<tr><th align="left" colspan="1">Object Name</th>

	<!-- Definició del Camp iesebreObjectName-->

	<td><input type="text" size="50" name="cn" value="{$cn}"></td></tr>
	
		<tr><td style="width:100%;"colspan="5"><hr></td></tr>
		
		
<!--DESCRIPTION:-->	

<!--Títol apartat Description-->
		
<tr><th align="left">Description</th>

	<!-- Definició del Camp iesebreDescription-->
	
	<td colspan="5"><input type="text" size="50" name="iesebreDescription" value="{$iesebreDescription}"></td></tr>
	
		<tr><td style="width:100%;"colspan="5"><hr></td></tr>
		
		
		
<!--ORIGIN:-->	

<!--Títol apartat Origin i Títols dels Camps-->
	
<tr>
	<th align="left">Origin: </th>
	<th align="left" colspan="1">Origin Code</th>
	
	
	<!-- Definició dels Camps de Origins-->

<tr>
	<td></td>
	
		<!--Menú desplegable per OriginCode-->
	<td>{html_options name=Origin options=$OriginCodes selected=$iesebreOriginName}</td>
	
		<tr><td style="width:100%;"colspan="5"><hr></td></tr>
		
		
<!--VENDOR:-->	

<!--Títol apartat Vendor i Títols dels Camps-->
	
<tr>
	<th align="left">Vendor: </th>
	<th align="left" colspan="1">Vendor Code</th></tr>
	
<tr>
	<td></td>
	
	<!--Menú desplegable amb llista de Vendors-->
	<td>{html_options name=Vendor options=$VendorCodes selected=$DefaultVendor}</td>
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>
	

<!--LOCATIONS:-->	

<!--Títol apartat Locations i Títols dels Camps-->

	
<tr>
	<th align="left">Lloc: </th>
	<th align="left" colspan="1">Location1 Code</th>
	<th align="left" colspan="1">Location2 Code</th>

	
	<!--Definició dels Camps de Locations-->
	
<tr>
	<td></td>
	
	<!--Menú desplegable amb llista de Codis de Aules-->
	<td>{html_options name=Location1 options=$Location1Codes selected=$DefaultLocation1}</td>
	
	<!--Menú desplegable amb llista de Codis de Aules-->
	<td>{html_options name=Location2 options=$Location2Codes selected=$DefaultLocation2}</td>
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>
	

<!--Tanquem taula del Formulari-->	
</table>
</body>



Creació d'una Plantilla de Formulari

Creació de les Plantilles per el plugin iesebreinventory;

  • S'utilitzen per introduir i modificar dades de objectes guardades en el servidor LDAP.


Plantilla Genèric

En aquest apartat crearem un formulari per puguer modificar i afegir entrades al nostre plugin de iesebreInventory; Aquest plugin serà un plugin genèric que utilitzarem pels objectes que no siguin workstations ni impressores.   Primer hem de crear un fitxer on col-locarem  el codi de la plantilla, aquest fitxer estarà situat dins de la carpeta del nostre plugin;

$ sudo geany /usr/share/gosa/plugins/admin/iesebreinventory/generic.tpl

El codi del formulari, es el següent;

<head>

<!--SCRIPT UPDATE

Script en JavaScript que actualitzará  el Camp centercode, quan és 
tria una opció d'un menú desplegable o és modifica el camp iesebreFinalCode

L'script s'ha de col·locar entre "literal" perque sinó, Smarty interpreta 
el codi de manera incorrecta-->

<SCRIPT TYPE="text/javascript">

{literal}
function updateCode(){
	document.getElementById('centercode').value=document.getElementById('depcode').value + "-" + document.getElementById('matcode').value + "-" + document.getElementById('mattypecode').value + "-" + document.getElementById('fincode').value;
}
		

{/literal}

</SCRIPT>

</head>

<body onload="updateCode();">



<!--TÍTOL: Títol Principal del Formulari-->

<h3>{t}Generic{/t} - {t}global defaults{/t}</h3>
 <tr><td style="width:100%;"colspan="2"><hr></td></tr>

<!--TAULA: Taula on se situará  tot els camps del Formulari-->
<table style="width:100%;" summary="{t}Generic{/t} - {t}global defaults{/t}">

<!--CENTER CODE:-->

<!--1a Definició dels Títols dels camps del Center Code:-->
<tr>
	<th align="left">Center Code: </th>
	<th align="left" colspan="1">Department Code{$must}</th>
	<th align="left" colspan="1">Material Type Code{$must}</th>
	<th align="left" colspan="1">Center Code</th>
	
</tr>

<!--1a Definició  dels Menús desplegables relacionats amb els apartats definits dins de l'apartat de Center Code-->

<tr>

		<td></td>
	
		<td>{html_options id="depcode" name=Departments options=$DepartmentCodes selected=$iesebreDepartamentCode onChange="updateCode();"}</td>
	
		<td>{html_options id="matcode" name=MaterialTypes options=$MaterialTypeCodes selected=$iesebreMaterialTypeCode onChange="updateCode();"}</td>
		
		
		<!--Camp que mostra els valors Introduïts als camps del Codi del Centre-->
		<td><input type="text" id="centercode" name="centercode" readonly></td>
	
</tr>

<!--2a Definició dels Títols dels camps del Center Code:-->

<tr>
	<th></th>
	<th align="left" colspan="1">Material Code{$must}</th>
	<th align="left" colspan="1">Final Code{$must}</th></tr>
	
<tr></tr>

<!--2a Definició dels Menús desplegables relacionats amb els apartats definits dins de l'apartat de Center Code-->


<tr>
	<td></td>
	
	<!--Menú Desplegable amb una llista de Codis de Materials-->
	
	<td>{html_options id="mattypecode" name=Materials options=$MaterialCodes selected=$iesebreMaterialCode onChange="updateCode();"}</td>
	
	<td><input type="text" id="fincode" size="10" name="iesebreFinalCode"  value="{$iesebreFinalCode}" onChange="updateCode();"}></td></tr>
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>


<!--CN:-->	

<!--Títol apartat cn-->

<tr><th align="left" colspan="1">Object Name</th>

	<!-- Definició del Camp cn-->

	<td><input type="text" size="50" name="cn" value="{$cn}"></td></tr>
	
		<tr><td style="width:100%;"colspan="5"><hr></td></tr>
		
		
<!--DESCRIPTION:-->	

<!--Títol apartat Description-->
		
<tr><th align="left">Description</th>

	<!-- Definició del Camp iesebreDescription-->
	
	<td colspan="5"><input type="text" size="50" name="iesebreDescription" value="{$iesebreDescription}"></td></tr>
	
		<tr><td style="width:100%;"colspan="5"><hr></td></tr>
		
		
		
<!--ORIGIN:-->	

<!--Títol apartat Origin i Títols dels Camps-->
	
<tr>
	<th align="left">Origin: </th>
	<th align="left" colspan="1">Origin Code</th>
	
	
	<!-- Definició dels Camps de Origins-->

<tr>
	<td></td>
	
		<!--Menú desplegable per OriginCode-->
	<td>{html_options name=Origin options=$OriginCodes selected=$iesebreOriginName}</td>
	
		<tr><td style="width:100%;"colspan="5"><hr></td></tr>
		
		
<!--VENDOR:-->	

<!--Títol apartat Vendor i Títols dels Camps-->
	
<tr>
	<th align="left">Vendor: </th>
	<th align="left" colspan="1">Vendor Code</th></tr>
	
<tr>
	<td></td>
	
	<!--Menú desplegable amb llista de Vendors-->
	<td>{html_options name=Vendor options=$VendorCodes selected=$DefaultVendor}</td>
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>
	

<!--LOCATIONS:-->	

<!--Títol apartat Locations i Títols dels Camps-->

	
<tr>
	<th align="left">Lloc: </th>
	<th align="left" colspan="1">Location1 Code</th>
	<th align="left" colspan="1">Location2 Code</th>

	
	<!--Definició dels Camps de Locations-->
	
<tr>
	<td></td>
	
	<!--Menú desplegable amb llista de Codis de Aules-->
	<td>{html_options name=Location1 options=$Location1Codes selected=$DefaultLocation1}</td>
	
	<!--Menú desplegable amb llista de Codis de Aules-->
	<td>{html_options name=Location2 options=$Location2Codes selected=$DefaultLocation2}</td>
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>
	

<!--Tanquem taula del Formulari-->	
</table>
</body>

L'estructura i format bàsic de la plantilla és codi html, podem crear taules, columnes i files exactament igual que en qualsevol altre pàgina web;

Per exemple aqui hem creat un camp on mostrem el Center Còde;

<td><input type="text" id="centercode" name="centercode" readonly></td>

El funcionament de omplir els camps creats anteriorment, es una mica més complex. Les plantilles de gosa utilitza el Smarty per gestionar tots els variables que rebem de la base de dades LDAP.

<td><input type="text" size="50" name="cn" value="{$cn}"></td></tr>
  • Aqui podem veure que este camp refereix al variable cn del objecte que volem mostrar. Per mostrar-ho, hem de posar el nom del nostre valor a l'opció value del <input>.
  • Aquest variable ha de ser definit al class_iesebreinventoryGeneric.inc
  • Per a fer proves, és pot passar el variable amb un valor estàtic. Això és pot aconseguir afegint la següent línia dins del fitxer class_iesebreinventoryGeneric.inc;
$smarty->assign ("cn","valor");

Per a crear un menú desplegable hem de utilitzar el següent codi;

<td>{html_options id="depcode" name=Departments options=$DepartmentCodes selected=$iesebreDepartamentCode onChange="updateCode();"}</td>

La opció options ha de tindre com a valor, el variable definit en el class_iesebreinventoryGeneric.inc que contè la llista de opcions. Quan és tria un valor del menú desplegable el que fà és passar el codi al servidor LDAP.

  • la llista de valors que volem mostrar al desplegable s'ha de definir al fitxer de class_iesebreinventoryGeneric.inc de la següent manera;
/*Departments*/
         
			 $smarty->assign('DepartmentCodes', array(
					07=> 'Edificació i Obra Civil',
					08 => 'Electricitat i Electrònica',
					02=> 'Administració',
					06 => 'Comerç i Marquèting',
					09 => 'Fusta i Moble (Casa oficis)',
					14 => 'Fabricació Mecànica',
					16 => 'Sanitat',
					17 => 'Serveis Sòcioculturals a la comunitat',
					19 => 'Manteniment i Serveis a la producció',
					20 => 'Familia Informàtica',
					62 => 'Formació i orientació laboral',
					70 => 'Anglès',
					71 => 'Castellà',
					72 => 'Català',
					73 => 'Ciències Experimentals',
					74 => 'Ciències Socials',
					75 => 'Educació Física',				
					76 => 'Matemàtiques',
					77 => 'Música',
					78 => 'Tecnologia',
					79 => 'Vísual i Plastica',								
					80 => 'Pintura (Casa oficis)',
					81 => 'Orientació Psicopedagògica',
					99 => 'Centre')
									
					);

Per fer proves, podem passar un variable amb valor determinat. Això és fa amb la línia següent:

$smarty->assign('DefaultDepartment', 20)
Plantilla Impressores
<head>

<!--SCRIPT UPDATE

Script en JavaScript que actualitzará  el Camp centercode, quan és 
tria una opció d'un menú desplegable o és modifica el camp iesebreFinalCode

L'script s'ha de col·locar entre "literal" perque sinó, Smarty interpreta 
el codi de manera incorrecta-->

<SCRIPT TYPE="text/javascript">

{literal}
function updateCode(){
	document.getElementById('centercode').value=document.getElementById('depcode').value + "-" + document.getElementById('matcode').value + "-" + document.getElementById('mattypecode').value + "-" + document.getElementById('fincode').value;
}
		

{/literal}

</SCRIPT>

</head>

<body onload="updateCode();">



<!--TÍTOL: Títol Principal del Formulari-->

<h3>{t}Printers{/t} - {t}global defaults{/t}</h3>
 <tr><td style="width:100%;"colspan="2"><hr></td></tr>

<!--TAULA: Taula on se situará  tot els camps del Formulari-->
<table style="width:100%;" summary="{t}Printers{/t} - {t}global defaults{/t}">

<!--CENTER CODE:-->

<!--1a Definició dels Títols dels camps del Center Code:-->
<tr>
	<th align="left">Center Code: </th>
	<th align="left" colspan="1">Department Code{$must}</th>
	<th align="left" colspan="1">Material Type Code{$must}</th>
	<th align="left" colspan="1">Center Code</th>
	
</tr>

<!--1a Definició  dels Menús desplegables relacionats amb els apartats definits dins de l'apartat de Center Code-->

<tr>

		<td></td>
	
		<td>{html_options id="depcode" name=Departments options=$DepartmentCodes selected=$iesebreDepartamentCode onChange="updateCode();"}</td>
	
		<td>{html_options id="matcode" name=MaterialTypes options=$MaterialTypeCodes selected=$iesebreMaterialTypeCode onChange="updateCode();"}</td>
		
		
		<!--Camp que mostra els valors Introduïts als camps del Codi del Centre-->
		<td><input type="text" id="centercode" name="centercode" readonly></td>
	
</tr>

<!--2a Definició dels Títols dels camps del Center Code:-->

<tr>
	<th></th>
	<th align="left" colspan="1">Material Code{$must}</th>
	<th align="left" colspan="1">Final Code{$must}</th></tr>
	
<tr></tr>

<!--2a Definició dels Menús desplegables relacionats amb els apartats definits dins de l'apartat de Center Code-->


<tr>
	<td></td>
	
	<!--Menú Desplegable amb una llista de Codis de Materials-->
	
	<td>{html_options id="mattypecode" name=Materials options=$MaterialCodes selected=$iesebreMaterialCode onChange="updateCode();"}</td>
	
	<td><input type="text" id="fincode" size="10" name="iesebreFinalCode"  value="{$iesebreFinalCode}" onChange="updateCode();"}></td></tr>
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>


<!--CN:-->	

<!--Títol apartat cn-->

<tr><th align="left" colspan="1">Object Name</th>

	<!-- Definició del Camp cn-->

	<td><input type="text" size="50" name="cn" value="{$cn}"></td></tr>
	
		<tr><td style="width:100%;"colspan="5"><hr></td></tr>
		
		
<!--DESCRIPTION:-->	

<!--Títol apartat Description-->
		
<tr><th align="left">Description</th>

	<!-- Definició del Camp iesebreDescription-->
	
	<td colspan="5"><input type="text" size="50" name="iesebreDescription" value="{$iesebreDescription}"></td></tr>
	
		<tr><td style="width:100%;"colspan="5"><hr></td></tr>
		
		
		
<!--ORIGIN:-->	

<!--Títol apartat Origin i Títols dels Camps-->
	
<tr>
	<th align="left">Origin: </th>
	<th align="left" colspan="1">Origin Code</th>
	
	
	<!-- Definició dels Camps de Origins-->

<tr>
	<td></td>
	
		<!--Menú desplegable per OriginCode-->
	<td>{html_options name=Origin options=$OriginCodes selected=$iesebreOriginName}</td>
	
		<tr><td style="width:100%;"colspan="5"><hr></td></tr>
		
		
<!--VENDOR:-->	

<!--Títol apartat Vendor i Títols dels Camps-->
	
<tr>
	<th align="left">Vendor: </th>
	<th align="left" colspan="1">Vendor Code</th></tr>
	
<tr>
	<td></td>
	
	<!--Menú desplegable amb llista de Vendors-->
	<td>{html_options name=Vendor options=$VendorCodes selected=$DefaultVendor}</td>
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>
	

<!--LOCATIONS:-->	

<!--Títol apartat Locations i Títols dels Camps-->

	
<tr>
	<th align="left">Lloc: </th>
	<th align="left" colspan="1">Location1 Code</th>
	<th align="left" colspan="1">Location2 Code</th>

	
	<!--Definició dels Camps de Locations-->
	
<tr>
	<td></td>
	
	<!--Menú desplegable amb llista de Codis de Aules-->
	<td>{html_options name=Location1 options=$Location1Codes selected=$DefaultLocation1}</td>
	
	<!--Menú desplegable amb llista de Codis de Aules-->
	<td>{html_options name=Location2 options=$Location2Codes selected=$DefaultLocation2}</td>
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>

<!--XARXA-->

<tr>
	<th align="left">MAC: </th>
	<th align="left" colspan="1">IP</th></tr>
	
<tr>
	<td></td>
	
	<input type="text" size="50" name="ipHost" value="{$ipHost}">
        <input type="text" size="50" name="macAddress" value="{$macAddress}">
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>
	
	

<!--Tanquem taula del Formulari-->	
</table>
</body>

Plantilla Workstations
<head>

<!--SCRIPT UPDATE

Script en JavaScript que actualitzará  el Camp centercode, quan és 
tria una opció d'un menú desplegable o és modifica el camp iesebreFinalCode

L'script s'ha de col·locar entre "literal" perque sinó, Smarty interpreta 
el codi de manera incorrecta-->

<SCRIPT TYPE="text/javascript">

{literal}
function updateCode(){
	document.getElementById('centercode').value=document.getElementById('depcode').value + "-" + document.getElementById('matcode').value + "-" + document.getElementById('mattypecode').value + "-" + document.getElementById('fincode').value;
}
		

{/literal}

</SCRIPT>

</head>

<body onload="updateCode();">



<!--TÍTOL: Títol Principal del Formulari-->

<h3>{t}Workstation{/t} - {t}global defaults{/t}</h3>
 <tr><td style="width:100%;"colspan="2"><hr></td></tr>

<!--TAULA: Taula on se situará  tot els camps del Formulari-->
<table style="width:100%;" summary="{t}Workstations{/t} - {t}global defaults{/t}">

<!--CENTER CODE:-->

<!--1a Definició dels Títols dels camps del Center Code:-->
<tr>
	<th align="left">Center Code: </th>
	<th align="left" colspan="1">Department Code{$must}</th>
	<th align="left" colspan="1">Material Type Code{$must}</th>
	<th align="left" colspan="1">Center Code</th>
	
</tr>

<!--1a Definició  dels Menús desplegables relacionats amb els apartats definits dins de l'apartat de Center Code-->

<tr>

		<td></td>
	
		<td>{html_options id="depcode" name=Departments options=$DepartmentCodes selected=$iesebreDepartamentCode onChange="updateCode();"}</td>
	
		<td>{html_options id="matcode" name=MaterialTypes options=$MaterialTypeCodes selected=$iesebreMaterialTypeCode onChange="updateCode();"}</td>
		
		
		<!--Camp que mostra els valors Introduïts als camps del Codi del Centre-->
		<td><input type="text" id="centercode" name="centercode" readonly></td>
	
</tr>

<!--2a Definició dels Títols dels camps del Center Code:-->

<tr>
	<th></th>
	<th align="left" colspan="1">Material Code{$must}</th>
	<th align="left" colspan="1">Final Code{$must}</th></tr>
	
<tr></tr>

<!--2a Definició dels Menús desplegables relacionats amb els apartats definits dins de l'apartat de Center Code-->


<tr>
	<td></td>
	
	<!--Menú Desplegable amb una llista de Codis de Materials-->
	
	<td>{html_options id="mattypecode" name=Materials options=$MaterialCodes selected=$iesebreMaterialCode onChange="updateCode();"}</td>
	
	<td><input type="text" id="fincode" size="10" name="iesebreFinalCode"  value="{$iesebreFinalCode}" onChange="updateCode();"}></td></tr>
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>


<!--CN:-->	

<!--Títol apartat cn-->

<tr><th align="left" colspan="1">Object Name</th>

	<!-- Definició del Camp cn-->

	<td><input type="text" size="50" name="cn" value="{$cn}"></td></tr>
	
		<tr><td style="width:100%;"colspan="5"><hr></td></tr>
		
		
<!--DESCRIPTION:-->	

<!--Títol apartat Description-->
		
<tr><th align="left">Description</th>

	<!-- Definició del Camp iesebreDescription-->
	
	<td colspan="5"><input type="text" size="50" name="iesebreDescription" value="{$iesebreDescription}"></td></tr>
	
		<tr><td style="width:100%;"colspan="5"><hr></td></tr>
		
		
		
<!--ORIGIN:-->	

<!--Títol apartat Origin i Títols dels Camps-->
	
<tr>
	<th align="left">Origin: </th>
	<th align="left" colspan="1">Origin Code</th>
	
	
	<!-- Definició dels Camps de Origins-->

<tr>
	<td></td>
	
		<!--Menú desplegable per OriginCode-->
	<td>{html_options name=Origin options=$OriginCodes selected=$iesebreOriginName}</td>
	
		<tr><td style="width:100%;"colspan="5"><hr></td></tr>
		
		
<!--VENDOR:-->	

<!--Títol apartat Vendor i Títols dels Camps-->
	
<tr>
	<th align="left">Vendor: </th>
	<th align="left" colspan="1">Vendor Code</th></tr>
	
<tr>
	<td></td>
	
	<!--Menú desplegable amb llista de Vendors-->
	<td>{html_options name=Vendor options=$VendorCodes selected=$DefaultVendor}</td>
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>
	

<!--LOCATIONS:-->	

<!--Títol apartat Locations i Títols dels Camps-->

	
<tr>
	<th align="left">Lloc: </th>
	<th align="left" colspan="1">Location1 Code</th>
	<th align="left" colspan="1">Location2 Code</th>

	
	<!--Definició dels Camps de Locations-->
	
<tr>
	<td></td>
	
	<!--Menú desplegable amb llista de Codis de Aules-->
	<td>{html_options name=Location1 options=$Location1Codes selected=$DefaultLocation1}</td>
	
	<!--Menú desplegable amb llista de Codis de Aules-->
	<td>{html_options name=Location2 options=$Location2Codes selected=$DefaultLocation2}</td>
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>

<!--XARXA-->

<tr>
	<th align="left">MAC: </th>
	<th align="left" colspan="1">IP</th></tr>
	
<tr>
	<td></td>
	
	<input type="text" size="50" name="ipHost" value="{$ipHost}">
        <input type="text" size="50" name="macAddress" value="{$macAddress}">
	
	<tr><td style="width:100%;"colspan="5"><hr></td></tr>
	

<!--Tanquem taula del Formulari-->	
</table>
</body>

Makefile per l'instal·lació del plugin iesebreinventory
# TODO Copyright
# 
# Makefile gosa-inventory
# 
# Files: TODO
# 
# Makefile base, al qual afegirem els fitxers que fase falta per a l'aplicacio.

OWNER=root
GROUP=root
INSTALL=/usr/bin/install
MKDIR=/bin/mkdir
RM=/bin/rm
MAKE=/usr/bin/make

PLUGIN_NAME=iesebreInventory

## usr/share/gosa
GOSA_DIR=usr/share/gosa
## usr/share/gosa/html
GOSA_HTML_DIR=$(GOSA_DIR)/html
## usr/share/gosa/html/plugins
GOSA_HTML_PLUGINS_DIR=$(GOSA_HTML_DIR)/plugins
## usr/share/gosa/html/plugins/iesebreInventory
PLUGIN_HTML_DIR=$(GOSA_HTML_PLUGINS_DIR)/$(PLUGIN_NAME)
## usr/share/gosa/html/plugins/iesebreInventory/images
PLUGIN_HTML_IMAGES_DIR=$(PLUGIN_HTML_DIR)/images
## usr/share/gosa/plugins
GOSA_PLUGINS_DIR=$(GOSA_DIR)/plugins
## usr/share/gosa/plugins/admin
GOSA_PLUGINS_ADMIN_DIR=$(GOSA_PLUGINS_DIR)/admin
## usr/share/gosa/plugins/admin/iesebreInventory
PLUGIN_PLUGINS_DIR=$(GOSA_PLUGINS_ADMIN_DIR)/$(PLUGIN_NAME)

## etc
ETC_DIR=etc
## etc/ldap					
ETC_LDAP_DIR=$(ETC_DIR)/ldap
## etc/ldap/schema
ETC_LDAP_SCHEMA_DIR=$(ETC_LDAP_DIR)/schema
## etc/ldap/slapd.d
ETC_LDAP_SLAPD_DIR=$(ETC_LDAP_DIR)/slapd.d
## etc/ldap/slapd.d/cn=config
CN_CONFIG_DIR=$(ETC_LDAP_SLAPD_DIR)/cn=config
## etc/ldap/slapd.d/cn=config/cn=schema
CN_SCHEMA_DIR=$(CN_CONFIG_DIR)/cn=schema

## Rules ###################################################################
#
# reinstall_gosa: 	UTILITZAR SOTA LA TEVA RESPONSABILITAT 
#					se suposa que reinstal·la el gosa sancer, pero no s'ha provat 
#
# clean:			TODO
#
# install:			Instal·la tot el plugin amb tots els subdirectoris necessaris pero no els esquemes
#
# install_schemas:	TODO: De moment no funciona
#					Instal·la només els esquemes del directori
#
# uninstall:		Elimina tots els fitxers, els esquemes, i els directoris del plugin
#
# gosa_update:		Actualitza la llista de plugins del gosa i reinicia l'apache
#
# apache_reload:	Només reinicia l'apache
#			
############################################################################


reinstall_gosa:
	apt-get install --reinstall --force-yes -y gosa
	apt-get install --reinstall --force-yes -y gosa-plugin-connectivity gosa-plugin-dhcp \
	gosa-plugin-dhcp-schema gosa-plugin-dns gosa-plugin-dns-schema \
	gosa-plugin-fai gosa-plugin-fai-schema gosa-plugin-gofax \
	gosa-plugin-gofon gosa-plugin-goto gosa-plugin-kolab \
	gosa-plugin-kolab-schema gosa-plugin-ldapmanager gosa-plugin-mail \
	gosa-plugin-mit-krb5 gosa-plugin-mit-krb5-schema gosa-plugin-nagios \
	gosa-plugin-nagios-schema gosa-plugin-netatalk \
	gosa-plugin-opengroupware gosa-plugin-openxchange \
	gosa-plugin-openxchange-schema gosa-plugin-opsi gosa-plugin-phpgw \
	gosa-plugin-phpgw-schema gosa-plugin-phpscheduleit gosa-plugin-phpscheduleit-schema \
	gosa-plugin-pptp gosa-plugin-pptp-schema gosa-plugin-pureftpd \
	gosa-plugin-pureftpd-schema gosa-plugin-rolemanagement gosa-plugin-rsyslog \
	gosa-plugin-samba gosa-plugin-scalix gosa-plugin-squid gosa-plugin-ssh \
	gosa-plugin-ssh-schema gosa-plugin-ssh-schema gosa-plugin-sudo gosa-plugin-sudo-schema \
	gosa-plugin-systems gosa-plugin-uw-imap gosa-plugin-webdav gosa-schema 
	apt-get install --reinstall --force-yes -y gosa-dev gosa-help-en
	apt-get install --reinstall --force-yes -y smarty3-gosa
	
	
clean:
	

install: clean
	$(MKDIR) -p $(DESTDIR)/$(GOSA_DIR)/
	
	$(MKDIR) -p $(DESTDIR)/$(GOSA_HTML_DIR)
	$(MKDIR) -p $(DESTDIR)/$(GOSA_HTML_PLUGINS_DIR)
	$(MKDIR) -p $(DESTDIR)/$(PLUGIN_HTML_DIR)
	$(MKDIR) -p $(DESTDIR)/$(PLUGIN_HTML_IMAGES_DIR)
	
	$(MKDIR) -p $(DESTDIR)/$(GOSA_PLUGINS_DIR)
	$(MKDIR) -p $(DESTDIR)/$(GOSA_PLUGINS_ADMIN_DIR)
	$(MKDIR) -p $(DESTDIR)/$(PLUGIN_PLUGINS_DIR)
	
	$(INSTALL) -o $(OWNER) -g $(GROUP) -m 755 $(PLUGIN_HTML_IMAGES_DIR)/* $(DESTDIR)/$(PLUGIN_HTML_IMAGES_DIR)
	$(INSTALL) -o $(OWNER) -g $(GROUP) -m 755 $(PLUGIN_PLUGINS_DIR)/* $(DESTDIR)/$(PLUGIN_PLUGINS_DIR)

	$(MKDIR) -p $(DESTDIR)/$(ETC_LDAP_SCHEMA_DIR)
	
	$(INSTALL) -o $(OWNER) -g $(GROUP) -m 755 $(ETC_LDAP_SCHEMA_DIR)/* $(DESTDIR)/$(ETC_LDAP_SCHEMA_DIR)
	
	$(MKDIR) -p $(DESTDIR)/$(ETC_LDAP_SLAPD_DIR)
	
	$(MKDIR) -p $(DESTDIR)/$(CN_CONFIG_DIR)
	$(MKDIR) -p $(DESTDIR)/$(CN_SCHEMA_DIR)

	#$(MAKE) install_schemas

	$(MAKE) gosa_update


install_schemas:
	
	## Es legeix el directori on estan els esquemes i s'incrementa el numero
	## per cada esquema que hi ha. Al final del for, el numero que queda es
	## el numero que ens interesa per a inserir el nou esquema.
	
	## iesebreinventory.ldif
	s_num=-1
	for s_name in `ls -1 /$(ETC_DIR)`; do
		echo $s_name
		#s_num=$((s_num+1))
	done
	#$(INSTALL) -o $(OWNER) -g $(GROUP) -m 755 $(CN_SCHEMA_DIR)/iesebreinventory.ldif /$(CN_SCHEMA_DIR)/cn=$($s_num)iesebreinventory.ldif
	
	
uninstall:

	$(RM) -f $(DESTDIR)/$(CN_SCHEMA_DIR)/iesebreinventory.ldif
	$(RM) -f $(DESTDIR)/$(ETC_LDAP_SCHEMA_DIR)/iesebreinventory.schema
	
	$(RM) -f $(DESTDIR)/$(PLUGIN_HTML_IMAGES_DIR)/*
	$(RM) -rf $(DESTDIR)/$(PLUGIN_HTML_IMAGES_DIR)
	
	$(RM) -f $(DESTDIR)/$(PLUGIN_HTML_DIR)/*
	$(RM) -rf $(DESTDIR)/$(PLUGIN_HTML_DIR)
	
	$(RM) -f $(DESTDIR)/$(PLUGIN_PLUGINS_DIR)/*
	$(RM) -rf $(DESTDIR)/$(PLUGIN_PLUGINS_DIR)
	

gosa_update:
	update-gosa
	
	$(MAKE) apache_reload
	

apache_reload:
	/etc/init.d/apache2 reload

Creació d'un Makefile per a la instal·lació del plugin

Una manera d'automatitzar la instal·lació del plugin anterior és la creació d'un Makefile.

Anem a suposar que desenvolupem amb eclipse i tenim creat el workspace:

~/workspace/dummyplug/

I a dins tenim l'estructura de directoris amb els fitxers de codi del plugin. Veure l'apartat anterior.

A continuació crearem el fitxer Makefile:

$ geany Makefile

El codi serà el següent:

# Makefile de dummyplug
# 
# Aquest Makefile conté les ordres bàsiques per a instal·lar i desinstal·lar el plugin dummyplug.

PLUGINNAME=dummyplug
OWNER=root
GROUP=root
INSTALL=/usr/bin/install

HTMLDIR=usr/share/gosa/html/plugins/$(PLUGINNAME)
PLUGINSDIR=usr/share/gosa/plugins/addons/$(PLUGINNAME)


clean:
	


install: clean
	mkdir -p $(DESTDIR)/$(HTMLDIR)
	mkdir -p $(DESTDIR)/$(HTMLDIR)/images
	mkdir -p $(DESTDIR)/$(PLUGINSDIR)
	
	$(INSTALL) -o $(OWNER) -g $(GROUP) -m 755 $(HTMLDIR)/images/* $(DESTDIR)/$(HTMLDIR)/images
	$(INSTALL) -o $(OWNER) -g $(GROUP) -m 755 $(PLUGINSDIR)/* $(DESTDIR)/$(PLUGINSDIR)


uninstall:
	rm -f $(DESTDIR)/$(HTMLDIR)/images/*
	rm -rf $(DESTDIR)/$(HTMLDIR)/images/
	rm -rf $(DESTDIR)/$(HTMLDIR)/
	rm -f $(DESTDIR)/$(PLUGINSDIR)/*
	rm -rf $(DESTDIR)/$(PLUGINSDIR)/
	

update:
	update-gosa

Tenim tres ordres programades:

  • install: Crea la estructura de directoris a l'arrel del sistema, on s'instal·laran els fitxers de codi del plugin, i a continuació copia aquests fitxers. Cal apuntar que aquesta estructura de directoris la tenim també al nostre workspace, així nomes cal copiar des del workspace fins a l'arrel.
  • uninstall: Desfà tot el que es crea a l'ordre install.
  • update: Executa l'ordre update-gosa per a guardar els canvis realitzats.

Repositori subversion

Es pot fer un checkout d'aquest plugin a:

http://www.iesebre.com/subversion/projectes/gosaexamples

Text en negreta

Llistes

TODO


Mostrar més camps a la llista d'usuaris

Cal fer dos coses per tal de mostrar nous camps (columnes) a les llistes:

  • Modificar el fitxer XML amb la llista del plugin: normalment nomplugin-list.xml, p.ex user-list.xml, aquí podeu modificar la presentació
  • Modificar el fitxer de filtratge: normalment nomplugin-filter.xml, p.ex user-filter.xml. Aquí cal indicar la llista de camps que s'obtindran a les cerques

Els camps que s'obtindran de la base de dades Ldap a partir d'una consulta són els indicats al fitxer user-filter.xml

/usr/share/gosa/plugins/admin/users/user-filter.xml

a:

<search>
   <query>
     <backend>LDAP</backend>
     <filter>(&(objectClass=gosaAccount)$TEMPLATES$NAME(|$FUNCTIONAL$SAMBA$POSIX$MAIL))</filter>
     <attribute>dn</attribute>
     <attribute>objectClass</attribute>
     <attribute>givenName</attribute>
     <attribute>sn</attribute>
     <attribute>sn1</attribute>
     <attribute>sn2</attribute>
     <attribute>uid</attribute>
     <attribute>userPassword</attribute>
   </query>
   <scope>auto</scope>
</search>

Com podeu veure també s'especifica el filtre de cerca (filter).

Es pot modificar quan ocupen (layout) els camps de la llista a user-list.xml:

<layout>|20px;c|||||||150px|185px;r|</layout> <department> <value>%{filter:objectType(dn,objectClass)}</value> </department> <department> <value>%{filter:departmentLink(row,dn,description)}</value> 8 </department> <column> <value>%{filter:objectType(dn,objectClass)}</value> </column>

Modificar les llistes

Per exemple la llista d'usuaris, els fitxers relevants són:

/usr/share/gosa/plugins/admin/users/user-list.tpl          <-- Plantilla Smarty: Permet canviar la presentació de la llsita
/usr/share/gosa/plugins/admin/users/user-list.xml          <-- Configuració de la llista. Permet canviar les columnes, les accions...
/usr/share/gosa/plugins/admin/users/user-filter.xml        <-- Configuració dels filtres. Configura els filtres de la llista.

en el cas del nostre plugin els fitxers són els equivalents però de la carpeta:

/usr/share/gosa/plugins/admin/HighSchoolUsers

NOTA: Per evitar confusions s'han canviat tots els noms de fitxers (i les referències). On posa user ara es posa highschooluser:

/usr/share/gosa/plugins/admin/HighSchoolUsers/highschooluser-list.tpl
/usr/share/gosa/plugins/admin/HighSchoolUsers/highschooluser-list.xml
/usr/share/gosa/plugins/admin/HighSchoolUsers/highschooluser-filter.xml

La configuració de la llista es carregada pel gestor (class_HighSchoolUserManagement.inc):

$ grep -n "user-list" -r .
...
./plugins/admin/HighSchoolUsers/class_HighSchoolUserManagement.inc:69:        $headpage = new listing(get_template_path("user-list.xml", true));

I el filtre també:

$ grep -n "user-filter" -r .
...
./plugins/admin/HighSchoolUsers/class_HighSchoolUserManagement.inc:63:            $filter = new filter(get_template_path("user-filter.xml", true));

La plantilla Smarty a utilitzar l'indica el fitxer de configuració XML de la llista:

$ grep -n "user-list.tpl" -r .
./plugins/admin/HighSchoolUsers/user-list.xml:9:    <template>user-list.tpl</template>


Filtres

Pestanyes

Consulteu: http://www.iesebre.com/subversion/projectes/gosaexamples/dummyplugtabs/dummyplug/

Afegir un nou grup de tabs

Plugins normals

En el cas de plugins normals:

TODO
Plugins de gestió

En cas de plugins de gestió les classes (hereten de la classe base managment) el procediment és similar als plugins. Per exemple:

/usr/share/gosa/plugins/admin/HighSchoolUsers/class_HighSchoolUserManagement.inc

Cal definir les definicions de pestanyes (tabs):

   // Tab definition
   protected $tabClass = "HighShoolUsertabs";         <-- Fa referència a la classe PHP que crearà l'objecte tabs (hereten de la classe general tabs)
   protected $tabType = "HIGHSCHOOLUSERTABS";         <-- És el nom del tag XML del fitxer gosa.conf on estan definits els tabs. Es posa en 
                                                          majúscules tot i que al fitxer XML pot estar com vulgueu: tot minúscules, majúscules, un mixt
   protected $aclCategory = "users";                  <--- TODO
   protected $aclPlugin   = "user";                   <--- TODO
   protected $objectName   = "user";                  <--- TODO

Al fitxer XML hem afegit una porció:

 <HighSchoolUsertabs>
    <tab class="user" name="Generic" />
    <tab class="posixAccount" name="POSIX" />
    <tab class="sambaAccount" name="Samba" />
== Com afegir un tab? ==

Extret de:

https://oss.gonicus.de/repositories/gosa/trunk/gosa-core/contrib/plugins/dyngroup/README

3. How to enable this feature in GOsa ?

It is very easy. Edit /etc/gosa/gosa.conf, and add the following line in the grouptabs section:

 <tab class="DynamicLdapGroup" name="Dynamic group" />

Then, add the following line in the deptabs section:

 <tab class="DynamicLdapGroup" name="Dynamic group" />

Then, put the plugin in /usr/share/gosa/plugins/addons, and update GOsa cache via the update-gosa command.

  </HighSchoolUsertabs>

I finalment a:

/usr/share/gosa/plugins/admin/HighSchoolUsers/tabs_user.inc

Hem canviat el nom de la classe:

...
class HighShoolUsertabs extends tabs

Per fer-ho coincidir amb la variable $tabClass del gestor del plugin.

Com afegir un tab?

Extret de:

https://oss.gonicus.de/repositories/gosa/trunk/gosa-core/contrib/plugins/dyngroup/README

3. How to enable this feature in GOsa ?

It is very easy. Edit /etc/gosa/gosa.conf, and add the following line in the grouptabs section:

 <tab class="DynamicLdapGroup" name="Dynamic group" />

Then, add the following line in the deptabs section:

 <tab class="DynamicLdapGroup" name="Dynamic group" />

Then, put the plugin in /usr/share/gosa/plugins/addons, and update GOsa cache via the update-gosa command.

Accions

Afegir accions de menú

Primer cal afegir-les a la interfície gràfica, per fer-ho cal editar la configuració de la llista d'usuaris:

/usr/share/gosa/plugins/admin/HighSchoolUsers/highschooluser-list.xml

Per exemple per afegir les accions "Nou alumne" i "Nou Professor" a <actionmenu> cal afegir:

   <action>
      <name>new_student</name>
      <type>entry</type>
      <image>plugins/users/images/select_user.png[new]</image>
      <label>Alumne</label>
     </action>

    <action>
       <name>new_teacher</name>
       <type>entry</type>
       <image>plugins/users/images/select_user.png[new]</image>
       <label>Professor</label>
    </action>

Amb això apareixeran però no es realitzarà cap acció. Cal afegir els controladors al gestor del plugin HighSchoolUserManagement.inc concretament al constructor (function __construct($config,$ui)) :

 // Register special user actions
 $this->registerAction("lock",   "lockEntry");
 $this->registerAction("lockUsers",   "lockUsers");
 $this->registerAction("unlockUsers", "lockUsers");
 $this->registerAction("new_template", "newTemplate");
 $this->registerAction("newfromtpl", "newUserFromTemplate");
 $this->registerAction("templateContinue", "templateContinue");
 $this->registerAction("templatize", "templatizeUsers");
 $this->registerAction("templatizeContinue", "templatizeContinue");
$this->registerAction("new_student", "newStudent");
$this->registerAction("new_teacher", "newTeacher");

Al registrar una acció el primer paràmetre és el nom de l'acció (indicat al tag name del fitxer XML de configuració de la llista) i el segon paràmetre és la funció que s'executa. Per tant registerAction relaciona les capes de presentació i model.

NOTA: noteu que l'acció new, no hi és, es troba a la classe pare!


TODO:

// Inject user actions 
   function detectPostActions()
   {
       $action = management::detectPostActions();
       if(isset($_POST['template_continue'])) $action['action'] = "templateContinue";
       if(isset($_POST['templatize_continue'])) $action['action'] = "templatizeContinue";
       if(isset($_POST['save_event_dialog'])) $action['action'] = "saveEventDialog";
       if(isset($_POST['abort_event_dialog'])) $action['action'] = "abortEventDialog";
       if(isset($_POST['password_cancel'])){
           $action['action'] = "passwordCancel";
       }elseif((count($this->pwd_change_queue) || isset($_POST['password_finish']) || isset($_POST['refreshProposal']))){
           $action['action'] = "passwordQueue";
       }
       return($action);
   }

Accions de llista

TODO

A

/usr/share/gosa/include/class_listing.php

La funció:

getAction()

gestiona les accions. Les accions de llista són les que es criden amb un botó submit amb el nom/id "listing_*":

// Filter POST with "listing_" attributes
   foreach ($_POST as $key => $prop) {

Afegir una acció al menú d'usuaris

Cal editar el fitxer:

/usr/share/gosa/plugins/admin/users/user-list.xml

I afegir l'acció:

<action>
     <type>separator</type>
   </action>
   
   <action>
     <name>resetPasswords</name>
     <type>entry</type>
     <image>plugins/users/images/wizard.png</image>
     <label>Reset passwords</label>
   </action>

NOTA: Caldrà definir les traduccions del label als fitxers MESSAGES

Per que la nova entrada aparegui al menú cal sortir de GOsa i tornar entrar (la configuració es guarda a nivell de sessió).

Ara a:

/usr/share/gosa/plugins/admin/users/class_userManagement.inc

Cal registrar l'acció

$ sudo joe /usr/share/gosa/plugins/admin/users/class_userManagement.inc

Al final del mètode:

function __construct($config,$ui) 

Afegir:

    //Institut de l'Ebre 
   $this->registerAction("resetPasswords","resetPasswords");

NOTA: No totes les accions es troben a class_userManagment. La classe userManagment hereta de managment i és en aquesta classe pare que trobareu la resta d'accions

ara cal crear la funció resetPasswords:

  function resetPasswords($action="",$target=array(),$all=array()) {
 
    $this->dns = array();
  
    if(count($target)){

      // Get the list of available templates.
      $templates = $this->get_templates();

      // Check entry locking
      foreach($target as $dn){
        if (($user= get_lock($dn)) != ""){
          $this->dn = $dn;
          return(gen_locked_message ($user, $dn));
        }
        $this->dns[] = $dn;
      }
          
      // Display template
      $smarty = get_smarty();
      $smarty->assign("templates", $templates);
      return($smarty->fetch(get_template_path('templatize.tpl', TRUE)));
    }

Acció reset passwords

Nova acció que apareix a la llista d'usuaris:

# sudo grep -n "Reset passwords" -r /usr/share/gosa | grep -v "svn"
/usr/share/gosa/include/utils/class_msgPool.inc:407:    return $what == "" ? sprintf(_("Reset passwords")): sprintf(_("Reset passwords %s"), $what);
/usr/share/gosa/plugins/admin/users/user-list.xml:213:      <label>Reset passwords</label>

Formularis

Modificar formularis, crear nous camps i nous esquemes Ldap per tal de guardar les modificacions

Els plugins han de ser classes que heretin de la classe plugin, per exemple:

class highschooluser extends plugin

A més cal indicar els objectes amb la variable:

var $objectclasses= array("top", "person", "organizationalPerson", "inetOrgPerson",
     "gosaAccount","extensibleObject","irisPerson");

La funció que s'encarrega de guardar és:

function save()

Formularis de matrícula ràpida (nou alumne | nou profe)

Per afegir les dos opcions noves (Afegir alumne nou i Afegir profe nou) cal tocar:

/usr/share/gosa/include/class_listing.inc

Quan hi han plantilles d'usuaris al crear un nou usuari apareix el menú per seleccionar una plantilla (si no hi ha plantilles no apareix).

Al fitxer:

/usr/share/gosa/plugins/admin/users/template.tpl

Hem modificat les opcions que apareixen.

TODO: Canvis fets per al calcul del Login Name???

Per modificar el formulari principal (el de dades, el que es pot posar una foto)

/usr/share/gosa/plugins/personal/generic/class_user.inc
/usr/share/gosa/plugins/personal/generic/generic.tpl

TODO: Per què aparegui per defecte la Home:

/home/alumnenou

Exemples operacions Ldap

Funcions: Objecte ldap. Clase: /usr/share/gosa/include/class_ldap.inc

cd

function cd($dir)
    {
        if ($dir == ".."){
            $this->basedn = $this->getParentDir();
        } else {
            $this->basedn = LDAP::convert($dir);
        }
    }

Canvia el basedn. Es pot utilitzar abans de una cerca per fer la cerca a partir d'aquest basedn.

search

Permet fer cerques Ldap. Vegeu ldapsearch per a més informació de com es fan cerques a Ldap.

  • srp. TODO ???
  • $filter (obligatori): Filtra de cerca Ldap, per exemple per buscar tots els objectes: (objectclass=*)
  • $attrs (opcional): dels objectes trobats quins atributs es volen obtenir. Oco que ha de ser un array, per exemple encara que sigui nomḉes un atribut cal posar: array('dn') . Per defecte és un array buit i aleshores s'obtenen tots les atributs

NOTA: Compte que no es pot indicar el basedn! Cal utilitzar prèviament la funció cd

 function search($srp, $filter, $attrs= array())
    {
        if($this->hascon){
            if ($this->reconnect) $this->connect();
 
            $start = microtime(true);
            $this->clearResult($srp);
            $this->sr[$srp] = @ldap_search($this->cid, LDAP::fix($this->basedn), $filter, $attrs);
            $this->error = @ldap_error($this->cid);
            $this->resetResult($srp);
            $this->hasres[$srp]=true;
 
            /* Check if query took longer as specified in max_ldap_query_time */
            if($this->max_ldap_query_time){
                $diff = microtime(true) - $start;
                if($diff > $this->max_ldap_query_time){
                    msg_dialog::display(_("Performance warning"), sprintf(_("LDAP performance is poor: last query took %.2fs!"), $diff), WARNING_DIALOG);
                }
            }
 
            $this->log("LDAP operation: time=".(microtime(true)-$start)." operation=search('".LDAP::fix($this->basedn)."', '$filter')");
 
            // Create statistic table entry 
            stats::log('ldap', $class = get_class($this), $category = array(),  $action = __FUNCTION__, 
                    $amount = 1, $duration = (microtime(TRUE) - $start));
            return($this->sr[$srp]);
        }else{
            $this->error = "Could not connect to LDAP server";
            return("");
        }
    }

Treballar amb els resultats

$ldap->count ()

nombre enter que mostra el nombre d'objectes retornats.

$ldap->getDN()

???

$ldap->fetch()

Retorna un vector amb tots els atributs

$atts= $ldap->fetch();

Un exemple:

 // We can't lock empty passwords.
                $val = $ldap->fetch();
                if(!isset($val['userPassword'])){
                    continue;
                }

En aquest cas se suposa que la cerca ha tornat un únic resultat o en tot cas si el resultat té múltiples objectes només es llegeix el primer. Per llegir els valors de múltiples objectes resultat:

 while ($attrs= $ldap->fetch()){
  $templates[$ldap->getDN()]= $attrs['uid'][0]." - ".LDAP::fix($key);
 }

Exemple d'obtenir i recórrer dades ldap

 /* Get an ldap handle and set the initial context to the ldap base. 
     */
    $ldap = $this->config->get_ldap_link();
    $ldap->cd($this->config->current['BASE']);

    /* Search for all objects, recursive, that match the given ldap filter.
     */
    $ldap->search("(&(objectClass=gosaAccount)(objectClass=person))",array("uid","cn"));

    /* Print out each returned object.
     * print_a is a debugging function and is not for productive use!
     */
    while($attrs = $ldap->fetch()){
      print_a($attrs);
    }

Altres

highSchoolUsers plugin

Consulteu highSchoolUsers Plugin

Treballar amb mysql

NOTA: Seria interessant tenir plugins que tinguessin una funcionalitat equivalent a la proporcionada per gosa (llistes, filtres, accions, etc) però per a des emmagatzemades a taules relacionals tipus MySQL

Les llistes

Complicat: Potser és més fàcil aprendre a definir squemes Ldap

El mètode update és el que ompla la llista de files

 function update()
 ...
 $this->entries= $this->filter->query();
  • Prèviament s'apliquen els filtres abans de mostrar tota la llista. Caldria redefinir els filtres també
  • Amb Ldap es defineix el tipus objecte. Amb SQL? una taula?
  • Els filtres són cerques Ldap? En SQL serien consultes SQL?


Objecte: ObjecteInventariable

  • Ordinadors: Classificats per espais/aules --> Ldap ok

Resol·lució de problemes. Troubleshooting

No apareixen els objectes a la llista i no mostra cap error!

En el meu cas era pel fet de no haver indicar la variable $objectName:

 class stuffManagement extends management
{
    var $plHeadline     = "Stuff rules";
    var $plDescription  = "Manage stuffs";
    var $plIcon  = "plugins/sudo/images/sudo.png";

    // Tab definition 
    //protected $tabClass = "stufftabs";
    //protected $tabType = "STUFFTABS";
    //protected $aclCategory = "stuff";
    //protected $aclPlugin   = "stuff";
    protected $objectName   = "stuff";

El nom que poseu aquí ha de coincidir amb el nom que poseu al fitxer de configuració XML del plugin:

 <list>
  <definition>
    ...

    <objectType>
      <label>Stuff</label>
      <objectClass>stuff</objectClass>
      <category>stuff</category>
      '''<class>stuff</class>'''
      <image>plugins/sudo/images/select_sudo.png</image>
    </objectType>

NOTA: No confondre el objectClass que és el no de l'objecte Ldap amb class que és el nom de l'objecte que indiquem a la variable $objectName

¡Esta cuenta tiene extensiones GOsa no validas!

NOTA: Al migrar a highshcoolusers cal recordar que els objectes no tenien dos classes que ara caldrà afegir: highschoolusers i irisPerson. Consulteu Highschooluser

Normalment és que l'objecte que estem mostrant té un objectClass Ldap que no està indicat a l'array:

$objectclasses

Per exemple al plugin highSchoolUsers cal afegir el objectClass highSchoolUser:

  var $objectclasses= array("top", "person", "organizationalPerson", "inetOrgPerson",
      "gosaAccount","extensibleObject","irisPerson","highSchoolUser");

IMPORTANT: Tots els objectes que apareixen a l'array han d'estar implementats a l'objecte Ldap (és a dir cal tenir com a mínim tots aquest objectsClass)!!

Aquest missatge es mostra al fitxer /usr/share/gosa/include/utils/class_msgPool.inc:

$ sudo grep -n "valid %s extensions" -r /usr/share/gosa
/usr/share/gosa/include/utils/class_msgPool.inc:363:    return sprintf(_("This account has no valid %s extensions!"), bold($name));

El missatge es mostrat amb la funció noValidExtension:

$ cat /usr/share/gosa/include/utils/class_msgPool.inc
...
public static function noValidExtension($name)
 {
   return sprintf(_("This account has no valid %s extensions!"), bold($name));
 }

Podeu buscar les línies de codi que executen aquest error amb:

$ grep -n "noValidExtension" -r /usr/share/gosa
grep: /usr/share/gosa/setup/DEADJOE: S’ha denegat el permís
/usr/share/gosa/include/utils/class_msgPool.inc:361:  public static function noValidExtension($name)
/usr/share/gosa/plugins/admin/ogroups/class_ogroup.inc:267:                msgPool::noValidExtension("object group")."</b>";
/usr/share/gosa/plugins/admin/groups/class_group.inc:230:            $display= "<img alt=\"\" src=\"images/small-error.png\" align=\"middle \">  
".msgPool::noValidExtension()."";
/usr/share/gosa/plugins/admin/systems/class_servGeneric.inc:158:                msgPool::noValidExtension(_("server"))."</b>"; 
/usr/share/gosa/plugins/admin/systems/class_componentGeneric.inc:84:                msgPool::noValidExtension(_("component"))."</b>";
/usr/share/gosa/plugins/admin/systems/samba/class_winGeneric.inc:112:        msgPool::noValidExtension(_("network"))."</b>";
/usr/share/gosa/plugins/personal/generic/class_user.inc:352:        msgPool::noValidExtension("GOsa")."</b>";
/usr/share/gosa/plugins/personal/posix/class_posixAccount.inc:270:          msgPool::noValidExtension(_("POSIX"))."</b>";
/usr/share/gosa/plugins/personal/samba/class_sambaAccount.inc:242:                msgPool::noValidExtension(_("Samba"))."</b>";
/usr/share/gosa/plugins/personal/highschoolgeneric/class_highschooluser.inc:137:        msgPool::noValidExtension("GOsa")."</b>";

El que fa el codi es comprovar que el objecte ldap té tots els objectsClass que s'indiquen a l'array. Aquesta comprovació es fa a la classe

$ geany /usr/share/gosa/include/class_plugin.inc 
...
  foreach ($this->objectclasses as $obj){
        if (preg_match('/top/i', $obj)){
          continue;
        }
        if (!isset($this->attrs['objectClass']) || !in_array_ics ($obj, $this->attrs['objectClass'])){
          $found= FALSE;
          break;
        }
      }
      if ($found){
        $this->is_account= TRUE;
        @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
            "found", "Object check");
      }

<ref>Insert footnote text here</ref>

plInfo

<?php

/*
 *   How to use plugin::plInfo()
 *   ===================
 *   
 *   The function returns a descriptive array of the plugin,
 *    which will then be used by GOsa to populate the plugin, its ACLs, 
 *    its properties, its schema requirements aso.
 *
 *
 *   The following values can be set:
 *   ================================
 *
 *   plShortName    |-> The name of the plugin in short (e.g. Posix)
 *                  |   This short-name will be shown for example in the ACL definitions.
 *                  | 
 *                  | 
 *   plDescription  |-> A descriptive text for the plugin (e.g. User posix account extension)
 *                  |   This will be shown in the ACL definitions.   
 *                  | 
 *                  | 
 *   plSelfModify   |-> If set to true this plugin allows to set 'self' ACLs.
 *                  |   For exampe to allow to change the users own password, but not the others.
 *                  | 
 *                  | 
 *   plDepends      |-> The plugins dependencies to other classes (e.g. sambaAccount requires posixAccount)
 *                  |  
 *                  | 
 *   plPriority     |-> The priority of the plugin, this influences the ACL listings only.
 *                  | 
 *                  | 
 *   plSection      |-> The section of this plugin 'administration', 'personal', 'addons'
 *                  | 
 *                  | 
 *   plCategory     |-> The plugin category this plugins belongs to (e.g. users, groups, departments) 
 *                  | 
 *                  | 
 *   plRequirements |-> Plugin requirements. 
 *                  | |
 *                  | |-> [activePlugin]           The schame checks will only be performed if the given plugin is enabled
 *                  | |                             in the gosa.conf definitions.
 *                  | |                            Defaults to the current class name if empty.
 *                  | |
 *                  | |-> [ldapSchema]             An array of objectClass requirements.
 *                  | |                            Syntax [[objectClass => 'version'], ... ]
 *                  | |                            Version can be emtpy which just checks for the existence of the class.
 *                  | |
 *                  | |-> [onFailureDisablePlugin] A list of plugins that which will be disabled if the 
 *                  |                               requirements couldn't be fillfulled.
 *                  |
 *                  |      ---------------------------------------------
 *                  |      EXAMPLE:
 *                  |      ---------------------------------------------
 *                  |      "plRequirements"=> array(
 *                  |         'activePlugin' => 'applicationManagement', 
 *                  |         'ldapSchema' => array(
 *                  |             'gosaObject' => '',
 *                  |             'gosaAccount' => '>=2.7',
 *                  |             'gosaLockEntry' => '>=2.7',
 *                  |             'gosaDepartment' => '>=2.7',
 *                  |             'gosaCacheEntry' => '>=2.7',
 *                  |             'gosaProperties' => '>=2.7',
 *                  |             'gosaConfig' => '>=2.7'
 *                  |             ),
 *                  |         'onFailureDisablePlugin' => array(get_class(), 'someClassName')
 *                  |         ),
 *                  |      ---------------------------------------------
 *                  |
 *                  |
 *                  |         
 *   plProvidedAcls |-> The ACLs provided by this plugin
 *                  |
 *                  |      ---------------------------------------------
 *                  |      EXAMPLE:
 *                  |      ---------------------------------------------
 *                  |      "plProvidedAcls"=> array(
 *                  |          'cn'             => _('Name'),
 *                  |          'uid'            => _('Uid'),
 *                  |          'phoneNumber'    => _('Phone number')
 *                  |          ),
 *                  |      ---------------------------------------------
 *                  |
 *                  |
 *                  | 
 *   plProperties   |-> Properties used by the plugin.
 *                  |   Properties which are defined here will be modifyable using the property editor.
 *                  |   To read properties you can use $config->get_cfg_value(className, propertyName)
 *                  | 
 *                  |      ---------------------------------------------
 *                  |      EXAMPLE:
 *                  |      ---------------------------------------------
 *                  |      "plProperties"=> array(
 *                  |         array(
 *                  |             "name"          => "htaccessAuthentication",
 *                  |             "type"          => "bool",
 *                  |             "default"       => "false",
 *                  |             "description"   => _("A description..."),
 *                  |             "check"         => "gosaProperty::isBool",
 *                  |             "migrate"       => "",
 *                  |             "group"         => "authentification",
 *                  |             "mandatory"     => TRUE
 *                  |             ),
 *                  |         ),
 *                  |   See class_core.inc for a huge amount of examples.
 */

Vegeu també

Enllaços externs