Velocity Training
Last modified by Simpel on 2024/01/03
How to use Velocity in XWiki pages
What is it?
- Velocity is a template language.
- It describes what your page should be.
- Which means it controls what you display.
Examples:
- display the name of the user
- display an image under certain circonstances only
- display a list of all the blog categories
Example
{{velocity}}
Welcome $xcontext.user !
#if($hasAdmin)
You will see the following picture because you are an administrator:
image:picture.jpg
#end
{{/velocity}}
Welcome $xcontext.user !
#if($hasAdmin)
You will see the following picture because you are an administrator:
image:picture.jpg
#end
{{/velocity}}
Will output:
- With XWiki and Velocity, you can retrieve informations contained in other pages
#set($docRef = $services.model.createDocumentReference('', 'OtherSpace', 'OtherPage'))
#set($document = $xwiki.getDocument($docRef))
The content of the other document is:
$document.getContent()
#set($document = $xwiki.getDocument($docRef))
The content of the other document is:
$document.getContent()
- or do advanced searches throught the wiki (via the Query Module) :
- « 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... »
- But XWiki also allows you to use Velocity to save things in the wiki.
#set($object = $doc.getObject('XWiki.XWikiUsers'))
$object.set('first_name', 'Nobody')
$doc.save()
$object.set('first_name', 'Nobody')
$doc.save()
Principles
Lines
- A line begining by '#' is a Velocity instruction
- All other lines are normal lines
## This is a velocity comment - a comment is never displayed and is used to
## add useful information inside a source code.
#set($myVar = 42)
## The line above was a velocity instruction
This line is a normal line
## add useful information inside a source code.
#set($myVar = 42)
## The line above was a velocity instruction
This line is a normal line
Variables
- A variable is like a box that can contain data: text, numbers, objects, etc...
- A variable is always prefixed by a dollar '$'.
- To create a variable, just use the #set() Velocity instruction
#set($myVar = 42)
- If a variable is inside a normal line, the content of the variable will be displayed:
#set($myVar = 42)
I am $myVar years old.
I am $myVar years old.
will display:
Some variables are already created by XWiki when you write a Velocity code, and you can use them.
This is some of them:
- $hasEdit : this variable tells us if the current user has the edit rights on the current page
- $isGuest : this variable tells us if the current user is a guest
- $doc : this variable represents the current document.
- $xwiki : this special variable is a tool to perform complicated stuffs
- $request : gives a lot of informations about the current request (like the referer, the query string, etc...)
Methods
- Some variable are objects. An object can contain variables and methods.
- A method is like an action that the object can perform.
- Some actions give you an information, some just perform something.
- To call them, you write $someObject.someMethod() - with the '()'.
Examples:
## will save the current document:
$doc.save()
## will give you the content of the document:
$doc.getContent()
## this method takes a "parameter", a text, which will be the new title:
$doc.setTitle("My new title")
## will give you the current skin
$xwiki.getSkin()
$doc.save()
## will give you the content of the document:
$doc.getContent()
## this method takes a "parameter", a text, which will be the new title:
$doc.setTitle("My new title")
## will give you the current skin
$xwiki.getSkin()
Class
- Every object is different, they don't have the same variables and methods.
- But every object is an instance of a class.
- A class is like a model that describes what the object will have.
- For example, the Document class has a save method, so every objects that are instances of Document will have the save method.
- The String class has a length variable, so every instances of String will have this variable too.
- You can use the following code to know what is the class of an object:
#set($myVar = 42)
$myVar.class.name ## will display 'java.lang.Integer'
#set($myVar2 = "This is a text")
$myVar2.class.name ## will display 'java.lang.String'
$doc.class.name ## will display 'com.xpn.xwiki.api.Document'
$xwiki.class.name ## will display 'com.xpn.xwiki.api.XWiki'
$myVar.class.name ## will display 'java.lang.Integer'
#set($myVar2 = "This is a text")
$myVar2.class.name ## will display 'java.lang.String'
$doc.class.name ## will display 'com.xpn.xwiki.api.Document'
$xwiki.class.name ## will display 'com.xpn.xwiki.api.XWiki'
- Now that you know the class of your object, you can google it to have its documentation!
- With this documentation, you will be able to knows what method you can use.
- Example with java.lang.String
- As you may have noticed, the classes come from the Java world.
- The documentation about the java classes is called Javadoc.
- So you can use the the Javadoc for Velocity too!
Basic instructions
Conditions
- When you want to display something only under certain circumstances, you can use the #if command.
#if($isGuest)
Welcome visitor! You should subscribe to the wiki !
#end
Welcome visitor! You should subscribe to the wiki !
#end
- You can also use the #else command:
#if($isGuest)
Welcome visitor! You should subscribe to the wiki !
#else
Hello $xcontext.user! I'm happy to see a registred user, I hate visitors!
#end
Welcome visitor! You should subscribe to the wiki !
#else
Hello $xcontext.user! I'm happy to see a registred user, I hate visitors!
#end
Conditions (bis)
- You can compare variables, with the following operators:
- == : compare if the variables are equal
- != : say if the variables are different
- > : say if the variable is superior to the other
- < : do the oposite
- >= : say if the variable is superior or equal to the other
- <= : say if the variable is inferior or equal to the other
- You can create complicated conditions, with the logic operators:
- && : which means "AND".
- || : which means "OR".
- ! : which means "NOT".
Examples
#set($a = 12)
#set($b = 28)
#if($a < $b)
A is inferior
#else
B is inferior
#end
#if($a < 20 && $b > 17)
A is inferior than 20 AND B is superior than 17
#end
#if($a == 15 || $b <= 2)
A equals 15 OR B is inferior than 2 or equal
#end
#set($b = 28)
#if($a < $b)
A is inferior
#else
B is inferior
#end
#if($a < 20 && $b > 17)
A is inferior than 20 AND B is superior than 17
#end
#if($a == 15 || $b <= 2)
A equals 15 OR B is inferior than 2 or equal
#end
Examples (continued)
#set($c = true)
#if($c)
C is true
#end
#if($doc.isNew())
The document is New
#else
The document is an old document
#end
#if(!$doc.isHidden())
The document is NOT hidden
#end
#if($c)
C is true
#end
#if($doc.isNew())
The document is New
#else
The document is an old document
#end
#if(!$doc.isHidden())
The document is NOT hidden
#end
Lists
- You can create a list of objects.
#set($myList = ['My first Item', 'My Second Item', 'My third item'])
- You can add a new element in the list:
$myList.add('My fourth item')
- You can know how many objects are inside the list:
$myList.size()
- You can ask if an object is inside the list
$myList.contains('My Second Item') ## which tells me 'true' or 'false'
Example of lists
$doc.getComments() ## will give all the comments of the current page !
$doc.getAttachmentList() ## will give all the attachments of the current page
$xwiki.getSpaces() ## will give the list of the different spaces of the wiki
$doc.getAttachmentList() ## will give all the attachments of the current page
$xwiki.getSpaces() ## will give the list of the different spaces of the wiki
How could I know the number of spaces in the wiki?
$xwiki.getSpaces().size()
How could I know if the space 'BlaBla' exists?
$xwiki.getSpaces().contains('BlaBla')
Foreach
- How can I display all the elements of a list in a nice way?
- Use the #foreach loop, son.
- Example:
This is the list of all the spaces of the wiki
#set($spaceList = $xwiki.getSpaces())
#foreach($space in $spaceList)
* $space
#end
#set($spaceList = $xwiki.getSpaces())
#foreach($space in $spaceList)
* $space
#end
- Results:
The API
- XWiki offers a lot of objects with a lot of methods, to perform a lot of things !
- Delete a document, add a tag to another document, display the list of all blog entries, handle complex formulars, etc...
- This objects & methods are called the API (as Application Programming Interface).
- But how can I know what are theses objects and how to use it?
By using the XWiki Script Reference Documentation (SRD)
Go to the SRD.
SRD
- The left column lists all the XWiki special variables that make the API.
- Select one of them, and you will have all the methods this special variable offers
- Examples:
- $xwiki offers a method getDocument()
- $doc has a method addAttachment()
- etc...
- Examples:
Is the API a mess?
- While looking at the SRD, we can ask youself "how many special variables are there?"
- When we create a variable for our own usage, we have to be sure first to not call it as an existing special variable.
- It's a mess!!!
Introducing Script Services
- In order to make the things cleaner, the plan is to remove a lot of this special variables and replace them by script services.
- Script services will become the only API in future.
- All script services are prefixed by $services.
- To use a script service, you do it this way:
$services.query ## to perform complicated researchs
$services.localization ## to take care of the languages
$services.officeimporter ## to import office documents
...
$services.localization ## to take care of the languages
$services.officeimporter ## to import office documents
...
- Of course, it is documented on the SRD!
- Sometime, you have different ways to do the same thing:
- Using an old method (which may be declared as deprecated).
- Using a script service instead
- Always perfers to use Script Service instead of deprecated APIs!!!
$xwiki.searchDocument() ## allow us to perfom a query with the HQL language
## now please use:
$services.query.hql() ## allow us to perfom a query with the HQL language
## or even better:
$services.query.xwql() ## XWQL language is easier to use
## now please use:
$services.query.hql() ## allow us to perfom a query with the HQL language
## or even better:
$services.query.xwql() ## XWQL language is easier to use
- Because it's the future!
Manipulation of XObjects
What is an XObject ?
- An XObject is an object that you can save in the wiki.
- An XObject is attached to a document, and you can see them with the "objects editor" on the wiki.
XClass
- An XClass is a class (a description) for XObjects.
- You can define them using the class editor.
- Or by using Application Within Minutes!
Class Editor
Application Within Minutes
Why using XClass and XObjects?
- It allows us to store structured informations.
- A Blog Post (with a title, a date, a content, etc...)
- An Evaluation document (with a remark for each category, a mark, etc...)
- An Holiday Request (with dates, status, etc...)
- So the information is not lost in a giant document that holds only a big text...
- And you can create Applications!
XClass is used everywhere
- Almost everything in XWiki is an XClass and stored as XObjects!
- Users
- Groups
- Comments
- Tags
- Access Rights
- ....
- Learn to use XClass and you can control all your wiki.
A comment is an XObject
A user is an XObject
How to get an XObject with Velocity?
## First, get the object
#set($object = $doc.getObject('XWiki.XWikiUsers'))
## The parameter is the name of the class of the object you want to have
## (a document can hold multiple objects of different classes)
## The class name is the Document name where the class is defined
## Display a parameter:
$object.get('first_name')
## the parameter is the name of the field you want to display
## if you are in "edit" mode, an HTML field will be displayed instead of the object value.
## Set values:
$object.set('last_name', 'Bond')
$object.set('first_name', 'James')
## Then save the document if you want your changes to be conserved
## (you can add a comment when you save)
$doc.save('I have changed the name of the user.')
#set($object = $doc.getObject('XWiki.XWikiUsers'))
## The parameter is the name of the class of the object you want to have
## (a document can hold multiple objects of different classes)
## The class name is the Document name where the class is defined
## Display a parameter:
$object.get('first_name')
## the parameter is the name of the field you want to display
## if you are in "edit" mode, an HTML field will be displayed instead of the object value.
## Set values:
$object.set('last_name', 'Bond')
$object.set('first_name', 'James')
## Then save the document if you want your changes to be conserved
## (you can add a comment when you save)
$doc.save('I have changed the name of the user.')
You can rollback what your script has done
Tips
How to get a document?
- In the past, we used to do:
#set($document = $xwiki.getDocument('Space.Page'))
- But it's not good, because what if the page name has a dot?
#set($document = $xwiki.getDocument('Space.Pa.ge'))
## ??? What is the Space ? What is the Page ?
## ??? What is the Space ? What is the Page ?
- And what will happen if the document name have accents or weird characters?
Solution: use references !
#set($reference = $services.model.createDocumentReference('Wiki', 'Space', 'Page'))
#set($document = $xwiki.getDocument($reference))
#set($document = $xwiki.getDocument($reference))
- It is better! The reference tool allow us to strictly separate what is the space and what is the page
- And the reference tool will take care of weird characters !
#set($reference = $services.model.createDocumentReference('Wiki', 'Space', 'Pa.ge'))
#set($document = $xwiki.getDocument($reference))
## Not a problem!!!
#set($document = $xwiki.getDocument($reference))
## Not a problem!!!
References
- You can get create references for documents in other wikis :
#set($reference = $services.model.createDocumentReference('Wiki', 'Space', 'Page'))
- If you want to get a document in the current wiki, you can set an empty parameter:
#set($reference = $services.model.createDocumentReference('', 'Space', 'Page'))
## the reference point to a document in the current wiki
## the reference point to a document in the current wiki
Use case: changing the name of a user
## First, create a reference to their user page
#set($reference = $services.model.createDocumentReference('', 'XWiki', 'ldubost'))
## Then, get its document
#set($document = $xwiki.getDocument($reference))
## Then, get the 'User' object
#set($object = $document.getObject('XWiki.XWikiUsers'))
## Then change their name
$object.set('first_name', 'Harry')
$object.set('last_name', 'Potter')
## And save the document
$document.save()
#set($reference = $services.model.createDocumentReference('', 'XWiki', 'ldubost'))
## Then, get its document
#set($document = $xwiki.getDocument($reference))
## Then, get the 'User' object
#set($object = $document.getObject('XWiki.XWikiUsers'))
## Then change their name
$object.set('first_name', 'Harry')
$object.set('last_name', 'Potter')
## And save the document
$document.save()
But remember we know who changes what!
"I have your name and I know where you live..."
Going further
- See the Velocity documentation to have more details about the language itself
- See the XWiki Script Guide to have some informations about how to make scripts in XWiki
- See the XWiki Query Module to learn how to do advanced queries
- See the XWiki Data Model to learn how to create your XWiki classes
But in general:
- practice and ask for help!!!
- I hope you now have a better idea of what Velocity is and how you can use it in XWiki.