Skip to content
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