Como precondición, es necesario disponer de una URL referencial (es decir, la URL donde estaba el enlace). Esta URL referencial tiene una estructura de Array del siguiente tipo:
$mxReferer = array ("protocol" => "","domain"=>"","uri"=>"","params"=>"","anchor"=>"");
LLamaremos a la función enviando la URL, que puede ser relativa, pero siempre al referente. Es decir: recogeremos del referente la información que falta en la URL analizada.
Para el caso que presento en el código de muestra, se supone que estamos en el documento "http://www.sopadebits.com/un_primer_post" y nos encontramos con un enlace cuyo atributo href es "/cuando_etiquetas_un_recurso".
El código de la función es:
$mxReferer = array
(
"protocol" => "http",
"domain" => "www.sopadebits.com",
"uri" => "content/view/",
"params" => "",
"anchor" => ""
);
print_r(tokenizeUrl("/un_primer_post"));
function tokenizeUrl($szUrl = false,$mxReferer = false)
{
if($szUrl == false || $mxReferer == false)
return false;
$mxTokens = array();
preg_match
(
"/^(((http|https|ftp):)?(\/\/)?|\/)([\w\.\/\_-%=&@]+)*((?)[\w\.\/\_-%=&@]+)?((#)[\w\.\/\_-%=&@]+)?$/i",
$szUrl,
$mxUrl
);
if($mxUrl[5] == '')
$mxUrl[5] = $mxReferer['uri'];
$mxUri = explode("/",$mxUrl[5]);
if($mxUrl[1] == $mxUrl[4])
{
$mxTokens['protocol'] = $mxReferer['protocol'];
if($mxUrl[4]=='//')
{
// no protocol, yes domain
$mxTokens['domain'] = $mxUri[0];
array_shift($mxUri);
}
else
{
// no protocol, no domain
$mxTokens['domain'] = $mxReferer['domain'];
}
}
else
{
if($mxUrl[4] == '//')
{
// no protocol, yes domain
$mxTokens['protocol'] = $mxUrl[3];
$mxTokens['domain' ] = $mxUri[0];
array_shift($mxUri);
}
else
{
// no protocol, no domain
$mxTokens['protocol'] = $mxReferer['protocol'];
$mxTokens['domain' ] = $mxReferer['domain'];
}
}
if(isset($mxUrl[7]))
{
$mxTokens['params'] = substr($mxUrl[6],1,strlen($mxUrl[6])-1);
}
if(isset($mxUrl[9]))
{
$mxTokens['anchor'] = substr($mxUrl[8],1,strlen($mxUrl[8])-1);
}
$mxTokens['uri'] = implode("/",$mxUri);
return $mxTokens;
}
?>
El resultado debe(ría) ser:
array
(
"protocol" => "http",
"domain" => "www.sopadebits.com",
"uri" => "/cuando_etiquetas_un_recurso"
)
Los parámetros y el ancla son opcionales. La simplicidad apremia, ya que trato lo que va "después" del dominio como un todo, sin importarme si se trata de un archivo php, html ni nada por el estilo.
A lo que vamos: la expresión regular. A ver si así se ve mejor:
/^(((http|https|ftp):)?(\/\/)?|\/)([\w\.\/\_-%=&@]+)*((?)[\w\.\/\_-%=&@]+)?((#)[\w\.\/\_-%=&@]+)?$/i
No me estoy acordando de la familia de nadie, que conste...
^ : Esto indica que la expresión se debe encontrar al principio de línea (es decir, que si hubiera espacios en blanco al principio, no se encontrarían coincidencias. Se podría realizar un trim pero eso ya lo dejo para quien le interese).
(((http|https|ftp):)?(\/\/)?|\/)
Esta parte verifica si la URL tiene el protocolo indicado, y en caso afirmativo, verifica que se trata de http, https o ftp. Incluso el FTP podría sobrar, pero mira... viene de propina ;-)
Como vemos, se abren tres paréntesis. Esto indica que la cadena que concuerde se guardará en una matriz ($mxUrl para el caso del código anterior).
Esto es importante: las URLs se pueden indicar en la forma "//dominio/uri...". Es decir, no siempre debe indicarse el protocolo. Lo más conocido es que suponga el nombre de dominio y que por lo tanto empiece por "/uri...", pero he querido asegurar esta posibilidad.
Los tres paréntesis siguientes son prácticamente idénticos. El primero corresponde a la URI, el segundo a los parámetros indicados con el interrogante y el tercero es el ancla. Echando un vistazo, sólo se diferencian del primer carácter de la expresión, que es lo que indica cuándo empieza uno y acaba el otro. La expresión:
([\w\.\/\_-%=&@]+)*
Busca 0 o más coincidencias (el asterisco) para un carácter alfanumérico (w), punto, barra, guión bajo o medio, signo % (esto es para los caracteres codificados), signo igual, ampersand y arroba. Esto puede ser una cadena (el signo + después del corchete indica que se pueden encontrar 1 o más ocurrencias) y los caracteres aceptados pueden estar en cualquier orden (se indican dentro de un corchete).
Bueno, creo que con esto ya basta por hoy. Si falta algún carácter, quizá se lo haya tragado el editor de HTML.
© 2007 and beyond Mario Alberich, licensed under CC-BY-SA unless stated otherwise.