Show last authors
1 {{include reference="Store.Code.Macros" /}}
2
3 {{velocity output="false"}}
4 #macro (getPriceMatrix $skus)
5 ## Make sure the rows are sorted by support level.
6 #set ($priceMatrix = {
7 'columns': $collectiontool.sortedSet,
8 'rows': {
9 'bronze': {},
10 'silver': {},
11 'gold': {},
12 'platinum': {},
13 'diamond': {}
14 }
15 })
16 #foreach ($sku in $skus)
17 #set ($support = "$!sku.support")
18 #set ($users = $numbertool.toNumber($sku.users).intValue())
19 #set ($price = "$!sku.price")
20 #if ($support && $users && $price)
21 #set ($pricePerUsers = $priceMatrix.rows.get($support))
22 #if (!$pricePerUsers)
23 #set ($pricePerUsers = {})
24 #set ($discard = $priceMatrix.rows.put($support, $pricePerUsers))
25 #end
26 #set ($discard = $pricePerUsers.put($users, $price))
27 #set ($discard = $priceMatrix.columns.add($users))
28 #end
29 #end
30 #set ($emptyRows = [])
31 #foreach ($entry in $priceMatrix.rows.entrySet())
32 #if ($entry.value.isEmpty())
33 #set ($discard = $emptyRows.add($entry.key))
34 #end
35 #end
36 #set ($discard = $priceMatrix.rows.keySet().removeAll($emptyRows))
37 #end
38
39 #macro (findSKUMatchingCurrentLicense $priceMatrix $minUserCount $currentLicenseDetails)
40 #set ($skuMatchingCurrentLicense = $NULL)
41 #if ($priceMatrix.rows.containsKey($currentLicenseDetails.support))
42 ## Select the best match for the specified support level.
43 #foreach ($column in $priceMatrix.columns)
44 #set ($price = $priceMatrix.rows.get($currentLicenseDetails.support).get($column))
45 #if ($price && $column >= $mathtool.max($minUserCount, $currentLicenseDetails.maxUserCount))
46 #set ($skuMatchingCurrentLicense = "$currentLicenseDetails.support,$column")
47 #break
48 #end
49 #end
50 #end
51 #if (!$skuMatchingCurrentLicense)
52 ## Select the best match for the specified user limit.
53 #foreach ($entry in $priceMatrix.rows.entrySet())
54 #foreach ($column in $priceMatrix.columns)
55 #set ($price = $entry.value.get($column))
56 #if ($price && $column >= $mathtool.max($minUserCount, $currentLicenseDetails.maxUserCount))
57 #set ($skuMatchingCurrentLicense = "$entry.key,$column")
58 #break
59 #end
60 #end
61 #if ($skuMatchingCurrentLicense)
62 #break
63 #end
64 #end
65 #end
66 #end
67
68 #macro (displayPriceMatrix $priceMatrix $minUserCount $currentLicenseDetails $readOnly)
69 <table class="prices">
70 <tr>
71 <th class="legend">$escapetool.xml($services.localization.render('store.buyLicense.support'))
72 / $escapetool.xml($services.localization.render('store.buyLicense.users'))</th>
73 #foreach ($column in $priceMatrix.columns)
74 #if ($column < 0)
75 #set ($columnLabel = $services.localization.render('store.buyLicense.unlimitedUsers'))
76 #set ($columnHint = $services.localization.render('store.buyLicense.unlimitedUsers.hint'))
77 #else
78 #set ($columnLabel = $column)
79 #set ($columnHint = $services.localization.render('store.buyLicense.users.hint', [$column]))
80 #end
81 #set ($disabled = $column >= 0 && $column < $minUserCount)
82 <th class="users#if ($disabled) disabled#end" title="$escapetool.xml($columnHint)"
83 >$escapetool.xml($columnLabel)<span class="icon">$services.icon.renderHTML('user')</span></th>
84 #end
85 </tr>
86 #set ($selectedSKU = $NULL)
87 #if (!$readOnly && $currentLicenseDetails)
88 #findSKUMatchingCurrentLicense($priceMatrix $minUserCount $currentLicenseDetails)
89 #set ($selectedSKU = $skuMatchingCurrentLicense)
90 #end
91 #foreach ($entry in $priceMatrix.rows.entrySet())
92 <tr class="support-$escapetool.xml($entry.key)">
93 <th><a tabindex="0" role="button" data-toggle="popover" data-trigger="focus" data-html="true"
94 title="$escapetool.xml($services.localization.render("store.buyLicense.support.${entry.key}.title"))"
95 data-content="$escapetool.xml($services.localization.render(
96 "store.buyLicense.support.${entry.key}.description", ['<a href="https://xwiki.com/en/pricing/">', '</a>']))"
97 >$escapetool.xml($services.localization.render("store.buyLicense.support.$entry.key"))<span
98 class="icon">$services.icon.renderHTML('info')</span></a></th>
99 #foreach ($column in $priceMatrix.columns)
100 #set ($price = $entry.value.get($column))
101 #if ($price)
102 #set ($sku = "$entry.key,$column")
103 #set ($disabled = $column >= 0 && $column < $minUserCount)
104 #if (!$disabled && !$selectedSKU && !$readOnly)
105 #set ($selectedSKU = $sku)
106 #end
107 <td class="price price-euro#if ($disabled) disabled#elseif ($selectedSKU == $sku) active#end"
108 data-support="$escapetool.xml($entry.key)" data-users="$escapetool.xml($column)">
109 <label>#if (!$readOnly)<input type="radio" name="sku" value="$escapetool.xml($sku)" required="required"
110 #if ($disabled)disabled="disabled"#elseif ($selectedSKU == $sku)checked="checked"#end
111 />#end$escapetool.xml($price)</label>
112 </td>
113 #else
114 <td/>
115 #end
116 #end
117 </tr>
118 #end
119 </table>
120 #end
121
122 #macro (getLicenseDetails)
123 #set ($licenseDetails = {})
124 #foreach ($name in ['firstName', 'lastName', 'email', 'instanceId'])
125 #set ($discard = $licenseDetails.put($name, $request.session.getAttribute("com.xwiki.store.buyer.$name")))
126 #end
127 #set ($licenseDetails.featureId = $doc.getValue('id'))
128 #set ($licenseDetails.extensionVersion = $request.version)
129 #if ("$!licenseDetails.extensionVersion" == '')
130 ## Use the latest stable version.
131 #set ($versions = $services.extension.resolveVersions($licenseDetails.featureId, 0, -1))
132 ## The versions are returned in ascending order and we want the latest.
133 ## Note that we can't access the last item directly. We're forced to iterate.
134 #foreach ($version in $versions)
135 #if ($version.type == 'STABLE')
136 #set ($licenseDetails.extensionVersion = $version.value)
137 #end
138 #end
139 #end
140 #set ($licenseDetails.licenseType = 'paid')
141 #end
142
143 #macro (getPackageExtension $packageDoc)
144 #set ($extension = $services.extension.resolve($packageDoc.getValue('id'), $packageDoc.getValue('lastVersion')))
145 #set ($packageId = $extension.getProperty('xwiki.extension.licensing.packageId'))
146 #if ("$!packageId" != '')
147 ## See XWIKI-15051: SafeExtension#getProperty(key, defaultValue) ignores the default value
148 #set ($packageVersion = $extension.getProperty('xwiki.extension.licensing.packageVersion'))
149 #if ("$!packageVersion" == '')
150 #set ($packageVersion = $extension.id.version.toString())
151 #end
152 #set ($packageExtension = $services.extension.resolve($packageId, $packageVersion))
153 #end
154 #end
155
156 #macro (displayPackageExtensions)
157 #getPackageExtension($doc)
158 #if ($packageExtension)
159 <div class="packageDependencies">
160 $services.localization.render('store.extension.packageDependencies.info', [$doc.getValue('name')])
161 <ul>
162 #foreach ($dependency in $packageExtension.dependencies)
163 #set ($extension = $services.extension.resolve($dependency))
164 #getExtensionPageName($extension.id.id)
165 #if ($extensionPageName.size() > 0)
166 #set ($extensionPageName = $extensionPageName[0])
167 #else
168 #set ($extensionPageName = $extension.name)
169 #end
170 <li>
171 ## Add a nice separator between extension names.
172 $services.icon.renderHTML('certificate')
173 #if ($xwiki.exists($extensionPageName))
174 #set ($extensionDoc = $xwiki.getDocument($extensionPageName))
175 <a href="$extensionDoc.URL#pricing" target="_blank">$extensionDoc.getValue('name')</a>
176 #else
177 <a href="http://extensions.xwiki.org?id=$extension.id.id" class="wikiexternallink" target="_blank">
178 $extensionPageName (Free)
179 </a>
180 #end
181 </li>
182 #end
183 </ul>
184 </div>
185 #end
186 #end
187
188 #macro (displayParentPackageInfo $licenseDetails)
189 ## Get all packages of extensions from store.
190 #set ($statement = "from doc.object(Store.Code.PayingAppsClass) as app where app.isPackage = '1'")
191 #set ($results = $services.query.xwql($statement).execute())
192 ## Get all licenses of the user.
193 #if ("$!licenseDetails.instanceId" != '')
194 #getLicenses($licenseDetails.instanceId)
195 #else
196 #set ($licenses = [])
197 #end
198 #foreach ($packageName in $results)
199 #set ($packageDoc = $xwiki.getDocument($packageName))
200 #getPackageExtension($packageDoc)
201 #set ($packageLink = "<a href='$packageDoc.URL#pricing' target='_blank'>$packageDoc.getValue('name')</a>")
202 ## Check if the current extension belongs to the currently analyzed package.
203 #isInPackage($doc.getValue('id') $packageExtension)
204 #if ($isInPackage)
205 #getPackageAppsSuggestions($packageExtension $licenses)
206 <div class="parentPackageInfo">
207 #if ($packageApps.size() > 0)
208 #set ($extraInfo = " $services.localization.render('store.extension.parentPackage.extraInfo', [$stringtool.join($packageApps, ', ')])")
209 #end
210 $services.localization.render('store.extension.parentPackage.info', [$doc.getValue('name'), $packageLink, "$!extraInfo"])
211 </div>
212 #end
213 #end
214 #end
215
216 #macro (isInPackage $extensionId $package)
217 #set ($isInPackage = false)
218 #foreach ($dependency in $package.dependencies)
219 #if ($dependency.id.equals($extensionId))
220 #set ($isInPackage = true)
221 #break
222 #end
223 #end
224 #end
225
226 #macro (getPackageAppsSuggestions $packageExtension $licenses)
227 ## Collect all the apps that are covered by a license, for the current user/instance id.
228 #set ($packageApps = [])
229 #foreach ($license in $licenses)
230 #set ($licenseDoc = $xwiki.getDocument($license))
231 ## Check if the user's licensed extensions belong to the currently analyzed package.
232 #isInPackage($licenseDoc.getValue('featureId') $packageExtension)
233 #if ($isInPackage)
234 #getExtensionPageName($licenseDoc.getValue('featureId'))
235 #if ($extensionPageName.size() > 0)
236 #set ($extensionDoc = $xwiki.getDocument($extensionPageName[0]))
237 ## Exclude the current extension from the list of suggested extensions.
238 #if (!$doc.documentReference.equals($extensionDoc.documentReference))
239 #set ($discard = $packageApps.add("<a href='$extensionDoc.URL' target='_blank'>$extensionDoc.getValue('name')</a>"))
240 #end
241 #end
242 #end
243 #end
244 #end
245
246 #macro (benefits)
247 <p>What do you get when you purchase an XWiki extension?</p>
248 <div class="row" id="benefits">
249 <div class="col-xs-12 col-sm-4">
250 <div class="icon">$services.icon.renderHTML('key')</div>
251 <h2>1 year license</h2>
252 <p>By purchasing an XWiki extension license, you'll benefit from it during one year.</p>
253 </div>
254 <div class="col-xs-12 col-sm-4">
255 <div class="icon">$services.icon.renderHTML('refresh')</div>
256 <h2>Free updates</h2>
257 <p>You benefit from all the extension updates during one year. You are always up to date.</p>
258 </div>
259 <div class="col-xs-12 col-sm-4">
260 <div class="icon">$services.icon.renderHTML('wrench')</div>
261 <h2>Support included</h2>
262 <p>If you are facing an issue, you can reach the XWiki support. Our team is always available to help.</p>
263 </div>
264 </div>
265 #end
266
267 #macro (getCurrentLicense $licenseDetails)
268 ## Get the best license for the specified instance and feature.
269 #set ($currentLicenseDetails = $NULL)
270 #getLicenseQuery($licenseDetails.instanceId $licenseDetails.featureId $query)
271 #set ($results = $query.setLimit(1).execute())
272 #if ($results && $results.size() > 0)
273 #set ($currentLicenseDetailsDocument = $xwiki.getDocument($results[0]))
274 #set ($oldLicenseDetails = $licenseDetails)
275 #readLicenseDetailsFromDocument($currentLicenseDetailsDocument)
276 ## Check if the best license is paid and still active.
277 #if ($licenseDetails.type == 'paid' && $licenseDetails.expirationDate
278 && $licenseDetails.expirationDate.time > $datetool.date.time)
279 #set ($currentLicenseDetails = $licenseDetails)
280 #end
281 #set ($licenseDetails = $oldLicenseDetails)
282 #end
283 #end
284
285 #macro (displayCurrentLicense $currentLicenseDetails)
286 #if ($currentLicenseDetails)
287 <dt>
288 <label>$escapetool.xml($services.localization.render('store.buyLicense.currentLicense'))</label>
289 </dt>
290 <dd>
291 ##
292 ## Extension name
293 ##
294 #if ("$!currentLicenseDetails.extensionName" == '')
295 #getLicensedExtension($currentLicenseDetails)
296 #if ($extension)
297 #set ($currentLicenseDetails.extensionName = $extension.name)
298 #else
299 #set ($currentLicenseDetails.extensionName = $currentLicenseDetails.featureId)
300 #end
301 #end
302 ##
303 ## User limit
304 ##
305 #set ($LONG_MAX_VALUE = $mathtool.pow(2,63))
306 #if (!$currentLicenseDetails.maxUserCount || $currentLicenseDetails.maxUserCount == $LONG_MAX_VALUE)
307 ## Unlimited user count.
308 #set ($currentLicenseDetails.maxUserCount = -1)
309 #end
310 ##
311 ## Days left
312 ##
313 #set ($remainingTime = $currentLicenseDetails.expirationDate.time - $datetool.date.time)
314 #set ($daysLeft = $xwiki.jodatime.getDuration($remainingTime).standardDays)
315 ##
316 ## Support
317 ##
318 #if ("$!currentLicenseDetails.support" != '')
319 #set ($support = $services.localization.render("store.buyLicense.support.$currentLicenseDetails.support"))
320 $escapetool.xml($services.localization.render('store.buyLicense.currentLicense.summary',
321 [$currentLicenseDetails.extensionName, $support, $currentLicenseDetails.maxUserCount, $daysLeft]))
322 #else
323 <div class="text-info">
324 $services.icon.renderHTML('info')
325 $escapetool.xml($services.localization.render('store.buyLicense.currentLicense.summaryWithoutSupport',
326 [$currentLicenseDetails.extensionName, $currentLicenseDetails.maxUserCount, $daysLeft]))
327 </div>
328 <p class="xHint">$escapetool.xml($services.localization.render('store.buyLicense.currentLicense.hint'))</p>
329 #end
330 </dd>
331 #end
332 #end
333
334 #macro (buyLicenseForm $licenseDetails $priceMatrix $minUserCount)
335 <form id="buyLicense" class="xform" action="" method="post">
336 <p>Fill in the form below to get your license.</p>
337 <div class="hidden">
338 <input type="hidden" name="instanceId" value="$!escapetool.xml($licenseDetails.instanceId)"/>
339 <input type="hidden" name="featureId" value="$!escapetool.xml($licenseDetails.featureId)"/>
340 <input type="hidden" name="extensionVersion" value="$!escapetool.xml($licenseDetails.extensionVersion)"/>
341 </div>
342 <dl>
343 <dt>
344 <label>$escapetool.xml($services.localization.render('store.buyLicense.buyer'))</label>
345 </dt>
346 <dd>
347 $!licenseDetails.firstName $!licenseDetails.lastName, $licenseDetails.email
348 <a href="#editBuyer" class="editBuyer"
349 title="$escapetool.xml($services.localization.render('store.buyLicense.buyer.edit'))"
350 >$services.icon.renderHTML('pencil')</a>
351 </dd>
352 <dt class="hidden">
353 <label for="firstName">
354 $escapetool.xml($services.localization.render('store.buyLicense.firstName'))
355 </label>
356 </dt>
357 <dd class="hidden">
358 <input type="text" name="firstName" id="firstName" value="$!escapetool.xml($licenseDetails.firstName)"
359 required="required"/>
360 </dd>
361 <dt class="hidden">
362 <label for="lastName">
363 $escapetool.xml($services.localization.render('store.buyLicense.lastName'))
364 </label>
365 </dt>
366 <dd class="hidden">
367 <input type="text" name="lastName" id="lastName" value="$!escapetool.xml($licenseDetails.lastName)"
368 required="required"/>
369 </dd>
370 <dt class="hidden">
371 <label for="email">
372 $escapetool.xml($services.localization.render('store.buyLicense.email'))
373 </label>
374 <span class="xHint">
375 $escapetool.xml($services.localization.render('store.buyLicense.email.hint'))
376 </span>
377 </dt>
378 <dd class="hidden">
379 <input type="email" name="email" id="email" value="$!escapetool.xml($licenseDetails.email)"
380 class="form-control" required="required"/>
381 </dd>
382 #getCurrentLicense($licenseDetails)
383 #displayCurrentLicense($currentLicenseDetails)
384 <dt>
385 <label>$escapetool.xml($services.localization.render('store.buyLicense.options'))</label>
386 <span class="xHint">$escapetool.xml($services.localization.render('store.buyLicense.options.hint'))</span>
387 </dt>
388 <dd>
389 #displayPriceMatrix($priceMatrix $minUserCount $currentLicenseDetails)
390 </dd>
391 </dl>
392 #displayPackageExtensions
393 #displayParentPackageInfo($licenseDetails)
394 #benefits
395 <p>
396 #if ($selectedSKU)
397 <input type="submit" class="button btn-success"
398 value="$escapetool.xml($services.localization.render('store.buyLicense.submit'))"/>
399 #else
400 <input type="button" id="requestLicense" class="button btn-success"
401 value="$escapetool.xml($services.localization.render('store.requestLicense.button'))"/>
402 #end
403 </p>
404 </form>
405 #end
406
407 #macro (accessPurchaseOrderForm $licenseDetails)
408 <form id="accessPurchaseOrder" class="hidden" action="$services.extension.store.activePurchaseOrderURL" method="post">
409 <input type="hidden" name="instanceId" value="$!escapetool.xml($licenseDetails.instanceId)"/>
410 <input type="hidden" name="email" value="$!escapetool.xml($licenseDetails.email)"/>
411 <input type="submit"/>
412 </form>
413 #end
414 {{/velocity}}
415
416 {{velocity}}
417 {{html clean="false"}}
418 #set ($discard = $xwiki.ssx.use('Store.Content.Pricing'))
419 #set ($discard = $xwiki.jsx.use('Store.Content.Pricing'))
420 #getLicenseDetails
421 #getPriceMatrix($prices.skus)
422 #set ($minUserCount = $request.session.getAttribute('com.xwiki.store.buyer.userCount'))
423 #if (!$minUserCount)
424 #set ($minUserCount = 1)
425 #end
426 #if ("$!licenseDetails.instanceId" != '' && "$!licenseDetails.featureId" != '')
427 #buyLicenseForm($licenseDetails $priceMatrix $minUserCount)
428 #accessPurchaseOrderForm($licenseDetails)
429 #else
430 <h2>Options</h2>
431 <p>The price is per year and varies depending on the support level and the number of users.</p>
432 #displayPriceMatrix($priceMatrix $minUserCount $NULL true)
433 #displayPackageExtensions
434 #displayParentPackageInfo($licenseDetails)
435 <h2>Benefits</h2>
436 #benefits
437 <h2>How to Buy</h2>
438 <p>To buy, install this extension from inside your XWiki instance and <a href="#installation">follow the instructions</a>.</p>
439 #end
440 {{/html}}
441 {{/velocity}}
XWiki SAS Copyright © 2024