Example scripts
To homepage
Confluence

Automate the Creation of Complex Page Structures within Confluence
Created 1 year ago, Updated 2 month(s) ago
App in script

ScriptRunner For Confluence
by Adaptavist
Compatibility

Confluence (7.15 - 8.6)

ScriptRunner For Confluence (7.10.0)
Language |
groovy
import com.atlassian.confluence.content.service.PageService
import com.atlassian.confluence.core.BodyContent
import com.atlassian.confluence.core.BodyType
import com.atlassian.confluence.core.DefaultSaveContext
import com.atlassian.confluence.pages.DuplicateDataRuntimeException
import com.atlassian.confluence.pages.Page
import com.atlassian.confluence.pages.PageManager
import com.atlassian.confluence.pages.templates.PageTemplateManager
import com.atlassian.confluence.security.Permission
import com.atlassian.confluence.security.PermissionManager
import com.atlassian.confluence.spaces.Space
import com.atlassian.confluence.spaces.SpaceManager
import com.atlassian.confluence.user.AuthenticatedUserThreadLocal
import com.atlassian.sal.api.component.ComponentLocator
import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import groovy.json.JsonOutput
import groovy.transform.BaseScript
import groovy.transform.Field
import org.apache.log4j.Logger
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response
@Field SpaceManager spaceManager = ComponentLocator.getComponent(SpaceManager)
@Field PageManager pageManager = ComponentLocator.getComponent(PageManager)
@Field PermissionManager permissionManager = ComponentLocator.getComponent(PermissionManager)
@Field PageTemplateManager pageTemplateManager = ComponentLocator.getComponent(PageTemplateManager)
@Field Logger log = Logger.getLogger("com.onresolve.scriptrunner.runner.ScriptRunnerImpl")
@Field PageService pageService = ComponentLocator.getComponent(PageService)
// The specified setup - Specify the page titles and hierarchy here
// This example setup contains one page with 2 child pages
// The template value takes the id of the template you want to use
def spec = [
[
title : "Planning",
templateName : "template1",
templateSpaceKey: "PS",
page : [
[
title : "Review",
templateName : "template2",
templateSpaceKey: "global-template"
],
[
title : "Social",
templateName : "template1",
templateSpaceKey: "PS"
]
]
]
]
@BaseScript CustomEndpointDelegate delegate
createProjectPages(httpMethod: "GET", groups: ["confluence-administrators", "confluence-users"]) { MultivaluedMap queryParams, String body ->
// This is the space key specified in the custom script fragment
def spaceKey = queryParams.getFirst("spaceKey") as String
// This is the parent page id specified in the custom script fragment
// The first page created in this script will use the page associated with the parent page id as its parent
def parentPageId = queryParams.getFirst("parentPageId") as Long
def mainPageTitle = spec.get(0).get("title")
// Flag shown to user on successful or failed creation of new project structure pages
def flag = [
type : 'success',
title: "Pages created",
close: 'auto',
body : "Refresh this page to see the newly created page (${mainPageTitle}) and its children in the page tree"
]
try {
createPages(spaceKey, parentPageId, spec)
} catch (IllegalStateException | DuplicateDataRuntimeException e) {
log.error("There was a problem trying to create the project structure", e)
flag = [
type : 'failure',
title: "An error occurred",
close: 'manual',
body : "There was an error trying to create project structure pages"
]
}
Response.ok(JsonOutput.toJson(flag)).build()
}
/**
* Create the desired page structure
*
* @param spaceKey The Key of the space to add pages for.
* @param parentPageId The page id of the parent page.
* @param spec The specification for the pages to be created.
*/
void createPages(String spaceKey, Long parentPageId, List spec) throws IllegalStateException, Exception {
def space = spaceManager.getSpace(spaceKey) as Space
def parentPageLocator = pageService.getIdPageLocator(parentPageId)
def parentPage = parentPageLocator?.getPage() ?: spaceManager.getSpace(spaceKey).homePage
if (!parentPage) {
throw new IllegalStateException("The specified parent page for new project structure pages does not exist")
}
if (!userHasPageViewPermission(parentPage)) {
throw new IllegalStateException("User does not have the required permission to create child pages on page with id ${parentPage.id}")
}
spec.each { pageSpec ->
createPage(parentPage, space, pageSpec as Map)
}
}
/**
* Check if the user clicking the fragment button has the relevant permission to create child pages.
* @param parentPage
* @return user permission view status
*/
boolean userHasPageViewPermission(Page parentPage) {
def user = AuthenticatedUserThreadLocal.get()
permissionManager.hasPermission(user, Permission.VIEW, parentPage)
}
/**
* Create a page using the given page specification (pageSpec). This spec dictates the title of the page, the template
* to be used to populate it (if any) and if required, the specification of any child pages.
*
* @param parentPage The parent page for the page we're about to create.
* @param space The space that the page should be created in.
* @param pageSpec The specification for the pages to be created.
*/
void createPage(Page parentPage, Space space, Map pageSpec) throws IllegalStateException {
def testPageTitle = pageSpec.title as String
def templateName = pageSpec.templateName as String
def templateSpaceKey = pageSpec.templateSpaceKey as String
def content = getTemplateContent(templateName, templateSpaceKey)
def createdPage = createBasicPage(space, testPageTitle, content)
parentPage.addChild(createdPage)
// Save this page
pageManager.saveContentEntity(createdPage, DefaultSaveContext.SUPPRESS_NOTIFICATIONS)
def createdPageLocator = pageService.getIdPageLocator(createdPage.id)
if (createdPageLocator.getPage()) {
log.debug("Created page ${testPageTitle} successfully")
} else {
throw new IllegalStateException("Unable to create page ${testPageTitle}")
}
// Build the children
if (pageSpec.page) {
pageSpec.page.each { childPageSpec ->
createPage(createdPage, space, childPageSpec as Map)
}
}
}
/**
* Get the content from the template to populate the page with.
*
* @param templateName The name of the template we wish to use.
* @param templateSpace The space associated with the template we wish to use.
* @return The template body content.
*/
String getTemplateContent(String templateName, String templateSpaceKey) {
def pageTemplate = templateSpaceKey == "global-template" ?
pageTemplateManager.getGlobalPageTemplate(templateName) :
pageTemplateManager.getPageTemplate(templateName, spaceManager.getSpace(templateSpaceKey))
if (!pageTemplate) {
throw new IllegalStateException("Unable to retrieve specified template")
}
pageTemplate.content
}
/**
* Create a basic page. This is not linked in any hierarchy.
*
* @param space The space that this page belongs to.
* @param title The title of the page we are creating.
* @param content The content of the page we are creating.
*
* @return The create page object.
*/
Page createBasicPage(Space space, String title, String content) {
def page = new Page()
def bodyContent = new BodyContent(page, content, BodyType.XHTML)
page.with {
setVersion(1)
setSpace(space)
setTitle(title)
setBodyContent(bodyContent)
setCreator(AuthenticatedUserThreadLocal.get())
}
page
}
Having an issue with this script?
Report it here