gridstack-8.x-2.5/src/Entity/GridStack.php
src/Entity/GridStack.php
<?php
namespace Drupal\gridstack\Entity;
use Drupal\Component\Serialization\Json;
/**
* Defines the GridStack configuration entity.
*
* @ConfigEntityType(
* id = "gridstack",
* label = @Translation("GridStack optionset"),
* list_path = "admin/structure/gridstack",
* config_prefix = "optionset",
* entity_keys = {
* "id" = "name",
* "label" = "label",
* "status" = "status",
* "weight" = "weight",
* },
* config_export = {
* "id",
* "name",
* "label",
* "status",
* "weight",
* "options",
* "json",
* }
* )
*/
class GridStack extends GridStackBase implements GridStackInterface {
/**
* The supported $breakpoints.
*
* @var array
*/
private static $activeBreakpoints = ['xs', 'sm', 'md', 'lg', 'xl'];
/**
* Returns the supported breakpoints.
*/
public static function getConstantBreakpoints() {
return self::$activeBreakpoints;
}
/**
* {@inheritdoc}
*/
public function getSettings($merged = TRUE) {
$default = self::load('default');
$options = $merged ? array_merge($default->options, $this->options) : $this->options;
return isset($options['settings']) ? $options['settings'] : [];
}
/**
* {@inheritdoc}
*/
public function setSettings(array $values, $merged = TRUE) {
$settings = isset($this->options['settings']) ? $this->options['settings'] : [];
$this->options['settings'] = $merged ? array_merge($settings, $values) : $values;
return $this;
}
/**
* {@inheritdoc}
*/
public function getSetting($name) {
return (NULL !== $this->getOptions('settings', $name)) ? $this->getOptions('settings', $name) : NULL;
}
/**
* {@inheritdoc}
*/
public function setSetting($name, $value) {
$this->options['settings'][$name] = $value;
return $this;
}
/**
* {@inheritdoc}
*/
public function getEndBreakpointGrids($current = 'grids') {
$build = [];
foreach ($this->getBreakpoints() as $key => $breakpoint) {
if (empty($breakpoint['grids'])) {
continue;
}
$build[$key] = $breakpoint;
}
$keys = array_keys($build);
$end = end($keys);
return $this->getBreakpointGrids($end, $current);
}
/**
* {@inheritdoc}
*/
public function getNestedGridsByDelta($delta = 0) {
$grids = $this->getEndBreakpointGrids('nested');
$nested = isset($grids[$delta]) ? $grids[$delta] : [];
$check = array_filter($nested);
return empty($check) ? [] : $nested;
}
/**
* {@inheritdoc}
*/
public function getBreakpoints($breakpoint = NULL) {
$breakpoints = $this->getOption('breakpoints') ?: [];
if ($breakpoint && isset($breakpoints[$breakpoint])) {
return $breakpoints[$breakpoint];
}
return $breakpoints;
}
/**
* Returns options.breakpoints.sm.[width, column, image_style, grids, nested].
*/
public function getBreakpointGrids($breakpoint = 'lg', $current = 'grids') {
$grids = !empty($this->getBreakpoints($breakpoint)) && isset($this->getBreakpoints($breakpoint)[$current]) ? $this->getBreakpoints($breakpoint)[$current] : '';
$grids = Json::decode($grids);
if ($grids) {
return $current == 'grids' ? array_filter($grids) : $grids;
}
return [];
}
/**
* Returns options.breakpoints.sm.[width, column, image_style, grids, nested].
*/
public function getBreakpointGrid($breakpoint = 'lg', $index = -1, $property = '', $current = 'grids') {
$grids = $this->getBreakpointGrids($breakpoint, $current);
return isset($grids[$index], $grids[$index][$property]) ? $grids[$index][$property] : NULL;
}
/**
* Converts gridstack breakpoint grids from stored JSON into array.
*/
public function gridsJsonToArray(array &$settings = []) {
$settings['breakpoints'] = array_filter($this->getBreakpoints());
if (!empty($settings['breakpoints'])) {
foreach ($settings['breakpoints'] as $key => $breakpoint) {
if (!empty($breakpoint['grids']) && is_string($breakpoint['grids'])) {
$settings['breakpoints'][$key]['grids'] = Json::decode($breakpoint['grids']);
}
if (!empty($breakpoint['nested']) && is_string($breakpoint['nested'])) {
$settings['breakpoints'][$key]['nested'] = Json::decode($breakpoint['nested']);
}
}
}
}
/**
* Optimize grid widths to remove similar widths.
*/
public function optimizeGridWidths(array $settings = [], $current = 'grids') {
$optimize = !empty($settings['optimized']);
$breakpoints = isset($settings['breakpoints']) ? $settings['breakpoints'] : [];
$delta = isset($settings['delta']) ? $settings['delta'] : 0;
$nested_delta = isset($settings['nested_delta']) ? $settings['nested_delta'] : NULL;
$unique = [];
foreach (static::$activeBreakpoints as $id) {
$item = isset($breakpoints[$id], $breakpoints[$id][$current][$delta]) ? $breakpoints[$id][$current][$delta] : '';
if (empty($item)) {
continue;
}
if ($current == 'grids') {
if (!empty($item['width'])) {
$unique[$id] = (int) $item['width'];
}
}
elseif ($current == 'nested') {
if (isset($item[$nested_delta]) && !empty($item[$nested_delta]['width'])) {
$unique[$id] = (int) $item[$nested_delta]['width'];
}
}
}
$reversed = array_reverse(array_unique($unique));
return $optimize ? array_reverse($reversed) : $unique;
}
/**
* Returns JSON for options.breakpoints[xs|sm|md|lg|xl] keyed by indices.
*/
public function getJsonSummaryBreakpoints($breakpoint = 'lg', $exclude_image_style = FALSE, $no_keys = TRUE) {
$grids = $this->getBreakpointGrids($breakpoint);
if ($grids && $no_keys) {
$values = [];
foreach ($grids as &$grid) {
if (empty($grid)) {
continue;
}
if ($exclude_image_style && isset($grid['image_style'])) {
array_pop($grid);
}
$values[] = array_values($grid);
}
// Simplify and remove keys:
// Original: [{"x":1,"y":0,"width":2,"height":8}.
// Now: [[1,0,2,8].
$grids = $values;
}
return $grids ? Json::encode($grids) : '';
}
/**
* Returns the icon URI.
*/
public function getIconUri() {
$id = $this->id();
$uri = file_build_uri('gridstack/' . $id . '.png');
// The icon was updated, and stored at public://gridstack/ directory.
if (is_file($uri)) {
return $uri;
}
// The icon may be empty, or not, yet not always exists at public directory.
$uri = $this->getOption('icon');
$dependencies = $this->getDependencies();
$module = isset($dependencies['module'][0]) && !empty($dependencies['module'][0]) ? $dependencies['module'][0] : '';
// Support static icons at MODULE_NAME/images/OPTIONSET_ID.png as long as
// the module dependencies are declared explicitly for the stored optionset.
if (empty($uri) || !is_file($uri)) {
// Reset to empty first.
$uri = '';
$handler = \Drupal::service('gridstack.manager')->getModuleHandler();
if ($module && $handler->moduleExists($module)) {
$icon_path = drupal_get_path('module', $module) . '/images/' . $id . '.png';
if (is_file(\Drupal::root() . '/' . $icon_path)) {
$uri = base_path() . $icon_path;
}
}
}
return $uri;
}
/**
* Returns the icon URL.
*/
public function getIconUrl($absolute = FALSE) {
$url = '';
if ($uri = $this->getIconUri()) {
$url = file_url_transform_relative(file_create_url($uri));
if (!$absolute) {
$url = ltrim($url, '/');
}
}
return $url;
}
/**
* {@inheritdoc}
*/
public function prepareRegions($clean = TRUE) {
$grids = $this->getEndBreakpointGrids();
$regions = [];
foreach ($grids as $delta => $grid) {
$label_index = ($delta + 1);
$label = $label_index;
$regions['gridstack_' . $delta]['label'] = $label;
// With nested grids, its container doesn't contain contents, but grids.
$nested_grids = $this->getNestedGridsByDelta($delta);
$is_nested = array_filter($nested_grids);
if ($is_nested) {
// Remove container since the actual contents are moved, if required.
if ($clean) {
unset($regions['gridstack_' . $delta]);
}
foreach ($nested_grids as $nested_delta => $nested_grid) {
$label = $label_index . ':' . ($nested_delta + 1);
$regions['gridstack_' . $delta . '_' . $nested_delta]['label'] = $label;
}
}
}
return $regions;
}
}
