Wiki source code of Scripting API Guide

Last modified by Sergei Kulagin on 2022/11/29

Show last authors
1 {{box cssClass="floatinginfobox" title="**Contents**"}}
2 {{toc/}}
3 {{/box}}
4
5 This guide covers the main XWiki APIs that you can use from scripts in wiki pages. It's not meant to be comprehensive. For that you'll need to check the [[XWiki Reference API page>>Documentation.DevGuide.API.WebHome]].
6
7 Note that while most examples are written in Velocity you can use [[any other scripting language>>Documentation.DevGuide.Scripting.WebHome]] to access the same APIs.
8
9 = Snippets =
10
11 Make sure to check the [[Snippets wiki>>snippets:Extension.WebHome]] which contains plenty of small script examples that you can copy/paste and adjust for your needs.
12
13 = Querying documents =
14
15 See the [[Query Module>>extensions:Extension.Query Module]] for examples on how to perform queries on the wiki using a scripting language.
16
17 = Create a new Document =
18
19 For example in Velocity:
20
21 {{code language="velocity"}}
22 ## Note that getDocument() creates a Document if it doesn't exist. This can be checked with $newDoc.isNew()
23 #set ($newDoc = $xwiki.getDocument('MySpace.MyPage'))
24 ## Set its content (for example)
25 #set ($discard = $newDoc.setContent("new content"))
26 ## The second parameter to save() indicates whether the save is a minor edit or not
27 #set ($discard = $newDoc.save("some comment explaining the save", true))
28 {{/code}}
29
30 = Accessing the request =
31
32 You can access the HTTP Request by accessing the ##com.xpn.xwiki.web.XWikiServletRequest## object through the ##request## script variable.
33
34 For example in Velocity, to access an ##action## HTTP parameter passed in the request you would write:
35
36 {{code language="velocity"}}
37 $request.action
38 {{/code}}
39
40 Note that this is a shortcut to:
41
42 {{code language="velocity"}}
43 $request.get("action")
44 {{/code}}
45
46 = Getting external content =
47
48 {{warning}}
49 Requires Programming Rights (since XWiki 9.10).
50 {{/warning}}
51
52 You can use the following APIs to get content located at external URLs:
53
54 {{code language="java"}}
55 public String getURLContent(String surl, String username, String password) throws IOException
56 public String getURLContent(String surl) throws IOException
57 public String getURLContent(String surl, String username, String password, int timeout) throws IOException
58 public String getURLContent(String surl, int timeout) throws IOException
59 public byte[] getURLContentAsBytes(String surl, String username, String password)
60 public byte[] getURLContentAsBytes(String surl) throws IOException
61 {{/code}}
62
63 For example in Velocity:
64
65 {{code language="velocity"}}
66 $xwiki.getURLContent("http://google.com")
67 {{/code}}
68
69 = Add objects to a page =
70
71 Here is a piece of Velocity script to show how it's possible to store a new object in one page:
72
73 {{code language="velocity"}}
74 ## Create an object
75 #set($obj = $doc.newObject("XWiki.SomeClass"))
76 $obj.set("field1",$value1)
77 $obj.set("field2",$value2)
78
79 ## Save the object in the page
80 $doc.save()
81 {{/code}}
82
83 The "XWiki.SomeClass" class has to be created (through the class editor): field1 and field2 are property of the class. At the moment, this code works fine only if the user currently logged in has editing rights on the page, otherwise the Document.save() will not work.
84
85 = Access objects in a page =
86
87 Here is a piece of Velocity script to show how it is possible to access an object attached to the page, and read its fields :
88
89 {{code language="velocity"}}
90 ## Retrieve the first object (index [0]) among all objects attached to this page and of a certain class
91 #set($obj = $doc.getObject('SomeSpace.SomeClass'))
92
93 ## Retrieve the raw value of the propertty "field1" for this object, provided
94 ## a property called "field1" is actually defined in the class of this object
95 #set($rawValue = $obj.getProperty('field1').value)
96 SomeSpace.SomeClass[0] : field1 = "$rawValue"
97
98 ## or value displayed (supports l10n or key-value properties)
99 #set($ValueDisplayed = $obj.field1)
100
101 #set($class = $obj.xWikiClass) ## access the class object representing SomeSpace.SomeClass
102 ## return the property type: String, TextAreaDate, Boolean, ...
103 $class.get('field1').classType
104 {{/code}}
105
106
107 You can also go through all the properties of an object, without knowing their respective names. That's how the default Class Sheet works, when you create a class using the Class Wizard.
108
109 {{code language="velocity"}}
110 #set($class = $obj.xWikiClass) ## access the class object representing SomeSpace.SomeClass
111 #foreach($prop in $class.properties) ## go through all properties
112 <dt> *${prop.prettyName}* </dt>
113 <dd>$doc.display($prop.getName())</dd>
114 #end
115 {{/code}}
116
117 Actually the line {{code}}$doc.display(propertyName){{/code}} can either display the property value, or generate an input field in the page, mapped to the property whose name is passed as argument (when you edit the page in inline mode). If you have a Velocity script that uses the ##display(propertyName)## method to access properties of an object attached to the including page and you want to include it somewhere else you have to use the ##includeForm()## Velocity macro in the including script:
118
119 {{code language="velocity"}}
120 #includeForm("spacename.docname")
121 {{/code}}
122
123 See [[the includeForm() macro>>extensions:Extension.Include Form Macro]] for more information.
124
125 = Access objects from any page and loop over all objects of same Class =
126
127 Here is a piece of Velocity script to show how it is possible to access an object attached to the page from another page, and read its fields:
128 (It is similar than previous code except you must "call" page before with ##$xwiki.getDocument##.)
129
130 {{code language="velocity"}}
131 ## get the document which has the object (only one here) - this is the page where I can see things in the object editor
132 ## Retrieve the first object (index [0]) among all objects attached to the page MySpace.MyDocWithMyClassObjects and of a certain class MySpace.MyClass
133 #set( $MyDoc = $xwiki.getDocument("MySpace.MyDocWithMyClassObjects"))
134 ## get the document wich contains the class definition: this page has entries in the class editor
135 #set( $class = $xwiki.getClass("MySpace.MyClass"))
136 #foreach($prop in $class.properties) ## go through all properties
137 * ${prop.prettyName} : $MyDoc.display($prop.getName())
138 #end
139 {{/code}}
140
141 If ##MySpace.MyDocWithMyClassObjects## have many attached objects of ##MySpace.MyClass## class (with different value)
142 {{image reference="APIGuide-MyDocWithMyClassObjects.png"/}} {{image reference="APIGuide-ResultOfLoops.png"/}}
143
144 {{code language="velocity"}}
145 ## if you have more than one object on a page, you will have to loop over them and use "$doc.use"
146 #set($MyDoc = $xwiki.getDocument("MySpace.MyDocWithMyClassObjects"))
147 #set($class = $xwiki.getClass("MySpace.MyClass"))
148 ## loop over all objects
149 #foreach($obj in $MyDoc.getObjects("MySpace.MyClass"))
150 * Object number $velocityCount
151 #set($discard = $MyDoc.use($obj))
152 #foreach($prop in $class.properties) ## go through all properties
153 ** ${prop.prettyName} : $MyDoc.display($prop.getName())
154 #end
155 #end
156 {{/code}}
157
158 = Include a Velocity page into another Velocity page =
159
160 See the [[Include In Velocity tutorial>>FAQ.IncludeInVelocity]].
161
162 = Redirecting to another page =
163
164 It's possible to redirect the user to another page. This is useful for example when a page has been removed and you have given the URL to someone so you want the old page to redirect to the new page.
165
166 Example:
167
168 {{code language="velocity"}}
169 $response.sendRedirect($xwiki.getURL("Space.Page"))
170 {{/code}}
171
172 For more examples, see the [[Redirect Snippet>>snippets:Extension.Redirect]].
173
174 = Add an Attachment to a page =
175
176 For example, in Velocity:
177
178 {{code}}
179 {{velocity}}
180 #set($content = "This is some small arbitrary content")
181 #set($discard = $doc.addAttachment("myfile.txt", $content.getBytes()))
182 #set($discard = $doc.save("some comment"))
183 {{/velocity}}
184 {{/code}}
185
186 = Add a new user to a List of Users xobject =
187
188 Let's imagine that ##Space.Page## contains an xobject having a ##users## xproperty of type "List of Users" (and configured to be a multiselect).
189
190 The following code adds a new user reference to the list:
191
192 {{code}}
193 {{velocity}}
194 #set ($usersObject = $doc.getObject('Space.Page'))
195 #set ($referenceList = $usersObject.getValue('users'))
196 #set ($referenceList = "${referenceList},XWiki.NewUser")
197 #set ($discard = $usersObject.set('users', $referenceList))
198 #set ($discard = $doc.save('Added new user', true))
199 {{velocity}}
200 {{/code}}
201
202 = Create an XClass =
203
204 The following example creates an XClass with a single ##mytextarea## xproperty of type Text Area in the document ##Sandbox.TestClass##.
205
206 {{warning}}
207 Requires Programming Rights
208 {{/warning}}
209
210 {{code}}
211 {{velocity}}
212 #set ($mydoc = $xwiki.getDocument('Sandbox.TestClass'))
213 #set ($myinternaldoc = $mydoc.getDocument())
214 #set ($myclass = $myinternaldoc.getXClass())
215 #set ($discard = $myclass.addTextAreaField("mytextarea", "My Text Area", 100, 5))
216 #set ($discard = $mydoc.save('created doc + xclass'))
217 {{/velocity}}
218 {{/code}}
219
220 = Modify the last update date =
221
222 {{warning}}
223 Requires Programming Rights
224 {{/warning}}
225
226 {{code}}
227 {{velocity}}
228 #set ($mydoc = $xwiki.getDocument('Sandbox.WebHome'))
229 #set ($date = $datetool.toDate('yyyy-MM-dd', '2013-01-01'))
230 #set ($mydocinternal = $mydoc.getDocument())
231 #set ($discard = $mydocinternal.setDate($date))
232 #set ($discard = $mydocinternal.setMetaDataDirty(false))
233 #set ($discard = $mydocinternal.setContentDirty(false))
234 $xwiki.getXWiki().saveDocument($mydocinternal, "change update date", true, $xcontext.getContext())
235 {{/velocity}}
236 {{/code}}
237
238 = Find XDOM Blocks =
239
240 You can access an AST (we all it the XDOM) of a document's content using the ##getXDOM()## API (See [[Rendering Documentation>>rendering:Main.WebHome]] for more). Then you can find all Blocks of a given type.
241
242 For example to find all Headings in ##Sandbox.WebHome## you could write:
243
244 {{code}}
245 {{velocity}}
246 #set ($mydoc = $xwiki.getDocument('Sandbox.WebHome'))
247 #foreach ($block in $mydoc.getXDOM().getBlocks('class:HeaderBlock', 'DESCENDANT'))
248 * $block
249 #end
250 {{/velocity}}
251 {{/code}}
252
253 = Mark a page as hidden =
254
255 {{code}}
256 {{velocity}}
257 #set ($myDoc = $xwiki.getDocument('MySpace.MyPage'))
258 #set ($discard = $myDoc.setHidden(true))
259 ## The second parameter to save() indicates whether the save is a minor edit or not
260 #set ($discard = $myDoc.save("some comment explaining the change", true))
261 {{/velocity}}
262 {{/code}}
263
264 = List all attachments of a page =
265
266 {{code}}
267 {{velocity}}
268 #set ($myDoc = $xwiki.getDocument('Main.attachment.WebHome'))
269 #foreach ($attachment in $myDoc.getAttachmentList())
270 * $attachment.getFilename()
271 #end
272 {{/velocity}}
273 {{/code}}

Get Connected