View source
<?php
namespace Drupal\opigno_dashboard;
use Drupal\block\Entity\Block;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Block\BlockManagerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\HttpFoundation\JsonResponse;
class BlockService implements BlockServiceInterface {
use StringTranslationTrait;
protected $blockManager;
protected $renderer;
protected $currentUser;
protected $configFactory;
protected $moduleHandler;
protected $database;
public function __construct(BlockManagerInterface $block_manager, RendererInterface $renderer, AccountInterface $account, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, Connection $database) {
$this->blockManager = $block_manager;
$this->renderer = $renderer;
$this->currentUser = $account;
$this->configFactory = $config_factory;
$this->moduleHandler = $module_handler;
$this->database = $database;
}
public function getAllBlocks() : array {
return $this->blockManager
->getDefinitions();
}
public function getAvailableBlocks() : array {
$blocks = $this
->getAllBlocks();
$availables = $this->configFactory
->get('opigno_dashboard.settings')
->get('blocks');
$account_roles = $this->currentUser
->getRoles();
foreach ($blocks as $key1 => &$block) {
if (!isset($availables[$key1]) || isset($availables[$key1]) && !$availables[$key1]['available']) {
unset($blocks[$key1]);
}
else {
$block_real = Block::load($this
->sanitizeId($key1));
if (!$block_real) {
$block_real = Block::load($this
->sanitizeIdOld($key1));
}
$role_access = TRUE;
if (!empty($block_real)) {
$block_visibility = $block_real
->getVisibility();
if (isset($block_visibility['user_role']) && !empty($block_visibility['user_role'])) {
$role_access = FALSE;
foreach ($block_visibility['user_role']['roles'] as $block_role) {
if (in_array($block_role, $account_roles)) {
$role_access = TRUE;
}
}
}
}
if (!$role_access) {
unset($blocks[$key1]);
continue;
}
foreach ($block as &$value) {
if (is_object($value)) {
$value = $value
->render();
}
}
$blocks[$key1]['id'] = $key1;
unset($blocks[$key1]['config_dependencies'], $blocks[$key1]['class'], $blocks[$key1]['provider'], $blocks[$key1]['category'], $blocks[$key1]['deriver'], $blocks[$key1]['context']);
}
}
return array_values($blocks);
}
public function getDashboardBlocksContents() : array {
$ids = [];
foreach ($this
->getAvailableBlocks() as $block) {
$ids[] = $block['id'];
}
$data = [
'attachments' => [],
];
foreach ($ids as $id) {
try {
$block = $this->blockManager
->createInstance($id);
} catch (PluginException $e) {
watchdog_exception('opigno_dashboard_exception', $e);
continue;
}
if (!$block instanceof BlockBase) {
continue;
}
$render = $block
->build();
$data['blocks'][$id] = $this->renderer
->renderRoot($render);
$attachments = $render['#attached'] ?? [];
$data['attachments'] = array_merge_recursive($data['attachments'], $attachments);
}
return $data;
}
public function createBlocksInstances() : void {
$items = $this
->getAvailableBlocks();
$theme = $this->configFactory
->get('opigno_dashboard.settings')
->get('theme');
foreach ($items as $item) {
$id = $this
->sanitizeId($item['id']);
if (!Block::load($id)) {
$settings = [
'plugin' => $item['id'],
'region' => 'content',
'id' => $id,
'theme' => $theme ?? $this->configFactory
->get('system.theme')
->get('default'),
'label' => $this
->t('Dashboard:') . ' ' . $item['admin_label'],
'visibility' => [
'request_path' => [
'id' => 'request_path',
'pages' => '<front>',
'negate' => FALSE,
'context_mapping' => [],
],
],
'weight' => 0,
];
$values = [];
foreach ([
'region',
'id',
'theme',
'plugin',
'weight',
'visibility',
] as $key) {
$values[$key] = $settings[$key];
unset($settings[$key]);
}
foreach ($values['visibility'] as $id => $visibility) {
$values['visibility'][$id]['id'] = $id;
}
$values['settings'] = $settings;
$block = Block::create($values);
try {
$block
->save();
} catch (EntityStorageException $e) {
watchdog_exception('opigno_dashboard_exception', $e);
}
}
}
}
public function sanitizeId(string $id) : string {
return 'dashboard_' . str_replace([
':',
'-',
], [
'_',
'_',
], $id);
}
public function sanitizeIdOld(string $id) : string {
return 'dashboard_' . str_replace(':', '_', $id);
}
public function isSocialFeatureEnabled() : bool {
$socials_enabled = $this->configFactory
->get('opigno_class.socialsettings')
->get('enable_social_features') ?? FALSE;
return $this->moduleHandler
->moduleExists('opigno_social') && $socials_enabled;
}
public function getDefaultDashboardConfig() : string {
return $this
->isSocialFeatureEnabled() ? '{"1":[{"admin_label":"User statistics","context_definitions":[],"id":"opigno_user_stats_block"},{"admin_label":"User connections","context_definitions":[],"id":"opigno_user_connections_block"},{"admin_label":"Latest active trainings","id":"views_block:latest_active_trainings-block","mandatory":false},{"admin_label":"Who is new","context_definitions":[],"id":"views_block:who_s_new-block_1"}],"2":[{"admin_label":"Social wall","context_definitions":[],"id":"opigno_social_wall_block"}],"3":[{"admin_label":"Opigno calendar block","id":"views_block:opigno_calendar-month_block","mandatory":false},{"admin_label":"Who is online","context_definitions":[],"id":"views_block:who_s_online-who_s_online_block"}]}' : '{"1":[{"admin_label":"Latest active trainings","id":"views_block:latest_active_trainings-block"}, {"admin_label":"Private Message: Dashboard - Last Threads","id":"views_block:private_message-block_dashboard"}],"2":[{"admin_label":"Opigno calendar block","id":"views_block:opigno_calendar-month_block"},{"admin_label":"Opigno Notifications: Dashboard - Unread Notifications","id":"views_block:opigno_notifications-block_unread_dashboard"},{"admin_label":"Recent comments","id":"views_block:comments_recent-block_1"}],"3":[]}';
}
public function getDefaultLayoutId() : int {
return $this
->isSocialFeatureEnabled() ? 5 : 3;
}
public function getPositioning($uid = NULL, bool $default = FALSE, bool $user_default = FALSE) {
if (empty($uid)) {
$uid = $this->currentUser
->id();
}
$availables = $this
->getAvailableBlocks();
$config_default = $this->configFactory
->get('opigno_dashboard.default.settings');
$default_positions = json_decode($config_default
->get('positions'), TRUE);
$default_columns = $config_default
->get('columns');
if ($default) {
$positions = $default_positions;
$columns = $default_columns;
}
else {
$query = $this->database
->select('opigno_dashboard_positioning', 'p')
->fields('p', [
'columns',
'positions',
])
->condition('p.uid', $uid);
$result = $query
->execute()
->fetchObject();
$positions = FALSE;
if (!empty($result->positions)) {
$positions = json_decode($result->positions, TRUE);
}
$columns = $result->columns ?? $this
->getDefaultLayoutId();
}
if (!$positions) {
if (!empty($default_positions)) {
$positions = $default_positions;
$columns = $default_columns;
}
else {
$positions = json_decode($this
->getDefaultDashboardConfig(), TRUE);
$columns = $this
->getDefaultLayoutId();
}
}
$mandatory_blocks = $this->configFactory
->get('opigno_dashboard.settings')
->get('blocks');
if (!empty($mandatory_blocks)) {
$mandatory_blocks = array_filter($mandatory_blocks, function ($block) {
return $block['available'] && $block['mandatory'];
});
}
$mandatory = $mandatory_blocks ?? [];
$availables_keys = [];
foreach ($availables as $available) {
$availables_keys[$available['id']] = $available['id'];
}
foreach ($positions as $key1 => $column) {
foreach ($column as $key2 => $row) {
if (!in_array($row['id'], $availables_keys)) {
unset($positions[$key1][$key2]);
continue;
}
if (!empty($mandatory_blocks) && isset($mandatory_blocks[$row['id']])) {
unset($mandatory_blocks[$row['id']]);
}
$positions[$key1][$key2]['mandatory'] = $mandatory && array_key_exists($row['id'], $mandatory);
}
}
foreach ($availables as $key => $value) {
foreach ($positions as $column) {
foreach ($column as $row) {
if (isset($row['id']) && isset($value['id']) && $row['id'] == $value['id']) {
unset($availables[$key]);
}
}
}
if (!empty($mandatory_blocks) && array_key_exists($value['id'], $mandatory_blocks)) {
$mandatory_blocks[$value['id']]['availables_key'] = $key;
}
}
if (!$user_default) {
$available_values = array_values($availables);
$entities = array_merge([
$available_values,
], $positions);
$positions = $entities ?: array_merge([
$available_values,
], [
[],
[],
[],
]);
}
if (!empty($mandatory_blocks)) {
foreach ($mandatory_blocks as $id => $mandatory_block) {
if (!empty($mandatory_block['availables_key'])) {
array_unshift($positions[1], [
'admin_label' => $availables[$mandatory_block['availables_key']]['admin_label'] ?? '',
'id' => $id,
'mandatory' => TRUE,
]);
}
}
}
$columns = $columns ?? $this
->getDefaultLayoutId();
$this
->clearEmptyPositions($positions, $availables_keys);
if ($default) {
return [
'positions' => $positions,
'columns' => $columns,
];
}
else {
return new JsonResponse([
'positions' => $positions,
'columns' => $columns,
]);
}
}
private function clearEmptyPositions(array &$positions, array $availables_keys) {
foreach ($positions as $c_key => $columns) {
if (!is_array($columns)) {
continue;
}
foreach ($columns as $key => $position) {
if (!is_array($columns)) {
continue;
}
if (!isset($position['id']) || isset($position['id']) && !in_array($position['id'], $availables_keys)) {
unset($positions[$c_key][$key]);
}
}
$positions[$c_key] = array_values($positions[$c_key]);
}
}
}