Modifications pour le document MacroService

Modifié par Florent Charton le 2026/03/13 11:04

Depuis la version 1.1
modifié par superadmin
sur 2022/06/20 08:49
Commentaire de modification : Install extension [org.xwiki.contrib:application-ckeditor-ui/1.63.1]
À la version 6.1
modifié par Florent Charton
sur 2026/03/13 11:04
Commentaire de modification : Install extension [org.xwiki.platform:xwiki-platform-ckeditor-ui/17.10.4]

Résumé

Détails

Propriétés de la Page
Auteur du document
... ... @@ -1,1 +1,1 @@
1 -XWiki.superadmin
1 +xwiki:XWiki.fcharton
Contenu
... ... @@ -38,36 +38,66 @@
38 38  ## }
39 39  ## ================================================================
40 40  #macro (getMacroList $syntaxId)
41 +
42 + ## Loads the css resources to display the macros list
43 + ## TODO: Refactor once we add support for loading css files from javascript without velocity.
44 + #if ($xcontext.action == 'get')
45 + #template('display_macros.vm')
46 + #initRequiredSkinExtensions()
47 + #end
48 +
49 + #set ($discard = $xwiki.linkx.use($services.webjars.url('selectize.js', 'css/selectize.bootstrap3.css'),
50 + {'type': 'text/css', 'rel': 'stylesheet'}))
51 + #set ($discard = $xwiki.ssfx.use('uicomponents/suggest/xwiki.selectize.css', true))
52 +
53 + #if ($xcontext.action == 'get')
54 + #sendRequiredSkinExtensions()
55 + #end
56 +
41 41   #set ($syntax = $services.rendering.resolveSyntax($syntaxId))
42 42   #set ($macroDescriptors = $services.rendering.getMacroDescriptors($syntax))
43 - #if (!$macroDescriptors)
44 - ## Before XWiki 9.7RC1 we had to use APIs that require programming rights.
45 - #set ($macroDescriptors = [])
46 - #try()
47 - #set ($macroManager = $services.component.getInstance('org.xwiki.rendering.macro.MacroManager'))
48 - #foreach ($macroId in $macroManager.getMacroIds($syntax))
49 - #set ($macroDescriptor = $macroManager.getMacro($macroId).descriptor)
50 - #set ($discard = $macroDescriptors.add($macroDescriptor))
51 - #end
52 - #end
53 - #end
54 54   #set ($data = {})
55 55   #set ($allMacrosExcludedCategories = [])
56 56   #set ($discard = $allMacrosExcludedCategories.add("#maybeTranslate('rendering.macroCategory.Internal' 'Internal')"))
57 57   #set ($discard = $allMacrosExcludedCategories.add("#maybeTranslate('rendering.macroCategory.Deprecated' 'Deprecated')"))
58 58   #set ($discard = $data.put('options', { 'allMacrosExcludedCategories' : $allMacrosExcludedCategories }))
64 + ## If the current user do not want to display hidden documents, we initialize the set of hidden default
65 + ## categories.
66 + ## TODO: Make the list of hidden by default categories configurable from the administration (XWIKI-19993).
67 + #if(!$services.user.getProperties().displayHiddenDocuments())
68 + #set ($hiddenCategories = $services.rendering.getHiddenMacroCategories())
69 + #else
70 + #set ($hiddenCategories = [])
71 + #end
59 59   #set ($macroList = [])
73 + #set ($installedMacros = [])
60 60   #foreach ($macroDescriptor in $macroDescriptors)
75 + #set ($discard = $installedMacros.add($macroDescriptor.id.id))
76 +
61 61   #set ($macroTranslationKey = "rendering.macro.$macroDescriptor.id")
62 - #set ($macroCategoryTranslationKey = "rendering.macroCategory.$macroDescriptor.defaultCategory")
63 - #set ($discard = $macroList.add({
64 - 'id': $macroDescriptor.id,
65 - 'name': "#maybeTranslate(""${macroTranslationKey}.name"" $macroDescriptor.name)",
66 - 'description': "#maybeTranslate(""${macroTranslationKey}.description"" $macroDescriptor.description)",
67 - 'defaultCategory': "#maybeTranslate($macroCategoryTranslationKey $macroDescriptor.defaultCategory)"
68 - }))
78 + #set ($categories = [])
79 + #set ($hidden = false)
80 + #foreach ($category in $services.rendering.getMacroCategories($macroDescriptor.id))
81 + #set ($macroCategoryTranslationKey = "rendering.macroCategory.$category")
82 + #set ($hidden = $hidden || $hiddenCategories.contains($category))
83 + #set ($discard = $categories.add({
84 + 'id': $category,
85 + 'label': "#maybeTranslate($macroCategoryTranslationKey $category)"
86 + }))
87 + #end
88 +
89 + #if (!$hidden)
90 + #set ($defaultCategoryTranslation = "rendering.macroCategory.${macroDescriptor.defaultCategory}")
91 + #set ($discard = $macroList.add({
92 + 'id': $macroDescriptor.id,
93 + 'name': "#maybeTranslate(""${macroTranslationKey}.name"" $macroDescriptor.name)",
94 + 'description': "#maybeTranslate(""${macroTranslationKey}.description"" $macroDescriptor.description)",
95 + 'defaultCategory': "#maybeTranslate($defaultCategoryTranslation $macroDescriptor.defaultCategory)",
96 + 'categories': $categories
97 + }))
98 + #end
69 69   #end
70 - #set ($macroList = $resolvedSortTool.sort($macroList, 'name'))
100 + #set ($macroList = $collectiontool.sort($macroList, 'name'))
71 71   #set ($discard = $data.put('list', $macroList))
72 72   ## Get macros provided by compatible available extensions
73 73   #set ($macroExtensionsList = [])
... ... @@ -84,11 +84,13 @@
84 84   #set ($macroExtensionsMap = {})
85 85   #foreach ($extension in $extensions)
86 86   ## TODO: move to a proper generic API to check if an extension can be installed by a given user
87 - #if ($services.security.authorization.hasAccess('programming')
117 + #set ($extensionInstallAllowed = $services.security.authorization.hasAccess('programming', $xcontext.userReference, $NULL)
88 88   || (($extension.type == 'xar' || $extension.type == 'webjar')
89 - && $services.security.authorization.hasAccess('admin', "wiki:$xcontext.database") && $services.extension.isAllowed($extension, "wiki:$xcontext.database")))
90 - #foreach ($extensionComponent in $extension.getComponents())
91 - #if ($extensionComponent.roleType == 'org.xwiki.rendering.macro.Macro')
119 + && $services.security.authorization.hasAccess('admin', $xcontext.userReference, "wiki:$xcontext.database") && $services.extension.isAllowed($extension, "wiki:$xcontext.database")))
120 + #foreach ($extensionComponent in $extension.getComponents())
121 + #if ($extensionComponent.roleType == 'org.xwiki.rendering.macro.Macro')
122 + ## Skip macros identifiers for which a macro is already installed
123 + #if (!$installedMacros.contains($extensionComponent.roleHint))
92 92   #set ($discard = $macroExtensionsList.add({
93 93   'id' : {
94 94   'id' : $extensionComponent.roleHint
... ... @@ -96,12 +96,17 @@
96 96   'name': $extensionComponent.roleHint,
97 97   'description': $extension.summary,
98 98   'defaultCategory': '_notinstalled',
131 + 'categories': [{
132 + 'id' :'_notinstalled',
133 + 'label': $services.localization.render('macroSelector.filter.category.notinstalled')
134 + }],
99 99   'extensionId' : $extension.id.id,
100 100   'extensionVersion' : $extension.id.version.value,
101 101   'extensionType' : $extension.type,
102 102   'extensionRecommended': $extension.recommended,
103 103   'extensionName': $extension.name,
104 - 'extensionSummary': $extension.summary
140 + 'extensionSummary': $extension.summary,
141 + 'extensionInstallAllowed': $extensionInstallAllowed
105 105   }))
106 106   #end
107 107   #end
... ... @@ -112,236 +112,18 @@
112 112  #end
113 113  
114 114  #macro (maybeGetMacroDescriptor $macroIdAsString)
115 - #set ($xmacro = $NULL)
116 - #set ($macroDescriptor = $NULL)
117 - #set ($macroId = $services.rendering.resolveMacroId($macroIdAsString))
118 - #if ($macroId)
119 - #set ($macroDescriptor = $services.rendering.getMacroDescriptor($macroId))
120 - #if (!$macroDescriptor && $macroId.syntax)
121 - ## Try the macro id without the syntax.
122 - #set ($macroId = $services.rendering.resolveMacroId($macroId.id))
123 - #set ($macroDescriptor = $services.rendering.getMacroDescriptor($macroId))
124 - #end
125 - #else
126 - ## Either the macro id could not be resolved (unlikely) or we are on an older XWiki instance (before 10.10RC1) where
127 - ## we had to use APIs that require programming rights.
128 - #getMacroWithPR($macroIdAsString)
129 - #if ($xmacro)
130 - #set ($macroDescriptor = $xmacro.descriptor)
131 - #end
132 - #end
152 + #template('display_macros.vm')
153 + #initRequiredSkinExtensions()
154 + #set ($macroDescriptor = $services.wysiwyg.getMacroDescriptorUI($macroIdAsString))
133 133   #if ($macroDescriptor)
134 - #getMacroDescriptor($macroDescriptor)
135 - #if ($xmacro)
136 - ## supportsInlineMode was not exposed on the macro descriptor before XWiki 10.10RC1.
137 - #set ($data.supportsInlineMode = $xmacro.supportsInlineMode())
138 - #end
139 - #end
140 -#end
141 -
142 -#macro (getMacroWithPR $macroIdAsString)
143 - #set ($xmacro = $NULL)
144 - #try()
145 - #set ($macroIdFactory = $services.component.getInstance('org.xwiki.rendering.macro.MacroIdFactory'))
146 - #set ($macroId = $macroIdFactory.createMacroId($macroIdAsString))
147 - #set ($macroManager = $services.component.getInstance('org.xwiki.rendering.macro.MacroManager'))
148 - #if ($macroManager.exists($macroId))
149 - #set ($xmacro = $macroManager.getMacro($macroId))
150 - #elseif ($macroId.syntax)
151 - ## Try the macro id without the syntax.
152 - #set ($macroId = $macroIdFactory.createMacroId($macroId.id))
153 - #if ($macroManager.exists($macroId))
154 - #set ($xmacro = $macroManager.getMacro($macroId))
155 - #end
156 - #end
157 - #end
158 -#end
159 -
160 -#macro (getMacroDescriptor $macroDescriptor)
161 - ## Translate the macro name and description.
162 - #set ($macroTranslationKey = "rendering.macro.$macroDescriptor.id")
163 - #ckeditor_initRequiredSkinExtensions()
164 - #set ($data = {
165 - 'id': $macroDescriptor.id,
166 - 'name': "#maybeTranslate(""${macroTranslationKey}.name"" $macroDescriptor.name)",
167 - 'description': "#maybeTranslate(""${macroTranslationKey}.description"" $macroDescriptor.description)",
168 - 'defaultCategory': $macroDescriptor.defaultCategory,
169 - 'supportsInlineMode': $macroDescriptor.supportsInlineMode(),
170 - 'parameterDescriptorMap': {}
171 - })
172 - #if ($macroDescriptor.contentDescriptor)
173 - ## Translate the content label and description.
174 - ## Treat the macro content as if it is the last macro parameter.
175 - #set ($data.contentDescriptor = {
176 - 'name': "#maybeTranslate('rendering.macroContent' 'Content')",
177 - 'description': "#maybeTranslate(""${macroTranslationKey}.content.description""
178 - $macroDescriptor.contentDescriptor.description)",
179 - 'mandatory': $macroDescriptor.contentDescriptor.mandatory,
180 - 'deprecated': $macroDescriptor.contentDescriptor.deprecated,
181 - 'advanced': $macroDescriptor.contentDescriptor.advanced,
182 - 'defaultValue': $macroDescriptor.contentDescriptor.defaultValue,
183 - 'type': $macroDescriptor.contentDescriptor.type,
184 - 'editTemplate': '<textarea name="$content" rows="7"></textarea>',
185 - 'index': $macroDescriptor.parameterDescriptorMap.size()
156 + #getRequiredSkinExtensions($requiredSkinExtensions)
157 + #set ($data = {
158 + 'descriptor': $macroDescriptor,
159 + 'requiredSkinExtensions': $requiredSkinExtensions
186 186   })
187 - #fixDescriptorType($data.contentDescriptor)
188 188   #end
189 - #set ($groupDescriptorTree = {})
190 - #foreach ($entry in $macroDescriptor.parameterDescriptorMap.entrySet())
191 - #set ($parameterDescriptor = $entry.value)
192 - ## Translate the parameter name and description.
193 - #set ($parameterTranslationKey = "${macroTranslationKey}.parameter.$parameterDescriptor.id")
194 - ## Note: The displayHidden parameter is new in XWiki 12.4RC1 so make sure we set 'hidden' to false if it doesn't
195 - ## exist
196 - #if ("$!parameterDescriptor.displayHidden" != '')
197 - #set ($parameterHidden = $parameterDescriptor.displayHidden)
198 - #else
199 - #set ($parameterHidden = false)
200 - #end
201 - #set ($translatedParameterDescriptor = {
202 - 'id': $parameterDescriptor.id,
203 - 'name': "#maybeTranslate(""${parameterTranslationKey}.name"" $parameterDescriptor.name)",
204 - 'description': "#maybeTranslate(""${parameterTranslationKey}.description"" $parameterDescriptor.description)",
205 - 'mandatory': $parameterDescriptor.mandatory,
206 - 'deprecated': $parameterDescriptor.deprecated,
207 - 'advanced': $parameterDescriptor.advanced,
208 - 'defaultValue': $parameterDescriptor.defaultValue,
209 - 'type': $parameterDescriptor.displayType,
210 - 'hidden' : $parameterHidden,
211 - 'index': $foreach.index
212 - })
213 - #if ("$!translatedParameterDescriptor.type" == '')
214 - ## displayType is not available before XWiki 11.0 so we need to fall back on parameterType.
215 - #set ($translatedParameterDescriptor.type = $parameterDescriptor.parameterType)
216 - #end
217 - #set ($translatedParameterDescriptor.caseInsensitive = $translatedParameterDescriptor.type.isEnum())
218 - #set ($groupDescriptor = $parameterDescriptor.groupDescriptor)
219 - #if ($groupDescriptor)
220 - #handleMacroParameterGroup($groupDescriptor $groupDescriptorTree $translatedParameterDescriptor)
221 - #end
222 - #if ($translatedParameterDescriptor.type.getName() == 'java.lang.String'
223 - && ($parameterDescriptor.defaultValue == 'false' || $parameterDescriptor.defaultValue == 'true')
224 - && $macroDescriptor.parametersBeanClass.getSimpleName() == 'WikiMacroParameters')
225 - #set ($translatedParameterDescriptor.defaultValue = $parameterDescriptor.defaultValue == 'true')
226 - #set ($translatedParameterDescriptor.type = $translatedParameterDescriptor.defaultValue.getClass())
227 - #end
228 - #set ($htmlDisplayerParameters = {'name': $parameterDescriptor.id})
229 - #if ($translatedParameterDescriptor.group)
230 - #set ($discard = $htmlDisplayerParameters.put('data-property-group',
231 - $stringtool.join($translatedParameterDescriptor.group, '/')))
232 - #end
233 - #set ($translatedParameterDescriptor.editTemplate = $services.display.html.display(
234 - $translatedParameterDescriptor.type, $translatedParameterDescriptor.defaultValue, $htmlDisplayerParameters, 'edit'
235 - ))
236 - #if ("$!translatedParameterDescriptor.editTemplate" == '')
237 - #set ($translatedParameterDescriptor.editTemplate = "#getMacroParameterEditTemplate(
238 - $translatedParameterDescriptor)")
239 - #end
240 - #set ($translatedParameterDescriptor.editTemplate = $translatedParameterDescriptor.editTemplate.trim())
241 - #fixDescriptorType($translatedParameterDescriptor)
242 - ## Make sure the key is lowercase (for XWiki <9.0).
243 - ## See XWIKI-13990: Inconsistency between Java-based and Wiki-based rendering macros regarding the parameter
244 - ## descriptor map keys
245 - #set ($discard = $data.parameterDescriptorMap.put($entry.key.toLowerCase(), $translatedParameterDescriptor))
246 - #end
247 - #if ($groupDescriptorTree.groups)
248 - #set ($data.groupDescriptorTree = $groupDescriptorTree.groups)
249 - #end
250 - #set ($data.requiredSkinExtensions = "#ckeditor_getRequiredSkinExtensions()")
251 251  #end
252 252  
253 -#macro (fixDescriptorType $descriptor)
254 - ## The goal of this code is to obtain a normalized string representation of the type specified in the descriptor.
255 - ## See XCOMMONS-1583: Define a stable way to serialize types
256 - ##
257 - ## The type specified in the descriptor can be any implementation of java.lang.reflect.Type, not necessarily a
258 - ## java.lang.Class. We can't use toString() because the return of Class#toString() is different than Class#getName().
259 - ## We can't use Type#getTypeName() either because the access to this method is restricted from Velocity. The only
260 - ## option for now is to try #getName() first and fall back on #toString() for types that are not instances of
261 - ## java.lang.Class.
262 - #set ($typeName = $descriptor.type.getName())
263 - #if ("$!typeName" == '')
264 - ## Probably not a java.lang.Class. Fall back on #toString().
265 - #set ($typeName = "$!descriptor.type")
266 - #end
267 - ## Remove whitespace from the type name in order to have a single string representation.
268 - #set ($descriptor.type = $typeName.replaceAll('\s+', ''))
269 -#end
270 -
271 -## Builds the group tree with the following structure:
272 -##
273 -## {
274 -## 'parentGroupId': {
275 -## 'id': 'parentGroupId',
276 -## 'name': 'Parent Group',
277 -## 'feature': 'someFeature',
278 -## 'groups': {
279 -## 'childGroupId': {...},
280 -## ...
281 -## }
282 -## },
283 -## ...
284 -## }
285 -#macro (handleMacroParameterGroup $groupDescriptor $groupDescriptorTree $translatedParameterDescriptor)
286 - #if ($groupDescriptor.group && $groupDescriptor.group.size() > 0)
287 - #set ($translatedParameterDescriptor.group = $groupDescriptor.group)
288 - #set ($parentGroup = $groupDescriptorTree)
289 - #foreach ($groupId in $groupDescriptor.group)
290 - #if (!$parentGroup.groups)
291 - #set ($parentGroup.groups = {})
292 - #end
293 - #set ($childGroup = $parentGroup.groups.get($groupId))
294 - #if (!$childGroup)
295 - #if ($groupId == $translatedParameterDescriptor.id)
296 - #set ($groupName = $translatedParameterDescriptor.name)
297 - #else
298 - #set ($groupTranslationKey = "${macroTranslationKey}.group.$groupId")
299 - #set ($groupName = "#maybeTranslate(""${groupTranslationKey}.name"" $groupId)")
300 - #end
301 - #set ($childGroup = {
302 - 'id': $groupId,
303 - 'name': $groupName
304 - })
305 - #set ($discard = $parentGroup.groups.put($groupId, $childGroup))
306 - #end
307 - #set ($parentGroup = $childGroup)
308 - #end
309 - #if ("$!groupDescriptor.feature" != '')
310 - #set ($parentGroup.feature = $groupDescriptor.feature)
311 - #end
312 - #elseif ($groupDescriptor.feature)
313 - ## This group is made of a single parameter. The feature then refers to this parameter.
314 - #set ($translatedParameterDescriptor.feature = $groupDescriptor.feature)
315 - #end
316 -#end
317 -
318 -#macro (getMacroParameterEditTemplate $translatedParameterDescriptor)
319 - #if ($translatedParameterDescriptor.type.getName() == 'boolean'
320 - || $translatedParameterDescriptor.type.getName() == 'java.lang.Boolean')
321 - <input type="checkbox" name="$escapetool.xml($translatedParameterDescriptor.id)" value="true"/>##
322 - ## We need to submit something in case the checkbox is not checked.
323 - <input type="hidden" name="$escapetool.xml($translatedParameterDescriptor.id)" value="false"/>
324 - #elseif ($translatedParameterDescriptor.type.isEnum())
325 - #if ($translatedParameterDescriptor.defaultValue)
326 - #set ($enumValues = $translatedParameterDescriptor.defaultValue.values())
327 - #else
328 - ## A parameter of type enum that doesn't have a default value is very unlikely. We attempt to read the list of
329 - ## possible values from the enum type in this case, which is currently forbidden, but at least it will generate
330 - ## a warning in the logs that will help us investigate the problem.
331 - #set ($enumValues = $translatedParameterDescriptor.type.getEnumConstants())
332 - #end
333 - <select name="$escapetool.xml($translatedParameterDescriptor.id)">##
334 - #foreach ($enumValue in $enumValues)
335 - #set ($value = $enumValue.name())
336 - #set ($label = "#maybeTranslate(""${parameterTranslationKey}.value.$value"" $enumValue)")
337 - <option value="$escapetool.xml($value)">$escapetool.xml($label)</option>##
338 - #end
339 - </select>
340 - #else
341 - <input type="text" name="$escapetool.xml($translatedParameterDescriptor.id)"/>
342 - #end
343 -#end
344 -
345 345  #macro (maybeTranslate $key $defaultValue)
346 346   #if ($services.localization.get($key))
347 347   $services.localization.render($key)##
... ... @@ -391,9 +391,19 @@
391 391   $response.sendError(404, $exceptiontool.getRootCauseMessage($job.status.error))
392 392   #end
393 393  #end
394 -{{/velocity}}
395 395  
396 -{{velocity wiki="false"}}
214 +#macro (getMacroParameters $macroId $macroParameters)
215 + #set ($macroId = $services.rendering.resolveMacroId($macroId))
216 + #set ($macroParameters = $jsontool.fromString($macroParameters))
217 + #foreach($macroParameter in $macroParameters.entrySet())
218 + ## TODO: Do we need to take into account the macro parameter type? We could have a macro parameter that is editable
219 + ## inline but whose value is not a List<Block> but rather a String (plain text).
220 + #set ($macroParameter.value = $services.wysiwyg.fromAnnotatedXHTML($macroParameter.value, $macroId.syntax))
221 + #end
222 + #set ($data = $macroParameters)
223 +#end
224 +
225 +#set ($data = $NULL)
397 397  #if ("$!request.action" == 'install')
398 398   #if ($services.csrf.isTokenValid($request.form_token))
399 399   #installMacroExtension($request.extensionId, $request.extensionVersion)
... ... @@ -400,18 +400,18 @@
400 400   #else
401 401   $response.sendError(403)
402 402   #end
403 -#elseif ("$!request.data" != '')
404 - #set ($data = $NULL)
405 - #if ($request.data == 'list')
406 - #getMacroList($request.syntaxId)
407 - #elseif ($request.data == 'descriptor')
408 - #maybeGetMacroDescriptor($request.macroId)
409 - #end
410 - #if ($data)
411 - #set ($discard = $response.setContentType('application/json'))
412 - $jsontool.serialize($data)
413 - #else
414 - $response.sendError(404)
415 - #end
232 +#elseif ($request.data == 'list')
233 + #getMacroList($request.syntaxId)
234 +#elseif ($request.data == 'descriptor')
235 + #maybeGetMacroDescriptor($request.macroId)
236 +#elseif ($request.data == 'macroParameters')
237 + #getMacroParameters($request.macroId, $request.macroParameters)
416 416  #end
239 +#if ($response.isCommitted())
240 + ## Do nothing.
241 +#elseif ($data)
242 + #jsonResponse($data)
243 +#elseif ("$!request.action" != '' || "$!request.data" != '')
244 + $response.sendError(404)
245 +#end
417 417  {{/velocity}}