Passed
Push — master ( e7bef7...3228c5 )
by Vladimir
03:06
created

renderClassMethod()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 26
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 20
dl 0
loc 26
rs 9.2888
c 0
b 0
f 0
cc 5
nc 4
nop 1
1
<?php
2
require __DIR__ . '/../vendor/autoload.php';
3
4
use GraphQL\Utils\Utils;
5
6
$outputFile = __DIR__  . '/../docs/reference.md';
7
8
$entries = [
9
    \GraphQL\GraphQL::class,
10
    \GraphQL\Type\Definition\Type::class,
11
    \GraphQL\Type\Definition\ResolveInfo::class,
12
    \GraphQL\Language\DirectiveLocation::class => ['constants' => true],
13
    \GraphQL\Type\SchemaConfig::class,
14
    \GraphQL\Type\Schema::class,
15
    \GraphQL\Language\Parser::class,
16
    \GraphQL\Language\Printer::class,
17
    \GraphQL\Language\Visitor::class,
18
    \GraphQL\Language\AST\NodeKind::class => ['constants' => true],
19
    \GraphQL\Executor\Executor::class,
20
    \GraphQL\Executor\ExecutionResult::class,
21
    \GraphQL\Executor\Promise\PromiseAdapter::class,
22
    \GraphQL\Validator\DocumentValidator::class,
23
    \GraphQL\Error\Error::class => ['constants' => true, 'methods' => true, 'props' => true],
24
    \GraphQL\Error\Warning::class => ['constants' => true, 'methods' => true],
25
    \GraphQL\Error\ClientAware::class,
26
    \GraphQL\Error\Debug::class => ['constants' => true],
27
    \GraphQL\Error\FormattedError::class,
28
    \GraphQL\Server\StandardServer::class,
29
    \GraphQL\Server\ServerConfig::class,
30
    \GraphQL\Server\Helper::class,
31
    \GraphQL\Server\OperationParams::class,
32
    \GraphQL\Utils\BuildSchema::class,
33
    \GraphQL\Utils\AST::class,
34
    \GraphQL\Utils\SchemaPrinter::class
35
];
36
37
function renderClassMethod(ReflectionMethod $method) {
38
    $args = Utils::map($method->getParameters(), function(ReflectionParameter $p) {
39
        $type = ltrim($p->getType() . " ");
40
        $def = $type . '$' . $p->getName();
41
42
        if ($p->isDefaultValueAvailable()) {
43
            $val = $p->isDefaultValueConstant()
44
                ? $p->getDefaultValueConstantName()
45
                : $p->getDefaultValue();
46
            $def .= " = " . Utils::printSafeJson($val);
47
        }
48
49
        return $def;
50
    });
51
    $argsStr = implode(", ", $args);
52
    if (strlen($argsStr) >= 80) {
53
        $argsStr = "\n    " . implode(",\n    ", $args) . "\n";
54
    }
55
    $def = "function {$method->getName()}($argsStr)";
56
    $def = $method->isStatic() ? "static $def" : $def;
57
    $docBlock = unpadDocblock($method->getDocComment());
58
59
    return <<<TEMPLATE
60
```php
61
{$docBlock}
62
{$def}
63
```
64
TEMPLATE;
65
}
66
67
function renderConstant($value, $name) {
68
    return "const $name = " . Utils::printSafeJson($value) . ";";
69
}
70
71
function renderProp(ReflectionProperty $prop) {
72
    $signature = implode(" ", Reflection::getModifierNames($prop->getModifiers())) . ' $' . $prop->getName() . ';';
73
    return unpadDocblock($prop->getDocComment()) . "\n" . $signature;
74
}
75
76
function renderClass(ReflectionClass $class, $options) {
77
    $classDocs = unwrapDocblock(unpadDocblock($class->getDocComment()));
78
    $content = '';
79
    $label = $class->isInterface() ? 'Interface' : 'Class';
80
81
    if (!empty($options['constants'])) {
82
        $constants = $class->getConstants();
83
        $constants = Utils::map($constants, 'renderConstant');
84
        if (!empty($constants)) {
85
            $constants = "```php\n" . implode("\n", $constants) . "\n```";
86
            $content .= "**$label Constants:** \n$constants\n\n";
87
        }
88
    }
89
90
    if (!empty($options['props'])) {
91
        $props = $class->getProperties(ReflectionProperty::IS_PUBLIC);
92
        $props = Utils::filter($props, 'isApi');
93
        if (!empty($props)) {
94
            $props = Utils::map($props, 'renderProp');
95
            $props = "```php\n" . implode("\n\n", $props) . "\n```";
96
            $content .= "**$label Props:** \n$props\n\n";
97
        }
98
    }
99
100
    if (!empty($options['methods'])) {
101
        $methods = $class->getMethods(ReflectionMethod::IS_PUBLIC);
102
        $methods = Utils::filter($methods, 'isApi');
103
        if (!empty($methods)) {
104
            $renderedMethods = Utils::map($methods, 'renderClassMethod');
105
            $renderedMethods = implode("\n\n", $renderedMethods);
106
            $content .= "**$label Methods:** \n{$renderedMethods}\n";
107
        }
108
    }
109
110
    return <<<TEMPLATE
111
# {$class->getName()}
112
{$classDocs}
113
114
$content
115
TEMPLATE;
116
}
117
118
function unwrapDocblock($docBlock, $stripAnnotations = true) {
119
    $content = preg_replace('~([\r\n]) \* (.*)~i', '$1$2', $docBlock); // strip *
120
    $content = preg_replace('~([\r\n])[\* ]+([\r\n])~i', '$1$2', $content); // strip single-liner *
121
    $content = substr($content, 3); // strip leading /**
122
    $content = substr($content, 0, -2); // strip trailing */
123
    if ($stripAnnotations) {
124
        $content = preg_replace('~([\r\n])@.*([\r\n])~i', '$1', $content); // strip annotations
125
    }
126
    return trim($content);
127
}
128
129
function unpadDocblock($docBlock) {
130
    $lines = explode("\n", $docBlock);
131
    $lines = \GraphQL\Utils\Utils::map($lines, function($line) {
132
        return ' ' . trim($line);
133
    });
134
    return trim(implode("\n", $lines));
135
}
136
137
function isApi($entry) {
138
    /** @var ReflectionProperty|ReflectionMethod $entry */
139
    $isApi = preg_match('~[\r\n ]+\* @api~', $entry->getDocComment());
140
    return $isApi;
141
}
142
143
file_put_contents($outputFile, '');
144
145
foreach ($entries as $className => $options) {
146
    $className = is_int($className) ? $options : $className;
147
    $options = is_array($options) ? $options : ['methods' => true, 'props' => true];
148
149
    $rendered = renderClass(new ReflectionClass($className), $options);
150
    file_put_contents($outputFile, $rendered, FILE_APPEND);
151
}
152