Skip to content

Commit

Permalink
Refactor header navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
carlbennett committed Jun 27, 2021
1 parent 39db81c commit 016e253
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 106 deletions.
51 changes: 51 additions & 0 deletions src/libraries/NewsPost.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,45 @@ public static function getAllNews($reverse) {
return null;
}

public static function getNewsPostsByLastEdited(int $count)
{
if (!isset(Common::$database))
{
Common::$database = DatabaseDriver::getDatabaseObject();
}

$stmt = Common::$database->prepare(
'SELECT
`category_id`,
`content`,
`created_datetime`,
`edited_count`,
`edited_datetime`,
`id`,
`options_bitmask`,
`title`,
`user_id`
FROM `news_posts`
ORDER BY IFNULL(`edited_datetime`, `created_datetime`) DESC
LIMIT ' . $count . ';'
);

$r = $stmt->execute();
if (!$r)
{
throw new QueryException('Cannot query news posts by last edited');
}

$r = [];
while ($row = $stmt->fetch(PDO::FETCH_OBJ))
{
$r[] = new self($row);
}

$stmt->closeCursor();
return $r;
}

public static function getNewsPostsByUserId($user_id) {
if (!isset(Common::$database)) {
Common::$database = DatabaseDriver::getDatabaseObject();
Expand Down Expand Up @@ -283,6 +322,18 @@ public function getUserId() {
return $this->user_id;
}

public function isMarkdown() {
return ($this->options_bitmask & self::OPTION_MARKDOWN);
}

public function isPublished() {
return ($this->options_bitmask & self::OPTION_PUBLISHED);
}

public function isRSSExempt() {
return ($this->options_bitmask & self::OPTION_RSS_EXEMPT);
}

protected static function normalize(StdClass &$data) {
$data->category_id = (int) $data->category_id;
$data->content = (string) $data->content;
Expand Down
273 changes: 167 additions & 106 deletions src/templates/header.inc.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ namespace BNETDocs\Templates;
use \BNETDocs\Libraries\Authentication;
use \BNETDocs\Libraries\Document;
use \BNETDocs\Libraries\Logger;
use \BNETDocs\Libraries\NewsPost;
use \BNETDocs\Libraries\Packet;
use \BNETDocs\Libraries\User;
use \BNETDocs\Libraries\VersionInfo;
use \CarlBennett\MVC\Libraries\Common;
use \CarlBennett\MVC\Libraries\DatabaseDriver;
use \LogicException;
$_header_user = Authentication::$user;
if (!isset($title))
{
throw new LogicException('template variable not set before include of header template: $title');
Expand All @@ -28,20 +28,7 @@ function _header_active($url, $sr)
else
return ' active';
}
if (isset(Authentication::$user))
{
$_header_user = Authentication::$user;
$_header_user_url = $_header_user->getURI();
$_header_staff = ($_header_user && $_header_user->isStaff());
} else {
$_header_user = null;
$_header_user_url = null;
$_header_staff = null;
}
$_header_documents = Document::getDocumentsByLastEdited(10);
$_header_packets = Packet::getPacketsByLastEdited(10);
$_header_navigation_config = Common::$config->bnetdocs->navigation;
$_header_user_register_disabled = Common::$config->bnetdocs->user_register_disabled;
$_header_user = Authentication::$user;
$_unique_asset = (
!Common::$config->bnetdocs->asset_versioning ? '' :
(
Expand All @@ -50,6 +37,170 @@ $_unique_asset = (
'?v=' . date('YmdHis')
)
);
$_header_nav = [
['label' => 'Welcome', 'url' => '/welcome'],
['label' => 'Community', 'dropdown' => [
['label' => 'Discord', 'url' => '/discord', 'visible' => (Common::$config->discord->enabled)],
['label' => '-', 'visible' => (Common::$config->discord->enabled)],
['label' => 'Contributors', 'url' => '/credits'],
['label' => 'Donate to Us', 'url' => '/donate'],
['label' => 'Server List', 'url' => '/servers'],
['label' => 'Users', 'url' => '/user/index'],
['label' => '-'],
['label' => 'Privacy Notice', 'url' => '/privacy'],
['label' => 'Disclaimer & TOS', 'url' => '/legal'],
['label' => '-'],
['label' => 'File Archive', 'url' => 'https://files.bnetdocs.org/'],
['label' => 'BNETDocs Redux', 'url' => 'https://redux.bnetdocs.org/'],
]],
['label' => 'Documents', 'dropdown' => [
['label' => 'All Documents', 'url' => '/document/index', 'class' => 'text-info'],
['label' => '-'],
['label' => 'Create Document', 'url' => '/document/create', 'class' => 'text-success', 'acl' => User::OPTION_ACL_DOCUMENT_CREATE],
['label' => '-', 'acl' => User::OPTION_ACL_DOCUMENT_CREATE],
['label' => '', 'recent_documents' => true],
]],
['label' => 'News', 'dropdown' => [
['label' => 'All News', 'url' => '/news', 'class' => 'text-info'],
['label' => '-'],
['label' => 'Create News Post', 'url' => '/news/create', 'class' => 'text-success', 'acl' => User::OPTION_ACL_NEWS_CREATE],
['label' => '-', 'acl' => User::OPTION_ACL_NEWS_CREATE],
['label' => '', 'recent_news' => true],
]],
['label' => 'Packets', 'dropdown' => [
['label' => 'All Packets', 'url' => '/packet/index', 'class' => 'text-info'],
['label' => '-'],
['label' => 'Create Packet', 'url' => '/packet/create', 'class' => 'text-success', 'acl' => User::OPTION_ACL_PACKET_CREATE],
['label' => '-', 'acl' => User::OPTION_ACL_PACKET_CREATE],
['label' => '', 'recent_packets' => true],
]],
['label' => 'Admin', 'acl' => User::OPTION_ACL_SERVER_CREATE | User::OPTION_ACL_EVENT_LOG_VIEW, 'class' => 'text-danger', 'dropdown' => [
['label' => 'Create Server', 'url' => '/server/create', 'class' => 'text-success', 'acl' => User::OPTION_ACL_SERVER_CREATE],
['label' => 'Event Logs', 'url' => '/eventlog/index', 'acl' => User::OPTION_ACL_EVENT_LOG_VIEW],
]],
];
/* <a>Account</a>
<a href="<?=Common::relativeUrlToAbsolute('/user/changepassword')?>">Change Password</a>
<a href="<?=Common::relativeUrlToAbsolute('/user/update')?>">Update Profile</a>*/
function _header_nav_html($nav)
{
function _line(string $format) { call_user_func_array('printf', func_get_args()) . PHP_EOL; }

ob_start();
_line('<nav class="navbar navbar-expand-lg navbar-dark bg-primary mb-3">');

// Brand
_line('<a class="navbar-brand" style="color:#00ccad;" href="%s"><img class="float-left mr-2" src="%s" style="height:32px;" /> %s</a>',
Common::$config->bnetdocs->navigation->front_page, '/a/VSZX0bJ.png', 'BNETDocs'
);

// Collapsible Hamburger Menu (Start)
_line('<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>');
_line('<div class="collapse navbar-collapse" id="navbarSupportedContent">');

// Navbar (Start)
_line('<ul class="navbar-nav mr-auto">');

function _nav_loop(array $nav, bool $dropdown)
{
foreach ($nav as $item)
{
if (!isset($item['label'])) continue;
if (isset($item['visible']) && !$item['visible']) continue;

if (isset($item['acl']))
{
if (!Authentication::$user) continue;
if (!(Authentication::$user->getOptionsBitmask() & $item['acl'])) continue;
}

if ($item['label'] == '-') { _line('<div class="dropdown-divider"></div>'); continue; }

$class = $item['class'] ?? '';
if (!empty($class)) $class = ' ' . $class;

if (isset($item['recent_documents']) && $item['recent_documents'])
{
_line('<div class="dropdown-header">Recently Edited Documents</div>');
$recent_documents = Document::getDocumentsByLastEdited(10);
$acl_doc_modify = (Authentication::$user && (Authentication::$user->getOptionsBitmask() & User::OPTION_ACL_DOCUMENT_MODIFY));
foreach ($recent_documents as $doc)
{
if (!$doc->isPublished() && !$acl_doc_modify) continue;
$doc_class = ($doc->isPublished() ? '' : ' text-warning');
_line('<a class="dropdown-item%s" href="%s">%s</a>', $doc_class, $doc->getURI(), filter_var($doc->getTitle(), FILTER_SANITIZE_FULL_SPECIAL_CHARS));
}
}
else if (isset($item['recent_news']) && $item['recent_news'])
{
_line('<div class="dropdown-header">Recent News</div>');
$recent_news = NewsPost::getNewsPostsByLastEdited(10);
$acl_news_modify = (Authentication::$user && (Authentication::$user->getOptionsBitmask() & User::OPTION_ACL_NEWS_MODIFY));
foreach ($recent_news as $news)
{
if (!$news->isPublished() && !$acl_neews_modify) continue;
$news_class = ($news->isPublished() ? '' : ' text-warning');
_line('<a class="dropdown-item%s" href="%s">%s</a>', $news_class, $news->getURI(), filter_var($news->getTitle(), FILTER_SANITIZE_FULL_SPECIAL_CHARS));
}
}
else if (isset($item['recent_packets']) && $item['recent_packets'])
{
_line('<div class="dropdown-header">Recently Edited Packets</div>');
$recent_packets = Packet::getPacketsByLastEdited(10);
$acl_pkt_modify = (Authentication::$user && (Authentication::$user->getOptionsBitmask() & User::OPTION_ACL_PACKET_MODIFY));
foreach ($recent_packets as $pkt)
{
if (!$pkt->isPublished() && !$acl_pkt_modify) continue;
$pkt_class = ($pkt->isPublished() ? '' : ' text-warning');
_line('<a class="dropdown-item%s" href="%s">%s</a>', $pkt_class, $pkt->getURI(), filter_var($pkt->getName(), FILTER_SANITIZE_FULL_SPECIAL_CHARS));
}
}
else if (!$dropdown)
{
if (isset($item['url'])) printf('<li class="nav-item"><a class="nav-link%s" href="%s">%s</a></li>' . PHP_EOL, $class, $item['url'], filter_var($item['label'], FILTER_SANITIZE_FULL_SPECIAL_CHARS));
}
else if ($dropdown)
{
if (isset($item['url'])) printf('<a class="dropdown-item%s" href="%s">%s</a>' . PHP_EOL, $class, $item['url'], filter_var($item['label'], FILTER_SANITIZE_FULL_SPECIAL_CHARS));
}

if (isset($item['dropdown']))
{
_line('<li class="nav-item dropdown">');
$navbarName = str_replace(' ', '_', $item['label']);
_line('<a class="nav-link dropdown-toggle%s" href="#" id="navbar%sDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">%s</a>', $class, $navbarName, $item['label']);
_line('<div class="dropdown-menu" aria-labelledby="navbar%sDropdown">', $navbarName);
_nav_loop($item['dropdown'], true);
_line('</div></li>');
}
}
}
_nav_loop($nav, false);

// Navbar (End)
_line('</ul>');

// Account
if (!Authentication::$user)
{
_line('<a class="btn btn-sm btn-outline-secondary my-2 my-sm-0" tabindex="-1" href="%s">Log in</a>', Common::relativeUrlToAbsolute('/user/login'));
if (!Common::$config->bnetdocs->user_register_disabled)
{
_line('<a class="btn btn-sm btn-outline-success my-2 my-sm-0 ml-2" tabindex="-2" href="%s">Register</a>', Common::relativeUrlToAbsolute('/user/register'));
}
}
else
{
_line('<span class="nav-item navbar-text mx-3"><a href="%s">%s</a></span>', Authentication::$user->getURI(), filter_var(Authentication::$user->getName(), FILTER_SANITIZE_FULL_SPECIAL_CHARS));
_line('<a class="btn btn-sm btn-outline-danger my-2 my-sm-0" tabindex="-1" href="%s">Log out</a>', Common::relativeUrlToAbsolute('/user/logout'));
}

// Collapsible Hamburger Menu (End)
_line('</div>');

_line('</nav>');
return ob_get_clean();
}
/*$_campaign_battleforthenet = (
!empty( Common::$config->bnetdocs->campaigns->battleforthenet ) ?
'<script type="text/javascript" src="' .
Expand Down Expand Up @@ -114,95 +265,5 @@ $_campaign_vultr = (
</head>
<body class="d-flex flex-column h-100">

<nav class="navbar navbar-expand-lg navbar-dark bg-primary mb-3">
<a class="navbar-brand" style="color:#00ccad;" href="<?=Common::relativeUrlToAbsolute($_header_navigation_config->front_page)?>"><img src="<?=Common::relativeUrlToAbsolute('/a/VSZX0bJ.png')?>" style="float:left;margin-right:6px;height:32px;"/> BNETDocs</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item<?=_header_active('/welcome', false)?>">
<a class="nav-link" href="<?=Common::relativeUrlToAbsolute('/welcome')?>">Welcome<?=_header_active('/welcome', true)?></a>
</li>
<? if (Common::$config->discord->enabled) { ?>
<li class="nav-item<?=_header_active('/discord', false)?>">
<a class="nav-link" href="<?=Common::relativeUrlToAbsolute('/discord')?>">Discord<?=_header_active('/discord', true)?></a>
</li>
<? } ?>
<li class="nav-item<?=_header_active('/document/', false)?> dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDocumentsDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Documents</a>
<div class="dropdown-menu" aria-labelledby="navbarDocumentsDropdown">
<a class="dropdown-item<?=_header_active('/document/index', false)?> text-info" href="<?=Common::relativeUrlToAbsolute('/document/index')?>">All Documents<?=_header_active('/document/index', true)?></a>
<? if ($_header_staff) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item<?=_header_active('/document/create', false)?> text-success" href="<?=Common::relativeUrlToAbsolute('/document/create')?>">Create Document<?=_header_active('/document/create', true)?></a>
<div class="dropdown-divider"></div>
<? }?>
<div class="dropdown-header">Recently Edited Documents</div>
<? foreach ($_header_documents as $doc) { $doc_url_part = '/document/' . $doc->getId(); ?>
<a class="dropdown-item<?=_header_active($doc_url_part, false)?>" href="<?=$doc->getURI()?>"><?=filter_var($doc->getTitle(), FILTER_SANITIZE_FULL_SPECIAL_CHARS)?><?=_header_active($doc_url_part, true)?></a>
<? } ?>
</div>
</li>
<li class="nav-item<?=_header_active('/packet/', false)?> dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarPacketsDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Packets</a>
<div class="dropdown-menu" aria-labelledby="navbarPacketsDropdown">
<a class="dropdown-item<?=_header_active('/packet/index', false)?> text-info" href="<?=Common::relativeUrlToAbsolute('/packet/index')?>">All Packets<?=_header_active('/packet/index', true)?></a>
<? if ($_header_staff) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item<?=_header_active('/packet/create', false)?> text-success" href="<?=Common::relativeUrlToAbsolute('/packet/create')?>">Create Packet<?=_header_active('/packet/create', true)?></a>
<div class="dropdown-divider"></div>
<? }?>
<div class="dropdown-header">Recently Edited Packets</div>
<? foreach ($_header_packets as $pkt) { $pkt_url_part = '/packet/' . $pkt->getId(); ?>
<a class="dropdown-item<?=_header_active($pkt_url_part, false)?>" href="<?=$pkt->getURI()?>"><?=filter_var($pkt->getName(), FILTER_SANITIZE_FULL_SPECIAL_CHARS)?><?=_header_active($pkt_url_part, true)?></a>
<? } ?>
</div>
</li>
</ul>
<? if (!$_header_user) { ?>
<a class="btn btn-sm btn-outline-success my-2 my-sm-0" tabindex="-1" href="<?=Common::relativeUrlToAbsolute('/user/login?return=' . rawurlencode((getenv('REQUEST_URI') == '/user/logout' ? '/tools' : getenv('REQUEST_URI'))))?>">Log in</a>
<? } else { ?>
<span class="nav-item navbar-text mx-3"><a href="<?=$_header_user->getURI()?>"><?=$_header_user->getName()?></a><?=($_header_user->isDisabled() ? ' <span class="font-weight-bold text-danger">(Disabled)</span>' : '')?></span>
<a class="btn btn-sm btn-outline my-2 my-sm-0" tabindex="-1" href="<?=Common::relativeUrlToAbsolute('/user/logout')?>">Log out</a>
<? } ?>
</div>
</nav>
<!--
<a href="<?=Common::relativeUrlToAbsolute('/credits')?>">Contributors</a>
<?php if (Common::$config->discord->enabled) { ?>
<a href="<?=Common::relativeUrlToAbsolute('/discord')?>">Discord</a>
<?php } ?>
<a href="<?=Common::relativeUrlToAbsolute('/donate')?>">Donate</a>
<a href="<?=Common::relativeUrlToAbsolute('/user/index')?>">Members</a>
<a href="<?=Common::relativeUrlToAbsolute('/news')?>">News</a>
<a href="<?=Common::relativeUrlToAbsolute('/servers')?>">Servers</a>
<a>Account</a>
<?php if ($_header_user) { ?>
<a href="<?=Common::relativeUrlToAbsolute('/user/logout')?>">Logout</a>
<a href="<?=Common::relativeUrlToAbsolute('/user/changepassword')?>">Change Password</a>
<a href="<?=Common::relativeUrlToAbsolute('/user/update')?>">Update Profile</a>
<a href="<?=Common::relativeUrlToAbsolute($_header_user_url)?>">View Profile</a>
<?php } else { ?>
<a href="<?=Common::relativeUrlToAbsolute('/user/login?return=' . rawurlencode(getenv('REQUEST_URI')))?>">Log In</a>
<?php if (!$_header_user_register_disabled) { ?>
<a href="<?=Common::relativeUrlToAbsolute('/user/register')?>">Create</a>
<?php } ?>
<?php } ?>
<a>The Docs</a>
<a href="<?=Common::relativeUrlToAbsolute('/packet/index')?>">Packet Index</a>
<a>Other Pages</a>
<a href="<?=Common::relativeUrlToAbsolute('//files.bnetdocs.org/')?>">File Archive</a>
<a href="<?=Common::relativeUrlToAbsolute('/privacy')?>">Privacy Notice</a>
<a href="<?=Common::relativeUrlToAbsolute('/legal')?>">Legal Policies</a>
<a href="<?=Common::relativeUrlToAbsolute('//redux.bnetdocs.org/')?>">BNETDocs Redux</a>
<?php if ($_header_staff) { ?>
<a>Site Admin</a>
<a href="<?=Common::relativeUrlToAbsolute('/document/create')?>">Create Document</a>
<a href="<?=Common::relativeUrlToAbsolute('/news/create')?>">Create News Post</a>
<a href="<?=Common::relativeUrlToAbsolute('/packet/create')?>">Create Packet</a>
<a href="<?=Common::relativeUrlToAbsolute('/server/create')?>">Create Server</a>
<a href="<?=Common::relativeUrlToAbsolute('/eventlog/index')?>">Event Log</a>
<?php } ?>
-->
<?=_header_nav_html($_header_nav)?>
<main>

0 comments on commit 016e253

Please sign in to comment.