OSDN Git Service

Creación y administración de documentos basados en DOM mediante PHP
[dombasic/DOMbasic.git] / DOM_attribs.php
1 <?php
2 //define("TAG", "LinkClass");
3 /*
4  * //SE ACONSEJA ESCRIBIR UNA FUNCION COMO ESTA DE 'AUTOCARGA' EN EL SCRIPT LLAMADOR
5  * //PARA EVITAR CARGAR UNA A UNA CADA LLAMADA A include ...
6                 // we've writen this code where we need
7                 function __autoload($classname) {
8                         $ruta="./clases";
9                         $filename = $ruta."/". $classname .".php";
10                         try{
11                                 include_once($filename);
12                                 parent::__autoload($classname);
13                         } catch (Exception $e){
14                                 throw new Exception("Imposible cargar $classname desde el directorio $ruta. ERROR: ".$e->getMessage().PHP_EOL);
15                         }
16                 } 
17  */
18 //TODO:IMPORTANTE: SI ES UNA CLASE HEREDADA SE DEBE ASEGURAR ANTES DE ELLA QUE LA CLASE PADRE SE ENCUENTRA CARGADA
19         /**
20          * Interfaz para crear atributos de elementos DOM. Para que objetos derivados del DOM (como links, ...) implementen atributos HTML.
21          * <p>El programador debe asegurarse que son nombres estandarizados para los atributos de elementos DOM. (W3C)</p>
22          * <p><span title="Filtrado futuro." style="color:navy; background:yellow;">TODO</span>: FILTRADO: 
23          * <del>Solo se admitiran nombres estandarizados para los atributos de elementos DOM. (W3C)</del></p>
24          * <p>Admite CONCATENACION DE METODOS mediante el retorno de la construccion '$this' en todos los metodos 'NO-GETTER': 
25          * &hellip; <code>$this->setAttrib('href','http://www.uno.com/')->removeAttrib('href');</code> &hellip;</p>
26          **/
27         abstract class DOM_attribs implements IteratorAggregate, ArrayAccess {
28                 //private static final $TAG="LinkClass";
29                 /**
30                  * <h1>Name Class</h1>
31                  * Constante de cadena que representa el nombre de esta Clase, util para labores de Depuracion 
32                  * (agregandola a las sentencias del log o de trade...)
33                  * @var String constant
34                  * @access public
35                  */
36                 const N_C = __CLASS__; //__CLASS__ -> problemas en PHP 4 (letras minusculas)
37                 /**
38                  * NORMA DE CODIFICACION URL. (espacios=+)
39                  * @var String
40                  */
41                 const ENCODE_RFC_1738="RFC_1738";
42                 /**
43                  * NORMA DE CODIFICACION URL. (espacios=%20)
44                  * @var String
45                  */
46                 const ENCODE_RFC_3986="RFC_3986";
47                 
48                 //------------  BEGIN: CONFIGURACION  -----------------
49                 /**
50                  * <h1>Boolean indicando si los atributos de este elemento son DE SOLO LECTURA O ESCRIBIBLES.</h1>
51                  * @var boolean
52                  * @access protected
53                  */
54                 protected $_READ_ONLY=false;//=boolean;
55                 //---- BEGIN: AVISOS ------
56                 /**
57                  * ¿ Lanzar Aviso cuando se lee un atributo que no existe ?
58                  **/
59                 protected $AVISO_GET=false;
60                 //---- END: AVISOS ------
61                 
62                 //------------ END: CONFIGURACION ------------------------
63                 
64                 /**
65                  * <h1>Array Asociativo (clave=>valor) de atributos DOM.</h1>
66                  * ATRIBUTOS DOM        (PARA METODOS MAGICOS): Se le pueden agregar propiedades, atributos o campos dinamicamente
67                  * @var Array Asociativo
68                  * @access protected
69                  */
70                 protected $_attribs=array();
71
72
73                 //CONSTRUCTORES
74                 /*      DESACONSEJADO A PARTIR DE PHP 5.3.3.3
75                 function DOM_attribs(){
76                         parent::__construct();
77                         $this->reinicializar();
78                 }
79                 */
80                 /*
81                  * <h1>CONSTRUCTOR PHP 4, Compatibilidad con PHP 4</h1>
82                  * <p>El parametro sera un array asociativo de atributos con pares correctos 'clave=valor' de atributos DOM.</p>
83                  **/
84                 /*
85                 function DOM_attribs($asocArrayAttribs=null) {
86                         if (version_compare(PHP_VERSION,"5.0.0","<")) {
87                                 return $this->__construct($asocArrayAttribs);
88                         }
89                         //register_shutdown_function(array($this,"__destruct")); 
90                 }
91                 */
92
93                 /**
94                  * <h1>CONSTRUCTOR PHP 5, CON ENTREGA DIRECTA DE ATRIBUTOS.</h1>
95                  * <p>El parametro sera un array asociativo de atributos con pares correctos 'clave=valor'.</p>
96                  * <p>El programador debe asegurarse que son nombres estandarizados para los atributos de elementos DOM.(W3C)</p>
97                  * <p><span title="Filtrado futuro." style="color:navy; background:yellow;">TODO</span>: FILTRADO:
98                  * <del>Solo se admitiran nombres estandarizados para los atributos de elementos DOM. (W3C)</del></p>
99                  * @param $asocArrayAttribs Array de pares 'clave=valor' de atributos DOM.
100                  **/
101                 public function __construct($asocArrayAttribs=null){
102                         //$this->__autoload(self::TAG);
103                         //parent::__construct();
104                         //if($this->PATRON_SINGLETON) $this->setInstance();
105                         //$this->reinicializar();
106                         if(! is_null($asocArrayAttribs) ) $this->setAttribs($asocArrayAttribs);
107                 }
108                 public function __destruct(){
109                         //parent::__destruct();
110                         //self::$instance=null;
111                         $this->_attribs=null;
112                 }
113                 
114                 //--------------------  BEGIN: METODOS ABSTRACTOS  -------------------------
115                 /**
116                  * <p>Establece si los atributos de este elemento son DE SOLO LECTURA O ESCRIBIBLES.</p>
117                  * @param boolean
118                  * @return DOM_element $this este elemento (DOM).
119                  **/
120                 abstract function setReadOnly($readOnly);
121                 /**
122                  * <p>Comprueba si los atributos de este elemento son DE SOLO LECTURA O ESCRIBIBLES.</p>
123                  * @return boolean
124                  **/
125                 abstract function getReadOnly();
126                 /**
127                  * <p>Pone a cero los elementos de arrays de este Objeto.</p>
128                  * @return DOM_element $this este elemento (DOM).
129                  **/
130                 abstract function reinicializar();//{
131                         //$this->_attribs=array();
132                         //TODO: ¡¡OJO NO ACTIVAR!! PUEDE PROVOCAR UNA EXCEPCION AL SER LLAMADA DESDE UN CONSTRUCTOR.
133                         //register_shutdown_function(array($this, '__destruct'));       //para evitar un bug en PHP 5.3.10 con la destruccion de objetos
134                 //}
135                 
136                 //--------------------  END: METODOS ABSTRACTOS  -------------------------
137                 
138                 /**
139                  * <p>Notifica una accion de escritura al objeto. Si es de solo-lectura lanzara una Excepcion.</p>
140                  * @return boolean TRUE=OK, FALSE=throw DOMBasicAttribReadOnlyException()
141                  * @throws DOMBasicAttribReadOnlyException;
142                  **/
143                 protected function tryingWrite($arg="") {
144                         if($this->_READ_ONLY){
145                                 //$mensaje="Intentando escribir en un Objeto de Solo-Lectura!!";
146                                 throw new DOMBasicAttribReadOnlyException($arg, DOMBasicAttribReadOnlyException::READ);
147                                 return false;
148                         }
149                         return true;
150                 }
151
152                 //public function __clone(){
153                                 //return self::getInstance();
154                                 //$clase=__CLASS__;     //self::TAG;
155                                 //return new $clase($this->_attribs);   //DA ERRORES EN PHP 4.0
156                 //}
157                 
158                 /*
159                 // we've writen this code where we need
160                 function __autoload($classname) {
161                         $ruta="./clases";
162                         $filename = $ruta."/". $classname .".php";
163                         try{
164                                 include_once($filename);
165                                 parent::__autoload($classname);
166                         } catch (Exception $e){
167                                 throw new Exception("Imposible cargar $classname desde el directorio $ruta. ERROR: ".$e->getMessage().PHP_EOL);
168                         }
169                 }
170                 */
171
172                 
173                 //----------------- BEGIN: MAGICS METHODS ----------------------
174                 //AL RETORNAR UN ARRAY ES MEJOR HACERLO POR REFERENCIA PARA QUE SE MANTENGA ACTUALIZADO??
175                 /**
176                  * Property get access.
177                  * Simply returns a given attrib.
178                  *
179                  * @throws DOMAttribNotFoundException
180                  *         If a the value for the property attrib is not an instance of
181                  * @param string $attrib The name of the attrib to get.
182                  * @return mixed The attrib value.
183                  * @ignore
184                  *
185                  * @throws DOMBasicAttribNotFoundException
186                  *         if the given property does not exist.
187                  * @throws DOMBasicAttribReadOnlyException
188                  *         if the attrib to be set is a write-only property.
189                  */
190                 public function __get($attrib) {
191                 //public function &__get($attrib) {
192                         //echo "Consultando '$attrib'\n";
193                         try{
194                                 if(is_null($this->_attribs) || count($this->_attribs)==0) {
195                                         throw new DOMBasicAttribNotFoundException( $attrib );
196                                         return null;
197                                 }
198                                 if (array_key_exists($attrib, $this->_attribs)) {
199                                         //if ( $this->__isset( $attrib ) === true ){
200                                         return $this->_attribs[$attrib];
201                                 }
202                                 throw new DOMBasicAttribNotFoundException( $attrib );
203                         }catch(Exception $e){
204                                 if($this->AVISO_GET) self::writeLog($e->getMessage(), $e->getTrace());
205                                 return "";
206                         }
207                         /*
208                         $trace = debug_backtrace();
209                         trigger_error(
210                         '"'. $self->TAG .'::__get() :> "Propiedad indefinida mediante __get(): ' . $name .
211                         ' en ' . $trace[0]['file'] . ' en la línea ' . $trace[0]['line'],
212                         E_USER_NOTICE);
213                         */
214                         return null;
215                 }
216                 /**
217                  * Sets an attrib.
218                  * This method is called when an attrib is set.
219                  *
220                  * @param string $attribName  The name of the attrib to set.
221                  * @param mixed $attribValue The attrib value.
222                  * @return DOM_element $this este elemento (DOM). (NO-UTIL)
223                  * @ignore
224                  *
225                  * @throws DOMBasicAttribNotFoundException
226                  *         if the given attrib does not exist.
227                  * @throws DOMBasicValueException
228                  *         if the value to be assigned to a attrib is invalid.
229                  * @throws DOMBasicAttribReadOnlyException
230                  *         if the attrib to be set is a read-only attrib.
231                  */
232                 //abstract public function __set( $attribName, $attribValue );
233                 public function __set($attrib, $value) {
234                         //echo "Estableciendo '$attrib' a '$value'\n";
235                         try{    
236                                 self::tryingWrite($attrib);
237                                 $this->_attribs[$attrib] = $value;
238                          }catch(Exception $e){
239                                 self::writeLog($e->getMessage(), $e->getTrace());
240                          }
241                          return $this;
242                 }
243                 /**
244                  * Returns if an attrib exists. (Desde PHP 5.1.0 )
245                  *
246                  * @param string $attrib Attrib name to check for.
247                  * @return bool Whether the attrib exists.
248                  * @ignore
249                  */
250                 public function __isset($attrib) {
251                         //echo "¿Está definido '$attrib'?\n";
252                         //return isset($this->_attribs[$attrib]);
253                         return array_key_exists( $attrib, $this->_attribs );
254                 }
255                 
256                 /**  
257                  * <h1>Desde PHP 5.1.0</h1>  
258                  * @throws DOMBasicAttribReadOnlyException If 'Read Only' ON.
259                  * @throws DOMBasicAttribNotFoundException
260                  *         If $attrib is not a key in the $_attribs array.
261                  * @param string $attrib The name of the attrib to unset.
262                  */
263                 public function __unset($attrib) {
264                         //echo "Eliminando '$attrib'\n";
265                         try{
266                                 self::tryingWrite($attrib);
267                                 /*
268                                         if(in_array($attrib,$this->_attribs)){
269                                         $index=array_search($child, $this->_attribs);
270                                         unset($this->_attribs[$index]);
271                                 }
272                                  */
273                                 unset($this->_attribs[$attrib]);
274                         }catch(Exception $e){
275                                 self::writeLog($e->getMessage(), $e->getTrace());
276                         }
277                 }
278                 //---------------- END: MAGICS METHODS --------------------
279                 
280                 //---------------- BEGIN: ABSTRACT METHODS INTERFAZ ARRAY-ACCESS -----------------
281                 /**
282                  * Returns if an attrib exists.
283                  * Allows isset() using ArrayAccess.
284                  *
285                  * @param string $attrib The name of the attrib to get.
286                  * @return bool Whether the attrib exists.
287                  */
288                 public function offsetExists( $attrib ) {
289                         return $this->__isset( $attrib );
290                 }
291                 /**
292                  * Returns an attrib value.
293                  * Get an attrib value by ArrayAccess.
294                  *
295                  * @throws DOMBasicAttribNotFoundException
296                  *         If $attrib is not a key in the $_attribs array.
297                  * @param string $attrib The name of the attrib to get.
298                  * @return mixed The attrib value.
299                  */
300                 public function offsetGet( $attrib ) {
301                         return $this->__get( $attrib );
302                 }
303                 
304                 /**
305                  * Set an attrib.
306                  * Sets an attrib using ArrayAccess.
307                  *
308                  * @throws DOMBasicAttribNotFoundException
309                  *         If $attrib is not a key in the $_attribs array.
310                  * @throws DOMBasicValueException
311                  *         If the value for a attrib is out of range.
312                  * @param string $attrib The name of the attrib to set.
313                  * @param mixed $attrib The value for the attrib.
314                  * @return DOM_element $this este elemento (DOM).
315                  */
316                 public function offsetSet( $attrib, $value ) {
317                         try{
318                                 self::tryingWrite($attrib);
319                                 $this->__set( $attrib, $value );
320                         }catch(Exception $e){
321                                 self::writeLog($e->getMessage(), $e->getTrace());
322                         }
323                         return $this;
324                 }
325                 
326                 /**
327                  * Unset an attrib.
328                  * Unsets an attrib using ArrayAccess.
329                  *
330                  * @throws DOMBasicAttribNotFoundException
331                  *         If $attrib is not a key in the $_attribs array.
332                  * @throws DOMBasicValueException
333                  *         If the value for a attrib is out of range.
334                  * @param string $attrib The name of the option to unset.
335                  */
336                 public function offsetUnset( $attrib ) {
337                         try{
338                                 self::tryingWrite($attrib);
339                                 $this->__set( $attrib, null );
340                         }catch(Exception $e){
341                                 self::writeLog($e->getMessage(), $e->getTrace());
342                         }
343                 }
344                 //---------------- END: ABSTRACT METHODS INTERFAZ ARRAY-ACCESS --------------
345                 
346                 //---------------- BEGIN: ABSTRACT METHODS INTERFAZ ITERATOR-AGGREGATE --------------
347                 public function getIterator() {
348                         return new ArrayIterator($this->_attribs);
349                 }
350                 //---------------- END: ABSTRACT METHODS INTERFAZ ITERATOR-AGGREGATE --------------
351                 
352                 //---------------- BEGIN: ATTRIBS HANDLER (TAMBIEN __set() DE LOS METODOS MAGICOS) ---------------
353                 /**
354                  * <p>El parametro sera un array asociativo de atributos con pares correctos 'clave=valor'.</p>
355                  * <p>El programador debe asegurarse que son nombres estandarizados para los atributos de elementos DOM.(W3C)</p>
356                  * <p><span title="Filtrado futuro." style="color:navy; background:yellow;">TODO</span>: FILTRADO: 
357                  * <del>Solo se admitiran nombres estandarizados para los atributos de elementos DOM.(W3C)</del></p> 
358                  * @throws DOMBasicAttribNotFoundException
359                  *         If $attrib is not a key in the $_attribs array.
360                  * @throws DOMBasicValueException
361                  *         If the value for a attrib is out of range.
362                  * @param array $asocArrayAttribs The array of the attribs to set.
363                  * @return DOM_element $this este elemento (DOM).
364                  **/
365                 public function setAttribs($asocArrayAttribs){
366                         try{
367                                 self::tryingWrite($asocArrayAttribs);
368                                 if(!is_null($asocArrayAttribs) && is_array( $asocArrayAttribs) ) $this->_attribs=$asocArrayAttribs;
369                         }catch(Exception $e){
370                                 self::writeLog($e->getMessage(), $e->getTrace());
371                         }
372                         return $this;
373                 }
374                 /**
375                  * <p>Retorna todos los atributos establecidos como un array asociativo 'clave=valor'.</p>
376                  * @return array assoc attribs (key=value) or null if not defined.
377                  **/
378                 public function getAttribs(){
379                         return $this->_attribs;
380                 }
381                 /**
382                  * <p>Retorna todos los atributos establecidos como una cadena con los pares 'clave=valor' separados por espacios.</p>
383                  * <p>Si el atributo comienza con la palabra reservada '_null' entonces solo imprimira el valor entrecomillado, por el 
384                  * contrario si el valor es 'nulo' entonces solo imprimira la clave (sin comillas).</p>
385                  * <p>Este metodo esta pensado para poder retornar atributos de etiquetas XHTML (y XML), donde existen casos de atributos 
386                  * sin valor y otros de atributos sin clave (por ej. en la etiqueta 'DOCTYPE')</p>
387                  * <p>Es sinonimo de '__toString()'.</p>
388                  * <p style="background:yellow; color:navy;">OJO !!: Que sea sinonimo no significa que pueda llamarse dentro de esta 
389                  * funcion a '__toString()' ya que crearia una REFERENCIA CIRCULAR!..</p>;
390                  * @return string Cadena de pares 'attrib="attribValue"' separados por espacios
391                  **/
392                 public function getAttribsStr() {
393                         //return $this->__toString();
394                         if(is_null($this->_attribs)) return "";
395                         $cadAttribs="";
396                         foreach($this->_attribs as $clave=>$valor) {
397                                 //echo "toString de attribs2";
398                                 //SIN CLAVE (CLAVE NUMERICA), se entiende entregar unicamente el $valor entrecomillado (por ej. DOCTYPE) 
399                                 if( substr($clave, 0, 5)=="_null" ){
400                                         $cadAttribs .= '"'.$valor.'" ';
401                                 }//SIN VALOR (VALOR NULO), se entiende entrega unicamente la clave (para atributos unicos como 'selected', 'checked', ..)
402                                 elseif(is_null($valor)){
403                                         $cadAttribs .= $clave.' ';
404                                 }else {
405                                         $cadAttribs .= $clave.'="'.$valor.'" ';
406                                 }
407                         }
408                         //$linksHTML[]='<a'.$clase.$id.$name.' href="'.$valor.'"'. ($widthTitle ? (' title="'.$clave.'"') : '') .'>'.$clave.'</a>';
409                         $cadAttribs = ($cadAttribs?(" ".trim($cadAttribs)):"");
410                         return $cadAttribs;
411                 }
412                 /**
413                  * <p>El programador debe asegurarse que los atributos aportados son nombres estandarizados y valores validos 
414                  * para los atributos de elementos DOM.(W3C)</p>
415                  * <p>Retorna <del>el total de los atributos establecidos si no hay exceptcion.</del> $this</p>
416                  * <p><span title="Filtrado futuro." style="color:navy; background:yellow;">TODO</span>: FILTRADO:
417                  * <del>Solo se admitiran nombres estandarizados para los atributos de elementos DOM. (W3C)</del></p> 
418                  * @throws DOMBasicAttribNotFoundException
419                  *         If $attrib is not a key in the $_attribs array.
420                  * @throws DOMBasicValueException
421                  *         If the value for a attrib is out of range.
422                  * @param string $attrib The name of the attrib to add.
423                  * @param mixed $valorAttrib The value of the attrib to add.
424                  * @return DOM_element $this este elemento (DOM).
425                  **/
426                 public function addAttrib($attrib, $valorAttrib){
427                         try{
428                                 self::tryingWrite($attrib);
429                                 if(is_null($this->_attribs)) $this->_attribs=array();
430                                 if(!is_null($attrib)){
431                                         $this->_attribs[$attrib]=$valorAttrib;
432                                 }
433                                 //return count($this->_attribs);
434                         }catch(Exception $e){
435                                 self::writeLog($e->getMessage(), $e->getTrace());
436                         }
437                         //return array_push ( $this->_links, $array);
438                         //return array_push ( $this->_links, new Object($nombreLink => $direccionLink));
439                         return $this;
440                 }
441                 /**
442                  * <p>Añade atributos (si no existian previamente). El parametro sera un array asociativo de atributos con pares correctos 'clave=valor'.</p>
443                  * <p>Retorna <del>el total de los atributos establecidos.</del> $this</p>
444                  * <p>El programador debe asegurarse que son nombres estandarizados (y valores validos) para los atributos de elementos DOM.(W3C)</p>
445                  * <p><span title="Filtrado futuro." style="color:navy; background:yellow;">TODO</span>: FILTRADO:
446                  * <del>Solo se admitiran nombres estandarizados para los atributos de elementos DOM. (W3C)</del></p> 
447                  * @throws DOMBasicAttribNotFoundException
448                  *         If $attrib is not a key in the $_attribs array.
449                  * @throws DOMBasicValueException
450                  *         If the value for a attrib is out of range.
451                  * @param array $arrayAttribs The array of the attribs to add.
452                  * @return DOM_element $this este elemento (DOM).
453                  **/
454                 public function addAttribs($arrayAttribs){
455                         try{
456                                 self::tryingWrite($arrayAttribs);
457                                 foreach($arrayAttribs as $clave=>$valor) {
458                                         $this->_attribs[$clave]=$valor;
459                                 }
460                                 //return count($this->_attribs);
461                         }catch(Exception $e){
462                                 self::writeLog($e->getMessage(), $e->getTrace());
463                         }
464                         return $this;
465                 }
466                 /**
467                  * <p>Suprime o elimina el atributo indicado (si es que existe). Retorna <del>el numero de atributos que quedan.</del> $this</p>
468                  * @throws DOMBasicAttribNotFoundException
469                  *         If $attrib is not a key in the $_attribs array.
470                  * @throws DOMBasicValueException
471                  *         If the value for a attrib is out of range.
472                  * @param string $attrib The name of the attrib to remove.
473                  * @return DOM_element $this este elemento (DOM).
474                  **/
475                 public function removeAttrib($attrib){
476                         try{
477                                 self::tryingWrite($attrib);
478                                 if(is_null($this->_attribs)) $this->_attribs=array();
479                                 unset($this->_attribs[$attrib]);
480                                 //return count($this->_attribs);
481                         }catch(Exception $e){
482                                 self::writeLog($e->getMessage(), $e->getTrace());
483                         }
484                         return $this;
485                 }
486                 /**
487                  * <p>Suprime o elimina todos los atributos indicados (si es que existen). Retorna <del>el numero de atributos que quedan.</del> $this</p>
488                  * @throws DOMBasicAttribNotFoundException
489                  *         If $attrib is not a key in the $_attribs array.
490                  * @throws DOMBasicValueException
491                  *         If the value for a attrib is out of range.
492                  * @param array string $arrayAttribs Array with the attribs's name to remove.
493                  * @return DOM_element $this este elemento (DOM).
494                  **/
495                 public function removeAttribs($arrayAttribs){
496                         try{
497                                 self::tryingWrite($arrayAttribs);
498                                 foreach($arrayAttribs as $attrib) {
499                                         unset($this->_attribs[$attrib]);
500                                 }
501                                 //return count($this->_attribs);
502                         }catch(Exception $e){
503                                 self::writeLog($e->getMessage(), $e->getTrace());
504                         }
505                         return $this;
506                 }
507                 /**
508                  * <p>Suprime o elimina todos los atributos. Retorna <del>el numero de atributos que quedan.</del> $this</p>
509                  * @throws DOMBasicAttribNotFoundException
510                  *         If $attrib is not a key in the $_attribs array.
511                  * @throws DOMBasicValueException
512                  *         If the value for a attrib is out of range.
513                  * @return DOM_element $this este elemento (DOM).
514                  **/
515                 public function clearAttribs(){
516                         try{
517                                 self::tryingWrite($arrayAttribs);
518                                 $this->_attribs=array();
519                                 //return count($this->_attribs);
520                         }catch(Exception $e){
521                                 self::writeLog($e->getMessage(), $e->getTrace());
522                         }
523                         return $this;
524                 }
525                 /**
526                  * <p>Retorna el total de los atribuos establecidos.</p>
527                  * @return int Total de atributos establecidos
528                  **/
529                 public function countAttrs(){
530                         if(is_null($this->_attribs)) $this->_attribs=array();
531                         return count($this->_attribs);
532                 }
533                 //---------------- END: ATTRIBS HANDLER ---------------------------
534                 
535                 /** 
536                  * <p>Compara si otro objeto es igual a este (no si es el mismo); para esto se tienen que cumplir las siguientes normas: </p>
537                  * <ul>
538                  *      <li>Que los dos sean instancias de la misma Clase (DOM_attribs).</li>
539                  *      <li>Que los dos tengan definidos el mismo numero de atributos y con los mismos valores.</li>
540                  * </ul>
541                  * @param DOM_attribs $objAttribs Algun objeto instancia de esta Clase
542                  * @return boolean **/
543                 public function equals($objAttribs) {
544                         if(is_null($objAttribs)) return false;
545                         if(is_null($objAttribs->_attribs)) $objAttribs->_attribs=array();
546                         if(is_null($this->_attribs)) $this->_attribs=array();
547                         //1º COMPARACION SI ES UNA INSTACIA DE ESTA CLASE
548                         if( !($objAttribs instanceof $this) ) return false;     //is_a(), get_class();
549                         //if(! is_subclass_of($objAttribs, self::TAG, false) ) return false;
550                         //2º COMPARACION RAPIDA
551                         $equal =( count($objAttribs->_attribs) == count($this->_attribs) );
552                         //3º COMPARACION ATRIBUTO A ATRIBUTO
553                         if($equal){
554                                 $contador=0;
555                                 foreach($objAttribs->_attribs as $clave=>$valor) {
556                                         foreach($this->_attribs as $clave2=>$valor2) {
557                                                 if(($clave==$clave2) && ($valor==$valor2)) $contador++;
558                                         }
559                                 }
560                                 $equal = ( (count($this->_attribs) == $contador) && (count($objAttribs->_attribs) == $contador) );
561                         }
562                         return $equal;
563                 }
564                 
565                 public function __toString() {
566                         if(is_null($this->_attribs)) return "";
567                         $cadAttribs="";
568                         foreach($this->_attribs as $clave=>$valor) {
569                                 //echo "toString de attribs2";
570                                 $cadAttribs .= $clave.'="'.$valor.'" ';
571                         }
572                         //$linksHTML[]='<a'.$clase.$id.$name.' href="'.$valor.'"'. ($widthTitle ? (' title="'.$clave.'"') : '') .'>'.$clave.'</a>';
573                         $cadAttribs = ($cadAttribs?(" ".trim($cadAttribs)):"");
574                         return $cadAttribs;
575                 }
576                 
577                 /** 
578                  * <p>Retorna una cadena con el formato de las URL's, construida con los Atributos de este Objeto.<br />
579                  * Contiene un parametro $encode indicando el tipo de codificacion a aplicar: 'RFC_1738' (espacios=+) o 'RFC_3986' (espacions=%20),
580                  * las cuales estan implementadas como cadenas staticas de esta clase.</p>
581                  * @param $encode Cadena indicando el tipo de codificacion (alguna de las dos constantes de esta
582                  * clase {@link DOM_attribs->ENCODE_RFC_1738 RFC_1738} o {@link DOM_attribs#ENCODE_RFC_3986 RFC_3986}).
583                  * @return Cadena con formato de codificacion URL. 
584                  **/
585                 protected function toURL($encode = self::ENCODE_RFC_3986) {
586                         $numericPrefix="var";   //en caso de arrays numericos
587                         $argSep="&";
588                         //$this->addAttrib("delete", "%20+-_?¿^*[]¨{}.:,;&");
589                         $attribsURL = http_build_query($this->_attribs, $numericPrefix, $argSep);
590                         //para evitar variables array ... files[]=1&files[]=2& ... sin numeracion hacer lo siguiente:
591                         //preg_replace('/%5B[0-9]+%5D/simU', '%5B%5D', $query);
592                         //$attribsURL = urlencode($attribsURL);
593                         //$attribsURL = urldecode($attribsURL);
594                         //var_dump($attribsURL);
595                         //$attribsURL = rawurlencode($attribsURL);
596                         return $attribsURL;
597                 }
598                 /**
599                  * <p>Establece y retorna un array de atributos con sus correspondientes valores extraidos de una cadena con el formato de las URL's, 
600                  * para construir Atributos de este Objeto.</p>
601                  * <p>El parametro es la cadena desde la que se extraeran los atributos y sus valores, esta cadena tendra el formato de las URL's 
602                  * (relativa o absoluta) donde debe incluirsele una 'queryString' (entre '?' y '#'), Igual a la generada por el metodo toURL().</p>
603                  * @param $strURLquery Cadena desde la que se extraeran los atributos y sus valores, esta cadena tendra el formato entregado en
604                  * las URL's como parte de su 'queryString' (entre '?' y '#').
605                  * @return Array de atributos extraidos de la queryString.
606                  **/
607                 protected function fromURL($strURLquery) {
608                         $attribsURL = self::arrayFromURL($strURLquery);
609                         //var_dump($attribsURL);
610                         $this->setAttribs($attribsURL);
611                         return $attribsURL;
612                 }
613                 /**
614                  * <p>Retorna un array de atributos con sus correspondientes valores extraidos de una cadena con el formato de las URL's.</p>
615                  * <p>El parametro es la cadena desde la que se extraeran los atributos y sus valores, esta cadena tendra el formato de las URL's 
616                  * (relativa o absoluta) donde debe incluirsele una 'queryString' (entre '?' y '#'), Igual a la generada por el metodo toURL().</p>
617                  * @param $strURLquery Cadena desde la que se extraeran los atributos y sus valores, esta cadena tendra el formato entregado en
618                  * las URL's como parte de su 'queryString' (entre '?' y '#').
619                  * @return Array de atributos extraidos de la queryString.
620                  **/
621                 public static function arrayFromURL($strURLquery) {
622                         //$strURLquery ="scheme://user:pass@host.com:port/path?".$strURLquery."#fragment/anchor";
623                         
624                         //
625                         $attribsURL = parse_url($strURLquery);
626                         if( ! array_key_exists("path",$attribsURL) ){
627                                 $attribsURL = parse_url("path.php?" . $strURLquery);
628                         }
629                         if( ! array_key_exists("host",$attribsURL) ){
630                                 $attribsURL = parse_url("www.host.com/" . $strURLquery);
631                         }
632                         if( ! array_key_exists("scheme",$attribsURL) ){
633                                 $attribsURL = parse_url("http://" . $strURLquery);
634                         }
635                         /*
636                         echo "<pre>";
637                         print_r($attribsURL);
638                         echo "</pre>";
639                         */
640                         $attribsURL_str = urldecode( $attribsURL['query'] );
641                         parse_str($attribsURL_str, $attribsURL);
642                         //var_dump($attribsURL);
643                         return $attribsURL;
644                 }
645                 //---------------- FIN LINKS ----------------
646                 
647                 //----------------  BEGIN: JSON  ----------------------------
648                 /**
649                  * <p>Metodo para retornar la cadena JSON que representa estos atributos en la forma '{"clave1":"valor1", "clave2":"valor2"}'.</p>
650                  * <p>Aporta un segundo parametro para codificar todos los valores (no las claves) en 'base64', (DEFECTO=true),
651                  * asi podriamos evitar el problema de los tipos de codificacion empleados (JSON solo admite UTF-8).</p>
652                  * <p>NO UTILIZA LA FUNCION PHP 'json_encode(..)'</p>
653                  * <p><del>Utiliza las siguientes constantes PHP 5.3: JSON_HEX_QUOT && JSON_HEX_TAG && JSON_HEX_AMP && JSON_HEX_APOS</del></p>
654                  * @param boolean $return Indica si retornar el resultado (TRUE) o imprimirlo (FALSE).
655                  * @param boolean $base64values Indica si codificar los textos en 'base64' o no.
656                  * @return String JSON de estos atributos o NULL en caso de desear imprimirlo.
657                  **/
658                 public function toJSON($return=true, $base64values=true) {
659                         //return json_encode($this->toHTML(), JSON_HEX_QUOT && JSON_HEX_TAG && JSON_HEX_AMP && JSON_HEX_APOS);
660                         $array=array();
661                         foreach ($this->getAttribs() as $clave=>$valor){
662                                 $clave = addslashes( htmlspecialchars( utf8_encode($clave) ) );
663                                 $valor = addslashes( htmlspecialchars( utf8_encode($valor) ) );
664                                 $clave=self::filtrarStrJSON($clave);
665                                 $valor=self::filtrarStrJSON($valor);
666                                 if($base64values) {
667                                         $array[]='"'.$clave.'":"'.base64_encode($valor).'"';
668                                 }else{
669                                         $array[]='"'.$clave.'":"'.$valor.'"';
670                                 }
671                         }
672                         //$return = '"'.__CLASS__.'-STATIC":{'.implode(',', $array).'}';
673                         $result = '{'.implode(',', $array).'}';
674                         if ($return) {
675                                 return $result;
676                         } else {
677                                 print $result;
678                                 return null;
679                         }
680                 }
681                 
682                 public function fromJSON($arrJSON) {
683                         self::clearAttribs();
684                         $arrAttribs=array();
685                         foreach ($arrJSON as $clave=>$valor){
686                                 if(is_object($valor)){
687                                         foreach ($valor as $key=>$value){
688                                                 $arrAttribs[$key]=$valor;
689                                         }
690                                 }
691                         }
692                         self::setAttribs($arrAttribs);
693                         return $this;
694                 }
695
696                 /** Limpia una cadena de RETORNOS DE CARRO, AVANCES DE LINEA y TABULACIONES, preparandola asi para datos JSON **/
697                 public static function filtrarStrJSON($str=""){
698                         /*
699                          $str = str_replace('\t', '', $str);
700                         $str = str_replace('\n', '', $str);
701                         $str = str_replace('\r', '', $str);
702                         */
703                         //$str = strtr($str, '\r\n\t', '');//array('\r','\n','\t'), array('','','')
704                         $str = strtr($str, array("\r"=>'',"\n"=>'',"\t"=>''));
705                         return $str;
706                 }
707                 //----------------  END: JSON  ------------------------------
708                 
709                 //METODO PARA MENSAJEAR AL LOG
710                 public static function writeLog($mensaje, $trace){
711                         echo '<pre class="doom-exception" style="background:pink; font-size:x-small;">';
712                         echo "<h2>EXCEPTION:</h2><ul><code>";
713                         echo "<li>MENSAJE: ".$mensaje."</li><li>TRACE: ";
714                         print_r($trace);
715                         echo "</li></code></ul></pre>";
716                 }
717                 //METODO PARA INSERTAR DATOS DE EJEMPLO
718                 public function setEjemplo(){
719                         $this->_data=array("attr_1"=>"valor del atributo 1", "attr_2"=>"valor del atributo 2");
720                 }
721         }
722 ?>