1<?php 2/** 3 * PHP_UML 4 * 5 * PHP version 5 6 * 7 * @category PHP 8 * @package PHP_UML 9 * @author Baptiste Autin <ohlesbeauxjours@yahoo.fr> 10 * @license http://www.gnu.org/licenses/lgpl.html LGPL License 3 11 * @version SVN: $Revision$ 12 * @link http://pear.php.net/package/PHP_UML 13 * @since $Date$ 14 */ 15 16/** 17 * General class for an renderer in the PHP implementation 18 * 19 * @category PHP 20 * @package PHP_UML 21 * @subpackage Output 22 * @subpackage Php 23 * @author Baptiste Autin <ohlesbeauxjours@yahoo.fr> 24 * @license http://www.gnu.org/licenses/lgpl.html LGPL License 3 25 */ 26abstract class PHP_UML_Output_Php_DocElement extends PHP_UML_Output_ApiRenderer 27{ 28 const FILE_EXT = 'php'; 29 const TEMPLATES_DIRNAME = 'templates'; 30 31 /** 32 * Constructor 33 * 34 * @param PHP_UML_Output_ExporterAPI $exporter Reference to an exporter 35 */ 36 public function __construct(PHP_UML_Output_ExporterAPI $exporter) 37 { 38 parent::__construct($exporter); 39 $this->mainTpl = $this->getTemplate('main.php'); 40 } 41 42 protected function getDescription(PHP_UML_Metamodel_Stereotype $s, $annotatedElement='') 43 { 44 $tag = PHP_UML_Metamodel_Helper::getStereotypeTag($s, 'description'); 45 if (!is_null($tag)) 46 return $tag->value; 47 else 48 return ''; 49 } 50 51 /** 52 * Renders the operation's parameters, as a comma-sep list, between brackets 53 * 54 * @param PHP_UML_Metamodel_Operation $operation The operation 55 * @param bool $withType If true, adds an hyperlink 56 * 57 * @return string 58 */ 59 protected function getParameterList(PHP_UML_Metamodel_Operation $operation, $withType = false) 60 { 61 $str = '('; 62 $n = count($operation->ownedParameter); 63 for ($i=0; $i<$n; $i++) { 64 $parameter = $operation->ownedParameter[$i]; 65 if (substr($parameter->direction, 0, 2)=='in') { 66 if ($withType && isset($parameter->type) && !($parameter->type instanceof PHP_UML_Metamodel_Datatype)) { 67 if (is_object($parameter->type)) 68 $str .= $this->getLinkTo($parameter->type).' '; 69 else if (strcasecmp($parameter->type, 'array')==0) 70 $str .= $this->displayUnresolved($parameter->type).' '; 71 } 72 if ($parameter->direction=='inout') { 73 $str .= '&'; 74 } 75 if ($parameter->name[0] != '$') 76 $str .= '$'; 77 $str .= $parameter->name; 78 $str .= $this->getDefaultValue($parameter); 79 if ($i<($n-1)) 80 $str .= ', '; 81 } 82 } 83 $str .= ')'; 84 return $str; 85 } 86 87 protected function getDefaultValue(PHP_UML_Metamodel_TypedElement $obj) 88 { 89 if ($obj->default!='') 90 return '='.$obj->default; 91 else 92 return ''; 93 } 94 95 /** 96 * Renders a link towards a given element 97 * (since datatypes don't own to a "package", we suppose they are located in 98 * the top package) 99 * 100 * @param PHP_UML_Metamodel_Classifier $t The element 101 * @param string $cssStyle CSS style to use 102 * 103 * @return string 104 */ 105 protected function getLinkTo(PHP_UML_Metamodel_Classifier $t, $hideDatatype=true) 106 { 107 if ($hideDatatype && ($t instanceof PHP_UML_Metamodel_Datatype)) 108 return ''; 109 110 $ns = $t instanceof PHP_UML_Metamodel_Datatype ? '' : self::T_NAMESPACE; 111 if (isset($t->package)) { 112 $ns .= $this->getAbsPath($t->package, self::T_NAMESPACE); 113 } 114 return $ns.$t->name; 115 } 116 117 /** 118 * Renders an unresolved type as an HTML span 119 * 120 * @param string $type Type, provided as a string 121 * 122 * @return string 123 */ 124 protected function displayUnresolved($type) 125 { 126 return $type; 127 } 128 129 130 protected function getTagsAsList(PHP_UML_Metamodel_Stereotype $s) 131 { 132 return $this->getDocblocks($s, 0); 133 } 134 135 /** 136 * Renders the properties of a given stereotype. 137 * Docblocks in $ignoredTag are not shown. 138 * 139 * @param PHP_UML_Metamodel_Stereotype $s A stereotype 140 * @param int $nbSpacer Number of spacers to add 141 * 142 * @return string 143 */ 144 protected function getDocblocks(PHP_UML_Metamodel_Stereotype $s, $nbSpacer = 0) 145 { 146 $str = ''; 147 $spacer = str_repeat(chr(9), $nbSpacer); 148 foreach ($s->ownedAttribute as $tag) { 149 if (!(in_array($tag->name, $this->ignoredTag))) { 150 $str .= $spacer; 151 if ($tag->name!='description') { 152 $str .= ' * @'.$tag->name.' '; 153 } else { 154 $str .= ' * '; 155 } 156 if (strlen($tag->value)>0) 157 $str .= str_replace($this->getNl(), $this->getNl().$spacer.' * ', $tag->value); 158 if ($tag->name=='description') { 159 $str .= $this->getNl().$spacer.' *'; 160 } 161 $str .= $this->getNl(); 162 } 163 } 164 if ($str != '') { 165 $str = $spacer.'/**'.$this->getNl().$str.$spacer.' */'.$this->getNl(); 166 } 167 return $str; 168 } 169 170 171 /** 172 * Renders the block "Properties" of a package or a class as HTML 173 * 174 * @param PHP_UML_Metamodel_NamedElement $p A classifier/a package 175 * 176 * @return string 177 */ 178 protected function getPropertyBlock(PHP_UML_Metamodel_NamedElement $p) 179 { 180 if (empty($p->ownedAttribute)) 181 return ''; 182 183 $str = ''; 184 $spacer = chr(9); 185 foreach ($p->ownedAttribute as $o) { 186 187 if (!is_null($o->description) && $this->exporter->getDocblocks()) { 188 // we add var/return docblocks if they are missing 189 $this->addVarDocblock($o); 190 $str .= $this->getDocblocks($o->description, 1); 191 } 192 193 $str .= $spacer; 194 if ($o->isReadOnly) 195 $str .= 'const '; 196 else { 197 $str .= $o->visibility.' '; 198 if (!$o->isInstantiable) 199 $str .= 'static '; 200 } 201 202 // type display; 203 /*if (is_object($o->type)) 204 $str .= $this->getLinkTo($o->type).' '; 205 else 206 $str .= $this->displayUnresolved($o->type);*/ 207 if ((!empty($o->name)) && ($o->name[0]!='$' && !$o->isReadOnly)) 208 $str .= '$'; 209 210 $str .= $o->name.''.$this->getDefaultValue($o).';'; 211 212 $str .= $this->getNl().$this->getNl(); 213 } 214 $str .= ''; 215 return $str; 216 } 217 218 private function addVarDocblock(PHP_UML_Metamodel_Property $o) 219 { 220 $found = false; 221 foreach ($o->description->ownedAttribute as $tag) { 222 if ($tag->name=='var') { 223 $found = true; 224 break; 225 } 226 } 227 if (!$found) { 228 $st = new PHP_UML_Metamodel_Stereotype(); 229 $st->name = 'var'; 230 if (is_object($o->type)) 231 $st->value = $this->getLinkTo($o->type, false); 232 else 233 $st->value = $this->displayUnresolved($o->type); 234 $o->description->ownedAttribute[] = $st; 235 } 236 } 237 238 private function addReturnDocblock(PHP_UML_Metamodel_Operation $o) 239 { 240 $found = false; 241 foreach ($o->description->ownedAttribute as $tag) { 242 if ($tag->name=='return') { 243 $found = true; 244 break; 245 } 246 } 247 if (!$found) { 248 $st = new PHP_UML_Metamodel_Stereotype(); 249 $st->name = 'return'; 250 foreach ($o->ownedParameter as $parameter) { 251 if ($parameter->direction != 'in') { 252 if (is_object($parameter->type)) 253 $st->value .= $this->getLinkTo($parameter->type, false).' '; 254 else 255 $st->value .= $this->displayUnresolved($parameter->type); 256 } 257 } 258 $o->description->ownedAttribute[] = $st; 259 } 260 } 261 262 263 /** 264 * Renders the block "Function" of a package or a classifier as HTML 265 * 266 * @param PHP_UML_Metamodel_NamedElement $p A classifier or a package 267 * 268 * @return string 269 */ 270 protected function getFunctionBlock(PHP_UML_Metamodel_NamedElement $p) 271 { 272 if (empty($p->ownedOperation)) 273 return''; 274 275 $str = ''; 276 $spacer = chr(9); 277 278 foreach ($p->ownedOperation as $o) { 279 280 if (!is_null($o->description) && $this->exporter->getDocblocks()) { 281 $this->addReturnDocblock($o); 282 $str .= $this->getDocblocks($o->description, 1); 283 } 284 285 $str .= $spacer.($o->visibility).' '; 286 if (!$o->isInstantiable) 287 $str .= 'static '; 288 if ($o->isAbstract) 289 $str .= 'abstract '; 290 291 $str .= 'function '.$o->name; 292 293 /*type hint 294 $return = $this->getReturnParam($o); 295 if (is_object($return->type)) 296 $str .= $this->getLinkTo($return->type).' '; 297 else 298 $str .= $this->displayUnresolved($return->type);*/ 299 $str .= $this->getParameterList($o, true); 300 301 if ($o->isAbstract || $p instanceof PHP_UML_Metamodel_Interface) 302 $str .= ';'.$this->getNl().$this->getNl(); 303 else 304 $str .= $this->getNl().$spacer.'{'.$this->getNl(). 305 $spacer.'}'.$this->getNl().$this->getNl(); 306 } 307 $str .= ''; 308 return $str; 309 } 310 311 /** 312 * Returns the HTML code for the "File" information tag 313 * 314 * @param PHP_UML_Metamodel_NamedElement $p An element 315 * 316 * @return string 317 */ 318 protected function getFileInfo(PHP_UML_Metamodel_NamedElement $p) 319 { 320 if (!empty($p->file->package)) 321 return ''.$this->getAbsPath($p->file->package).$p->file->name.''; 322 else 323 return ''; 324 } 325 326 protected function getNl() 327 { 328 return PHP_EOL; 329 } 330 331 /** 332 * Replace the template's placeholders with their value 333 * 334 * @param string $main Main HTML content (generated by PHP_UML) 335 * @param string $header Navigation HTML content (navig bar) 336 * @param string $ns Title content 337 * @param string $name Element name 338 * 339 * @return string 340 */ 341 protected function replaceInTpl($main, $header, $ns, $name) 342 { 343 $str = str_replace('#HEADER', $header, $this->mainTpl); 344 $str = str_replace('#NAMESPACE', $ns, $str); 345 $str = str_replace('#DETAIL', $main, $str); 346 $str = str_replace('#NAME', $this->getTypeName().' '.$name, $str); 347 return $str; 348 } 349 350 protected function getTemplateDirectory() 351 { 352 return dirname(__FILE__).DIRECTORY_SEPARATOR.self::TEMPLATES_DIRNAME; 353 } 354 355 protected function save($elementName, $str) 356 { 357 $fic = $this->getContextPackage()->dir.$elementName.'.'.self::FILE_EXT; 358 file_put_contents($fic, $str); 359 } 360} 361?> 362