#! /usr/bin/php4 -qC ------------------------------------------------------------------------------- $Id$ -----------------------------------------------------------------------------*/ //Recibe como parametros el directorio o una lista de archivos a diagramar //TAG's XML {{{ $comienzo = << EOT; $medio = << EOT2; $fin = << EOT3; //}}} //LINEAS TEMPLATES XMI {{{ $umlclass = ''; $umlclass_c = ''; $umloperation = ''; $umloperation_c = ''; $umlparameter = ''; $umlattribute = ''; $umllistitem = ''; $umllistitem_c = ''; //}}} //VARIABLES GLOBALES {{{ $ID = 0; $IDPARAM = 0; $ARRAY = array(); //}}} //CHUPO LA INFO DE LOS ARCHIVOS {{{ for ($j = 1; $j < count($argv); $j++) { $file = $argv[$j]; //ARMO LA LISTA DE ARCHIVOS {{{ // Si es un directorio, agrego cada archivo legible .php al argv. if (is_dir($file)) { $dh = opendir($file); while (($f = readdir($dh)) !== false) { if (is_readable("$file/$f") and substr($f, -4) == '.php') { $argv[] = "$file/$f"; } } closedir($dh); continue; } //}}} //GUARDO LA INFO{{{ elseif (is_readable($file) and substr($file, -4) == '.php') { $cont = file ($file); $DOCUMENTANDO = false; $opciones = array (); $cont_param = -1; foreach ($cont as $linea) { $linea = trim ($linea); $tmp = preg_split ('/[^\w_\/\*\@\$\&\.\']+/', $linea); //DOCUMENTANDO? {{{ if ($tmp['0'] == '/**') { //Comienza la documentacion $DOCUMENTANDO = true; $doc_param = 0; } if ($tmp['0'] == '*/') { //Termina la documentacion $DOCUMENTANDO = false; $doc_param = 0; } //}}} //DOCUMENTANDO{{{ if ($DOCUMENTANDO) { $tmp2 = ltrim ($linea,'* /**'); //Elimino el * o /** del comienzo de la linea $accion = substr($tmp2, 0, strpos($tmp2,' ')); //Obtengo la accion $accion = ($accion === '') ? $tmp2 : $accion; $value = trim(strstr($tmp2, ' ')); //Solo me importa lo que esta detras del @ //SWITCH ACCIONES {{{ switch ($accion) { case '@access' : switch ($value) { case 'private' : $opciones['access'] = 201; break; case 'protected': $opciones['access'] = 202; break; default : $opciones['access'] = 200; } $doc_param = 0; break; case '@package' : $opciones['package'] = $value; $doc_param = 0; break; case '@abstract': $opciones['abstract'] = 1; $doc_param = 0; break; case '@static' : $opciones['static'] = 1; $doc_param = 0; break; case '@var' : $opciones['type'] = substr($value, 0, strpos($value,' ')); $doc_param = 0; break; case '@return' : $type = substr($value, 0, strpos($value,' ')); $resto = (strpos($value,' ')) ? substr($value, strpos($value,' ')) : ''; if ($type === '') { $type = $value; } if (strtolower($type) == 'object') { $resto = trim($resto); $type = substr($resto, 0, strpos($resto,' ')); $resto = (strpos($resto,' ')) ? substr($resto, strpos($resto,' ')) : ''; } $opciones['type'] = $type; if (trim($resto)) { $opciones['documentacion'].= "Returns: ".trim($resto); } $doc_param = 0; $resto = ''; break; case '@param' : $cont_param++; $type = substr($value, 0, strpos($value,' ')); $resto = substr($value, strpos($value,' ') + 1); if (strtolower($type) == 'object') { $resto = trim($resto); $type = substr($resto, 0, strpos($resto,' ')); $resto = substr($resto, strpos($resto,' ') + 1); } $opciones['param'][$cont_param]['type'] = $type; $opciones['param'][$cont_param]['documentacion'] = trim(substr(trim($resto), strpos(trim($resto), ' '))); $doc_param = 1; break; default: $tmp2 = str_replace('"', '"', $tmp2); $tmp2 = str_replace('<', '<' , $tmp2); $tmp2 = str_replace('>', '>' , $tmp2); $tmp2 = str_replace('&', '&' , $tmp2); if (@$doc_param) { $opciones['param'][$cont_param]['documentacion'].= "\n".$tmp2; } else { @$opciones['documentacion'].= $tmp2."\n"; } } //}}} } //}}} //CLASE {{{ if (!$DOCUMENTANDO && $tmp['0'] == 'class') { $ID++; $IDCLASE = $ID; $ARRAY[$ID]['id'] = $ID; $ARRAY[$ID]['name'] = $tmp['1']; $ARRAY[$ID]['stereotype'] = (@$opciones['stereotype']) ? $opciones['stereotype'] : ''; $ARRAY[$ID]['package'] = (@$opciones['package']) ? $opciones['package'] : ''; $ARRAY[$ID]['abstract'] = (@$opciones['abstract']) ? $opciones['abstract'] : 0; $ARRAY[$ID]['documentation'] = (@$opciones['documentacion']) ? $opciones['documentacion'] : ''; $ARRAY[$ID]['static'] = (@$opciones['static']) ? $opciones['static'] : 0; $ARRAY[$ID]['scope'] = (@$opciones['access']) ? $opciones['access'] : 200; $ARRAY[$ID]['operations'] = array(); $ARRAY[$ID]['attributes'] = array(); $opciones = array(); } //}}} //FUNCION {{{ if (!$DOCUMENTANDO && $tmp['0'] == 'function') { $ID++; if ($tmp['1']{0} == '&') { $tmp['1'] = substr($tmp['1'], 1); //SACO EL & $opciones['type'] = (@$opciones['type']) ? '&'.$opciones['type'] : ''; } if ($tmp['1']{0} == '_') { $tmp['1'] = substr($tmp['1'], 1); //SACO EL _ } $ARRAY[$IDCLASE]['operations'][$ID]['id'] = $ID; $ARRAY[$IDCLASE]['operations'][$ID]['name'] = $tmp['1']; $ARRAY[$IDCLASE]['operations'][$ID]['stereotype'] = (@$opciones['stereotype']) ? $opciones['stereotype'] : ''; $ARRAY[$IDCLASE]['operations'][$ID]['package'] = (@$opciones['package']) ? $opciones['package'] : ''; $ARRAY[$IDCLASE]['operations'][$ID]['abstract'] = (@$opciones['abstract']) ? $opciones['abstract'] : 0; $ARRAY[$IDCLASE]['operations'][$ID]['documentation'] = (@$opciones['documentacion']) ? $opciones['documentacion'] : ''; $ARRAY[$IDCLASE]['operations'][$ID]['static'] = (@$opciones['static']) ? $opciones['static'] : 0; $ARRAY[$IDCLASE]['operations'][$ID]['scope'] = (@$opciones['access']) ? $opciones['access'] : 200; $ARRAY[$IDCLASE]['operations'][$ID]['type'] = (@$opciones['type']) ? $opciones['type'] : ''; $ARRAY[$IDCLASE]['operations'][$ID]['param'] = array(); //PARAMETROS {{{ $param_line = trim(substr(strstr($linea,'('),0),'{ '); //Saco la ultima { $param = parseParentesis($param_line); $i = 0; foreach ($param as $par) { if ($par['name']{0} == '$'|| $par['name']{0} == '&') { //Veo si empiezo con $ o & switch ($par['name']{0}) { case '$': $par['name'] = substr($par['name'], 1); //SACO EL $ break; case '&': $par['name'] = substr($par['name'], 2); //SACO EL & Y EL $ $opciones['param'][$i]['type'] = (@$opciones['param'][$i]['type']) ? '&'.$opciones['param'][$i]['type'] : ''; break; } $ARRAY[$IDCLASE]['operations'][$ID]['param'][$i]['id'] = $i; $ARRAY[$IDCLASE]['operations'][$ID]['param'][$i]['name'] = $par['name']; $ARRAY[$IDCLASE]['operations'][$ID]['param'][$i]['stereotype'] = (@$opciones['param'][$i]['stereotype']) ? $opciones['param'][$i]['stereotype'] : ''; $ARRAY[$IDCLASE]['operations'][$ID]['param'][$i]['package'] = (@$opciones['param'][$i]['package']) ? $opciones['param'][$i]['package'] : ''; $ARRAY[$IDCLASE]['operations'][$ID]['param'][$i]['abstract'] = (@$opciones['param'][$i]['abstract']) ? $opciones['param'][$i]['abstract'] : 0; $ARRAY[$IDCLASE]['operations'][$ID]['param'][$i]['documentation'] = (@$opciones['param'][$i]['documentacion']) ? $opciones['param'][$i]['documentacion'] : ''; $ARRAY[$IDCLASE]['operations'][$ID]['param'][$i]['static'] = (@$opciones['param'][$i]['static']) ? $opciones['param'][$i]['static'] : 0; $ARRAY[$IDCLASE]['operations'][$ID]['param'][$i]['scope'] = (@$opciones['param'][$i]['access']) ? $opciones['param'][$i]['access'] : ''; $ARRAY[$IDCLASE]['operations'][$ID]['param'][$i]['type'] = (@$opciones['param'][$i]['type']) ? $opciones['param'][$i]['type'] : ''; $ARRAY[$IDCLASE]['operations'][$ID]['param'][$i]['value'] = (@$par['value']) ? $par['value'] : ''; } $i++; } //}}} $opciones = array(); $cont_param = -1; $i = 0; } //}}} //ATRIBUTOS {{{ if (!$DOCUMENTANDO && $tmp['0'] == 'var') { $ID++; $tmp['1'] = substr($tmp['1'], 1); //SACO EL $ if ($tmp['1']{0} == '_') { $tmp['1'] = substr($tmp['1'],1); //SACO EL _ if (!(@$opciones['access'])) { $opciones['access'] = 201; } } //Agrego si tiene valor inicial if (array_key_exists('2',$tmp)) { $opciones['value'] = $tmp['2']; } $ARRAY[$IDCLASE]['attributes'][$ID]['id'] = $ID; $ARRAY[$IDCLASE]['attributes'][$ID]['name'] = $tmp['1']; $ARRAY[$IDCLASE]['attributes'][$ID]['stereotype'] = (@$opciones['stereotype']) ? $opciones['stereotype'] : ''; $ARRAY[$IDCLASE]['attributes'][$ID]['package'] = (@$opciones['package']) ? $opciones['package'] : ''; $ARRAY[$IDCLASE]['attributes'][$ID]['abstract'] = (@$opciones['abstract']) ? $opciones['abstract'] : 0; $ARRAY[$IDCLASE]['attributes'][$ID]['documentation'] = (@$opciones['documentacion']) ? $opciones['documentacion'] : ''; $ARRAY[$IDCLASE]['attributes'][$ID]['static'] = (@$opciones['static']) ? $opciones['static'] : 0; $ARRAY[$IDCLASE]['attributes'][$ID]['scope'] = (@$opciones['access']) ? $opciones['access'] : 200; $ARRAY[$IDCLASE]['attributes'][$ID]['type'] = (@$opciones['type']) ? $opciones['type'] : ''; $ARRAY[$IDCLASE]['attributes'][$ID]['value'] = (@$opciones['value']) ? $opciones['value'] : ''; $opciones = array(); } //}}} } } //}}} } //}}} //GUARDO EN EL ARCHIVO {{{ $m =fopen ('./umlOut.xmi', 'w'); fwrite($m, $comienzo); $LISTITEM = ''; //CLASES foreach ($ARRAY as $ar) { //PREPARO LA CLASE $tmp2 = $umlclass; fwrite($m, preg_replace (array ('/##STEREOTYPE##/','/##PACKAGE##/','/##ID##/','/##ABSTRACT##/','/##DOCUMENTATION##/','/##NAME##/', '/##STATIC##/','/##SCOPE##/'), array ($ar['stereotype'],$ar['package'],$ar['id'],$ar['abstract'],trim($ar['documentation']),$ar['name'], $ar['static'],$ar['scope']), $tmp2)."\n"); //PREPARO LOS LISTITEM $tmp2 = $umllistitem; $LISTITEM.= preg_replace (array('/##TYPE##/','/##LABEL##/','/##ID##/'),array(813, $ar['name'], $ar['id']),$tmp2)."\n"; //OPERACIONES foreach ($ar['operations'] as $op) { $tmp2 = $umloperation; fwrite($m, preg_replace (array('/##STEREOTYPE##/','/##PACKAGE##/','/##ID##/','/##TYPE##/','/##ABSTRACT##/','/##DOCUMENTATION##/', '/##NAME##/','/##STATIC##/','/##SCOPE##/'), array($op['stereotype'],$op['package'],$op['id'],$op['type'],$op['abstract'],trim($op['documentation']), $op['name'],$op['static'],$op['scope']) , $tmp2)."\n"); //PARAMETROS NO TIENE LISTITEM foreach ($op['param'] as $pa) { $tmp2 = $umlparameter; fwrite ($m, preg_replace(array('/##STEREOTYPE##/','/##PACKAGE##/','/##ID##/','/##TYPE##/','/##ABSTRACT##/','/##DOCUMENTATION##/', '/##NAME##/','/##STATIC##/','/##SCOPE##/','/##VALUE##/'), array($pa['stereotype'],$pa['package'],$pa['id'],$pa['type'],$pa['abstract'],trim($pa['documentation']), $pa['name'],$pa['static'],$pa['scope'],$pa['value']), $tmp2)."\n"); } fwrite($m,$umloperation_c."\n"); //PREPARO LOS LISTITEM $tmp2 = $umllistitem; $LISTITEM.= preg_replace (array('/##TYPE##/','/##LABEL##/','/##ID##/'),array(815, $op['name'], $op['id']),$tmp2)."\n"; $LISTITEM.=$umllistitem_c."\n"; } //ATRIBUTOS foreach ($ar['attributes'] as $op) { $tmp2 = $umlattribute; fwrite($m, preg_replace(array('/##STEREOTYPE##/','/##PACKAGE##/','/##ID##/','/##TYPE##/','/##ABSTRACT##/','/##DOCUMENTATION##/', '/##NAME##/','/##STATIC##/','/##SCOPE##/','/##VALUE##/'), array($op['stereotype'],$op['package'],$op['id'],$op['type'],$op['abstract'],trim($op['documentation']),$op['name'], $op['static'],$op['scope'],$op['value']), $tmp2)."\n"); //PREPARO LOS LISTITEM $tmp2 = $umllistitem; $LISTITEM.= preg_replace (array('/##TYPE##/','/##LABEL##/','/##ID##/'),array(814, $op['name'], $op['id']),$tmp2)."\n"; $LISTITEM.=$umllistitem_c."\n"; } fwrite($m,$umlclass_c); $LISTITEM.=$umllistitem_c."\n"; } fwrite($m, $medio. $LISTITEM."\n".$fin); exit; //}}} //PARSER_PARENTESIS {{{ //Funcion que parsea por el contenido entre parentesis //Devuelve un array de arrays function parseParentesis($value) { $pos = 0; $content = true; $char = true; $value = substr(substr(trim($value), 1), 0, strrpos(substr(trim($value), 1),')')); while ($char) { //Busco la siguiente separacion ( , o = ) {{{ if (!strpos($value, ',') && !strpos($value, '=')) { $char = false; } elseif (!strpos($value, ',') && strpos($value, '=')) { if ($value{strpos($value, '=') + 1} == '>') { $char = '=>'; } else { $char = '='; } } elseif (strpos($value, ',') && !strpos($value, '=')) { $char = ','; } elseif (strpos($value, ',') && strpos($value, '=') && strpos($value, ',') > strpos($value, '=')) { if ($value{strpos($value, '=') + 1} == '>') { $char = '=>'; } else { $char = '='; } } elseif (strpos($value, ',') && strpos($value, '=') && strpos($value, ',') < strpos($value, '=')) { $char = ','; } //}}} //Obtengo el nombre a partir del caracter de separacion {{{ $result[$pos]['name'] = (strpos($value, $char)) ? substr($value, 0, strpos($value, $char)) : $value; $pos_del = strpos($value, $char); //}}} //Busco el valor asociado {{{ if ($char == '=') { $op_value = (strpos($value, $char)) ? trim(substr($value, strpos($value, $char) + 1)) : false; } elseif ($char == '=>') { $op_value = (strpos($value, $char)) ? trim(substr($value, strpos($value, $char) + 2)) : false; } //}}} //Parseo el resto de la linea {{{ if ($op_value) { if ($op_value{0} == "'" || $op_value{0} == '"') { $pos_del = parseComillas($op_value); if ($pos_del == 0) { $result[$pos]['value'] = "''"; } else { $op_value = substr($op_value, 1); $result[$pos]['value'] = substr($op_value, 0, $pos_del); } } elseif (trim(strtolower(substr($op_value, 0 ,5))) == 'array') { //RECURSIVIDAD {{{ $op_value = trim(substr($op_value, 5)); $op_value = trim(substr($op_value, 1)); //Saco el ( if ($op_value{0} == ')') { $result[$pos]['value'] = 'array()'; } else { //Busco a manopla el ) que cierra el array(##ALGO##) {{{ $subpos = 0; $seguir = true; $temp = $op_value; while ($seguir) { if (($temp{$subpos} == '"' || $temp{$subpos} == "'") && $temp{$subpos - 1} != '\\') { $pos_del = parseComillas(substr($temp,$subpos)) + $subpos; $subpos = $pos_del + 2; if (trim($temp{$subpos}) == ')') { $seguir = false; } } else { if ($subpos > strlen($temp)) { $seguir = false; } $subpos++; } } //}}} $par = parseParentesis('('.substr($op_value, 0 , $subpos).')'); $result[$pos]['value'] = 'array('; foreach ($par as $p) { $result[$pos]['value'] .= $p['name']; if (@$p['value']) { $result[$pos]['value'] .= '=>\''.$p['value'].'\','; } else { $result[$pos]['value'] .= ','; } } $result[$pos]['value'] = rtrim($result[$pos]['value'],','); $result[$pos]['value'] .= ')'; $pos_del = $subpos; } } //}}} else { //Busco la , de separacion con el proximo parametro //en caso de ser el utlimo lo asigno como viene if ($pos_del = strpos($op_value, ',')) { $result[$pos]['value'] = ($pos_del) ? trim(substr($op_value, 0, $pos_del)): $op_value; } } $value = $op_value; } //}}} //Borro de $value lo que ya parsee {{{ if ($pos_del) { $value = trim(substr(trim($value), $pos_del + 2)); } if (!$value) { $char = false; } //}}} $pos++; $op_value=''; } return $result; } //}}} //PARSER_COMILLAS {{{ //Funcion que parsea por el contenido entre comillas //Devuelve la pos de la ' que cierra el comentario function parseComillas($value) { $result = -1; $ii = 1; $cont = true; switch ($value{0}) { //{{{ case "'": $char = "'"; break; case '"': $char = '"'; break; }//}}} $value = substr($value, 1); //Saco la ' o " del comienzo del string if ($value{0} == $char) { $result = 0; } else { while ($cont) { //{{{ $ii++; if ($value{$ii} == $char) { if ($value{$ii - 1} != '\\') { $cont = false; $result = $ii; } } }//}}} } return $result; } //}}} ?>