emlog pro 模板 API 大字典
时间:2022-11-12 12:15 作者:独元殇 分类: emlog 文档
介绍
我们对 emlog pro 的模板开发,只需符合本「字典」规范即可,无序探究 emlog pro 是怎么运行的。只要是已经成型的完整网站前端代码,都能一定程度转化为 emlog pro 模版。
因此,为了保障模板的显示质量,以及你的艺术和创意性能够不受 emlog 系统的干扰,强烈要求你在制作模板之前,先通过这个流程【纸上画出草图和创意】--【电脑画出设计稿】--【HTML CSS JS 切图还原】--【工程优化】......... 完事俱全后,再按照本字典,对接 emlog pro。
如果目标就是制作一个 emlog 的模板,那么可以先浏览一遍本字典,大概了解 emlog 对哪些参数的支持比较好,以免以后麻烦。
当然,在此之前,你得略微熟悉 PHP 的语法,知道怎么输出,怎么写函数,变量等等。
系统自带模板「default」 只是一个示范参考,不能做到万事俱全,模板开发事宜,一切以本文内容为准。
这不是模板开发教程!这不是模板开发教程!这不是模板开发教程!这是模板开发的「字典」,供 emlog 开发者复制、粘贴、查询、参考使用的开发规范,或 emlog pro 模板的游戏规则。
预祝使用愉快!
( ps: 制作一个有良好可用性的开发字典是个有挑战性的事,目前这种形式只是一种解决方案,如有更好建议,敬请提出。)
模板文件系统
模板位置
emlog 的模版位置位于 ./content/templates/< 模版文件夹 >。
模板文件(夹)命名规范
模板的「文件夹」名称,为模板的英文名称。
如 default、sunshine。
./content/templates/default/
./content/templates/sunshine/
模板文件夹内部,系统的硬性要求有五个文件,即模板里必须要包含以下五个文件,否则系统会报错。
文件名 | 介绍 |
---|---|
header.php | 模板中,博客的 html 头部 |
log_list.php | 模板中,博客的首页(一般为博客文章的列出) |
echo_log.php | 模板中,博客某个文章的文章阅读页 |
page.php | 模板中,博客某个页面的页面显示页(这个后台有设置,用户也可用其他文件显示,比如 page1.php,但 page.php 是默认,必须有) |
404.php | 404 页面 |
preview.jpg | 模板在后台「模板外观设置」页面里的预览图。建议尺寸为 300×225 或这个比例。 |
当然,也有个文件可有,可没有
文件名 | 介绍 |
---|---|
pw.php | 文章密码输入页(如果没有这个文件,则使用系统默认的密码输入页) |
除了上面这些文件,其余的 php 文件结构,大家可据自己的编码和架构风格来确定,如果是全新制作的模板,可参考系统自带模板 default 的模板代码结构(比如 module.php、side.php、css 文件夹)。
模板文件的调用模式
系统对模板的调用模式
上面的七个文件,是 emlog 系统可以直接获取的七个文件,像 DNA 一样刻在了 emlog 系统核心代码里,一切我们的博客行为,都是系统搭配以上文件来调用的。
这些搭配模式 emlog 只是方便常见的博客行为而设计。大家可灵活运用,来适配自己的模板中博客交互设计方式。
emlog pro 后端程序是以路由映射表来控制我们博客页面的显示,我们可理解成「搭配模式」,或「调用模式」。
现在我们假设,我们有了一个博客,首页域名为 http://127.0.0.1/ ,而且我们也暂时没开「伪静态」。
显示「首页」模式
系统输出 header.php + log_list.php
输出就是,执行上面两文件的 php 代码内容。当然,非直接执行,是系统通过一些措施来执行,上面两个 php 文件可以访问系统的很多变量。比如 php 常量 BLOG_URL
(博客的地址)。
阅读某个「博文」模式
如访问 http://127.0.0.1/?post=4 (4 是文章 ID,每个文章或页面都有它独有的 ID 号)
系统输出 header.php + echo_log.php
显示某个「页面」模式
如访问 http://127.0.0.1/?post=6 (6 是页面 ID)
系统输出 header.php + page.php
如果用户在后台设置了其他页面模板,如 page0001,则调用输出相应文件.
系统输出 header.php + page0001.php
显示「作者文章」模式
如访问 http://127.0.0.1/?author=1 (1 是作者 ID)
系统输出 header.php + log_list.php
我们看到,这个和「首页」模式一样。其实此时,emlog pro 向模板传递的数据不一样。这次,只传递了属于这个作者文章的数据。
下面几个模式也一样道理。
显示「归档文章」模式
如访问 http://127.0.0.1/?record=20221110 (显示日期为 2022 年 11 月 10 日的文章)
系统输出 header.php + log_list.php
显示「搜索文章」模式
如访问 http://127.0.0.1/?keyword=emlog(搜索 emlog 后,系统的显示)
系统输出 header.php + log_list.php
显示「分类文章」模式
如访问 http://127.0.0.1/?sort=1 (1 是这个文章分类的 ID)
系统输出 header.php + log_list.php
显示「标签文章」模式
如访问 http://127.0.0.1/?tag=1 (1 是这个标签分类的 ID)
系统输出 header.php + log_list.php
显示「404」模式
如访问 http://127.0.0.1/?post=400 (400 是一个不存在的文章 ID)
系统输出 404.php
显示「密码输入」模式
如访问 http://127.0.0.1/?post=25 (25 是一个有设置密码的文章的 ID)
系统输出 pw.php 或 系统默认的密码输入界面。
前端(模板)怎么知道当前调用模式
这个,目前最简单的办法,就是在前端进行判断。
如果特殊情况下,不想使用 log_list.php 等文件的话(比如我们只是把 emlog pro 当做一个平台,想在此基础上做一些比较复杂的网站的话),可将 log_list.php 等文件空白(空白可以,但一定要有这个文件,当然,如非特别必要,还是建议使用这些系统建议的文件),可以只使用 header.php。
在 hearder.php 文件中,使用类似如下代码进行逻辑判断,这些代码,在 header.php 中是有效的。
<?php
if(isset($record) && isset($page)) {
echo "当前是「归档」模式,日期数据是".$record."<br>";
echo "当前是第".$page."页";
}
if(isset($author) && isset($page)) {
echo "当前是「作者」模式,查询作者的 ID 是".$author."<br>";
echo "当前是第".$page."页";
}
if(isset($keyword) && isset($page)) {
echo "当前是「搜索」模式,搜索数据是".$keyword."<br>";
echo "当前是第".$page."页";
}
if(isset($sortid) && isset($page)) {
echo "当前是「分类」模式,查询分类的 ID 是".$sortid."<br>";
echo "当前是第".$page."页";
}
if(isset($tag) && isset($page)) {
echo "当前是「标签」模式,标签数据是".$tag."<br>";
echo "当前是第".$page."页";
}
if(isset($type)) {
if(!empty($password)){
echo "<br>当前是已经根据之前 cookie 中储存的文章密码而跳转到的文章界面";
}
if($type === "blog"){
echo "<br>当前是「文章」阅读模式";
}
if ($type === "page") {
echo "<br>当前是「页面」显示模式";
}
}
至于 「404」模式和「密码输入」模式,这个轮不到 header.php 判断,emlog pro 系统会直接只输出 404.php 或 pw.php(或默认的密码输入界面)。
怎么自定义模式
例:自定义「用户搜索模式」
除了上面的模式,我们可能还会有其他的模式需求,比如「用户搜索」模式。
这个如果想实现伪静态的话,是有点麻烦。有这方面需求,建议使用系统面板中的页面来搞定,如果没有,像其他一样,使用 GET 协议来搞定。
假定我们使用 GET,我们访问的链接是 http://127.0.0.1/?userkeyword=Tom ,那么我们代码就可像上面那样判断了。
$sunshine_uk = isset($_GET["userkeyword"]) ? addslashes($_GET["userkeyword"]) : "";
// 为防止出现变量冲突,这些直接在全局声明的变量,最好要带上如 sunshine_ 这样的前缀
if(!empty($sunshine_uk)) {
echo "当前是「用户搜索」模式,参数值是".$sunshine_uk;
}
目前,模式有了,但业务代码,只能自己去写了......
例:移动设备模式
如果我们的模板并非响应式的,是桌面端一套模板、移动端一套模板,那也可在 header.php 中进行逻辑判断,这里可以使用如下函数。
function is_mobile() {
$user_agent = $_SERVER['HTTP_USER_AGENT'];
$mobile_browser = Array(
"mqqbrowser", // 手机 QQ 浏览器
"opera mobi", // 手机 opera
"juc","iuc", // uc 浏览器
"fennec","ios","applewebKit/420","applewebkit/525","applewebkit/532","ipad","iphone","ipaq","ipod",
"iemobile", "windows ce", // windows phone
"240×320","480×640","acer","android","anywhereyougo.com","asus","audio","blackberry","blazer","coolpad" ,"dopod", "etouch", "hitachi","htc","huawei", "jbrowser", "lenovo","lg","lg-","lge-","lge", "mobi","moto","nokia","phone","samsung","sony","symbian","tablet","tianyu","wap","xda","xde","zte"
);
$is_mobile = false;
foreach ($mobile_browser as $device) {
if (stristr($user_agent, $device)) {
$is_mobile = true;
break;
}
}
return $is_mobile;
}
if(is_mobile()){
echo "当前是移动设备模式";
}else{
echo "当前是桌面设备模式";
}
使用 View::getView(); 引入我们的模板文件
View::getView() 的用法如下。
// 一般,我们在模板 php 代码中引入除上述七个系统必要的文件之外的 php 文件时
// 可能会使用 require_once include 语句,如下
require_once 'function.php';
include 'footer.php';
// 而在 emlog 模板中,我们统一使用如下语句来代替后面的内容
require_once View::getView("function");
include View::getView("footer");
使用 View::getView() 与直接使用 require、include 的区别有一个。
- 在系统找不到这个文件时,不会直接报错,而是前台提示“模板已被损坏,请更换模板”
提示一下:
require 和 include 的区别?
require 生成一个致命错误(E_COMPILE_ERROR),在错误发生后脚本会停止执行。
include 生成一个警告(E_WARNING),在错误发生后脚本会继续执行。
模板的代码规范
emlog pro 版本的模板,必须符合以下的代码规范。否则将是不合格的模板。
模板体积
体积应以精简为本。最好不要超过 5MB,否则无法在官方商店上线。
模板信息
模板信息要写在 header.php 中,内容很简单。我们假设以「阳光」为例,以下是一个案例。
含义依次为「模板名(最好是中文名)」、「模板的官方 url」、「模板版本号」、「模板的简介」、「模板作者昵称」、「模板作者的个人主页 url」。
这些内容建议尽量不要留空。
/*
Template Name:阳光
Template Url:https://www.test.com/sunshine/
Version:1.3.3
Description:这是一个以「阳光」为主题的模板,简约大方,适合做个人生活、心情记录使用
Author:张三
Author Url:https://www.test.com
*/
防跨权限访问
为防止模板文件被直接访问(有暴露系统敏感信息的隐患),固在模板中的所有 php 文件的最开头,都应有如下代码。
if(!defined('EMLOG_ROOT')) {exit('error!');}
模板文件调用 getView
模板中的 php 文件可分为两种。
- 一些模板程序中的函数库、组件库等。
- 主要是前端 HTML 代码,做为视图显示模板。
对于第一类,函数库、组件库文件,比如这个 php 文件中有一些计算日期类的函数等等,使用以下语句引入。如 function.php。
require_once View::getView("function");
对于第二类,主要是储存前端 HTML 代码的 php 文件,比如 side.php、footer.php,我们使用以下语句引入。
include View::getView("footer");
模板钩子(挂载点)
为了紧密配合 emlog pro 系统钩子机制的正常运行,每个模板中都应有如下六个挂载点。
挂载点代码 | 挂载点含义 | 挂载点位置 |
---|---|---|
<?php doAction('index_head') ?> |
HTML 头部。用于向博客添加 CSS 等内容。 | 模板中 HTML 里 <head> 标签的最后面。 |
<?php doAction('index_navi_ext') ?> |
导航栏上的扩展。可用于向导航栏上添加内容,比如插件的页面,或一些类似搜索的小组件。 | 模板中导航栏 HTML 代码的最后面。 |
<?php doAction('index_loglist_top');?> |
首页的内容区最开始。可用于添加主页的公告等。 | 模板中,首页导航栏外后,首页主体内容的最开头。 |
<?php doAction('log_related', $logData) ?> |
添加文章相关内容,比如“打赏”、“收藏、“分享”。 | 模板中,文章阅读页,紧邻文章阅读结尾的区域。 |
<?php doAction('diff_side'); ?> |
侧边栏控制点。【非必须】 | 侧边栏组件上方。 |
<?php doAction('index_footer') ?> |
足部扩展。用于系统和插件在博客页脚处输出内容以及添加 JS 脚本内容。 | 博客模板页脚处内容区。 |
因为各模板各皆有差异,详细位置不做严格要求,但一定要保证挂载点在插件调用时能发挥其应有的作用。
安全方面
因前端模板的性质比较特殊,不能将 XSS 隐患一概过滤,但还是应十分谨慎。
对于用户输入的内容,以及系统输出的内容,如果不是 emlog pro 自带的交互功能,而理论上也不应包含 < script > 的地方,都应使用 php 进行代码过滤。(比如接收网址里的 GET 参数)
示例如下:
$action = isset($_GET["action"]) ? addslashes($_GET["action"]) : "";
SEO
网站 SEO 优化以个人经验量力而行。这里给出两个建议。
- 在做完模板后,可验证一下 W3C :https://validator.w3.org/ 可以避免犯一些 HTML 语法上的错误。当然它的这些建议仅供参考。
- 可以使用 Chrome 浏览器自带的 dev tool 工具中的 lighthouse 工具来跑一下分,它会给出一些 SEO 上的优化建议。
模板主要变量信息获取
<?= $someValue ?>
是 php 的一种简写语法,等同于<?php echo $somevalue; ?>
模板 head 头部
代码 | (代码描述)输出示例 | 备注 |
---|---|---|
<?= $site_title ?> |
(站点标题)张三的博客 | 用户可在后台 SEO 中设置 ,这是站点浏览器标签页标题 |
<?= $site_key ?> |
(站点关键字)张三 大学生 运动 摄影 个人网站 | 用户可在后台 SEO 中设置 |
<?= $site_description ?> |
(站点描述/文章描述)张三分享自己的生活,写一些心灵感悟。 | 1.在首页,它是站点描述。2.在文章阅读页,它是文章的摘要。 |
<?= BLOG_URL ?> |
(站点的首页 URL )http://127.0.0.1 | 可用于引入站点的浏览器图标等 |
<?= TEMPLATE_URL ?> |
(站点模板的 URL)http://127.0.0.1/content/templates | 可用于向前台引入模板一些 CSS 文件等。 |
模板页顶
代码 | (代码描述)输出示例 | 备注 |
---|---|---|
<?= BLOG_URL ?> |
( 站点的首页 URL)http://127.0.0.1 | 可用于设置博客标题< a >标签 href |
<?= $blogname ?> |
(博客标题)张三博客 | HTML 页面显示的博客标题 |
<?= $bloginfo ?> |
(博客副标题)记录心情、生活、照片..... | HTML 页面显示的博客副标题 |
文章列出页(文章目录页)
$logs
是博客首页在当前请求下,系统给出的所有文章目录的集合。可以先判断一下,$log
是否为空。然后再循环输出文章。
if(!empty($logs)) {
foreach ($logs as $value) {
if (!empty($value['log_cover'])) { // 是否设置了「文章封面」图片
echo '封面图片地址是' . $value['log_cover'];
}
}
} else {
echo '没有文章';
}
其他
缓存,也就是
模板向系统信息的传递
模板 Ajax 获取内容
模板设置
emlog pro 函数大礼包
额......其实吧,开发模板,有这么几种情况:
如果已经有 html 了,那很简单可以照搬过来,毕竟只是后端往 html 里玩几个填字游戏而已。用不到什么更多的 API 手册了。
如果没有,只是仿站,那大多数情况下是面对一些简单要求的客户的,那尽可寥寥草草套换一下,也费不了什么功夫。
如果只是做着玩,0 开始,那...... 为什么不直接在 默认模版的基础上删删减减呢?
时间宝贵,效率宝贵,有可用性好的轮子,就不要重复造轮子,就不要重复造轮子,就不要重复造轮子!!!对自己,对别人,对未来,都好。不丢脸。
因此,在下面,我不像上面一样更新什么细节了,直接把 默认模板的重要文件(除 CSS)给放到下面。
header.php
<?php
/*
Template Name:默认模板
Template Url:https://www.emlog.net/template/
Description:这是emlog pro的默认模板
Author:emlog官方
Author Url:https://www.emlog.net
*/
if (!defined('EMLOG_ROOT')) {
exit('error!');
}
require_once View::getView('module');
?>
<!doctype html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title><?= $site_title ?></title>
<meta name="keywords" content="<?= $site_key ?>"/>
<meta name="description" content="<?= $site_description ?>"/>
<base href="<?= BLOG_URL ?>"/>
<link rel="shortcut icon" href="<?= BLOG_URL ?>favicon.ico"/>
<link rel="alternate" title="RSS" href="<?= BLOG_URL ?>rss.php" type="application/rss+xml"/>
<link href="<?= TEMPLATE_URL ?>css/style.css?t=<?= Option::EMLOG_VERSION_TIMESTAMP ?>" rel="stylesheet" type="text/css"/>
<link href="<?= TEMPLATE_URL ?>css/markdown.css?t=<?= Option::EMLOG_VERSION_TIMESTAMP ?>" rel="stylesheet" type="text/css"/>
<script src="<?= TEMPLATE_URL ?>js/jquery.min.3.5.1.js?v=<?= Option::EMLOG_VERSION_TIMESTAMP ?>"></script>
<script>function sendinfo(url) { // 日历生成和翻页
$("#calendar").load(url)
}</script>
<?php doAction('index_head') ?>
</head>
<body>
<nav class="blog-header">
<div class="blog-header-c container">
<a class="blog-header-title" href="<?= BLOG_URL ?>"><?= $blogname ?></a>
<div class="blog-header-subtitle subtitle-overflow" title="<?= $bloginfo ?>"><?= $bloginfo ?></div>
<div class="blog-header-toggle">
<svg class="blogtoggle-icon">
<rect x="1" y="1" fill="#5F5F5F" width="26" height="1.6"/>
<rect x="1" y="8" fill="#5F5F5F" width="26" height="1.6"/>
<rect x="1" y="15" fill="#5F5F5F" width="26" height="1.6"/>
</svg>
</div>
<?php blog_navi() ?>
<?php doAction('index_navi_ext') ?>
</div>
</nav>
log_list.php
<?php
/**
* 首页模板
*/
if (!defined('EMLOG_ROOT')) {
exit('error!');
}
?>
<main class="container blog-container">
<div class="row">
<div class="column-big">
<?php doAction('index_loglist_top');
if (!empty($logs)):
foreach ($logs as $value):
?>
<div class="shadow-theme bottom-5">
<?php if (!empty($value['log_cover'])) : ?>
<div class="loglist-cover">
<img src="<?= $value['log_cover'] ?>" alt="article cover" class="rea-width" data-action="zoom">
</div>
<?php endif ?>
<div class="card-padding loglist-body">
<h3 class="card-title">
<a href="<?= $value['log_url'] ?>" class="loglist-title"><?= $value['log_title'] ?></a>
<?php topflg($value['top'], $value['sortop'], isset($sortid) ? $sortid : '') ?>
<?php bloglist_sort($value['logid']) ?>
</h3>
<div class="loglist-content markdown"><?= $value['log_description'] ?></div>
<div class="loglist-tag"><?php blog_tag($value['logid']) ?></div>
</div>
<hr class="list-line"/>
<div class="row info-row">
<div class="log-info">
<?php blog_author($value['author']) ?> 发布于
<?= date('Y-n-j H:i', $value['date']) ?>
<span class="mh"><?php editflg($value['logid'], $value['author']) ?></span>
</div>
<div class="log-count">
<a href="<?= $value['log_url'] ?>#comment">评论(<?= $value['comnum'] ?>) </a>
<a href="<?= $value['log_url'] ?>">浏览(<?= $value['views'] ?>)</a>
</div>
</div>
</div>
<?php
endforeach;
else:
?>
<p>抱歉,暂时还没有内容。</p>
<?php endif ?>
<div class="pagination bottom-5">
<?= $page_url ?>
</div>
</div>
<?php include View::getView('side') ?>
</div>
</main>
<?php include View::getView('footer') ?>
footer.php
<?php
/**
* 页面底部信息
*/
if (!defined('EMLOG_ROOT')) {
exit('error!');
}
?>
<footer class="blog-footer">
<div class="container footinfo">
<?php
if (!empty($icp)) {
echo '<div><a href="https://beian.miit.gov.cn/" target="_blank">' . $icp . '</a></div>';
}
?>
<?= $footer_info ?>
<?php doAction('index_footer') ?>
</div>
</footer>
<script src="<?= TEMPLATE_URL ?>js/common_tpl.js?t=<?= Option::EMLOG_VERSION_TIMESTAMP ?>"></script>
<script src="<?= TEMPLATE_URL ?>js/zoom.js?t=<?= Option::EMLOG_VERSION_TIMESTAMP ?>"></script>
</body>
</html>
echo_log.php
<?php
/**
* 阅读文章页面
*/
if (!defined('EMLOG_ROOT')) {
exit('error!');
}
?>
<article class="container log-con blog-container">
<span class="back-top mh" onclick="history.go(-1);">«</span>
<h1 class="log-title"><?php topflg($top) ?><?= $log_title ?></h1>
<p class="date">
<b>时间:</b><?= date('Y-n-j H:i', $date) ?>
<b>作者:</b><?php blog_author($author) ?>
<b>分类:</b><?php blog_sort($logid) ?>
<?php editflg($logid, $author) ?>
</p>
<hr class="bottom-5"/>
<div class="markdown" id="emlogEchoLog"><?= $log_content ?></div>
<p class="top-5"><?php blog_tag($logid) ?></p>
<?php doAction('log_related', $logData) ?>
<nav class="neighbor-log"><?php neighbor_log($neighborLog) ?></nav>
<?php blog_comments_post($logid, $ckname, $ckmail, $ckurl, $verifyCode, $allow_remark) ?>
<?php blog_comments($comments) ?>
<div style="clear:both;"></div>
</article>
<?php include View::getView('footer') ?>
page.php
<?php
/**
* 自建页面模板
*/
if (!defined('EMLOG_ROOT')) {
exit('error!');
}
?>
<article class="container blog-container">
<div class="row">
<div class="column-big log-con " id="page">
<h1 class="page-title"><?= $log_title ?></h1>
<div class="markdown">
<?= $log_content ?>
</div>
<?php blog_comments_post($logid, $ckname, $ckmail, $ckurl, $verifyCode, $allow_remark) ?>
<?php blog_comments($comments) ?>
</div>
<?php
include View::getView('side');
?>
</div>
</article>
<?php
include View::getView('footer');
?>
pw.php
<?php
/**
* 加密文章输入密码页面
*/
if (!defined('EMLOG_ROOT')) {
exit('error!');
}
?>
<!doctype html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>请输入文章访问密码</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
}
form {
background-color: #fff;
border: 1px solid #ccc;
border-radius: 5px;
margin: 20px auto;
max-width: 500px;
padding: 20px;
}
h1 {
font-size: 24px;
color: #333333;
margin: 0 0 20px;
text-align: center;
}
input[type="password"] {
border-radius: 3px;
border: 1px solid #ccc;
font-size: 14px;
height: 25px;
padding: 8px;
width: calc(100% - 100px);
}
button[type="submit"] {
background-color: #007bff;
border: none;
border-radius: 3px;
color: #fff;
cursor: pointer;
font-size: 16px;
font-weight: bold;
height: 40px;
margin-left: 10px;
transition: all .3s ease-in-out;
width: 100px;
}
button[type="submit"]:hover {
background-color: #0069d9;
}
a {
color: #007bff;
display: block;
margin-top: 20px;
text-align: center;
text-decoration: none;
font-size: 14px;
}
</style>
</head>
<body>
<form action="" method="post">
<h1>请输入文章访问密码</h1>
<div style="display: flex;">
<input type="password" id="logpwd" name="logpwd" required autofocus>
<button type="submit">提交</button>
</div>
<a href="<?= BLOG_URL ?>">←返回首页</a>
</form>
</body>
</html>
404.php
<?php
/**
* 自定义404页面
*/
if (!defined('EMLOG_ROOT')) {
exit('error!');
}
?>
<!doctype html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>错误提示-页面未找到</title>
<style>
body {
background-color: #F7F7F7;
font-family: Arial;
font-size: 12px;
line-height: 150%
}
.main {
background-color: #FFFFFF;
font-size: 12px;
color: #666666;
width: 650px;
margin: 60px auto 0px;
padding: 30px 10px;
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, .02);
border-radius: 10px;
transition: box-shadow 0.4s
}
.main p {
text-align: center;
font-weight: 600;
font-size: 2rem
}
.main p a {
border: 1px solid #ccc !important;
padding: 8px;
border-radius: 10px !important;
color: #929292;
font-size: initial;
text-decoration: none
}
</style>
</head>
<body>
<div class="main">
<p>404 Not Found !</p>
<p><a href="<?= BLOG_URL ?>">首页</a></p>
</div>
</body>
</html>
module.php
<?php
/**
* 侧边栏组件、页面模块
*/
if (!defined('EMLOG_ROOT')) {
exit('error!');
}
?>
<?php
/**
* 侧边栏:链接
*/
function widget_link($title) {
global $CACHE;
$link_cache = $CACHE->readCache('link');
//if (!blog_tool_ishome()) return;#只在首页显示友链去掉双斜杠注释即可
?>
<div class="widget shadow-theme">
<div class="widget-title">
<h3><?= $title ?></h3>
</div>
<ul class="widget-list no-margin-bottom unstyle-li">
<?php foreach ($link_cache as $value): ?>
<li><a href="<?= $value['url'] ?>" title="<?= $value['des'] ?>" target="_blank"><?= $value['link'] ?></a></li>
<?php endforeach ?>
</ul>
</div>
<?php } ?>
<?php
/**
* 侧边栏:个人资料
*/
function widget_blogger($title) {
global $CACHE;
$user_cache = $CACHE->readCache('user');
$name = $user_cache[1]['name'] ?>
<div class="widget shadow-theme">
<div class="widget-title">
<h3><?= $title ?></h3>
</div>
<div class="unstyle-li bloggerinfo">
<?php if (!empty($user_cache[1]['photo']['src'])): ?>
<div>
<img class='bloggerinfo-img' src="<?= BLOG_URL . $user_cache[1]['photo']['src'] ?>" alt="blogger"/>
</div>
<?php endif ?>
<div class='bloginfo-name'><b><?= $name ?></b></div>
<div class='bloginfo-descript'><?= $user_cache[1]['des'] ?></div>
</div>
</div>
<?php } ?>
<?php
/**
* 侧边栏:日历
*/
function widget_calendar($title) { ?>
<div class="widget shadow-theme">
<div class="widget-title m">
<h3><?= $title ?></h3>
</div>
<div class="unstyle-li">
<div id="calendar"></div>
<script>sendinfo('<?= Calendar::url() ?>', 'calendar');</script>
</div>
</div>
<?php } ?>
<?php
/**
* 侧边栏:标签
*/
function widget_tag($title) {
global $CACHE;
$tag_cache = $CACHE->readCache('tags') ?>
<div class="widget shadow-theme">
<div class="widget-title m">
<h3><?= $title ?></h3>
</div>
<div class="unstyle-li tag-container">
<?php foreach ($tag_cache as $value): ?>
<span style="font-size:<?= $value['fontsize'] ?>pt; line-height:30px;">
<a href="<?= Url::tag($value['tagurl']) ?>" title="<?= $value['usenum'] ?> 篇文章" class='tags-side'><?= $value['tagname'] ?></a></span>
<?php endforeach ?>
</div>
</div>
<?php } ?>
<?php
/**
* 侧边栏:分类
*/
function widget_sort($title) {
global $CACHE;
$sort_cache = $CACHE->readCache('sort') ?>
<div class="widget shadow-theme">
<div class="widget-title m">
<h3><?= $title ?></h3>
</div>
<ul class="unstyle-li log-classify-f">
<?php
foreach ($sort_cache as $value):
if ($value['pid'] != 0) continue;
?>
<li>
<a href="<?= Url::sort($value['sid']) ?>" title="<?= $value["description"] ?>"><?= $value['sortname'] ?>
<?= (($value['lognum']) > 0) ? '(' . ($value['lognum']) . ')' : '' ?></a>
<?php if (!empty($value['children'])): ?>
<ul class="log-classify-c">
<?php
$children = $value['children'];
foreach ($children as $key):
$value = $sort_cache[$key];
?>
<li>
<a href="<?= Url::sort($value['sid']) ?>" title="<?= $value["description"] ?>">-- <?= $value['sortname'] ?>
(<?= $value['lognum'] ?>)</a>
</li>
<?php endforeach ?>
</ul>
<?php endif ?>
</li>
<?php endforeach ?>
</ul>
</div>
<?php } ?>
<?php
/**
* 侧边栏:最新评论
*/
function widget_newcomm($title) {
global $CACHE;
$com_cache = $CACHE->readCache('comment');
$isGravatar = Option::get('isgravatar');
?>
<div class="widget shadow-theme">
<div class="widget-title">
<h3><?= $title ?></h3>
</div>
<hr>
<ul class="unstyle-li">
<?php
foreach ($com_cache as $value):
$url = Url::comment($value['gid'], $value['page'], $value['cid']);
?>
<li class="comment-info">
<?php if ($isGravatar == 'y'): ?>
<img class='comment-info_img' src="<?= getGravatar($value['mail']) ?>" alt="commentator"/>
<?php endif ?>
<span class='comm-lates-name'><?= $value['name'] ?></span>
<span class='logcom-latest-time'><?= smartDate($value['date']) ?></span><br/>
<a href="<?= $url ?>"><?= $value['content'] ?></a>
<hr>
</li>
<?php endforeach ?>
</ul>
</div>
<?php } ?>
<?php
/**
* 侧边栏:最新文章
*/
function widget_newlog($title) {
global $CACHE;
$newLogs_cache = $CACHE->readCache('newlog');
?>
<div class="widget shadow-theme">
<div class="widget-title m">
<h3><?= $title ?></h3>
</div>
<ul class="unstyle-li">
<?php foreach ($newLogs_cache as $value): ?>
<li class="blog-lates"><a href="<?= Url::log($value['gid']) ?>"><?= $value['title'] ?></a></li>
<?php endforeach ?>
</ul>
</div>
<?php } ?>
<?php
/**
* 侧边栏:热门文章
*/
function widget_hotlog($title) {
$index_hotlognum = Option::get('index_hotlognum');
$Log_Model = new Log_Model();
$hotLogs = $Log_Model->getHotLog($index_hotlognum) ?>
<div class="widget shadow-theme">
<div class="widget-title m">
<h3><?= $title ?></h3>
</div>
<ul class="unstyle-li">
<?php foreach ($hotLogs as $value): ?>
<li class="blog-hot"><a href="<?= Url::log($value['gid']) ?>"><?= $value['title'] ?></a></li>
<?php endforeach ?>
</ul>
</div>
<?php } ?>
<?php
/**
* 侧边栏:搜索
*/
function widget_search($title) { ?>
<div class="widget shadow-theme">
<div class="widget-title">
<h3><?= $title ?></h3>
</div>
<div class="unstyle-li" style="text-align: center;">
<form name="keyform" method="get" action="<?= BLOG_URL ?>index.php">
<input name="keyword" class="search form-control" autocomplete="off" aria-label="Search" type="text"/>
<input type="submit" value="搜索">
</form>
</div>
</div>
<?php } ?>
<?php
/**
* 侧边栏:归档
*/
function widget_archive($title) {
$bar_id = "36";
global $CACHE;
$record_cache = $CACHE->readCache('record');
?>
<div class="widget shadow-theme">
<div class="widget-title m">
<h3><?= $title ?></h3>
</div>
<select id="archive" class="archive">
<?php foreach ($record_cache as $value): ?>
<option value="<?= Url::record($value['date']) ?>"><?= $value['record'] ?> (<?= $value['lognum'] ?>)</option>
<?php endforeach ?>
</select>
</div>
<?php } ?>
<?php
/**
* 侧边栏:自定义组件
*/
function widget_custom_text($title, $content) { ?>
<div class="widget shadow-theme">
<div class="widget-title m">
<h3><?= $title ?></h3>
</div>
<ul class="unstyle-li">
<?= $content ?>
</ul>
</div>
<?php } ?>
<?php
/**
* 页顶:导航
*/
function blog_navi() {
global $CACHE;
$navi_cache = $CACHE->readCache('navi');
?>
<div class="blog-header-nav" id="navbarResponsive">
<ul class="nav-list">
<?php
foreach ($navi_cache as $value):
if ($value['pid'] != 0) {
continue;
}
if ($value['url'] == 'admin' && (!User::isVistor())):
?>
<li class="list-item list-menu"><a href="<?= BLOG_URL ?>admin/" class="nav-link">管理</a></li>
<li class="list-item list-menu"><a href="<?= BLOG_URL ?>admin/account.php?action=logout" class="nav-link">退出</a></li>
<?php
continue;
endif;
$newtab = $value['newtab'] == 'y' ? 'target="_blank"' : '';
$value['url'] = $value['isdefault'] == 'y' ? BLOG_URL . $value['url'] : trim($value['url'], '/');
$current_tab = BLOG_URL . trim(Dispatcher::setPath(), '/') == $value['url'] ? 'active' : '';
?>
<?php if (!empty($value['children']) || !empty($value['childnavi'])) : ?>
<li class="list-item list-menu">
<?php if (!empty($value['children'])): ?>
<a class="nav-link has-down" id="nav_link" href="<?= $value['url'] ?>" <?= $newtab ?>><?= $value['naviname'] ?></a>
<ul class="dropdown-menus">
<?php foreach ($value['children'] as $row) {
echo '<li class="list-item list-menu"><a class="nav-link" href="' . Url::sort($row['sid']) . '">' . $row['sortname'] . '</a></li>';
} ?>
</ul>
<?php endif ?>
<?php if (!empty($value['childnavi'])) : ?>
<a class='nav-link has-down' id="nav_link" <?= $newtab ?> ><?= $value['naviname'] ?></a>
<ul class="dropdown-menus">
<?php foreach ($value['childnavi'] as $row) {
$newtab = $row['newtab'] == 'y' ? 'target="_blank"' : '';
echo '<li class="list-item list-menu"><a class="nav-link" href="' . $row['url'] . "\" $newtab >" . $row['naviname'] . '</a></li>';
} ?>
</ul>
<?php endif ?>
</li>
<?php else: ?>
<li class="list-item list-menu"><a class="nav-link" href="<?= $value['url'] ?>" <?= $newtab ?>><?= $value['naviname'] ?></a></li>
<?php endif ?>
<?php endforeach ?>
</ul>
</div>
<?php } ?>
<?php
/**
* 文章列出卡片:置顶标志
*/
function topflg($top, $sortop = 'n', $sortid = null) {
$ishome_flg = '<span title="首页置顶" class="log-topflg" >置顶</span>';
$issort_flg = '<span title="分类置顶" class="log-topflg" >分类置顶</span>';
if (blog_tool_ishome()) {
echo $top == 'y' ? $ishome_flg : '';
} elseif ($sortid) {
echo $sortop == 'y' ? $issort_flg : '';
}
}
?>
<?php
/**
* 文章详情页:编辑链接
*/
function editflg($logid, $author) {
$editflg = User::haveEditPermission() || $author == UID ? ' <a href="' . BLOG_URL . 'admin/article.php?action=edit&gid=' . $logid . '" target="_blank">编辑</a>' : '';
echo $editflg;
}
?>
<?php
/**
* 文章详情页:分类
*/
function blog_sort($blogid) {
$Log_Model = new Log_Model();
$logInfo = $Log_Model->getDetail($blogid);
$sortID = isset($logInfo['sid']) ? $logInfo['sid'] : '';
$sortName = isset($logInfo['sortname']) ? $logInfo['sortname'] : '';
?>
<?php if (!empty($sortName)) { ?>
<a href="<?= Url::sort($sortID) ?>"><?= $sortName ?></a>
<?php } else { ?>
<a href="#" title="未分类">无</a>
<?php }
} ?>
<?php
/**
* 首页文章列表:分类
*/
function bloglist_sort($blogid) {
$Log_Model = new Log_Model();
$logInfo = $Log_Model->getDetail($blogid);
$sortID = isset($logInfo['sid']) ? $logInfo['sid'] : '';
$sortName = isset($logInfo['sortname']) ? $logInfo['sortname'] : '';
?>
<?php if (!empty($sortName)) { ?>
<span class="loglist-sort">
<a href="<?= Url::sort($sortID) ?>"><?= $sortName ?></a>
</span>
<?php }
} ?>
<?php
/**
* 首页文章列表和文章详情页:标签
*/
function blog_tag($blogid) {
$tag_model = new Tag_Model();
$tag_ids = $tag_model->getTagIdsFromBlogId($blogid);
$tag_names = $tag_model->getNamesFromIds($tag_ids);
if (!empty($tag_names)) {
$tag = '标签:';
foreach ($tag_names as $key => $value) {
$tag .= " <a href=\"" . Url::tag(rawurlencode($value)) . "\" class='tags' title='标签' >" . htmlspecialchars($value) . '</a>';
}
echo $tag;
}
}
?>
<?php
/**
* 首页文章列表和文章详情页:作者
*/
function blog_author($uid) {
$User_Model = new User_Model();
$user_info = $User_Model->getOneUser($uid);
$author = $user_info['nickname'];
echo '<a href="' . Url::author($uid) . "\">$author</a>";
}
?>
<?php
/**
* 文章详情页:相邻文章
*/
function neighbor_log($neighborLog) {
extract($neighborLog) ?>
<?php if ($prevLog): ?>
<span class="prev-log"><a href="<?= Url::log($prevLog['gid']) ?>" title="<?= $prevLog['title'] ?>">上一篇</a></span>
<?php endif ?>
<?php if ($nextLog): ?>
<span class="next-log"><a href="<?= Url::log($nextLog['gid']) ?>" title="<?= $nextLog['title'] ?>">下一篇</a></span>
<?php endif ?>
<?php } ?>
<?php
/**
* 文章详情页:评论列表
*/
function blog_comments($comments) {
extract($comments);
if ($commentStacks): ?>
<div class="comment-header"><b>评论:</b></div>
<?php endif ?>
<?php
$isGravatar = Option::get('isgravatar');
foreach ($commentStacks as $cid):
$comment = $comments[$cid];
$comment['poster'] = $comment['url'] ? '<a href="' . $comment['url'] . '" rel="external nofollow" target="_blank">' . $comment['poster'] . '</a>' : $comment['poster'];
?>
<div class="comment" id="<?= $comment['cid'] ?>">
<?php if ($isGravatar == 'y'): ?>
<div class="avatar"><img src="<?= getGravatar($comment['mail']) ?>" alt="avatar"/></div>
<div class="comment-infos">
<div class="arrow"></div>
<b><?= $comment['poster'] ?> </b><span class="comment-time"><?= $comment['date'] ?></span>
<div class="comment-content"><?= $comment['content'] ?></div>
<div class="comment-reply">
<button class="com-reply comment-replay-btn">回复</button>
</div>
</div>
<?php else: ?>
<div class="comment-infos-unGravatar">
<b><?= $comment['poster'] ?> </b><span class="comment-time"><?= $comment['date'] ?></span>
<div class="comment-content"><?= $comment['content'] ?></div>
<div class="comment-reply">
<button class="com-reply comment-replay-btn">回复</button>
</div>
</div>
<?php endif ?>
<?php blog_comments_children($comments, $comment['children']) ?>
</div>
<?php endforeach ?>
<div id="pagenavi">
<?= $commentPageUrl ?>
</div>
<?php } ?>
<?php
/**
* 文章详情页:子评论
*/
function blog_comments_children($comments, $children) {
$isGravatar = Option::get('isgravatar');
foreach ($children as $child):
$comment = $comments[$child];
$comment['poster'] = $comment['url'] ? '<a href="' . $comment['url'] . '" rel="external nofollow" target="_blank">' . $comment['poster'] . '</a>' : $comment['poster'];
?>
<div class="comment comment-children" id="<?= $comment['cid'] ?>">
<?php if ($isGravatar == 'y'): ?>
<div class="avatar"><img src="<?= getGravatar($comment['mail']) ?>" alt="commentator"/></div>
<div class="comment-infos">
<div class="arrow"></div>
<b><?= $comment['poster'] ?> </b><span class="comment-time"><?= $comment['date'] ?></span>
<div class="comment-content"><?= $comment['content'] ?></div>
<?php if ($comment['level'] < 4): ?>
<div class="comment-reply">
<button class="com-reply comment-replay-btn">回复</button>
</div><?php endif ?>
</div>
<?php else: ?>
<div class="comment-infos-unGravatar">
<b><?= $comment['poster'] ?> </b><span class="comment-time"><?= $comment['date'] ?></span>
<div class="comment-content"><?= $comment['content'] ?></div>
<?php if ($comment['level'] < 4): ?>
<div class="comment-reply">
<button class="com-reply comment-replay-btn">回复</button>
</div><?php endif ?>
</div>
<?php endif ?>
<?php blog_comments_children($comments, $comment['children']) ?>
</div>
<?php endforeach ?>
<?php } ?>
<?php
/**
* 文章详情页:评论表单
*/
function blog_comments_post($logid, $ckname, $ckmail, $ckurl, $verifyCode, $allow_remark) {
$isNeedChinese = Option::get('comment_needchinese');
if ($allow_remark == 'y'): ?>
<div id="comments">
<div class="comment-post" id="comment-post">
<div class="cancel-reply" id="cancel-reply" style="display:none">
<button class="comment-replay-btn">取消回复</button>
</div>
<form class="commentform" method="post" name="commentform" action="<?= BLOG_URL ?>index.php?action=addcom" id="commentform"
is-chinese="<?= $isNeedChinese ?>">
<input type="hidden" name="gid" value="<?= $logid ?>"/>
<textarea class="form-control log_comment" name="comment" id="comment" rows="10" tabindex="4" required></textarea>
<?php if (User::isVistor()): ?>
<div class="comment-info" id="comment-info">
<input class="form-control com_control comment-name" id="info_n" autocomplete="off" type="text" name="comname" maxlength="49"
value="<?= $ckname ?>" size="22"
tabindex="1" placeholder="昵称*" required/>
<input class="form-control com_control comment-mail" id="info_m" autocomplete="off" type="text" name="commail" maxlength="128"
value="<?= $ckmail ?>" size="22"
tabindex="2" placeholder="邮箱"/>
<input class="form-control com_control comment-url" id="info_u" autocomplete="off" type="text" name="comurl" maxlength="128"
value="<?= $ckurl ?>" size="22"
tabindex="3" placeholder="个人主页"/>
</div>
<?php endif ?>
<span class="com_submit_p">
<input class="btn"<?php if ($verifyCode != "") { ?> type="button" data-toggle="modal" data-target="#myModal"<?php } else { ?> type="submit" <?php } ?>
id="comment_submit" value="发布评论" tabindex="6"/>
</span>
<?php if ($verifyCode != "") { ?>
<!-- 验证窗口 -->
<div class="modal" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content" style="display: table-cell;">
<div class="modal-header" style="border-bottom: 0px;">
输入验证码
</div>
<?= $verifyCode ?>
<div class="modal-footer" style="border-top: 0px;">
<button type="button" class="btn" id="close-modal" data-dismiss="modal">关闭</button>
<button type="submit" class="btn" id="comment_submit2">提交</button>
</div>
</div>
</div>
<div class="lock-screen"></div>
</div>
<!-- 验证窗口(end) -->
<?php } ?>
<input type="hidden" name="pid" id="comment-pid" value="0" tabindex="1"/>
</form>
</div>
</div>
<?php endif ?>
<?php } ?>
<?php
/**
* 判断函数:是否是首页
*/
function blog_tool_ishome() {
if (BLOG_URL . trim(Dispatcher::setPath(), '/') == BLOG_URL) {
return true;
} else {
return FALSE;
}
}
?>
side.php
<?php
/**
* 侧边栏
*/
if (!defined('EMLOG_ROOT')) {
exit('error!');
}
?>
<div class="column-small side-bar">
<?php
$widgets = !empty($options_cache['widgets1']) ? unserialize($options_cache['widgets1']) : array();
doAction('diff_side');
foreach ($widgets as $val) {
$widget_title = @unserialize($options_cache['widget_title']);
$custom_widget = @unserialize($options_cache['custom_widget']);
if (strpos($val, 'custom_wg_') === 0) {
$callback = 'widget_custom_text';
if (function_exists($callback)) {
call_user_func($callback, htmlspecialchars($custom_widget[$val]['title']), $custom_widget[$val]['content']);
}
} else {
$callback = 'widget_' . $val;
if (function_exists($callback)) {
preg_match("/^.*\s\((.*)\)/", $widget_title[$val], $matchs);
$wgTitle = isset($matchs[1]) ? $matchs[1] : $widget_title[$val];
call_user_func($callback, htmlspecialchars($wgTitle));
}
}
}
?>
</div>