You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
399 lines
27 KiB
399 lines
27 KiB
<?php
|
|
if (file_exists(__DIR__."/../../pp-config.php")) {
|
|
if (file_exists(__DIR__.'/../../maintenance.lock')) {
|
|
if (file_exists(__DIR__.'/../../pp-include/pp-maintenance.php')) {
|
|
|
|
}else{
|
|
die('System is under maintenance. Please try again later.');
|
|
}
|
|
exit();
|
|
}else{
|
|
if (file_exists(__DIR__.'/../../pp-include/pp-controller.php')) {
|
|
if (file_exists(__DIR__.'/../../pp-include/pp-view.php')) {
|
|
|
|
}else{
|
|
echo 'System is under maintenance. Please try again later.';
|
|
exit();
|
|
}
|
|
}else{
|
|
echo 'System is under maintenance. Please try again later.';
|
|
exit();
|
|
}
|
|
|
|
if (file_exists(__DIR__.'/../../pp-include/pp-model.php')) {
|
|
include(__DIR__."/../../pp-include/pp-model.php");
|
|
}else{
|
|
echo 'System is under maintenance. Please try again later.';
|
|
exit();
|
|
}
|
|
}
|
|
}else{
|
|
echo 'System is under maintenance. Please try again later.';
|
|
exit();
|
|
}
|
|
|
|
if (!defined('pp_allowed_access')) {
|
|
die('Direct access not allowed');
|
|
}
|
|
|
|
if(isset($global_user_login) && $global_user_login == true){
|
|
?>
|
|
<style>
|
|
.plugin-card {
|
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
border-radius: 0.5rem;
|
|
overflow: hidden;
|
|
}
|
|
.plugin-card:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.1);
|
|
}
|
|
.plugin-icon {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 0.5rem;
|
|
font-size: 1.5rem;
|
|
}
|
|
.plugin-icon img{
|
|
height: 40px;
|
|
}
|
|
.status-badge {
|
|
font-size: 0.65rem;
|
|
letter-spacing: 0.5px;
|
|
padding: 3px 6px;
|
|
}
|
|
.nav-pills .nav-link.active {
|
|
|
|
}
|
|
.nav-pills .nav-link {
|
|
color: #495057;
|
|
font-weight: 500;
|
|
}
|
|
.tab-content {
|
|
background: #fff;
|
|
border-radius: 0 0.5rem 0.5rem 0.5rem;
|
|
}
|
|
.search-box {
|
|
position: relative;
|
|
}
|
|
.search-box .form-control {
|
|
padding-left: 2.5rem;
|
|
border-radius: 2rem;
|
|
}
|
|
.search-box .bi {
|
|
position: absolute;
|
|
left: 1rem;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
color: #6c757d;
|
|
}
|
|
.plugin-actions .btn {
|
|
padding: 0.25rem 0.5rem;
|
|
font-size: 0.8rem;
|
|
}
|
|
</style>
|
|
|
|
<div class="row">
|
|
<div class="col-lg-12 mx-auto">
|
|
<div class="card border-0 shadow-sm">
|
|
<div class="card-header bg-white border-0 pb-0">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h1 class="h4 mb-0">
|
|
<i class="bi bi-plug me-2 text-primary"></i>Theme Manager
|
|
</h1>
|
|
<button class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#add-new-plugins">
|
|
<i class="bi bi-plus-lg me-1"></i> Add New
|
|
</button>
|
|
</div>
|
|
|
|
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link active" id="pills-gateway-tab" data-bs-toggle="pill" data-bs-target="#pills-gateway" type="button" role="tab">
|
|
<i class="bi bi-check-circle me-1"></i> Installed (<span class="gateway-count">0</span>)
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<span class="response-action"></span>
|
|
|
|
<div class="card-body pt-0">
|
|
<div class="tab-content" id="pills-tabContent">
|
|
<!-- Installed Plugins Tab -->
|
|
<div class="tab-pane fade show active" id="pills-gateway" role="tabpanel">
|
|
<div class="row mb-4">
|
|
<div class="col-md-6">
|
|
<div class="search-box">
|
|
<i class="bi bi-search"></i>
|
|
<input type="text" class="form-control" id="gatewaysSearch" onkeyup="filterGateways(currentFilter)"placeholder="Search installed gateway themes...">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="d-flex justify-content-end">
|
|
<div class="btn-group" role="group">
|
|
<button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle" data-bs-toggle="dropdown">
|
|
<i class="bi bi-funnel me-1"></i> Filter
|
|
</button>
|
|
<ul class="dropdown-menu dropdown-menu-end">
|
|
<li><a class="dropdown-item" href="#" onclick="filterGateways('all')">All Themes</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item" href="#" onclick="filterGateways('active')">Active Only</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="filterGateways('inactive')">Inactive Only</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-4">
|
|
<?php
|
|
$baseDir = __DIR__.'/../../pp-content/themes/';
|
|
|
|
$mainFolders = array_filter(scandir($baseDir), function($item) use ($baseDir) {
|
|
return $item !== '.' && $item !== '..' && is_dir($baseDir . DIRECTORY_SEPARATOR . $item);
|
|
});
|
|
|
|
$foundThemes = false;
|
|
|
|
$installed_count = 0;
|
|
|
|
foreach ($mainFolders as $mainFolder) {
|
|
$themeBasePath = $baseDir . DIRECTORY_SEPARATOR . $mainFolder;
|
|
|
|
$themeFolders = array_filter(scandir($themeBasePath), function($item) use ($themeBasePath) {
|
|
return $item !== '.' && $item !== '..' && is_dir($themeBasePath . DIRECTORY_SEPARATOR . $item);
|
|
});
|
|
|
|
foreach ($themeFolders as $themeFolder) {
|
|
$mainLocation = $themeBasePath . DIRECTORY_SEPARATOR . $themeFolder. DIRECTORY_SEPARATOR;
|
|
|
|
$mainFile = $themeBasePath . DIRECTORY_SEPARATOR . $themeFolder . DIRECTORY_SEPARATOR . $themeFolder . '-class.php';
|
|
|
|
if (file_exists($mainFile)) {
|
|
$foundThemes = true;
|
|
$themeInfo = parseThemeHeader($mainFile);
|
|
|
|
$plugin_rand = rand();
|
|
|
|
$installed_count = $installed_count+1;
|
|
?>
|
|
<!-- Plugin Card 1 -->
|
|
<div class="col-md-6 col-lg-4 plugin-items <?php if($global_setting_response['response'][0]['gateway_theme'] == $themeFolder){echo "active";}else{echo "inactive";}?>plugins">
|
|
<div class="plugin-card card h-100 border">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-start mb-3">
|
|
<div class="plugin-icon bg-primary bg-opacity-10 text-primary me-3">
|
|
<img src="https://<?php echo $_SERVER['HTTP_HOST']?>/pp-content/themes/<?php echo $mainFolder.'/'.$themeFolder?>/assets/icon.png" alt="Image Description">
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<h5 class="mb-1"><?php echo htmlspecialchars($themeInfo['Theme Name'] ?? '')?></h5>
|
|
<p class="text-primary small mb-2" onclick="location.href='<?php echo htmlspecialchars($themeInfo['Author URI'] ?? '')?>'" style="cursor: pointer;">v<?php echo htmlspecialchars($themeInfo['Version'] ?? '')?> by <?php echo htmlspecialchars($themeInfo['Author'] ?? '')?></p>
|
|
<?php
|
|
if($global_setting_response['response'][0]['gateway_theme'] == $themeFolder){
|
|
?>
|
|
<span class="badge bg-success status-badge me-1">Active</span>
|
|
<?php
|
|
}else{
|
|
?>
|
|
<span class="badge bg-danger status-badge me-1">Inactive</span>
|
|
<?php
|
|
}
|
|
?>
|
|
</div>
|
|
</div>
|
|
<p class="small text-muted mb-3"><?php echo htmlspecialchars($themeInfo['Description'] ?? '')?></p>
|
|
|
|
<div class="plugin-actions d-flex justify-content-between border-top pt-3">
|
|
<button class="btn btn-outline-secondary btn-sm" data-bs-toggle="modal" data-bs-target="#themeDetailsModal<?php echo $plugin_rand?>">
|
|
<i class="bi bi-info-circle me-1"></i> Details
|
|
</button>
|
|
|
|
<?php
|
|
if($global_setting_response['response'][0]['gateway_theme'] !== $themeFolder){
|
|
?>
|
|
<button class="btn btn-outline-success btn-sm btn-activate<?php echo $plugin_rand?>" onclick="pluginhit('btn-activate<?php echo $plugin_rand?>', 'activate', '<?php echo $mainFolder?>', '<?php echo $themeFolder?>', 'themeDetailsModal<?php echo $plugin_rand?>')">
|
|
<i class="bi bi-power me-1"></i> Activate
|
|
</button>
|
|
<?php
|
|
}
|
|
?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Plugin Details Modal -->
|
|
<div class="modal fade" id="themeDetailsModal<?php echo $plugin_rand?>" tabindex="-1" aria-labelledby="themeDetailsModalLabel<?php echo $plugin_rand?>" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="themeDetailsModalLabel<?php echo $plugin_rand?>">Theme Details</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<h4><?php echo htmlspecialchars($themeInfo['Theme Name'] ?? '')?></h4>
|
|
|
|
<?php
|
|
if (file_exists($mainLocation.'readme.txt')) {
|
|
$content = file_get_contents($mainLocation.'readme.txt');
|
|
$sections = parse_readme_sections($content);
|
|
|
|
$pluginHeader = parse_readme_header($content);
|
|
|
|
$tags = [];
|
|
if (!empty($pluginHeader['tags'])) {
|
|
$tags = array_map('trim', explode(',', $pluginHeader['tags']));
|
|
}
|
|
?>
|
|
<p class="text-muted"><?php echo htmlspecialchars($themeInfo['Description'] ?? '')?></p>
|
|
|
|
<div class="d-flex flex-wrap gap-2 mb-4">
|
|
<?php foreach ($tags as $tag): ?>
|
|
<span class="badge bg-primary"><?php echo htmlspecialchars($tag); ?></span>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<h5>Description</h5>
|
|
<p><?php echo nl2br(htmlspecialchars($sections['description'] ?? 'N/A')); ?></p>
|
|
|
|
<h5 class="mt-4">Changelog</h5>
|
|
<?php
|
|
$changelogData = parse_readme_changelog($sections['changelog'] ?? '');
|
|
?>
|
|
<div class="accordion" id="changelogAccordion">
|
|
<?php
|
|
$index = 0;
|
|
foreach ($changelogData as $version => $items):
|
|
$isFirst = ($index === 0);
|
|
$collapseId = 'changelog' . $index;
|
|
?>
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header">
|
|
<button class="accordion-button <?php echo $isFirst ? '' : 'collapsed'; ?>" type="button" data-bs-toggle="collapse" data-bs-target="#<?php echo $collapseId; ?>">
|
|
Version <?php echo htmlspecialchars($version); ?><?php echo $isFirst ? ' (Current)' : ''; ?>
|
|
</button>
|
|
</h2>
|
|
<div id="<?php echo $collapseId; ?>" class="accordion-collapse collapse <?php echo $isFirst ? 'show' : ''; ?>" data-bs-parent="#changelogAccordion">
|
|
<div class="accordion-body small">
|
|
<ul>
|
|
<?php foreach ($items as $item): ?>
|
|
<li><?php echo htmlspecialchars($item); ?></li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
$index++;
|
|
endforeach;
|
|
?>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
<?php
|
|
if($global_setting_response['response'][0]['gateway_theme'] !== $themeFolder){
|
|
?>
|
|
<button type="button" class="btn btn-primary btn-activate<?php echo $plugin_rand?>-popup" onclick="pluginhit('btn-activate<?php echo $plugin_rand?>-popup', 'activate', '<?php echo $mainFolder?>', '<?php echo $themeFolder?>', 'themeDetailsModal<?php echo $plugin_rand?>')">Activate</button>
|
|
<?php
|
|
}
|
|
?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$foundThemes) {
|
|
?>
|
|
<div class="col-md-12 col-lg-12">
|
|
<div class="alert alert-danger"><i class="bi bi-info-circle-fill me-2"></i> No themes available</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<script>
|
|
function initialize(){
|
|
document.querySelector(".gateway-count").innerHTML = "<?php echo $installed_count?>";
|
|
|
|
let currentFilter = "all"; // Track current type globally
|
|
}
|
|
initialize();
|
|
|
|
function filterGateways(type) {
|
|
currentFilter = type;
|
|
const search = document.getElementById('gatewaysSearch').value.toLowerCase();
|
|
|
|
document.querySelectorAll('.plugin-items').forEach(el => {
|
|
const name = el.querySelector('h5')?.textContent.toLowerCase() || '';
|
|
|
|
const matchesType = (type === "all") || el.classList.contains(type + "plugins");
|
|
const matchesSearch = name.includes(search);
|
|
|
|
if (matchesType && matchesSearch) {
|
|
el.style.display = 'block';
|
|
} else {
|
|
el.style.display = 'none';
|
|
}
|
|
});
|
|
}
|
|
|
|
function pluginhit(btn, type, mainfolder, themesfolder, model){
|
|
var btn_value = document.querySelector("."+btn).innerHTML;
|
|
|
|
$("."+btn).html('<div class="spinner-border spinner-border-sm" role="status"> <span class="visually-hidden">Loading...</span> </div>');
|
|
$("."+btn).prop("disabled", true);
|
|
|
|
$.ajax
|
|
({
|
|
type: "POST",
|
|
url: "https://<?php echo $_SERVER['HTTP_HOST']?>/admin/appearance-themes",
|
|
data: { "action": "pp_appearance_themes_manager", "type": type, "mainfolder": mainfolder, "themesfolder": themesfolder},
|
|
success: function (data) {
|
|
console.log(data);
|
|
$("."+btn).prop("disabled", false);
|
|
$("."+btn).html(btn_value);
|
|
|
|
$('#'+model).modal('hide');
|
|
|
|
var dedata = JSON.parse(data);
|
|
|
|
if(dedata.status == "false"){
|
|
document.querySelector(".response-action").innerHTML = '<div class="alert alert-danger" style="margin-top:10px;margin-bottom:10px"> <i class="fa fa-info-circle me-2"></i> '+dedata.message+'</div>';
|
|
}else{
|
|
$('#'+model).modal('hide');
|
|
|
|
load_content('Appearance','appearance-themes','nav-btn-appearance');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
<?php
|
|
}
|
|
?>
|