All Broken Links
Last modified by Antoine Tran on 2025/02/12 12:24
![]() | Provides a UI to find all broken links in the wiki |
Type | Snippet |
Category | |
Developed by | xwiki:XWiki.cjdelisle |
Rating | |
License | GNU Lesser General Public License 2.1 |
Table of contents
Description
This code displays a list of checkboxes with the name of each space in your wiki. They are all checked by default, except for Panels, XWiki and Stats. You can uncheck other spaces which you don't want to search. When you press go, it finds all broken links residing in any page in the spaces checked.
These are the stats on my db running on Postgres on an Intel 2.66Ghz dual core. Links Examined: 592119 Total Pages in wiki: 401400 Time taken: 28.6 seconds
{{groovy}}
//allBrokenLinks 0.01
//By Caleb James DeLisle calebdelisle{{at}}lavabit_com
//queries database for all links which don't contain dollar signs or spaces (" ").
//removes links containing ' or multiple dots
//queries database for all document fullNames (even in non checked spaces), creates HashSet
//compares each link to HashSet, if no document found, link is reported.
int counter = 0;
ArrayList<String> spaces = xwiki.getSpaces();
String space;
if(request.get("s")!=null){
long startTime = new Date().getTime();
ArrayList<String> lookInSpaces = request.getParameterMap().get("s");
ArrayList<String> links = new ArrayList<String>();
ArrayList<String> fullNames = new ArrayList<String>();
String sql = "select lnk.fullName, lnk.link from XWikiLink as lnk where lnk.link not like '%\$%' and lnk.link not like '% %' and "
String out = "", fullName, link;
if(lookInSpaces.size() > (spaces.size()/2)){
while(counter < spaces.size()){
space = spaces.get(counter);
if(!lookInSpaces.contains(space)){
sql += "lnk.fullName not like '"+space+".%' and ";
}
counter++;
}
sql = sql.substring(0,sql.length()-5);
}else{
sql += "(";
while(counter < lookInSpaces.size()){
sql += "lnk.fullName like '"+lookInSpaces.get(counter)+".%' or ";
counter++;
}
sql = sql.substring(0,sql.length()-4)+")";
}
pairs = xwiki.search(sql,0,0);
ArrayList<String> pair;
counter = pairs.size();
while(counter > 0){
counter--;
pair = pairs.get(counter);
link = pair.get(1);
if(link.indexOf("'")==-1 && link.indexOf(".")==link.lastIndexOf(".")){
//out += pairs.get(0)+" "+fullName+"\n";
links.add(link);
fullNames.add(pair.get(0));
}
}
HashSet<String> docNames = xwiki.search("select doc.fullName from XWikiDocument as doc",0,0);
counter = links.size();
while(counter > 0){
counter--;
if(!docNames.contains(links.get(counter))){
out += "; **"+links.get(counter)+"**\n: [["+fullNames.get(counter)+"]]\n\n";
}
}
println("allBrokenLinks 0.01\nLinks Examined: "+links.size()+"\nTotal Pages in wiki: "+docNames.size()+"\nTime taken: "+(Math.round((new Date().getTime()-startTime)/100)/10)+" seconds\nThe following broken links were found:\n\n\n; **Broken Link**\n: Page Linked From\n\n"+out);
}else{
println("{{html}}allBrokenLinks 0.01<br/>By Caleb James DeLisle<br/>Look for broken links on all pages in spaces:<form action=\""+this.doc.name+"\"><br/>");
while(counter < spaces.size()){
space = spaces.get(counter);
if(space.equals("XWiki") || space.equals("Stats") || space.equals("Panels")){
println("<input type=\"checkbox\" name=\"s\" value=\""+space+"\" />"+space+"<br/>");
}else{
println("<input type=\"checkbox\" name=\"s\" value=\""+space+"\" checked=checked />"+space+"<br/>");
}
counter++;
}
println("<input type=submit value=\"Go!\"/></form>{{/html}}");
}
{{/groovy}}
//allBrokenLinks 0.01
//By Caleb James DeLisle calebdelisle{{at}}lavabit_com
//queries database for all links which don't contain dollar signs or spaces (" ").
//removes links containing ' or multiple dots
//queries database for all document fullNames (even in non checked spaces), creates HashSet
//compares each link to HashSet, if no document found, link is reported.
int counter = 0;
ArrayList<String> spaces = xwiki.getSpaces();
String space;
if(request.get("s")!=null){
long startTime = new Date().getTime();
ArrayList<String> lookInSpaces = request.getParameterMap().get("s");
ArrayList<String> links = new ArrayList<String>();
ArrayList<String> fullNames = new ArrayList<String>();
String sql = "select lnk.fullName, lnk.link from XWikiLink as lnk where lnk.link not like '%\$%' and lnk.link not like '% %' and "
String out = "", fullName, link;
if(lookInSpaces.size() > (spaces.size()/2)){
while(counter < spaces.size()){
space = spaces.get(counter);
if(!lookInSpaces.contains(space)){
sql += "lnk.fullName not like '"+space+".%' and ";
}
counter++;
}
sql = sql.substring(0,sql.length()-5);
}else{
sql += "(";
while(counter < lookInSpaces.size()){
sql += "lnk.fullName like '"+lookInSpaces.get(counter)+".%' or ";
counter++;
}
sql = sql.substring(0,sql.length()-4)+")";
}
pairs = xwiki.search(sql,0,0);
ArrayList<String> pair;
counter = pairs.size();
while(counter > 0){
counter--;
pair = pairs.get(counter);
link = pair.get(1);
if(link.indexOf("'")==-1 && link.indexOf(".")==link.lastIndexOf(".")){
//out += pairs.get(0)+" "+fullName+"\n";
links.add(link);
fullNames.add(pair.get(0));
}
}
HashSet<String> docNames = xwiki.search("select doc.fullName from XWikiDocument as doc",0,0);
counter = links.size();
while(counter > 0){
counter--;
if(!docNames.contains(links.get(counter))){
out += "; **"+links.get(counter)+"**\n: [["+fullNames.get(counter)+"]]\n\n";
}
}
println("allBrokenLinks 0.01\nLinks Examined: "+links.size()+"\nTotal Pages in wiki: "+docNames.size()+"\nTime taken: "+(Math.round((new Date().getTime()-startTime)/100)/10)+" seconds\nThe following broken links were found:\n\n\n; **Broken Link**\n: Page Linked From\n\n"+out);
}else{
println("{{html}}allBrokenLinks 0.01<br/>By Caleb James DeLisle<br/>Look for broken links on all pages in spaces:<form action=\""+this.doc.name+"\"><br/>");
while(counter < spaces.size()){
space = spaces.get(counter);
if(space.equals("XWiki") || space.equals("Stats") || space.equals("Panels")){
println("<input type=\"checkbox\" name=\"s\" value=\""+space+"\" />"+space+"<br/>");
}else{
println("<input type=\"checkbox\" name=\"s\" value=\""+space+"\" checked=checked />"+space+"<br/>");
}
counter++;
}
println("<input type=submit value=\"Go!\"/></form>{{/html}}");
}
{{/groovy}}
A much simpler and faster snippet, but which doesn't filter out false hits:
= Broken links =
{{velocity}}
#foreach ($l in $xwiki.search("select link.id.link, link.fullName from XWikiLink link where link.id.link not in (select distinct doc.fullName from XWikiDocument doc)"))
* [[$l.get(1)]] -> $l.get(0)
#end
{{/velocity}}
{{velocity}}
#foreach ($l in $xwiki.search("select link.id.link, link.fullName from XWikiLink link where link.id.link not in (select distinct doc.fullName from XWikiDocument doc)"))
* [[$l.get(1)]] -> $l.get(0)
#end
{{/velocity}}
Prerequisites & Installation Instructions
To get it running, download the attachment, open it in a txt editor, copy the code, create a new wiki page, paste the code in, save as xwiki syntax 2.0 and view