Wiki source code of FAQ Pages

Last modified by Eleni Cojocariu on 2026/10/09 19:21

Show last authors
1 One row per [[FAQ>>doc:FAQ.WebHome]], with what it was converted into. The numbers on [[Migration progress>>XWikiOrg.documentation-scripts-queries.migration-progress.WebHome]] are these same queries counted instead of listed.
2
3 {{velocity}}
4 #set ($Q = '"')
5 #set ($mappingClass = 'XWikiOrg.documentation-scripts-queries.MigratedPageClass')
6 #set ($redirectClass = 'XWiki.RedirectClass')
7 ## A FAQ is a page carrying a FAQCode.FAQClass object -- the same set the FAQ home page lists, and
8 ## the same number its live table reports. The FAQ space holds further pages without that object;
9 ## they are deliberately out of scope here.
10 #set ($base = "type:DOCUMENT AND wiki:xwiki AND hidden:false AND space_prefix:${Q}FAQ${Q} AND class:${Q}FAQCode.FAQClass${Q} AND -name:WebPreferences AND doclocale:${Q}${Q}")
11 ## Only the fields the table reads. The first five are mandatory whatever it shows: SolrQueryExecutor
12 ## resolves every result to a DocumentReference to check view rights, and a result it cannot resolve
13 ## is dropped -- an incomplete 'fl' empties the table while the total still looks right. 'class' is
14 ## the multi-valued field holding every class the page carries an object of, and it is what tells an
15 ## entry from a plain page as well as which rows are worth a getDocument() call.
16 #set ($fields = 'wiki,spaces,name,type,doclocale,fullname,title_,class')
17
18 = Pages carrying a FAQ object =
19
20 #set ($query = $services.query.createQuery($base, 'solr'))
21 #set ($discard = $query.setLimit(2000))
22 #set ($discard = $query.bindValue('fl', $fields))
23 #set ($discard = $query.bindValue('sort', 'fullname asc'))
24 #set ($results = $query.execute().get(0).results)
25 ## The same test as the Done column of the summary page, so the two can never disagree.
26 #set ($doneQuery = $services.query.createQuery("${base} AND property.XWiki.TagClass.tags:done", 'solr'))
27 #set ($discard = $doneQuery.setLimit(2000))
28 #set ($discard = $doneQuery.bindValue('fl', $fields))
29 #set ($doneRefs = [])
30 #foreach ($row in $doneQuery.execute().get(0).results)
31 #set ($discard = $doneRefs.add($row.get('fullname')))
32 #end
33 #set ($redirectCount = 0)
34 ## Distinct replacement pages of the whole set: several legacy pages often converge on the same new
35 ## page, so this is a count of labels already seen, not a sum of the rows.
36 #set ($allTargets = [])
37 (% class="table" %)
38 |=Legacy page|=Done|=Converted into|=Redirects to
39 #foreach ($row in $results)
40 #set ($fullName = $row.get('fullname'))
41 #set ($title = "$!row.get('title_')")
42 #if ($title == '')
43 #set ($title = "$!row.get('name')")
44 #end
45 #set ($title = $title.replace('|', '~|'))
46 #set ($classes = $row.get('class'))
47 #set ($newPages = '')
48 #set ($redirect = '')
49 #if ($classes && ($classes.contains($mappingClass) || $classes.contains($redirectClass)))
50 #set ($legacyDoc = $xwiki.getDocument($fullName))
51 #set ($mapping = $legacyDoc.getObject($mappingClass))
52 #if ($mapping)
53 #set ($newPages = "$!mapping.getValue('newPages')")
54 #end
55 #set ($redirectObject = $legacyDoc.getObject($redirectClass))
56 #if ($redirectObject)
57 #set ($redirect = "$!redirectObject.getValue('location')")
58 #end
59 #end
60 #if ($doneRefs.contains($fullName))
61 #set ($doneCell = '✅')
62 #else
63 #set ($doneCell = '❌')
64 #end
65 #set ($targets = [])
66 #set ($targetLabels = [])
67 #foreach ($line in $newPages.split('[\r\n]+'))
68 ## The field holds one wiki link per line, so that moving a replacement page rewrites it: the
69 ## rename job only follows links, and a bare reference it cannot see goes stale silently. Values
70 ## written before that change are still bare, hence unwrapping rather than parsing a link.
71 #set ($target = $line.trim().replaceAll('^\[\[', '').replaceAll('\]\]$', ''))
72 #set ($target = $target.replaceAll('\|\|.*$', '').replaceAll('^.*>>', ''))
73 #set ($target = $target.replaceAll('^doc:', '').trim())
74 #if ($target != '')
75 #set ($label = $target.replaceAll('^xwiki:', '').replaceAll('\.WebHome$', ''))
76 #set ($discard = $targetLabels.add($label))
77 #set ($discard = $targets.add("[[$label>>doc:$target]]"))
78 #if (!$allTargets.contains($label))
79 #set ($discard = $allTargets.add($label))
80 #end
81 #end
82 #end
83 ## A redirect names a replacement too, and it is the only one most legacy pages have: list it here
84 ## as well, unless the mapping object already records it.
85 #if ($redirect == '')
86 #set ($redirectCell = '—')
87 #else
88 #set ($redirectCount = $redirectCount + 1)
89 #set ($redirectLabel = $redirect.replaceAll('^xwiki:', '').replaceAll('\.WebHome$', ''))
90 #set ($redirectCell = "[[$redirectLabel>>doc:$redirect]]")
91 #if (!$targetLabels.contains($redirectLabel))
92 #set ($discard = $targets.add("[[$redirectLabel>>doc:$redirect]] //(redirect)//"))
93 #end
94 #if (!$allTargets.contains($redirectLabel))
95 #set ($discard = $allTargets.add($redirectLabel))
96 #end
97 #end
98 #if ($targets.isEmpty())
99 #set ($targetCell = '—')
100 #else
101 #set ($targetCell = $stringtool.join($targets, '\\'))
102 #end
103 |[[$title>>doc:$fullName]]|$doneCell|$targetCell|$redirectCell
104 #end
105 |=**$results.size() pages**|=**$doneRefs.size() done**|=**$allTargets.size() new pages**|=**$redirectCount redirects**
106 {{/velocity}}
107
108 A page counts as **done** when it carries the ##done## tag. //Converted into// is the ##newPages## field of its [[MigratedPageClass>>XWikiOrg.documentation-scripts-queries.MigratedPageClass]] object, so it stays empty until someone records where the content went. The total under //Converted into// counts the **distinct** replacement pages of the set, so it is smaller than the sum of the rows whenever several pages were merged into one. //Redirects to// is the ##location## of an ##XWiki.RedirectClass## object: such a page already sends its readers elsewhere, whether or not anyone marked it as done. None of the three has been used in this space yet, so the table shows the starting state.

Get Connected