Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

How can i find pages on which a macro is used, programmatically?

J D
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 16, 2014
 

8 answers

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

4 votes
Alex Medved _ConfiForms_
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 17, 2014

Some discussion could be found here: https://answers.atlassian.com/questions/11460827

But for API, look for:

  • Start with com.atlassian.confluence.search.v2.SearchManager, create a query (use MacroUsageQuery class to look for macro name), something like

    searchManager.search(new ContentSearch(new MacroUsageQuery("info"), null, null, 0, 100))
  • PluginAccessor class (com.atlassian.plugin.PluginAccessor)  to get plugins and macros installed
  • com.atlassian.confluence.xhtml.api.XhtmlContent to parse the page content for macros used

And you should be good smile

J D
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 17, 2014

Okay, thanks for you contribution. I will try that :)

2 votes
Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 17, 2014

Here is a user macro that I have created for this. Just put it on a page and it should give you a report of all of the macros and user macros that are being used in your instance. This requires at least Confluence 5.5 as the MacroBrowserManager.getMacroSummaries() method was added in 5.5.

## Developed by: Davin Studer
## Date created: 12/17/2014
## @noparams
 
#set($containerManagerClass = $content.class.forName('com.atlassian.spring.container.ContainerManager'))
#set($getInstanceMethod = $containerManagerClass.getDeclaredMethod('getInstance',null))
#set($containerManager = $getInstanceMethod.invoke(null,null))
#set($containerContext = $containerManager.containerContext)
#set($macroBrowserManager = $containerContext.getComponent('macroBrowserManager'))
#set($allMacros = $macroBrowserManager.getMacroSummaries())

#########################################################################################
## This is used for getting around velocity issues when writing jQuery.                ##
#########################################################################################
#set( $d = '$' )

#########################################################################################
## Populate the macro information into a string that we will use as a JS object array. ##
#########################################################################################
#set ($i = 0)
#set($macroObjects = "")
#foreach($macro in $allMacros)
  #if($i != 0)
    #set($macroObjects = $macroObjects + ",")
  #end
  #set($macroObjects = $macroObjects + "{title:'" + $macro.getTitle().getKey().replace("'","\'") + "', name:'" + $macro.getMacroName().replace("'","\'") + "'}")
#set ($i = $i + 1)
#end

<script type="text/javascript">
var queue = {
    macros: [$macroObjects],
    current: 0,
    start: function () {
        this.macros.sort(compare);
        this.current = 0;
        this.next();
    },
    next: function () {
		if (this.current >= this.macros.length) {
            AJS.$('#queryStatus span').removeClass('aui-lozenge-current');
            AJS.$('#queryStatus span').addClass('aui-lozenge-success');
            AJS.$('#queryStatus span').text('Report Complete');
            AJS.tablessortable.setTableSortable(AJS.$('#macroUsageReport table'));
            return null;
		}
		else {
			this.current += 1;
			lookupMacro(this.macros[this.current - 1]);
		}
    }
};

function lookupMacro(macro) {
    var html = '';
    var searchURL = '';
    
    AJS.$('#queryStatus span').text('Getting counts for macro: ' + macro.title);
    
    searchURL = '/rest/searchv3/1.0/search?where=conf_all&spaceSearch=true&queryString=macroName:' + encodeURIComponent(macro.name);
    AJS.${d}.ajax(
        {
            type: 'GET',
            url: searchURL,
            dataType: "json",
            success: function(data) {
                if(data.total > 0) {
                    html = '<tr>';
                    html += '   <td class="confluenceTd">' + macro.title + '</td>';
                    html += '   <td class="confluenceTd">' + macro.name + '</td>';
                    html += '   <td class="confluenceTd">' + data.total + '</td>';
                    html += '   <td class="confluenceTd"><a href="/dosearchsite.action?where=conf_all&spaceSearch=true&queryString=macroName:' + encodeURIComponent(macro.name) + '" target="_blank">macro usage</a></td>';
                    html += '</tr>';
                }
                AJS.$('#macroUsageReport table tbody').append(html);
                
                queue.next();
            },
            error: function (x, y, z) {
                AJS.$('#queryStatus span').removeClass('aui-lozenge-current');
                AJS.$('#queryStatus span').addClass('aui-lozenge-error');
                AJS.$('#queryStatus span').text('Error getting counts for macro:' + macro.title);
            }
        }
    );
}

function compare(a, b) {
    if (a.title < b.title) {
        return -1;
    }
    if (a.title > b.title) {
        return 1;
    }
    return 0;
}

AJS.toInit(function(){
    queue.start();    
});
</script>

<div id="queryStatus">
    <span class="status-macro aui-lozenge aui-lozenge-current"></span>
</div>
<div id="macroUsageReport">
    <table class="confluenceTable">
        <thead>
            <tr>
                <th>Macro Title</th>
                <th>Macro Name</th>
                <th>Times Used</th>
                <th>Pages Used On</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>
</div>
1 vote
Stephen Deutsch
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 17, 2014

