<?php
/**
* SeekQuarry/Yioop --
* Open Source Pure PHP Search Engine, Crawler, and Indexer
*
* Copyright (C) 2009 - 2026 Chris Pollett chris@pollett.org
*
* LICENSE:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* END LICENSE
*
* @author Chris Pollett chris@pollett.org
* @license https://www.gnu.org/licenses/ GPL3
* @link https://www.seekquarry.com/
* @copyright 2009 - 2026
* @filesource
*/
namespace seekquarry\yioop\views\helpers;
/**
* This is a helper class is used to draw
* icon buttons and links
*
* @author Chris Pollett
*/
class IconlinkHelper extends Helper
{
/**
* Types of icons supported by this helper
* @var array
*/
public $icon_possibilities;
/**
* Initials mapping between names of icons and the actual icons
* to be used as links or buttons
*/
public function __construct()
{
$this->icon_possibilities = [
"account_home" => [ tl('iconlink_helper_account_home'), 'π '],
"account_settings" => [ tl('iconlink_helper_account_settings'),'β'],
"add" => [ tl('iconlink_helper_add'), 'β'],
"ai_summary" => [tl('iconlink_helper_ai_summary'), 'π'],
"ask_join_group" => [ tl('iconlink_helper_ask_join_group'), "π"],
"audio_call" => [ tl('iconlink_helper_audio_call'), 'π'],
"audio_call_end" => [ tl('iconlink_helper_end_audio_call'), 'π'],
"back" => [tl('iconlink_helper_back'), 'β¬
οΈ'],
"close" => [ tl('iconlink_helper_close'), 'X'],
"create_group" => [ tl('iconlink_helper_create_group'), 'β'],
"combined_discussions" => [
tl('iconlink_helper_combined_discussions'), 'π'],
"compose" => [tl('iconlink_helper_compose'),
'<svg viewBox="0 0 16 16" width="14" ' .
'height="14" aria-hidden="true">' .
'<path d="M14,2 L2,7 L7,9 L9,14 Z" ' .
'fill="none" stroke="currentColor" ' .
'stroke-width="1.5" ' .
'stroke-linejoin="round" />' .
'<path d="M14,2 L7,9" ' .
'fill="none" stroke="currentColor" ' .
'stroke-width="1.5" ' .
'stroke-linejoin="round" />' .
'</svg>'],
"clip_copy" => [tl('iconlink_helper_clip_copy'),
'<svg viewBox="0 0 16 16" width="14" ' .
'height="14" aria-hidden="true">' .
'<rect x="5" y="5" width="8" height="9" rx="1" ' .
'fill="none" stroke="currentColor" ' .
'stroke-width="1.5" />' .
'<path d="M3,11 L3,2 L10,2" ' .
'fill="none" stroke="currentColor" ' .
'stroke-width="1.5" stroke-linejoin="round" ' .
'stroke-linecap="round" />' .
'</svg>'],
"clip_cut" => [tl('iconlink_helper_clip_cut'),
'<svg viewBox="0 0 16 16" width="14" ' .
'height="14" aria-hidden="true">' .
'<circle cx="4" cy="11" r="2" fill="none" ' .
'stroke="currentColor" stroke-width="1.5" />' .
'<circle cx="4" cy="5" r="2" fill="none" ' .
'stroke="currentColor" stroke-width="1.5" />' .
'<path d="M5.7,9.7 L14,3 M5.7,6.3 L14,13" ' .
'fill="none" stroke="currentColor" ' .
'stroke-width="1.5" stroke-linecap="round" />' .
'</svg>'],
"clone_copy" => [tl('iconlink_helper_clone_copy'), 'π'],
"copy" => [tl('iconlink_helper_copy'), 'π·'],
"crawls" => [tl('iconlink_helper_manage_crawls'), 'πΈοΈ'],
"cut" => [tl('iconlink_helper_cut'), 'βοΈ'],
"delete" => [tl('iconlink_helper_delete'), 'ποΈ',
tl('iconlink_helper_delete_confirm')],
"flag" => [tl('iconlink_helper_flag'), 'π³οΈ',
tl('iconlink_helper_flag_confirm')],
"discuss_page" => [
tl('iconlink_helper_discuss_page'), 'π£οΈ'],
"edit" => [ tl('iconlink_helper_edit'), 'βοΈ'],
"groups" => [ tl('iconlink_helper_groups'), 'ποΈ'],
"group_feed" => [ tl('iconlink_helper_group_discussions'), 'π'],
"filter" => [tl('iconlink_helper_filter'),
'<svg viewBox="0 0 16 16" width="14" ' .
'height="14" aria-hidden="true">' .
'<path d="M2,3 H14 L10,8 V13 L6,13 V8 Z" ' .
'fill="none" stroke="currentColor" ' .
'stroke-width="1.5" stroke-linejoin="round" />' .
'</svg>'],
"history" => [tl('iconlink_helper_history'), 'π'],
"information" => [tl('iconlink_helper_information'), 'βΉοΈ'],
"issue_tracker" => [tl('iconlink_helper_issue_tracker'),
'π£οΈ'],
"new_issue" => [tl('iconlink_helper_new_issue'), 'πͺ²'],
"join_group" => [ tl('iconlink_helper_join_group'), "π¬"],
"join_group_fee" => [ tl('iconlink_helper_join_group'), "π¬",
tl('iconlink_helper_fee_warning')],
"join_invited_group" => [ tl('iconlink_helper_join_invited_group'),
"ποΈ"],
"join_groups" => [ tl('iconlink_helper_join_groups'), "π¬"],
"leave_group" => [ tl('iconlink_helper_leave_group'), "π«"],
"localize" => [ tl('iconlink_helper_localize'), 'π'],
"machines" => [tl('iconlink_helper_manage_machines'), 'π€'],
"mail" => [tl('iconlink_helper_mail'), 'βοΈ'],
"media_jobs" => [tl('iconlink_helper_media_jobs'), 'πΌ'],
"media_sources" => [tl('iconlink_helper_media_sources'),
'π'],
"mail_filter_unread" => [
tl('iconlink_helper_mail_filter_unread'),
'<svg viewBox="0 0 16 16" width="14" ' .
'height="14" aria-hidden="true">' .
'<path d="M2,3 H14 L10,8 V13 L6,13 V8 Z" ' .
'fill="none" stroke="currentColor" ' .
'stroke-width="1.5" ' .
'stroke-linejoin="round" />' .
'</svg>'],
"mail_filter_all" => [
tl('iconlink_helper_mail_filter_all'),
'<svg viewBox="0 0 16 16" width="14" ' .
'height="14" aria-hidden="true">' .
'<path d="M2,3 H14 L10,8 V13 L6,13 V8 Z" ' .
'fill="currentColor" stroke="currentColor" ' .
'stroke-width="1.5" ' .
'stroke-linejoin="round" />' .
'</svg>'],
"mail_reply" => [tl('iconlink_helper_mail_reply'),
'<svg viewBox="0 0 16 16" width="14" ' .
'height="14" aria-hidden="true">' .
'<path d="M7,4 L3,8 L7,12 M3,8 H10 ' .
'C12,8 13,9 13,11 V13" ' .
'fill="none" stroke="currentColor" ' .
'stroke-width="1.5" ' .
'stroke-linejoin="round" ' .
'stroke-linecap="round" />' .
'</svg>'],
"mail_reply_all" => [
tl('iconlink_helper_mail_reply_all'),
'<svg viewBox="0 0 16 16" width="14" ' .
'height="14" aria-hidden="true">' .
'<path d="M4,4 L1,8 L4,12 M8,4 L5,8 L8,12 ' .
'M5,8 H10 ' .
'C12,8 13,9 13,11 V13" ' .
'fill="none" stroke="currentColor" ' .
'stroke-width="1.5" ' .
'stroke-linejoin="round" ' .
'stroke-linecap="round" />' .
'</svg>'],
"mail_forward" => [tl('iconlink_helper_mail_forward'),
'<svg viewBox="0 0 16 16" width="14" ' .
'height="14" aria-hidden="true">' .
'<path d="M9,4 L13,8 L9,12 M13,8 H6 ' .
'C4,8 3,9 3,11 V13" ' .
'fill="none" stroke="currentColor" ' .
'stroke-width="1.5" ' .
'stroke-linejoin="round" ' .
'stroke-linecap="round" />' .
'</svg>'],
"mixes" => [tl('iconlink_helper_manage_mixes'), 'π₯¨'],
"messages" => [ tl('iconlink_helper_messages'), 'π¬'],
"pages" => [tl('iconlink_helper_group_pages'), 'π'],
"pending" => [ tl('iconlink_helper_request_pending'), "β³",
tl('iconlink_helper_cancel_request')],
"play" => [tl('iconlink_helper_group_play'), 'βΆοΈ'],
"query_stats" => [ tl('iconlink_helper_query_stats'), 'π'],
"refresh" => [tl('iconlink_helper_refresh'), 'π'],
"rename" => [tl('iconlink_helper_rename'),
'<svg viewBox="0 0 16 16" width="14" ' .
'height="14" aria-hidden="true">' .
'<rect x="1" y="3.5" width="14" height="9" rx="2.5" ' .
'fill="none" stroke="currentColor" ' .
'stroke-width="1.3" />' .
'<path d="M2.8,10.4 L4.3,5.6 L5.8,10.4 M3.4,9 L5.2,9" ' .
'fill="none" stroke="currentColor" stroke-width="1" ' .
'stroke-linejoin="round" stroke-linecap="round" />' .
'<path d="M7,5.6 L7,10.4 M7,5.6 L8.3,5.6 ' .
'A0.9,0.9 0 0 1 8.3,7.7 L7,7.7 ' .
'M7,7.7 L8.6,7.7 A1.35,1.35 0 0 1 8.6,10.4 L7,10.4" ' .
'fill="none" stroke="currentColor" stroke-width="1" ' .
'stroke-linejoin="round" stroke-linecap="round" />' .
'<path d="M12,1.5 L12,14.5 M11,1.5 L13,1.5 ' .
'M11,14.5 L13,14.5" ' .
'fill="none" stroke="currentColor" ' .
'stroke-width="1.1" stroke-linecap="round" />' .
'</svg>'],
"reset" => [ tl('iconlink_helper_reset'), 'X'],
"resources" => [ tl('iconlink_helper_resources'), 'ποΈ'],
"search" => [ tl('iconlink_helper_search'), 'π'],
"settings" => [ tl('iconlink_helper_settings'),
"<b class='black medium-font'>β</b>"],
"statistics" => [ tl('iconlink_helper_statistics'), "π"],
"thread_followed" => [tl('iconlink_helper_unfollow_thread'),
'π'],
"thread_unfollowed" => [tl('iconlink_helper_follow_thread'),
'π'],
"video_call" => [ tl('iconlink_helper_video_call'), 'π¦'],
"video_call_end" => [ tl('iconlink_helper_end_video_call'), 'βΉοΈ'],
"view_read" => [ tl('iconlink_helper_view_read'), 'β©οΈ'],
"view_source" => [ tl('iconlink_helper_view_source'), 'ποΈ'],
"wiki" => [ tl('iconlink_helper_group_main_page'),
'π'],
"wiki_syntax" => [ tl('iconlink_helper_wiki_syntax'), 'π'],
];
}
/**
* Draws a link button suitable to indicate the activity $type
*
* @param string $url url that is sent when one clicks and confirms
* @param string $type one of "edit", ...
* @param string $badge_text if not empty, text to use to draw a badge
* on the top right of the icon
* @param bool $as_string whether to return a string or html
* @param string $div_classes space separated, additional css classes
* to add to outermost div
* @param string $anchor_classes space separated, additional css classes
* to add to anchor tag
* @param bool $replace_css whether to append css in $div_classes and
* $anchor_classes to existing or to replace.
* @param string $tab_target whether to open link in a new tab with target
* $tab_target
* @return mixed either void, or a string of html if $as_string = true
*/
public function renderButton($url, $type = "edit", $badge_text = "",
$as_string = false, $div_classes = "", $anchor_classes = "",
$replace_css = false, $tab_target = "")
{
if (is_array($url)) {
list($id, $url,) = $url;
$id_attr = " id='$id' ";
} else {
$id_attr = "";
}
if ($as_string) {
ob_start();
}
$div_classes = ($replace_css) ? $div_classes : "icon-button-container ".
$div_classes;
?><div <?=$id_attr ?> class='<?= $div_classes ?>'><?=
$this->renderLink($url, $type, $badge_text, $as_string,
$anchor_classes, $replace_css, $tab_target); ?></div><?php
if ($as_string) {
$button = ob_get_contents();
ob_end_clean();
return $button;
}
}
/**
* Draws a button for a form that uses an icon as its main text
* @param string $button_type value for type attribute of html button
* @param string $type of icon one of "edit", ...
* @param bool $as_string whether to return a string or html
* @param string $anchor_classes space separated, additional css classes
* to add to anchor
* @param string $additional_attributes a string to enclose with the open
* button tag with additional attributes
* @return mixed either void, or a string of html if $as_string = true
*/
public function renderFormButton($button_type = "submit" , $type = "edit",
$as_string = false, $anchor_classes = "",
$additional_attributes = "")
{
$type = (isset($this->icon_possibilities[$type])) ? $type : "submit";
$icon_info = $this->icon_possibilities[$type];
list($icon_text, $icon, ) = $icon_info;
if ($as_string) {
ob_start();
}
?><button type='<?=$button_type ?>' class='<?=$anchor_classes
?>' <?=$additional_attributes ?> ><span role='img'
class='icon-glyph' aria-label='<?=
$icon_text ?>' ><?=$icon ?></span></button><?php
if ($as_string) {
$button = ob_get_contents();
ob_end_clean();
return $button;
}
}
/**
* Draws a link suitable to indicate the activity $type
*
* @param string $url url that is sent when one clicks and confirms
* @param string $type one of "edit", ...
* @param string $badge_text if not empty, text to use to draw a badge
* on the top right of the icon
* @param bool $as_string whether to return a string or html
* @param string $anchor_classes space separated, additional css classes
* to add to anchor
* @param bool $replace_css whether to replace default anchor css or
* append to it
* @param string $tab_target whether to open link in a new tab with target
* $tab_target
* @return mixed either void, or a string of html if $as_string = true
*/
public function renderLink($url, $type = "edit", $badge_text = "",
$as_string = false, $anchor_classes = "", $replace_css = false,
$tab_target = "")
{
$type = (isset($this->icon_possibilities[$type])) ? $type : "edit";
$icon_info = $this->icon_possibilities[$type];
if (empty($tab_target)) {
$target = (empty($_REQUEST['noscript'])) ? "" :
" target='_parent' rel='noopener' ";
} else {
$target = " target='$tab_target' rel='noopener' ";
}
list($icon_text, $icon, ) = $icon_info;
$confirm = "";
if (is_array($url) && !empty($url[1]) && !empty($icon_info[2])) {
list($url, $translate_aux,) = $url;
$icon_info[2] = tl($icon_info[2], $translate_aux);
$icon = "<div class='inline align-opposite'>$icon<br>".
"<span class='tiny-font' style='position:relative; top: -8px;'".
">$translate_aux</span></div>";
}
if (!empty($icon_info[2])) {
$confirm = " onclick='javascript:return ".
"confirm(\"{$icon_info[2]}\")' ";
}
if ($as_string) {
ob_start();
}
$anchor_classes = ($replace_css) ? $anchor_classes :
"icon-anchor-button ". $anchor_classes;
$badge_attribute = (empty($badge_text)) ? "" :
" data-badge='$badge_text' ";
?><div class='position-context <?=$anchor_classes?>' <?=$badge_attribute
?> ><a <?=$confirm ?> class='<?= $anchor_classes
?>' <?=$target?> href='<?= $url ?>'><span role='img'
class='icon-glyph' aria-label='<?=
$icon_text ?>' ><?=$icon ?></span></a></div><?php
if ($as_string) {
$button = ob_get_contents();
ob_end_clean();
return $button;
}
}
}