Modifications pour le document MacroService

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

Depuis 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]
À la version 2.1
modifié par Florent Charton
sur 2022/06/28 18:01
Commentaire de modification : Install extension [org.xwiki.contrib:application-ckeditor-ui/1.64.2]

Résumé

Détails

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