__('Your Cerebrate instance requires immediate attention.'), 'warning' => __('Issues found, it is recommended that you resolve them.'), 'info' => __('There are some optional settings that are incorrect or not set.'), ]; $noticeDescriptionPerLevel = [ 'critical' => __('Cerebrate will not operate correctly or will be unsecure until these issues are resolved.'), 'warning' => __('Some of the features of Cerebrate cannot be utilised until these issues are resolved.'), 'info' => __('There are some optional tweaks that could be done to improve the looks of your Cerebrate instance.'), ]; $headingPerLevel = [ 'critical' => __('Critical settings'), 'warning' => __('Warning settings'), 'info' => __('Info settings'), ]; $variantFromSeverity = [ 'critical' => 'danger', 'warning' => 'warning', 'info' => 'info', ]; $this->set('variantFromSeverity', $variantFromSeverity); $alertVariant = 'info'; $alertBody = ''; $skipHeading = false; $tableItems = []; foreach (array_keys($mainNoticeHeading) as $level) { if(!empty($notices[$level])) { $variant = $variantFromSeverity[$level]; if (!$skipHeading) { $alertBody .= sprintf('
%s
', $mainNoticeHeading[$level]); $alertVariant = $variant; $skipHeading = true; } $tableItems[] = [ 'severity' => $headingPerLevel[$level], 'issues' => count($notices[$level]), 'badge-variant' => $variant, 'description' => $noticeDescriptionPerLevel[$level], ]; } } $alertBody .= $this->Bootstrap->table([ 'small' => true, 'striped' => false, 'hover' => false, 'borderless' => true, 'bordered' => false, 'tableClass' => 'mb-0' ], [ 'fields' => [ ['key' => 'severity', 'label' => __('Severity')], ['key' => 'issues', 'label' => __('Issues'), 'formatter' => function($count, $row) { return $this->Bootstrap->badge([ 'variant' => $row['badge-variant'], 'text' => $count ]); }], ['key' => 'description', 'label' => __('Description')] ], 'items' => $tableItems, ]); $settingNotice = $this->Bootstrap->alert([ 'dismissible' => false, 'variant' => $alertVariant, 'html' => $alertBody ]); $settingNotice = sprintf('
%s
', $settingNotice); $this->set('settingNotice', $settingNotice); $settingTable = genLevel0($settingsProvider, $this); ?>
$level1Setting) { if (!empty($level1Setting)) { $content0[] = genLevel1($level1Setting, $appView); } else { $content0[] = __('No Settings available yet'); } } array_unshift($level0, __('Setting Diagnostic')); array_unshift($content0, $appView->get('settingNotice')); $tabsOptions0 = [ // 'vertical' => true, // 'vertical-size' => 2, 'card' => false, 'pills' => false, 'justify' => 'center', 'nav-class' => ['settings-tabs'], 'data' => [ 'navs' => $level0, 'content' => $content0 ] ]; $table0 = $appView->Bootstrap->tabs($tabsOptions0); return $table0; } function genLevel1($level1Setting, $appView) { $content1 = []; $nav1 = []; foreach ($level1Setting as $level2Name => $level2Setting) { if (!empty($level2Setting)) { $content1[] = genLevel2($level2Name, $level2Setting, $appView); } else { $content1[] = ''; } $nav1[$level2Name] = array_filter( // only show grouped settings array_keys($level2Setting), function ($settingGroupName) use ($level2Setting) { return !isLeaf($level2Setting[$settingGroupName]); } ); } $contentHtml = implode('', $content1); $scrollspyNav = genScrollspyNav($nav1); $mainPanelHeight = 'calc(100vh - 8px - 42px - 1rem - 56px - 38px - 1rem)'; $container = '
'; $container .= "
{$scrollspyNav}
"; $container .= "
{$contentHtml}
"; $container .= '
'; return $container; } function genLevel2($level2Name, $level2Setting, $appView) { foreach ($level2Setting as $level3Name => $level3Setting) { if (!empty($level3Setting)) { $level3 = genLevel3($level2Name, $level3Name, $level3Setting, $appView); $content2[] = sprintf('
%s
', sprintf('sp-%s', h($level2Name)), $level3); } else { $content2[] = ''; } } return implode('', $content2); } function genLevel3($level2Name, $settingGroupName, $setting, $appView) { $settingGroup = ''; if (isLeaf($setting)) { $tmp = genSingleSetting($settingGroupName, $setting, $appView); $settingGroup = "
{$tmp}
"; } else { $tmpID = sprintf('sp-%s-%s', h($level2Name), h($settingGroupName)); $settingGroup .= sprintf('

%s

', $tmpID, $tmpID, h($settingGroupName)); $groupIssueSeverity = false; foreach ($setting as $singleSettingName => $singleSetting) { $tmp = genSingleSetting($singleSettingName, $singleSetting, $appView); $settingGroup .= sprintf('
%s
', $tmp); if (!empty($singleSetting['error'])) { $settingVariant = $appView->get('variantFromSeverity')[$singleSetting['severity']]; if ($groupIssueSeverity != 'danger') { if ($groupIssueSeverity != 'warning') { $groupIssueSeverity = $settingVariant; } } } } $settingGroup = $appView->Bootstrap->genNode('div', [ 'class' => [ 'shadow', 'p-2', 'mb-4', 'rounded', (!empty($groupIssueSeverity) ? "callout callout-${groupIssueSeverity}" : ''), ($appView->get('darkMode') ? 'bg-dark' : 'bg-light') ], ], $settingGroup); } return $settingGroup; } function genSingleSetting($settingName, $setting, $appView) { $dependsOnHtml = ''; if (!empty($setting['dependsOn'])) { $dependsOnHtml = $appView->Bootstrap->genNode('span', [ ], $appView->Bootstrap->genNode('sup', [ 'class' => [ $appView->FontAwesome->getClass('info'), 'ml-1', ], 'title' => __('This setting depends on the validity of: {0}', h($setting['dependsOn'])) ])); } $settingId = str_replace('.', '_', $settingName); $label = $appView->Bootstrap->genNode('label', [ 'class' => ['font-weight-bolder', 'mb-0'], 'for' => $settingId ], h($setting['name']) . $dependsOnHtml); $description = ''; if (!empty($setting['description'])) { $description = $appView->Bootstrap->genNode('small', [ 'class' => ['form-text', 'text-muted', 'mt-0'], 'id' => "{$settingId}Help" ], h($setting['description'])); } $error = ''; if (!empty($setting['error'])) { $textColor = ''; $textColor = "text-{$appView->get('variantFromSeverity')[$setting['severity']]}"; $error = $appView->Bootstrap->genNode('div', [ 'class' => ['d-block', 'invalid-feedback', $textColor], ], h($setting['errorMessage'])); } if (empty($setting['type'])) { $setting['type'] = 'string'; } if ($setting['type'] == 'string') { $input = genInputString($settingId, $setting, $appView); } elseif ($setting['type'] == 'boolean') { $input = genInputCheckbox($settingId, $setting, $appView); $description = ''; } elseif ($setting['type'] == 'integer') { $input = genInputInteger($settingId, $setting, $appView); } elseif ($setting['type'] == 'select') { $input = genInputSelect($settingId, $setting, $appView); } elseif ($setting['type'] == 'multi-select') { $input = genInputMultiSelect($settingId, $setting, $appView); } else { $input = genInputString($settingId, $setting, $appView); } $container = $appView->Bootstrap->genNode('div', [ 'class' => ['form-group', 'mb-2'] ], implode('', [$label, $input, $description, $error])); return $container; } function genInputString($settingId, $setting, $appView) { return $appView->Bootstrap->genNode('input', [ 'class' => [ 'form-control', "xxx-{$appView->get('variantFromSeverity')[$setting['severity']]} yyy-{$setting['severity']}", (!empty($setting['error']) ? 'is-invalid' : ''), (!empty($setting['error']) ? "border-{$appView->get('variantFromSeverity')[$setting['severity']]}" : ''), (!empty($setting['error']) && $setting['severity'] == 'warning' ? 'warning' : ''), ], 'type' => 'text', 'id' => $settingId, 'value' => isset($setting['value']) ? $setting['value'] : "", 'placeholder' => $setting['default'] ?? '', 'aria-describedby' => "{$settingId}Help" ]); } function genInputCheckbox($settingId, $setting, $appView) { $switch = $appView->Bootstrap->genNode('input', [ 'class' => [ 'custom-control-input' ], 'type' => 'checkbox', 'value' => !empty($setting['value']) ? 1 : 0, 'checked' => !empty($setting['value']) ? 'checked' : '', 'id' => $settingId, ]); $label = $appView->Bootstrap->genNode('label', [ 'class' => [ 'custom-control-label' ], 'for' => $settingId, ], h($setting['description'])); $container = $appView->Bootstrap->genNode('div', [ 'class' => [ 'custom-control', 'custom-switch', ], ], implode('', [$switch, $label])); return $container; } function genInputInteger($settingId, $setting, $appView) { return $appView->Bootstrap->genNode('input', [ 'class' => [ 'form-control' ], 'type' => 'number', 'min' => '0', 'step' => 1, 'id' => $settingId, 'aria-describedby' => "{$settingId}Help" ]); } function genInputSelect($settingId, $setting, $appView) { } function genInputMultiSelect($settingId, $setting, $appView) { } function genScrollspyNav($nav1) { $nav = ''; return $nav; } function isLeaf($setting) { return !empty($setting['name']) && !empty($setting['type']); } ?>