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