If you are wanting to use the REST API to do so, you could use the searchv3/1.0/search method (https://bunjil.jira-dev.com/wiki/plugins/servlet/restbrowser#/resource/searchv3-1-0-search) and search as you would in the Confluence search bar: "macroName: xxxx".  That would be a lot faster than going through every page smile

J D
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 17, 2014

Looked at it and first thing see is that it isnt public. Its not even in the official docs (https://docs.atlassian.com/confluence/REST/latest/) Is it official supported?

0 votes
Stan Ry
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 13, 2019

.

0 votes
Stan Ry
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 13, 2019

.

0 votes
Stan Ry
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 13, 2019

.

0 votes
Stan Ry
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 13, 2019

Great thread. Could somebody please help to modify Davin's script for a much simpler case:

I'd like to find all pages in a specific space that use specific macros. I don't have access to admin console on the instance and would like to list pages for specific macro names like: "info", "ui-text-box".

How do I properly preconfigure the macroObjects array with a static set of macros that I want to check?

Would this be the proper notation for two macros?

var macroObjects = {
  'title'  : ['UI Text Box', 'Info'],
  'name': ['ui-text-box', 'info'],
};

As far as I understand, the correct request string to query results for a specific space will look as:

https://confluence.example.net/<confluence_instance>/rest/searchv3/1.0/search?where=<space_name>&spaceSearch=true&queryString=macroName:<macro_name>

For example, following should return pages that use Info macro

https:/confluence.example.net/wiki/rest/searchv3/1.0/search?where=~stanry&spaceSearch=true&queryString=macroName:info

Worked fine for a single macro. Could somebody please fix this so that it works for multiple macros defined in an array?

Thank you.

<script type="text/javascript"> /* Works fine for an array with single element */
var macroObjects = { 'title' : ['Info'], 'name' : ['info'], };

/* How to get it to work for multiple elements? So that both
'info' and 'ui-text-box' macros are handled and results are returned for both
var macroObjects = {
'title' : ['Info', 'UI Text'],
'name': ['info', 'ui-text-box']
} */

var queue = {
macros: [macroObjects],
current: 0,
start: function () {
this.macros.sort(compare);
this.current = 0;
this.next(); },
next: function () {
if (this.current >= this.macros.length) {
AJS.$('#queryStatus span').removeClass('aui-lozenge-current');
AJS.$('#queryStatus span').addClass('aui-lozenge-success');
AJS.$('#queryStatus span').text('Report Complete'); AJS.tablessortable.setTableSortable(AJS.$('#macroUsageReport table')); return null; } else { this.current += 1; console.log('Position','', + this.macros[this.current - 1]); lookupMacro(this.macros[this.current - 1]); } } }; function lookupMacro(macro) { var html = ''; var searchURL = ''; AJS.$('#queryStatus span').text('Getting counts for macro: ' + macro.title); searchURL = '/wiki/rest/searchv3/1.0/search?where=myspaceName&spaceSearch=true&queryString=macroName:' + encodeURIComponent(macro.name); AJS.$.ajax( { type: 'GET', url: searchURL, dataType: "json", success: function(data) { if(data.total > 0) { html = '<tr>'; html += ' <td class="confluenceTd">' + macro.title + '</td>'; html += ' <td class="confluenceTd">' + macro.name + '</td>'; html += ' <td class="confluenceTd">' + data.total + '</td>'; html += ' <td class="confluenceTd"><a href="/wiki/dosearchsite.action?where=myspaceName&spaceSearch=true&queryString=macroName:' + encodeURIComponent(macro.name) + '" target="_blank">Показать все страницы</a></td>'; html += '</tr>'; } AJS.$('#macroUsageReport table tbody').append(html); queue.next(); },
error: function (x, y, z) {
AJS.$('#queryStatus span').removeClass('aui-lozenge-current');
AJS.$('#queryStatus span').addClass('aui-lozenge-error');
AJS.$('#queryStatus span').text('Error getting counts for macro:' + macro.title); } } ); }

function compare(a, b) {
if (a.title < b.title) {
return -1;
}
if (a.title > b.title) {
return 1; }
return 0; }

AJS.toInit(function(){
queue.start();
}); </script>

<div id="queryStatus">
<span class="status-macro aui-lozenge aui-lozenge-current">
</span>
</div>

<div id="macroUsageReport">
<table class="confluenceTable">
<thead>
<tr>
<th>Name</th>
<th>Id</th>
<th>Used, times</th>
<th>On page</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>

 

I have described my case and the problem in this thread: How do I list pages that contain specific macros in a specific space

I'd appreciate if somebody could help me to modify the original script for this simpler case.

Thank you.

Stan

P.S. Haven't found an option to delete the other two leftover posts... 

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 13, 2019

For the sake of keeping this question easy to read please thread your replies under your original answer instead of adding answers for each update. Better yet you should open up your own question and reference this question from it as this really is a different question than the original post. Feel free to do that and I will reply on that question.

Stan Ry
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 14, 2019

@Davin Studer , first off, sorry to misspel your name, Davin. As for forking this thread, yes, makes sense.

0 votes
Adrian Moerchen
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 16, 2014
Pseudocode
for every page
   if content of page contains macro
       print id of page

Might be veeeeery slow depending on the number of pages wink

J D
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 16, 2014

Yep, it would be veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery slow. :D But it is a possible way. I will search for a better solution. If there is none, i accept your answer. Thanks

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

TAGS
AUG Leaders

Atlassian Community Events