Wiki source code of Velocity Training
Version 40.1 by Lucas Charpentier (Sereza7) on 2025/04/03
Show last authors
author | version | line-number | content |
---|---|---|---|
1 | {{box cssClass="floatinginfobox" title="**Contents**"}} | ||
2 | {{toc depth="2" start="2"/}} | ||
3 | {{/box}} | ||
4 | |||
5 | = How to use Velocity in XWiki pages = | ||
6 | |||
7 | == What is it? == | ||
8 | |||
9 | === === | ||
10 | |||
11 | * Velocity is a **template** language. | ||
12 | * It describes what your page should be. | ||
13 | ** Which means it **controls** what you **display**. | ||
14 | |||
15 | Examples: | ||
16 | |||
17 | * display the name of the user | ||
18 | * display an image under certain circonstances only | ||
19 | * display a list of all the blog categories | ||
20 | |||
21 | === Example === | ||
22 | |||
23 | {{code language="velocity"}} | ||
24 | {{velocity}} | ||
25 | Welcome $xcontext.user ! | ||
26 | #if($hasAdmin) | ||
27 | You will see the following picture because you are an administrator: | ||
28 | image:picture.jpg | ||
29 | #end | ||
30 | {{/velocity}} | ||
31 | {{/code}} | ||
32 | |||
33 | Will output: | ||
34 | {{image reference="sample1.png"/}} | ||
35 | |||
36 | === === | ||
37 | |||
38 | * With XWiki and Velocity, you can retrieve informations contained in other pages | ||
39 | |||
40 | {{code language="velocity"}} | ||
41 | #set($docRef = $services.model.createDocumentReference('', 'OtherSpace', 'OtherPage')) | ||
42 | #set($document = $xwiki.getDocument($docRef)) | ||
43 | The content of the other document is: | ||
44 | $document.getContent() | ||
45 | {{/code}} | ||
46 | |||
47 | |||
48 | {{image reference="serrure.jpg"/}} | ||
49 | |||
50 | === === | ||
51 | |||
52 | * or do advanced searches throught the wiki (via the //Query Module//) : | ||
53 | ** //« give me all the blog entries posted during the month of july 2012 and that are not archived and that have at least 3 comments and... »// | ||
54 | |||
55 | {{image reference="detective.jpg"/}} | ||
56 | |||
57 | === === | ||
58 | |||
59 | * But XWiki also allows you to use Velocity to **save** things in the wiki. | ||
60 | |||
61 | {{code language="velocity"}} | ||
62 | #set($object = $doc.getObject('XWiki.XWikiUsers')) | ||
63 | $object.set('first_name', 'Nobody') | ||
64 | $doc.save() | ||
65 | {{/code}} | ||
66 | |||
67 | |||
68 | {{image reference="nobody.jpg"/}} | ||
69 | |||
70 | == Principles == | ||
71 | |||
72 | === Lines === | ||
73 | |||
74 | * A line begining by '#' is a Velocity instruction | ||
75 | * All other lines are normal lines | ||
76 | |||
77 | {{code language="velocity"}} | ||
78 | ## This is a velocity comment - a comment is never displayed and is used to | ||
79 | ## add useful information inside a source code. | ||
80 | #set($myVar = 42) | ||
81 | ## The line above was a velocity instruction | ||
82 | This line is a normal line | ||
83 | {{/code}} | ||
84 | |||
85 | === Variables === | ||
86 | |||
87 | * A //variable// is like a box that can contain data: text, numbers, objects, etc... | ||
88 | * A variable is always prefixed by a dollar '$'. | ||
89 | * To create a variable, just use the //#set()// Velocity instruction | ||
90 | |||
91 | {{code language="velocity"}} | ||
92 | #set($myVar = 42) | ||
93 | {{/code}} | ||
94 | |||
95 | * If a variable is inside a normal line, the content of the variable will be displayed: | ||
96 | |||
97 | {{code language="velocity"}} | ||
98 | #set($myVar = 42) | ||
99 | I am $myVar years old. | ||
100 | {{/code}} | ||
101 | |||
102 | will display: | ||
103 | |||
104 | {{image reference="variables.png"/}} | ||
105 | |||
106 | === === | ||
107 | |||
108 | Some variables are already created by XWiki when you write a Velocity code, and you can use them. | ||
109 | |||
110 | |||
111 | This is some of them: | ||
112 | |||
113 | * //$hasEdit// : this variable tells us if the current user has the edit rights on the current page | ||
114 | * //$isGuest// : this variable tells us if the current user is a guest | ||
115 | * //$doc// : this variable represents the current document. | ||
116 | * //$xwiki// : this special variable is a tool to perform complicated stuffs | ||
117 | * //$request// : gives a lot of informations about the current request (like the referer, the query string, etc...) | ||
118 | |||
119 | === Methods === | ||
120 | |||
121 | * Some variable are //objects//. An object can contain //variables// and //methods//. | ||
122 | * A method is like an //action// that the object can perform. | ||
123 | * Some actions give you an information, some just perform something. | ||
124 | * To call them, you write //$someObject.someMethod()// - with the '()'. | ||
125 | |||
126 | Examples: | ||
127 | |||
128 | {{code language="velocity"}} | ||
129 | ## will save the current document: | ||
130 | $doc.save() | ||
131 | ## will give you the content of the document: | ||
132 | $doc.getContent() | ||
133 | ## this method takes a "parameter", a text, which will be the new title: | ||
134 | $doc.setTitle("My new title") | ||
135 | ## will give you the current skin | ||
136 | $xwiki.getSkin() | ||
137 | {{/code}} | ||
138 | |||
139 | === Class === | ||
140 | |||
141 | * Every object is different, they don't have the same variables and methods. | ||
142 | * But every object is an //instance// of a //class//. | ||
143 | * A //class// is like a model that describes what the object will have. | ||
144 | ** For example, the //Document// class has a //save// method, so every objects that are //instances// of //Document// will have the //save// method. | ||
145 | ** The //String// class has a //length// variable, so every instances of //String// will have this variable too. | ||
146 | |||
147 | === === | ||
148 | |||
149 | * You can use the following code to know what is the class of an object: | ||
150 | |||
151 | {{code language="velocity"}} | ||
152 | #set($myVar = 42) | ||
153 | $myVar.class.name ## will display 'java.lang.Integer' | ||
154 | #set($myVar2 = "This is a text") | ||
155 | $myVar2.class.name ## will display 'java.lang.String' | ||
156 | $doc.class.name ## will display 'com.xpn.xwiki.api.Document' | ||
157 | $xwiki.class.name ## will display 'com.xpn.xwiki.api.XWiki' | ||
158 | {{/code}} | ||
159 | |||
160 | |||
161 | {{image reference="class.jpg"/}} | ||
162 | |||
163 | === === | ||
164 | |||
165 | * Now that you know the class of your object, you can google it to have its documentation! | ||
166 | * With this documentation, you will be able to knows what method you can use. | ||
167 | ** Example with //java.lang.String// | ||
168 | |||
169 | {{image reference="javadoc.png"/}} | ||
170 | |||
171 | === === | ||
172 | |||
173 | * As you may have noticed, the classes come from the //Java// world. | ||
174 | * The documentation about the java classes is called //Javadoc//. | ||
175 | * So you can use the the //Javadoc// for Velocity too! | ||
176 | |||
177 | {{image reference="java.jpg"/}} | ||
178 | |||
179 | == Basic instructions == | ||
180 | |||
181 | === Conditions === | ||
182 | |||
183 | * When you want to display something only under certain circumstances, you can use the //#if// command. | ||
184 | |||
185 | {{code language="velocity"}} | ||
186 | #if($isGuest) | ||
187 | Welcome visitor! You should subscribe to the wiki ! | ||
188 | #end | ||
189 | {{/code}} | ||
190 | |||
191 | * You can also use the //#else// command: | ||
192 | |||
193 | {{code language="velocity"}} | ||
194 | #if($isGuest) | ||
195 | Welcome visitor! You should subscribe to the wiki ! | ||
196 | #else | ||
197 | Hello $xcontext.user! I'm happy to see a registred user, I hate visitors! | ||
198 | #end | ||
199 | {{/code}} | ||
200 | |||
201 | |||
202 | {{image reference="visitors.jpg"/}} | ||
203 | |||
204 | === Conditions (bis) === | ||
205 | |||
206 | * You can compare variables, with the following operators: | ||
207 | ** **//==//** : compare if the variables are equal | ||
208 | ** **//!=//** : say if the variables are different | ||
209 | ** **//>//** : say if the variable is superior to the other | ||
210 | ** **//<//** : do the oposite | ||
211 | ** **//>=//** : say if the variable is superior or equal to the other | ||
212 | ** **//<=//** : say if the variable is inferior or equal to the other | ||
213 | |||
214 | * You can create complicated conditions, with the logic operators: | ||
215 | ** **//&&//** : which means **"AND"**. | ||
216 | ** **//||//** : which means **"OR"**. | ||
217 | ** **//!//** : which means **"NOT"**. | ||
218 | |||
219 | === Examples === | ||
220 | |||
221 | {{code language="velocity"}} | ||
222 | #set($a = 12) | ||
223 | #set($b = 28) | ||
224 | |||
225 | #if($a < $b) | ||
226 | A is inferior | ||
227 | #else | ||
228 | B is inferior | ||
229 | #end | ||
230 | |||
231 | #if($a < 20 && $b > 17) | ||
232 | A is inferior than 20 AND B is superior than 17 | ||
233 | #end | ||
234 | |||
235 | #if($a == 15 || $b <= 2) | ||
236 | A equals 15 OR B is inferior than 2 or equal | ||
237 | #end | ||
238 | {{/code}} | ||
239 | |||
240 | === Examples (continued) === | ||
241 | |||
242 | {{code language="velocity"}} | ||
243 | #set($c = true) | ||
244 | |||
245 | #if($c) | ||
246 | C is true | ||
247 | #end | ||
248 | |||
249 | #if($doc.isNew()) | ||
250 | The document is New | ||
251 | #else | ||
252 | The document is an old document | ||
253 | #end | ||
254 | |||
255 | #if(!$doc.isHidden()) | ||
256 | The document is NOT hidden | ||
257 | #end | ||
258 | {{/code}} | ||
259 | |||
260 | === Lists === | ||
261 | |||
262 | * You can create a list of objects. | ||
263 | |||
264 | {{code language="velocity"}} | ||
265 | #set($myList = ['My first Item', 'My Second Item', 'My third item']) | ||
266 | {{/code}} | ||
267 | |||
268 | * You can add a new element in the list: | ||
269 | |||
270 | {{code language="velocity"}} | ||
271 | $myList.add('My fourth item') | ||
272 | {{/code}} | ||
273 | |||
274 | * You can know how many objects are inside the list: | ||
275 | |||
276 | {{code language="velocity"}} | ||
277 | $myList.size() | ||
278 | {{/code}} | ||
279 | |||
280 | * You can ask if an object is inside the list | ||
281 | |||
282 | {{code language="velocity"}} | ||
283 | $myList.contains('My Second Item') ## which tells me 'true' or 'false' | ||
284 | {{/code}} | ||
285 | |||
286 | |||
287 | {{image reference="teacher.jpg"/}} | ||
288 | |||
289 | === Example of lists === | ||
290 | |||
291 | {{code language="velocity"}} | ||
292 | $doc.getComments() ## will give all the comments of the current page ! | ||
293 | $doc.getAttachmentList() ## will give all the attachments of the current page | ||
294 | $xwiki.getSpaces() ## will give the list of the different spaces of the wiki | ||
295 | {{/code}} | ||
296 | |||
297 | |||
298 | How could I know the number of spaces in the wiki? | ||
299 | |||
300 | {{code language="velocity"}} | ||
301 | $xwiki.getSpaces().size() | ||
302 | {{/code}} | ||
303 | |||
304 | |||
305 | How could I know if the space 'BlaBla' exists? | ||
306 | |||
307 | {{code language="velocity"}} | ||
308 | $xwiki.getSpaces().contains('BlaBla') | ||
309 | {{/code}} | ||
310 | |||
311 | |||
312 | {{image reference="goodmark.jpg"/}} | ||
313 | |||
314 | === Foreach === | ||
315 | |||
316 | * How can I display all the elements of a list in a nice way? | ||
317 | ** Use the //#foreach// loop, son. | ||
318 | * Example: | ||
319 | |||
320 | {{code language="velocity"}} | ||
321 | This is the list of all the spaces of the wiki | ||
322 | #set($spaceList = $xwiki.getSpaces()) | ||
323 | #foreach($space in $spaceList) | ||
324 | * $space | ||
325 | #end | ||
326 | {{/code}} | ||
327 | |||
328 | * Results: | ||
329 | {{image reference="foreach1.png"/}} | ||
330 | |||
331 | == The API == | ||
332 | |||
333 | === === | ||
334 | |||
335 | * XWiki offers a lot of objects with a lot of methods, to perform a lot of things ! | ||
336 | ** Delete a document, add a tag to another document, display the list of all blog entries, handle complex formulars, etc... | ||
337 | * This objects & methods are called the **API** (as //Application Programming Interface//). | ||
338 | * But how can I know what are theses objects and how to use it? | ||
339 | |||
340 | {{image reference="API.jpg"/}} | ||
341 | |||
342 | === By using the XWiki Script Reference Documentation (SRD) === | ||
343 | |||
344 | {{image reference="SRD.png"/}} | ||
345 | |||
346 | Go to the [[SRD>>xwiki:ScriptingDocumentation.WebHome]]. | ||
347 | |||
348 | === SRD === | ||
349 | |||
350 | * The left column lists **all the XWiki special variables that make the API**. | ||
351 | * Select one of them, and you will have **all the methods this special variable offers** | ||
352 | ** Examples: | ||
353 | *** //$xwiki// offers a method //getDocument()// | ||
354 | *** //$doc// has a method //addAttachment()// | ||
355 | *** etc... | ||
356 | |||
357 | === Is the API a mess? === | ||
358 | |||
359 | * While looking at the SRD, we can ask youself //"how many special variables are there?"// | ||
360 | * When we create a variable for our own usage, we have to be sure first to not call it as an existing special variable. | ||
361 | ** It's a mess!!! | ||
362 | |||
363 | {{image reference="mess.jpg"/}} | ||
364 | |||
365 | === Introducing Script Services === | ||
366 | |||
367 | * In order to make the things cleaner, the plan is to remove a lot of this special variables and replace them by //script services//. | ||
368 | * Script services will become the only API in future. | ||
369 | * All script services are prefixed by //$services//. | ||
370 | |||
371 | {{image reference="datacenter.jpg"/}} | ||
372 | |||
373 | === === | ||
374 | |||
375 | * To use a script service, you do it this way: | ||
376 | |||
377 | {{code language="velocity"}} | ||
378 | $services.query ## to perform complicated researchs | ||
379 | $services.localization ## to take care of the languages | ||
380 | $services.officeimporter ## to import office documents | ||
381 | ... | ||
382 | {{/code}} | ||
383 | |||
384 | * Of course, it is documented on the SRD! | ||
385 | |||
386 | {{image reference="wayne.jpg"/}} | ||
387 | |||
388 | === === | ||
389 | |||
390 | * Sometime, you have different ways to do the same thing: | ||
391 | ** Using an old method (which may be declared as //deprecated//). | ||
392 | ** Using a script service instead | ||
393 | * ** Always perfers to use Script Service instead of deprecated APIs!!!** | ||
394 | |||
395 | {{code language="velocity"}} | ||
396 | $xwiki.searchDocument() ## allow us to perfom a query with the HQL language | ||
397 | ## now please use: | ||
398 | $services.query.hql() ## allow us to perfom a query with the HQL language | ||
399 | ## or even better: | ||
400 | $services.query.xwql() ## XWQL language is easier to use | ||
401 | {{/code}} | ||
402 | |||
403 | * Because it's the future! | ||
404 | |||
405 | {{image reference="future.jpg"/}} | ||
406 | |||
407 | == Manipulation of XObjects == | ||
408 | |||
409 | === What is an XObject ? === | ||
410 | |||
411 | * An //XObject// is an **object** that you can **save** in the wiki. | ||
412 | * An XObject is attached to a document, and you can see them with the "objects editor" on the wiki. {{warning}} If you can't see the object editor, it's probably because you are not registered as an advanced user on your wiki. In order to become an advanced user, use the shortcut keys x+x+x+a or go into your profile, section ##Preferences##. This complex editor is hidden from simple users :) {{/warning}} | ||
413 | |||
414 | {{image reference="edit_objects.png"/}} | ||
415 | |||
416 | === === | ||
417 | |||
418 | {{image reference="objects.png"/}} | ||
419 | |||
420 | === XClass === | ||
421 | |||
422 | * An //XClass// is a //class// (a //description//) for XObjects. | ||
423 | ** You can define them using the class editor. | ||
424 | ** Or by using //Application Within Minutes//! | ||
425 | |||
426 | === Class Editor === | ||
427 | |||
428 | {{image reference="class_editor.png"/}} | ||
429 | |||
430 | === Application Within Minutes === | ||
431 | |||
432 | {{image reference="appwithinminutes.png"/}} | ||
433 | |||
434 | === Why using XClass and XObjects? === | ||
435 | |||
436 | * It allows us to store **structured** informations. | ||
437 | ** A //Blog Post// (with a //title//, a //date//, a //content//, etc...) | ||
438 | ** An //Evaluation document// (with a //remark// for each //category//, a //mark//, etc...) | ||
439 | ** An //Holiday Request// (with //dates//, //status//, etc...) | ||
440 | |||
441 | * So the //information// is not lost in a giant document that holds only a big text... | ||
442 | ** And you can create //Applications//! | ||
443 | |||
444 | === XClass is used //everywhere// === | ||
445 | |||
446 | * Almost everything in XWiki is an XClass and stored as XObjects! | ||
447 | ** //Users// | ||
448 | ** //Groups// | ||
449 | ** //Comments// | ||
450 | ** //Tags// | ||
451 | ** //Access Rights// | ||
452 | ** .... | ||
453 | * Learn to use //XClass// and you can **control all your wiki**. | ||
454 | |||
455 | === A comment is an XObject === | ||
456 | |||
457 | {{image reference="comments.png"/}} | ||
458 | |||
459 | === A user is an XObject === | ||
460 | |||
461 | {{image reference="user.png"/}} | ||
462 | |||
463 | === How to get an XObject with Velocity? === | ||
464 | |||
465 | {{code language="velocity"}} | ||
466 | ## First, get the object | ||
467 | #set($object = $doc.getObject('XWiki.XWikiUsers')) | ||
468 | ## The parameter is the name of the class of the object you want to have | ||
469 | ## (a document can hold multiple objects of different classes) | ||
470 | ## The class name is the Document name where the class is defined | ||
471 | |||
472 | ## Display a parameter: | ||
473 | $object.get('first_name') | ||
474 | ## the parameter is the name of the field you want to display | ||
475 | ## if you are in "edit" mode, an HTML field will be displayed instead of the object value. | ||
476 | |||
477 | ## Set values: | ||
478 | $object.set('last_name', 'Bond') | ||
479 | $object.set('first_name', 'James') | ||
480 | |||
481 | ## Then save the document if you want your changes to be conserved | ||
482 | ## (you can add a comment when you save) | ||
483 | $doc.save('I have changed the name of the user.') | ||
484 | {{/code}} | ||
485 | |||
486 | === You can rollback what your script has done === | ||
487 | |||
488 | {{image reference="rollback.png"/}} | ||
489 | |||
490 | == Tips == | ||
491 | |||
492 | === How to get a document? === | ||
493 | |||
494 | * In the past, we used to do: | ||
495 | |||
496 | {{code language="velocity"}} | ||
497 | #set($document = $xwiki.getDocument('Space.Page')) | ||
498 | {{/code}} | ||
499 | |||
500 | * But it's not good, because what if the page name has a dot? | ||
501 | |||
502 | {{code language="velocity"}} | ||
503 | #set($document = $xwiki.getDocument('Space.Pa.ge')) | ||
504 | ## ??? What is the Space ? What is the Page ? | ||
505 | {{/code}} | ||
506 | |||
507 | * And what will happen if the document name have accents or weird characters? | ||
508 | |||
509 | === Solution: use references ! === | ||
510 | |||
511 | {{code language="velocity"}} | ||
512 | #set($reference = $services.model.createDocumentReference('Wiki', 'Space', 'Page')) | ||
513 | #set($document = $xwiki.getDocument($reference)) | ||
514 | {{/code}} | ||
515 | |||
516 | * It is better! The reference tool allow us to strictly separate what is the space and what is the page | ||
517 | * And the reference tool will take care of weird characters ! | ||
518 | |||
519 | {{code language="velocity"}} | ||
520 | #set($reference = $services.model.createDocumentReference('Wiki', 'Space', 'Pa.ge')) | ||
521 | #set($document = $xwiki.getDocument($reference)) | ||
522 | ## Not a problem!!! | ||
523 | {{/code}} | ||
524 | |||
525 | === References === | ||
526 | |||
527 | * You can get create references for documents in other wikis : | ||
528 | |||
529 | {{code language="velocity"}} | ||
530 | #set($reference = $services.model.createDocumentReference('Wiki', 'Space', 'Page')) | ||
531 | {{/code}} | ||
532 | |||
533 | * If you want to get a document in the current wiki, you can set an empty parameter: | ||
534 | |||
535 | {{code language="velocity"}} | ||
536 | #set($reference = $services.model.createDocumentReference('', 'Space', 'Page')) | ||
537 | ## the reference point to a document in the current wiki | ||
538 | {{/code}} | ||
539 | |||
540 | === Use case: changing the name of a user === | ||
541 | |||
542 | {{code language="velocity"}} | ||
543 | ## First, create a reference to their user page | ||
544 | #set($reference = $services.model.createDocumentReference('', 'XWiki', 'ldubost')) | ||
545 | ## Then, get its document | ||
546 | #set($document = $xwiki.getDocument($reference)) | ||
547 | ## Then, get the 'User' object | ||
548 | #set($object = $document.getObject('XWiki.XWikiUsers')) | ||
549 | ## Then change their name | ||
550 | $object.set('first_name', 'Harry') | ||
551 | $object.set('last_name', 'Potter') | ||
552 | ## And save the document | ||
553 | $document.save() | ||
554 | {{/code}} | ||
555 | |||
556 | === But remember we know who changes what! === | ||
557 | |||
558 | {{image reference="history.png"/}} | ||
559 | |||
560 | (% style="text-align: right; margin-top: 20px;" %) | ||
561 | "//I have your name and I know where you live...//" | ||
562 | |||
563 | == Going further == | ||
564 | |||
565 | === === | ||
566 | |||
567 | * See the [[Velocity documentation>>http://velocity.apache.org/]] to have more details about the language itself | ||
568 | * See the [[XWiki Script Guide>>doc:Documentation.DevGuide.Scripting.WebHome]] to have some informations about how to make scripts in XWiki | ||
569 | * See the [[XWiki Query Module>>doc:extensions:Extension.Query Module]] to learn how to do advanced queries | ||
570 | * See the [[XWiki Data Model>>doc:Documentation.DevGuide.DataModel]] to learn how to create your XWiki classes | ||
571 | |||
572 | **But in general:** | ||
573 | |||
574 | * practice and ask for help!!! | ||
575 | |||
576 | === === | ||
577 | |||
578 | * I hope you now have a better idea of what Velocity is and how you can use it in XWiki. | ||
579 | |||
580 | {{image reference="velocity.jpg"/}} |