$vars */
private function fillTpl(string $name, array $vars): string {
$tpl = $this->tpl($name);
$search = array();
$replace = array();
foreach ($vars as $k => $v) {
$search[] = '{' . $k . '}';
$replace[] = $v;
}
if (is_object($this->f)) {
return (string)$this->f->str_replace($search, $replace, $tpl);
}
return (string)str_replace($search, $replace, $tpl);
}
/** @return void */
function echoAdminFooter(): void {
$html = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . "/html/adminFooter.html");
echo $this->f->renderTemplate($html, array('{JAPANESE_FLASHCARDS_URL}' => ABJ404_FC_URL));
}
function outputAdminHeaderTabs(string $sub = 'list', string $message = ''): void {
ABJ_404_Solution_WPNotices::echoAdminNotices();
echo $this->tpl('adminHeaderWrapOpen.html');
if (isset($_GET['setup_complete']) && $_GET['setup_complete'] === '1') {
$options = abj_service('options_repository')->getOptions();
$auto = !empty($options['auto_redirects']) && $options['auto_redirects'] !== '0';
$notify = !empty($options['admin_notification']) && $options['admin_notification'] !== '0';
if ($auto && $notify) {
$body = esc_html__('404 Solution is now monitoring your site. When visitors hit broken links, they will be automatically redirected. We will email you if something needs attention.', '404-solution');
} elseif ($auto) {
$body = esc_html__('404 Solution is now monitoring your site. When visitors hit broken links, they will be automatically redirected.', '404-solution');
} elseif ($notify) {
$body = esc_html__('404 Solution is now monitoring your site. We will email you if captured 404 URLs need attention.', '404-solution');
} else {
$body = esc_html__('404 Solution is now monitoring your site. You can create manual redirects anytime from the Page Redirects tab.', '404-solution');
}
echo $this->fillTpl('setupCompleteWelcomeBanner.html', array(
'heading' => esc_html__("You're all set!", '404-solution'),
'body' => $body,
)) . "\n";
}
if ($message != "") {
$allowed_tags = array(
'br' => array(),
'em' => array(),
'strong' => array(),
);
if (($this->f->strlen($message) >= 6) && ($this->f->substr($this->f->strtolower($message), 0, 6) == 'error:')) {
$cssClasses = 'notice notice-error';
} else {
$cssClasses = 'notice notice-success';
}
echo $this->fillTpl('adminHeaderMessageNotice.html', array(
'cssClasses' => $cssClasses,
'message' => (string)wp_kses($message, $allowed_tags),
)) . "\n";
}
if (class_exists('ABJ_404_Solution_RegexAutoPromote')) {
$regexNotice = ABJ_404_Solution_RegexAutoPromote::readNotice();
if (is_array($regexNotice) && $regexNotice['redirect_id'] > 0) {
$this->renderRegexAutoPromoteNotice($regexNotice);
}
}
$isSimpleMode = abj_service('settings_mode_preference')->getMode() === 'simple';
$tabs = array(
array('abj404_redirects', __('Page Redirects', '404-solution')),
array('abj404_captured', __('Captured 404s', '404-solution')),
);
if (!$isSimpleMode) {
$tabs[] = array('abj404_logs', __('Logs', '404-solution'));
$tabs[] = array('abj404_stats', __('Stats', '404-solution'));
}
$tabs[] = array('abj404_tools', __('Tools', '404-solution'));
$tabs[] = array('abj404_options', __('Options', '404-solution'));
$itemTpl = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . '/html/adminHeaderTab.html');
$tabsHtml = '';
foreach ($tabs as $pair) {
list($subKey, $label) = $pair;
$isActive = ($sub == $subKey);
$row = $itemTpl;
$row = str_replace('{url}', esc_url('?page=' . ABJ404_PP . '&subpage=' . $subKey), $row);
$row = str_replace('{activeClass}', $isActive ? ' nav-tab-active active' : '', $row);
$row = str_replace('{ariaSelected}', $isActive ? ' aria-selected="true"' : '', $row);
$row = str_replace('{label}', esc_html($label), $row);
$tabsHtml .= $row;
}
$outer = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . '/html/adminHeaderTabs.html');
echo str_replace('{tabs}', $tabsHtml, $outer);
}
/**
* @param array{redirect_id: int, original_url: string, new_url: string, url_rewritten: bool, created_at: int} $notice
* @return void
*/
public function renderRegexAutoPromoteNotice(array $notice): void {
$redirectId = (int)$notice['redirect_id'];
$originalUrl = (string)$notice['original_url'];
$newUrl = (string)$notice['new_url'];
$urlRewritten = !empty($notice['url_rewritten']);
$editUrl = admin_url('admin.php?page=' . ABJ404_PP . '&subpage=abj404_edit&id=' . $redirectId);
$undoBase = admin_url('admin.php?page=' . ABJ404_PP . '&subpage=abj404_redirects&action=undoRegexAutoPromote');
$undoUrl = wp_nonce_url($undoBase, 'abj404undoRegexAutoPromote');
if ($urlRewritten) {
$message = sprintf(
__('Detected as a regex pattern. Stored "%1$s" as "%2$s".', '404-solution'),
$originalUrl,
$newUrl
);
} else {
$message = sprintf(
__('Detected as a regex pattern. Stored "%s" with Regex status.', '404-solution'),
$originalUrl
);
}
echo $this->fillTpl('regexAutoPromoteNotice.html', array(
'label' => esc_html__('404 Solution:', '404-solution'),
'message' => esc_html($message),
'editUrl' => esc_url($editUrl),
'editLabel' => esc_html__('Edit', '404-solution'),
'undoUrl' => esc_url($undoUrl),
'confirm' => esc_js(__('Undo regex auto-promotion and restore Manual status?', '404-solution')),
'undoLabel' => esc_html__('Undo', '404-solution'),
)) . "\n";
}
/**
* @param string|int $id
* @param mixed $content
*/
function echoPostBox($id, string $title, $content): void {
echo $this->fillTpl('postBox.html', array(
'id' => esc_attr((string)$id),
'title' => esc_html($title),
'content' => (string)$content,
));
}
function echoOptionsSection(ABJ_404_Solution_OptionsSectionView $section): void {
$expandedClass = $section->initiallyVisible ? ' expanded' : '';
$badgeHtml = '';
if ($section->badge) {
$badgeHtml = $this->fillTpl('optionsSectionBadge.html', array(
'badge' => esc_html($section->badge),
));
}
echo $this->fillTpl('optionsSection.html', array(
'expandedClass' => esc_attr($expandedClass),
'sectionId' => esc_attr($section->sectionId),
'postboxId' => esc_attr($section->postboxId),
'ariaExpanded' => $section->initiallyVisible ? 'true' : 'false',
'icon' => (string)$section->icon,
'title' => esc_html($section->title),
'badge' => $badgeHtml,
'content' => (string)$section->content,
));
}
function getCardIcon(string $iconName): string {
$icons = array(
'lightning' => '',
'gear' => '',
'filter' => '',
'document' => '',
'sliders' => '',
'lightbulb' => '',
'chart' => '',
'warning' => '',
'clock' => '',
'download' => '',
'upload' => '',
'trash' => '',
'database' => '',
'cog' => ''
);
return isset($icons[$iconName]) ? $icons[$iconName] : '';
}
function echoStickySaveBar(): void {
$version = ABJ404_VERSION;
$restoreNonce = wp_create_nonce('abj404_restore_defaults');
$versionLabel = esc_html(sprintf(__('Plugin v%s', '404-solution'), $version));
echo $this->fillTpl('stickySaveBar.html', array(
'versionLabel' => $versionLabel,
'restoreNonce' => esc_attr($restoreNonce),
'restoreLabel' => esc_html__('Restore Defaults', '404-solution'),
'saveLabel' => esc_attr__('Save Settings', '404-solution'),
));
$this->echoRestoreDefaultsModal();
}
function echoRestoreDefaultsModal(): void {
echo "\n" . $this->fillTpl('restoreDefaultsModal.html', array(
'title' => esc_html__('Restore Default Settings?', '404-solution'),
'closeLabel' => esc_attr__('Close', '404-solution'),
'body' => esc_html__('This will reset all plugin settings to their default values. This cannot be undone. Your redirect rules and 404 logs will not be affected.', '404-solution'),
'cancelLabel' => esc_html__('Cancel', '404-solution'),
'confirmLabel' => esc_html__('Restore Defaults', '404-solution'),
)) . "\n ";
}
function echoToastNotification(): void {
echo $this->fillTpl('toastNotification.html', array(
'icon' => '✓',
'message' => esc_html__('Settings saved successfully!', '404-solution'),
));
}
function echoExpandCollapseButton(bool $showSuggestions = true): void {
echo "\n" . $this->fillTpl('expandCollapseButton.html', array(
'expandAllLabel' => esc_html__('Expand All', '404-solution'),
'saveLabel' => esc_attr__('Save Settings', '404-solution'),
)) . "\n ";
}
function echoSettingsModeToggle(string $currentMode): void {
$simpleActive = ($currentMode === 'simple') ? 'active' : '';
$advancedActive = ($currentMode === 'advanced') ? 'active' : '';
$simplePressedState = ($currentMode === 'simple') ? 'true' : 'false';
$advancedPressedState = ($currentMode === 'advanced') ? 'true' : 'false';
if ($currentMode === 'simple') {
$modeDescription = __('Simple Mode shows essential options only. Switch to Advanced Mode for full configuration.', '404-solution');
} else {
$modeDescription = __('Advanced Mode shows all options. Switch to Simple Mode for a streamlined view.', '404-solution');
}
$html = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . "/html/settingsModeToggle.html");
$html = $this->f->str_replace('{nonce}', wp_create_nonce('abj404_mode_toggle'), $html);
$html = $this->f->str_replace('{simpleActive}', $simpleActive, $html);
$html = $this->f->str_replace('{advancedActive}', $advancedActive, $html);
$html = $this->f->str_replace('{simplePressedState}', $simplePressedState, $html);
$html = $this->f->str_replace('{advancedPressedState}', $advancedPressedState, $html);
$html = $this->f->str_replace('{Simple Mode}', __('Simple Mode', '404-solution'), $html);
$html = $this->f->str_replace('{Advanced Mode}', __('Advanced Mode', '404-solution'), $html);
$html = $this->f->str_replace('{mode_description}', $modeDescription, $html);
echo $html;
}
function echoInlineModeToggle(): void {
$currentMode = abj_service('settings_mode_preference')->getMode();
$simpleActive = ($currentMode === 'simple') ? 'active' : '';
$advancedActive = ($currentMode === 'advanced') ? 'active' : '';
$simplePressedState = ($currentMode === 'simple') ? 'true' : 'false';
$advancedPressedState = ($currentMode === 'advanced') ? 'true' : 'false';
echo $this->fillTpl('inlineModeToggle.html', array(
'nonce' => esc_attr(wp_create_nonce('abj404_mode_toggle')),
'simpleActive' => esc_attr($simpleActive),
'advancedActive' => esc_attr($advancedActive),
'simplePressedState' => esc_attr($simplePressedState),
'advancedPressedState' => esc_attr($advancedPressedState),
'simpleLabel' => esc_html__('Simple', '404-solution'),
'advancedLabel' => esc_html__('Advanced', '404-solution'),
));
}
}