PageRenderTime 170ms CodeModel.GetById 81ms app.highlight 42ms RepoModel.GetById 38ms app.codeStats 1ms

/library/text.php

https://github.com/alugo/Goteo
PHP | 680 lines | 477 code | 76 blank | 127 comment | 62 complexity | f4fe4447c82f674265c47933ed2accd2 MD5 | raw file
  1<?php
  2/*
  3 *  Copyright (C) 2012 Platoniq y Fundación Fuentes Abiertas (see README for details)
  4 *	This file is part of Goteo.
  5 *
  6 *  Goteo is free software: you can redistribute it and/or modify
  7 *  it under the terms of the GNU Affero General Public License as published by
  8 *  the Free Software Foundation, either version 3 of the License, or
  9 *  (at your option) any later version.
 10 *
 11 *  Goteo is distributed in the hope that it will be useful,
 12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14 *  GNU Affero General Public License for more details.
 15 *
 16 *  You should have received a copy of the GNU Affero General Public License
 17 *  along with Goteo.  If not, see <http://www.gnu.org/licenses/agpl.txt>.
 18 *
 19 */
 20
 21
 22namespace Goteo\Library {
 23
 24	use Goteo\Core\Model,
 25		Goteo\Core\Registry,
 26        Goteo\Core\Exception;
 27	/*
 28	 * Clase para sacar textos dinámicos de la tabla text
 29     *  @TODO, definir donde se define y se cambia la constante LANG y utilizarla en los _::get_
 30	 */
 31    class Text {
 32
 33        public
 34            $id,
 35            $lang,
 36            $text,
 37            $purpose,
 38            $html,
 39            $pendiente; // no traducido
 40
 41        /*
 42         * Devuelve un texto en HTML
 43         */
 44        static public function html ($id) {
 45            // sacamos el contenido del texto
 46            $text = call_user_func_array ( 'static::get' , \func_get_args() );
 47            if (self::isHtml($id))
 48                return $text; // el texto ES html, lo devuelve tal cual
 49            else
 50                return \htmlspecialchars ($text); // el texto NO es html, lo pasa por html especial chars
 51        }
 52
 53        /*
 54         * Devuelve un texto sin HTML
 55         */
 56        static public function plain ($id) {
 57            // sacamos el contenido del texto
 58            $text = call_user_func_array ( 'static::get' , \func_get_args() );
 59            if (self::isHtml($id))
 60                return \strip_tags($text) ; // ES html, le quitamos los tags
 61            else
 62                return $text;
 63        }
 64
 65        /*
 66         * Devuelve un texto con comillas escapadas para usarlo en javascript
 67         */
 68        static public function slash ($id) {
 69            // sacamos el contenido del texto
 70            $text = call_user_func_array ( 'static::get' , \func_get_args() );
 71            return \addslashes($text);
 72        }
 73
 74        static public function getAdmin ($id) {
 75
 76
 77			// buscamos el texto en la tabla, si no está sacamos el propósito
 78            $values = array(':id'=>$id, ':lang' => LANG);
 79
 80            $sql = "SELECT
 81                        IFNULL(text.text,purpose.purpose) as `text`
 82                    FROM purpose
 83                    LEFT JOIN text
 84                        ON text.id = purpose.text
 85                        AND text.lang = :lang
 86                    WHERE text.id = :id
 87                    ";
 88
 89			$query = Model::query($sql, $values);
 90            return $query->fetchObject()->text;
 91		}
 92
 93        static public function getTrans ($id) {
 94
 95            $lang = $_SESSION['translate_lang'];
 96
 97			// buscamos el texto en la tabla, si no está sacamos el propósito
 98            $values = array(':id'=>$id, ':lang' => $lang);
 99
100            $sql = "SELECT
101                        IFNULL(text.text,purpose.purpose) as `text`
102                    FROM purpose
103                    LEFT JOIN text
104                        ON text.id = purpose.text
105                        AND text.lang = :lang
106                    WHERE text.id = :id
107                    ";
108
109			$query = Model::query($sql, $values);
110            return $query->fetchObject()->text;
111		}
112
113		/**
114		 * Gettext-like interface for the i18n of interface strings.
115		 *
116		 * @param string $str string to translate
117		 * @return string translated version
118		 */
119		static public function _($str) {
120			return Registry::get('translate')->text($str);
121		}
122
123        static public function get ($id) {
124
125            $lang = LANG;
126
127            if (\defined('GOTEO_ADMIN_NOCACHE')) {
128                $nocache = true;
129            } else {
130                $nocache = false;
131            }
132
133            // si hay mas de un argumento, hay que meter el resto con
134            $args = \func_get_args();
135            if (count($args) > 1) {
136                array_shift($args);
137            } else {
138                $args = array();
139            }
140
141			// buscamos el texto en cache
142			static $_cache = array();
143			if (!$nocache && isset($_cache[$id][$lang]) && empty($args)) {
144				return $_cache[$id][$lang];
145            }
146
147			// buscamos el texto en la tabla
148            $values = array(':id'=>$id, ':lang' => $lang);
149
150            // Español de purpose como alternativa
151            $sql_es = "SELECT
152                        IFNULL(text.text,purpose.purpose) as `text`
153                    FROM purpose
154                    LEFT JOIN text
155                        ON text.id = purpose.text
156                        AND text.lang = :lang
157                    WHERE purpose.text = :id
158                    ";
159            // Inglés como alternativa
160            $sql_en = "SELECT
161                        IFNULL(text.text, eng.text) as `text`
162                    FROM purpose
163                    LEFT JOIN text
164                        ON text.id = purpose.text
165                        AND text.lang = :lang
166                    LEFT JOIN text as eng
167                        ON  eng.id = purpose.text
168                        AND eng.lang = 'en'
169                    WHERE purpose.text = :id
170                    ";
171            // idiomas no españoles usan alternativa en inglés
172            $sql = (in_array($lang, array('es','ca', 'gl', 'eu', 'en'))) ? $sql_es : $sql_en;
173            $query = Model::query($sql, $values);
174			if ($exist = $query->fetchObject()) {
175                $tmptxt = $_cache[$id][$lang] = $exist->text;
176
177                //contamos cuantos argumentos necesita el texto
178                $req_args = \substr_count($exist->text, '%');
179
180                if (!empty($args) && $req_args > 0 && count($args) >= $req_args) {
181                    $texto = $nocache ? vsprintf($exist->text, $args) : vsprintf($tmptxt, $args);
182                } else {
183                    $texto = $nocache ? $exist->text : $tmptxt;
184                }
185
186			} else {
187                // para catalogar textos nuevos
188//				Model::query("REPLACE INTO purpose (text, purpose, html, `group`) VALUES (:text, :purpose, NULL, 'new')", array(':text' => $id, ':purpose' => $id));
189                $texto = $id;
190			}
191
192            $texto = nl2br($texto);
193
194            return $texto;
195		}
196
197		static public function getPurpose ($id) {
198			// buscamos la explicación del texto en la tabla
199			$query = Model::query("SELECT purpose, html FROM purpose WHERE `text` = :id", array(':id' => $id));
200			$exist = $query->fetchObject();
201			if (!empty($exist->purpose)) {
202                return $exist->purpose;
203			} else {
204				Model::query("REPLACE INTO purpose (text, purpose) VALUES (:text, :purpose)", array(':text' => $id, ':purpose' => "Texto $id"));
205				return 'Texto: ' . $id;
206			}
207		}
208
209        /*
210         * Si un texto esta marcado como html devuelve true, si no está marcado así, false
211         * Se marca en la tabla de propósitos ya que en la tabla texts habría que marcarlo en cada idioma
212         */
213		static public function isHtml ($id) {
214            try
215            {
216                // lo miramos en la tabla de propósitos
217                $query = Model::query("SELECT html FROM purpose WHERE text = :id", array(':id' => $id));
218                $purpose = $query->fetchObject();
219                if ($purpose->html == 1)
220                    return true;
221                else
222                    return false;
223            } catch (\PDOException $e) {
224                return false; // Si la tabla purpose no tiene el campo html
225            }
226		}
227
228
229		/*
230		 *  Metodo para la lista de textos segun idioma
231		 */
232		public static function getAll($filters = array(), $lang = null) {
233            $texts = array();
234
235            $values = array(':lang' => $lang);
236
237            $sql = "SELECT
238                        purpose.text as id,
239                        IFNULL(text.text,purpose.purpose) as text,
240                        IF(text.text IS NULL, 1, 0) as pendiente,
241                        purpose.`group` as `group`
242                    FROM purpose
243                    LEFT JOIN text
244                        ON text.id = purpose.text
245                        AND text.lang = :lang
246                    WHERE purpose.text != ''
247                    ";
248            if (!empty($filters['idfilter'])) {
249                $sql .= " AND purpose.text LIKE :idfilter";
250                $values[':idfilter'] = "%{$filters['idfilter']}%";
251            }
252            if (!empty($filters['group'])) {
253                $sql .= " AND purpose.`group` = :group";
254                $values[':group'] = "{$filters['group']}";
255            }
256            if (!empty($filters['text'])) {
257                $sql .= " AND ( text.text LIKE :text OR (text.text IS NULL AND purpose.purpose LIKE :text ))";
258                $values[':text'] = "%{$filters['text']}%";
259            }
260            // pendientes de traducir
261            if (!empty($filters['pending'])) {
262                $sql .= " HAVING pendiente = 1";
263            }
264            $sql .= " ORDER BY pendiente DESC, text ASC";
265            
266            try {
267                $query = Model::query($sql, $values);
268                foreach ($query->fetchAll(\PDO::FETCH_CLASS, __CLASS__) as $text) {
269                    $texts[] = $text;
270                }
271                return $texts;
272            } catch (\PDOException $e) {
273                throw new Exception($e->getMessage() . "<br />$sql<br /><pre>" . print_r($values, 1) . "</pre>");
274            }
275		}
276
277		/*
278		 *  Esto se usa para traducciones
279		 */
280		public static function save($data, &$errors = array()) {
281			if (!is_array($data) ||
282				empty($data['id']) ||
283				empty($data['text']) ||
284				empty($data['lang'])) {
285					return false;
286			}
287
288            $sql = "REPLACE `text` SET
289                            `text` = :text,
290                            id = :id,
291                            lang = :lang
292                    ";
293			if (Model::query($sql, array(':text' => $data['text'], ':id' => $data['id'], ':lang' => $data['lang']))) {
294				return true;
295			} else {
296				$errors[] = 'Error al insertar los datos <pre>' . print_r($data, 1) . '</pre>';
297				return false;
298			}
299		}
300
301		/*
302		 *  Esto se usa para gestión de originales
303		 */
304		public static function update($data, &$errors = array()) {
305			if (!is_array($data) ||
306				empty($data['id']) ||
307				empty($data['text'])) {
308					return false;
309			}
310
311            $sql = "UPDATE `purpose` SET
312                            `purpose` = :text
313                            WHERE `text` = :id
314                    ";
315			if (Model::query($sql, array(':text' => $data['text'], ':id' => $data['id']))) {
316				return true;
317			} else {
318				$errors[] = 'Error al insertar los datos <pre>' . print_r($data, 1) . '</pre>';
319				return false;
320			}
321		}
322
323        /*
324         * Grupos de textos
325         */
326        static public function groups()
327        {
328            $groups = array(
329                'home' => static::_('Portada'),
330                'public_profile' => static::_('Pagina de perfil de usuario'),
331                'project'  => static::_('Proyecto, pública y formulario'),
332                'form'     => static::_('Generales del formulario de proyecto'),
333                'profile'  => static::_('Gestión de perfil del usuario'),
334                'personal' => static::_('Datos personales del usuario'),
335                'overview' => static::_('Descripción del proyecto'),
336                'costs'    => static::_('Costes del proyecto'),
337                'rewards'  => static::_('Retornos y recompensas del proyecto'),
338                'supports' => static::_('Colaboraciones del proyecto'),
339                'preview'  => static::_('Previsualización del proyecto'),
340                'dashboard'=> static::_('Dashboard del usuario'),
341                'register' => static::_('Registro de usuarios'),
342                'login'    => static::_('Pagina de login'),
343                'discover'  => static::_('Sección descubre proyectos'),
344                'community'  => static::_('Sección comunidad'),
345                'general'  => static::_('Propósito general'),
346                'blog'  => static::_('Blog/Actualizaciones'),
347                'faq'  => static::_('Pagina de FAQ'),
348                'contact'  => static::_('Pagina de contacto'),
349                'widget'  => static::_('Banderolos'),
350                'invest'  => static::_('Pagina de aportar a un proyecto'),
351                'types' => static::_('Tooltips para tipos de necesidades'),
352                'banners' => static::_('Banners y cabeceras'),
353                'footer' => static::_('Footer'),
354                'social' => static::_('Cuentas de redes sociales'),
355                'review' => static::_('Panel revisor'),
356                'translate' => static::_('Panel traductor'),
357                'menu' => static::_('Menu superior'),
358                'feed' => static::_('Eventos recientes'),
359                'mailer' => static::_('Emails automaticos'),
360                'bluead' => static::_('Avisos azules'),
361                'error' => static::_('Errores catastroficos'),
362                'call_public' => static::_('Convocatorias: publicos'),
363                'call_form' => static::_('Convocatorias: formulario'),
364                'call_dash' => static::_('Convocatorias: dashboard'),
365                'wof' => static::_('Wall of friends'),
366                'node_public' => static::_('Nodos'),
367                'contract' => static::_('Formulario Contrato')
368            );
369
370            \asort($groups);
371
372            return $groups;
373        }
374
375        /*
376         * Devuelve el número de palabras del contenido recibido
377         */
378        static public function wordCount ($section, $table, $fields = array(), &$total = 0 ) {
379
380            $count = 0;
381            $sqlFilter = '';
382
383            switch ($section) {
384                case 'texts':
385                    // todos son de la tabla purpose, $table nos indica la agrupación
386                    //  y hay que filtrar la columna group
387                    $sqlFilter = " WHERE `group` = '{$table}'";
388                    $table = 'purpose';
389                    $fields = array('purpose');
390                    break;
391                case 'pages':
392                    // table nos indica si es la de descripciones o la de contenido,
393                    //  en la de contenido hay que filtrar nodo goteo y español
394                    if ($table == 'page_node') {
395                        $sqlFilter = " WHERE node = 'goteo' AND lang = 'es'";
396                    }
397                    break;
398                case 'contents':
399                case 'home':
400                    // ojo! post es solo del blog 1 (goteo)
401                    if ($table == 'post') {
402                        $sqlFilter = " WHERE blog = '1'";
403                    }
404                    break;
405            }
406
407            // seleccionar toda la tabla,
408            $sql = "SELECT ".implode(', ', $fields)." FROM {$table}{$sqlFilter}";
409			$query = Model::query($sql, $values);
410            foreach ($query->fetchAll(\PDO::FETCH_ASSOC) as $row) {
411                // para cada campo
412                foreach ($fields as $field) {
413                    // contar palabras (ojo! hay que quitar los tags html)
414                    $count += count(explode(' ', \strip_tags($row[$field])));
415                }
416            }
417
418            $total += $count;
419
420            return $count;
421        }
422
423
424        /*
425         * Devuelve el código embed de un widget de proyecto
426         */
427        static public function widget ($url, $type = 'project', $styles = null) {
428
429            $style = (isset($styles)) ? ' style="'.$styles.'"' : '';
430            
431            switch ($type) {
432                case 'fb':
433                    $code = '<div class="fb-like" data-href="'.$url.'" data-send="false" data-layout="button_count" data-width="450" data-show-faces="false"></div>';
434                    break;
435                case 'fb-nocount':
436                    $code = '<div class="fb-like"'.$style.' data-href="'.$url.'" data-send="false" data-layout="box_count" data-width="0" data-height="0" data-show-faces="false"></div>';
437                    break;
438                case 'wof':
439                    $code = '<iframe frameborder="0" height="100%" src="'.$url.'" width="630px" scrolling="no"></iframe>';
440                    break;
441                case 'project':
442                default:
443                    $code = '<iframe frameborder="0" height="480px" src="'.$url.'" width="250px" scrolling="no"></iframe>';
444                    break;
445            }
446
447            return $code;
448        }
449
450        /*
451         * Devuelve array de urls para compartir en redes sociales
452         */
453        static public function shareLinks ($url, $title) {
454
455            $urls = array(
456                'twitter' => 'http://twitter.com/home?status=' . rawurlencode($title . ': ' . $url . ' #Goteo'),
457                'facebook' => 'http://facebook.com/sharer.php?u=' . rawurlencode($url . '&t=' . rawurlencode($title)) 
458            );
459            
460            return $urls;
461        }
462
463		/*
464		 *   Pone el enlace a gmaps segun localidad
465         * @TODO , ponerle el LANG
466		 */
467		static public function GmapsLink($location)
468		{
469			$texto = '<a href="http://maps.google.es/maps?q='.htmlspecialchars(rawurlencode($location)).'&hl=es" target="_blank">'.htmlspecialchars($location).'</a>';
470			return $texto;
471		}
472
473		/*
474		 *   Método para formatear friendly un texto para ponerlo en la url
475		 */
476		static public function urliza($texto)
477		{
478			$texto = trim(strtolower($texto));
479			// Acentos
480//			$texto = strtr($texto, "ÁÀÄÂáàâäÉÈËÊéèêëÍÌÏÎíìîïÓÒÖÔóòôöÚÙÛÜúùûüÇçÑñ", "aaaaaaaaeeeeeeeeiiiiiiiioooooooouuuuuuuuccnn");
481            $table = array(
482                'Š'=>'S', 'š'=>'s', 'Đ'=>'Dj', 'đ'=>'dj', 'Ž'=>'Z', 'ž'=>'z', 'Č'=>'C', 'č'=>'c', 'Ć'=>'C', 'ć'=>'c',
483                'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E',
484                'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O',
485                'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U', 'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss',
486                'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c', 'è'=>'e', 'é'=>'e',
487                'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o',
488                'ô'=>'o', 'õ'=>'o', 'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'ý'=>'y', 'þ'=>'b',
489                'ÿ'=>'y', 'Ŕ'=>'R', 'ŕ'=>'r',
490            );
491
492            $texto = strtr($texto, $table);
493			// Separadores
494			$texto = preg_replace("/[\s\,\;\_\/\-]+/i", "-", $texto);
495			$texto = preg_replace("/[^a-z0-9\.\-\+]/", "", $texto);
496			return $texto;
497		}
498
499		/*
500		 *   Método para recortar un texto
501		 */
502		static public function recorta ($texto, $longitud, $puntos = '...')  {
503			// Es HTML?
504			$html = (strip_tags($texto) != $texto);
505			$palabras_vacias = array();
506			$separadores = array(" ",".",",",";");
507
508			$palabras_vacias = array ("un", "uno", "unos", "unas", "una",
509			"dos", "tres", "cuatro", "cinco", "seis", "siete", "ocho", "nueve", "diez",
510			"el", "la", "los", "las", "lo",
511			"que",
512			"o", "y", "u", "e", "a",
513			"ante", "bajo", "cabe", "con", "contra", "de", "desde", "hasta", "hacia", "para", "por", "según", "sin", "sobre", "tras", "durante", "mediante",
514			);
515
516			$texto = trim($texto);
517			if (strlen($texto) <= $longitud) return $texto;
518			$texto = substr($texto,0,$longitud);
519
520			// Buscamos el último espacio
521			$texto = substr($texto, 0, strrpos($texto, " "));
522
523			// Quitamos palabras vacías
524			$ultima = self::ultima_palabra($texto,$separadores );
525			while ($texto != "" && (in_array($ultima,$palabras_vacias) || strlen($ultima)<=2) || ($html && $ultima{1} == "<" && substr($ultima,-1) == ">")) {
526				$texto = substr($texto,0,strlen($texto)-strlen($ultima));
527				while ($texto != "" && in_array(substr($texto,-1),$separadores)){
528					$texto = substr($texto, 0, -1);
529				}
530				$ultima = self::ultima_palabra($texto,$separadores);
531			}
532
533			// Hemos cortado una etiqueta html?
534			if ($html && strrpos($texto,"<") > strrpos($texto,">")) {
535				$texto = substr($texto,0,strrpos($texto,"<"));
536			}
537			// Si el texto era html, cerramos las etiquetas
538			if ($html) $texto = self::cerrar_etiquetas($texto);
539			if ($puntos !== false) $texto .= $puntos;
540			return $texto;
541		}
542
543        static public function ultima_palabra ($texto, $separadores = false) {
544            $palabra = '';
545            if ($separadores === false) $separadores = array(" ", ".", ",", ";");
546            $i = strlen($texto) - 1;
547            while ($i >= 0 && (!in_array(substr($texto,$i,1), $separadores))) {
548                $palabra = substr($texto,$i,1).$palabra;
549                $i--;
550            }
551            return $palabra;
552        }
553
554        static public function cerrar_etiquetas ($html) {
555            // Ponemos todos los tags abiertos en un array
556            preg_match_all("#<([a-z]+)( .*)?(?!/)>#iU", $html, $res);
557            $abiertas = $res[1];
558
559            // Ponemos todos los tags cerrados en un array
560            preg_match_all("#</([a-z]+)>#iU", $html, $res);
561            $cerradas = $res[1];
562
563            // Obtenemos el array de etiquetas no cerradas
564
565            if (count($cerradas) == count($abiertas)) {
566                // *Suponemos* que todas las etiquetas están cerradas
567                return $html;
568            }
569
570            $abiertas = array_reverse($abiertas);
571
572            // Cerramos
573            for ($i = 0;$i < count($abiertas);$i++) {
574                if (!in_array($abiertas[$i],$cerradas)){
575                    $html .= "</".$abiertas[$i].">";
576                } else {
577                    unset($cerradas[array_search($abiertas[$i],$cerradas)]);
578                }
579            }
580            return $html;
581        }
582
583
584		/*
585		 *   Método para aplicar saltos de linea y poner links en las url
586         *   ¿¡Como se puede ser tan guay!?
587         *   http://www.kwi.dk/projects/php/UrlLinker/
588         * -------------------------------------------------------------------------------
589         *  UrlLinker - facilitates turning plaintext URLs into HTML links.
590         *
591         *  Author: Søren Løvborg
592         *
593         *  To the extent possible under law, Søren Løvborg has waived all copyright
594         *  and related or neighboring rights to UrlLinker.
595         *  http://creativecommons.org/publicdomain/zero/1.0/
596         * -------------------------------------------------------------------------------
597		 */
598		static public function urlink($text)
599		{
600            /*
601             *  Regular expression bits used by htmlEscapeAndLinkUrls() to match URLs.
602             */
603            $rexProtocol = '(https?://)?';
604            $rexDomain   = '((?:[-a-zA-Z0-9]{1,63}\.)+[-a-zA-Z0-9]{2,63}|(?:[0-9]{1,3}\.){3}[0-9]{1,3})';
605            $rexPort     = '(:[0-9]{1,5})?';
606            $rexPath     = '(/[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]*?)?';
607            $rexQuery    = '(\?[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]+?)?';
608            $rexFragment = '(#[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]+?)?';
609            $rexUrlLinker = "{\\b$rexProtocol$rexDomain$rexPort$rexPath$rexQuery$rexFragment(?=[?.!,;:\)\"]?(,|\s|\)|$))}";
610
611            /**
612             *  $validTlds is an associative array mapping valid TLDs to the value true.
613             *  Since the set of valid TLDs is not static, this array should be updated
614             *  from time to time.
615             *
616             *  List source:  http://data.iana.org/TLD/tlds-alpha-by-domain.txt
617             *  Last updated: 2010-09-04
618             */
619            $validTlds = array_fill_keys(explode(" ", ".ac .ad .ae .aero .af .ag .ai .al .am .an .ao .aq .ar .arpa .as .asia .at .au .aw .ax .az .ba .bb .bd .be .bf .bg .bh .bi .biz .bj .bm .bn .bo .br .bs .bt .bv .bw .by .bz .ca .cat .cc .cd .cf .cg .ch .ci .ck .cl .cm .cn .co .com .coop .cr .cu .cv .cx .cy .cz .de .dj .dk .dm .do .dz .ec .edu .ee .eg .er .es .et .eu .fi .fj .fk .fm .fo .fr .ga .gb .gd .ge .gf .gg .gh .gi .gl .gm .gn .gov .gp .gq .gr .gs .gt .gu .gw .gy .hk .hm .hn .hr .ht .hu .id .ie .il .im .in .info .int .io .iq .ir .is .it .je .jm .jo .jobs .jp .ke .kg .kh .ki .km .kn .kp .kr .kw .ky .kz .la .lb .lc .li .lk .lr .ls .lt .lu .lv .ly .ma .mc .md .me .mg .mh .mil .mk .ml .mm .mn .mo .mobi .mp .mq .mr .ms .mt .mu .museum .mv .mw .mx .my .mz .na .name .nc .ne .net .nf .ng .ni .nl .no .np .nr .nu .nz .om .org .pa .pe .pf .pg .ph .pk .pl .pm .pn .pr .pro .ps .pt .pw .py .qa .re .ro .rs .ru .rw .sa .sb .sc .sd .se .sg .sh .si .sj .sk .sl .sm .sn .so .sr .st .su .sv .sy .sz .tc .td .tel .tf .tg .th .tj .tk .tl .tm .tn .to .tp .tr .travel .tt .tv .tw .tz .ua .ug .uk .us .uy .uz .va .vc .ve .vg .vi .vn .vu .wf .ws .xn--0zwm56d .xn--11b5bs3a9aj6g .xn--80akhbyknj4f .xn--9t4b11yi5a .xn--deba0ad .xn--fiqs8s .xn--fiqz9s .xn--fzc2c9e2c .xn--g6w251d .xn--hgbk6aj7f53bba .xn--hlcj6aya9esc7a .xn--j6w193g .xn--jxalpdlp .xn--kgbechtv .xn--kprw13d .xn--kpry57d .xn--mgbaam7a8h .xn--mgbayh7gpa .xn--mgberp4a5d4ar .xn--o3cw4h .xn--p1ai .xn--pgbs0dh .xn--wgbh1c .xn--xkc2al3hye2a .xn--ygbi2ammx .xn--zckzah .ye .yt .za .zm .zw"), true);
620
621            /**
622             *  Transforms plain text into valid HTML, escaping special characters and
623             *  turning URLs into links.
624             */
625            $result = "";
626
627            $position = 0;
628            while (preg_match($rexUrlLinker, $text, $match, PREG_OFFSET_CAPTURE, $position))
629            {
630                list($url, $urlPosition) = $match[0];
631
632                // Add the text leading up to the URL.
633                $result .= htmlspecialchars(substr($text, $position, $urlPosition - $position));
634
635                $domain = $match[2][0];
636                $port   = $match[3][0];
637                $path   = $match[4][0];
638
639                // Check that the TLD is valid (or that $domain is an IP address).
640                // Quitamos esto para que no confunda los millares con ips
641                //preg_match('{^\.[0-9]{1,3}$}', $tld) ||
642                $tld = strtolower(strrchr($domain, '.'));
643                if (isset($validTlds[$tld]))
644                {
645                    // Prepend http:// if no protocol specified
646                    $completeUrl = $match[1][0] ? $url : "http://$url";
647
648                    // Add the hyperlink.
649                    $result .= '<a href="' . htmlspecialchars($completeUrl) . '" target="_blank">'
650                        . htmlspecialchars("$domain$port$path")
651                        . '</a>';
652                }
653                else
654                {
655                    // Not a valid URL.
656                    $result .= htmlspecialchars($url);
657                }
658
659                // Continue text parsing from after the URL.
660                $position = $urlPosition + strlen($url);
661            }
662
663            // Add the remainder of the text.
664            $result .= htmlspecialchars(substr($text, $position));
665            return $result;
666
667
668		}
669
670        /*
671         * Método para ocultar parámetros de una url
672         */
673        public static function cutUrlParams($url) {
674            return $url = preg_replace('#/.+#', '', preg_replace('#http|s?://#', '', $url));
675        }
676        
677        
678	}
679    
680}