1: <?php
2:
3: /*
4: * The MIT License (MIT)
5: *
6: * Copyright (c) 2013 Jonathan Vollebregt (jnvsor@gmail.com), Rokas Šleinius (raveren@gmail.com)
7: *
8: * Permission is hereby granted, free of charge, to any person obtaining a copy of
9: * this software and associated documentation files (the "Software"), to deal in
10: * the Software without restriction, including without limitation the rights to
11: * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12: * the Software, and to permit persons to whom the Software is furnished to do so,
13: * subject to the following conditions:
14: *
15: * The above copyright notice and this permission notice shall be included in all
16: * copies or substantial portions of the Software.
17: *
18: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20: * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21: * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22: * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23: * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24: */
25:
26: namespace Kint\Object;
27:
28: use Kint\Object\Representation\DocstringRepresentation;
29: use Kint\Utils;
30: use ReflectionFunctionAbstract;
31: use ReflectionMethod;
32:
33: class MethodObject extends BasicObject
34: {
35: public $type = 'method';
36: public $filename;
37: public $startline;
38: public $endline;
39: public $parameters = array();
40: public $abstract;
41: public $final;
42: public $internal;
43: public $docstring;
44: public $returntype;
45: public $return_reference = false;
46: public $hints = array('callable', 'method');
47: public $showparams = true;
48:
49: private $paramcache;
50:
51: public function __construct(ReflectionFunctionAbstract $method)
52: {
53: parent::__construct();
54:
55: $this->name = $method->getName();
56: $this->filename = $method->getFileName();
57: $this->startline = $method->getStartLine();
58: $this->endline = $method->getEndLine();
59: $this->internal = $method->isInternal();
60: $this->docstring = $method->getDocComment();
61: $this->return_reference = $method->returnsReference();
62:
63: foreach ($method->getParameters() as $param) {
64: $this->parameters[] = new ParameterObject($param);
65: }
66:
67: if (KINT_PHP70) {
68: $this->returntype = $method->getReturnType();
69: if ($this->returntype) {
70: $this->returntype = Utils::getTypeString($this->returntype);
71: }
72: }
73:
74: if ($method instanceof ReflectionMethod) {
75: $this->static = $method->isStatic();
76: $this->operator = $this->static ? BasicObject::OPERATOR_STATIC : BasicObject::OPERATOR_OBJECT;
77: $this->abstract = $method->isAbstract();
78: $this->final = $method->isFinal();
79: $this->owner_class = $method->getDeclaringClass()->name;
80: $this->access = BasicObject::ACCESS_PUBLIC;
81: if ($method->isProtected()) {
82: $this->access = BasicObject::ACCESS_PROTECTED;
83: } elseif ($method->isPrivate()) {
84: $this->access = BasicObject::ACCESS_PRIVATE;
85: }
86: }
87:
88: if ($this->internal) {
89: return;
90: }
91:
92: $docstring = new DocstringRepresentation(
93: $this->docstring,
94: $this->filename,
95: $this->startline
96: );
97:
98: $docstring->implicit_label = true;
99: $this->addRepresentation($docstring);
100: $this->value = $docstring;
101: }
102:
103: public function setAccessPathFrom(InstanceObject $parent)
104: {
105: static $magic = array(
106: '__call' => true,
107: '__callstatic' => true,
108: '__clone' => true,
109: '__construct' => true,
110: '__debuginfo' => true,
111: '__destruct' => true,
112: '__get' => true,
113: '__invoke' => true,
114: '__isset' => true,
115: '__set' => true,
116: '__set_state' => true,
117: '__sleep' => true,
118: '__tostring' => true,
119: '__unset' => true,
120: '__wakeup' => true,
121: );
122:
123: $name = \strtolower($this->name);
124:
125: if ('__construct' === $name) {
126: $this->access_path = 'new \\'.$parent->getType();
127: } elseif ('__invoke' === $name) {
128: $this->access_path = $parent->access_path;
129: } elseif ('__clone' === $name) {
130: $this->access_path = 'clone '.$parent->access_path;
131: $this->showparams = false;
132: } elseif ('__tostring' === $name) {
133: $this->access_path = '(string) '.$parent->access_path;
134: $this->showparams = false;
135: } elseif (isset($magic[$name])) {
136: $this->access_path = null;
137: } elseif ($this->static) {
138: $this->access_path = '\\'.$this->owner_class.'::'.$this->name;
139: } else {
140: $this->access_path = $parent->access_path.'->'.$this->name;
141: }
142: }
143:
144: public function getValueShort()
145: {
146: if (!$this->value || !($this->value instanceof DocstringRepresentation)) {
147: return parent::getValueShort();
148: }
149:
150: $ds = $this->value->getDocstringWithoutComments();
151:
152: if (!$ds) {
153: return null;
154: }
155:
156: $ds = \explode("\n", $ds);
157:
158: $out = '';
159:
160: foreach ($ds as $line) {
161: if (0 === \strlen(\trim($line)) || '@' === $line[0]) {
162: break;
163: }
164:
165: $out .= $line.' ';
166: }
167:
168: if (\strlen($out)) {
169: return \rtrim($out);
170: }
171: }
172:
173: public function getModifiers()
174: {
175: $mods = array(
176: $this->abstract ? 'abstract' : null,
177: $this->final ? 'final' : null,
178: $this->getAccess(),
179: $this->static ? 'static' : null,
180: );
181:
182: $out = '';
183:
184: foreach ($mods as $word) {
185: if (null !== $word) {
186: $out .= $word.' ';
187: }
188: }
189:
190: if (\strlen($out)) {
191: return \rtrim($out);
192: }
193: }
194:
195: public function getAccessPath()
196: {
197: if (null !== $this->access_path) {
198: if ($this->showparams) {
199: return parent::getAccessPath().'('.$this->getParams().')';
200: }
201:
202: return parent::getAccessPath();
203: }
204: }
205:
206: public function getParams()
207: {
208: if (null !== $this->paramcache) {
209: return $this->paramcache;
210: }
211:
212: $out = array();
213:
214: foreach ($this->parameters as $p) {
215: $type = $p->getType();
216: if ($type) {
217: $type .= ' ';
218: }
219:
220: $default = $p->getDefault();
221: if ($default) {
222: $default = ' = '.$default;
223: }
224:
225: $ref = $p->reference ? '&' : '';
226:
227: $out[] = $type.$ref.$p->getName().$default;
228: }
229:
230: return $this->paramcache = \implode(', ', $out);
231: }
232:
233: public function getPhpDocUrl()
234: {
235: if (!$this->internal) {
236: return null;
237: }
238:
239: if ($this->owner_class) {
240: $class = \strtolower($this->owner_class);
241: } else {
242: $class = 'function';
243: }
244:
245: $funcname = \str_replace('_', '-', \strtolower($this->name));
246:
247: if (0 === \strpos($funcname, '--') && 0 !== \strpos($funcname, '-', 2)) {
248: $funcname = \substr($funcname, 2);
249: }
250:
251: return 'https://secure.php.net/'.$class.'.'.$funcname;
252: }
253: }
254: