<?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\elements;
use seekquarry\yioop as B;
use seekquarry\yioop\configs as C;
/**
* Element responsible for displaying the user account features
* that someone can modify for their own SeekQuarry/Yioop account.
*
* @author Chris Pollett
*/
class ManageaccountElement extends Element
{
/**
* Draws a view with a summary of a user's account together with
* a form for updating user info such as password as well as with
* useful links for groups, etc
*
* @param array $data anti-CSRF token
*/
public function render($data)
{
$token = C\p('CSRF_TOKEN') . "=" . $data[C\p('CSRF_TOKEN')];
$admin_url = htmlentities(B\controllerUrl('admin', true));
$feed_url = htmlentities(B\feedsUrl("", "",
true, "group")). "$token";
$base_url = "{$admin_url}a=manageAccount&$token";
$edit_or_no_url = $base_url . (
(isset($data['EDIT_USER'])) ? "&edit=false":"&edit=true");
$icon_helper = $this->view->helper('iconlink');
$is_mobile = !empty($_SERVER['MOBILE']);
if (isset($data['EDIT_USER'])) {
return $this->renderEditUser($data);
}
$more_groups =
(count(($data['RECENT_GROUPS'] ?? [])) < $data['NUM_GROUPS']);
?>
<div class="current-activity">
<div class="account-info">
<h2><img class='home-icon'
src="<?= $data['USER']['USER_ICON'] ?>" alt="<?=
tl('manageaccount_element_icon') ?>" >
<span><?= $data['USERNAME'] ?></span>
</h2> <?=
$icon_helper->renderButton($edit_or_no_url,
'account_settings'); ?>
</div>
<?php
if (isset($data['CRAWL_MANAGER']) && $data['CRAWL_MANAGER']) {
?>
<h2 class="medium-margin"><?php
e(tl('manageaccount_element_search_and_index')); ?>
</h2>
<?=$this->view->element("crawlcontrols")->render($data) ?>
<?php
} ?>
<h2 class="medium-margin"><?=
tl('manageaccount_element_groups')?></h2>
<?=$this->view->element("socialcontrols")->render($data) ?>
<?php
$this->view->helper("grouplist")->render($data['GROUPS'], $token,
$icon_helper, "admin", "account", modifiers:
$data['GROUP_MODIFIERS']);
if ($more_groups) {?>
<div class="more-groups"><b><a href="<?=$feed_url?>"><?=
tl('manageaccount_element_more_groups')?></a></b></div><?php
}
if (!empty($data['THREAD_RECOMMENDATIONS']) ||
!empty($data['GROUP_RECOMMENDATIONS']) ||
!empty($data['RESOURCE_RECOMMENDATIONS'])) {
?>
<h2><?=tl('manageaccount_element_recommendations')?></h2>
<div class="access-result">
<?php
if (!empty($data['THREAD_RECOMMENDATIONS'])) {
?><b><?=tl('manageaccount_element_rec_threads')
?></b><ul><?php
foreach ($data['THREAD_RECOMMENDATIONS'] as
$thread => $threadName) { ?>
<li><a href="<?=htmlentities(B\feedsUrl("thread",
$thread, true, "group")) .
$token ?>" ><?= $threadName ?></a></li>
<?php
}?></ul><?php
}
?><br><?php
if (!empty($data['GROUP_RECOMMENDATIONS'])) {
?><b><?=tl('manageaccount_element_rec_groups')
?></b><ul><?php
foreach ($data['GROUP_RECOMMENDATIONS'] as
$group_id => $group_name) { ?>
<li><a href="<?= htmlentities(B\feedsUrl("group",
$group_id, true, "group")) .
$token ?>" ><?= $group_name ?></a></li>
<?php
}?></ul><?php
}
?><br><?php
if (!empty($data['RESOURCE_RECOMMENDATIONS'])) {
?><b><?=tl('manageaccount_element_rec_resources')
?></b><ul><?php
foreach ($data['RESOURCE_RECOMMENDATIONS'] as
$recommendation) {
$encoded_name = str_replace(" ",
"+", $recommendation[3]); ?><li>
<a href="<?= htmlentities(B\controllerUrl("group")) .
"/$recommendation[0]/$recommendation[2]?" .
"$token&page_id=$recommendation[1]&" .
"sf=$recommendation[4]&arg=media&n=$encoded_name"
?>" ><?= $recommendation[3] ?></a></li>
<?php
}?></div><?php
}
}
?>
</div>
<?php
}
/**
* Renders the form used to control account settings such as
* icon photo, email, password, etc. for a user
*
* @param array $data has field with current values for these setting
* (except password) so that forms can be pre-populated.
*/
public function renderEditUser($data)
{
$token = C\p('CSRF_TOKEN') . "=" . $data[C\p('CSRF_TOKEN')];
$admin_url = htmlentities(B\controllerUrl('admin', true));
$base_url = "{$admin_url}a=manageAccount&$token";
$password_or_no_url = $base_url .(
(isset($data['EDIT_PASSWORD'])) ? "&edit_pass=false":
"&edit_pass=true");
$recover_or_no_url = $base_url .(
(isset($data['EDIT_RECOVERY'])) ? "&edit_recovery=false":
"&edit_recovery=true");
$edit_or_no_url = $base_url . (
(isset($data['EDIT_USER'])) ? "&edit=false":"&edit=true");
$close_url = (!empty($data['EDIT_PASSWORD'])) ?
$password_or_no_url : ((!empty($data['EDIT_RECOVERY'])) ?
$recover_or_no_url : $edit_or_no_url);
$disabled = (isset($data['EDIT_USER'])) ? "" : "disabled='disabled'";
$is_mobile = !empty($_SERVER['MOBILE']);
?>
<div class="current-activity">
<div class="account-info" tabindex="1">
<?= $this->view->helper("close")->render($close_url); ?>
<form id="changeUserForm" method="post" class="account-details"
autocomplete="off" enctype="multipart/form-data">
<h2><?php
if (!empty($data['EDIT_PASSWORD'])) {
e(tl('manageaccount_element_change_password'));
} else if (!empty($data['EDIT_RECOVERY'])) {
e(tl('manageaccount_element_change_recovery'));
} else {
e(tl('manageaccount_element_account_details'));
}
?></h2><?php
$account_rows = 11;
if (!empty($data['USER']['IS_BOT_USER'])) {
$account_rows = 15;
}
if (!empty($data['SELLABLE_ROLES_EXIST'])) {
$account_rows++;
}
$row_col_span = 'rowspan="' . $account_rows . '"';
if ($is_mobile) {
$row_col_span = 'class="center" style="width:300px"';
} ?>
<input type="hidden" name="c" value="admin" >
<input type="hidden" name="<?= C\p('CSRF_TOKEN') ?>" value="<?=
$data[C\p('CSRF_TOKEN')] ?>" >
<input type="hidden" name="a" value="manageAccount" >
<input type="hidden" name="arg" value="updateuser" >
<table class="name-table"><?php
if (empty($data['EDIT_PASSWORD']) && empty($data['EDIT_RECOVERY'])) { ?>
<tr>
<td <?=$row_col_span?> class="user-icon-td" ><img
class='user-icon' id='current-icon'
src="<?= $data['USER']['USER_ICON'] ?>" alt="<?=
tl('manageaccount_element_icon') ?>" ><?php
$this->view->helper("fileupload")->render('current-icon',
'user_icon', 'user-icon', C\THUMB_SIZE, 'image',
['image/png', 'image/gif', 'image/jpeg', 'image/webp',
'image/x-icon']);
if ($is_mobile) { ?>
</td></tr></table><table class="name-table">
<?php
} else {
e('</td>');
}?>
<th class="table-label"><label for="user-name"><?=
tl('manageaccount_element_username') ?>:</label></th>
<td><input type="text" id="user-name"
name="user_name" maxlength="<?= C\NAME_LEN ?>"
value="<?= $data['USER']['USER_NAME'] ?>"
class="narrow-field" disabled="disabled" ></td>
</tr>
<tr><th class="table-label"><label for="first-name"><?php
e(tl('manageaccount_element_firstname')); ?>:</label></th>
<td><input type="text" id="first-name"
name="FIRST_NAME" maxlength="<?= C\NAME_LEN?>"
value="<?php e($data['USER']['FIRST_NAME']); ?>"
class="narrow-field" <?php e($disabled);?> ></td></tr>
<tr><th class="table-label"><label for="last-name"><?php
e(tl('manageaccount_element_lastname')); ?>:</label></th>
<td><input type="text" id="last-name"
name="LAST_NAME" maxlength="<?= C\NAME_LEN ?>"
value="<?php e($data['USER']['LAST_NAME']); ?>"
class="narrow-field" <?php e($disabled);?> ></td></tr>
<tr><th class="table-label"><label for="e-mail"><?php
e(tl('manageaccount_element_email')); ?>:</label></th>
<td><input type="email" id="e-mail"
name="EMAIL" maxlength="<?= C\LONG_NAME_LEN ?>"
<?php e($disabled);?>
value="<?php e($data['USER']['EMAIL']); ?>"
class="narrow-field" ></td></tr>
<tr>
<th class="table-label"><label for="locale"><b><?=
tl('options_element_language_label')
?></b></label></th>
<td><?php
$this->view->element("language")->render($data); ?></td>
</tr><?php
if (!empty($data['SELLABLE_ROLES_EXIST'])) { ?>
<tr>
<th class="table-label align-top"><label><b><?=
tl('accountaccess_component_roles_label')
?></b></label></th>
<td><div class="role-list"><?php
$sellable = [];
foreach ($data['USER_SELLABLE_ROLES'] as $sub_role) {
$sellable[(int)$sub_role['ROLE_ID']] = $sub_role;
}
$now = time();
$role_parts = [];
foreach ($data['USER_ROLE_LIST'] as $held_role) {
$name = htmlentities($held_role['ROLE_NAME']);
$held_id = (int)$held_role['ROLE_ID'];
if (empty($sellable[$held_id])) {
$role_parts[] = $name;
continue;
}
$sub = $sellable[$held_id];
$expires = (int)$sub['EXPIRES'];
if ((int)$sub['WILL_RENEW'] === 0 &&
$expires !== C\FOREVER && $expires > $now) {
$on_url = $base_url . "&arg=purchaserole" .
"&purchase_role_id=" . $held_id .
"&edit=true";
$when = date("Y-m-d", $expires);
$confirm = tl(
'accountaccess_component_confirm_resubscribe');
$role_parts[] = $name . " (<a href=\"" . $on_url .
"\" onclick=\"return confirm('" . $confirm .
"');\">" .
tl('accountaccess_component_role_expires',
$when) . "</a>)";
} else {
$off_url = $base_url .
"&arg=unsubscriberole" .
"&unsubscribe_role_id=" . $held_id .
"&edit=true";
$confirm = tl(
'accountaccess_component_confirm_unsubscribe');
$role_parts[] = "<a href=\"" . $off_url .
"\" onclick=\"return confirm('" . $confirm .
"');\">" . $name . "</a>";
}
}
echo implode(", ", $role_parts);
?><br>
<a href="<?= $base_url . "&edit_purchase=true" ?>"><?=
tl('accountaccess_component_purchase_new_roles')
?></a></div></td>
</tr><?php
}
if (!empty($data['yioop_bot_configuration'])) {
?>
<tr>
<th class="table-label"><label for="is_bot"><?php
e(tl('manageaccount_element_is_bot'));
?></label></th>
<td><input type="checkbox" id="is_bot"
name="IS_BOT_USER" value="true"
<?php if (!empty($data['USER']['IS_BOT_USER'])
&& $data['USER']['IS_BOT_USER'] == true) {
e("checked='checked'");
} ?>
>
</td></tr><?php
if ($data['USER']['IS_BOT_USER'] == true) { ?>
<tr><th class="table-label">
<label for="bot-unique-token"><?php
e(tl('manageaccount_element_bot_unique_token'))
?></label></th>
<td><input type="text" id="bot-unique-token"
name="BOT_TOKEN" value="<?php
e($data['USER']['BOT_TOKEN']); ?>"
class="narrow-field" >
</td>
</tr>
<tr>
<th class="table-label">
<label for="bot-callback-url"><?php
e(tl('manageaccount_element_bot_callback_url'));
?></label></th>
<td><input type="text" id="bot-callback-url"
name="BOT_CALLBACK_URL" value="<?php
e($data['USER']['CALLBACK_URL']); ?>"
class="narrow-field" >
</td>
</tr>
<?php
}
} ?>
<tr><th class="table-label"><label for="password"><?php
e(tl('manageaccount_element_password'))?></label></th>
<td><input type="password" id="password"
name="password" maxlength="<?= C\LONG_NAME_LEN
?>" class="narrow-field" >
</td></tr><?php
} else if (!empty($data['EDIT_PASSWORD']) &&
empty($_SESSION['LDAP_NAME'])) { ?>
<tr><th class="table-label"><label for="password"><?php
e(tl('manageaccount_element_password'))?></label></th>
<td><input type="password" id="password"
name="password" maxlength="<?= C\LONG_NAME_LEN
?>" class="narrow-field" >
</td></tr>
<tr><th class="table-label"><label for="new-password"><?php
e(tl('manageaccount_element_new_password'))?></label></th>
<td><input type="password" id="new-password"
name="new_password" maxlength="<?=
C\LONG_NAME_LEN?>" class="narrow-field" ><?php
$this->view->helper("passwordrequirements")->render(
"new-password"); ?>
</td></tr>
<tr><th class="table-label"><label for="retype-password"><?php
e(tl('manageaccount_element_retype_password'));
?></label></th>
<td><input type="password" id="retype-password"
name="retype_password" maxlength="<?=
C\LONG_NAME_LEN?>" class="narrow-field" >
</td></tr><?php
} else if (empty($_SESSION['LDAP_NAME'])) {
if (C\p('RECOVERY_MODE') == C\QUESTIONS_RECOVERY) {
$recovery_question = $data['RECOVERY_QUESTION'] ?? "";
$recovery_answer = $data['RECOVERY_ANSWER'] ?? "";
?>
<tr><th class="table-label"><label
for="recovery-question"><?php
e(tl('manageaccount_element_recovery_question'));
?></label></th>
<td class="table-input border-top">
<input type="text" id="recovery-question"
name="recovery_question" maxlength="<?=
C\RECOVERY_QUESTION_LEN ?>" class="narrow-field"
value="<?= $recovery_question ?>" >
</td></tr>
<tr><th class="table-label"><label
for="recovery-answer"><?php
e(tl('manageaccount_element_recovery_answer'));
?></label></th>
<td class="table-input">
<input type="text" id="recovery-answer"
name="recovery_answer" maxlength="<?=
C\LONG_NAME_LEN ?>" class="narrow-field"
value="<?= $recovery_answer ?>" >
</td></tr><?php
}?>
<tr><th class="table-label"><label for="password"><?php
e(tl('manageaccount_element_password'))?></label></th>
<td><input type="password" id="password"
name="password" maxlength="<?= C\LONG_NAME_LEN
?>" class="narrow-field" >
</td></tr><?php
}?>
<tr><td></td>
<td class="center"><button
class="button-box" type="submit"><?php
e(tl('manageaccount_element_save')); ?></button></td></tr><?php
if (empty($data['EDIT_PASSWORD']) && empty($data['EDIT_RECOVERY'])
&& empty($_SESSION['LDAP_NAME'])) { ?>
<tr><td> </td><td></td></tr>
<tr><td></td><td><a href="<?php
e($password_or_no_url);?>"><?php
e(tl('manageaccount_element_change_password'))?></a>
</td></tr><?php
if (C\p('RECOVERY_MODE') == C\QUESTIONS_RECOVERY) {?>
<tr><td></td><td><a href="<?php
e($recover_or_no_url);?>"><?php
e(tl('manageaccount_element_change_recovery'))?></a>
</td></tr><?php
}
} ?>
</table>
</form><?php
if (!empty($data['EDIT_PURCHASE'])) { ?>
<form id="purchaseRoleForm" method="post"
class="account-details">
<input type="hidden" name="c" value="admin" >
<input type="hidden" name="<?= C\p('CSRF_TOKEN') ?>" value="<?=
$data[C\p('CSRF_TOKEN')] ?>" >
<input type="hidden" name="a" value="manageAccount" >
<input type="hidden" name="arg" value="purchaserole" >
<input type="hidden" name="edit_purchase" value="true" >
<h2><?= tl('accountaccess_component_purchase_new_roles') ?></h2>
<p><?= tl('accountaccess_component_credit_balance',
$data['CREDIT_BALANCE']) ?></p><?php
if (empty($data['PURCHASABLE_ROLES'])) { ?>
<p><?= tl('accountaccess_component_no_roles_to_buy')
?></p><?php
} else { ?>
<table class="name-table">
<tr><th class="table-label"><label
for="purchase_role_id"><b><?=
tl('accountaccess_component_choose_role')
?></b></label></th>
<td><select id="purchase_role_id"
name="purchase_role_id"><?php
foreach ($data['PURCHASABLE_ROLES'] as $buy_role) { ?>
<option value="<?= (int)$buy_role['ROLE_ID'] ?>"><?php
e($buy_role['NAME'] . " - " .
$buy_role['ROLE_COST']);
?></option><?php
} ?>
</select></td></tr>
<tr><td></td><td><button type="submit"><?=
tl('accountaccess_component_buy_role')
?></button></td></tr>
</table><?php
} ?>
</form><?php
} ?>
</div>
</div><?php
}
}