24
24
use phpDocumentor \Guides \Nodes \PrefixedLinkTargetNode ;
25
25
use phpDocumentor \Guides \Nodes \SectionNode ;
26
26
use phpDocumentor \Guides \ReferenceResolvers \AnchorNormalizer ;
27
+ use Psr \Log \LoggerInterface ;
27
28
use SplStack ;
28
29
use Webmozart \Assert \Assert ;
29
30
31
+ use function sprintf ;
32
+
30
33
/** @implements NodeTransformer<DocumentNode|AnchorNode|SectionNode> */
31
34
final class CollectLinkTargetsTransformer implements NodeTransformer
32
35
{
@@ -35,6 +38,7 @@ final class CollectLinkTargetsTransformer implements NodeTransformer
35
38
36
39
public function __construct (
37
40
private readonly AnchorNormalizer $ anchorReducer ,
41
+ private LoggerInterface |null $ logger = null ,
38
42
) {
39
43
/*
40
44
* TODO: remove stack here, as we should not have sub documents in this way, sub documents are
@@ -74,18 +78,45 @@ public function enterNode(Node $node, CompilerContext $compilerContext): Node
74
78
$ prefix = $ node ->getPrefix ();
75
79
}
76
80
77
- $ compilerContext ->getProjectNode ()->addLinkTarget (
78
- $ anchor ,
79
- new InternalTarget (
80
- $ currentDocument ->getFilePath (),
81
+ if ($ compilerContext ->getProjectNode ()->hasInternalTarget ($ anchor , $ node ->getLinkType ())) {
82
+ $ this ->logger ?->warning(
83
+ sprintf (
84
+ 'Duplicate anchor "%s" for link type "%s" in document "%s". The anchor is already used at "%s" ' ,
85
+ $ anchor ,
86
+ $ node ->getLinkType (),
87
+ $ compilerContext ->getDocumentNode ()->getFilePath (),
88
+ $ compilerContext ->getProjectNode ()->getInternalTarget ($ anchor , $ node ->getLinkType ())?->getDocumentPath(),
89
+ ),
90
+ $ compilerContext ->getLoggerInformation (),
91
+ );
92
+ } else {
93
+ $ compilerContext ->getProjectNode ()->addLinkTarget (
81
94
$ anchor ,
82
- $ node ->getLinkText (),
83
- $ node ->getLinkType (),
84
- $ prefix ,
85
- ),
86
- );
95
+ new InternalTarget (
96
+ $ currentDocument ->getFilePath (),
97
+ $ anchor ,
98
+ $ node ->getLinkText (),
99
+ $ node ->getLinkType (),
100
+ $ prefix ,
101
+ ),
102
+ );
103
+ }
104
+
87
105
if ($ node instanceof MultipleLinkTargetsNode) {
88
106
foreach ($ node ->getAdditionalIds () as $ id ) {
107
+ if ($ compilerContext ->getProjectNode ()->hasInternalTarget ($ id , $ node ->getLinkType ())) {
108
+ $ this ->logger ?->warning(
109
+ sprintf (
110
+ 'Duplicate anchor "%s" for link type "%s" in document "%s". The anchor is already used at "%s" ' ,
111
+ $ anchor ,
112
+ $ node ->getLinkType (),
113
+ $ compilerContext ->getDocumentNode ()->getFilePath (),
114
+ $ compilerContext ->getProjectNode ()->getInternalTarget ($ anchor , $ node ->getLinkType ())?->getDocumentPath(),
115
+ ),
116
+ $ compilerContext ->getLoggerInformation (),
117
+ );
118
+ }
119
+
89
120
$ compilerContext ->getProjectNode ()->addLinkTarget (
90
121
$ id ,
91
122
new InternalTarget (
0 commit comments