Your starting base: play-cms-demo

To bootstrap your project, you should use the play-cms-demo as your starting point. Once it's up and running, continue with the steps below.

 

Setup and initialize the cms

To setup the cms programatically (wire up your own provider classes), you implement the ch.insign.cms.CMSApiLifecycle interface or override the ch.insign.cms.CMSApiLifecycleImpl class to change runtime settings, and implement the ch.insign.cms.models.Bootstrapper interface or override the ch.insign.cms.models.DefaultBootstrapper class to change the initial database content.

Main setup options 

Registering Blocks

play-cms allows to change set of enabled blocks without modifying code. To do so you need to update application.conf of your play-cms instance and modify following settings

cms.blocks.enabled
cms.blocks.disabled

Both these settings accepts array of fully qualified block class names. By default following blocks are enabled:

ch.insign.cms.models.PageBlock
ch.insign.cms.models.ContentBlock
ch.insign.cms.models.CollectionBlock
ch.insign.cms.blocks.linkblock.LinkBlock
ch.insign.cms.blocks.backendlinkblock.BackendLinkBlock
ch.insign.cms.blocks.groupingblock.GroupingBlock
ch.insign.cms.blocks.sliderblock.SliderCollectionBlock
ch.insign.cms.blocks.searchresultblock.SearchResultBlock
ch.insign.cms.blocks.jotformpageblock.JotFormPageBlock
ch.insign.cms.blocks.errorblock.ErrorPage

Adding additional entries to the list of enabled blocks looks like following:

// Enable ReviewBlock
cms.blocks.enabled += "ch.insign.cms.blocks.reviewblock.models.ReviewBlock"

Similarly, disabling of any block might be done like this:

// Disable JotForms
cms.blocks.disabled += "ch.insign.cms.blocks.jotformpageblock.JotFormPageBlock"

Sometimes there might be situations when block availability should be controlled at runtime. For such cases play-cms provides BlockManager class. It allows to enable blocks by calling BlockManager#register() method. Here is an example of usage:

 

public void registerNewyearWidgetBlock() {
    LocalDate currentDate = LocalDate.now();

    if (currentDate.isAfter(LocalDate.of(currentDate.getYear(), 12, 1))
            && currentDate.isBefore(LocalDate.of(currentDate.getYear(), 12, 31))) {
        blockManager.register(NewYearWidgetBlock.class);
   }
}

Create your own error pages
Error pages are treated as normal cms pages. Create and return them initially form code - the admins can then modify them using the cms.

Add example data
This helps greatly during development of your project: Create some demo pages and content using your own blocks and design, and matching the final project's desired content. During development, you can then easily reset the db (call yourdomain.ext/reset) and will find your example content again.

Add your own content filters
Content filters are a great tool to let the user add e.g. variables freely inside any content, e.g. [[currentUserCount]] which your filter resolves to the current value when displaying the page.

CMSApiLifecycle example

app/MyCMSApiLifecycle.java:

@Singleton
public class MyCMSApiLifecycle extends CMSApiLifecycleImpl {
    private final MyAuthenticationListener myAuthenticationListener;
    private final PlayAuthApi playAuthApi;

    @Inject
    public MyCMSApiLifecycle(
            JPAApi jpaApi,
            ActorSystem actorSystem,
            PlayAuthApi playAuthApi,
            MyAuthenticationListener myAuthenticationListener
    ) {
        super(jpaApi, actorSystem);
        this.myAuthenticationListener = myAuthenticationListener;
        this.playAuthApi = playAuthApi;
    }

    @Override
    public void onStart(CMSApi cmsApi) {
        super.onStart(cmsApi);

        // set your own authentication listener
        playAuthApi.getEventDispatcher().addSubscriber(loggingAuthenticationListener);

        // change other settings here...
    }

    @Override
    protected void registerContentFilters(CMSApi cmsApi) {
        // Add your own content filters.
        super.registerContentFilters(cmsApi);
        cmsApi.getFilterManager().register(
            MyEmoticonContentFilter.class
        );
    }
}

 

Bootstrapper example

app/MyCMSBootstrapper.java:

@Singleton
public class MyCMSBootstrapper extends DefaultBootstrapper implements Bootstrapper {

    private PartyManager pm;
    private PartyRoleManager prm;
    private JPAApi jpaApi;

    @Inject
    public MyCMSBootstrapper(
            AccessControlManager accessControlManager,
             CMSApi cmsApi,
             PartyManager partyManager,
             PartyRoleManager partyRoleManager,
             JPAApi jpaApi
    ) {
        super(accessControlManager, cmsApi, partyRoleManager, jpaApi);
        this.pm = partyManager;
        this.prm = partyRoleManager;
        this.jpaApi = jpaApi;
    }

    /**
     * Load essential data which is required for all configured sites to function properly.
     *
     * Used to perform an initial project bootstrap or to reload it to the initial state.
     */
    @Override
    public synchronized void loadEssentialData() {
        super.loadEssentialData();
    }

    /**
     * Load example data for all configured sites.
     */
    @Override
    public synchronized void loadExampleData() {
        super.loadExampleData();
    }

    /* Override DefaultBootstrapper methods:
     *   The DefaultBootstrapper defines more fine grained methods
     *   which are called by DefaultBootstrapper.load*Data methods
     *   so it may be easier to override them if small changes required.
     */

    /**
     * Delete data created by loadEssentialData
     */
    @Override
    protected void deleteEssentialData() {
        super.deleteEssentialData();
    }

    /**
     * Delete data created by deleteExampleData
     */
    @Override
    protected void deleteExampleData() {
        super.deleteExampleData();
    }

    /**
     * Add navigation entries in the backend
     */
    @Override
    protected void createBackendNavigation() {
        super.createBackendNavigation();
    }

    @Override
    protected ErrorPage createErrorPageNotFound(Sites.Site site) {
        return super.createErrorPageNotFound(site);
    }

    @Override
    protected ErrorPage createErrorPageUnavailable(Sites.Site site) {
        return super.createErrorPageUnavailable(site);
    }

    @Override
    protected ErrorPage createErrorPageInternalServerError(Sites.Site site) {
        return super.createErrorPageInternalServerError(site);
    }

    @Override
    protected ErrorPage createErrorPageForbidden(Sites.Site site) {
        return super.createErrorPageForbidden(site);
    }

    @Override
    protected void createPartyRoles() {
        super.createPartyRoles();
        
        // add more user roles
    }

    @Override
    protected void createParties() {
        super.createParties();
        
        // add more users
    }
}

 

The CMSApiLifecycle and Bootstrapper implementations are configured as DI bindings in ch.insign.cms.inject.CmsApiModule and ch.insign.cms.inject.BootstrapperModule correspondingly, so they should also be overridden by implementing custom play.api.inject.Module, enabling them in the application.conf and also disabling the overridden modules, e.g.:

conf/application.conf

# Override CmsApiModule
play.modules.disabled += "ch.insign.cms.inject.CmsApiModule"
play.modules.enabled += "my.CmsApiModule"

# Override BootstrapperModule
play.modules.disabled += "ch.insign.cms.inject.BootstrapperModule"
play.modules.enabled += "my.BootstrapperModule"

 

Configuration


The cms uses configuration values defined in play-cms/conf/application.conf. You can override them in your global application.conf.

play-cms/conf/application.conf:
# play-cms default configuration
application.router=cms.Routes
 
# CMS config values.
# Always access these using Cms.getConfig().*
cms.deleteWithoutTrashBin = false
cms.enableResetRoute = false


From code, config values can be accessed using CMSApi#getConfig().*