1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\apidoc\helpers;
use phpDocumentor\Reflection\DocBlock\Type\Collection;
use yii\apidoc\models\MethodDoc;
use yii\apidoc\models\TypeDoc;
/**
* Class ApiMarkdownTrait
*
* @property TypeDoc $renderingContext
*/
trait ApiMarkdownTrait
{
/**
* @marker [[
*/
protected function parseApiLinks($text)
{
$context = $this->renderingContext;
if (preg_match('/^\[\[([\w\d\\\\\(\):$]+)(\|[^\]]*)?\]\]/', $text, $matches)) {
$offset = strlen($matches[0]);
$object = $matches[1];
$title = (empty($matches[2]) || $matches[2] == '|') ? null : substr($matches[2], 1);
if (($pos = strpos($object, '::')) !== false) {
$typeName = substr($object, 0, $pos);
$subjectName = substr($object, $pos + 2);
if ($context !== null) {
// Collection resolves relative types
$typeName = (new Collection([$typeName], $context->phpDocContext))->__toString();
}
/** @var $type TypeDoc */
$type = static::$renderer->apiContext->getType($typeName);
if ($type === null) {
static::$renderer->apiContext->errors[] = [
'file' => ($context !== null) ? $context->sourceFile : null,
'message' => 'broken link to ' . $typeName . '::' . $subjectName . (($context !== null) ? ' in ' . $context->name : ''),
];
return [
['brokenApiLink', '<span class="broken-link">' . $typeName . '::' . $subjectName . '</span>'],
$offset
];
} else {
if (($subject = $type->findSubject($subjectName)) !== null) {
if ($title === null) {
$title = $type->name . '::' . $subject->name;
if ($subject instanceof MethodDoc) {
$title .= '()';
}
}
return [
['apiLink', static::$renderer->createSubjectLink($subject, $title)],
$offset
];
} else {
static::$renderer->apiContext->errors[] = [
'file' => ($context !== null) ? $context->sourceFile : null,
'message' => 'broken link to ' . $type->name . '::' . $subjectName . (($context !== null) ? ' in ' . $context->name : ''),
];
return [
['brokenApiLink', '<span class="broken-link">' . $type->name . '::' . $subjectName . '</span>'],
$offset
];
}
}
} elseif ($context !== null && ($subject = $context->findSubject($object)) !== null) {
return [
['apiLink', static::$renderer->createSubjectLink($subject, $title)],
$offset
];
}
if ($context !== null) {
// Collection resolves relative types
$object = (new Collection([$object], $context->phpDocContext))->__toString();
}
if (($type = static::$renderer->apiContext->getType($object)) !== null) {
return [
['apiLink', static::$renderer->createTypeLink($type, null, $title)],
$offset
];
} elseif (strpos($typeLink = static::$renderer->createTypeLink($object, null, $title), '<a href') !== false) {
return [
['apiLink', $typeLink],
$offset
];
}
static::$renderer->apiContext->errors[] = [
'file' => ($context !== null) ? $context->sourceFile : null,
'message' => 'broken link to ' . $object . (($context !== null) ? ' in ' . $context->name : ''),
];
return [
['brokenApiLink', '<span class="broken-link">' . $object . '</span>'],
$offset
];
}
return [['text', '[['], 2];
}
/**
* Renders API link
* @param array $block
* @return string
*/
protected function renderApiLink($block)
{
return $block[1];
}
/**
* Renders API link that is broken i.e. points nowhere
* @param array $block
* @return string
*/
protected function renderBrokenApiLink($block)
{
return $block[1];
}
}