Limit a Page Type or Area to certain Block Types

Permalink
I am looking for a Way to control what Block Types that are available to insert in a certain Page Type or Area.

A practical Example:
I have a PageType called "newsletter" that i use to let the user Create HTML Content. This Content will be processed by my Package and later sent by E-Mail.
Since there are quite a few Block Types that rely on Javascript or for other reasons wouldn't render right in a E-Mail Client i want to prevent the User from inserting them in the first place.

I've looked through the API and Permission System but couldn't find a way to achieve that.
Does anyone have an Idea on how i can get this done?

I wouldn't mind doing it programmatically and hardcode the Block Type Handles i want to disallow. My Page Type already has a custom controller and template with some stuff that's unrelated to this requirement.

haeflimi
 
hutman replied on at Permalink Reply
hutman
If advanced permissions are enabled you can limit block types to an area by clicking on an area in edit mode and then click on permissions. This will not limit the area for the Super User (admin) but it will for the other registered users of the site.
haeflimi replied on at Permalink Reply
haeflimi
Thanks for the quick reply!
This is basically what i want. I had suspected it would work somehow with advanced permissions. I woudn't know because of the "no advanced permissions" policy we follow for our projects.

Is there i way to set this programmatically from the page type controller or in my package installation?

Since this will be part of a package i want it to work "out of the box" without having to explain to the User: "you have to enable advanced permissions and alter the permission like this and that."
MrKDilkington replied on at Permalink Reply
MrKDilkington
I would also be interested in how to set available blocks per area, or by page type, programmatically.
stinchjack replied on at Permalink Best Answer Reply
Here's a partial solution working in version 8.3.2.

Add an area in the template normally, setting the block limit:

$a = new Area('Banner Header');
$a->setAreaDisplayName('Banner Header');
$a->setBlockLimit(1);
$a->display($c);


Add a controller, in my case packages/mytheme/controllers/page_types/home.php.

In the controller, use the view method add a block of your choice to the area if there isn't one already:

<?php
namespace Concrete\Package\Mytheme\Controller\PageType;
use Concrete\Core\Block\BlockType\BlockType;
use Concrete\Core\Page\Controller\PageTypeController;
use PageType;
use Page;
use Concrete\Core\Area\Area;
class Home extends PageTypeController
{
    public function on_start() {
      $this->page = \Page::getCurrentPage();
      $this->pageType = PageType::getByID($this->page->getPageTypeID());
    }
    public function view()
    {



This puts a default block (in this case a Content block) in the target area when there are
no other blocks in the area. in edit mode, only the one block is allowed in the area. But! ... if the block is deleted in Edit mode, then a block of the user's choice can still be added.


For reference, see also https://documentation.concrete5.org/tutorials/concrete5-7-add-pageli...
haeflimi replied on at Permalink Reply
haeflimi
By the way for anyone that's interested. I've found another, somewhat hacky method to get what i wanted:

I include a snippet of JavaScript to catch the "PanelOpen" Event and manipulate the DOM in order to hide the undesired block types like this:

(function($)
    {
    window.ConcreteEvent.bind('PanelOpen', function (e, data) {
        $('.ccm-panel-add-block-draggable-block-type').parent().hide();
        $('.ccm-panel-add-block-draggable-block-type[data-block-type-handle="content"]').parent().show();
        $('.ccm-panel-add-block-draggable-block-type[data-block-type-handle="html"]').parent().show();
        $('.ccm-panel-add-block-draggable-block-type[data-block-type-handle="image"]').parent().show();
        $('.ccm-panel-add-block-draggable-block-type[data-block-type-handle="file"]').parent().show();
        $('.ccm-panel-add-block-draggable-block-type[data-block-type-handle="horizontal_rule"]').parent().show();
        $('.ccm-panel-add-block-draggable-block-type[data-block-type-handle="page_title"]').parent().show();
        $('.ccm-panel-add-block-draggable-block-type[data-block-type-handle="page_list"]').parent().show();
        $('.ccm-panel-add-block-draggable-block-type[data-block-type-handle="mesch_filter_list"]').parent().show();
        $('.ccm-panel-add-block-draggable-block-type[data-block-type-handle="mesch_newsletter_button"]').parent().show();
        $('.ccm-panel-add-block-draggable-block-type[data-block-type-handle="mesch_spacer"]').parent().show();
    });
Ottokarl replied on at Permalink Reply
I don't prevent, but instead if block is on the wrong page, i tell the user.

my view.php looks like this
if ( $c->getCollectionTypeHandle() <> 'my_pagetype_handle' ) {
    echo '<div><p>This block is useful only for pages of type <strong>MyPagetype</strong></p></div>';
} else {
    ... do the normal view stuff .... 
}