Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for editing blocks via the CMS #36

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
46 changes: 44 additions & 2 deletions Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@

namespace Winter\Blocks;

use Backend\Classes\NavigationManager;
use Backend\Classes\WidgetManager;
use Backend\Facades\Backend;
use Backend\Models\UserRole;
use Cms\Classes\AutoDatasource;
use Cms\Classes\Theme;
use Event;
use System\Classes\PluginBase;
use Winter\Blocks\Classes\Block as BlockModel;
use Winter\Blocks\Classes\BlockManager;
use Winter\Blocks\Classes\BlocksDatasource;
use Winter\Blocks\Classes\Block as BlockModel;
use Winter\Blocks\FormWidgets\Block;
use Winter\Storm\Support\Facades\Config;
use Winter\Storm\Support\Facades\Event;

/**
* Blocks Plugin Information File
Expand Down Expand Up @@ -103,6 +107,27 @@ public function boot(): void
{
$this->extendThemeDatasource();
$this->extendControlLibraryBlocks();

if ($this->app->runningInBackend() && in_array('Cms', Config::get('cms.loadModules'))) {
$this->extendCms();
}
}

/**
* Registers any back-end permissions used by this plugin.
*
* @return array
*/
public function registerPermissions()
{
return [
'winter.blocks.manage_blocks' => [
'tab' => 'winter.blocks::lang.plugin.name',
'order' => 200,
'roles' => [UserRole::CODE_DEVELOPER, UserRole::CODE_PUBLISHER],
'label' => 'winter.blocks::lang.blocks.manage_blocks'
],
];
}

/**
Expand Down Expand Up @@ -176,4 +201,21 @@ protected function extendControlLibraryBlocks(): void
}
});
}

/**
* Extend the CMS to implement the BlocksController as a child of the CMS
*/
public function extendCms(): void
{
Event::listen('backend.menu.extendItems', function (NavigationManager $manager) {
$manager->addSideMenuItem('winter.cms', 'cms', 'blocks', [
'label' => 'winter.blocks::lang.plugin.name',
'icon' => 'icon-cubes',
'url' => Backend::url('winter/blocks/blockscontroller'),
// TODO: Make good
'attributes' => 'onclick="window.location.href = this.querySelector(\'a\').href;"',
'permissions' => ['winter.blocks.manage_blocks']
]);
});
}
}
1 change: 1 addition & 0 deletions assets/dist/js/winter.cmspage.extension.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions assets/src/js/winter.cmspage.extension.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(($) => {
$.wn.cmsPage.updateModifiedCounter = function () {
var counters = {
page: {menu: 'pages', count: 0},
partial: {menu: 'partials', count: 0},
layout: {menu: 'layouts', count: 0},
content: {menu: 'content', count: 0},
asset: {menu: 'assets', count: 0},
block: {menu: 'blocks', count: 0},
}

$('> div.tab-content > div.tab-pane[data-modified]', '#cms-master-tabs').each(function () {
var inputType = $('> form > input[name=templateType]', this).val();
counters[inputType].count++;
});

$.each(counters, function (type, data) {
$.wn.sideNav.setCounter('cms/' + data.menu, data.count);
});
};
})(window.jQuery);
10 changes: 10 additions & 0 deletions classes/Block.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ class Block extends CmsCompoundObject
*/
protected $allowedExtensions = ['block'];

/**
* @var array The attributes that are mass assignable.
*/
protected $fillable = [
'markup',
'settings',
'code',
'yaml'
];

protected PartialStack $partialStack;

public function __construct(array $attributes = [])
Expand Down
62 changes: 60 additions & 2 deletions classes/BlockParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,72 @@ class BlockParser extends SectionParser
*/
public static function parseSettings(string $settings): array
{
return Yaml::parse($settings);
$parsed = Yaml::parse($settings);
// Ensure that the parsed settings returns an array (errors return input string)
return is_array($parsed) ? $parsed : [];
}

/**
* Renders the provided settings data into a string that can be stored in the Settings section
*/
public static function renderSettings(array $data): string
{
return Yaml::render($data);
return is_string($data['yaml']) ? $data['yaml'] : Yaml::render($data);
}

/**
* Parses Halcyon section content.
* The expected file format is following:
*
* INI settings section
* ==
* PHP code section
* ==
* Twig markup section
*
* If the content has only 2 sections they are parsed as settings and markup.
* If there is only a single section, it is parsed as markup.
*
* Returns an array with the following elements: (array|null) 'settings',
* (string|null) 'markup', (string|null) 'code'.
*/
public static function parse(string $content, array $options = []): array
{
$sectionOptions = array_merge([
'isCompoundObject' => true
], $options);
extract($sectionOptions);

$result = [
'settings' => [],
'code' => null,
'markup' => null,
'yaml' => null
];

if (!isset($isCompoundObject) || $isCompoundObject === false || !strlen($content)) {
return $result;
}

$sections = static::parseIntoSections($content);
$count = count($sections);
foreach ($sections as &$section) {
$section = trim($section);
}

if ($count >= 3) {
$result['yaml'] = $sections[0];
$result['settings'] = static::parseSettings($sections[0]);
$result['code'] = static::parseCode($sections[1]);
$result['markup'] = static::parseMarkup($sections[2]);
} elseif ($count == 2) {
$result['yaml'] = $sections[0];
$result['settings'] = static::parseSettings($sections[0]);
$result['markup'] = static::parseMarkup($sections[1]);
} elseif ($count == 1) {
$result['markup'] = static::parseMarkup($sections[0]);
}

return $result;
}
}
3 changes: 2 additions & 1 deletion classes/BlockProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ protected function parseTemplateContent($query, $result, $fileName)
'content' => $content,
'mtime' => array_get($result, 'mtime'),
'markup' => $processed['markup'],
'code' => $processed['code']
'code' => $processed['code'],
'yaml' => $processed['yaml'],
] + $processed['settings'];
}

Expand Down
Loading
Loading