1<?php 2 3namespace dokuwiki\Remote\OpenApiDoc; 4 5use ReflectionFunction; 6use ReflectionMethod; 7 8class DocBlockMethod extends DocBlock 9{ 10 /** 11 * Parse the given docblock 12 * 13 * The docblock can be of a method, class or property. 14 * 15 * @param ReflectionMethod|ReflectionFunction $reflector 16 */ 17 public function __construct($reflector) 18 { 19 parent::__construct($reflector); 20 $this->refineParam(); 21 $this->refineReturn(); 22 } 23 24 /** @inheritdoc */ 25 protected function getContext() 26 { 27 if ($this->reflector instanceof ReflectionFunction) { 28 return null; 29 } 30 return parent::getContext(); 31 } 32 33 /** 34 * Convenience method to access the method parameters 35 * 36 * @return array 37 */ 38 public function getParameters() 39 { 40 return $this->getTag('param'); 41 } 42 43 /** 44 * Convenience method to access the method return 45 * 46 * @return array 47 */ 48 public function getReturn() 49 { 50 return $this->getTag('return'); 51 } 52 53 /** 54 * Parse the param tag into its components 55 * 56 * @return void 57 */ 58 protected function refineParam() 59 { 60 $result = []; 61 62 // prefill from reflection 63 foreach ($this->reflector->getParameters() as $parameter) { 64 $refType = $parameter->getType(); 65 $result[$parameter->getName()] = [ 66 'type' => new Type($refType ? $refType->getName() : 'string', $this->getContext()), 67 'optional' => $parameter->isOptional(), 68 'description' => '', 69 ]; 70 if ($parameter->isDefaultValueAvailable()) { 71 $result[$parameter->getName()]['default'] = $parameter->getDefaultValue(); 72 } 73 } 74 75 // refine from doc tags 76 foreach ($this->tags['param'] ?? [] as $param) { 77 [$type, $name, $description] = array_map('trim', sexplode(' ', $param, 3, '')); 78 if ($name === '' || $name[0] !== '$') continue; 79 $name = substr($name, 1); 80 if (!isset($result[$name])) continue; // reflection says this param does not exist 81 82 $result[$name]['type'] = new Type($type, $this->getContext()); 83 $result[$name]['description'] = $description; 84 } 85 $this->tags['param'] = $result; 86 } 87 88 /** 89 * Parse the return tag into its components 90 * 91 * @return void 92 */ 93 protected function refineReturn() 94 { 95 96 97 // prefill from reflection 98 $refType = $this->reflector->getReturnType(); 99 $result = [ 100 'type' => new Type($refType ? $refType->getName() : 'void', $this->getContext()), 101 'description' => '', 102 ]; 103 104 // refine from doc tag 105 foreach ($this->tags['return'] ?? [] as $return) { 106 [$type, $description] = array_map('trim', sexplode(' ', $return, 2, '')); 107 $result['type'] = new Type($type, $this->getContext()); 108 $result['description'] = $description; 109 } 110 $this->tags['return'] = $result; 111 } 112} 113