getMethods() as $method) { if (array_search($method->class, $ignoredClasses) !== false || !$method->isPublic() || $method->isConstructor()) { continue; } $description = ''; $help = ''; if ($method->getDocComment()) { $docBlock = $docBlockFactory->create($method); if ($docBlock->getTagsByName('private') || $docBlock->getTagsByName('deprecated') || $this->requiredModuleIsDisabled($docBlock)) { continue; } $description = $docBlock->getSummary(); $help = $docBlock->getDescription()->render(); } if (substr($method->name, 0, 6) == 'field_') { $name = substr($method->name, 6); $rawName = $name; $isMethod = false; } else { $name = $this->printMethodPrototype($method); $rawName = $method->name.'()'; $isMethod = true; } $return = $method->getReturnType(); if ($return) { $return = strval($return->getName()); } $tmpArr = [ 'name' => $name, 'rawName' => $rawName, 'description' => $description, 'help' => $help, 'method' => $isMethod, 'return' => $return, 'value' => !$isMethod && (!isset($docBlock) || !$docBlock->getTagsByName('implementedInJS')) ? call_user_func([$this, $method->name]) : '', ]; // TODO: remove clone once non shared wrappers are used if ($tmpArr['value'] instanceof IObjectInfo) { $tmpArr['value'] = clone $tmpArr['value']; } $introspection[] = $tmpArr; } usort($introspection, function ($a, $b) { return strcmp($a['name'], $b['name']); }); return $introspection; } protected function printMethodPrototype(\ReflectionMethod $method) { $args = []; foreach ($method->getParameters() as $p) { $args[] = ($this->declaresArray($p) ? 'array ' : ($p->getType() !== null && $p->getType()->__toString() ? $p->getType()->__toString().' ' : '')) .($p->isPassedByReference() ? '&' : '').'$'.$p->name .($p->isOptional() ? ' = '.var_export($p->getDefaultValue(), true) : ''); } return "{$method->name} (".implode(', ', $args).')'; } protected function declaresArray(\ReflectionParameter $reflectionParameter): bool { $reflectionType = $reflectionParameter->getType(); if (!$reflectionType) { return false; } $types = $reflectionType instanceof \ReflectionUnionType ? $reflectionType->getTypes() : [$reflectionType]; return in_array('array', array_map(fn (\ReflectionNamedType $t) => $t->getName(), $types)); } protected function requiredModuleIsDisabled(DocBlock $docBlock): bool { $moduleRaw = $docBlock->getTagsByName('module'); if (!empty($moduleRaw)) { $key = trim((string) ($moduleRaw[0] ?? ''), "\"'"); $parts = explode('__', $key); $module = $parts[0]; $submodule = getVal(1, $parts); if (!\Modules::check($module, $submodule)) { return true; // disabled module } } return false; } }