Merge pull request #1151 from typecho/dev

Dev
This commit is contained in:
joyqi 2021-09-07 11:00:58 +08:00 committed by GitHub
commit 5303124431
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
213 changed files with 13492 additions and 13360 deletions

View File

@ -6,3 +6,6 @@ indent_size = 4
[*.scss]
indent_size = 2
[*.php]
insert_final_newline = true

48
.phpstorm.meta.php Normal file
View File

@ -0,0 +1,48 @@
<?php
namespace PHPSTORM_META {
override(\Typecho\Widget::widget(0), map([
'' => '@'
]));
exitPoint(\Typecho\Widget\Response::redirect());
exitPoint(\Typecho\Widget\Response::throwContent());
exitPoint(\Typecho\Widget\Response::throwFile());
exitPoint(\Typecho\Widget\Response::throwJson());
exitPoint(\Typecho\Widget\Response::throwXml());
exitPoint(\Typecho\Widget\Response::goBack());
override(\Widget\Options::__get(0), map([
'feedUrl' => string,
'feedRssUrl' => string,
'feedAtomUrl' => string,
'commentsFeedUrl' => string,
'commentsFeedRssUrl' => string,
'commentsFeedAtomUrl' => string,
'xmlRpcUrl' => string,
'index' => string,
'siteUrl' => string,
'routingTable' => \ArrayObject::class,
'rootUrl' => string,
'themeUrl' => string,
'pluginUrl' => string,
'adminUrl' => string,
'loginUrl' => string,
'loginAction' => string,
'registerUrl' => string,
'registerAction' => string,
'profileUrl' => string,
'logoutUrl' => string,
'serverTimezone' => int,
'contentType' => string,
'software' => string,
'version' => string,
'markdown' => int,
'allowedAttachmentTypes'=> \ArrayObject::class
]));
override(\Typecho\Widget::__get(0), map([
'sequence' => int,
'length' => int
]));
}

View File

@ -4,10 +4,10 @@ include 'header.php';
include 'menu.php';
$actionUrl = $security->getTokenUrl(
Typecho_Router::url('do', array('action' => 'backup', 'widget' => 'Backup'),
Typecho_Common::url('index.php', $options->rootUrl)));
\Typecho\Router::url('do', array('action' => 'backup', 'widget' => 'Backup'),
\Typecho\Common::url('index.php', $options->rootUrl)));
$backupFiles = Typecho_Widget::widget('Widget_Backup')->listFiles();
$backupFiles = \Widget\Backup::alloc()->listFiles();
?>
<div class="main">

View File

@ -9,7 +9,7 @@ include 'menu.php';
<?php include 'page-title.php'; ?>
<div class="row typecho-page-main" role="form">
<div class="col-mb-12 col-tb-6 col-tb-offset-3">
<?php Typecho_Widget::widget('Widget_Metas_Category_Edit')->form()->render(); ?>
<?php \Widget\Metas\Category\Edit::alloc()->form()->render(); ?>
</div>
</div>
</div>

View File

@ -7,13 +7,13 @@
$(document).ready(function() {
// 处理消息机制
(function () {
var prefix = '<?php echo Typecho_Cookie::getPrefix(); ?>',
var prefix = '<?php echo \Typecho\Cookie::getPrefix(); ?>',
cookies = {
notice : $.cookie(prefix + '__typecho_notice'),
noticeType : $.cookie(prefix + '__typecho_notice_type'),
highlight : $.cookie(prefix + '__typecho_notice_highlight')
},
path = '<?php echo Typecho_Cookie::getPath(); ?>';
path = '<?php echo \Typecho\Cookie::getPath(); ?>';
if (!!cookies.notice && 'success|notice|error'.indexOf(cookies.noticeType) >= 0) {
var head = $('.typecho-head-nav'),
@ -110,7 +110,7 @@
if ((href && href[0] == '#')
|| /^<?php echo preg_quote($options->adminUrl, '/'); ?>.*$/.exec(href)
|| /^<?php echo substr(preg_quote(Typecho_Common::url('s', $options->index), '/'), 0, -1); ?>action\/[_a-zA-Z0-9\/]+.*$/.exec(href)) {
|| /^<?php echo substr(preg_quote(\Typecho\Common::url('s', $options->index), '/'), 0, -1); ?>action\/[_a-zA-Z0-9\/]+.*$/.exec(href)) {
return;
}

View File

@ -12,19 +12,19 @@ if (!defined('__TYPECHO_ROOT_DIR__') && !@include_once __DIR__ . '/../config.inc
}
/** 初始化组件 */
Typecho_Widget::widget('Widget_Init');
\Widget\Init::alloc();
/** 注册一个初始化插件 */
Typecho_Plugin::factory('admin/common.php')->begin();
\Typecho\Plugin::factory('admin/common.php')->begin();
Typecho_Widget::widget('Widget_Options')->to($options);
Typecho_Widget::widget('Widget_User')->to($user);
Typecho_Widget::widget('Widget_Security')->to($security);
Typecho_Widget::widget('Widget_Menu')->to($menu);
\Widget\Options::alloc()->to($options);
\Widget\User::alloc()->to($user);
\Widget\Security::alloc()->to($security);
\Widget\Menu::alloc()->to($menu);
/** 初始化上下文 */
$request = Typecho_Request::getInstance();
$response = Typecho_Response::getInstance();
$request = $options->request;
$response = $options->response;
/** 检测是否是第一次登录 */
$currentMenu = $menu->getCurrentMenu();
@ -33,22 +33,21 @@ if (!empty($currentMenu)) {
$params = parse_url($currentMenu[2]);
$adminFile = basename($params['path']);
if (!$user->logged && !Typecho_Cookie::get('__typecho_first_run')) {
if (!$user->logged && !\Typecho\Cookie::get('__typecho_first_run')) {
if ('welcome.php' != $adminFile) {
$response->redirect(Typecho_Common::url('welcome.php', $options->adminUrl));
$response->redirect(\Typecho\Common::url('welcome.php', $options->adminUrl));
} else {
Typecho_Cookie::set('__typecho_first_run', 1);
\Typecho\Cookie::set('__typecho_first_run', 1);
}
} elseif ($user->pass('administrator', true)) {
/** 检测版本是否升级 */
$mustUpgrade = version_compare(Typecho_Common::VERSION, $options->version, '>');
$mustUpgrade = version_compare(\Typecho\Common::VERSION, $options->version, '>');
if ($mustUpgrade && 'upgrade.php' != $adminFile && 'backup.php' != $adminFile) {
$response->redirect(Typecho_Common::url('upgrade.php', $options->adminUrl));
} else if (!$mustUpgrade && 'upgrade.php' == $adminFile) {
$response->redirect(\Typecho\Common::url('upgrade.php', $options->adminUrl));
} elseif (!$mustUpgrade && 'upgrade.php' == $adminFile) {
$response->redirect($options->adminUrl);
} else if (!$mustUpgrade && 'welcome.php' == $adminFile && $user->logged) {
} elseif (!$mustUpgrade && 'welcome.php' == $adminFile && $user->logged) {
$response->redirect($options->adminUrl);
}
}

View File

@ -23,6 +23,8 @@ a.button:hover, a.balloon-button:hover { background-color: #A5CADC; color: #FFF;
/** Forms */
input[type=text], input[type=password], input[type=email], textarea { background: #FFF; border: 1px solid #D9D9D6; padding: 7px; border-radius: 2px; box-sizing: border-box; }
input[type=text]:disabled, input[type=text]:read-only, input[type=password]:disabled, input[type=password]:read-only, input[type=email]:disabled, input[type=email]:read-only, textarea:disabled, textarea:read-only { background: #F3F3F3; }
textarea { resize: vertical; line-height: 1.5; }
input[type="radio"], input[type="checkbox"] { margin-right: 3px; }
@ -203,9 +205,6 @@ select { border: 1px solid #CCC; height: 28px; }
.typecho-foot .resource a { margin: 0 3px; color: #999; }
/* 低版本浏览器升级提示 */
.browsehappy { border: none; text-align: center; }
/** 顶部消息样式 by 70 */
.popup { display: none; position: absolute; top: 0; left: 0; margin: 0; padding: 8px 0; border: none; width: 100%; z-index: 10; text-align: center; border-radius: 0; }

View File

@ -1,73 +1,82 @@
<?php if(!defined('__TYPECHO_ADMIN__')) exit; ?>
<?php if (!defined('__TYPECHO_ADMIN__')) exit; ?>
<?php
$fields = isset($post) ? $post->getFieldItems() : $page->getFieldItems();
$defaultFields = isset($post) ? $post->getDefaultFieldItems() : $page->getDefaultFieldItems();
?>
<section id="custom-field" class="typecho-post-option<?php if (empty($defaultFields) && empty($fields)): ?> fold<?php endif; ?>">
<label id="custom-field-expand" class="typecho-label"><a href="##"><i class="i-caret-right"></i> <?php _e('自定义字段'); ?></a></label>
<table class="typecho-list-table mono">
<colgroup>
<col width="25%"/>
<col width="10%"/>
<col width="55%"/>
<col width="10%"/>
</colgroup>
<?php foreach ($defaultFields as $field): ?>
<?php list ($label, $input) = $field; ?>
<tr>
<td><?php $label->render(); ?></td>
<td colspan="3"><?php $input->render(); ?></td>
</tr>
<?php endforeach; ?>
<?php foreach ($fields as $field): ?>
<tr>
<td>
<label for="fieldname" class="sr-only"><?php _e('字段名称'); ?></label>
<input type="text" name="fieldNames[]" value="<?php echo htmlspecialchars($field['name']); ?>" id="fieldname" class="text-s w-100">
</td>
<td>
<label for="fieldtype" class="sr-only"><?php _e('字段类型'); ?></label>
<select name="fieldTypes[]" id="fieldtype">
<option value="str"<?php if ('str' == $field['type']): ?> selected<?php endif; ?>><?php _e('字符'); ?></option>
<option value="int"<?php if ('int' == $field['type']): ?> selected<?php endif; ?>><?php _e('整数'); ?></option>
<option value="float"<?php if ('float' == $field['type']): ?> selected<?php endif; ?>><?php _e('小数'); ?></option>
</select>
</td>
<td>
<label for="fieldvalue" class="sr-only"><?php _e('字段值'); ?></label>
<textarea name="fieldValues[]" id="fieldvalue" class="text-s w-100" rows="2"><?php echo htmlspecialchars($field[$field['type'] . '_value']); ?></textarea>
</td>
<td>
<button type="button" class="btn btn-xs"><?php _e('删除'); ?></button>
</td>
</tr>
<?php endforeach; ?>
<?php if (empty($defaultFields) && empty($fields)): ?>
<tr>
<td>
<label for="fieldname" class="sr-only"><?php _e('字段名称'); ?></label>
<input type="text" name="fieldNames[]" placeholder="<?php _e('字段名称'); ?>" id="fieldname" class="text-s w-100">
</td>
<td>
<label for="fieldtype" class="sr-only"><?php _e('字段类型'); ?></label>
<select name="fieldTypes[]" id="fieldtype">
<option value="str"><?php _e('字符'); ?></option>
<option value="int"><?php _e('整数'); ?></option>
<option value="float"><?php _e('小数'); ?></option>
</select>
</td>
<td>
<label for="fieldvalue" class="sr-only"><?php _e('字段值'); ?></label>
<textarea name="fieldValues[]" placeholder="<?php _e('字段值'); ?>" id="fieldvalue" class="text-s w-100" rows="2"></textarea>
</td>
<td>
<button type="button" class="btn btn-xs"><?php _e('删除'); ?></button>
</td>
</tr>
<?php endif; ?>
</table>
<div class="description clearfix">
<button type="button" class="btn btn-xs operate-add"><?php _e('+添加字段'); ?></button>
<?php _e('自定义字段可以扩展你的模板功能, 使用方法参见 <a href="http://docs.typecho.org/help/custom-fields">帮助文档</a>'); ?>
</div>
</section>
<section id="custom-field"
class="typecho-post-option<?php if (empty($defaultFields) && empty($fields)): ?> fold<?php endif; ?>">
<label id="custom-field-expand" class="typecho-label"><a href="##"><i
class="i-caret-right"></i> <?php _e('自定义字段'); ?></a></label>
<table class="typecho-list-table mono">
<colgroup>
<col width="25%"/>
<col width="10%"/>
<col width="55%"/>
<col width="10%"/>
</colgroup>
<?php foreach ($defaultFields as $field): ?>
<?php [$label, $input] = $field; ?>
<tr>
<td><?php $label->render(); ?></td>
<td colspan="3"><?php $input->render(); ?></td>
</tr>
<?php endforeach; ?>
<?php foreach ($fields as $field): ?>
<tr>
<td>
<label for="fieldname" class="sr-only"><?php _e('字段名称'); ?></label>
<input type="text" name="fieldNames[]" value="<?php echo htmlspecialchars($field['name']); ?>"
id="fieldname" class="text-s w-100">
</td>
<td>
<label for="fieldtype" class="sr-only"><?php _e('字段类型'); ?></label>
<select name="fieldTypes[]" id="fieldtype">
<option
value="str"<?php if ('str' == $field['type']): ?> selected<?php endif; ?>><?php _e('字符'); ?></option>
<option
value="int"<?php if ('int' == $field['type']): ?> selected<?php endif; ?>><?php _e('整数'); ?></option>
<option
value="float"<?php if ('float' == $field['type']): ?> selected<?php endif; ?>><?php _e('小数'); ?></option>
</select>
</td>
<td>
<label for="fieldvalue" class="sr-only"><?php _e('字段值'); ?></label>
<textarea name="fieldValues[]" id="fieldvalue" class="text-s w-100"
rows="2"><?php echo htmlspecialchars($field[$field['type'] . '_value']); ?></textarea>
</td>
<td>
<button type="button" class="btn btn-xs"><?php _e('删除'); ?></button>
</td>
</tr>
<?php endforeach; ?>
<?php if (empty($defaultFields) && empty($fields)): ?>
<tr>
<td>
<label for="fieldname" class="sr-only"><?php _e('字段名称'); ?></label>
<input type="text" name="fieldNames[]" placeholder="<?php _e('字段名称'); ?>" id="fieldname"
class="text-s w-100">
</td>
<td>
<label for="fieldtype" class="sr-only"><?php _e('字段类型'); ?></label>
<select name="fieldTypes[]" id="fieldtype">
<option value="str"><?php _e('字符'); ?></option>
<option value="int"><?php _e('整数'); ?></option>
<option value="float"><?php _e('小数'); ?></option>
</select>
</td>
<td>
<label for="fieldvalue" class="sr-only"><?php _e('字段值'); ?></label>
<textarea name="fieldValues[]" placeholder="<?php _e('字段值'); ?>" id="fieldvalue"
class="text-s w-100" rows="2"></textarea>
</td>
<td>
<button type="button" class="btn btn-xs"><?php _e('删除'); ?></button>
</td>
</tr>
<?php endif; ?>
</table>
<div class="description clearfix">
<button type="button" class="btn btn-xs operate-add"><?php _e('+添加字段'); ?></button>
<?php _e('自定义字段可以扩展你的模板功能, 使用方法参见 <a href="http://docs.typecho.org/help/custom-fields">帮助文档</a>'); ?>
</div>
</section>

View File

@ -109,7 +109,7 @@ $(document).ready(function () {
}
});
<?php Typecho_Plugin::factory('admin/editor-js.php')->markdownEditor($content); ?>
<?php \Typecho\Plugin::factory('admin/editor-js.php')->markdownEditor($content); ?>
var th = textarea.height(), ph = preview.height(),
uploadBtn = $('<button type="button" id="btn-fullscreen-upload" class="btn btn-link">'

View File

@ -1,13 +1,14 @@
<?php
include 'common.php';
$panel = $request->get('panel');
$panelTable = unserialize($options->panelTable);
if (!isset($panelTable['file']) || !in_array(urlencode($panel), $panelTable['file'])) {
throw new Typecho_Plugin_Exception(_t('页面不存在'), 404);
throw new \Typecho\Plugin\Exception(_t('页面不存在'), 404);
}
list ($pluginName, $file) = explode('/', trim($panel, '/'), 2);
[$pluginName, $file] = explode('/', trim($panel, '/'), 2);
require_once $options->pluginDir($pluginName) . '/' . $panel;
require_once $options->pluginDir($pluginName) . '/' . $file;

View File

@ -1,8 +1,8 @@
<?php if(!defined('__TYPECHO_ADMIN__')) exit; ?>
<?php
if (isset($post) && $post instanceof Typecho_Widget && $post->have()) {
if (isset($post) && $post instanceof \Typecho\Widget && $post->have()) {
$fileParentContent = $post;
} else if (isset($page) && $page instanceof Typecho_Widget && $page->have()) {
} elseif (isset($page) && $page instanceof \Typecho\Widget && $page->have()) {
$fileParentContent = $page;
}

View File

@ -5,9 +5,9 @@ if (isset($post) || isset($page)) {
$cid = isset($post) ? $post->cid : $page->cid;
if ($cid) {
Typecho_Widget::widget('Widget_Contents_Attachment_Related', 'parentId=' . $cid)->to($attachment);
\Widget\Contents\Related::alloc(['parentId' => $cid])->to($attachment);
} else {
Typecho_Widget::widget('Widget_Contents_Attachment_Unattached')->to($attachment);
\Widget\Contents\Attachment\Unattached::alloc()->to($attachment);
}
}
?>

View File

@ -3,4 +3,4 @@
</html>
<?php
/** 注册一个结束插件 */
Typecho_Plugin::factory('admin/footer.php')->end();
\Typecho\Plugin::factory('admin/footer.php')->end();

View File

@ -8,7 +8,7 @@ $header = '<link rel="stylesheet" href="' . $options->adminStaticUrl('css', 'nor
<link rel="stylesheet" href="' . $options->adminStaticUrl('css', 'style.css', true) . '">';
/** 注册一个初始化插件 */
$header = Typecho_Plugin::factory('admin/header.php')->header($header);
$header = \Typecho\Plugin::factory('admin/header.php')->header($header);
?><!DOCTYPE HTML>
<html>
@ -21,6 +21,3 @@ $header = Typecho_Plugin::factory('admin/header.php')->header($header);
<?php echo $header; ?>
</head>
<body<?php if (isset($bodyClass)) {echo ' class="' . $bodyClass . '"';} ?>>
<!--[if lt IE 9]>
<div class="message error browsehappy" role="dialog"><?php _e('当前网页 <strong>不支持</strong> 你正在使用的浏览器. 为了正常的访问, 请 <a href="http://browsehappy.com/">升级你的浏览器</a>'); ?>.</div>
<![endif]-->

View File

@ -3,7 +3,7 @@ include 'common.php';
include 'header.php';
include 'menu.php';
$stat = Typecho_Widget::widget('Widget_Stat');
$stat = \Widget\Stat::alloc();
?>
<div class="main">
<div class="container typecho-dashboard">
@ -11,35 +11,40 @@ $stat = Typecho_Widget::widget('Widget_Stat');
<div class="row typecho-page-main">
<div class="col-mb-12 welcome-board" role="main">
<p><?php _e('目前有 <em>%s</em> 篇文章, 并有 <em>%s</em> 条关于你的评论在 <em>%s</em> 个分类中.',
$stat->myPublishedPostsNum, $stat->myPublishedCommentsNum, $stat->categoriesNum); ?>
<br><?php _e('点击下面的链接快速开始:'); ?></p>
$stat->myPublishedPostsNum, $stat->myPublishedCommentsNum, $stat->categoriesNum); ?>
<br><?php _e('点击下面的链接快速开始:'); ?></p>
<ul id="start-link" class="clearfix">
<?php if($user->pass('contributor', true)): ?>
<li><a href="<?php $options->adminUrl('write-post.php'); ?>"><?php _e('撰写新文章'); ?></a></li>
<?php if($user->pass('editor', true) && 'on' == $request->get('__typecho_all_comments') && $stat->waitingCommentsNum > 0): ?>
<li><a href="<?php $options->adminUrl('manage-comments.php?status=waiting'); ?>"><?php _e('待审核的评论'); ?></a>
<span class="balloon"><?php $stat->waitingCommentsNum(); ?></span>
</li>
<?php elseif($stat->myWaitingCommentsNum > 0): ?>
<li><a href="<?php $options->adminUrl('manage-comments.php?status=waiting'); ?>"><?php _e('待审核评论'); ?></a>
<span class="balloon"><?php $stat->myWaitingCommentsNum(); ?></span>
</li>
<?php endif; ?>
<?php if($user->pass('editor', true) && 'on' == $request->get('__typecho_all_comments') && $stat->spamCommentsNum > 0): ?>
<li><a href="<?php $options->adminUrl('manage-comments.php?status=spam'); ?>"><?php _e('垃圾评论'); ?></a>
<span class="balloon"><?php $stat->spamCommentsNum(); ?></span>
</li>
<?php elseif($stat->mySpamCommentsNum > 0): ?>
<li><a href="<?php $options->adminUrl('manage-comments.php?status=spam'); ?>"><?php _e('垃圾评论'); ?></a>
<span class="balloon"><?php $stat->mySpamCommentsNum(); ?></span>
</li>
<?php endif; ?>
<?php if($user->pass('administrator', true)): ?>
<li><a href="<?php $options->adminUrl('themes.php'); ?>"><?php _e('更换外观'); ?></a></li>
<li><a href="<?php $options->adminUrl('plugins.php'); ?>"><?php _e('插件管理'); ?></a></li>
<li><a href="<?php $options->adminUrl('options-general.php'); ?>"><?php _e('系统设置'); ?></a></li>
<?php endif; ?>
<?php if ($user->pass('contributor', true)): ?>
<li><a href="<?php $options->adminUrl('write-post.php'); ?>"><?php _e('撰写新文章'); ?></a></li>
<?php if ($user->pass('editor', true) && 'on' == $request->get('__typecho_all_comments') && $stat->waitingCommentsNum > 0): ?>
<li>
<a href="<?php $options->adminUrl('manage-comments.php?status=waiting'); ?>"><?php _e('待审核的评论'); ?></a>
<span class="balloon"><?php $stat->waitingCommentsNum(); ?></span>
</li>
<?php elseif ($stat->myWaitingCommentsNum > 0): ?>
<li>
<a href="<?php $options->adminUrl('manage-comments.php?status=waiting'); ?>"><?php _e('待审核评论'); ?></a>
<span class="balloon"><?php $stat->myWaitingCommentsNum(); ?></span>
</li>
<?php endif; ?>
<?php if ($user->pass('editor', true) && 'on' == $request->get('__typecho_all_comments') && $stat->spamCommentsNum > 0): ?>
<li>
<a href="<?php $options->adminUrl('manage-comments.php?status=spam'); ?>"><?php _e('垃圾评论'); ?></a>
<span class="balloon"><?php $stat->spamCommentsNum(); ?></span>
</li>
<?php elseif ($stat->mySpamCommentsNum > 0): ?>
<li>
<a href="<?php $options->adminUrl('manage-comments.php?status=spam'); ?>"><?php _e('垃圾评论'); ?></a>
<span class="balloon"><?php $stat->mySpamCommentsNum(); ?></span>
</li>
<?php endif; ?>
<?php if ($user->pass('administrator', true)): ?>
<li><a href="<?php $options->adminUrl('themes.php'); ?>"><?php _e('更换外观'); ?></a></li>
<li><a href="<?php $options->adminUrl('plugins.php'); ?>"><?php _e('插件管理'); ?></a></li>
<li><a href="<?php $options->adminUrl('options-general.php'); ?>"><?php _e('系统设置'); ?></a>
</li>
<?php endif; ?>
<?php endif; ?>
<!--<li><a href="<?php $options->adminUrl('profile.php'); ?>"><?php _e('更新我的资料'); ?></a></li>-->
</ul>
@ -48,18 +53,18 @@ $stat = Typecho_Widget::widget('Widget_Stat');
<div class="col-mb-12 col-tb-4" role="complementary">
<section class="latest-link">
<h3><?php _e('最近发布的文章'); ?></h3>
<?php Typecho_Widget::widget('Widget_Contents_Post_Recent', 'pageSize=10')->to($posts); ?>
<?php \Widget\Contents\Post\Recent::alloc('pageSize=10')->to($posts); ?>
<ul>
<?php if($posts->have()): ?>
<?php while($posts->next()): ?>
<li>
<span><?php $posts->date('n.j'); ?></span>
<a href="<?php $posts->permalink(); ?>" class="title"><?php $posts->title(); ?></a>
</li>
<?php endwhile; ?>
<?php else: ?>
<li><em><?php _e('暂时没有文章'); ?></em></li>
<?php endif; ?>
<?php if ($posts->have()): ?>
<?php while ($posts->next()): ?>
<li>
<span><?php $posts->date('n.j'); ?></span>
<a href="<?php $posts->permalink(); ?>" class="title"><?php $posts->title(); ?></a>
</li>
<?php endwhile; ?>
<?php else: ?>
<li><em><?php _e('暂时没有文章'); ?></em></li>
<?php endif; ?>
</ul>
</section>
</div>
@ -68,17 +73,18 @@ $stat = Typecho_Widget::widget('Widget_Stat');
<section class="latest-link">
<h3><?php _e('最近得到的回复'); ?></h3>
<ul>
<?php Typecho_Widget::widget('Widget_Comments_Recent', 'pageSize=10')->to($comments); ?>
<?php if($comments->have()): ?>
<?php while($comments->next()): ?>
<li>
<span><?php $comments->date('n.j'); ?></span>
<a href="<?php $comments->permalink(); ?>" class="title"><?php $comments->author(false); ?></a>:
<?php $comments->excerpt(35, '...'); ?>
</li>
<?php endwhile; ?>
<?php \Widget\Comments\Recent::alloc('pageSize=10')->to($comments); ?>
<?php if ($comments->have()): ?>
<?php while ($comments->next()): ?>
<li>
<span><?php $comments->date('n.j'); ?></span>
<a href="<?php $comments->permalink(); ?>"
class="title"><?php $comments->author(false); ?></a>:
<?php $comments->excerpt(35, '...'); ?>
</li>
<?php endwhile; ?>
<?php else: ?>
<li><?php _e('暂时没有回复'); ?></li>
<li><?php _e('暂时没有回复'); ?></li>
<?php endif; ?>
</ul>
</section>
@ -104,46 +110,46 @@ include 'common-js.php';
?>
<script>
$(document).ready(function () {
var ul = $('#typecho-message ul'), cache = window.sessionStorage,
html = cache ? cache.getItem('feed') : '',
update = cache ? cache.getItem('update') : '';
if (!!html) {
ul.html(html);
} else {
html = '';
$.get('<?php $options->index('/action/ajax?do=feed'); ?>', function (o) {
for (var i = 0; i < o.length; i ++) {
var item = o[i];
html += '<li><span>' + item.date + '</span> <a href="' + item.link + '" target="_blank">' + item.title
+ '</a></li>';
}
$(document).ready(function () {
var ul = $('#typecho-message ul'), cache = window.sessionStorage,
html = cache ? cache.getItem('feed') : '',
update = cache ? cache.getItem('update') : '';
if (!!html) {
ul.html(html);
cache.setItem('feed', html);
}, 'json');
}
} else {
html = '';
$.get('<?php $options->index('/action/ajax?do=feed'); ?>', function (o) {
for (var i = 0; i < o.length; i++) {
var item = o[i];
html += '<li><span>' + item.date + '</span> <a href="' + item.link + '" target="_blank">' + item.title
+ '</a></li>';
}
function applyUpdate(update) {
if (update.available) {
$('<div class="update-check message error"><p>'
+ '<?php _e('您当前使用的版本是 %s'); ?>'.replace('%s', update.current) + '<br />'
+ '<strong><a href="' + update.link + '" target="_blank">'
+ '<?php _e('官方最新版本是 %s'); ?>'.replace('%s', update.latest) + '</a></strong></p></div>')
.insertAfter('.typecho-page-title').effect('highlight');
ul.html(html);
cache.setItem('feed', html);
}, 'json');
}
}
if (!!update) {
applyUpdate($.parseJSON(update));
} else {
$.get('<?php $options->index('/action/ajax?do=checkVersion'); ?>', function (o, status, resp) {
applyUpdate(o);
cache.setItem('update', resp.responseText);
}, 'json');
}
});
function applyUpdate(update) {
if (update.available) {
$('<div class="update-check message error"><p>'
+ '<?php _e('您当前使用的版本是 %s'); ?>'.replace('%s', update.current) + '<br />'
+ '<strong><a href="' + update.link + '" target="_blank">'
+ '<?php _e('官方最新版本是 %s'); ?>'.replace('%s', update.latest) + '</a></strong></p></div>')
.insertAfter('.typecho-page-title').effect('highlight');
}
}
if (!!update) {
applyUpdate($.parseJSON(update));
} else {
$.get('<?php $options->index('/action/ajax?do=checkVersion'); ?>', function (o, status, resp) {
applyUpdate(o);
cache.setItem('update', resp.responseText);
}, 'json');
}
});
</script>
<?php include 'footer.php'; ?>

View File

@ -4,8 +4,8 @@ include 'common.php';
if ($user->hasLogin()) {
$response->redirect($options->adminUrl);
}
$rememberName = htmlspecialchars(Typecho_Cookie::get('__typecho_remember_name'));
Typecho_Cookie::delete('__typecho_remember_name');
$rememberName = htmlspecialchars(\Typecho\Cookie::get('__typecho_remember_name'));
\Typecho\Cookie::delete('__typecho_remember_name');
$bodyClass = 'body-100';

View File

@ -3,27 +3,35 @@ include 'common.php';
include 'header.php';
include 'menu.php';
Typecho_Widget::widget('Widget_Metas_Category_Admin')->to($categories);
\Widget\Metas\Category\Admin::alloc()->to($categories);
?>
<div class="main">
<div class="body container">
<?php include 'page-title.php'; ?>
<div class="row typecho-page-main manage-metas">
<div class="col-mb-12" role="main">
<form method="post" name="manage_categories" class="operate-form">
<div class="col-mb-12" role="main">
<form method="post" name="manage_categories" class="operate-form">
<div class="typecho-list-operate clearfix">
<div class="operate">
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox" class="typecho-table-select-all" /></label>
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox"
class="typecho-table-select-all"/></label>
<div class="btn-group btn-drop">
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i class="i-caret-down"></i></button>
<button class="btn dropdown-toggle btn-s" type="button"><i
class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i
class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('此分类下的所有内容将被删除, 你确认要删除这些分类吗?'); ?>" href="<?php $security->index('/action/metas-category-edit?do=delete'); ?>"><?php _e('删除'); ?></a></li>
<li><a lang="<?php _e('刷新分类可能需要等待较长时间, 你确认要刷新这些分类吗?'); ?>" href="<?php $security->index('/action/metas-category-edit?do=refresh'); ?>"><?php _e('刷新'); ?></a></li>
<li><a lang="<?php _e('此分类下的所有内容将被删除, 你确认要删除这些分类吗?'); ?>"
href="<?php $security->index('/action/metas-category-edit?do=delete'); ?>"><?php _e('删除'); ?></a>
</li>
<li><a lang="<?php _e('刷新分类可能需要等待较长时间, 你确认要刷新这些分类吗?'); ?>"
href="<?php $security->index('/action/metas-category-edit?do=refresh'); ?>"><?php _e('刷新'); ?></a>
</li>
<li class="multiline">
<button type="button" class="btn merge btn-s" rel="<?php $security->index('/action/metas-category-edit?do=merge'); ?>"><?php _e('合并到'); ?></button>
<button type="button" class="btn merge btn-s"
rel="<?php $security->index('/action/metas-category-edit?do=merge'); ?>"><?php _e('合并到'); ?></button>
<select name="merge">
<?php $categories->parse('<option value="{mid}">{name}</option>'); ?>
</select>
@ -47,53 +55,63 @@ Typecho_Widget::widget('Widget_Metas_Category_Admin')->to($categories);
<col width="10%" class="kit-hidden-mb"/>
</colgroup>
<thead>
<tr class="nodrag">
<th class="kit-hidden-mb"> </th>
<th><?php _e('名称'); ?></th>
<th><?php _e('子分类'); ?></th>
<th class="kit-hidden-mb"><?php _e('缩略名'); ?></th>
<th> </th>
<th class="kit-hidden-mb"><?php _e('文章数'); ?></th>
</tr>
<tr class="nodrag">
<th class="kit-hidden-mb"></th>
<th><?php _e('名称'); ?></th>
<th><?php _e('子分类'); ?></th>
<th class="kit-hidden-mb"><?php _e('缩略名'); ?></th>
<th></th>
<th class="kit-hidden-mb"><?php _e('文章数'); ?></th>
</tr>
</thead>
<tbody>
<?php if($categories->have()): ?>
<?php if ($categories->have()): ?>
<?php while ($categories->next()): ?>
<tr id="mid-<?php $categories->theId(); ?>">
<td class="kit-hidden-mb"><input type="checkbox" value="<?php $categories->mid(); ?>" name="mid[]"/></td>
<td><a href="<?php $options->adminUrl('category.php?mid=' . $categories->mid); ?>"><?php $categories->name(); ?></a>
<a href="<?php $categories->permalink(); ?>" title="<?php _e('浏览 %s', $categories->name); ?>"><i class="i-exlink"></i></a>
</td>
<td>
<?php if (count($categories->children) > 0): ?>
<a href="<?php $options->adminUrl('manage-categories.php?parent=' . $categories->mid); ?>"><?php echo _n('一个分类', '%d个分类', count($categories->children)); ?></a>
<?php else: ?>
<a href="<?php $options->adminUrl('category.php?parent=' . $categories->mid); ?>"><?php echo _e('新增'); ?></a>
<?php endif; ?>
</td>
<td class="kit-hidden-mb"><?php $categories->slug(); ?></td>
<td>
<?php if ($options->defaultCategory == $categories->mid): ?>
<?php _e('默认'); ?>
<?php else: ?>
<a class="hidden-by-mouse" href="<?php $security->index('/action/metas-category-edit?do=default&mid=' . $categories->mid); ?>" title="<?php _e('设为默认'); ?>"><?php _e('默认'); ?></a>
<?php endif; ?>
</td>
<td class="kit-hidden-mb"><a class="balloon-button left size-<?php echo Typecho_Common::splitByCount($categories->count, 1, 10, 20, 50, 100); ?>" href="<?php $options->adminUrl('manage-posts.php?category=' . $categories->mid); ?>"><?php $categories->count(); ?></a></td>
</tr>
<tr id="mid-<?php $categories->theId(); ?>">
<td class="kit-hidden-mb"><input type="checkbox"
value="<?php $categories->mid(); ?>"
name="mid[]"/></td>
<td>
<a href="<?php $options->adminUrl('category.php?mid=' . $categories->mid); ?>"><?php $categories->name(); ?></a>
<a href="<?php $categories->permalink(); ?>"
title="<?php _e('浏览 %s', $categories->name); ?>"><i class="i-exlink"></i></a>
</td>
<td>
<?php if (count($categories->children) > 0): ?>
<a href="<?php $options->adminUrl('manage-categories.php?parent=' . $categories->mid); ?>"><?php echo _n('一个分类', '%d个分类', count($categories->children)); ?></a>
<?php else: ?>
<a href="<?php $options->adminUrl('category.php?parent=' . $categories->mid); ?>"><?php echo _e('新增'); ?></a>
<?php endif; ?>
</td>
<td class="kit-hidden-mb"><?php $categories->slug(); ?></td>
<td>
<?php if ($options->defaultCategory == $categories->mid): ?>
<?php _e('默认'); ?>
<?php else: ?>
<a class="hidden-by-mouse"
href="<?php $security->index('/action/metas-category-edit?do=default&mid=' . $categories->mid); ?>"
title="<?php _e('设为默认'); ?>"><?php _e('默认'); ?></a>
<?php endif; ?>
</td>
<td class="kit-hidden-mb"><a
class="balloon-button left size-<?php echo \Typecho\Common::splitByCount($categories->count, 1, 10, 20, 50, 100); ?>"
href="<?php $options->adminUrl('manage-posts.php?category=' . $categories->mid); ?>"><?php $categories->count(); ?></a>
</td>
</tr>
<?php endwhile; ?>
<?php else: ?>
<?php else: ?>
<tr>
<td colspan="6"><h6 class="typecho-list-table-title"><?php _e('没有任何分类'); ?></h6></td>
<td colspan="6"><h6 class="typecho-list-table-title"><?php _e('没有任何分类'); ?></h6>
</td>
</tr>
<?php endif; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</form>
</div>
</form>
</div>
</div>
</div>
</div>
@ -104,51 +122,51 @@ include 'common-js.php';
?>
<script type="text/javascript">
(function () {
$(document).ready(function () {
var table = $('.typecho-list-table').tableDnD({
onDrop : function () {
var ids = [];
(function () {
$(document).ready(function () {
var table = $('.typecho-list-table').tableDnD({
onDrop: function () {
var ids = [];
$('input[type=checkbox]', table).each(function () {
ids.push($(this).val());
});
$('input[type=checkbox]', table).each(function () {
ids.push($(this).val());
});
$.post('<?php $security->index('/action/metas-category-edit?do=sort'); ?>',
$.param({mid : ids}));
$.post('<?php $security->index('/action/metas-category-edit?do=sort'); ?>',
$.param({mid: ids}));
$('tr', table).each(function (i) {
if (i % 2) {
$(this).addClass('even');
} else {
$(this).removeClass('even');
}
});
}
$('tr', table).each(function (i) {
if (i % 2) {
$(this).addClass('even');
} else {
$(this).removeClass('even');
}
});
}
});
table.tableSelectable({
checkEl: 'input[type=checkbox]',
rowEl: 'tr',
selectAllEl: '.typecho-table-select-all',
actionEl: '.dropdown-menu a'
});
$('.btn-drop').dropdownMenu({
btnEl: '.dropdown-toggle',
menuEl: '.dropdown-menu'
});
$('.dropdown-menu button.merge').click(function () {
var btn = $(this);
btn.parents('form').attr('action', btn.attr('rel')).submit();
});
<?php if (isset($request->mid)): ?>
$('.typecho-mini-panel').effect('highlight', '#AACB36');
<?php endif; ?>
});
table.tableSelectable({
checkEl : 'input[type=checkbox]',
rowEl : 'tr',
selectAllEl : '.typecho-table-select-all',
actionEl : '.dropdown-menu a'
});
$('.btn-drop').dropdownMenu({
btnEl : '.dropdown-toggle',
menuEl : '.dropdown-menu'
});
$('.dropdown-menu button.merge').click(function () {
var btn = $(this);
btn.parents('form').attr('action', btn.attr('rel')).submit();
});
<?php if (isset($request->mid)): ?>
$('.typecho-mini-panel').effect('highlight', '#AACB36');
<?php endif; ?>
});
})();
})();
</script>
<?php include 'footer.php'; ?>

View File

@ -3,9 +3,9 @@ include 'common.php';
include 'header.php';
include 'menu.php';
$stat = Typecho_Widget::widget('Widget_Stat');
$comments = Typecho_Widget::widget('Widget_Comments_Admin');
$isAllComments = ('on' == $request->get('__typecho_all_comments') || 'on' == Typecho_Cookie::get('__typecho_all_comments'));
$stat = \Widget\Stat::alloc();
$comments = \Widget\Comments\Admin::alloc();
$isAllComments = ('on' == $request->get('__typecho_all_comments') || 'on' == \Typecho\Cookie::get('__typecho_all_comments'));
?>
<div class="main">
<div class="body container">
@ -112,7 +112,7 @@ $isAllComments = ('on' == $request->get('__typecho_all_comments') || 'on' == Typ
'text' => $comments->text
);
echo htmlspecialchars(Json::encode($comment));
echo htmlspecialchars(json_encode($comment));
?>">
<td valign="top" class="kit-hidden-mb">
<input type="checkbox" value="<?php $comments->coid(); ?>" name="coid[]"/>

View File

@ -3,112 +3,134 @@ include 'common.php';
include 'header.php';
include 'menu.php';
$stat = Typecho_Widget::widget('Widget_Stat');
$stat = \Widget\Stat::alloc();
$attachments = \Widget\Contents\Attachment\Admin::alloc();
?>
<?php Typecho_Widget::widget('Widget_Contents_Attachment_Admin')->to($attachments); ?>
<div class="main">
<div class="body container">
<?php include 'page-title.php'; ?>
<div class="row typecho-page-main" role="main">
<div class="col-mb-12">
<div class="typecho-list-operate clearfix">
<form method="get">
<div class="operate">
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox" class="typecho-table-select-all" /></label>
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox"
class="typecho-table-select-all"/></label>
<div class="btn-group btn-drop">
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('你确认要删除这些文件吗?'); ?>" href="<?php $security->index('/action/contents-attachment-edit?do=delete'); ?>"><?php _e('删除'); ?></a></li>
</ul>
<button class="btn btn-s btn-warn btn-operate" href="<?php $security->index('/action/contents-attachment-edit?do=clear'); ?>" lang="<?php _e('您确认要清理未归档的文件吗?'); ?>"><?php _e('清理未归档文件'); ?></button>
<button class="btn dropdown-toggle btn-s" type="button"><i
class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i
class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('你确认要删除这些文件吗?'); ?>"
href="<?php $security->index('/action/contents-attachment-edit?do=delete'); ?>"><?php _e('删除'); ?></a>
</li>
</ul>
<button class="btn btn-s btn-warn btn-operate"
href="<?php $security->index('/action/contents-attachment-edit?do=clear'); ?>"
lang="<?php _e('您确认要清理未归档的文件吗?'); ?>"><?php _e('清理未归档文件'); ?></button>
</div>
</div>
<div class="search" role="search">
<?php if ('' != $request->keywords): ?>
<a href="<?php $options->adminUrl('manage-medias.php'); ?>"><?php _e('&laquo; 取消筛选'); ?></a>
<a href="<?php $options->adminUrl('manage-medias.php'); ?>"><?php _e('&laquo; 取消筛选'); ?></a>
<?php endif; ?>
<input type="text" class="text-s" placeholder="<?php _e('请输入关键字'); ?>" value="<?php echo htmlspecialchars($request->keywords); ?>"<?php if ('' == $request->keywords): ?> onclick="value='';name='keywords';" <?php else: ?> name="keywords"<?php endif; ?>/>
<input type="text" class="text-s" placeholder="<?php _e('请输入关键字'); ?>"
value="<?php echo htmlspecialchars($request->keywords); ?>"<?php if ('' == $request->keywords): ?> onclick="value='';name='keywords';" <?php else: ?> name="keywords"<?php endif; ?>/>
<button type="submit" class="btn btn-s"><?php _e('筛选'); ?></button>
</div>
</form>
</div><!-- end .typecho-list-operate -->
<form method="post" name="manage_medias" class="operate-form">
<div class="typecho-table-wrap">
<table class="typecho-list-table draggable">
<colgroup>
<col width="20" class="kit-hidden-mb"/>
<col width="6%" class="kit-hidden-mb"/>
<col width="30%"/>
<col width="" class="kit-hidden-mb"/>
<col width="30%" class="kit-hidden-mb"/>
<col width="16%"/>
</colgroup>
<thead>
<div class="typecho-table-wrap">
<table class="typecho-list-table draggable">
<colgroup>
<col width="20" class="kit-hidden-mb"/>
<col width="6%" class="kit-hidden-mb"/>
<col width="30%"/>
<col width="" class="kit-hidden-mb"/>
<col width="30%" class="kit-hidden-mb"/>
<col width="16%"/>
</colgroup>
<thead>
<tr>
<th class="kit-hidden-mb"> </th>
<th class="kit-hidden-mb"> </th>
<th class="kit-hidden-mb"></th>
<th class="kit-hidden-mb"></th>
<th><?php _e('文件名'); ?></th>
<th class="kit-hidden-mb"><?php _e('上传者'); ?></th>
<th class="kit-hidden-mb"><?php _e('所属文章'); ?></th>
<th><?php _e('发布日期'); ?></th>
</tr>
</thead>
<tbody>
<?php if($attachments->have()): ?>
<?php while($attachments->next()): ?>
<?php $mime = Typecho_Common::mimeIconType($attachments->attachment->mime); ?>
<tr id="<?php $attachments->theId(); ?>">
<td class="kit-hidden-mb"><input type="checkbox" value="<?php $attachments->cid(); ?>" name="cid[]"/></td>
<td class="kit-hidden-mb"><a href="<?php $options->adminUrl('manage-comments.php?cid=' . $attachments->cid); ?>" class="balloon-button size-<?php echo Typecho_Common::splitByCount($attachments->commentsNum, 1, 10, 20, 50, 100); ?>"><?php $attachments->commentsNum(); ?></a></td>
<td>
<i class="mime-<?php echo $mime; ?>"></i>
<a href="<?php $options->adminUrl('media.php?cid=' . $attachments->cid); ?>"><?php $attachments->title(); ?></a>
<a href="<?php $attachments->permalink(); ?>" title="<?php _e('浏览 %s', $attachments->title); ?>"><i class="i-exlink"></i></a>
</td>
<td class="kit-hidden-mb"><?php $attachments->author(); ?></td>
<td class="kit-hidden-mb">
<?php if ($attachments->parentPost->cid): ?>
<a href="<?php $options->adminUrl('write-' . (0 === strpos($attachments->parentPost->type, 'post') ? 'post' : 'page') . '.php?cid=' . $attachments->parentPost->cid); ?>"><?php $attachments->parentPost->title(); ?></a>
<?php else: ?>
<span class="description"><?php _e('未归档'); ?></span>
<?php endif; ?>
</td>
<td><?php $attachments->dateWord(); ?></td>
</tr>
<?php endwhile; ?>
</thead>
<tbody>
<?php if ($attachments->have()): ?>
<?php while ($attachments->next()): ?>
<?php $mime = \Typecho\Common::mimeIconType($attachments->attachment->mime); ?>
<tr id="<?php $attachments->theId(); ?>">
<td class="kit-hidden-mb"><input type="checkbox"
value="<?php $attachments->cid(); ?>"
name="cid[]"/></td>
<td class="kit-hidden-mb"><a
href="<?php $options->adminUrl('manage-comments.php?cid=' . $attachments->cid); ?>"
class="balloon-button size-<?php echo \Typecho\Common::splitByCount($attachments->commentsNum, 1, 10, 20, 50, 100); ?>"><?php $attachments->commentsNum(); ?></a>
</td>
<td>
<i class="mime-<?php echo $mime; ?>"></i>
<a href="<?php $options->adminUrl('media.php?cid=' . $attachments->cid); ?>"><?php $attachments->title(); ?></a>
<a href="<?php $attachments->permalink(); ?>"
title="<?php _e('浏览 %s', $attachments->title); ?>"><i
class="i-exlink"></i></a>
</td>
<td class="kit-hidden-mb"><?php $attachments->author(); ?></td>
<td class="kit-hidden-mb">
<?php if ($attachments->parentPost->cid): ?>
<a href="<?php $options->adminUrl('write-' . (0 === strpos($attachments->parentPost->type, 'post') ? 'post' : 'page') . '.php?cid=' . $attachments->parentPost->cid); ?>"><?php $attachments->parentPost->title(); ?></a>
<?php else: ?>
<span class="description"><?php _e('未归档'); ?></span>
<?php endif; ?>
</td>
<td><?php $attachments->dateWord(); ?></td>
</tr>
<?php endwhile; ?>
<?php else: ?>
<tr>
<td colspan="6"><h6 class="typecho-list-table-title"><?php _e('没有任何文件'); ?></h6></td>
</tr>
<tr>
<td colspan="6"><h6 class="typecho-list-table-title"><?php _e('没有任何文件'); ?></h6>
</td>
</tr>
<?php endif; ?>
</tbody>
</table><!-- end .typecho-list-table -->
</div><!-- end .typecho-table-wrap -->
</tbody>
</table><!-- end .typecho-list-table -->
</div><!-- end .typecho-table-wrap -->
</form><!-- end .operate-form -->
<div class="typecho-list-operate clearfix">
<form method="get">
<div class="operate">
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox" class="typecho-table-select-all" /></label>
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox"
class="typecho-table-select-all"/></label>
<div class="btn-group btn-drop">
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i class="i-caret-down"></i></button>
<button class="btn dropdown-toggle btn-s" type="button"><i
class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i
class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('你确认要删除这些文件吗?'); ?>" href="<?php $security->index('/action/contents-attachment-edit?do=delete'); ?>"><?php _e('删除'); ?></a></li>
<li><a lang="<?php _e('你确认要删除这些文件吗?'); ?>"
href="<?php $security->index('/action/contents-attachment-edit?do=delete'); ?>"><?php _e('删除'); ?></a>
</li>
</ul>
</div>
<button class="btn btn-s btn-warn btn-operate" href="<?php $security->index('/action/contents-attachment-edit?do=clear'); ?>" lang="<?php _e('您确认要清理未归档的文件吗?'); ?>"><?php _e('清理未归档文件'); ?></button>
<button class="btn btn-s btn-warn btn-operate"
href="<?php $security->index('/action/contents-attachment-edit?do=clear'); ?>"
lang="<?php _e('您确认要清理未归档的文件吗?'); ?>"><?php _e('清理未归档文件'); ?></button>
</div>
<?php if($attachments->have()): ?>
<ul class="typecho-pager">
<?php $attachments->pageNav(); ?>
</ul>
<?php endif; ?>
<?php if ($attachments->have()): ?>
<ul class="typecho-pager">
<?php $attachments->pageNav(); ?>
</ul>
<?php endif; ?>
</form>
</div><!-- end .typecho-list-operate -->
</div>
</div><!-- end .typecho-page-main -->
</div>

View File

@ -3,7 +3,8 @@ include 'common.php';
include 'header.php';
include 'menu.php';
$stat = Typecho_Widget::widget('Widget_Stat');
$stat = \Widget\Stat::alloc();
$pages = \Widget\Contents\Page\Admin::alloc();
?>
<div class="main">
<div class="body container">
@ -13,93 +14,112 @@ $stat = Typecho_Widget::widget('Widget_Stat');
<div class="typecho-list-operate clearfix">
<form method="get">
<div class="operate">
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox" class="typecho-table-select-all" /></label>
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox"
class="typecho-table-select-all"/></label>
<div class="btn-group btn-drop">
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('你确认要删除这些页面吗?'); ?>" href="<?php $security->index('/action/contents-page-edit?do=delete'); ?>"><?php _e('删除'); ?></a></li>
<li><a href="<?php $security->index('/action/contents-page-edit?do=mark&status=publish'); ?>"><?php _e('标记为<strong>%s</strong>', _t('公开')); ?></a></li>
<li><a href="<?php $security->index('/action/contents-page-edit?do=mark&status=hidden'); ?>"><?php _e('标记为<strong>%s</strong>', _t('隐藏')); ?></a></li>
</ul>
<button class="btn dropdown-toggle btn-s" type="button"><i
class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i
class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('你确认要删除这些页面吗?'); ?>"
href="<?php $security->index('/action/contents-page-edit?do=delete'); ?>"><?php _e('删除'); ?></a>
</li>
<li>
<a href="<?php $security->index('/action/contents-page-edit?do=mark&status=publish'); ?>"><?php _e('标记为<strong>%s</strong>', _t('公开')); ?></a>
</li>
<li>
<a href="<?php $security->index('/action/contents-page-edit?do=mark&status=hidden'); ?>"><?php _e('标记为<strong>%s</strong>', _t('隐藏')); ?></a>
</li>
</ul>
</div>
</div>
<div class="search" role="search">
<?php if ('' != $request->keywords): ?>
<a href="<?php $options->adminUrl('manage-pages.php'); ?>"><?php _e('&laquo; 取消筛选'); ?></a>
<a href="<?php $options->adminUrl('manage-pages.php'); ?>"><?php _e('&laquo; 取消筛选'); ?></a>
<?php endif; ?>
<input type="text" class="text-s" placeholder="<?php _e('请输入关键字'); ?>" value="<?php echo htmlspecialchars($request->keywords); ?>" name="keywords" />
<input type="text" class="text-s" placeholder="<?php _e('请输入关键字'); ?>"
value="<?php echo htmlspecialchars($request->keywords); ?>" name="keywords"/>
<button type="submit" class="btn btn-s"><?php _e('筛选'); ?></button>
</div>
</form>
</div><!-- end .typecho-list-operate -->
<form method="post" name="manage_pages" class="operate-form">
<div class="typecho-table-wrap">
<table class="typecho-list-table">
<colgroup>
<col width="20" class="kit-hidden-mb"/>
<col width="6%" class="kit-hidden-mb"/>
<col width="30%"/>
<col width="30%"/>
<col width="" class="kit-hidden-mb"/>
<col width="16%"/>
</colgroup>
<thead>
<div class="typecho-table-wrap">
<table class="typecho-list-table">
<colgroup>
<col width="20" class="kit-hidden-mb"/>
<col width="6%" class="kit-hidden-mb"/>
<col width="30%"/>
<col width="30%"/>
<col width="" class="kit-hidden-mb"/>
<col width="16%"/>
</colgroup>
<thead>
<tr class="nodrag">
<th class="kit-hidden-mb"> </th>
<th class="kit-hidden-mb"> </th>
<th class="kit-hidden-mb"></th>
<th class="kit-hidden-mb"></th>
<th><?php _e('标题'); ?></th>
<th><?php _e('缩略名'); ?></th>
<th class="kit-hidden-mb"><?php _e('作者'); ?></th>
<th><?php _e('日期'); ?></th>
</tr>
</thead>
<tbody>
<?php Typecho_Widget::widget('Widget_Contents_Page_Admin')->to($pages); ?>
<?php if($pages->have()): ?>
<?php while($pages->next()): ?>
<tr id="<?php $pages->theId(); ?>">
<td class="kit-hidden-mb"><input type="checkbox" value="<?php $pages->cid(); ?>" name="cid[]"/></td>
<td class="kit-hidden-mb"><a href="<?php $options->adminUrl('manage-comments.php?cid=' . $pages->cid); ?>" class="balloon-button size-<?php echo Typecho_Common::splitByCount($pages->commentsNum, 1, 10, 20, 50, 100); ?>" title="<?php $pages->commentsNum(); ?> <?php _e('评论'); ?>"><?php $pages->commentsNum(); ?></a></td>
<td>
<a href="<?php $options->adminUrl('write-page.php?cid=' . $pages->cid); ?>"><?php $pages->title(); ?></a>
<?php
if ($pages->hasSaved || 'page_draft' == $pages->type) {
echo '<em class="status">' . _t('草稿') . '</em>';
}
if ('hidden' == $pages->status) {
echo '<em class="status">' . _t('隐藏') . '</em>';
}
?>
<a href="<?php $options->adminUrl('write-page.php?cid=' . $pages->cid); ?>" title="<?php _e('编辑 %s', htmlspecialchars($pages->title)); ?>"><i class="i-edit"></i></a>
<?php if ('page_draft' != $pages->type): ?>
<a href="<?php $pages->permalink(); ?>" title="<?php _e('浏览 %s', htmlspecialchars($pages->title)); ?>"><i class="i-exlink"></i></a>
<?php endif; ?>
</td>
<td><?php $pages->slug(); ?></td>
<td class="kit-hidden-mb"><?php $pages->author(); ?></td>
<td>
<?php if ($pages->hasSaved): ?>
<span class="description">
<?php $modifyDate = new Typecho_Date($pages->modified); ?>
</thead>
<tbody>
<?php if ($pages->have()): ?>
<?php while ($pages->next()): ?>
<tr id="<?php $pages->theId(); ?>">
<td class="kit-hidden-mb"><input type="checkbox" value="<?php $pages->cid(); ?>"
name="cid[]"/></td>
<td class="kit-hidden-mb"><a
href="<?php $options->adminUrl('manage-comments.php?cid=' . $pages->cid); ?>"
class="balloon-button size-<?php echo \Typecho\Common::splitByCount($pages->commentsNum, 1, 10, 20, 50, 100); ?>"
title="<?php $pages->commentsNum(); ?> <?php _e('评论'); ?>"><?php $pages->commentsNum(); ?></a>
</td>
<td>
<a href="<?php $options->adminUrl('write-page.php?cid=' . $pages->cid); ?>"><?php $pages->title(); ?></a>
<?php
if ($pages->hasSaved || 'page_draft' == $pages->type) {
echo '<em class="status">' . _t('草稿') . '</em>';
}
if ('hidden' == $pages->status) {
echo '<em class="status">' . _t('隐藏') . '</em>';
}
?>
<a href="<?php $options->adminUrl('write-page.php?cid=' . $pages->cid); ?>"
title="<?php _e('编辑 %s', htmlspecialchars($pages->title)); ?>"><i
class="i-edit"></i></a>
<?php if ('page_draft' != $pages->type): ?>
<a href="<?php $pages->permalink(); ?>"
title="<?php _e('浏览 %s', htmlspecialchars($pages->title)); ?>"><i
class="i-exlink"></i></a>
<?php endif; ?>
</td>
<td><?php $pages->slug(); ?></td>
<td class="kit-hidden-mb"><?php $pages->author(); ?></td>
<td>
<?php if ($pages->hasSaved): ?>
<span class="description">
<?php $modifyDate = new \Typecho\Date($pages->modified); ?>
<?php _e('保存于 %s', $modifyDate->word()); ?>
</span>
<?php else: ?>
<?php $pages->dateWord(); ?>
<?php endif; ?>
</td>
</tr>
<?php endwhile; ?>
<?php else: ?>
<?php $pages->dateWord(); ?>
<?php endif; ?>
</td>
</tr>
<?php endwhile; ?>
<?php else: ?>
<tr>
<td colspan="6"><h6 class="typecho-list-table-title"><?php _e('没有任何页面'); ?></h6></td>
</tr>
<tr>
<td colspan="6"><h6 class="typecho-list-table-title"><?php _e('没有任何页面'); ?></h6>
</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div><!-- end .typecho-table-wrap -->
</tbody>
</table>
</div><!-- end .typecho-table-wrap -->
</form><!-- end .operate-form -->
</div><!-- end .typecho-list -->
</div><!-- end .typecho-page-main -->
@ -112,25 +132,25 @@ include 'common-js.php';
include 'table-js.php';
?>
<?php if(!isset($request->status) || 'publish' == $request->get('status')): ?>
<script type="text/javascript">
(function () {
$(document).ready(function () {
var table = $('.typecho-list-table').tableDnD({
onDrop : function () {
var ids = [];
<?php if (!isset($request->status) || 'publish' == $request->get('status')): ?>
<script type="text/javascript">
(function () {
$(document).ready(function () {
var table = $('.typecho-list-table').tableDnD({
onDrop: function () {
var ids = [];
$('input[type=checkbox]', table).each(function () {
ids.push($(this).val());
$('input[type=checkbox]', table).each(function () {
ids.push($(this).val());
});
$.post('<?php $security->index('/action/contents-page-edit?do=sort'); ?>',
$.param({cid: ids}));
}
});
$.post('<?php $security->index('/action/contents-page-edit?do=sort'); ?>',
$.param({cid : ids}));
}
});
});
})();
</script>
});
})();
</script>
<?php endif; ?>
<?php include 'footer.php'; ?>

View File

@ -3,9 +3,9 @@ include 'common.php';
include 'header.php';
include 'menu.php';
$stat = Typecho_Widget::widget('Widget_Stat');
$posts = Typecho_Widget::widget('Widget_Contents_Post_Admin');
$isAllPosts = ('on' == $request->get('__typecho_all_posts') || 'on' == Typecho_Cookie::get('__typecho_all_posts'));
$stat = \Widget\Stat::alloc();
$posts = \Widget\Contents\Post\Admin::alloc();
$isAllPosts = ('on' == $request->get('__typecho_all_posts') || 'on' == \Typecho\Cookie::get('__typecho_all_posts'));
?>
<div class="main">
<div class="body container">
@ -14,183 +14,234 @@ $isAllPosts = ('on' == $request->get('__typecho_all_posts') || 'on' == Typecho_C
<div class="col-mb-12 typecho-list">
<div class="clearfix">
<ul class="typecho-option-tabs right">
<?php if($user->pass('editor', true) && !isset($request->uid)): ?>
<li class="<?php if($isAllPosts): ?> current<?php endif; ?>"><a href="<?php echo $request->makeUriByRequest('__typecho_all_posts=on'); ?>"><?php _e('所有'); ?></a></li>
<li class="<?php if(!$isAllPosts): ?> current<?php endif; ?>"><a href="<?php echo $request->makeUriByRequest('__typecho_all_posts=off'); ?>"><?php _e('我的'); ?></a></li>
<?php endif; ?>
<?php if ($user->pass('editor', true) && !isset($request->uid)): ?>
<li class="<?php if ($isAllPosts): ?> current<?php endif; ?>"><a
href="<?php echo $request->makeUriByRequest('__typecho_all_posts=on'); ?>"><?php _e('所有'); ?></a>
</li>
<li class="<?php if (!$isAllPosts): ?> current<?php endif; ?>"><a
href="<?php echo $request->makeUriByRequest('__typecho_all_posts=off'); ?>"><?php _e('我的'); ?></a>
</li>
<?php endif; ?>
</ul>
<ul class="typecho-option-tabs">
<li<?php if(!isset($request->status) || 'all' == $request->get('status')): ?> class="current"<?php endif; ?>><a href="<?php $options->adminUrl('manage-posts.php'
. (isset($request->uid) ? '?uid=' . $request->uid : '')); ?>"><?php _e('可用'); ?></a></li>
<li<?php if('waiting' == $request->get('status')): ?> class="current"<?php endif; ?>><a href="<?php $options->adminUrl('manage-posts.php?status=waiting'
. (isset($request->uid) ? '&uid=' . $request->uid : '')); ?>"><?php _e('待审核'); ?>
<?php if(!$isAllPosts && $stat->myWaitingPostsNum > 0 && !isset($request->uid)): ?>
<span class="balloon"><?php $stat->myWaitingPostsNum(); ?></span>
<?php elseif($isAllPosts && $stat->waitingPostsNum > 0 && !isset($request->uid)): ?>
<span class="balloon"><?php $stat->waitingPostsNum(); ?></span>
<?php elseif(isset($request->uid) && $stat->currentWaitingPostsNum > 0): ?>
<span class="balloon"><?php $stat->currentWaitingPostsNum(); ?></span>
<?php endif; ?>
</a></li>
<li<?php if('draft' == $request->get('status')): ?> class="current"<?php endif; ?>><a href="<?php $options->adminUrl('manage-posts.php?status=draft'
. (isset($request->uid) ? '&uid=' . $request->uid : '')); ?>"><?php _e('草稿'); ?>
<?php if(!$isAllPosts && $stat->myDraftPostsNum > 0 && !isset($request->uid)): ?>
<span class="balloon"><?php $stat->myDraftPostsNum(); ?></span>
<?php elseif($isAllPosts && $stat->draftPostsNum > 0 && !isset($request->uid)): ?>
<span class="balloon"><?php $stat->draftPostsNum(); ?></span>
<?php elseif(isset($request->uid) && $stat->currentDraftPostsNum > 0): ?>
<span class="balloon"><?php $stat->currentDraftPostsNum(); ?></span>
<?php endif; ?>
</a></li>
<li<?php if (!isset($request->status) || 'all' == $request->get('status')): ?> class="current"<?php endif; ?>>
<a href="<?php $options->adminUrl('manage-posts.php'
. (isset($request->uid) ? '?uid=' . $request->uid : '')); ?>"><?php _e('可用'); ?></a>
</li>
<li<?php if ('waiting' == $request->get('status')): ?> class="current"<?php endif; ?>><a
href="<?php $options->adminUrl('manage-posts.php?status=waiting'
. (isset($request->uid) ? '&uid=' . $request->uid : '')); ?>"><?php _e('待审核'); ?>
<?php if (!$isAllPosts && $stat->myWaitingPostsNum > 0 && !isset($request->uid)): ?>
<span class="balloon"><?php $stat->myWaitingPostsNum(); ?></span>
<?php elseif ($isAllPosts && $stat->waitingPostsNum > 0 && !isset($request->uid)): ?>
<span class="balloon"><?php $stat->waitingPostsNum(); ?></span>
<?php elseif (isset($request->uid) && $stat->currentWaitingPostsNum > 0): ?>
<span class="balloon"><?php $stat->currentWaitingPostsNum(); ?></span>
<?php endif; ?>
</a></li>
<li<?php if ('draft' == $request->get('status')): ?> class="current"<?php endif; ?>><a
href="<?php $options->adminUrl('manage-posts.php?status=draft'
. (isset($request->uid) ? '&uid=' . $request->uid : '')); ?>"><?php _e('草稿'); ?>
<?php if (!$isAllPosts && $stat->myDraftPostsNum > 0 && !isset($request->uid)): ?>
<span class="balloon"><?php $stat->myDraftPostsNum(); ?></span>
<?php elseif ($isAllPosts && $stat->draftPostsNum > 0 && !isset($request->uid)): ?>
<span class="balloon"><?php $stat->draftPostsNum(); ?></span>
<?php elseif (isset($request->uid) && $stat->currentDraftPostsNum > 0): ?>
<span class="balloon"><?php $stat->currentDraftPostsNum(); ?></span>
<?php endif; ?>
</a></li>
</ul>
</div>
<div class="typecho-list-operate clearfix">
<form method="get">
<div class="operate">
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox" class="typecho-table-select-all" /></label>
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox"
class="typecho-table-select-all"/></label>
<div class="btn-group btn-drop">
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i class="i-caret-down"></i></button>
<button class="btn dropdown-toggle btn-s" type="button"><i
class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i
class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('你确认要删除这些文章吗?'); ?>" href="<?php $security->index('/action/contents-post-edit?do=delete'); ?>"><?php _e('删除'); ?></a></li>
<li><a lang="<?php _e('你确认要删除这些文章吗?'); ?>"
href="<?php $security->index('/action/contents-post-edit?do=delete'); ?>"><?php _e('删除'); ?></a>
</li>
<?php if ($user->pass('editor', true)): ?>
<li><a href="<?php $security->index('/action/contents-post-edit?do=mark&status=publish'); ?>"><?php _e('标记为<strong>%s</strong>', _t('公开')); ?></a></li>
<li><a href="<?php $security->index('/action/contents-post-edit?do=mark&status=waiting'); ?>"><?php _e('标记为<strong>%s</strong>', _t('待审核')); ?></a></li>
<li><a href="<?php $security->index('/action/contents-post-edit?do=mark&status=hidden'); ?>"><?php _e('标记为<strong>%s</strong>', _t('隐藏')); ?></a></li>
<li><a href="<?php $security->index('/action/contents-post-edit?do=mark&status=private'); ?>"><?php _e('标记为<strong>%s</strong>', _t('私密')); ?></a></li>
<li>
<a href="<?php $security->index('/action/contents-post-edit?do=mark&status=publish'); ?>"><?php _e('标记为<strong>%s</strong>', _t('公开')); ?></a>
</li>
<li>
<a href="<?php $security->index('/action/contents-post-edit?do=mark&status=waiting'); ?>"><?php _e('标记为<strong>%s</strong>', _t('待审核')); ?></a>
</li>
<li>
<a href="<?php $security->index('/action/contents-post-edit?do=mark&status=hidden'); ?>"><?php _e('标记为<strong>%s</strong>', _t('隐藏')); ?></a>
</li>
<li>
<a href="<?php $security->index('/action/contents-post-edit?do=mark&status=private'); ?>"><?php _e('标记为<strong>%s</strong>', _t('私密')); ?></a>
</li>
<?php endif; ?>
</ul>
</div>
</div>
</div>
<div class="search" role="search">
<?php if ('' != $request->keywords || '' != $request->category): ?>
<a href="<?php $options->adminUrl('manage-posts.php'
. (isset($request->status) || isset($request->uid) ? '?' .
(isset($request->status) ? 'status=' . htmlspecialchars($request->get('status')) : '') .
(isset($request->uid) ? '?uid=' . htmlspecialchars($request->get('uid')) : '') : '')); ?>"><?php _e('&laquo; 取消筛选'); ?></a>
<a href="<?php $options->adminUrl('manage-posts.php'
. (isset($request->status) || isset($request->uid) ? '?' .
(isset($request->status) ? 'status=' . htmlspecialchars($request->get('status')) : '') .
(isset($request->uid) ? '?uid=' . htmlspecialchars($request->get('uid')) : '') : '')); ?>"><?php _e('&laquo; 取消筛选'); ?></a>
<?php endif; ?>
<input type="text" class="text-s" placeholder="<?php _e('请输入关键字'); ?>" value="<?php echo htmlspecialchars($request->keywords); ?>" name="keywords" />
<input type="text" class="text-s" placeholder="<?php _e('请输入关键字'); ?>"
value="<?php echo htmlspecialchars($request->keywords); ?>" name="keywords"/>
<select name="category">
<option value=""><?php _e('所有分类'); ?></option>
<?php Typecho_Widget::widget('Widget_Metas_Category_List')->to($category); ?>
<?php while($category->next()): ?>
<option value="<?php $category->mid(); ?>"<?php if($request->get('category') == $category->mid): ?> selected="true"<?php endif; ?>><?php $category->name(); ?></option>
<?php endwhile; ?>
<option value=""><?php _e('所有分类'); ?></option>
<?php \Widget\Metas\Category\Rows::alloc()->to($category); ?>
<?php while ($category->next()): ?>
<option
value="<?php $category->mid(); ?>"<?php if ($request->get('category') == $category->mid): ?> selected="true"<?php endif; ?>><?php $category->name(); ?></option>
<?php endwhile; ?>
</select>
<button type="submit" class="btn btn-s"><?php _e('筛选'); ?></button>
<?php if(isset($request->uid)): ?>
<input type="hidden" value="<?php echo htmlspecialchars($request->get('uid')); ?>" name="uid" />
<?php if (isset($request->uid)): ?>
<input type="hidden" value="<?php echo htmlspecialchars($request->get('uid')); ?>"
name="uid"/>
<?php endif; ?>
<?php if(isset($request->status)): ?>
<input type="hidden" value="<?php echo htmlspecialchars($request->get('status')); ?>" name="status" />
<?php if (isset($request->status)): ?>
<input type="hidden" value="<?php echo htmlspecialchars($request->get('status')); ?>"
name="status"/>
<?php endif; ?>
</div>
</form>
</div><!-- end .typecho-list-operate -->
<form method="post" name="manage_posts" class="operate-form">
<div class="typecho-table-wrap">
<table class="typecho-list-table">
<colgroup>
<col width="20" class="kit-hidden-mb"/>
<col width="6%" class="kit-hidden-mb"/>
<col width="45%"/>
<col width="" class="kit-hidden-mb"/>
<col width="18%" class="kit-hidden-mb"/>
<col width="16%"/>
</colgroup>
<thead>
<div class="typecho-table-wrap">
<table class="typecho-list-table">
<colgroup>
<col width="20" class="kit-hidden-mb"/>
<col width="6%" class="kit-hidden-mb"/>
<col width="45%"/>
<col width="" class="kit-hidden-mb"/>
<col width="18%" class="kit-hidden-mb"/>
<col width="16%"/>
</colgroup>
<thead>
<tr>
<th class="kit-hidden-mb"> </th>
<th class="kit-hidden-mb"> </th>
<th class="kit-hidden-mb"></th>
<th class="kit-hidden-mb"></th>
<th><?php _e('标题'); ?></th>
<th class="kit-hidden-mb"><?php _e('作者'); ?></th>
<th class="kit-hidden-mb"><?php _e('分类'); ?></th>
<th><?php _e('日期'); ?></th>
</tr>
</thead>
<tbody>
<?php if($posts->have()): ?>
<?php while($posts->next()): ?>
<tr id="<?php $posts->theId(); ?>">
<td class="kit-hidden-mb"><input type="checkbox" value="<?php $posts->cid(); ?>" name="cid[]"/></td>
<td class="kit-hidden-mb"><a href="<?php $options->adminUrl('manage-comments.php?cid=' . ($posts->parentId ? $posts->parentId : $posts->cid)); ?>" class="balloon-button size-<?php echo Typecho_Common::splitByCount($posts->commentsNum, 1, 10, 20, 50, 100); ?>" title="<?php $posts->commentsNum(); ?> <?php _e('评论'); ?>"><?php $posts->commentsNum(); ?></a></td>
<td>
<a href="<?php $options->adminUrl('write-post.php?cid=' . $posts->cid); ?>"><?php $posts->title(); ?></a>
<?php
if ($posts->hasSaved || 'post_draft' == $posts->type) {
echo '<em class="status">' . _t('草稿') . '</em>';
}
if ('hidden' == $posts->status) {
echo '<em class="status">' . _t('隐藏') . '</em>';
} else if ('waiting' == $posts->status) {
echo '<em class="status">' . _t('待审核') . '</em>';
} else if ('private' == $posts->status) {
echo '<em class="status">' . _t('私密') . '</em>';
} else if ($posts->password) {
echo '<em class="status">' . _t('密码保护') . '</em>';
}
?>
<a href="<?php $options->adminUrl('write-post.php?cid=' . $posts->cid); ?>" title="<?php _e('编辑 %s', htmlspecialchars($posts->title)); ?>"><i class="i-edit"></i></a>
<?php if ('post_draft' != $posts->type): ?>
<a href="<?php $posts->permalink(); ?>" title="<?php _e('浏览 %s', htmlspecialchars($posts->title)); ?>"><i class="i-exlink"></i></a>
<?php endif; ?>
</td>
<td class="kit-hidden-mb"><a href="<?php $options->adminUrl('manage-posts.php?uid=' . $posts->author->uid); ?>"><?php $posts->author(); ?></a></td>
<td class="kit-hidden-mb"><?php $categories = $posts->categories; $length = count($categories); ?>
<?php foreach ($categories as $key => $val): ?>
<?php echo '<a href="';
$options->adminUrl('manage-posts.php?category=' . $val['mid']
. (isset($request->uid) ? '&uid=' . $request->uid : '')
. (isset($request->status) ? '&status=' . $request->status : ''));
echo '">' . $val['name'] . '</a>' . ($key < $length - 1 ? ', ' : ''); ?>
<?php endforeach; ?>
</td>
<td>
<?php if ($posts->hasSaved): ?>
<span class="description">
<?php $modifyDate = new Typecho_Date($posts->modified); ?>
</thead>
<tbody>
<?php if ($posts->have()): ?>
<?php while ($posts->next()): ?>
<tr id="<?php $posts->theId(); ?>">
<td class="kit-hidden-mb"><input type="checkbox" value="<?php $posts->cid(); ?>"
name="cid[]"/></td>
<td class="kit-hidden-mb"><a
href="<?php $options->adminUrl('manage-comments.php?cid=' . ($posts->parentId ? $posts->parentId : $posts->cid)); ?>"
class="balloon-button size-<?php echo \Typecho\Common::splitByCount($posts->commentsNum, 1, 10, 20, 50, 100); ?>"
title="<?php $posts->commentsNum(); ?> <?php _e('评论'); ?>"><?php $posts->commentsNum(); ?></a>
</td>
<td>
<a href="<?php $options->adminUrl('write-post.php?cid=' . $posts->cid); ?>"><?php $posts->title(); ?></a>
<?php
if ($posts->hasSaved || 'post_draft' == $posts->type) {
echo '<em class="status">' . _t('草稿') . '</em>';
}
if ('hidden' == $posts->status) {
echo '<em class="status">' . _t('隐藏') . '</em>';
} elseif ('waiting' == $posts->status) {
echo '<em class="status">' . _t('待审核') . '</em>';
} elseif ('private' == $posts->status) {
echo '<em class="status">' . _t('私密') . '</em>';
} elseif ($posts->password) {
echo '<em class="status">' . _t('密码保护') . '</em>';
}
?>
<a href="<?php $options->adminUrl('write-post.php?cid=' . $posts->cid); ?>"
title="<?php _e('编辑 %s', htmlspecialchars($posts->title)); ?>"><i
class="i-edit"></i></a>
<?php if ('post_draft' != $posts->type): ?>
<a href="<?php $posts->permalink(); ?>"
title="<?php _e('浏览 %s', htmlspecialchars($posts->title)); ?>"><i
class="i-exlink"></i></a>
<?php endif; ?>
</td>
<td class="kit-hidden-mb"><a
href="<?php $options->adminUrl('manage-posts.php?uid=' . $posts->author->uid); ?>"><?php $posts->author(); ?></a>
</td>
<td class="kit-hidden-mb"><?php $categories = $posts->categories;
$length = count($categories); ?>
<?php foreach ($categories as $key => $val): ?>
<?php echo '<a href="';
$options->adminUrl('manage-posts.php?category=' . $val['mid']
. (isset($request->uid) ? '&uid=' . $request->uid : '')
. (isset($request->status) ? '&status=' . $request->status : ''));
echo '">' . $val['name'] . '</a>' . ($key < $length - 1 ? ', ' : ''); ?>
<?php endforeach; ?>
</td>
<td>
<?php if ($posts->hasSaved): ?>
<span class="description">
<?php $modifyDate = new \Typecho\Date($posts->modified); ?>
<?php _e('保存于 %s', $modifyDate->word()); ?>
</span>
<?php else: ?>
<?php $posts->dateWord(); ?>
<?php endif; ?>
</td>
</tr>
<?php endwhile; ?>
<?php else: ?>
<?php $posts->dateWord(); ?>
<?php endif; ?>
</td>
</tr>
<?php endwhile; ?>
<?php else: ?>
<tr>
<td colspan="6"><h6 class="typecho-list-table-title"><?php _e('没有任何文章'); ?></h6></td>
</tr>
<tr>
<td colspan="6"><h6 class="typecho-list-table-title"><?php _e('没有任何文章'); ?></h6>
</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</tbody>
</table>
</div>
</form><!-- end .operate-form -->
<div class="typecho-list-operate clearfix">
<form method="get">
<div class="operate">
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox" class="typecho-table-select-all" /></label>
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox"
class="typecho-table-select-all"/></label>
<div class="btn-group btn-drop">
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i class="i-caret-down"></i></button>
<button class="btn dropdown-toggle btn-s" type="button"><i
class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i
class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('你确认要删除这些文章吗?'); ?>" href="<?php $security->index('/action/contents-post-edit?do=delete'); ?>"><?php _e('删除'); ?></a></li>
<li><a lang="<?php _e('你确认要删除这些文章吗?'); ?>"
href="<?php $security->index('/action/contents-post-edit?do=delete'); ?>"><?php _e('删除'); ?></a>
</li>
<?php if ($user->pass('editor', true)): ?>
<li><a href="<?php $security->index('/action/contents-post-edit?do=mark&status=publish'); ?>"><?php _e('标记为<strong>%s</strong>', _t('公开')); ?></a></li>
<li><a href="<?php $security->index('/action/contents-post-edit?do=mark&status=waiting'); ?>"><?php _e('标记为<strong>%s</strong>', _t('待审核')); ?></a></li>
<li><a href="<?php $security->index('/action/contents-post-edit?do=mark&status=hidden'); ?>"><?php _e('标记为<strong>%s</strong>', _t('隐藏')); ?></a></li>
<li><a href="<?php $security->index('/action/contents-post-edit?do=mark&status=private'); ?>"><?php _e('标记为<strong>%s</strong>', _t('私密')); ?></a></li>
<li>
<a href="<?php $security->index('/action/contents-post-edit?do=mark&status=publish'); ?>"><?php _e('标记为<strong>%s</strong>', _t('公开')); ?></a>
</li>
<li>
<a href="<?php $security->index('/action/contents-post-edit?do=mark&status=waiting'); ?>"><?php _e('标记为<strong>%s</strong>', _t('待审核')); ?></a>
</li>
<li>
<a href="<?php $security->index('/action/contents-post-edit?do=mark&status=hidden'); ?>"><?php _e('标记为<strong>%s</strong>', _t('隐藏')); ?></a>
</li>
<li>
<a href="<?php $security->index('/action/contents-post-edit?do=mark&status=private'); ?>"><?php _e('标记为<strong>%s</strong>', _t('私密')); ?></a>
</li>
<?php endif; ?>
</ul>
</div>
</div>
</div>
<?php if($posts->have()): ?>
<ul class="typecho-pager">
<?php $posts->pageNav(); ?>
</ul>
<?php if ($posts->have()): ?>
<ul class="typecho-pager">
<?php $posts->pageNav(); ?>
</ul>
<?php endif; ?>
</form>
</div><!-- end .typecho-list-operate -->

View File

@ -3,54 +3,65 @@ include 'common.php';
include 'header.php';
include 'menu.php';
Typecho_Widget::widget('Widget_Metas_Tag_Admin')->to($tags);
\Widget\Metas\Tag\Admin::alloc()->to($tags);
?>
<div class="main">
<div class="body container">
<?php include 'page-title.php'; ?>
<div class="row typecho-page-main manage-metas">
<div class="col-mb-12 col-tb-8" role="main">
<form method="post" name="manage_tags" class="operate-form">
<div class="col-mb-12 col-tb-8" role="main">
<form method="post" name="manage_tags" class="operate-form">
<div class="typecho-list-operate clearfix">
<div class="operate">
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox" class="typecho-table-select-all" /></label>
<div class="btn-group btn-drop">
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('你确认要删除这些标签吗?'); ?>" href="<?php $security->index('/action/metas-tag-edit?do=delete'); ?>"><?php _e('删除'); ?></a></li>
<li><a lang="<?php _e('刷新标签可能需要等待较长时间, 你确认要刷新这些标签吗?'); ?>" href="<?php $security->index('/action/metas-tag-edit?do=refresh'); ?>"><?php _e('刷新'); ?></a></li>
<li class="multiline">
<button type="button" class="btn btn-s merge" rel="<?php $security->index('/action/metas-tag-edit?do=merge'); ?>"><?php _e('合并到'); ?></button>
<input type="text" name="merge" class="text-s" />
</li>
</ul>
</div>
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox"
class="typecho-table-select-all"/></label>
<div class="btn-group btn-drop">
<button class="btn dropdown-toggle btn-s" type="button"><i
class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i
class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('你确认要删除这些标签吗?'); ?>"
href="<?php $security->index('/action/metas-tag-edit?do=delete'); ?>"><?php _e('删除'); ?></a>
</li>
<li><a lang="<?php _e('刷新标签可能需要等待较长时间, 你确认要刷新这些标签吗?'); ?>"
href="<?php $security->index('/action/metas-tag-edit?do=refresh'); ?>"><?php _e('刷新'); ?></a>
</li>
<li class="multiline">
<button type="button" class="btn btn-s merge"
rel="<?php $security->index('/action/metas-tag-edit?do=merge'); ?>"><?php _e('合并到'); ?></button>
<input type="text" name="merge" class="text-s"/>
</li>
</ul>
</div>
</div>
</div>
<ul class="typecho-list-notable tag-list clearfix">
<?php if($tags->have()): ?>
<?php while ($tags->next()): ?>
<li class="size-<?php $tags->split(5, 10, 20, 30); ?>" id="<?php $tags->theId(); ?>">
<input type="checkbox" value="<?php $tags->mid(); ?>" name="mid[]"/>
<span rel="<?php echo $request->makeUriByRequest('mid=' . $tags->mid); ?>"><?php $tags->name(); ?></span>
<a class="tag-edit-link" href="<?php echo $request->makeUriByRequest('mid=' . $tags->mid); ?>"><i class="i-edit"></i></a>
</li>
<?php endwhile; ?>
<?php if ($tags->have()): ?>
<?php while ($tags->next()): ?>
<li class="size-<?php $tags->split(5, 10, 20, 30); ?>" id="<?php $tags->theId(); ?>">
<input type="checkbox" value="<?php $tags->mid(); ?>" name="mid[]"/>
<span
rel="<?php echo $request->makeUriByRequest('mid=' . $tags->mid); ?>"><?php $tags->name(); ?></span>
<a class="tag-edit-link"
href="<?php echo $request->makeUriByRequest('mid=' . $tags->mid); ?>"><i
class="i-edit"></i></a>
</li>
<?php endwhile; ?>
<?php else: ?>
<h6 class="typecho-list-table-title"><?php _e('没有任何标签'); ?></h6>
<h6 class="typecho-list-table-title"><?php _e('没有任何标签'); ?></h6>
<?php endif; ?>
</ul>
<input type="hidden" name="do" value="delete" />
</form>
</div>
<div class="col-mb-12 col-tb-4" role="form">
<?php Typecho_Widget::widget('Widget_Metas_Tag_Edit')->form()->render(); ?>
</div>
<input type="hidden" name="do" value="delete"/>
</form>
</div>
<div class="col-mb-12 col-tb-4" role="form">
<?php \Widget\Metas\Tag\Edit::alloc()->form()->render(); ?>
</div>
</div>
</div>
</div>
@ -61,31 +72,31 @@ include 'common-js.php';
?>
<script type="text/javascript">
(function () {
$(document).ready(function () {
(function () {
$(document).ready(function () {
$('.typecho-list-notable').tableSelectable({
checkEl : 'input[type=checkbox]',
rowEl : 'li',
selectAllEl : '.typecho-table-select-all',
actionEl : '.dropdown-menu a'
$('.typecho-list-notable').tableSelectable({
checkEl: 'input[type=checkbox]',
rowEl: 'li',
selectAllEl: '.typecho-table-select-all',
actionEl: '.dropdown-menu a'
});
$('.btn-drop').dropdownMenu({
btnEl: '.dropdown-toggle',
menuEl: '.dropdown-menu'
});
$('.dropdown-menu button.merge').click(function () {
var btn = $(this);
btn.parents('form').attr('action', btn.attr('rel')).submit();
});
<?php if (isset($request->mid)): ?>
$('.typecho-mini-panel').effect('highlight', '#AACB36');
<?php endif; ?>
});
$('.btn-drop').dropdownMenu({
btnEl : '.dropdown-toggle',
menuEl : '.dropdown-menu'
});
$('.dropdown-menu button.merge').click(function () {
var btn = $(this);
btn.parents('form').attr('action', btn.attr('rel')).submit();
});
<?php if (isset($request->mid)): ?>
$('.typecho-mini-panel').effect('highlight', '#AACB36');
<?php endif; ?>
});
})();
})();
</script>
<?php include 'footer.php'; ?>

View File

@ -2,6 +2,8 @@
include 'common.php';
include 'header.php';
include 'menu.php';
$users = \Widget\Users\Admin::alloc();
?>
<div class="main">
<div class="body container">
@ -11,97 +13,116 @@ include 'menu.php';
<div class="typecho-list-operate clearfix">
<form method="get">
<div class="operate">
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox" class="typecho-table-select-all" /></label>
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox"
class="typecho-table-select-all"/></label>
<div class="btn-group btn-drop">
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('你确认要删除这些用户吗?'); ?>" href="<?php $security->index('/action/users-edit?do=delete'); ?>"><?php _e('删除'); ?></a></li>
</ul>
</div>
<button class="btn dropdown-toggle btn-s" type="button"><i
class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i
class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('你确认要删除这些用户吗?'); ?>"
href="<?php $security->index('/action/users-edit?do=delete'); ?>"><?php _e('删除'); ?></a>
</li>
</ul>
</div>
</div>
<div class="search" role="search">
<?php if ('' != $request->keywords): ?>
<a href="<?php $options->adminUrl('manage-users.php'); ?>"><?php _e('&laquo; 取消筛选'); ?></a>
<a href="<?php $options->adminUrl('manage-users.php'); ?>"><?php _e('&laquo; 取消筛选'); ?></a>
<?php endif; ?>
<input type="text" class="text-s" placeholder="<?php _e('请输入关键字'); ?>" value="<?php echo htmlspecialchars($request->keywords); ?>" name="keywords" />
<input type="text" class="text-s" placeholder="<?php _e('请输入关键字'); ?>"
value="<?php echo htmlspecialchars($request->keywords); ?>" name="keywords"/>
<button type="submit" class="btn btn-s"><?php _e('筛选'); ?></button>
</div>
</form>
</div><!-- end .typecho-list-operate -->
<form method="post" name="manage_users" class="operate-form">
<div class="typecho-table-wrap">
<table class="typecho-list-table">
<colgroup>
<col width="20" class="kit-hidden-mb"/>
<col width="6%" class="kit-hidden-mb"/>
<col width="30%"/>
<col width="" class="kit-hidden-mb"/>
<col width="25%" class="kit-hidden-mb"/>
<col width="15%"/>
</colgroup>
<thead>
<div class="typecho-table-wrap">
<table class="typecho-list-table">
<colgroup>
<col width="20" class="kit-hidden-mb"/>
<col width="6%" class="kit-hidden-mb"/>
<col width="30%"/>
<col width="" class="kit-hidden-mb"/>
<col width="25%" class="kit-hidden-mb"/>
<col width="15%"/>
</colgroup>
<thead>
<tr>
<th class="kit-hidden-mb"> </th>
<th class="kit-hidden-mb"> </th>
<th class="kit-hidden-mb"></th>
<th class="kit-hidden-mb"></th>
<th><?php _e('用户名'); ?></th>
<th class="kit-hidden-mb"><?php _e('昵称'); ?></th>
<th class="kit-hidden-mb"><?php _e('电子邮件'); ?></th>
<th><?php _e('用户组'); ?></th>
</tr>
</thead>
<tbody>
<?php Typecho_Widget::widget('Widget_Users_Admin')->to($users); ?>
<?php while($users->next()): ?>
<tr id="user-<?php $users->uid(); ?>">
<td class="kit-hidden-mb"><input type="checkbox" value="<?php $users->uid(); ?>" name="uid[]"/></td>
<td class="kit-hidden-mb"><a href="<?php $options->adminUrl('manage-posts.php?uid=' . $users->uid); ?>" class="balloon-button left size-<?php echo Typecho_Common::splitByCount($users->postsNum, 1, 10, 20, 50, 100); ?>"><?php $users->postsNum(); ?></a></td>
<td><a href="<?php $options->adminUrl('user.php?uid=' . $users->uid); ?>"><?php $users->name(); ?></a>
<a href="<?php $users->permalink(); ?>" title="<?php _e('浏览 %s', $users->screenName); ?>"><i class="i-exlink"></i></a>
</td>
<td class="kit-hidden-mb"><?php $users->screenName(); ?></td>
<td class="kit-hidden-mb"><?php if($users->mail): ?><a href="mailto:<?php $users->mail(); ?>"><?php $users->mail(); ?></a><?php else: _e('暂无'); endif; ?></td>
<td><?php switch ($users->group) {
case 'administrator':
_e('管理员');
break;
case 'editor':
_e('编辑');
break;
case 'contributor':
_e('贡献者');
break;
case 'subscriber':
_e('关注者');
break;
case 'visitor':
_e('访问者');
break;
default:
break;
} ?></td>
</tr>
</thead>
<tbody>
<?php while ($users->next()): ?>
<tr id="user-<?php $users->uid(); ?>">
<td class="kit-hidden-mb"><input type="checkbox" value="<?php $users->uid(); ?>"
name="uid[]"/></td>
<td class="kit-hidden-mb"><a
href="<?php $options->adminUrl('manage-posts.php?uid=' . $users->uid); ?>"
class="balloon-button left size-<?php echo \Typecho\Common::splitByCount($users->postsNum, 1, 10, 20, 50, 100); ?>"><?php $users->postsNum(); ?></a>
</td>
<td>
<a href="<?php $options->adminUrl('user.php?uid=' . $users->uid); ?>"><?php $users->name(); ?></a>
<a href="<?php $users->permalink(); ?>"
title="<?php _e('浏览 %s', $users->screenName); ?>"><i
class="i-exlink"></i></a>
</td>
<td class="kit-hidden-mb"><?php $users->screenName(); ?></td>
<td class="kit-hidden-mb"><?php if ($users->mail): ?><a
href="mailto:<?php $users->mail(); ?>"><?php $users->mail(); ?></a><?php else: _e('暂无'); endif; ?>
</td>
<td><?php switch ($users->group) {
case 'administrator':
_e('管理员');
break;
case 'editor':
_e('编辑');
break;
case 'contributor':
_e('贡献者');
break;
case 'subscriber':
_e('关注者');
break;
case 'visitor':
_e('访问者');
break;
default:
break;
} ?></td>
</tr>
<?php endwhile; ?>
</tbody>
</table><!-- end .typecho-list-table -->
</div><!-- end .typecho-table-wrap -->
</tbody>
</table><!-- end .typecho-list-table -->
</div><!-- end .typecho-table-wrap -->
</form><!-- end .operate-form -->
<div class="typecho-list-operate clearfix">
<form method="get">
<div class="operate">
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox" class="typecho-table-select-all" /></label>
<label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox"
class="typecho-table-select-all"/></label>
<div class="btn-group btn-drop">
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('你确认要删除这些用户吗?'); ?>" href="<?php $security->index('/action/users-edit?do=delete'); ?>"><?php _e('删除'); ?></a></li>
</ul>
</div>
<button class="btn dropdown-toggle btn-s" type="button"><i
class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i
class="i-caret-down"></i></button>
<ul class="dropdown-menu">
<li><a lang="<?php _e('你确认要删除这些用户吗?'); ?>"
href="<?php $security->index('/action/users-edit?do=delete'); ?>"><?php _e('删除'); ?></a>
</li>
</ul>
</div>
</div>
<?php if($users->have()): ?>
<ul class="typecho-pager">
<?php $users->pageNav(); ?>
</ul>
<?php if ($users->have()): ?>
<ul class="typecho-pager">
<?php $users->pageNav(); ?>
</ul>
<?php endif; ?>
</form>
</div><!-- end .typecho-list-operate -->

View File

@ -9,7 +9,7 @@ if (preg_match("/^([0-9]+)([a-z]{1,2})$/i", $phpMaxFilesize, $matches)) {
$phpMaxFilesize = strtolower($matches[1] . $matches[2] . (1 == strlen($matches[2]) ? 'b' : ''));
}
Typecho_Widget::widget('Widget_Contents_Attachment_Edit')->to($attachment);
$attachment = \Widget\Contents\Attachment\Edit::alloc();
?>
<div class="main">
@ -18,22 +18,25 @@ Typecho_Widget::widget('Widget_Contents_Attachment_Edit')->to($attachment);
<div class="row typecho-page-main">
<div class="col-mb-12 col-tb-8" role="main">
<?php if ($attachment->attachment->isImage): ?>
<p><img src="<?php $attachment->attachment->url(); ?>" alt="<?php $attachment->attachment->name(); ?>" class="typecho-attachment-photo" /></p>
<p><img src="<?php $attachment->attachment->url(); ?>"
alt="<?php $attachment->attachment->name(); ?>" class="typecho-attachment-photo"/></p>
<?php endif; ?>
<p>
<?php $mime = Typecho_Common::mimeIconType($attachment->attachment->mime); ?>
<?php $mime = \Typecho\Common::mimeIconType($attachment->attachment->mime); ?>
<i class="mime-<?php echo $mime; ?>"></i>
<a href=""><strong><?php $attachment->attachment->name(); ?></strong></a>
<span><?php echo number_format(ceil($attachment->attachment->size / 1024)); ?> Kb</span>
</p>
<p>
<input id="attachment-url" type="text" class="mono w-100" value="<?php $attachment->attachment->url(); ?>" readonly />
<input id="attachment-url" type="text" class="mono w-100"
value="<?php $attachment->attachment->url(); ?>" readonly/>
</p>
<div id="upload-panel" class="p">
<div class="upload-area" draggable="true"><?php _e('拖放文件到这里<br>或者 %s选择文件上传%s', '<a href="###" class="upload-file">', '</a>'); ?></div>
<div class="upload-area"
draggable="true"><?php _e('拖放文件到这里<br>或者 %s选择文件上传%s', '<a href="###" class="upload-file">', '</a>'); ?></div>
<ul id="file-list"></ul>
</div>
</div>
@ -51,143 +54,146 @@ include 'common-js.php';
<script src="<?php $options->adminStaticUrl('js', 'moxie.js'); ?>"></script>
<script src="<?php $options->adminStaticUrl('js', 'plupload.js'); ?>"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#attachment-url').click(function () {
$(this).select();
});
$('.operate-delete').click(function () {
var t = $(this), href = t.attr('href');
if (confirm(t.attr('lang'))) {
window.location.href = href;
}
return false;
});
$('.upload-area').bind({
dragenter : function () {
$(this).parent().addClass('drag');
},
dragover : function (e) {
$(this).parent().addClass('drag');
},
drop : function () {
$(this).parent().removeClass('drag');
},
dragend : function () {
$(this).parent().removeClass('drag');
},
dragleave : function () {
$(this).parent().removeClass('drag');
}
});
function fileUploadStart (file) {
$('<ul id="file-list"></ul>').appendTo('#upload-panel');
$('<li id="' + file.id + '" class="loading">'
+ file.name + '</li>').prependTo('#file-list');
}
function fileUploadError (error) {
var file = error.file, code = error.code, word;
switch (code) {
case plupload.FILE_SIZE_ERROR:
word = '<?php _e('文件大小超过限制'); ?>';
break;
case plupload.FILE_EXTENSION_ERROR:
word = '<?php _e('文件扩展名不被支持'); ?>';
break;
case plupload.FILE_DUPLICATE_ERROR:
word = '<?php _e('文件已经上传过'); ?>';
break;
case plupload.HTTP_ERROR:
default:
word = '<?php _e('上传出现错误'); ?>';
break;
}
var fileError = '<?php _e('%s 上传失败'); ?>'.replace('%s', file.name),
li, exist = $('#' + file.id);
if (exist.length > 0) {
li = exist.removeClass('loading').html(fileError);
} else {
$('<ul id="file-list"></ul>').appendTo('#upload-panel');
li = $('<li>' + fileError + '<br />' + word + '</li>').prependTo('#file-list');
}
li.effect('highlight', {color : '#FBC2C4'}, 2000, function () {
$(this).remove();
$(document).ready(function () {
$('#attachment-url').click(function () {
$(this).select();
});
}
function fileUploadComplete (id, url, data) {
var img = $('.typecho-attachment-photo');
$('.operate-delete').click(function () {
var t = $(this), href = t.attr('href');
if (img.length > 0) {
img.get(0).src = '<?php $attachment->attachment->url(); ?>?' + Math.random();
}
$('#' + id).html('<?php _e('文件 %s 已经替换'); ?>'.replace('%s', data.title))
.effect('highlight', 1000, function () {
$(this).remove();
$('#file-list').remove();
});
}
var uploader = new plupload.Uploader({
browse_button : $('.upload-file').get(0),
url : '<?php $security->index('/action/upload?do=modify&cid=' . $attachment->cid); ?>',
runtimes : 'html5,flash,html4',
flash_swf_url : '<?php $options->adminStaticUrl('js', 'Moxie.swf'); ?>',
drop_element : $('.upload-area').get(0),
filters : {
max_file_size : '<?php echo $phpMaxFilesize ?>',
mime_types : [{'title' : '<?php _e('允许上传的文件'); ?>', 'extensions' : '<?php $attachment->attachment->type(); ?>'}],
prevent_duplicates : true
},
multi_selection : false,
init : {
FilesAdded : function (up, files) {
plupload.each(files, function(file) {
fileUploadStart(file);
});
uploader.start();
},
FileUploaded : function (up, file, result) {
if (200 == result.status) {
var data = $.parseJSON(result.response);
if (data) {
fileUploadComplete(file.id, data[0], data[1]);
return;
}
}
fileUploadError({
code : plupload.HTTP_ERROR,
file : file
});
},
Error : function (up, error) {
fileUploadError(error);
if (confirm(t.attr('lang'))) {
window.location.href = href;
}
}
});
uploader.init();
});
return false;
});
$('.upload-area').bind({
dragenter: function () {
$(this).parent().addClass('drag');
},
dragover: function (e) {
$(this).parent().addClass('drag');
},
drop: function () {
$(this).parent().removeClass('drag');
},
dragend: function () {
$(this).parent().removeClass('drag');
},
dragleave: function () {
$(this).parent().removeClass('drag');
}
});
function fileUploadStart(file) {
$('<ul id="file-list"></ul>').appendTo('#upload-panel');
$('<li id="' + file.id + '" class="loading">'
+ file.name + '</li>').prependTo('#file-list');
}
function fileUploadError(error) {
var file = error.file, code = error.code, word;
switch (code) {
case plupload.FILE_SIZE_ERROR:
word = '<?php _e('文件大小超过限制'); ?>';
break;
case plupload.FILE_EXTENSION_ERROR:
word = '<?php _e('文件扩展名不被支持'); ?>';
break;
case plupload.FILE_DUPLICATE_ERROR:
word = '<?php _e('文件已经上传过'); ?>';
break;
case plupload.HTTP_ERROR:
default:
word = '<?php _e('上传出现错误'); ?>';
break;
}
var fileError = '<?php _e('%s 上传失败'); ?>'.replace('%s', file.name),
li, exist = $('#' + file.id);
if (exist.length > 0) {
li = exist.removeClass('loading').html(fileError);
} else {
$('<ul id="file-list"></ul>').appendTo('#upload-panel');
li = $('<li>' + fileError + '<br />' + word + '</li>').prependTo('#file-list');
}
li.effect('highlight', {color: '#FBC2C4'}, 2000, function () {
$(this).remove();
});
}
function fileUploadComplete(id, url, data) {
var img = $('.typecho-attachment-photo');
if (img.length > 0) {
img.get(0).src = '<?php $attachment->attachment->url(); ?>?' + Math.random();
}
$('#' + id).html('<?php _e('文件 %s 已经替换'); ?>'.replace('%s', data.title))
.effect('highlight', 1000, function () {
$(this).remove();
$('#file-list').remove();
});
}
var uploader = new plupload.Uploader({
browse_button: $('.upload-file').get(0),
url: '<?php $security->index('/action/upload?do=modify&cid=' . $attachment->cid); ?>',
runtimes: 'html5,flash,html4',
flash_swf_url: '<?php $options->adminStaticUrl('js', 'Moxie.swf'); ?>',
drop_element: $('.upload-area').get(0),
filters: {
max_file_size: '<?php echo $phpMaxFilesize ?>',
mime_types: [{
'title': '<?php _e('允许上传的文件'); ?>',
'extensions': '<?php $attachment->attachment->type(); ?>'
}],
prevent_duplicates: true
},
multi_selection: false,
init: {
FilesAdded: function (up, files) {
plupload.each(files, function (file) {
fileUploadStart(file);
});
uploader.start();
},
FileUploaded: function (up, file, result) {
if (200 == result.status) {
var data = $.parseJSON(result.response);
if (data) {
fileUploadComplete(file.id, data[0], data[1]);
return;
}
}
fileUploadError({
code: plupload.HTTP_ERROR,
file: file
});
},
Error: function (up, error) {
fileUploadError(error);
}
}
});
uploader.init();
});
</script>
<?php
include 'footer.php';

View File

@ -1,16 +1,18 @@
<?php if(!defined('__TYPECHO_ADMIN__')) exit; ?>
<?php if (!defined('__TYPECHO_ADMIN__')) exit; ?>
<div class="typecho-head-nav clearfix" role="navigation">
<button class="menu-bar"><?php _e('菜单'); ?></button>
<nav id="typecho-nav-list">
<?php $menu->output(); ?>
</nav>
<div class="operate">
<?php Typecho_Plugin::factory('admin/menu.php')->navBar(); ?><a title="<?php
if ($user->logged > 0) {
$logged = new Typecho_Date($user->logged);
_e('最后登录: %s', $logged->word());
}
?>" href="<?php $options->adminUrl('profile.php'); ?>" class="author"><?php $user->screenName(); ?></a><a class="exit" href="<?php $options->logoutUrl(); ?>"><?php _e('登出'); ?></a><a href="<?php $options->siteUrl(); ?>"><?php _e('网站'); ?></a>
<?php \Typecho\Plugin::factory('admin/menu.php')->navBar(); ?><a title="<?php
if ($user->logged > 0) {
$logged = new \Typecho\Date($user->logged);
_e('最后登录: %s', $logged->word());
}
?>" href="<?php $options->adminUrl('profile.php'); ?>" class="author"><?php $user->screenName(); ?></a><a
class="exit" href="<?php $options->logoutUrl(); ?>"><?php _e('登出'); ?></a><a
href="<?php $options->siteUrl(); ?>"><?php _e('网站'); ?></a>
</div>
</div>

View File

@ -9,7 +9,7 @@ include 'menu.php';
<?php include 'page-title.php'; ?>
<div class="row typecho-page-main" role="form">
<div class="col-mb-12 col-tb-8 col-tb-offset-2">
<?php Typecho_Widget::widget('Widget_Options_Discussion')->form()->render(); ?>
<?php \Widget\Options\Discussion::alloc()->form()->render(); ?>
</div>
</div>
</div>

View File

@ -9,7 +9,7 @@ include 'menu.php';
<?php include 'page-title.php'; ?>
<div class="row typecho-page-main" role="form">
<div class="col-mb-12 col-tb-8 col-tb-offset-2">
<?php Typecho_Widget::widget('Widget_Options_General')->form()->render(); ?>
<?php \Widget\Options\General::alloc()->form()->render(); ?>
</div>
</div>
</div>

View File

@ -9,7 +9,7 @@ include 'menu.php';
<?php include 'page-title.php'; ?>
<div class="row typecho-page-main" role="form">
<div class="col-mb-12 col-tb-8 col-tb-offset-2">
<?php Typecho_Widget::widget('Widget_Options_Permalink')->form()->render(); ?>
<?php \Widget\Options\Permalink::alloc()->form()->render(); ?>
</div>
</div>
</div>

View File

@ -9,7 +9,7 @@ include 'menu.php';
<?php include 'page-title.php'; ?>
<div class="row typecho-page-main" role="form">
<div class="col-mb-12 col-tb-8 col-tb-offset-2">
<?php Typecho_Widget::widget('Widget_Plugins_Config')->config()->render(); ?>
<?php \Widget\Plugins\Config::alloc()->config()->render(); ?>
</div>
</div>
</div>

View File

@ -9,7 +9,7 @@ include 'menu.php';
<?php include 'page-title.php'; ?>
<div class="row typecho-page-main" role="form">
<div class="col-mb-12 col-tb-8 col-tb-offset-2">
<?php Typecho_Widget::widget('Widget_Options_Reading')->form()->render(); ?>
<?php \Widget\Options\Reading::alloc()->form()->render(); ?>
</div>
</div>
</div>

View File

@ -14,11 +14,12 @@ include 'menu.php';
<?php if (!defined('__TYPECHO_THEME_WRITEABLE__') || __TYPECHO_THEME_WRITEABLE__): ?>
<li><a href="<?php $options->adminUrl('theme-editor.php'); ?>"><?php _e('编辑当前外观'); ?></a></li>
<?php endif; ?>
<li class="current"><a href="<?php $options->adminUrl('options-theme.php'); ?>"><?php _e('设置外观'); ?></a></li>
<li class="current"><a
href="<?php $options->adminUrl('options-theme.php'); ?>"><?php _e('设置外观'); ?></a></li>
</ul>
</div>
<div class="col-mb-12 col-tb-8 col-tb-offset-2" role="form">
<?php Typecho_Widget::widget('Widget_Themes_Config')->config()->render(); ?>
<?php \Widget\Themes\Config::alloc()->config()->render(); ?>
</div>
</div>
</div>

View File

@ -8,19 +8,19 @@ include 'menu.php';
<?php include 'page-title.php'; ?>
<div class="row typecho-page-main" role="main">
<div class="col-mb-12 typecho-list">
<?php Typecho_Widget::widget('Widget_Plugins_List@activated', 'activated=1')->to($activatedPlugins); ?>
<?php \Widget\Plugins\Rows::allocWithAlias('activated', 'activated=1')->to($activatedPlugins); ?>
<?php if ($activatedPlugins->have() || !empty($activatedPlugins->activatedPlugins)): ?>
<h4 class="typecho-list-table-title"><?php _e('启用的插件'); ?></h4>
<div class="typecho-table-wrap">
<table class="typecho-list-table">
<colgroup>
<col width="25%"/>
<col width="45%"/>
<col width="8%" class="kit-hidden-mb"/>
<col width="10%" class="kit-hidden-mb"/>
<col width=""/>
</colgroup>
<thead>
<h4 class="typecho-list-table-title"><?php _e('启用的插件'); ?></h4>
<div class="typecho-table-wrap">
<table class="typecho-list-table">
<colgroup>
<col width="25%"/>
<col width="45%"/>
<col width="8%" class="kit-hidden-mb"/>
<col width="10%" class="kit-hidden-mb"/>
<col width=""/>
</colgroup>
<thead>
<tr>
<th><?php _e('名称'); ?></th>
<th><?php _e('描述'); ?></th>
@ -28,61 +28,66 @@ include 'menu.php';
<th class="kit-hidden-mb"><?php _e('作者'); ?></th>
<th><?php _e('操作'); ?></th>
</tr>
</thead>
<tbody>
</thead>
<tbody>
<?php while ($activatedPlugins->next()): ?>
<tr id="plugin-<?php $activatedPlugins->name(); ?>">
<td><?php $activatedPlugins->title(); ?>
<?php if (!$activatedPlugins->dependence): ?>
<i class="i-delete" title="<?php _e('%s 无法在此版本的typecho下正常工作', $activatedPlugins->title); ?>"></i>
<?php endif; ?>
</td>
<td><?php $activatedPlugins->description(); ?></td>
<td class="kit-hidden-mb"><?php $activatedPlugins->version(); ?></td>
<td class="kit-hidden-mb"><?php echo empty($activatedPlugins->homepage) ? $activatedPlugins->author : '<a href="' . $activatedPlugins->homepage
. '">' . $activatedPlugins->author . '</a>'; ?></td>
<td>
<?php if ($activatedPlugins->activate || $activatedPlugins->deactivate || $activatedPlugins->config || $activatedPlugins->personalConfig): ?>
<?php if ($activatedPlugins->config): ?>
<a href="<?php $options->adminUrl('options-plugin.php?config=' . $activatedPlugins->name); ?>"><?php _e('设置'); ?></a>
&bull;
<tr id="plugin-<?php $activatedPlugins->name(); ?>">
<td><?php $activatedPlugins->title(); ?>
<?php if (!$activatedPlugins->dependence): ?>
<i class="i-delete"
title="<?php _e('%s 无法在此版本的typecho下正常工作', $activatedPlugins->title); ?>"></i>
<?php endif; ?>
<a lang="<?php _e('你确认要禁用插件 %s 吗?', $activatedPlugins->name); ?>" href="<?php $security->index('/action/plugins-edit?deactivate=' . $activatedPlugins->name); ?>"><?php _e('禁用'); ?></a>
<?php else: ?>
<span class="important"><?php _e('即插即用'); ?></span>
<?php endif; ?>
</td>
</tr>
</td>
<td><?php $activatedPlugins->description(); ?></td>
<td class="kit-hidden-mb"><?php $activatedPlugins->version(); ?></td>
<td class="kit-hidden-mb"><?php echo empty($activatedPlugins->homepage) ? $activatedPlugins->author : '<a href="' . $activatedPlugins->homepage
. '">' . $activatedPlugins->author . '</a>'; ?></td>
<td>
<?php if ($activatedPlugins->activate || $activatedPlugins->deactivate || $activatedPlugins->config || $activatedPlugins->personalConfig): ?>
<?php if ($activatedPlugins->config): ?>
<a href="<?php $options->adminUrl('options-plugin.php?config=' . $activatedPlugins->name); ?>"><?php _e('设置'); ?></a>
&bull;
<?php endif; ?>
<a lang="<?php _e('你确认要禁用插件 %s 吗?', $activatedPlugins->name); ?>"
href="<?php $security->index('/action/plugins-edit?deactivate=' . $activatedPlugins->name); ?>"><?php _e('禁用'); ?></a>
<?php else: ?>
<span class="important"><?php _e('即插即用'); ?></span>
<?php endif; ?>
</td>
</tr>
<?php endwhile; ?>
<?php if (!empty($activatedPlugins->activatedPlugins)): ?>
<?php foreach ($activatedPlugins->activatedPlugins as $key => $val): ?>
<tr>
<td><?php echo $key; ?></td>
<td colspan="3"><span class="warning"><?php _e('此插件文件已经损坏或者被不安全移除, 强烈建议你禁用它'); ?></span></td>
<td><a lang="<?php _e('你确认要禁用插件 %s 吗?', $key); ?>" href="<?php $security->index('/action/plugins-edit?deactivate=' . $key); ?>"><?php _e('禁用'); ?></a></td>
</tr>
<?php endforeach; ?>
<?php foreach ($activatedPlugins->activatedPlugins as $key => $val): ?>
<tr>
<td><?php echo $key; ?></td>
<td colspan="3"><span
class="warning"><?php _e('此插件文件已经损坏或者被不安全移除, 强烈建议你禁用它'); ?></span></td>
<td><a lang="<?php _e('你确认要禁用插件 %s 吗?', $key); ?>"
href="<?php $security->index('/action/plugins-edit?deactivate=' . $key); ?>"><?php _e('禁用'); ?></a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</tbody>
</table>
</div>
<?php endif; ?>
<?php Typecho_Widget::widget('Widget_Plugins_List@unactivated', 'activated=0')->to($deactivatedPlugins); ?>
<?php \Widget\Plugins\Rows::allocWithAlias('unactivated', 'activated=0')->to($deactivatedPlugins); ?>
<?php if ($deactivatedPlugins->have() || !$activatedPlugins->have()): ?>
<h4 class="typecho-list-table-title"><?php _e('禁用的插件'); ?></h4>
<div class="typecho-table-wrap">
<table class="typecho-list-table deactivate">
<colgroup>
<col width="25%"/>
<col width="45%"/>
<col width="8%" class="kit-hidden-mb"/>
<col width="10%" class="kit-hidden-mb"/>
<col width=""/>
</colgroup>
<thead>
<h4 class="typecho-list-table-title"><?php _e('禁用的插件'); ?></h4>
<div class="typecho-table-wrap">
<table class="typecho-list-table deactivate">
<colgroup>
<col width="25%"/>
<col width="45%"/>
<col width="8%" class="kit-hidden-mb"/>
<col width="10%" class="kit-hidden-mb"/>
<col width=""/>
</colgroup>
<thead>
<tr>
<th><?php _e('名称'); ?></th>
<th><?php _e('描述'); ?></th>
@ -90,31 +95,32 @@ include 'menu.php';
<th class="kit-hidden-mb"><?php _e('作者'); ?></th>
<th class="typecho-radius-topright"><?php _e('操作'); ?></th>
</tr>
</thead>
<tbody>
</thead>
<tbody>
<?php if ($deactivatedPlugins->have()): ?>
<?php while ($deactivatedPlugins->next()): ?>
<tr id="plugin-<?php $deactivatedPlugins->name(); ?>">
<td><?php $deactivatedPlugins->title(); ?></td>
<td><?php $deactivatedPlugins->description(); ?></td>
<td class="kit-hidden-mb"><?php $deactivatedPlugins->version(); ?></td>
<td class="kit-hidden-mb"><?php echo empty($deactivatedPlugins->homepage) ? $deactivatedPlugins->author : '<a href="' . $deactivatedPlugins->homepage
. '">' . $deactivatedPlugins->author . '</a>'; ?></td>
<td>
<a href="<?php $security->index('/action/plugins-edit?activate=' . $deactivatedPlugins->name); ?>"><?php _e('启用'); ?></a>
</td>
</tr>
<?php endwhile; ?>
<?php while ($deactivatedPlugins->next()): ?>
<tr id="plugin-<?php $deactivatedPlugins->name(); ?>">
<td><?php $deactivatedPlugins->title(); ?></td>
<td><?php $deactivatedPlugins->description(); ?></td>
<td class="kit-hidden-mb"><?php $deactivatedPlugins->version(); ?></td>
<td class="kit-hidden-mb"><?php echo empty($deactivatedPlugins->homepage) ? $deactivatedPlugins->author : '<a href="' . $deactivatedPlugins->homepage
. '">' . $deactivatedPlugins->author . '</a>'; ?></td>
<td>
<a href="<?php $security->index('/action/plugins-edit?activate=' . $deactivatedPlugins->name); ?>"><?php _e('启用'); ?></a>
</td>
</tr>
<?php endwhile; ?>
<?php else: ?>
<tr>
<td colspan="5"><h6 class="typecho-list-table-title"><?php _e('没有安装插件'); ?></h6></td>
</tr>
<tr>
<td colspan="5"><h6 class="typecho-list-table-title"><?php _e('没有安装插件'); ?></h6>
</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>

View File

@ -3,7 +3,7 @@
include 'common.php';
/** 获取内容 Widget */
Typecho_Widget::widget('Widget_Archive', 'type=single&checkPermalink=0&preview=1')->to($content);
\Widget\Archive::alloc('type=single&checkPermalink=0&preview=1')->to($content);
/** 检测是否存在 */
if (!$content->have()) {
@ -24,4 +24,4 @@ $content->render();
window.parent.postMessage('cancelPreview', '<?php $options->rootUrl(); ?>');
}
}
</script>
</script>

View File

@ -3,7 +3,7 @@ include 'common.php';
include 'header.php';
include 'menu.php';
$stat = Typecho_Widget::widget('Widget_Stat');
$stat = \Widget\Stat::alloc();
?>
<div class="main">
@ -11,41 +11,43 @@ $stat = Typecho_Widget::widget('Widget_Stat');
<?php include 'page-title.php'; ?>
<div class="row typecho-page-main">
<div class="col-mb-12 col-tb-3">
<p><a href="http://gravatar.com/emails/" title="<?php _e('在 Gravatar 上修改头像'); ?>"><?php echo '<img class="profile-avatar" src="' . Typecho_Common::gravatarUrl($user->mail, 220, 'X', 'mm', $request->isSecure()) . '" alt="' . $user->screenName . '" />'; ?></a></p>
<p><a href="http://gravatar.com/emails/"
title="<?php _e('在 Gravatar 上修改头像'); ?>"><?php echo '<img class="profile-avatar" src="' . \Typecho\Common::gravatarUrl($user->mail, 220, 'X', 'mm', $request->isSecure()) . '" alt="' . $user->screenName . '" />'; ?></a>
</p>
<h2><?php $user->screenName(); ?></h2>
<p><?php $user->name(); ?></p>
<p><?php _e('目前有 <em>%s</em> 篇日志, 并有 <em>%s</em> 条关于你的评论在 <em>%s</em> 个分类中.',
$stat->myPublishedPostsNum, $stat->myPublishedCommentsNum, $stat->categoriesNum); ?></p>
<p><?php _e('目前有 <em>%s</em> 篇日志, 并有 <em>%s</em> 条关于你的评论在 <em>%s</em> 个分类中.',
$stat->myPublishedPostsNum, $stat->myPublishedCommentsNum, $stat->categoriesNum); ?></p>
<p><?php
if ($user->logged > 0) {
$logged = new Typecho_Date($user->logged);
_e('最后登录: %s', $logged->word());
}
?></p>
if ($user->logged > 0) {
$logged = new \Typecho\Date($user->logged);
_e('最后登录: %s', $logged->word());
}
?></p>
</div>
<div class="col-mb-12 col-tb-6 col-tb-offset-1 typecho-content-panel" role="form">
<section>
<h3><?php _e('个人资料'); ?></h3>
<?php Typecho_Widget::widget('Widget_Users_Profile')->profileForm()->render(); ?>
<?php \Widget\Users\Profile::alloc()->profileForm()->render(); ?>
</section>
<?php if($user->pass('contributor', true)): ?>
<br>
<section id="writing-option">
<h3><?php _e('撰写设置'); ?></h3>
<?php Typecho_Widget::widget('Widget_Users_Profile')->optionsForm()->render(); ?>
</section>
<?php if ($user->pass('contributor', true)): ?>
<br>
<section id="writing-option">
<h3><?php _e('撰写设置'); ?></h3>
<?php \Widget\Users\Profile::alloc()->optionsForm()->render(); ?>
</section>
<?php endif; ?>
<br>
<section id="change-password">
<h3><?php _e('密码修改'); ?></h3>
<?php Typecho_Widget::widget('Widget_Users_Profile')->passwordForm()->render(); ?>
<?php \Widget\Users\Profile::alloc()->passwordForm()->render(); ?>
</section>
<?php Typecho_Widget::widget('Widget_Users_Profile')->personalFormList(); ?>
<?php \Widget\Users\Profile::alloc()->personalFormList(); ?>
</div>
</div>
</div>
@ -55,6 +57,6 @@ $stat = Typecho_Widget::widget('Widget_Stat');
include 'copyright.php';
include 'common-js.php';
include 'form-js.php';
Typecho_Plugin::factory('admin/profile.php')->bottom();
\Typecho\Plugin::factory('admin/profile.php')->bottom();
include 'footer.php';
?>

View File

@ -4,10 +4,10 @@ include 'common.php';
if ($user->hasLogin() || !$options->allowRegister) {
$response->redirect($options->siteUrl);
}
$rememberName = htmlspecialchars(Typecho_Cookie::get('__typecho_remember_name'));
$rememberMail = htmlspecialchars(Typecho_Cookie::get('__typecho_remember_mail'));
Typecho_Cookie::delete('__typecho_remember_name');
Typecho_Cookie::delete('__typecho_remember_mail');
$rememberName = htmlspecialchars(\Typecho\Cookie::get('__typecho_remember_name'));
$rememberMail = htmlspecialchars(\Typecho\Cookie::get('__typecho_remember_mail'));
\Typecho\Cookie::delete('__typecho_remember_name');
\Typecho\Cookie::delete('__typecho_remember_mail');
$bodyClass = 'body-100';

View File

@ -11,6 +11,10 @@ textarea {
border-radius: 2px;
box-sizing: border-box;
&:disabled, &:read-only {
background: #F3F3F3;
}
}
textarea {

View File

@ -78,12 +78,6 @@ a.button:hover, a.balloon-button:hover {
@import "header";
@import "footer";
/* 低版本浏览器升级提示 */
.browsehappy {
border: none;
text-align: center;
}
/** 顶部消息样式 by 70 */
.popup {
display: none;

View File

@ -3,7 +3,7 @@ include 'common.php';
include 'header.php';
include 'menu.php';
Typecho_Widget::widget('Widget_Themes_Files')->to($files);
\Widget\Themes\Files::alloc()->to($files);
?>
<div class="main">
@ -14,28 +14,30 @@ Typecho_Widget::widget('Widget_Themes_Files')->to($files);
<ul class="typecho-option-tabs fix-tabs clearfix">
<li><a href="<?php $options->adminUrl('themes.php'); ?>"><?php _e('可以使用的外观'); ?></a></li>
<li class="current"><a href="<?php $options->adminUrl('theme-editor.php'); ?>">
<?php if ($options->theme == $files->theme): ?>
<?php _e('编辑当前外观'); ?>
<?php else: ?>
<?php _e('编辑%s外观', ' <cite>' . $files->theme . '</cite> '); ?>
<?php endif; ?>
</a></li>
<?php if (Widget_Themes_Config::isExists()): ?>
<li><a href="<?php $options->adminUrl('options-theme.php'); ?>"><?php _e('设置外观'); ?></a></li>
<?php if ($options->theme == $files->theme): ?>
<?php _e('编辑当前外观'); ?>
<?php else: ?>
<?php _e('编辑%s外观', ' <cite>' . $files->theme . '</cite> '); ?>
<?php endif; ?>
</a></li>
<?php if (\Widget\Themes\Config::isExists()): ?>
<li><a href="<?php $options->adminUrl('options-theme.php'); ?>"><?php _e('设置外观'); ?></a></li>
<?php endif; ?>
</ul>
</div>
<div class="typecho-edit-theme">
<div class="col-mb-12 col-tb-8 col-9 content">
<form method="post" name="theme" id="theme" action="<?php $security->index('/action/themes-edit'); ?>">
<form method="post" name="theme" id="theme"
action="<?php $security->index('/action/themes-edit'); ?>">
<label for="content" class="sr-only"><?php _e('编辑源码'); ?></label>
<textarea name="content" id="content" class="w-100 mono" <?php if(!$files->currentIsWriteable()): ?>readonly<?php endif; ?>><?php echo $files->currentContent(); ?></textarea>
<textarea name="content" id="content" class="w-100 mono"
<?php if (!$files->currentIsWriteable()): ?>readonly<?php endif; ?>><?php echo $files->currentContent(); ?></textarea>
<p class="typecho-option typecho-option-submit">
<?php if($files->currentIsWriteable()): ?>
<input type="hidden" name="theme" value="<?php echo $files->currentTheme(); ?>" />
<input type="hidden" name="edit" value="<?php echo $files->currentFile(); ?>" />
<button type="submit" class="btn primary"><?php _e('保存文件'); ?></button>
<?php if ($files->currentIsWriteable()): ?>
<input type="hidden" name="theme" value="<?php echo $files->currentTheme(); ?>"/>
<input type="hidden" name="edit" value="<?php echo $files->currentFile(); ?>"/>
<button type="submit" class="btn primary"><?php _e('保存文件'); ?></button>
<?php else: ?>
<em><?php _e('此文件无法写入'); ?></em>
<?php endif; ?>
@ -44,9 +46,10 @@ Typecho_Widget::widget('Widget_Themes_Files')->to($files);
</div>
<ul class="col-mb-12 col-tb-4 col-3">
<li><strong>模板文件</strong></li>
<?php while($files->next()): ?>
<li<?php if($files->current): ?> class="current"<?php endif; ?>>
<a href="<?php $options->adminUrl('theme-editor.php?theme=' . $files->currentTheme() . '&file=' . $files->file); ?>"><?php $files->file(); ?></a></li>
<?php while ($files->next()): ?>
<li<?php if ($files->current): ?> class="current"<?php endif; ?>>
<a href="<?php $options->adminUrl('theme-editor.php?theme=' . $files->currentTheme() . '&file=' . $files->file); ?>"><?php $files->file(); ?></a>
</li>
<?php endwhile; ?>
</ul>
</div>
@ -57,6 +60,6 @@ Typecho_Widget::widget('Widget_Themes_Files')->to($files);
<?php
include 'copyright.php';
include 'common-js.php';
Typecho_Plugin::factory('admin/theme-editor.php')->bottom($files);
\Typecho\Plugin::factory('admin/theme-editor.php')->bottom($files);
include 'footer.php';
?>

View File

@ -10,50 +10,55 @@ include 'menu.php';
<div class="row typecho-page-main" role="main">
<div class="col-mb-12">
<ul class="typecho-option-tabs fix-tabs clearfix">
<li class="current"><a href="<?php $options->adminUrl('themes.php'); ?>"><?php _e('可以使用的外观'); ?></a></li>
<li class="current"><a href="<?php $options->adminUrl('themes.php'); ?>"><?php _e('可以使用的外观'); ?></a>
</li>
<?php if (!defined('__TYPECHO_THEME_WRITEABLE__') || __TYPECHO_THEME_WRITEABLE__): ?>
<li><a href="<?php $options->adminUrl('theme-editor.php'); ?>"><?php _e('编辑当前外观'); ?></a></li>
<li><a href="<?php $options->adminUrl('theme-editor.php'); ?>"><?php _e('编辑当前外观'); ?></a></li>
<?php endif; ?>
<?php if (Widget_Themes_Config::isExists()): ?>
<li><a href="<?php $options->adminUrl('options-theme.php'); ?>"><?php _e('设置外观'); ?></a></li>
<?php if (\Widget\Themes\Config::isExists()): ?>
<li><a href="<?php $options->adminUrl('options-theme.php'); ?>"><?php _e('设置外观'); ?></a></li>
<?php endif; ?>
</ul>
<div class="typecho-table-wrap">
<table class="typecho-list-table typecho-theme-list">
<colgroup>
<col width="35%" />
<col />
<col width="35%"/>
<col/>
</colgroup>
<thead>
<th><?php _e('截图'); ?></th>
<th><?php _e('详情'); ?></th>
<th><?php _e('截图'); ?></th>
<th><?php _e('详情'); ?></th>
</thead>
<tbody>
<?php Typecho_Widget::widget('Widget_Themes_List')->to($themes); ?>
<?php while($themes->next()): ?>
<tr id="theme-<?php $themes->name(); ?>" class="<?php if($themes->activated): ?>current<?php endif; ?>">
<td valign="top"><img src="<?php $themes->screen(); ?>" alt="<?php $themes->name(); ?>" /></td>
<?php \Widget\Themes\Rows::alloc()->to($themes); ?>
<?php while ($themes->next()): ?>
<tr id="theme-<?php $themes->name(); ?>"
class="<?php if ($themes->activated): ?>current<?php endif; ?>">
<td valign="top"><img src="<?php $themes->screen(); ?>"
alt="<?php $themes->name(); ?>"/></td>
<td valign="top">
<h3><?php '' != $themes->title ? $themes->title() : $themes->name(); ?></h3>
<cite>
<?php if($themes->author): ?><?php _e('作者'); ?>: <?php if($themes->homepage): ?><a href="<?php $themes->homepage() ?>"><?php endif; ?><?php $themes->author(); ?><?php if($themes->homepage): ?></a><?php endif; ?> &nbsp;&nbsp;<?php endif; ?>
<?php if($themes->version): ?><?php _e('版本'); ?>: <?php $themes->version() ?><?php endif; ?>
<?php if ($themes->author): ?><?php _e('作者'); ?>: <?php if ($themes->homepage): ?><a href="<?php $themes->homepage() ?>"><?php endif; ?><?php $themes->author(); ?><?php if ($themes->homepage): ?></a><?php endif; ?> &nbsp;&nbsp;<?php endif; ?>
<?php if ($themes->version): ?><?php _e('版本'); ?>: <?php $themes->version() ?><?php endif; ?>
</cite>
<p><?php echo nl2br($themes->description); ?></p>
<?php if($options->theme != $themes->name): ?>
<?php if ($options->theme != $themes->name): ?>
<p>
<?php if (!defined('__TYPECHO_THEME_WRITEABLE__') || __TYPECHO_THEME_WRITEABLE__): ?>
<a class="edit" href="<?php $options->adminUrl('theme-editor.php?theme=' . $themes->name); ?>"><?php _e('编辑'); ?></a> &nbsp;
<a class="edit"
href="<?php $options->adminUrl('theme-editor.php?theme=' . $themes->name); ?>"><?php _e('编辑'); ?></a> &nbsp;
<?php endif; ?>
<a class="activate" href="<?php $security->index('/action/themes-edit?change=' . $themes->name); ?>"><?php _e('启用'); ?></a>
<a class="activate"
href="<?php $security->index('/action/themes-edit?change=' . $themes->name); ?>"><?php _e('启用'); ?></a>
</p>
<?php endif; ?>
</td>
</tr>
<?php endwhile; ?>
<?php endwhile; ?>
</tbody>
</table>
</div>

View File

@ -2,8 +2,6 @@
include 'common.php';
include 'header.php';
include 'menu.php';
$errors = $security->systemCheck();
?>
<div class="main">
@ -12,29 +10,21 @@ $errors = $security->systemCheck();
<div class="row typecho-page-main" role="main">
<div class="col-mb-12">
<div id="typecho-welcome">
<?php if (!empty($errors)): ?>
<form action="<?php echo Typecho_Common::url('upgrade.php', $options->adminUrl); ?>" method="get">
<h3><?php _e('发现安全问题'); ?></h3>
<ul>
<?php foreach ($errors as $error): ?>
<li class="warning"><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<p><button class="btn primary" type="submit"><?php _e('解决完毕 &raquo;'); ?></button></p>
</form>
<?php else: ?>
<form action="<?php echo $security->getTokenUrl(
Typecho_Router::url('do', array('action' => 'upgrade', 'widget' => 'Upgrade'),
Typecho_Common::url('index.php', $options->rootUrl))); ?>" method="post">
<h3><?php _e('检测到新版本!'); ?></h3>
<ul>
<li><?php _e('您已经更新了系统程序, 我们还需要执行一些后续步骤来完成升级'); ?></li>
<li><?php _e('此程序将把您的系统从 <strong>%s</strong> 升级到 <strong>%s</strong>', $options->version, Typecho_Common::VERSION); ?></li>
<li><strong class="warning"><?php _e('在升级之前强烈建议先<a href="%s">备份您的数据</a>', Typecho_Common::url('backup.php', $options->adminUrl)); ?></strong></li>
</ul>
<p><button class="btn primary" type="submit"><?php _e('完成升级 &raquo;'); ?></button></p>
</form>
<?php endif; ?>
<form action="<?php echo $security->getTokenUrl(
\Typecho\Router::url('do', ['action' => 'upgrade', 'widget' => 'Upgrade'],
\Typecho\Common::url('index.php', $options->rootUrl))); ?>" method="post">
<h3><?php _e('检测到新版本!'); ?></h3>
<ul>
<li><?php _e('您已经更新了系统程序, 我们还需要执行一些后续步骤来完成升级'); ?></li>
<li><?php _e('此程序将把您的系统从 <strong>%s</strong> 升级到 <strong>%s</strong>', $options->version, \Typecho\Common::VERSION); ?></li>
<li><strong
class="warning"><?php _e('在升级之前强烈建议先<a href="%s">备份您的数据</a>', \Typecho\Common::url('backup.php', $options->adminUrl)); ?></strong>
</li>
</ul>
<p>
<button class="btn primary" type="submit"><?php _e('完成升级 &raquo;'); ?></button>
</p>
</form>
</div>
</div>
</div>
@ -46,10 +36,10 @@ include 'copyright.php';
include 'common-js.php';
?>
<script>
(function () {
if (window.sessionStorage) {
sessionStorage.removeItem('update');
}
})();
(function () {
if (window.sessionStorage) {
sessionStorage.removeItem('update');
}
})();
</script>
<?php include 'footer.php'; ?>

View File

@ -9,7 +9,7 @@ include 'menu.php';
<?php include 'page-title.php'; ?>
<div class="row typecho-page-main" role="form">
<div class="col-mb-12 col-tb-6 col-tb-offset-3">
<?php Typecho_Widget::widget('Widget_Users_Edit')->form()->render(); ?>
<?php \Widget\Users\Edit::alloc()->form()->render(); ?>
</div>
</div>
</div>

View File

@ -1,6 +1,6 @@
<?php if(!defined('__TYPECHO_ADMIN__')) exit; ?>
<?php Typecho_Plugin::factory('admin/write-js.php')->write(); ?>
<?php Typecho_Widget::widget('Widget_Metas_Tag_Cloud', 'sort=count&desc=1&limit=200')->to($tags); ?>
<?php \Typecho\Plugin::factory('admin/write-js.php')->write(); ?>
<?php \Widget\Metas\Tag\Cloud::alloc('sort=count&desc=1&limit=200')->to($tags); ?>
<script src="<?php $options->adminStaticUrl('js', 'timepicker.js'); ?>"></script>
<script src="<?php $options->adminStaticUrl('js', 'tokeninput.js'); ?>"></script>
@ -67,7 +67,7 @@ $(document).ready(function() {
'tags' => $tags->name
);
}
echo Json::encode($data);
echo json_encode($data);
?>, {
propertyToSearch: 'tags',
tokenValue : 'tags',

View File

@ -2,7 +2,7 @@
include 'common.php';
include 'header.php';
include 'menu.php';
Typecho_Widget::widget('Widget_Contents_Page_Edit')->to($page);
\Widget\Contents\Page\Edit::alloc()->to($page);
?>
<div class="main">
<div class="body container">
@ -12,21 +12,23 @@ Typecho_Widget::widget('Widget_Contents_Page_Edit')->to($page);
<div class="col-mb-12 col-tb-9" role="main">
<?php if ($page->draft): ?>
<?php if ($page->draft['cid'] != $page->cid): ?>
<?php $pageModifyDate = new Typecho_Date($page->draft['modified']); ?>
<cite class="edit-draft-notice"><?php _e('当前正在编辑的是保存于%s的草稿, 你可以<a href="%s">删除它</a>', $pageModifyDate->word(),
<?php $pageModifyDate = new \Typecho\Date($page->draft['modified']); ?>
<cite
class="edit-draft-notice"><?php _e('当前正在编辑的是保存于%s的草稿, 你可以<a href="%s">删除它</a>', $pageModifyDate->word(),
$security->getIndex('/action/contents-page-edit?do=deleteDraft&cid=' . $page->cid)); ?></cite>
<?php else: ?>
<cite class="edit-draft-notice"><?php _e('当前正在编辑的是未发布的草稿'); ?></cite>
<?php endif; ?>
<input name="draft" type="hidden" value="<?php echo $page->draft['cid'] ?>" />
<input name="draft" type="hidden" value="<?php echo $page->draft['cid'] ?>"/>
<?php endif; ?>
<p class="title">
<label for="title" class="sr-only"><?php _e('标题'); ?></label>
<input type="text" id="title" name="title" autocomplete="off" value="<?php $page->title(); ?>" placeholder="<?php _e('标题'); ?>" class="w-100 text title" />
<input type="text" id="title" name="title" autocomplete="off" value="<?php $page->title(); ?>"
placeholder="<?php _e('标题'); ?>" class="w-100 text title"/>
</p>
<?php $permalink = Typecho_Common::url($options->routingTable['page']['url'], $options->index);
list ($scheme, $permalink) = explode(':', $permalink, 2);
<?php $permalink = \Typecho\Common::url($options->routingTable['page']['url'], $options->index);
[$scheme, $permalink] = explode(':', $permalink, 2);
$permalink = ltrim($permalink, '/');
$permalink = preg_replace("/\[([_a-z0-9-]+)[^\]]*\]/i", "{\\1}", $permalink);
if ($page->have()) {
@ -40,26 +42,31 @@ Typecho_Widget::widget('Widget_Contents_Page_Edit')->to($page);
</p>
<p>
<label for="text" class="sr-only"><?php _e('页面内容'); ?></label>
<textarea style="height: <?php $options->editorSize(); ?>px" autocomplete="off" id="text" name="text" class="w-100 mono"><?php echo htmlspecialchars($page->text); ?></textarea>
<textarea style="height: <?php $options->editorSize(); ?>px" autocomplete="off" id="text"
name="text" class="w-100 mono"><?php echo htmlspecialchars($page->text); ?></textarea>
</p>
<?php include 'custom-fields.php'; ?>
<p class="submit clearfix">
<span class="left">
<button type="button" id="btn-cancel-preview" class="btn"><i class="i-caret-left"></i> <?php _e('取消预览'); ?></button>
<button type="button" id="btn-cancel-preview" class="btn"><i
class="i-caret-left"></i> <?php _e('取消预览'); ?></button>
</span>
<span class="right">
<input type="hidden" name="cid" value="<?php $page->cid(); ?>" />
<button type="button" id="btn-preview" class="btn"><i class="i-exlink"></i> <?php _e('预览页面'); ?></button>
<button type="submit" name="do" value="save" id="btn-save" class="btn"><?php _e('保存草稿'); ?></button>
<button type="submit" name="do" value="publish" class="btn primary" id="btn-submit"><?php _e('发布页面'); ?></button>
<input type="hidden" name="cid" value="<?php $page->cid(); ?>"/>
<button type="button" id="btn-preview" class="btn"><i
class="i-exlink"></i> <?php _e('预览页面'); ?></button>
<button type="submit" name="do" value="save" id="btn-save"
class="btn"><?php _e('保存草稿'); ?></button>
<button type="submit" name="do" value="publish" class="btn primary"
id="btn-submit"><?php _e('发布页面'); ?></button>
<?php if ($options->markdown && (!$page->have() || $page->isMarkdown)): ?>
<input type="hidden" name="markdown" value="1" />
<input type="hidden" name="markdown" value="1"/>
<?php endif; ?>
</span>
</p>
<?php Typecho_Plugin::factory('admin/write-page.php')->content($page); ?>
<?php \Typecho\Plugin::factory('admin/write-page.php')->content($page); ?>
</div>
<div id="edit-secondary" class="col-mb-12 col-tb-3" role="complementary">
<ul class="typecho-option-tabs clearfix">
@ -68,68 +75,80 @@ Typecho_Widget::widget('Widget_Contents_Page_Edit')->to($page);
</ul>
<div id="tab-advance" class="tab-content">
<section class="typecho-post-option" role="application">
<section class="typecho-post-option" role="application">
<label for="date" class="typecho-label"><?php _e('发布日期'); ?></label>
<p><input class="typecho-date w-100" type="text" name="date" id="date" autocomplete="off" value="<?php $page->have() && $page->created > 0 ? $page->date('Y-m-d H:i') : ''; ?>" /></p>
<p><input class="typecho-date w-100" type="text" name="date" id="date" autocomplete="off"
value="<?php $page->have() && $page->created > 0 ? $page->date('Y-m-d H:i') : ''; ?>"/>
</p>
</section>
<section class="typecho-post-option">
<label for="order" class="typecho-label"><?php _e('页面顺序'); ?></label>
<p><input type="text" id="order" name="order" value="<?php $page->order(); ?>" class="w-100" /></p>
<p><input type="text" id="order" name="order" value="<?php $page->order(); ?>"
class="w-100"/></p>
<p class="description"><?php _e('为你的自定义页面设定一个序列值以后, 能够使得它们按此值从小到大排列'); ?></p>
</section>
<section class="typecho-post-option">
<section class="typecho-post-option">
<label for="template" class="typecho-label"><?php _e('自定义模板'); ?></label>
<p>
<select name="template" id="template">
<option value=""><?php _e('不选择'); ?></option>
<?php $templates = $page->getTemplates(); foreach ($templates as $template => $name): ?>
<option value="<?php echo $template; ?>"<?php if($template == $page->template): ?> selected="true"<?php endif; ?>><?php echo $name; ?></option>
<?php endforeach; ?>
</select>
</p>
<p class="description"><?php _e('如果你为此页面选择了一个自定义模板, 系统将按照你选择的模板文件展现它'); ?></p>
<p>
<select name="template" id="template">
<option value=""><?php _e('不选择'); ?></option>
<?php $templates = $page->getTemplates();
foreach ($templates as $template => $name): ?>
<option
value="<?php echo $template; ?>"<?php if ($template == $page->template): ?> selected="true"<?php endif; ?>><?php echo $name; ?></option>
<?php endforeach; ?>
</select>
</p>
<p class="description"><?php _e('如果你为此页面选择了一个自定义模板, 系统将按照你选择的模板文件展现它'); ?></p>
</section>
<?php Typecho_Plugin::factory('admin/write-page.php')->option($page); ?>
<?php \Typecho\Plugin::factory('admin/write-page.php')->option($page); ?>
<button type="button" id="advance-panel-btn" class="btn btn-xs"><?php _e('高级选项'); ?> <i class="i-caret-down"></i></button>
<button type="button" id="advance-panel-btn" class="btn btn-xs"><?php _e('高级选项'); ?> <i
class="i-caret-down"></i></button>
<div id="advance-panel">
<section class="typecho-post-option visibility-option">
<label for="visibility" class="typecho-label"><?php _e('公开度'); ?></label>
<p>
<select id="visibility" name="visibility">
<option value="publish"<?php if ($page->status == 'publish' || !$page->status): ?> selected<?php endif; ?>><?php _e('公开'); ?></option>
<option value="hidden"<?php if ($page->status == 'hidden'): ?> selected<?php endif; ?>><?php _e('隐藏'); ?></option>
</select>
<select id="visibility" name="visibility">
<option
value="publish"<?php if ($page->status == 'publish' || !$page->status): ?> selected<?php endif; ?>><?php _e('公开'); ?></option>
<option
value="hidden"<?php if ($page->status == 'hidden'): ?> selected<?php endif; ?>><?php _e('隐藏'); ?></option>
</select>
</p>
</section>
<section class="typecho-post-option allow-option">
<label class="typecho-label"><?php _e('权限控制'); ?></label>
<ul>
<li><input id="allowComment" name="allowComment" type="checkbox" value="1" <?php if($page->allow('comment')): ?>checked="true"<?php endif; ?> />
<label for="allowComment"><?php _e('允许评论'); ?></label></li>
<li><input id="allowPing" name="allowPing" type="checkbox" value="1" <?php if($page->allow('ping')): ?>checked="true"<?php endif; ?> />
<label for="allowPing"><?php _e('允许被引用'); ?></label></li>
<li><input id="allowFeed" name="allowFeed" type="checkbox" value="1" <?php if($page->allow('feed')): ?>checked="true"<?php endif; ?> />
<label for="allowFeed"><?php _e('允许在聚合中出现'); ?></label></li>
<li><input id="allowComment" name="allowComment" type="checkbox" value="1"
<?php if ($page->allow('comment')): ?>checked="true"<?php endif; ?> />
<label for="allowComment"><?php _e('允许评论'); ?></label></li>
<li><input id="allowPing" name="allowPing" type="checkbox" value="1"
<?php if ($page->allow('ping')): ?>checked="true"<?php endif; ?> />
<label for="allowPing"><?php _e('允许被引用'); ?></label></li>
<li><input id="allowFeed" name="allowFeed" type="checkbox" value="1"
<?php if ($page->allow('feed')): ?>checked="true"<?php endif; ?> />
<label for="allowFeed"><?php _e('允许在聚合中出现'); ?></label></li>
</ul>
</section>
<?php Typecho_Plugin::factory('admin/write-page.php')->advanceOption($page); ?>
<?php \Typecho\Plugin::factory('admin/write-page.php')->advanceOption($page); ?>
</div>
<?php if($page->have()): ?>
<?php $modified = new Typecho_Date($page->modified); ?>
<section class="typecho-post-option">
<p class="description">
<br>&mdash;<br>
<?php _e('本页面由 <a href="%s">%s</a> 创建',
Typecho_Common::url('manage-pages.php?uid=' . $page->author->uid, $options->adminUrl), $page->author->screenName); ?><br>
<?php _e('最后更新于 %s', $modified->word()); ?>
</p>
</section>
<?php if ($page->have()): ?>
<?php $modified = new \Typecho\Date($page->modified); ?>
<section class="typecho-post-option">
<p class="description">
<br>&mdash;<br>
<?php _e('本页面由 <a href="%s">%s</a> 创建',
\Typecho\Common::url('manage-pages.php?uid=' . $page->author->uid, $options->adminUrl), $page->author->screenName); ?>
<br>
<?php _e('最后更新于 %s', $modified->word()); ?>
</p>
</section>
<?php endif; ?>
</div><!-- end #tab-advance -->
@ -148,13 +167,13 @@ include 'common-js.php';
include 'form-js.php';
include 'write-js.php';
Typecho_Plugin::factory('admin/write-page.php')->trigger($plugged)->richEditor($page);
\Typecho\Plugin::factory('admin/write-page.php')->trigger($plugged)->richEditor($page);
if (!$plugged) {
include 'editor-js.php';
}
include 'file-upload-js.php';
include 'custom-fields-js.php';
Typecho_Plugin::factory('admin/write-page.php')->bottom($page);
\Typecho\Plugin::factory('admin/write-page.php')->bottom($page);
include 'footer.php';
?>

View File

@ -2,7 +2,7 @@
include 'common.php';
include 'header.php';
include 'menu.php';
Typecho_Widget::widget('Widget_Contents_Post_Edit')->to($post);
\Widget\Contents\Post\Edit::alloc()->to($post);
?>
<div class="main">
<div class="body container">
@ -12,29 +12,31 @@ Typecho_Widget::widget('Widget_Contents_Post_Edit')->to($post);
<div class="col-mb-12 col-tb-9" role="main">
<?php if ($post->draft): ?>
<?php if ($post->draft['cid'] != $post->cid): ?>
<?php $postModifyDate = new Typecho_Date($post->draft['modified']); ?>
<cite class="edit-draft-notice"><?php _e('你正在编辑的是保存于 %s 的草稿, 你也可以 <a href="%s">删除它</a>', $postModifyDate->word(),
<?php $postModifyDate = new \Typecho\Date($post->draft['modified']); ?>
<cite
class="edit-draft-notice"><?php _e('你正在编辑的是保存于 %s 的草稿, 你也可以 <a href="%s">删除它</a>', $postModifyDate->word(),
$security->getIndex('/action/contents-post-edit?do=deleteDraft&cid=' . $post->cid)); ?></cite>
<?php else: ?>
<cite class="edit-draft-notice"><?php _e('当前正在编辑的是未发布的草稿'); ?></cite>
<?php endif; ?>
<input name="draft" type="hidden" value="<?php echo $post->draft['cid'] ?>" />
<input name="draft" type="hidden" value="<?php echo $post->draft['cid'] ?>"/>
<?php endif; ?>
<p class="title">
<label for="title" class="sr-only"><?php _e('标题'); ?></label>
<input type="text" id="title" name="title" autocomplete="off" value="<?php $post->title(); ?>" placeholder="<?php _e('标题'); ?>" class="w-100 text title" />
<input type="text" id="title" name="title" autocomplete="off" value="<?php $post->title(); ?>"
placeholder="<?php _e('标题'); ?>" class="w-100 text title"/>
</p>
<?php $permalink = Typecho_Common::url($options->routingTable['post']['url'], $options->index);
list ($scheme, $permalink) = explode(':', $permalink, 2);
<?php $permalink = \Typecho\Common::url($options->routingTable['post']['url'], $options->index);
[$scheme, $permalink] = explode(':', $permalink, 2);
$permalink = ltrim($permalink, '/');
$permalink = preg_replace("/\[([_a-z0-9-]+)[^\]]*\]/i", "{\\1}", $permalink);
if ($post->have()) {
$permalink = str_replace(array(
$permalink = str_replace([
'{cid}', '{category}', '{year}', '{month}', '{day}'
), array(
], [
$post->cid, $post->category, $post->year, $post->month, $post->day
), $permalink);
], $permalink);
}
$input = '<input type="text" id="slug" name="slug" autocomplete="off" value="' . htmlspecialchars($post->slug) . '" class="mono" />';
?>
@ -44,27 +46,32 @@ Typecho_Widget::widget('Widget_Contents_Post_Edit')->to($post);
</p>
<p>
<label for="text" class="sr-only"><?php _e('文章内容'); ?></label>
<textarea style="height: <?php $options->editorSize(); ?>px" autocomplete="off" id="text" name="text" class="w-100 mono"><?php echo htmlspecialchars($post->text); ?></textarea>
<textarea style="height: <?php $options->editorSize(); ?>px" autocomplete="off" id="text"
name="text" class="w-100 mono"><?php echo htmlspecialchars($post->text); ?></textarea>
</p>
<?php include 'custom-fields.php'; ?>
<p class="submit clearfix">
<span class="left">
<button type="button" id="btn-cancel-preview" class="btn"><i class="i-caret-left"></i> <?php _e('取消预览'); ?></button>
<button type="button" id="btn-cancel-preview" class="btn"><i
class="i-caret-left"></i> <?php _e('取消预览'); ?></button>
</span>
<span class="right">
<input type="hidden" name="cid" value="<?php $post->cid(); ?>" />
<button type="button" id="btn-preview" class="btn"><i class="i-exlink"></i> <?php _e('预览文章'); ?></button>
<button type="submit" name="do" value="save" id="btn-save" class="btn"><?php _e('保存草稿'); ?></button>
<button type="submit" name="do" value="publish" class="btn primary" id="btn-submit"><?php _e('发布文章'); ?></button>
<input type="hidden" name="cid" value="<?php $post->cid(); ?>"/>
<button type="button" id="btn-preview" class="btn"><i
class="i-exlink"></i> <?php _e('预览文章'); ?></button>
<button type="submit" name="do" value="save" id="btn-save"
class="btn"><?php _e('保存草稿'); ?></button>
<button type="submit" name="do" value="publish" class="btn primary"
id="btn-submit"><?php _e('发布文章'); ?></button>
<?php if ($options->markdown && (!$post->have() || $post->isMarkdown)): ?>
<input type="hidden" name="markdown" value="1" />
<input type="hidden" name="markdown" value="1"/>
<?php endif; ?>
</span>
</p>
<?php Typecho_Plugin::factory('admin/write-post.php')->content($post); ?>
<?php \Typecho\Plugin::factory('admin/write-post.php')->content($post); ?>
</div>
<div id="edit-secondary" class="col-mb-12 col-tb-3" role="complementary">
@ -77,88 +84,108 @@ Typecho_Widget::widget('Widget_Contents_Post_Edit')->to($post);
<div id="tab-advance" class="tab-content">
<section class="typecho-post-option" role="application">
<label for="date" class="typecho-label"><?php _e('发布日期'); ?></label>
<p><input class="typecho-date w-100" type="text" name="date" id="date" autocomplete="off" value="<?php $post->have() && $post->created > 0 ? $post->date('Y-m-d H:i') : ''; ?>" /></p>
<p><input class="typecho-date w-100" type="text" name="date" id="date" autocomplete="off"
value="<?php $post->have() && $post->created > 0 ? $post->date('Y-m-d H:i') : ''; ?>"/>
</p>
</section>
<section class="typecho-post-option category-option">
<label class="typecho-label"><?php _e('分类'); ?></label>
<?php Typecho_Widget::widget('Widget_Metas_Category_List')->to($category); ?>
<?php \Widget\Metas\Category\Rows::alloc()->to($category); ?>
<ul>
<?php
if ($post->have()) {
$categories = Typecho_Common::arrayFlatten($post->categories, 'mid');
$categories = array_column($post->categories, 'mid');
} else {
$categories = array();
$categories = [];
}
?>
<?php while($category->next()): ?>
<li><?php echo str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $category->levels); ?><input type="checkbox" id="category-<?php $category->mid(); ?>" value="<?php $category->mid(); ?>" name="category[]" <?php if(in_array($category->mid, $categories)): ?>checked="true"<?php endif; ?>/>
<label for="category-<?php $category->mid(); ?>"><?php $category->name(); ?></label></li>
<?php while ($category->next()): ?>
<li><?php echo str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $category->levels); ?><input
type="checkbox" id="category-<?php $category->mid(); ?>"
value="<?php $category->mid(); ?>" name="category[]"
<?php if (in_array($category->mid, $categories)): ?>checked="true"<?php endif; ?>/>
<label
for="category-<?php $category->mid(); ?>"><?php $category->name(); ?></label>
</li>
<?php endwhile; ?>
</ul>
</section>
<section class="typecho-post-option">
<label for="token-input-tags" class="typecho-label"><?php _e('标签'); ?></label>
<p><input id="tags" name="tags" type="text" value="<?php $post->tags(',', false); ?>" class="w-100 text" /></p>
<p><input id="tags" name="tags" type="text" value="<?php $post->tags(',', false); ?>"
class="w-100 text"/></p>
</section>
<?php Typecho_Plugin::factory('admin/write-post.php')->option($post); ?>
<?php \Typecho\Plugin::factory('admin/write-post.php')->option($post); ?>
<button type="button" id="advance-panel-btn" class="btn btn-xs"><?php _e('高级选项'); ?> <i class="i-caret-down"></i></button>
<button type="button" id="advance-panel-btn" class="btn btn-xs"><?php _e('高级选项'); ?> <i
class="i-caret-down"></i></button>
<div id="advance-panel">
<?php if($user->pass('editor', true)): ?>
<section class="typecho-post-option visibility-option">
<label for="visibility" class="typecho-label"><?php _e('公开度'); ?></label>
<p>
<select id="visibility" name="visibility">
<?php if ($user->pass('editor', true)): ?>
<option value="publish"<?php if (($post->status == 'publish' && !$post->password) || !$post->status): ?> selected<?php endif; ?>><?php _e('公开'); ?></option>
<option value="hidden"<?php if ($post->status == 'hidden'): ?> selected<?php endif; ?>><?php _e('隐藏'); ?></option>
<option value="password"<?php if (strlen($post->password) > 0): ?> selected<?php endif; ?>><?php _e('密码保护'); ?></option>
<option value="private"<?php if ($post->status == 'private'): ?> selected<?php endif; ?>><?php _e('私密'); ?></option>
<?php endif; ?>
<option value="waiting"<?php if (!$user->pass('editor', true) || $post->status == 'waiting'): ?> selected<?php endif; ?>><?php _e('待审核'); ?></option>
</select>
</p>
<p id="post-password"<?php if (strlen($post->password) == 0): ?> class="hidden"<?php endif; ?>>
<label for="protect-pwd" class="sr-only">内容密码</label>
<input type="text" name="password" id="protect-pwd" class="text-s" value="<?php $post->password(); ?>" size="16" placeholder="<?php _e('内容密码'); ?>" autocomplete="off" />
</p>
</section>
<?php if ($user->pass('editor', true)): ?>
<section class="typecho-post-option visibility-option">
<label for="visibility" class="typecho-label"><?php _e('公开度'); ?></label>
<p>
<select id="visibility" name="visibility">
<?php if ($user->pass('editor', true)): ?>
<option
value="publish"<?php if (($post->status == 'publish' && !$post->password) || !$post->status): ?> selected<?php endif; ?>><?php _e('公开'); ?></option>
<option
value="hidden"<?php if ($post->status == 'hidden'): ?> selected<?php endif; ?>><?php _e('隐藏'); ?></option>
<option
value="password"<?php if (strlen($post->password) > 0): ?> selected<?php endif; ?>><?php _e('密码保护'); ?></option>
<option
value="private"<?php if ($post->status == 'private'): ?> selected<?php endif; ?>><?php _e('私密'); ?></option>
<?php endif; ?>
<option
value="waiting"<?php if (!$user->pass('editor', true) || $post->status == 'waiting'): ?> selected<?php endif; ?>><?php _e('待审核'); ?></option>
</select>
</p>
<p id="post-password"<?php if (strlen($post->password) == 0): ?> class="hidden"<?php endif; ?>>
<label for="protect-pwd" class="sr-only">内容密码</label>
<input type="text" name="password" id="protect-pwd" class="text-s"
value="<?php $post->password(); ?>" size="16"
placeholder="<?php _e('内容密码'); ?>" autocomplete="off"/>
</p>
</section>
<?php endif; ?>
<section class="typecho-post-option allow-option">
<label class="typecho-label"><?php _e('权限控制'); ?></label>
<ul>
<li><input id="allowComment" name="allowComment" type="checkbox" value="1" <?php if($post->allow('comment')): ?>checked="true"<?php endif; ?> />
<label for="allowComment"><?php _e('允许评论'); ?></label></li>
<li><input id="allowPing" name="allowPing" type="checkbox" value="1" <?php if($post->allow('ping')): ?>checked="true"<?php endif; ?> />
<label for="allowPing"><?php _e('允许被引用'); ?></label></li>
<li><input id="allowFeed" name="allowFeed" type="checkbox" value="1" <?php if($post->allow('feed')): ?>checked="true"<?php endif; ?> />
<label for="allowFeed"><?php _e('允许在聚合中出现'); ?></label></li>
<li><input id="allowComment" name="allowComment" type="checkbox" value="1"
<?php if ($post->allow('comment')): ?>checked="true"<?php endif; ?> />
<label for="allowComment"><?php _e('允许评论'); ?></label></li>
<li><input id="allowPing" name="allowPing" type="checkbox" value="1"
<?php if ($post->allow('ping')): ?>checked="true"<?php endif; ?> />
<label for="allowPing"><?php _e('允许被引用'); ?></label></li>
<li><input id="allowFeed" name="allowFeed" type="checkbox" value="1"
<?php if ($post->allow('feed')): ?>checked="true"<?php endif; ?> />
<label for="allowFeed"><?php _e('允许在聚合中出现'); ?></label></li>
</ul>
</section>
<section class="typecho-post-option">
<label for="trackback" class="typecho-label"><?php _e('引用通告'); ?></label>
<p><textarea id="trackback" class="w-100 mono" name="trackback" rows="2"></textarea></p>
<p class="description"><?php _e('每一行一个引用地址, 用回车隔开'); ?></p>
</section>
<?php Typecho_Plugin::factory('admin/write-post.php')->advanceOption($post); ?>
<?php \Typecho\Plugin::factory('admin/write-post.php')->advanceOption($post); ?>
</div><!-- end #advance-panel -->
<?php if($post->have()): ?>
<?php $modified = new Typecho_Date($post->modified); ?>
<section class="typecho-post-option">
<p class="description">
<br>&mdash;<br>
<?php _e('本文由 <a href="%s">%s</a> 撰写',
Typecho_Common::url('manage-posts.php?uid=' . $post->author->uid, $options->adminUrl), $post->author->screenName); ?><br>
<?php _e('最后更新于 %s', $modified->word()); ?>
</p>
</section>
<?php if ($post->have()): ?>
<?php $modified = new \Typecho\Date($post->modified); ?>
<section class="typecho-post-option">
<p class="description">
<br>&mdash;<br>
<?php _e('本文由 <a href="%s">%s</a> 撰写',
\Typecho\Common::url('manage-posts.php?uid=' . $post->author->uid, $options->adminUrl), $post->author->screenName); ?>
<br>
<?php _e('最后更新于 %s', $modified->word()); ?>
</p>
</section>
<?php endif; ?>
</div><!-- end #tab-advance -->
@ -177,13 +204,13 @@ include 'common-js.php';
include 'form-js.php';
include 'write-js.php';
Typecho_Plugin::factory('admin/write-post.php')->trigger($plugged)->richEditor($post);
\Typecho\Plugin::factory('admin/write-post.php')->trigger($plugged)->richEditor($post);
if (!$plugged) {
include 'editor-js.php';
}
include 'file-upload-js.php';
include 'custom-fields-js.php';
Typecho_Plugin::factory('admin/write-post.php')->bottom($post);
\Typecho\Plugin::factory('admin/write-post.php')->bottom($post);
include 'footer.php';
?>

View File

@ -14,13 +14,13 @@ if (!defined('__TYPECHO_ROOT_DIR__') && !@include_once 'config.inc.php') {
}
/** 初始化组件 */
Typecho_Widget::widget('Widget_Init');
\Widget\Init::alloc();
/** 注册一个初始化插件 */
Typecho_Plugin::factory('index.php')->begin();
\Typecho\Plugin::factory('index.php')->begin();
/** 开始路由分发 */
Typecho_Router::dispatch();
\Typecho\Router::dispatch();
/** 注册一个结束插件 */
Typecho_Plugin::factory('index.php')->end();
\Typecho\Plugin::factory('index.php')->end();

View File

@ -1,58 +1,49 @@
<?php if (!file_exists(dirname(__FILE__) . '/config.inc.php')): ?>
<?php
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id$
*/
// site root path
define('__TYPECHO_ROOT_DIR__', dirname(__FILE__));
if (!file_exists(dirname(__FILE__) . '/config.inc.php')) {
// site root path
define('__TYPECHO_ROOT_DIR__', dirname(__FILE__));
// plugin directory (relative path)
define('__TYPECHO_PLUGIN_DIR__', '/usr/plugins');
// plugin directory (relative path)
define('__TYPECHO_PLUGIN_DIR__', '/usr/plugins');
// theme directory (relative path)
define('__TYPECHO_THEME_DIR__', '/usr/themes');
// theme directory (relative path)
define('__TYPECHO_THEME_DIR__', '/usr/themes');
// admin directory (relative path)
define('__TYPECHO_ADMIN_DIR__', '/admin/');
// admin directory (relative path)
define('__TYPECHO_ADMIN_DIR__', '/admin/');
// register autoload
require_once __TYPECHO_ROOT_DIR__ . '/var/Typecho/Common.php';
// init
Typecho_Common::init();
else:
// register autoload
require_once __TYPECHO_ROOT_DIR__ . '/var/Typecho/Common.php';
// init
\Typecho\Common::init();
} else {
require_once dirname(__FILE__) . '/config.inc.php';
$installDb = Typecho_Db::get();
endif;
$installDb = \Typecho\Db::get();
}
/**
* get lang
*
* @return string
*/
function install_get_lang(): string {
$serverLang = Typecho_Request::getInstance()->getServer('TYPECHO_LANG');
function install_get_lang(): string
{
$serverLang = \Typecho\Request::getInstance()->getServer('TYPECHO_LANG');
if (!empty($serverLang)) {
return $serverLang;
} else {
$lang = 'zh_CN';
$request = Typecho_Request::getInstance();
$request = \Typecho\Request::getInstance();
if ($request->is('lang')) {
$lang = $request->get('lang');
Typecho_Cookie::set('lang', $lang);
\Typecho\Cookie::set('lang', $lang);
}
return Typecho_Cookie::get('lang', $lang);
return \Typecho\Cookie::get('lang', $lang);
}
}
@ -61,8 +52,9 @@ function install_get_lang(): string {
*
* @return string
*/
function install_get_site_url(): string {
$serverSiteUrl = Typecho_Request::getInstance()->getServer(
function install_get_site_url(): string
{
$serverSiteUrl = \Typecho\Request::getInstance()->getServer(
'TYPECHO_SITE_URL',
install_is_cli() ? 'http://localhost' : null
);
@ -70,7 +62,7 @@ function install_get_site_url(): string {
if (!empty($serverSiteUrl)) {
return $serverSiteUrl;
} else {
$request = Typecho_Request::getInstance();
$request = \Typecho\Request::getInstance();
return $request->get('userUrl', $request->getRequestRoot());
}
}
@ -80,8 +72,170 @@ function install_get_site_url(): string {
*
* @return bool
*/
function install_is_cli(): bool {
return php_sapi_name() == 'cli';
function install_is_cli(): bool
{
return \Typecho\Request::getInstance()->isCli();
}
/**
* get default router
*
* @return string[][]
*/
function install_get_default_routers(): array
{
return [
'index' =>
[
'url' => '/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'archive' =>
[
'url' => '/blog/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'do' =>
[
'url' => '/action/[action:alpha]',
'widget' => '\Widget\Action',
'action' => 'action',
],
'post' =>
[
'url' => '/archives/[cid:digital]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'attachment' =>
[
'url' => '/attachment/[cid:digital]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'category' =>
[
'url' => '/category/[slug]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'tag' =>
[
'url' => '/tag/[slug]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'author' =>
[
'url' => '/author/[uid:digital]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'search' =>
[
'url' => '/search/[keywords]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'index_page' =>
[
'url' => '/page/[page:digital]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'archive_page' =>
[
'url' => '/blog/page/[page:digital]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'category_page' =>
[
'url' => '/category/[slug]/[page:digital]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'tag_page' =>
[
'url' => '/tag/[slug]/[page:digital]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'author_page' =>
[
'url' => '/author/[uid:digital]/[page:digital]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'search_page' =>
[
'url' => '/search/[keywords]/[page:digital]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'archive_year' =>
[
'url' => '/[year:digital:4]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'archive_month' =>
[
'url' => '/[year:digital:4]/[month:digital:2]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'archive_day' =>
[
'url' => '/[year:digital:4]/[month:digital:2]/[day:digital:2]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'archive_year_page' =>
[
'url' => '/[year:digital:4]/page/[page:digital]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'archive_month_page' =>
[
'url' => '/[year:digital:4]/[month:digital:2]/page/[page:digital]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'archive_day_page' =>
[
'url' => '/[year:digital:4]/[month:digital:2]/[day:digital:2]/page/[page:digital]/',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'comment_page' =>
[
'url' => '[permalink:string]/comment-page-[commentPage:digital]',
'widget' => '\Widget\Archive',
'action' => 'render',
],
'feed' =>
[
'url' => '/feed[feed:string:0]',
'widget' => '\Widget\Archive',
'action' => 'feed',
],
'feedback' =>
[
'url' => '[permalink:string]/[type:alpha]',
'widget' => '\Widget\Feedback',
'action' => 'action',
],
'page' =>
[
'url' => '/[slug].html',
'widget' => '\Widget\Archive',
'action' => 'render',
],
];
}
/**
@ -89,7 +243,8 @@ function install_is_cli(): bool {
*
* @return array
*/
function install_get_default_options(): array {
function install_get_default_options(): array
{
static $options;
if (empty($options)) {
@ -98,10 +253,10 @@ function install_get_default_options(): array {
'theme:default' => 'a:2:{s:7:"logoUrl";N;s:12:"sidebarBlock";a:5:{i:0;s:15:"ShowRecentPosts";i:1;s:18:"ShowRecentComments";i:2;s:12:"ShowCategory";i:3;s:11:"ShowArchive";i:4;s:9:"ShowOther";}}',
'timezone' => '28800',
'lang' => install_get_lang(),
'charset' => _t('UTF-8'),
'charset' => 'UTF-8',
'contentType' => 'text/html',
'gzip' => 0,
'generator' => 'Typecho ' . Typecho_Common::VERSION,
'generator' => 'Typecho ' . \Typecho\Common::VERSION,
'title' => 'Hello World',
'description' => 'Your description here.',
'keywords' => 'typecho,php,blog',
@ -148,11 +303,11 @@ function install_get_default_options(): array {
'commentsAvatar' => 1,
'commentsAvatarRating' => 'G',
'commentsAntiSpam' => 1,
'routingTable' => 'a:25:{s:5:"index";a:3:{s:3:"url";s:1:"/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:7:"archive";a:3:{s:3:"url";s:6:"/blog/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:2:"do";a:3:{s:3:"url";s:22:"/action/[action:alpha]";s:6:"widget";s:9:"Widget_Do";s:6:"action";s:6:"action";}s:4:"post";a:3:{s:3:"url";s:24:"/archives/[cid:digital]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:10:"attachment";a:3:{s:3:"url";s:26:"/attachment/[cid:digital]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:8:"category";a:3:{s:3:"url";s:17:"/category/[slug]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:3:"tag";a:3:{s:3:"url";s:12:"/tag/[slug]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:6:"author";a:3:{s:3:"url";s:22:"/author/[uid:digital]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:6:"search";a:3:{s:3:"url";s:19:"/search/[keywords]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:10:"index_page";a:3:{s:3:"url";s:21:"/page/[page:digital]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:12:"archive_page";a:3:{s:3:"url";s:26:"/blog/page/[page:digital]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:13:"category_page";a:3:{s:3:"url";s:32:"/category/[slug]/[page:digital]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:8:"tag_page";a:3:{s:3:"url";s:27:"/tag/[slug]/[page:digital]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:11:"author_page";a:3:{s:3:"url";s:37:"/author/[uid:digital]/[page:digital]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:11:"search_page";a:3:{s:3:"url";s:34:"/search/[keywords]/[page:digital]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:12:"archive_year";a:3:{s:3:"url";s:18:"/[year:digital:4]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:13:"archive_month";a:3:{s:3:"url";s:36:"/[year:digital:4]/[month:digital:2]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:11:"archive_day";a:3:{s:3:"url";s:52:"/[year:digital:4]/[month:digital:2]/[day:digital:2]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:17:"archive_year_page";a:3:{s:3:"url";s:38:"/[year:digital:4]/page/[page:digital]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:18:"archive_month_page";a:3:{s:3:"url";s:56:"/[year:digital:4]/[month:digital:2]/page/[page:digital]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:16:"archive_day_page";a:3:{s:3:"url";s:72:"/[year:digital:4]/[month:digital:2]/[day:digital:2]/page/[page:digital]/";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:12:"comment_page";a:3:{s:3:"url";s:53:"[permalink:string]/comment-page-[commentPage:digital]";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}s:4:"feed";a:3:{s:3:"url";s:20:"/feed[feed:string:0]";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:4:"feed";}s:8:"feedback";a:3:{s:3:"url";s:31:"[permalink:string]/[type:alpha]";s:6:"widget";s:15:"Widget_Feedback";s:6:"action";s:6:"action";}s:4:"page";a:3:{s:3:"url";s:12:"/[slug].html";s:6:"widget";s:14:"Widget_Archive";s:6:"action";s:6:"render";}}',
'routingTable' => serialize(install_get_default_routers()),
'actionTable' => 'a:0:{}',
'panelTable' => 'a:0:{}',
'attachmentTypes' => '@image@',
'secret' => Typecho_Common::randString(32, true),
'secret' => \Typecho\Common::randString(32, true),
'installed' => 0,
'allowXmlRpc' => 2
];
@ -167,7 +322,8 @@ function install_get_default_options(): array {
* @param string $driver
* @return string
*/
function install_get_db_type(string $driver): string {
function install_get_db_type(string $driver): string
{
$parts = explode('_', $driver);
return $driver == 'Mysqli' ? 'Mysql' : array_pop($parts);
}
@ -177,30 +333,31 @@ function install_get_db_type(string $driver): string {
*
* @return array
*/
function install_get_db_drivers(): array {
function install_get_db_drivers(): array
{
$drivers = [];
if (Typecho_Db_Adapter_Pdo_Mysql::isAvailable()) {
if (\Typecho\Db\Adapter\Pdo\Mysql::isAvailable()) {
$drivers['Pdo_Mysql'] = _t('Pdo 驱动 Mysql 适配器');
}
if (Typecho_Db_Adapter_Pdo_SQLite::isAvailable()) {
$drivers['Pdo_SQLite'] = _t('Pdo 驱动 SQLite 适配器 (SQLite 3.x)');
if (\Typecho\Db\Adapter\Pdo\SQLite::isAvailable()) {
$drivers['Pdo_SQLite'] = _t('Pdo 驱动 SQLite 适配器');
}
if (Typecho_Db_Adapter_Pdo_Pgsql::isAvailable()) {
if (\Typecho\Db\Adapter\Pdo\Pgsql::isAvailable()) {
$drivers['Pdo_Pgsql'] = _t('Pdo 驱动 PostgreSql 适配器');
}
if (Typecho_Db_Adapter_Mysqli::isAvailable()) {
if (\Typecho\Db\Adapter\Mysqli::isAvailable()) {
$drivers['Mysqli'] = _t('Mysql 原生函数适配器');
}
if (Typecho_Db_Adapter_SQLite::isAvailable()) {
$drivers['SQLite'] = _t('SQLite 原生函数适配器 (SQLite 2.x)');
if (\Typecho\Db\Adapter\SQLite::isAvailable()) {
$drivers['SQLite'] = _t('SQLite 原生函数适配器');
}
if (Typecho_Db_Adapter_Pgsql::isAvailable()) {
if (\Typecho\Db\Adapter\Pgsql::isAvailable()) {
$drivers['Pgsql'] = _t('Pgsql 原生函数适配器');
}
@ -212,11 +369,12 @@ function install_get_db_drivers(): array {
*
* @return string
*/
function install_get_current_db_driver(): string {
function install_get_current_db_driver(): string
{
global $installDb;
if (empty($installDb)) {
$driver = Typecho_Request::getInstance()->get('driver');
$driver = \Typecho\Request::getInstance()->get('driver');
$drivers = install_get_db_drivers();
if (empty($driver) || !isset($drivers[$driver])) {
@ -238,18 +396,35 @@ function install_get_current_db_driver(): string {
* @param bool $return
* @return string
*/
function install_config_file(string $adapter, string $dbPrefix, array $dbConfig, bool $return = false): string {
function install_config_file(string $adapter, string $dbPrefix, array $dbConfig, bool $return = false): string
{
global $configWritten;
$lines = array_slice(file(__FILE__), 1, 26);
$lines[] = "
/** 定义数据库参数 */
\$db = new Typecho_Db('{$adapter}', '{$dbPrefix}');
\$db->addServer(" . (var_export($dbConfig, true)) . ", Typecho_Db::READ | Typecho_Db::WRITE);
Typecho_Db::set(\$db);
$code = "<" . "?php
// site root path
define('__TYPECHO_ROOT_DIR__', dirname(__FILE__));
// plugin directory (relative path)
define('__TYPECHO_PLUGIN_DIR__', '/usr/plugins');
// theme directory (relative path)
define('__TYPECHO_THEME_DIR__', '/usr/themes');
// admin directory (relative path)
define('__TYPECHO_ADMIN_DIR__', '/admin/');
// register autoload
require_once __TYPECHO_ROOT_DIR__ . '/var/Typecho/Common.php';
// init
\Typecho\Common::init();
// config db
\$db = new \Typecho\Db('{$adapter}', '{$dbPrefix}');
\$db->addServer(" . (var_export($dbConfig, true)) . ", \Typecho\Db::READ | \Typecho\Db::WRITE);
\Typecho\Db::set(\$db);
";
$code = implode('', $lines);
$configWritten = false;
if (!$return) {
@ -262,7 +437,8 @@ Typecho_Db::set(\$db);
/**
* remove config file if written
*/
function install_remove_config_file() {
function install_remove_config_file()
{
global $configWritten;
if ($configWritten) {
@ -276,7 +452,8 @@ function install_remove_config_file() {
* @param string $type
* @return bool
*/
function install_check(string $type): bool {
function install_check(string $type): bool
{
switch ($type) {
case 'config':
return file_exists(__TYPECHO_ROOT_DIR__ . '/config.inc.php');
@ -296,7 +473,9 @@ function install_check(string $type): bool {
if ($type == 'db_data' && empty($values)) {
return false;
}
} catch (Typecho_Db_Exception $e) {
} catch (\Typecho\Db\Adapter\ConnectionException $e) {
return true;
} catch (\Typecho\Db\Adapter\SQLException $e) {
return false;
}
@ -312,7 +491,8 @@ function install_check(string $type): bool {
* @param mixed $error
* @param mixed $config
*/
function install_raise_error($error, $config = null) {
function install_raise_error($error, $config = null)
{
if (install_is_cli()) {
if (is_array($error)) {
foreach ($error as $key => $value) {
@ -324,7 +504,7 @@ function install_raise_error($error, $config = null) {
exit(1);
} else {
Typecho_Response::getInstance()->throwJson([
install_throw_json([
'success' => 0,
'message' => is_string($error) ? nl2br($error) : $error,
'config' => $config
@ -336,7 +516,8 @@ function install_raise_error($error, $config = null) {
* @param $step
* @param array|null $config
*/
function install_success($step, ?array $config = null) {
function install_success($step, ?array $config = null)
{
if (install_is_cli()) {
if ($step > 0) {
$method = 'install_step_' . $step . '_perform';
@ -352,7 +533,7 @@ function install_success($step, ?array $config = null) {
exit(0);
} else {
Typecho_Response::getInstance()->throwJson([
install_throw_json([
'success' => 1,
'message' => $step,
'config' => $config
@ -361,13 +542,32 @@ function install_success($step, ?array $config = null) {
}
/**
* add common js support
*
* @throws Typecho_Exception
* @param $data
*/
function install_js_support() {
$options = Typecho_Widget::widget('Widget_Options');
function install_throw_json($data)
{
\Typecho\Response::getInstance()->setContentType('application/json')
->addResponder(function () use ($data) {
echo json_encode($data);
})
->respond();
}
/**
* @param string $url
*/
function install_redirect(string $url)
{
\Typecho\Response::getInstance()->setStatus(302)
->setHeader('Location', $url)
->respond();
}
/**
* add common js support
*/
function install_js_support()
{
?>
<div id="success" class="row typecho-page-main hidden">
<div class="col-mb-12 col-tb-8 col-tb-offset-2">
@ -471,20 +671,37 @@ function install_js_support() {
});
});
</script>
<?php
<?php
}
function install_step_1() {
$langs = Widget_Options_General::getLangs();
/**
* @param string[] $extensions
* @return string|null
*/
function install_check_extension(array $extensions): ?string
{
foreach ($extensions as $extension) {
if (extension_loaded($extension)) {
return null;
}
}
return _n('缺少PHP扩展', '请在服务器上安装以下PHP扩展中的至少一个', count($extensions))
. ': ' . implode(', ', $extensions);
}
function install_step_1()
{
$langs = \Widget\Options\General::getLangs();
$lang = install_get_lang();
?>
?>
<div class="row typecho-page-main">
<div class="col-mb-12 col-tb-8 col-tb-offset-2">
<div class="typecho-page-title">
<h2><?php _e('欢迎使用 Typecho'); ?></h2>
</div>
<div id="typecho-welcome">
<form autocomplete="off" method="get" action="install.php">
<form autocomplete="off" method="post" action="install.php">
<h3><?php _e('安装说明'); ?></h3>
<p class="warning">
<strong><?php _e('本安装程序将自动检测服务器环境是否符合最低配置需求. 如果不符合, 将在上方出现提示信息, 请按照提示信息检查您的主机配置. 如果服务器环境符合要求, 将在下方出现 "开始下一步" 的按钮, 点击此按钮即可一步完成安装.'); ?></strong>
@ -500,12 +717,14 @@ function install_step_1() {
<p class="submit">
<button class="btn primary" type="submit"><?php _e('我准备好了, 开始下一步 &raquo;'); ?></button>
<input type="hidden" name="step" value="2">
<input type="hidden" name="step" value="1">
<?php if (count($langs) > 1): ?>
<?php if (count($langs) > 1) : ?>
<select style="float: right" onchange="location.href='?lang=' + this.value">
<?php foreach ($langs as $key => $val): ?>
<option value="<?php echo $key; ?>"<?php if ($lang == $key): ?> selected<?php endif; ?>><?php echo $val; ?></option>
<?php foreach ($langs as $key => $val) : ?>
<option value="<?php echo $key; ?>"<?php if ($lang == $key) :
?> selected<?php
endif; ?>><?php echo $val; ?></option>
<?php endforeach; ?>
</select>
<?php endif; ?>
@ -514,13 +733,62 @@ function install_step_1() {
</div>
</div>
</div>
<?php
<?php
install_js_support();
}
/**
* check dependencies before install
*/
function install_step_1_perform()
{
$errors = [];
$checks = [
'mbstring',
'json',
'Reflection',
['mysqli', 'sqlite3', 'pgsql', 'pdo_mysql', 'pdo_sqlite', 'pdo_pgsql']
];
foreach ($checks as $check) {
$error = install_check_extension(is_array($check) ? $check : [$check]);
if (!empty($error)) {
$errors[] = $error;
}
}
$uploadDir = '/usr/uploads';
$realUploadDir = \Typecho\Common::url($uploadDir, __TYPECHO_ROOT_DIR__);
$writeable = true;
if (is_dir($realUploadDir)) {
if (!is_writeable($realUploadDir)) {
if (!@chmod($realUploadDir, 0644)) {
$writeable = false;
}
}
} else {
if (!@mkdir($realUploadDir, 0644)) {
$writeable = false;
}
}
if (!$writeable) {
$errors[] = _t('上传目录无法写入, 请手动将安装目录下的 %s 目录的权限设置为可写然后继续升级', $uploadDir);
}
if (empty($errors)) {
install_success(2);
} else {
install_raise_error(implode("\n", $errors));
}
}
/**
* display step 2
*/
function install_step_2() {
function install_step_2()
{
global $installDb;
$drivers = install_get_db_drivers();
@ -528,11 +796,11 @@ function install_step_2() {
$type = install_get_db_type($adapter);
if (!empty($installDb)) {
$config = $installDb->getConfig(Typecho_Db::WRITE)->toArray();
$config = $installDb->getConfig(\Typecho\Db::WRITE)->toArray();
$config['prefix'] = $installDb->getPrefix();
$config['adapter'] = $adapter;
}
?>
?>
<div class="row typecho-page-main">
<div class="col-mb-12 col-tb-8 col-tb-offset-2">
<div class="typecho-page-title">
@ -543,8 +811,10 @@ function install_step_2() {
<li>
<label for="dbAdapter" class="typecho-label"><?php _e('数据库适配器'); ?></label>
<select name="dbAdapter" id="dbAdapter" onchange="location.href='?step=2&driver=' + this.value">
<?php foreach ($drivers as $driver => $name): ?>
<option value="<?php echo $driver; ?>"<?php if($driver == $adapter): ?> selected="selected"<?php endif; ?>><?php echo $name; ?></option>
<?php foreach ($drivers as $driver => $name) : ?>
<option value="<?php echo $driver; ?>"<?php if ($driver == $adapter) :
?> selected="selected"<?php
endif; ?>><?php echo $name; ?></option>
<?php endforeach; ?>
</select>
<p class="description"><?php _e('请根据您的数据库类型选择合适的适配器'); ?></p>
@ -619,7 +889,7 @@ function install_step_2() {
$('#dbNext').val('none');
});
<?php if (!empty($config)): ?>
<?php if (!empty($config)) : ?>
function fillInput(config) {
for (let k in config) {
let value = config[k],
@ -632,20 +902,21 @@ function install_step_2() {
}
}
fillInput(<?php echo Json::encode($config); ?>);
fillInput(<?php echo json_encode($config); ?>);
<?php endif; ?>
</script>
<?php
<?php
install_js_support();
}
/**
* perform install step 2
*/
function install_step_2_perform() {
function install_step_2_perform()
{
global $installDb;
$request = Typecho_Request::getInstance();
$request = \Typecho\Request::getInstance();
$drivers = install_get_db_drivers();
$configMap = [
@ -703,7 +974,7 @@ function install_step_2_perform() {
]);
}
$error = (new Typecho_Validate())
$error = (new \Typecho\Validate())
->addRule('dbPrefix', 'required', _t('确认您的配置'))
->addRule('dbPrefix', 'minLength', _t('确认您的配置'), 1)
->addRule('dbPrefix', 'maxLength', _t('确认您的配置'), 16)
@ -722,12 +993,12 @@ function install_step_2_perform() {
$dbConfig = [];
foreach ($configMap[$type] as $key => $value) {
$config[$key] = $config[$key] === null ? (install_is_cli() ? $value : null) : $config[$key];
$config[$key] = !isset($config[$key]) ? (install_is_cli() ? $value : null) : $config[$key];
}
switch ($type) {
case 'Mysql':
$error = (new Typecho_Validate())
$error = (new \Typecho\Validate())
->addRule('dbHost', 'required', _t('确认您的配置'))
->addRule('dbPort', 'required', _t('确认您的配置'))
->addRule('dbPort', 'isInteger', _t('确认您的配置'))
@ -740,7 +1011,7 @@ function install_step_2_perform() {
->run($config);
break;
case 'Pgsql':
$error = (new Typecho_Validate())
$error = (new \Typecho\Validate())
->addRule('dbHost', 'required', _t('确认您的配置'))
->addRule('dbPort', 'required', _t('确认您的配置'))
->addRule('dbPort', 'isInteger', _t('确认您的配置'))
@ -751,7 +1022,7 @@ function install_step_2_perform() {
->run($config);
break;
case 'SQLite':
$error = (new Typecho_Validate())
$error = (new \Typecho\Validate())
->addRule('dbFile', 'required', _t('确认您的配置'))
->run($config);
break;
@ -775,12 +1046,12 @@ function install_step_2_perform() {
} elseif (empty($installDb)) {
// detect db config
try {
$installDb = new Typecho_Db($config['dbAdapter'], $config['dbPrefix']);
$installDb->addServer($dbConfig, Typecho_Db::READ | Typecho_Db::WRITE);
$installDb = new \Typecho\Db($config['dbAdapter'], $config['dbPrefix']);
$installDb->addServer($dbConfig, \Typecho\Db::READ | \Typecho\Db::WRITE);
$installDb->query('SELECT 1=1');
} catch (Typecho_Db_Adapter_Exception $e) {
} catch (\Typecho\Db\Adapter_Exception $e) {
install_raise_error(_t('对不起, 无法连接数据库, 请先检查数据库配置再继续进行安装'));
} catch (Typecho_Db_Exception $e) {
} catch (\Typecho\Db\Exception $e) {
install_raise_error(_t('安装程序捕捉到以下错误: " %s ". 程序被终止, 请检查您的配置信息.', $e->getMessage()));
}
@ -789,15 +1060,16 @@ function install_step_2_perform() {
if (!install_check('config')) {
install_raise_error(
_t('安装程序无法自动创建 <strong>config.inc.php</strong> 文件') . "\n" .
_t('您可以在网站根目录下手动创建 <strong>config.inc.php</strong> 文件, 并复制如下代码至其中')
, [
_t('您可以在网站根目录下手动创建 <strong>config.inc.php</strong> 文件, 并复制如下代码至其中'),
[
'code' => $code
]);
]
);
}
}
// delete exists db
if($config['dbNext'] == 'delete') {
if ($config['dbNext'] == 'delete') {
$tables = [
$config['dbPrefix'] . 'comments',
$config['dbPrefix'] . 'contents',
@ -818,7 +1090,7 @@ function install_step_2_perform() {
$installDb->query("DROP TABLE {$table}");
}
}
} catch (Typecho_Db_Exception $e) {
} catch (\Typecho\Db\Exception $e) {
install_raise_error(_t('安装程序捕捉到以下错误: "%s". 程序被终止, 请检查您的配置信息.', $e->getMessage()));
}
}
@ -840,16 +1112,17 @@ function install_step_2_perform() {
foreach ($scripts as $script) {
$script = trim($script);
if ($script) {
$installDb->query($script, Typecho_Db::WRITE);
$installDb->query($script, \Typecho\Db::WRITE);
}
}
} catch (Typecho_Db_Exception $e) {
} catch (\Typecho\Db\Exception $e) {
$code = $e->getCode();
if(('Mysql' == $type && (1050 == $code || '42S01' == $code)) ||
if (
('Mysql' == $type && (1050 == $code || '42S01' == $code)) ||
('SQLite' == $type && ('HY000' == $code || 1 == $code)) ||
('Pgsql' == $type && '42P07' == $code)) {
('Pgsql' == $type && '42P07' == $code)
) {
if ($config['dbNext'] == 'keep') {
if (install_check('db_data')) {
install_success(0);
@ -877,9 +1150,10 @@ function install_step_2_perform() {
/**
* display step 3
*/
function install_step_3() {
$options = Typecho_Widget::widget('Widget_Options');
?>
function install_step_3()
{
$options = \Widget\Options::alloc();
?>
<div class="row typecho-page-main">
<div class="col-mb-12 col-tb-8 col-tb-offset-2">
<div class="typecho-page-title">
@ -923,19 +1197,20 @@ function install_step_3() {
</form>
</div>
</div>
<?php
<?php
install_js_support();
}
/**
* perform step 3
*/
function install_step_3_perform() {
function install_step_3_perform()
{
global $installDb;
$request = Typecho_Request::getInstance();
$defaultPassword = Typecho_Common::randString(8);
$options = Typecho_Widget::widget('Widget_Options');
$request = \Typecho\Request::getInstance();
$defaultPassword = \Typecho\Common::randString(8);
$options = \Widget\Options::alloc();
if (install_is_cli()) {
$config = [
@ -953,10 +1228,10 @@ function install_step_3_perform() {
]);
}
$error = (new Typecho_Validate())
$error = (new \Typecho\Validate())
->addRule('userUrl', 'required', _t('请填写站点地址'))
->addRule('userUrl', 'url', _t('请填写一个合法的URL地址'))
->addRule('userName', 'required', _t('必须填写用户名称'))
->addRule('userName', 'required', _t('必须填写用户名称'))
->addRule('userName', 'xssCheck', _t('请不要在用户名中使用特殊字符'))
->addRule('userName', 'maxLength', _t('用户名长度超过限制, 请不要超过 32 个字符'), 32)
->addRule('userMail', 'required', _t('必须填写电子邮箱'))
@ -981,16 +1256,16 @@ function install_step_3_perform() {
}
// write user
$hasher = new PasswordHash(8, true);
$hasher = new \Utils\PasswordHash(8, true);
$installDb->query(
$installDb->insert('table.users')->rows([
'name' => $config['userName'],
'password' => $hasher->HashPassword($config['userPassword']),
'password' => $hasher->hashPassword($config['userPassword']),
'mail' => $config['userMail'],
'url' => $options->siteUrl,
'screenName' => $config['userName'],
'group' => 'administrator',
'created' => Typecho_Date::time()
'created' => \Typecho\Date::time()
])
);
@ -1012,8 +1287,8 @@ function install_step_3_perform() {
$installDb->query(
$installDb->insert('table.contents')->rows([
'title' => _t('欢迎使用 Typecho'),
'slug' => 'start', 'created' => Typecho_Date::time(),
'modified' => Typecho_Date::time(),
'slug' => 'start', 'created' => \Typecho\Date::time(),
'modified' => \Typecho\Date::time(),
'text' => '<!--markdown-->' . _t('如果您看到这篇文章,表示您的 blog 已经安装成功.'),
'authorId' => 1,
'type' => 'post',
@ -1030,8 +1305,8 @@ function install_step_3_perform() {
$installDb->insert('table.contents')->rows([
'title' => _t('关于'),
'slug' => 'start-page',
'created' => Typecho_Date::time(),
'modified' => Typecho_Date::time(),
'created' => \Typecho\Date::time(),
'modified' => \Typecho\Date::time(),
'text' => '<!--markdown-->' . _t('本页面由 Typecho 创建, 这只是个测试页面.'),
'authorId' => 1,
'order' => 0,
@ -1048,7 +1323,7 @@ function install_step_3_perform() {
// write comment
$installDb->query(
$installDb->insert('table.comments')->rows([
'cid' => 1, 'created' => Typecho_Date::time(),
'cid' => 1, 'created' => \Typecho\Date::time(),
'author' => 'Typecho',
'ownerId' => 1,
'url' => 'http://typecho.org',
@ -1060,7 +1335,7 @@ function install_step_3_perform() {
'parent' => 0
])
);
} catch (Typecho_Db_Exception $e) {
} catch (\Typecho\Db\Exception $e) {
install_raise_error($e->getMessage());
}
@ -1070,12 +1345,12 @@ function install_step_3_perform() {
'password' => $config['userPassword'],
'referer' => $options->adminUrl
]);
$loginUrl = Typecho_Common::buildUrl($parts);
$loginUrl = \Typecho\Common::buildUrl($parts);
install_success(0, [
$config['userName'],
$config['userPassword'],
Typecho_Widget::widget('Widget_Security')->getTokenUrl($loginUrl, $request->getReferer()),
\Widget\Security::alloc()->getTokenUrl($loginUrl, $request->getReferer()),
$options->siteUrl
]);
}
@ -1083,9 +1358,9 @@ function install_step_3_perform() {
/**
* dispatch install action
*
* @throws Typecho_Exception
*/
function install_dispatch() {
function install_dispatch()
{
define('__TYPECHO_INSTALL__', true);
// disable root url on cli mode
@ -1094,8 +1369,8 @@ function install_dispatch() {
}
// init default options
$options = Typecho_Widget::widget('Widget_Options', install_get_default_options());
Typecho_Widget::widget('Widget_Init');
$options = \Widget\Options::alloc(install_get_default_options());
\Widget\Init::alloc();
// install finished yet
if (
@ -1105,17 +1380,16 @@ function install_dispatch() {
) {
// redirect to siteUrl if not cli
if (!install_is_cli()) {
Typecho_Response::getInstance()->redirect($options->siteUrl);
install_redirect($options->siteUrl);
}
exit(1);
}
if (install_is_cli()) {
install_step_2_perform();
install_step_1_perform();
} else {
$request = Typecho_Request::getInstance();
$response = Typecho_Response::getInstance();
$request = \Typecho\Request::getInstance();
$step = $request->get('step');
$action = 1;
@ -1125,14 +1399,14 @@ function install_dispatch() {
if (!install_check('db_structure')) {
$action = 2;
} else {
$response->redirect('install.php?step=3');
install_redirect('install.php?step=3');
}
break;
case $step == 3:
if (install_check('db_structure')) {
$action = 3;
} else {
$response->redirect('install.php?step=2');
install_redirect('install.php?step=2');
}
break;
default:
@ -1141,12 +1415,12 @@ function install_dispatch() {
$method = 'install_step_' . $action;
if ($request->isPost() && $action > 1) {
if ($request->isPost()) {
$method .= '_perform';
$method();
exit;
}
?>
?>
<!DOCTYPE HTML>
<html>
<head>
@ -1166,7 +1440,7 @@ function install_dispatch() {
</div>
</body>
</html>
<?php
<?php
}
}

View File

@ -4,10 +4,11 @@ $langs = [];
/**
* output lang
*
*
* @param string $str
*/
function output_lang($str) {
function output_lang(string $str)
{
global $langs;
$key = md5($str);
@ -19,19 +20,20 @@ function output_lang($str) {
/**
* get all files
*
*
* @param string $dir
* @param string $pattern
* @return array
*/
function all_files($dir, $pattern = '*') {
$result = array();
function all_files(string $dir, string $pattern = '*'): array
{
$result = [];
$items = glob($dir . '/' . $pattern, GLOB_BRACE);
foreach ($items as $item) {
if (is_file($item)) {
$result[] = $item;
}
}
}
$items = glob($dir . '/*', GLOB_ONLYDIR);
@ -46,11 +48,12 @@ function all_files($dir, $pattern = '*') {
/**
* get msgid
*
*
* @param string $value
* @return string
*/
function get_msgid($value) {
function get_msgid(string $value): string
{
if ($value[0] == '"') {
return $value;
} else {
@ -61,22 +64,22 @@ function get_msgid($value) {
/**
* get pot from file
*
*
* @param string $file
* @return string
*/
function get_pot($file) {
function get_pot(string $file)
{
$source = file_get_contents($file);
$matched = null;
$plural = [];
foreach (token_get_all($source) as $token) {
if (is_array($token)) {
list ($type, $value) = $token;
[$type, $value] = $token;
if ($type == T_STRING && in_array($value, ['_t', '_e', '_n'])) {
$matched = $value;
} else if ($type == T_CONSTANT_ENCAPSED_STRING && $matched) {
} elseif ($type == T_CONSTANT_ENCAPSED_STRING && $matched) {
$key = md5($value);
if ($matched == '_n') {
@ -85,7 +88,7 @@ function get_pot($file) {
output_lang('msgid ' . get_msgid($value) . "\nmsgstr \"\"\n\n");
$matched = null;
}
} else if ($type != T_WHITESPACE) {
} elseif ($type != T_WHITESPACE) {
$matched = null;
if (!empty($plural)) {
@ -102,16 +105,13 @@ function get_pot($file) {
$plural = [];
}
}
} else if ($token != ',' && $token != '(') {
} elseif ($token != ',' && $token != '(') {
$matched = null;
$plural = [];
}
}
}
require_once __DIR__ . '/../var/Typecho/Common.php';
echo <<<EOF
# Copyright (C) Typecho
# This file is distributed under the same license as the Typecho Project.

View File

@ -1,70 +1,72 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
namespace HelloWorld;
use Typecho\Plugin\PluginInterface;
use Typecho\Widget\Helper\Form;
use Typecho\Widget\Helper\Form\Element\Text;
use Widget\Options;
if (!defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
/**
* Hello World
*
* @package HelloWorld
*
* @package HelloWorld
* @author qining
* @version 1.0.0
* @link http://typecho.org
*/
class HelloWorld_Plugin implements Typecho_Plugin_Interface
class Plugin implements PluginInterface
{
/**
* 激活插件方法,如果激活失败,直接抛出异常
*
* @access public
* @return void
* @throws Typecho_Plugin_Exception
*/
public static function activate()
{
Typecho_Plugin::factory('admin/menu.php')->navBar = array('HelloWorld_Plugin', 'render');
\Typecho\Plugin::factory('admin/menu.php')->navBar = ['HelloWorld_Plugin', 'render'];
}
/**
* 禁用插件方法,如果禁用失败,直接抛出异常
*
* @static
* @access public
* @return void
* @throws Typecho_Plugin_Exception
*/
public static function deactivate(){}
public static function deactivate()
{
}
/**
* 获取插件配置面板
*
* @access public
* @param Typecho_Widget_Helper_Form $form 配置面板
* @return void
*
* @param Form $form 配置面板
*/
public static function config(Typecho_Widget_Helper_Form $form)
public static function config(Form $form)
{
/** 分类名称 */
$name = new Typecho_Widget_Helper_Form_Element_Text('word', NULL, 'Hello World', _t('说点什么'));
$name = new Text('word', null, 'Hello World', _t('说点什么'));
$form->addInput($name);
}
/**
* 个人用户的配置面板
*
* @access public
* @param Typecho_Widget_Helper_Form $form
* @return void
*
* @param Form $form
*/
public static function personalConfig(Typecho_Widget_Helper_Form $form){}
public static function personalConfig(Form $form)
{
}
/**
* 插件实现方法
*
*
* @access public
* @return void
*/
public static function render()
{
echo '<span class="message success">'
. htmlspecialchars(Typecho_Widget::widget('Widget_Options')->plugin('HelloWorld')->word)
. htmlspecialchars(Options::alloc()->plugin('HelloWorld')->word)
. '</span>';
}
}

View File

@ -1,16 +1,18 @@
<?php if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<?php $this->need('header.php'); ?>
<div class="col-mb-12 col-tb-8 col-tb-offset-2">
<div class="col-mb-12 col-tb-8 col-tb-offset-2">
<div class="error-page">
<h2 class="post-title">404 - <?php _e('页面没找到'); ?></h2>
<p><?php _e('你想查看的页面已被转移或删除了, 要不要搜索看看: '); ?></p>
<form method="post">
<p><input type="text" name="s" class="text" autofocus /></p>
<p><button type="submit" class="submit"><?php _e('搜索'); ?></button></p>
</form>
</div>
<div class="error-page">
<h2 class="post-title">404 - <?php _e('页面没找到'); ?></h2>
<p><?php _e('你想查看的页面已被转移或删除了, 要不要搜索看看: '); ?></p>
<form method="post">
<p><input type="text" name="s" class="text" autofocus/></p>
<p>
<button type="submit" class="submit"><?php _e('搜索'); ?></button>
</p>
</form>
</div>
</div><!-- end #content-->
<?php $this->need('footer.php'); ?>
</div><!-- end #content-->
<?php $this->need('footer.php'); ?>

View File

@ -1,36 +1,45 @@
<?php if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<?php $this->need('header.php'); ?>
<div class="col-mb-12 col-8" id="main" role="main">
<h3 class="archive-title"><?php $this->archiveTitle(array(
'category' => _t('分类 %s 下的文章'),
'search' => _t('包含关键字 %s 的文章'),
'tag' => _t('标签 %s 下的文章'),
'author' => _t('%s 发布的文章')
), '', ''); ?></h3>
<?php if ($this->have()): ?>
<?php while($this->next()): ?>
<div class="col-mb-12 col-8" id="main" role="main">
<h3 class="archive-title"><?php $this->archiveTitle([
'category' => _t('分类 %s 下的文章'),
'search' => _t('包含关键字 %s 的文章'),
'tag' => _t('标签 %s 下的文章'),
'author' => _t('%s 发布的文章')
], '', ''); ?></h3>
<?php if ($this->have()): ?>
<?php while ($this->next()): ?>
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
<h2 class="post-title" itemprop="name headline"><a itemprop="url" href="<?php $this->permalink() ?>"><?php $this->title() ?></a></h2>
<ul class="post-meta">
<li itemprop="author" itemscope itemtype="http://schema.org/Person"><?php _e('作者: '); ?><a itemprop="name" href="<?php $this->author->permalink(); ?>" rel="author"><?php $this->author(); ?></a></li>
<li><?php _e('时间: '); ?><time datetime="<?php $this->date('c'); ?>" itemprop="datePublished"><?php $this->date(); ?></time></li>
<li><?php _e('分类: '); ?><?php $this->category(','); ?></li>
<li itemprop="interactionCount"><a href="<?php $this->permalink() ?>#comments"><?php $this->commentsNum('评论', '1 条评论', '%d 条评论'); ?></a></li>
</ul>
<h2 class="post-title" itemprop="name headline"><a itemprop="url"
href="<?php $this->permalink() ?>"><?php $this->title() ?></a>
</h2>
<ul class="post-meta">
<li itemprop="author" itemscope itemtype="http://schema.org/Person"><?php _e('作者: '); ?><a
itemprop="name" href="<?php $this->author->permalink(); ?>"
rel="author"><?php $this->author(); ?></a></li>
<li><?php _e('时间: '); ?>
<time datetime="<?php $this->date('c'); ?>"
itemprop="datePublished"><?php $this->date(); ?></time>
</li>
<li><?php _e('分类: '); ?><?php $this->category(','); ?></li>
<li itemprop="interactionCount"><a
href="<?php $this->permalink() ?>#comments"><?php $this->commentsNum('评论', '1 条评论', '%d 条评论'); ?></a>
</li>
</ul>
<div class="post-content" itemprop="articleBody">
<?php $this->content('- 阅读剩余部分 -'); ?>
<?php $this->content('- 阅读剩余部分 -'); ?>
</div>
</article>
<?php endwhile; ?>
<?php else: ?>
<article class="post">
<h2 class="post-title"><?php _e('没有找到内容'); ?></h2>
</article>
<?php endif; ?>
<?php endwhile; ?>
<?php else: ?>
<article class="post">
<h2 class="post-title"><?php _e('没有找到内容'); ?></h2>
</article>
<?php endif; ?>
<?php $this->pageNav('&laquo; 前一页', '后一页 &raquo;'); ?>
</div><!-- end #main -->
<?php $this->pageNav('&laquo; 前一页', '后一页 &raquo;'); ?>
</div><!-- end #main -->
<?php $this->need('sidebar.php'); ?>
<?php $this->need('footer.php'); ?>
<?php $this->need('sidebar.php'); ?>
<?php $this->need('footer.php'); ?>

View File

@ -2,48 +2,57 @@
<div id="comments">
<?php $this->comments()->to($comments); ?>
<?php if ($comments->have()): ?>
<h3><?php $this->commentsNum(_t('暂无评论'), _t('仅有一条评论'), _t('已有 %d 条评论')); ?></h3>
<?php $comments->listComments(); ?>
<h3><?php $this->commentsNum(_t('暂无评论'), _t('仅有一条评论'), _t('已有 %d 条评论')); ?></h3>
<?php $comments->listComments(); ?>
<?php $comments->pageNav('&laquo; 前一页', '后一页 &raquo;'); ?>
<?php $comments->pageNav('&laquo; 前一页', '后一页 &raquo;'); ?>
<?php endif; ?>
<?php if($this->allow('comment')): ?>
<div id="<?php $this->respondId(); ?>" class="respond">
<div class="cancel-comment-reply">
<?php $comments->cancelReply(); ?>
<?php if ($this->allow('comment')): ?>
<div id="<?php $this->respondId(); ?>" class="respond">
<div class="cancel-comment-reply">
<?php $comments->cancelReply(); ?>
</div>
<h3 id="response"><?php _e('添加新评论'); ?></h3>
<form method="post" action="<?php $this->commentUrl() ?>" id="comment-form" role="form">
<?php if ($this->user->hasLogin()): ?>
<p><?php _e('登录身份: '); ?><a
href="<?php $this->options->profileUrl(); ?>"><?php $this->user->screenName(); ?></a>. <a
href="<?php $this->options->logoutUrl(); ?>" title="Logout"><?php _e('退出'); ?> &raquo;</a>
</p>
<?php else: ?>
<p>
<label for="author" class="required"><?php _e('称呼'); ?></label>
<input type="text" name="author" id="author" class="text"
value="<?php $this->remember('author'); ?>" required/>
</p>
<p>
<label
for="mail"<?php if ($this->options->commentsRequireMail): ?> class="required"<?php endif; ?>><?php _e('Email'); ?></label>
<input type="email" name="mail" id="mail" class="text"
value="<?php $this->remember('mail'); ?>"<?php if ($this->options->commentsRequireMail): ?> required<?php endif; ?> />
</p>
<p>
<label
for="url"<?php if ($this->options->commentsRequireURL): ?> class="required"<?php endif; ?>><?php _e('网站'); ?></label>
<input type="url" name="url" id="url" class="text" placeholder="<?php _e('http://'); ?>"
value="<?php $this->remember('url'); ?>"<?php if ($this->options->commentsRequireURL): ?> required<?php endif; ?> />
</p>
<?php endif; ?>
<p>
<label for="textarea" class="required"><?php _e('内容'); ?></label>
<textarea rows="8" cols="50" name="text" id="textarea" class="textarea"
required><?php $this->remember('text'); ?></textarea>
</p>
<p>
<button type="submit" class="submit"><?php _e('提交评论'); ?></button>
</p>
</form>
</div>
<h3 id="response"><?php _e('添加新评论'); ?></h3>
<form method="post" action="<?php $this->commentUrl() ?>" id="comment-form" role="form">
<?php if($this->user->hasLogin()): ?>
<p><?php _e('登录身份: '); ?><a href="<?php $this->options->profileUrl(); ?>"><?php $this->user->screenName(); ?></a>. <a href="<?php $this->options->logoutUrl(); ?>" title="Logout"><?php _e('退出'); ?> &raquo;</a></p>
<?php else: ?>
<p>
<label for="author" class="required"><?php _e('称呼'); ?></label>
<input type="text" name="author" id="author" class="text" value="<?php $this->remember('author'); ?>" required />
</p>
<p>
<label for="mail"<?php if ($this->options->commentsRequireMail): ?> class="required"<?php endif; ?>><?php _e('Email'); ?></label>
<input type="email" name="mail" id="mail" class="text" value="<?php $this->remember('mail'); ?>"<?php if ($this->options->commentsRequireMail): ?> required<?php endif; ?> />
</p>
<p>
<label for="url"<?php if ($this->options->commentsRequireURL): ?> class="required"<?php endif; ?>><?php _e('网站'); ?></label>
<input type="url" name="url" id="url" class="text" placeholder="<?php _e('http://'); ?>" value="<?php $this->remember('url'); ?>"<?php if ($this->options->commentsRequireURL): ?> required<?php endif; ?> />
</p>
<?php endif; ?>
<p>
<label for="textarea" class="required"><?php _e('内容'); ?></label>
<textarea rows="8" cols="50" name="text" id="textarea" class="textarea" required ><?php $this->remember('text'); ?></textarea>
</p>
<p>
<button type="submit" class="submit"><?php _e('提交评论'); ?></button>
</p>
</form>
</div>
<?php else: ?>
<h3><?php _e('评论已关闭'); ?></h3>
<h3><?php _e('评论已关闭'); ?></h3>
<?php endif; ?>
</div>

View File

@ -1,26 +1,44 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
function themeConfig($form) {
$logoUrl = new Typecho_Widget_Helper_Form_Element_Text('logoUrl', NULL, NULL, _t('站点 LOGO 地址'), _t('在这里填入一个图片 URL 地址, 以在网站标题前加上一个 LOGO'));
function themeConfig($form)
{
$logoUrl = new \Typecho\Widget\Helper\Form\Element\Text(
'logoUrl',
null,
null,
_t('站点 LOGO 地址'),
_t('在这里填入一个图片 URL 地址, 以在网站标题前加上一个 LOGO')
);
$form->addInput($logoUrl);
$sidebarBlock = new Typecho_Widget_Helper_Form_Element_Checkbox('sidebarBlock',
array('ShowRecentPosts' => _t('显示最新文章'),
'ShowRecentComments' => _t('显示最近回复'),
'ShowCategory' => _t('显示分类'),
'ShowArchive' => _t('显示归档'),
'ShowOther' => _t('显示其它杂项')),
array('ShowRecentPosts', 'ShowRecentComments', 'ShowCategory', 'ShowArchive', 'ShowOther'), _t('侧边栏显示'));
$sidebarBlock = new \Typecho\Widget\Helper\Form\Element\Checkbox(
'sidebarBlock',
[
'ShowRecentPosts' => _t('显示最新文章'),
'ShowRecentComments' => _t('显示最近回复'),
'ShowCategory' => _t('显示分类'),
'ShowArchive' => _t('显示归档'),
'ShowOther' => _t('显示其它杂项')
],
['ShowRecentPosts', 'ShowRecentComments', 'ShowCategory', 'ShowArchive', 'ShowOther'],
_t('侧边栏显示')
);
$form->addInput($sidebarBlock->multiMode());
}
/*
function themeFields($layout) {
$logoUrl = new Typecho_Widget_Helper_Form_Element_Text('logoUrl', NULL, NULL, _t('站点LOGO地址'), _t('在这里填入一个图片URL地址, 以在网站标题前加上一个LOGO'));
function themeFields($layout)
{
$logoUrl = new \Typecho\Widget\Helper\Form\Element\Text(
'logoUrl',
null,
null,
_t('站点LOGO地址'),
_t('在这里填入一个图片URL地址, 以在网站标题前加上一个LOGO')
);
$layout->addItem($logoUrl);
}
*/

View File

@ -3,60 +3,54 @@
<html>
<head>
<meta charset="<?php $this->options->charset(); ?>">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title><?php $this->archiveTitle(array(
'category' => _t('分类 %s 下的文章'),
'search' => _t('包含关键字 %s 的文章'),
'tag' => _t('标签 %s 下的文章'),
'author' => _t('%s 发布的文章')
), '', ' - '); ?><?php $this->options->title(); ?></title>
<title><?php $this->archiveTitle([
'category' => _t('分类 %s 下的文章'),
'search' => _t('包含关键字 %s 的文章'),
'tag' => _t('标签 %s 下的文章'),
'author' => _t('%s 发布的文章')
], '', ' - '); ?><?php $this->options->title(); ?></title>
<!-- 使用url函数转换相关路径 -->
<link rel="stylesheet" href="<?php $this->options->themeUrl('normalize.css'); ?>">
<link rel="stylesheet" href="<?php $this->options->themeUrl('grid.css'); ?>">
<link rel="stylesheet" href="<?php $this->options->themeUrl('style.css'); ?>">
<!--[if lt IE 9]>
<script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->
<!-- 通过自有函数输出HTML头部信息 -->
<?php $this->header(); ?>
</head>
<body>
<!--[if lt IE 8]>
<div class="browsehappy" role="dialog"><?php _e('当前网页 <strong>不支持</strong> 你正在使用的浏览器. 为了正常的访问, 请 <a href="http://browsehappy.com/">升级你的浏览器</a>'); ?>.</div>
<![endif]-->
<header id="header" class="clearfix">
<div class="container">
<div class="row">
<div class="site-name col-mb-12 col-9">
<?php if ($this->options->logoUrl): ?>
<a id="logo" href="<?php $this->options->siteUrl(); ?>">
<img src="<?php $this->options->logoUrl() ?>" alt="<?php $this->options->title() ?>" />
</a>
<?php else: ?>
<a id="logo" href="<?php $this->options->siteUrl(); ?>"><?php $this->options->title() ?></a>
<p class="description"><?php $this->options->description() ?></p>
<?php endif; ?>
<?php if ($this->options->logoUrl): ?>
<a id="logo" href="<?php $this->options->siteUrl(); ?>">
<img src="<?php $this->options->logoUrl() ?>" alt="<?php $this->options->title() ?>"/>
</a>
<?php else: ?>
<a id="logo" href="<?php $this->options->siteUrl(); ?>"><?php $this->options->title() ?></a>
<p class="description"><?php $this->options->description() ?></p>
<?php endif; ?>
</div>
<div class="site-search col-3 kit-hidden-tb">
<form id="search" method="post" action="<?php $this->options->siteUrl(); ?>" role="search">
<label for="s" class="sr-only"><?php _e('搜索关键字'); ?></label>
<input type="text" id="s" name="s" class="text" placeholder="<?php _e('输入关键字搜索'); ?>" />
<input type="text" id="s" name="s" class="text" placeholder="<?php _e('输入关键字搜索'); ?>"/>
<button type="submit" class="submit"><?php _e('搜索'); ?></button>
</form>
</div>
<div class="col-mb-12">
<nav id="nav-menu" class="clearfix" role="navigation">
<a<?php if($this->is('index')): ?> class="current"<?php endif; ?> href="<?php $this->options->siteUrl(); ?>"><?php _e('首页'); ?></a>
<?php $this->widget('Widget_Contents_Page_List')->to($pages); ?>
<?php while($pages->next()): ?>
<a<?php if($this->is('page', $pages->slug)): ?> class="current"<?php endif; ?> href="<?php $pages->permalink(); ?>" title="<?php $pages->title(); ?>"><?php $pages->title(); ?></a>
<a<?php if ($this->is('index')): ?> class="current"<?php endif; ?>
href="<?php $this->options->siteUrl(); ?>"><?php _e('首页'); ?></a>
<?php \Widget\Contents\Page\Rows::alloc()->to($pages); ?>
<?php while ($pages->next()): ?>
<a<?php if ($this->is('page', $pages->slug)): ?> class="current"<?php endif; ?>
href="<?php $pages->permalink(); ?>"
title="<?php $pages->title(); ?>"><?php $pages->title(); ?></a>
<?php endwhile; ?>
</nav>
</div>

View File

@ -1,32 +1,42 @@
<?php
/**
* Default theme for Typecho
*
* @package Typecho Replica Theme
*
* @package Typecho Replica Theme
* @author Typecho Team
* @version 1.2
* @link http://typecho.org
*/
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
$this->need('header.php');
?>
$this->need('header.php');
?>
<div class="col-mb-12 col-8" id="main" role="main">
<?php while($this->next()): ?>
<?php while ($this->next()): ?>
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
<h2 class="post-title" itemprop="name headline"><a itemprop="url" href="<?php $this->permalink() ?>"><?php $this->title() ?></a></h2>
<ul class="post-meta">
<li itemprop="author" itemscope itemtype="http://schema.org/Person"><?php _e('作者: '); ?><a itemprop="name" href="<?php $this->author->permalink(); ?>" rel="author"><?php $this->author(); ?></a></li>
<li><?php _e('时间: '); ?><time datetime="<?php $this->date('c'); ?>" itemprop="datePublished"><?php $this->date(); ?></time></li>
<li><?php _e('分类: '); ?><?php $this->category(','); ?></li>
<li itemprop="interactionCount"><a itemprop="discussionUrl" href="<?php $this->permalink() ?>#comments"><?php $this->commentsNum('评论', '1 条评论', '%d 条评论'); ?></a></li>
</ul>
<h2 class="post-title" itemprop="name headline">
<a itemprop="url"
href="<?php $this->permalink() ?>"><?php $this->title() ?></a>
</h2>
<ul class="post-meta">
<li itemprop="author" itemscope itemtype="http://schema.org/Person"><?php _e('作者: '); ?><a
itemprop="name" href="<?php $this->author->permalink(); ?>"
rel="author"><?php $this->author(); ?></a></li>
<li><?php _e('时间: '); ?>
<time datetime="<?php $this->date('c'); ?>" itemprop="datePublished"><?php $this->date(); ?></time>
</li>
<li><?php _e('分类: '); ?><?php $this->category(','); ?></li>
<li itemprop="interactionCount">
<a itemprop="discussionUrl"
href="<?php $this->permalink() ?>#comments"><?php $this->commentsNum('评论', '1 条评论', '%d 条评论'); ?></a>
</li>
</ul>
<div class="post-content" itemprop="articleBody">
<?php $this->content('- 阅读剩余部分 -'); ?>
<?php $this->content('- 阅读剩余部分 -'); ?>
</div>
</article>
<?php endwhile; ?>
<?php endwhile; ?>
<?php $this->pageNav('&laquo; 前一页', '后一页 &raquo;'); ?>
</div><!-- end #main-->

View File

@ -3,7 +3,10 @@
<div class="col-mb-12 col-8" id="main" role="main">
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
<h1 class="post-title" itemprop="name headline"><a itemprop="url" href="<?php $this->permalink() ?>"><?php $this->title() ?></a></h1>
<h1 class="post-title" itemprop="name headline">
<a itemprop="url"
href="<?php $this->permalink() ?>"><?php $this->title() ?></a>
</h1>
<div class="post-content" itemprop="articleBody">
<?php $this->content(); ?>
</div>

View File

@ -3,10 +3,19 @@
<div class="col-mb-12 col-8" id="main" role="main">
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
<h1 class="post-title" itemprop="name headline"><a itemprop="url" href="<?php $this->permalink() ?>"><?php $this->title() ?></a></h1>
<h1 class="post-title" itemprop="name headline">
<a itemprop="url"
href="<?php $this->permalink() ?>"><?php $this->title() ?></a>
</h1>
<ul class="post-meta">
<li itemprop="author" itemscope itemtype="http://schema.org/Person"><?php _e('作者: '); ?><a itemprop="name" href="<?php $this->author->permalink(); ?>" rel="author"><?php $this->author(); ?></a></li>
<li><?php _e('时间: '); ?><time datetime="<?php $this->date('c'); ?>" itemprop="datePublished"><?php $this->date(); ?></time></li>
<li itemprop="author" itemscope itemtype="http://schema.org/Person">
<?php _e('作者: '); ?><a itemprop="name"
href="<?php $this->author->permalink(); ?>"
rel="author"><?php $this->author(); ?></a>
</li>
<li><?php _e('时间: '); ?>
<time datetime="<?php $this->date('c'); ?>" itemprop="datePublished"><?php $this->date(); ?></time>
</li>
<li><?php _e('分类: '); ?><?php $this->category(','); ?></li>
</ul>
<div class="post-content" itemprop="articleBody">
@ -18,8 +27,8 @@
<?php $this->need('comments.php'); ?>
<ul class="post-near">
<li>上一篇: <?php $this->thePrev('%s','没有了'); ?></li>
<li>下一篇: <?php $this->theNext('%s','没有了'); ?></li>
<li>上一篇: <?php $this->thePrev('%s', '没有了'); ?></li>
<li>下一篇: <?php $this->theNext('%s', '没有了'); ?></li>
</ul>
</div><!-- end #main-->

View File

@ -1,59 +1,63 @@
<?php if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<div class="col-mb-12 col-offset-1 col-3 kit-hidden-tb" id="secondary" role="complementary">
<?php if (!empty($this->options->sidebarBlock) && in_array('ShowRecentPosts', $this->options->sidebarBlock)): ?>
<section class="widget">
<h3 class="widget-title"><?php _e('最新文章'); ?></h3>
<ul class="widget-list">
<?php $this->widget('Widget_Contents_Post_Recent')
->parse('<li><a href="{permalink}">{title}</a></li>'); ?>
</ul>
</section>
<section class="widget">
<h3 class="widget-title"><?php _e('最新文章'); ?></h3>
<ul class="widget-list">
<?php \Widget\Contents\Post\Recent::alloc()
->parse('<li><a href="{permalink}">{title}</a></li>'); ?>
</ul>
</section>
<?php endif; ?>
<?php if (!empty($this->options->sidebarBlock) && in_array('ShowRecentComments', $this->options->sidebarBlock)): ?>
<section class="widget">
<h3 class="widget-title"><?php _e('最近回复'); ?></h3>
<ul class="widget-list">
<?php $this->widget('Widget_Comments_Recent')->to($comments); ?>
<?php while($comments->next()): ?>
<li><a href="<?php $comments->permalink(); ?>"><?php $comments->author(false); ?></a>: <?php $comments->excerpt(35, '...'); ?></li>
<?php endwhile; ?>
</ul>
</section>
<section class="widget">
<h3 class="widget-title"><?php _e('最近回复'); ?></h3>
<ul class="widget-list">
<?php \Widget\Comments\Recent::alloc()->to($comments); ?>
<?php while ($comments->next()): ?>
<li>
<a href="<?php $comments->permalink(); ?>"><?php $comments->author(false); ?></a>: <?php $comments->excerpt(35, '...'); ?>
</li>
<?php endwhile; ?>
</ul>
</section>
<?php endif; ?>
<?php if (!empty($this->options->sidebarBlock) && in_array('ShowCategory', $this->options->sidebarBlock)): ?>
<section class="widget">
<h3 class="widget-title"><?php _e('分类'); ?></h3>
<?php $this->widget('Widget_Metas_Category_List')->listCategories('wrapClass=widget-list'); ?>
</section>
<section class="widget">
<h3 class="widget-title"><?php _e('分类'); ?></h3>
<?php \Widget\Metas\Category\Rows::alloc()->listCategories('wrapClass=widget-list'); ?>
</section>
<?php endif; ?>
<?php if (!empty($this->options->sidebarBlock) && in_array('ShowArchive', $this->options->sidebarBlock)): ?>
<section class="widget">
<h3 class="widget-title"><?php _e('归档'); ?></h3>
<ul class="widget-list">
<?php $this->widget('Widget_Contents_Post_Date', 'type=month&format=F Y')
->parse('<li><a href="{permalink}">{date}</a></li>'); ?>
</ul>
</section>
<section class="widget">
<h3 class="widget-title"><?php _e('归档'); ?></h3>
<ul class="widget-list">
<?php \Widget\Contents\Post\Date::alloc('type=month&format=F Y')
->parse('<li><a href="{permalink}">{date}</a></li>'); ?>
</ul>
</section>
<?php endif; ?>
<?php if (!empty($this->options->sidebarBlock) && in_array('ShowOther', $this->options->sidebarBlock)): ?>
<section class="widget">
<h3 class="widget-title"><?php _e('其它'); ?></h3>
<ul class="widget-list">
<?php if($this->user->hasLogin()): ?>
<li class="last"><a href="<?php $this->options->adminUrl(); ?>"><?php _e('进入后台'); ?> (<?php $this->user->screenName(); ?>)</a></li>
<li><a href="<?php $this->options->logoutUrl(); ?>"><?php _e('退出'); ?></a></li>
<?php else: ?>
<li class="last"><a href="<?php $this->options->adminUrl('login.php'); ?>"><?php _e('登录'); ?></a></li>
<?php endif; ?>
<li><a href="<?php $this->options->feedUrl(); ?>"><?php _e('文章 RSS'); ?></a></li>
<li><a href="<?php $this->options->commentsFeedUrl(); ?>"><?php _e('评论 RSS'); ?></a></li>
<li><a href="http://www.typecho.org">Typecho</a></li>
</ul>
</section>
<section class="widget">
<h3 class="widget-title"><?php _e('其它'); ?></h3>
<ul class="widget-list">
<?php if ($this->user->hasLogin()): ?>
<li class="last"><a href="<?php $this->options->adminUrl(); ?>"><?php _e('进入后台'); ?>
(<?php $this->user->screenName(); ?>)</a></li>
<li><a href="<?php $this->options->logoutUrl(); ?>"><?php _e('退出'); ?></a></li>
<?php else: ?>
<li class="last"><a href="<?php $this->options->adminUrl('login.php'); ?>"><?php _e('登录'); ?></a>
</li>
<?php endif; ?>
<li><a href="<?php $this->options->feedUrl(); ?>"><?php _e('文章 RSS'); ?></a></li>
<li><a href="<?php $this->options->commentsFeedUrl(); ?>"><?php _e('评论 RSS'); ?></a></li>
<li><a href="http://www.typecho.org">Typecho</a></li>
</ul>
</section>
<?php endif; ?>
</div><!-- end #sidebar -->

View File

@ -98,18 +98,6 @@ textarea {
border-bottom-color: transparent;
}
.browsehappy {
padding: 8px 0;
background: #FBE3E4;
color: #8A1F11;
text-align: center;
}
.browsehappy a {
color: #8A1F11;
text-decoration: underline;
font-weight: bold;
}
/* ------------------
* Header
* --------------- */

View File

@ -1,18 +1,13 @@
<?php
/*
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
Site: http://scripts.incutio.com/xmlrpc/
Manual: http://scripts.incutio.com/xmlrpc/manual.php
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
*/
namespace IXR;
/**
* IXR Base64编码
*
* @package IXR
*/
class IXR_Base64
class Base64
{
/**
* 编码数据
@ -26,7 +21,7 @@ class IXR_Base64
*
* @param string $data
*/
public function __construct($data)
public function __construct(string $data)
{
$this->data = $data;
}

View File

@ -1,11 +1,8 @@
<?php
/*
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
Site: http://scripts.incutio.com/xmlrpc/
Manual: http://scripts.incutio.com/xmlrpc/manual.php
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
*/
namespace IXR;
use Typecho\Http\Client as HttpClient;
/**
* IXR客户端
@ -13,71 +10,28 @@
*
* @package IXR
*/
class IXR_Client
class Client
{
/** 默认客户端 */
const DEFAULT_USERAGENT = 'The Incutio XML-RPC PHP Library(Reload By Typecho)';
/**
* 服务端地址
*
* @access private
* @var string
*/
private $server;
/**
* 端口名称
*
* @access private
* @var integer
*/
private $port;
/**
* 路径名称
*
* @access private
* @var string
*/
private $path;
private const DEFAULT_USERAGENT = 'Typecho XML-RPC PHP Library';
/**
* 地址
*
* @access private
* @var string
*/
private $url;
/**
* 客户端
*
* @access private
* @var string
*/
private $useragent;
/**
* 回执结构体
*
* @access private
* @var string
*/
private $response;
/**
* 消息体
*
* @access private
* @var string
* @var Message
*/
private $message = false;
private $message;
/**
* 调试开关
*
* @access private
* @var boolean
*/
private $debug = false;
@ -85,66 +39,35 @@ class IXR_Client
/**
* 请求前缀
*
* @access private
* @var string
* @var string|null
*/
private $prefix = NULL;
private $prefix;
// Storage place for an error message
private $error = false;
/**
* @var Error
*/
private $error;
/**
* 客户端构造函数
*
* @access public
* @param string $server 服务端地址
* @param string $path 路径名称
* @param integer $port 端口名称
* @param string $useragent 客户端
* @param string $url 服务端地址
* @param string|null $prefix
* @return void
*/
public function __construct($server, $path = false, $port = 80, $useragent = self::DEFAULT_USERAGENT, $prefix = NULL)
{
if (!$path) {
$this->url = $server;
// Assume we have been given a Url instead
$bits = parse_url($server);
$this->server = $bits['host'];
$this->port = isset($bits['port']) ? $bits['port'] : 80;
$this->path = isset($bits['path']) ? $bits['path'] : '/';
// Make absolutely sure we have a path
if (isset($bits['query'])) {
$this->path .= '?' . $bits['query'];
}
} else {
/** Typecho_Common */
require_once 'Typecho/Common.php';
$this->url = Typecho_Common::buildUrl(array(
'scheme' => 'http',
'host' => $server,
'path' => $path,
'port' => $port
));
$this->server = $server;
$this->path = $path;
$this->port = $port;
}
public function __construct(
string $url,
?string $prefix = null
) {
$this->url = $url;
$this->prefix = $prefix;
$this->useragent = $useragent;
}
/**
* 设置调试模式
*
* @access public
* @return void
* @deprecated
*/
public function __setDebug()
public function setDebug()
{
$this->debug = true;
}
@ -152,44 +75,48 @@ class IXR_Client
/**
* 执行请求
*
* @access public
* @return void
* @param string $method
* @param array $args
* @return bool
*/
public function __rpcCall()
private function rpcCall(string $method, array $args): bool
{
$args = func_get_args();
$method = array_shift($args);
$request = new IXR_Request($method, $args);
$request = new Request($method, $args);
$xml = $request->getXml();
$client = Typecho_Http_Client::get();
$client = HttpClient::get();
if (!$client) {
$this->error = new IXR_Error(-32300, 'transport error - could not open socket');
$this->error = new Error(-32300, 'transport error - could not open socket');
return false;
}
$client->setHeader('Content-Type', 'text/xml')
->setHeader('User-Agent', $this->useragent)
->setData($xml)
->send($this->url);
try {
$client->setHeader('Content-Type', 'text/xml')
->setHeader('User-Agent', self::DEFAULT_USERAGENT)
->setData($xml)
->send($this->url);
} catch (HttpClient\Exception $e) {
$this->error = new Error(-32700, $e->getMessage());
return false;
}
$contents = $client->getResponseBody();
if ($this->debug) {
echo '<pre>'.htmlspecialchars($contents)."\n</pre>\n\n";
echo '<pre>' . htmlspecialchars($contents) . "\n</pre>\n\n";
}
// Now parse what we've got back
$this->message = new IXR_Message($contents);
$this->message = new Message($contents);
if (!$this->message->parse()) {
// XML error
$this->error = new IXR_Error(-32700, 'parse error. not well formed');
$this->error = new Error(-32700, 'parse error. not well formed');
return false;
}
// Is the message a fault?
if ($this->message->messageType == 'fault') {
$this->error = new IXR_Error($this->message->faultCode, $this->message->faultString);
$this->error = new Error($this->message->faultCode, $this->message->faultString);
return false;
}
@ -203,42 +130,38 @@ class IXR_Client
* $rpc->metaWeblog->newPost();
* </code>
*
* @access public
* @param string $prefix 前缀
* @return IXR_Client
* @return Client
*/
public function __get($prefix)
public function __get(string $prefix): Client
{
return new IXR_Client($this->server, $this->path, $this->port, $this->useragent, $this->prefix . $prefix . '.');
return new self($this->url, $this->prefix . $prefix . '.');
}
/**
* 增加魔术特性
* by 70
*
* @access public
* @return mixed
* @throws Exception
*/
public function __call($method, $args)
{
array_unshift($args, $this->prefix . $method);
$return = call_user_func_array(array($this, '__rpcCall'), $args);
$return = $this->rpcCall($this->prefix . $method, $args);
if ($return) {
return $this->__getResponse();
return $this->getResponse();
} else {
require_once 'IXR/Exception.php';
throw new IXR_Exception($this->__getErrorMessage(), $this->__getErrorCode());
throw new Exception($this->getErrorMessage(), $this->getErrorCode());
}
}
/**
* 获得返回值
*
* @access public
* @return void
* @return mixed
*/
public function __getResponse()
public function getResponse()
{
// methodResponses can only have one param - return that
return $this->message->params[0];
@ -247,21 +170,19 @@ class IXR_Client
/**
* 是否为错误
*
* @access public
* @return void
* @return bool
*/
public function __isError()
public function isError(): bool
{
return (is_object($this->error));
return isset($this->error);
}
/**
* 获取错误代码
*
* @access public
* @return void
* @return int
*/
public function __getErrorCode()
private function getErrorCode(): int
{
return $this->error->code;
}
@ -269,10 +190,9 @@ class IXR_Client
/**
* 获取错误消息
*
* @access public
* @return void
* @return string
*/
public function __getErrorMessage()
private function getErrorMessage(): string
{
return $this->error->message;
}

View File

@ -1,33 +1,44 @@
<?php
/*
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
Site: http://scripts.incutio.com/xmlrpc/
Manual: http://scripts.incutio.com/xmlrpc/manual.php
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
*/
namespace IXR;
/**
* IXR日期
*
* @package IXR
*/
class IXR_Date {
var $year;
var $month;
var $day;
var $hour;
var $minute;
var $second;
function __construct($time) {
class Date
{
private $year;
private $month;
private $day;
private $hour;
private $minute;
private $second;
/**
* @param int|string $time
*/
public function __construct($time)
{
// $time can be a PHP timestamp or an ISO one
if (is_numeric($time)) {
$this->parseTimestamp($time);
$this->parseTimestamp(intval($time));
} else {
$this->parseIso($time);
}
}
function parseTimestamp($timestamp) {
/**
* @param int $timestamp
*/
private function parseTimestamp(int $timestamp)
{
$this->year = date('Y', $timestamp);
$this->month = date('m', $timestamp);
$this->day = date('d', $timestamp);
@ -35,7 +46,12 @@ class IXR_Date {
$this->minute = date('i', $timestamp);
$this->second = date('s', $timestamp);
}
function parseIso($iso) {
/**
* @param string $iso
*/
private function parseIso(string $iso)
{
$this->year = substr($iso, 0, 4);
$this->month = substr($iso, 4, 2);
$this->day = substr($iso, 6, 2);
@ -43,13 +59,28 @@ class IXR_Date {
$this->minute = substr($iso, 12, 2);
$this->second = substr($iso, 15, 2);
}
function getIso() {
return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second;
/**
* @return string
*/
public function getIso(): string
{
return $this->year . $this->month . $this->day . 'T' . $this->hour . ':' . $this->minute . ':' . $this->second;
}
function getXml() {
return '<dateTime.iso8601>'.$this->getIso().'</dateTime.iso8601>';
/**
* @return string
*/
public function getXml(): string
{
return '<dateTime.iso8601>' . $this->getIso() . '</dateTime.iso8601>';
}
function getTimestamp() {
/**
* @return false|int
*/
public function getTimestamp()
{
return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
}
}

View File

@ -1,18 +1,13 @@
<?php
/*
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
Site: http://scripts.incutio.com/xmlrpc/
Manual: http://scripts.incutio.com/xmlrpc/manual.php
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
*/
namespace IXR;
/**
* IXR错误
*
* @package IXR
*/
class IXR_Error
class Error
{
/**
* 错误代码
@ -26,19 +21,17 @@ class IXR_Error
* 错误消息
*
* @access public
* @var string
* @var string|null
*/
public $message;
/**
* 构造函数
*
* @access public
* @param integer $code 错误代码
* @param string $message 错误消息
* @return void
* @param string|null $message 错误消息
*/
public function __construct($code, $message)
public function __construct(int $code, ?string $message)
{
$this->code = $code;
$this->message = $message;
@ -47,12 +40,11 @@ class IXR_Error
/**
* 获取xml
*
* @access public
* @return string
*/
public function getXml()
public function getXml(): string
{
$xml = <<<EOD
return <<<EOD
<methodResponse>
<fault>
<value>
@ -71,6 +63,5 @@ class IXR_Error
</methodResponse>
EOD;
return $xml;
}
}

View File

@ -1,17 +1,12 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/*
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
Site: http://scripts.incutio.com/xmlrpc/
Manual: http://scripts.incutio.com/xmlrpc/manual.php
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
*/
namespace IXR;
/**
* IXR异常类
*
* @package IXR
*/
class IXR_Exception extends Exception
{}
class Exception extends \Exception
{
}

25
var/IXR/Hook.php Normal file
View File

@ -0,0 +1,25 @@
<?php
namespace IXR;
use ReflectionMethod;
/**
* hook rpc call
*/
interface Hook
{
/**
* @param string $methodName
* @param ReflectionMethod $reflectionMethod
* @param array $parameters
* @return mixed
*/
public function beforeRpcCall(string $methodName, ReflectionMethod $reflectionMethod, array $parameters);
/**
* @param string $methodName
* @param mixed $result
*/
public function afterRpcCall(string $methodName, &$result): void;
}

View File

@ -1,57 +1,79 @@
<?php
/*
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
Site: http://scripts.incutio.com/xmlrpc/
Manual: http://scripts.incutio.com/xmlrpc/manual.php
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
*/
namespace IXR;
/**
* IXR消息
*
* @package IXR
*/
class IXR_Message {
var $message;
var $messageType; // methodCall / methodResponse / fault
var $faultCode;
var $faultString;
var $methodName;
var $params;
class Message
{
/**
* @var string
*/
public $message;
/**
* @var string
*/
public $messageType; // methodCall / methodResponse / fault
public $faultCode;
public $faultString;
/**
* @var string
*/
public $methodName;
/**
* @var array
*/
public $params = [];
// Current variable stacks
var $_arraystructs = array(); // The stack used to keep track of the current array/struct
var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array
var $_currentStructName = array(); // A stack as well
var $_param;
var $_value;
var $_currentTag;
var $_currentTagContents;
// The XML parser
var $_parser;
function __construct ($message) {
private $arrayStructs = []; // The stack used to keep track of the current array/struct
private $arrayStructsTypes = []; // Stack keeping track of if things are structs or array
private $currentStructName = []; // A stack as well
private $currentTagContents;
/**
* @param string $message
*/
public function __construct(string $message)
{
$this->message = $message;
}
function parse() {
/**
* @return bool
*/
public function parse(): bool
{
// first remove the XML declaration
$this->message = preg_replace('/<\?xml(.*)?\?'.'>/', '', $this->message);
$this->message = preg_replace('/<\?xml(.*)?\?' . '>/', '', $this->message);
if (trim($this->message) == '') {
return false;
}
$this->_parser = xml_parser_create();
$parser = xml_parser_create();
// Set XML parser to take the case of tags in to account
xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false);
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
// Set XML parser callback functions
xml_set_object($this->_parser, $this);
xml_set_element_handler($this->_parser, 'tag_open', 'tag_close');
xml_set_character_data_handler($this->_parser, 'cdata');
if (!xml_parse($this->_parser, $this->message)) {
xml_set_object($parser, $this);
xml_set_element_handler($parser, [$this, 'tagOpen'], [$this, 'tagClose']);
xml_set_character_data_handler($parser, [$this, 'cdata']);
if (!xml_parse($parser, $this->message)) {
/* die(sprintf('XML error: %s at line %d',
xml_error_string(xml_get_error_code($this->_parser)),
xml_get_current_line_number($this->_parser))); */
xml_error_string(xml_get_error_code($this->parser)),
xml_get_current_line_number($this->parser))); */
return false;
}
xml_parser_free($this->_parser);
xml_parser_free($parser);
// Grab the error messages, if any
if ($this->messageType == 'fault') {
$this->faultCode = $this->params[0]['faultCode'];
@ -59,9 +81,15 @@ class IXR_Message {
}
return true;
}
function tag_open($parser, $tag, $attr) {
$this->currentTag = $tag;
switch($tag) {
/**
* @param $parser
* @param $tag
* @param $attr
*/
private function tagOpen($parser, string $tag, $attr)
{
switch ($tag) {
case 'methodCall':
case 'methodResponse':
case 'fault':
@ -69,94 +97,98 @@ class IXR_Message {
break;
/* Deal with stacks of arrays and structs */
case 'data': // data is to all intents and puposes more interesting than array
$this->_arraystructstypes[] = 'array';
$this->_arraystructs[] = array();
$this->arrayStructsTypes[] = 'array';
$this->arrayStructs[] = [];
break;
case 'struct':
$this->_arraystructstypes[] = 'struct';
$this->_arraystructs[] = array();
$this->arrayStructsTypes[] = 'struct';
$this->arrayStructs[] = [];
break;
}
}
function cdata($parser, $cdata) {
$this->_currentTagContents .= $cdata;
/**
* @param $parser
* @param string $cdata
*/
private function cdata($parser, string $cdata)
{
$this->currentTagContents .= $cdata;
}
function tag_close($parser, $tag) {
$valueFlag = false;
switch($tag) {
/**
* @param $parser
* @param string $tag
*/
private function tagClose($parser, string $tag)
{
switch ($tag) {
case 'int':
case 'i4':
$value = (int)trim($this->_currentTagContents);
$this->_currentTagContents = '';
$valueFlag = true;
$value = (int) trim($this->currentTagContents);
$this->currentTagContents = '';
break;
case 'double':
$value = (double)trim($this->_currentTagContents);
$this->_currentTagContents = '';
$valueFlag = true;
$value = (double) trim($this->currentTagContents);
$this->currentTagContents = '';
break;
case 'string':
$value = (string)trim($this->_currentTagContents);
$this->_currentTagContents = '';
$valueFlag = true;
$value = (string)trim($this->currentTagContents);
$this->currentTagContents = '';
break;
case 'dateTime.iso8601':
$value = new IXR_Date(trim($this->_currentTagContents));
$value = new Date(trim($this->currentTagContents));
// $value = $iso->getTimestamp();
$this->_currentTagContents = '';
$valueFlag = true;
$this->currentTagContents = '';
break;
case 'value':
// "If no type is indicated, the type is string."
if (trim($this->_currentTagContents) != '') {
$value = (string)$this->_currentTagContents;
$this->_currentTagContents = '';
$valueFlag = true;
if (trim($this->currentTagContents) != '') {
$value = (string) $this->currentTagContents;
$this->currentTagContents = '';
}
break;
case 'boolean':
$value = (boolean)trim($this->_currentTagContents);
$this->_currentTagContents = '';
$valueFlag = true;
$value = (bool) trim($this->currentTagContents);
$this->currentTagContents = '';
break;
case 'base64':
$value = base64_decode($this->_currentTagContents);
$this->_currentTagContents = '';
$valueFlag = true;
$value = base64_decode($this->currentTagContents);
$this->currentTagContents = '';
break;
/* Deal with stacks of arrays and structs */
case 'data':
case 'struct':
$value = array_pop($this->_arraystructs);
array_pop($this->_arraystructstypes);
$valueFlag = true;
$value = array_pop($this->arrayStructs);
array_pop($this->arrayStructsTypes);
break;
case 'member':
array_pop($this->_currentStructName);
array_pop($this->currentStructName);
break;
case 'name':
$this->_currentStructName[] = trim($this->_currentTagContents);
$this->_currentTagContents = '';
$this->currentStructName[] = trim($this->currentTagContents);
$this->currentTagContents = '';
break;
case 'methodName':
$this->methodName = trim($this->_currentTagContents);
$this->_currentTagContents = '';
$this->methodName = trim($this->currentTagContents);
$this->currentTagContents = '';
break;
}
if ($valueFlag) {
if (isset($value)) {
/*
if (!is_array($value) && !is_object($value)) {
$value = trim($value);
}
*/
if (count($this->_arraystructs) > 0) {
if (count($this->arrayStructs) > 0) {
// Add value to struct or array
if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') {
if ($this->arrayStructsTypes[count($this->arrayStructsTypes) - 1] == 'struct') {
// Add to struct
$this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value;
$this->arrayStructs[count($this->arrayStructs) - 1]
[$this->currentStructName[count($this->currentStructName) - 1]] = $value;
} else {
// Add to array
$this->_arraystructs[count($this->_arraystructs)-1][] = $value;
$this->arrayStructs[count($this->arrayStructs) - 1][] = $value;
}
} else {
// Just add as a paramater

120
var/IXR/Pingback.php Normal file
View File

@ -0,0 +1,120 @@
<?php
namespace IXR;
use Typecho\Common;
use Typecho\Http\Client as HttpClient;
use Typecho\Http\Client\Exception as HttpException;
/**
* fetch pingback
*/
class Pingback
{
/**
* @var string
*/
private $html;
/**
* @var string
*/
private $target;
/**
* @param string $url
* @param string $target
* @throws Exception
*/
public function __construct(string $url, string $target)
{
$client = HttpClient::get();
$this->target = $target;
if (!isset($client)) {
throw new Exception('No available http client', 50);
}
try {
$client->setTimeout(5)
->send($url);
} catch (HttpException $e) {
throw new Exception('Pingback http error', 50);
}
if ($client->getResponseStatus() != 200) {
throw new Exception('Pingback wrong http status', 50);
}
$response = $client->getResponseBody();
$encoding = 'UTF-8';
$contentType = $client->getResponseHeader('Content-Type');
if (!empty($contentType) && preg_match("/charset=([_a-z0-9-]+)/i", $contentType, $matches)) {
$encoding = strtoupper($matches[1]);
} elseif (preg_match("/<meta\s+charset=\"([_a-z0-9-]+)\"/i", $response, $matches)) {
$encoding = strtoupper($matches[1]);
}
$this->html = $encoding == 'UTF-8' ? $response : mb_convert_encoding($response, 'UTF-8', $encoding);
if (
!$client->getResponseHeader('X-Pingback') &&
!preg_match_all("/<link[^>]*rel=[\"']pingback[\"'][^>]+href=[\"']([^\"']*)[\"'][^>]*>/i", $this->html)
) {
throw new Exception("Source server doesn't support pingback", 50);
}
}
/**
* get title
*
* @return string
*/
public function getTitle(): string
{
if (preg_match("/\<title\>([^<]*?)\<\/title\\>/is", $this->html, $matchTitle)) {
return Common::subStr(Common::removeXSS(trim(strip_tags($matchTitle[1]))), 0, 150, '...');
}
return parse_url($this->target, PHP_URL_HOST);
}
/**
* get content
*
* @return string
* @throws Exception
*/
public function getContent(): string
{
/** 干掉html tag只留下<a>*/
$text = Common::stripTags($this->html, '<a href="">');
/** 此处将$target quote,留着后面用*/
$pregLink = preg_quote($this->target);
/** 找出含有target链接的最长的一行作为$finalText*/
$finalText = null;
$lines = explode("\n", $text);
foreach ($lines as $line) {
$line = trim($line);
if (null != $line) {
if (preg_match("|<a[^>]*href=[\"']{$pregLink}[\"'][^>]*>(.*?)</a>|", $line)) {
if (strlen($line) > strlen($finalText)) {
/** <a>也要干掉,*/
$finalText = Common::stripTags($line);
break;
}
}
}
}
if (!isset($finalText)) {
throw new Exception("Source page doesn't have target url", 50);
}
return '[...]' . Common::subStr($finalText, 0, 200, '') . '[...]';
}
}

View File

@ -1,43 +1,55 @@
<?php
/*
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
Site: http://scripts.incutio.com/xmlrpc/
Manual: http://scripts.incutio.com/xmlrpc/manual.php
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
*/
namespace IXR;
/**
* IXR请求体
*
* @package IXR
*/
class IXR_Request {
var $method;
var $args;
var $xml;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
class Request
{
/**
* @var string
*/
private $xml;
/**
* @param string $method
* @param array $args
*/
public function __construct(string $method, array $args)
{
$this->xml = <<<EOD
<?xml version="1.0"?>
<methodCall>
<methodName>{$this->method}</methodName>
<methodName>{$method}</methodName>
<params>
EOD;
foreach ($this->args as $arg) {
foreach ($args as $arg) {
$this->xml .= '<param><value>';
$v = new IXR_Value($arg);
$v = new Value($arg);
$this->xml .= $v->getXml();
$this->xml .= "</value></param>\n";
}
$this->xml .= '</params></methodCall>';
}
function getLength() {
/**
* @return int
*/
public function getLength(): int
{
return strlen($this->xml);
}
function getXml() {
/**
* @return string
*/
public function getXml(): string
{
return $this->xml;
}
}

View File

@ -1,137 +1,228 @@
<?php
/*
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
Site: http://scripts.incutio.com/xmlrpc/
Manual: http://scripts.incutio.com/xmlrpc/manual.php
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
*/
namespace IXR;
use Typecho\Widget\Exception as WidgetException;
/**
* IXR服务器
*
* @package IXR
*/
class IXR_Server
class Server
{
/**
* 输入参数
*
* @access private
* @var array
*/
private $data;
/**
* 回调函数
*
* @access private
* @var array
*/
private $callbacks = array();
/**
* 消息体
*
* @access private
* @var IXR_Message
*/
private $message;
private $callbacks;
/**
* 默认参数
*
* @access private
* @var array
*/
private $capabilities;
/**
* @var Hook
*/
private $hook;
/**
* 构造函数
*
* @access public
* @param mixed $callbacks 回调函数
* @param mixed $data 输入参数
* @return void
* @param array $callbacks 回调函数
*/
public function __construct($callbacks = false, $data = false)
public function __construct(array $callbacks = [])
{
$this->setCapabilities();
if ($callbacks) {
$this->callbacks = $callbacks;
}
$this->callbacks = $callbacks;
$this->setCallbacks();
$this->serve($data);
$this->serve();
}
/**
* 获取默认参数
*
* @access public
* @return array
*/
public function getCapabilities(): array
{
return $this->capabilities;
}
/**
* 列出所有方法
*
* @access public
* @return array
*/
public function listMethods(): array
{
// Returns a list of methods - uses array_reverse to ensure user defined
// methods are listed before server defined methods
return array_reverse(array_keys($this->callbacks));
}
/**
* 一次处理多个请求
*
* @param array $methodcalls
* @return array
*/
public function multiCall(array $methodcalls): array
{
// See http://www.xmlrpc.com/discuss/msgReader$1208
$return = [];
foreach ($methodcalls as $call) {
$method = $call['methodName'];
$params = $call['params'];
if ($method == 'system.multicall') {
$result = new Error(-32600, 'Recursive calls to system.multicall are forbidden');
} else {
$result = $this->call($method, $params);
}
if (is_a($result, 'Error')) {
$return[] = [
'faultCode' => $result->code,
'faultString' => $result->message
];
} else {
$return[] = [$result];
}
}
return $return;
}
/**
* @param string $methodName
* @return string|Error
*/
public function methodHelp(string $methodName)
{
if (!$this->hasMethod($methodName)) {
return new Error(-32601, 'server error. requested method ' . $methodName . ' does not exist.');
}
[$object, $method] = $this->callbacks[$methodName];
try {
$ref = new \ReflectionMethod($object, $method);
$doc = $ref->getDocComment();
return $doc ?: '';
} catch (\ReflectionException $e) {
return '';
}
}
/**
* @param Hook $hook
*/
public function setHook(Hook $hook)
{
$this->hook = $hook;
}
/**
* 呼叫内部方法
*
* @access private
* @param string $methodname 方法名
* @param mixed $args 参数
* @param string $methodName 方法名
* @param array $args 参数
* @return mixed
*/
private function call($methodname, $args)
private function call(string $methodName, array $args)
{
// hook
if (0 !== strpos($methodname, 'hook.') && $this->hasMethod('hook.beforeCall')) {
$this->call('hook.beforeCall', array($methodname));
if (!$this->hasMethod($methodName)) {
return new Error(-32601, 'server error. requested method ' . $methodName . ' does not exist.');
}
if (!$this->hasMethod($methodname)) {
return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.');
}
$method = $this->callbacks[$methodname];
$method = $this->callbacks[$methodName];
// Are we dealing with a function or a method?
if (is_string($method) && substr($method, 0, 5) == 'this:') {
// It's a class method - check it exists
$method = substr($method, 5);
if (!method_exists($this, $method)) {
return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.');
if (!is_callable($method)) {
return new Error(
-32601,
'server error. requested class method "' . $methodName . '" does not exist.'
);
}
[$object, $objectMethod] = $method;
try {
$ref = new \ReflectionMethod($object, $objectMethod);
$requiredArgs = $ref->getNumberOfRequiredParameters();
if (count($args) < $requiredArgs) {
return new Error(
-32602,
'server error. requested class method "' . $methodName . '" require ' . $requiredArgs . ' params.'
);
}
// Call the method
$result = $this->$method($args);
} else {
if (is_array($method)) {
list($object, $func) = $method;
if (!is_callable($method)) {
return new IXR_Error(-32601, 'server error. requested class method "'.$object . '.' . $func.'" does not exist.');
foreach ($ref->getParameters() as $key => $parameter) {
if ($parameter->hasType() && !settype($args[$key], $parameter->getType()->getName())) {
return new Error(
-32602,
'server error. requested class method "'
. $methodName . '" ' . $key . ' param has wrong type.'
);
}
$result = call_user_func_array(array($object, $func), $args);
} elseif (!function_exists($method)) {
// It's a function - does it exist?
return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.');
} else {
// Call the function
$result = $method($args);
}
if (isset($this->hook)) {
$result = $this->hook->beforeRpcCall($methodName, $ref, $args);
if (isset($result)) {
return $result;
}
}
$result = call_user_func_array($method, $args);
if (isset($this->hook)) {
$this->hook->afterRpcCall($methodName, $result);
}
return $result;
} catch (\ReflectionException $e) {
return new Error(
-32601,
'server error. requested class method "' . $methodName . '" does not exist.'
);
} catch (Exception $e) {
return new Error(
$e->getCode(),
$e->getMessage()
);
} catch (WidgetException $e) {
return new Error(
-32001,
$e->getMessage()
);
} catch (\Exception $e) {
return new Error(
-32001,
'server error. requested class method "' . $methodName . '" failed.'
);
}
// hook
if (0 !== strpos($methodname, 'hook.') && $this->hasMethod('hook.afterCall')) {
$this->call('hook.afterCall', array($methodname));
}
return $result;
}
/**
* 抛出错误
*
* @access private
* @param integer $error 错误代码
* @param string $message 错误消息
* @param integer|Error $error 错误代码
* @param string|null $message 错误消息
* @return void
*/
private function error($error, $message = false)
private function error($error, ?string $message = null)
{
// Accepts either an error object or an error code and message
if ($message && !is_object($error)) {
$error = new IXR_Error($error, $message);
if (!$error instanceof Error) {
$error = new Error($error, $message);
}
$this->output($error->getXml());
}
@ -140,16 +231,15 @@ class IXR_Server
*
* @access private
* @param string $xml 输出xml
* @return 输出xml
*/
private function output($xml)
private function output(string $xml)
{
$xml = '<?xml version="1.0"?>'."\n".$xml;
$xml = '<?xml version="1.0"?>' . "\n" . $xml;
$length = strlen($xml);
header('Connection: close');
header('Content-Length: '.$length);
header('Content-Length: ' . $length);
header('Content-Type: text/xml');
header('Date: '.date('r'));
header('Date: ' . date('r'));
echo $xml;
exit;
}
@ -161,7 +251,7 @@ class IXR_Server
* @param string $method 方法名
* @return mixed
*/
private function hasMethod($method)
private function hasMethod(string $method)
{
return in_array($method, array_keys($this->callbacks));
}
@ -175,20 +265,20 @@ class IXR_Server
private function setCapabilities()
{
// Initialises capabilities array
$this->capabilities = array(
'xmlrpc' => array(
'specUrl' => 'http://www.xmlrpc.com/spec',
$this->capabilities = [
'xmlrpc' => [
'specUrl' => 'http://www.xmlrpc.com/spec',
'specVersion' => 1
),
'faults_interop' => array(
'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
],
'faults_interop' => [
'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
'specVersion' => 20010516
),
'system.multicall' => array(
'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
],
'system.multicall' => [
'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
'specVersion' => 1
),
);
],
];
}
/**
@ -199,130 +289,50 @@ class IXR_Server
*/
private function setCallbacks()
{
$this->callbacks['system.getCapabilities'] = 'this:getCapabilities';
$this->callbacks['system.listMethods'] = 'this:listMethods';
$this->callbacks['system.multicall'] = 'this:multiCall';
$this->callbacks['system.getCapabilities'] = [$this, 'getCapabilities'];
$this->callbacks['system.listMethods'] = [$this, 'listMethods'];
$this->callbacks['system.multicall'] = [$this, 'multiCall'];
$this->callbacks['system.methodHelp'] = [$this, 'methodHelp'];
}
/**
* 服务入口
*
* @access private
* @param mixed $data 输入参数
* @return void
*/
private function serve($data = false)
private function serve()
{
if (!isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
$GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents("php://input");
}
if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
$GLOBALS['HTTP_RAW_POST_DATA'] = trim($GLOBALS['HTTP_RAW_POST_DATA']);
}
$message = new Message(file_get_contents('php://input') ?: '');
if (!$data) {
global $HTTP_RAW_POST_DATA;
if (!$HTTP_RAW_POST_DATA) {
die('XML-RPC server accepts POST requests only.');
}
$data = $HTTP_RAW_POST_DATA;
}
$this->message = new IXR_Message($data);
if (!$this->message->parse()) {
if (!$message->parse()) {
$this->error(-32700, 'parse error. not well formed');
}
if ($this->message->messageType != 'methodCall') {
} elseif ($message->messageType != 'methodCall') {
$this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall');
}
if (0 === strpos($this->message->methodName, 'hook.')) {
die('THIS METHOD MUST BE CALLED INSIDE.');
}
$result = $this->call($this->message->methodName, $this->message->params);
$result = $this->call($message->methodName, $message->params);
// Is the result an error?
if (is_a($result, 'IXR_Error')) {
if ($result instanceof Error) {
$this->error($result);
}
// Encode the result
$r = new IXR_Value($result);
$resultxml = $r->getXml();
$r = new Value($result);
$resultXml = $r->getXml();
// Create the XML
$xml = <<<EOD
<methodResponse>
<params>
<param>
<value>
$resultxml
$resultXml
</value>
</param>
</params>
</methodResponse>
EOD;
// hook
if ($this->hasMethod('hook.beforeOutput')) {
$this->call('hook.beforeOutput', array());
}
// Send it
$this->output($xml);
}
/**
* 获取默认参数
*
* @access public
* @param mixed $args 输入参数
* @return array
*/
public function getCapabilities($args)
{
return $this->capabilities;
}
/**
* 列出所有方法
*
* @access public
* @param mixed $args 输入参数
* @return mixed
*/
public function listMethods($args)
{
// Returns a list of methods - uses array_reverse to ensure user defined
// methods are listed before server defined methods
return array_reverse(array_keys($this->callbacks));
}
/**
* 一次处理多个请求
*
* @access public
* @param void $methodcalls
* @return array
*/
public function multiCall($methodcalls)
{
// See http://www.xmlrpc.com/discuss/msgReader$1208
$return = array();
foreach ($methodcalls as $call) {
$method = $call['methodName'];
$params = $call['params'];
if ($method == 'system.multicall') {
$result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden');
} else {
$result = $this->call($method, $params);
}
if (is_a($result, 'IXR_Error')) {
$return[] = array(
'faultCode' => $result->code,
'faultString' => $result->message
);
} else {
$return[] = array($result);
}
}
return $return;
}
}

View File

@ -1,21 +1,24 @@
<?php
/*
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
Site: http://scripts.incutio.com/xmlrpc/
Manual: http://scripts.incutio.com/xmlrpc/manual.php
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
*/
namespace IXR;
/**
* IXR值
*
* @package IXR
*/
class IXR_Value {
var $data;
var $type;
function __construct ($data, $type = false) {
class Value
{
private $data;
private $type;
/**
* @param mixed $data
* @param bool|string $type
*/
public function __construct($data, $type = false)
{
$this->data = $data;
if (!$type) {
$type = $this->calculateType();
@ -24,16 +27,55 @@ class IXR_Value {
if ($type == 'struct') {
/* Turn all the values in the array in to new IXR_Value objects */
foreach ($this->data as $key => $value) {
$this->data[$key] = new IXR_Value($value);
$this->data[$key] = new Value($value);
}
}
if ($type == 'array') {
for ($i = 0, $j = count($this->data); $i < $j; $i++) {
$this->data[$i] = new IXR_Value($this->data[$i]);
$this->data[$i] = new Value($this->data[$i]);
}
}
}
function calculateType() {
public function getXml(): string
{
/* Return XML for this value */
switch ($this->type) {
case 'boolean':
return '<boolean>' . (($this->data) ? '1' : '0') . '</boolean>';
case 'int':
return '<int>' . $this->data . '</int>';
case 'double':
return '<double>' . $this->data . '</double>';
case 'string':
return '<string>' . htmlspecialchars($this->data) . '</string>';
case 'array':
$return = '<array><data>' . "\n";
foreach ($this->data as $item) {
$return .= ' <value>' . $item->getXml() . "</value>\n";
}
$return .= '</data></array>';
return $return;
case 'struct':
$return = '<struct>' . "\n";
foreach ($this->data as $name => $value) {
$return .= " <member><name>$name</name><value>";
$return .= $value->getXml() . "</value></member>\n";
}
$return .= '</struct>';
return $return;
case 'date':
case 'base64':
return $this->data->getXml();
}
return false;
}
/**
* @return string
*/
private function calculateType(): string
{
if ($this->data === true || $this->data === false) {
return 'boolean';
}
@ -52,7 +94,6 @@ class IXR_Value {
}
// If it is a normal PHP object convert it in to a struct
if (is_object($this->data)) {
$this->data = get_object_vars($this->data);
return 'struct';
}
@ -66,46 +107,9 @@ class IXR_Value {
return 'array';
}
}
function getXml() {
/* Return XML for this value */
switch ($this->type) {
case 'boolean':
return '<boolean>'.(($this->data) ? '1' : '0').'</boolean>';
break;
case 'int':
return '<int>'.$this->data.'</int>';
break;
case 'double':
return '<double>'.$this->data.'</double>';
break;
case 'string':
return '<string>'.htmlspecialchars($this->data).'</string>';
break;
case 'array':
$return = '<array><data>'."\n";
foreach ($this->data as $item) {
$return .= ' <value>'.$item->getXml()."</value>\n";
}
$return .= '</data></array>';
return $return;
break;
case 'struct':
$return = '<struct>'."\n";
foreach ($this->data as $name => $value) {
$return .= " <member><name>$name</name><value>";
$return .= $value->getXml()."</value></member>\n";
}
$return .= '</struct>';
return $return;
break;
case 'date':
case 'base64':
return $this->data->getXml();
break;
}
return false;
}
function isStruct($array) {
private function isStruct($array): bool
{
/* Nasty function to check if an array is a struct or not */
$expected = 0;
foreach ($array as $key => $value) {

View File

@ -1,545 +0,0 @@
<?php
/**********************************
* Created on: 2007-2-2
* File Name : lib.json.php
* Copyright : 2005 Michal Migursk
* License : http://www.opensource.org/licenses/bsd-license.php
*********************************/
class Json
{
const SERVICES_JSON_SLICE = 1;
const SERVICES_JSON_IN_STR = 2;
const SERVICES_JSON_IN_ARR = 3;
const SERVICES_JSON_IN_OBJ = 4;
const SERVICES_JSON_IN_CMT = 5;
const SERVICES_JSON_LOOSE_TYPE = 16;
const SERVICES_JSON_SUPPRESS_ERRORS = 32;
const E_JSONTYPE = 'json decode error';
/**
* 对配对值编码
*
* @access public
* @param string $name 名称
* @param mixed $value
* @return string
*/
public static function _name_value($name, $value)
{
$encoded_value = self::_encode($value);
if (self::_is_error($encoded_value)) {
return $encoded_value;
}
return self::_encode(strval($name)) . ':' . $encoded_value;
}
/**
* 将对象转换为json串
*
* @access public
* @param mixed $var 需要转换的对象
* @return string
*/
public static function _encode($var)
{
switch (gettype($var)) {
case 'boolean':
return $var ? 'true' : 'false';
case 'NULL':
return 'null';
case 'integer':
return (int)$var;
case 'double':
case 'float':
return (float)$var;
case 'string':
$ascii = '';
$strlen_var = strlen($var);
for ($c = 0; $c < $strlen_var; ++ $c) {
$ord_var_c = ord($var[$c]);
switch (true) {
case $ord_var_c == 0x08:
$ascii .= '\b';
break;
case $ord_var_c == 0x09:
$ascii .= '\t';
break;
case $ord_var_c == 0x0A:
$ascii .= '\n';
break;
case $ord_var_c == 0x0C:
$ascii .= '\f';
break;
case $ord_var_c == 0x0D:
$ascii .= '\r';
break;
case $ord_var_c == 0x22:
case $ord_var_c == 0x2F:
case $ord_var_c == 0x5C:
$ascii .= '\\' . $var[$c];
break;
case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
$ascii .= $var[$c];
break;
case (($ord_var_c & 0xE0) == 0xC0):
$char = pack('C*', $ord_var_c, ord($var[$c + 1]));
$c += 1;
$utf16 = self::utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xF0) == 0xE0):
$char = pack('C*', $ord_var_c,
ord($var[$c + 1]),
ord($var[$c + 2]));
$c += 2;
$utf16 = self::utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xF8) == 0xF0):
$char = pack('C*', $ord_var_c,
ord($var[$c + 1]),
ord($var[$c + 2]),
ord($var[$c + 3]));
$c += 3;
$utf16 = self::utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xFC) == 0xF8):
$char = pack('C*', $ord_var_c,
ord($var[$c + 1]),
ord($var[$c + 2]),
ord($var[$c + 3]),
ord($var[$c + 4]));
$c += 4;
$utf16 = self::utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xFE) == 0xFC):
$char = pack('C*', $ord_var_c,
ord($var[$c + 1]),
ord($var[$c + 2]),
ord($var[$c + 3]),
ord($var[$c + 4]),
ord($var[$c + 5]));
$c += 5;
$utf16 = self::utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
}
}
return '"' . $ascii . '"';
case 'array':
if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
$properties = array_map(['Json', '_name_value'],
array_keys($var),
array_values($var));
foreach ($properties as $property) {
if (self::_is_error($property)) {
return $property;
}
}
return '{' . join(',', $properties) . '}';
}
// treat it like a regular array
$elements = array_map(['Json', '_encode'], $var);
foreach ($elements as $element) {
if (self::_is_error($element)) {
return $element;
}
}
return '[' . join(',', $elements) . ']';
case 'object':
$vars = get_object_vars($var);
$properties = array_map(['Json', '_name_value'],
array_keys($vars),
array_values($vars));
foreach ($properties as $property) {
if (self::_is_error($property)) {
return $property;
}
}
return '{' . join(',', $properties) . '}';
default:
return false;
}
}
/**
* 将utf8转换为utf16
*
* @access private
* @param string $utf8 utf8字符串
* @return string
*/
private static function utf82utf16($utf8)
{
if (function_exists('mb_convert_encoding')) {
return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
}
switch (strlen($utf8)) {
case 1:
return $utf8;
case 2:
return chr(0x07 & (ord($utf8[0]) >> 2))
. chr((0xC0 & (ord($utf8[0]) << 6))
| (0x3F & ord($utf8[1])));
case 3:
return chr((0xF0 & (ord($utf8[0]) << 4))
| (0x0F & (ord($utf8[1]) >> 2)))
. chr((0xC0 & (ord($utf8[1]) << 6))
| (0x7F & ord($utf8[2])));
}
return '';
}
/**
* 判断错误
*
* @access private
* @param mixed $data 错误对象
* @param string $code 错误代码
* @return boolean
*/
private static function _is_error($data, $code = null)
{
if (is_object($data) && (get_class($data) == 'services_json_error' ||
is_subclass_of($data, 'services_json_error'))) {
return true;
}
return false;
}
/**
* 对变量进行json编码
*
* @access public
* @param mixed $var 需要处理的对象
* @return string
*/
public static function encode($var)
{
if (function_exists('json_encode')) {
/** from php 5.1 */
return json_encode($var);
} else {
return self::_encode($var);
}
}
/**
* 对字符串进行json解码
*
* @access public
* @param string $var 需要解码的字符串
* @param boolean $assoc 是否强制解释为数组
* @return mixed
*/
public static function decode($var, $assoc = false)
{
if (function_exists('json_decode')) {
/** from php 5.1 */
return json_decode($var, $assoc);
} else {
$result = self::_decode($var);
}
if ($assoc && is_object($result)) {
return (array)$result;
} elseif (!$assoc && is_array($result)) {
return (object)$result;
}
return $result;
}
/**
* 解码json字符串
*
* @access public
* @param string $str 解码字符串
* @return mixed
*/
public static function _decode($str)
{
$str = self::_reduce_string($str);
switch (strtolower($str)) {
case 'true':
return true;
case 'false':
return false;
case 'null':
return null;
default:
$m = [];
if (is_numeric($str)) {
return ((float)$str == (integer)$str)
? (integer)$str
: (float)$str;
} elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
$delim = substr($str, 0, 1);
$chrs = substr($str, 1, - 1);
$utf8 = '';
$strlen_chrs = strlen($chrs);
for ($c = 0; $c < $strlen_chrs; ++ $c) {
$substr_chrs_c_2 = substr($chrs, $c, 2);
$ord_chrs_c = ord($chrs[$c]);
switch (true) {
case $substr_chrs_c_2 == '\b':
$utf8 .= chr(0x08);
++ $c;
break;
case $substr_chrs_c_2 == '\t':
$utf8 .= chr(0x09);
++ $c;
break;
case $substr_chrs_c_2 == '\n':
$utf8 .= chr(0x0A);
++ $c;
break;
case $substr_chrs_c_2 == '\f':
$utf8 .= chr(0x0C);
++ $c;
break;
case $substr_chrs_c_2 == '\r':
$utf8 .= chr(0x0D);
++ $c;
break;
case $substr_chrs_c_2 == '\\"':
case $substr_chrs_c_2 == '\\\'':
case $substr_chrs_c_2 == '\\\\':
case $substr_chrs_c_2 == '\\/':
if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
($delim == "'" && $substr_chrs_c_2 != '\\"')) {
$utf8 .= $chrs[++ $c];
}
break;
case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
$utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
. chr(hexdec(substr($chrs, ($c + 4), 2)));
$utf8 .= self::utf162utf8($utf16);
$c += 5;
break;
case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
$utf8 .= $chrs[$c];
break;
case ($ord_chrs_c & 0xE0) == 0xC0:
$utf8 .= substr($chrs, $c, 2);
++ $c;
break;
case ($ord_chrs_c & 0xF0) == 0xE0:
$utf8 .= substr($chrs, $c, 3);
$c += 2;
break;
case ($ord_chrs_c & 0xF8) == 0xF0:
$utf8 .= substr($chrs, $c, 4);
$c += 3;
break;
case ($ord_chrs_c & 0xFC) == 0xF8:
$utf8 .= substr($chrs, $c, 5);
$c += 4;
break;
case ($ord_chrs_c & 0xFE) == 0xFC:
$utf8 .= substr($chrs, $c, 6);
$c += 5;
break;
}
}
return $utf8;
} elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
if ($str [0] == '[') {
$stk = [self::SERVICES_JSON_IN_ARR];
$arr = [];
} else {
$stk = [self::SERVICES_JSON_IN_OBJ];
$obj = new stdClass();
}
array_push($stk, ['what' => self::SERVICES_JSON_SLICE,
'where' => 0,
'delim' => false]);
$chrs = substr($str, 1, - 1);
$chrs = self::_reduce_string($chrs);
if ($chrs == '') {
if (reset($stk) == self::SERVICES_JSON_IN_ARR) {
return $arr;
} else {
return $obj;
}
}
$strlen_chrs = strlen($chrs);
for ($c = 0; $c <= $strlen_chrs; ++ $c) {
$top = end($stk);
$substr_chrs_c_2 = substr($chrs, $c, 2);
if (($c == $strlen_chrs) || (($chrs [$c] == ',') && ($top['what'] == self::SERVICES_JSON_SLICE))) {
$slice = substr($chrs, $top['where'], ($c - $top['where']));
array_push($stk, ['what' => self::SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false]);
if (reset($stk) == self::SERVICES_JSON_IN_ARR) {
array_push($arr, self::_decode($slice));
} elseif (reset($stk) == self::SERVICES_JSON_IN_OBJ) {
$parts = [];
if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
$key = self::_decode($parts[1]);
$val = self::_decode($parts[2]);
$obj->$key = $val;
} elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
$key = $parts[1];
$val = self::_decode($parts[2]);
$obj->$key = $val;
}
}
} elseif ((($chrs [$c] == '"') || ($chrs[$c] == "'")) && ($top['what'] != self::SERVICES_JSON_IN_STR)) {
array_push($stk, ['what' => self::SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs[$c]]);
} elseif (($chrs [$c] == $top['delim']) &&
($top['what'] == self::SERVICES_JSON_IN_STR) &&
((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
array_pop($stk);
} elseif (($chrs [$c] == '[') &&
in_array($top['what'], [self::SERVICES_JSON_SLICE, self::SERVICES_JSON_IN_ARR, self::SERVICES_JSON_IN_OBJ])) {
array_push($stk, ['what' => self::SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false]);
} elseif (($chrs [$c] == ']') && ($top['what'] == self::SERVICES_JSON_IN_ARR)) {
array_pop($stk);
} elseif (($chrs [$c] == '{') &&
in_array($top['what'], [self::SERVICES_JSON_SLICE, self::SERVICES_JSON_IN_ARR, self::SERVICES_JSON_IN_OBJ])) {
array_push($stk, ['what' => self::SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false]);
} elseif (($chrs [$c] == '}') && ($top['what'] == self::SERVICES_JSON_IN_OBJ)) {
array_pop($stk);
} elseif (($substr_chrs_c_2 == '/*') &&
in_array($top['what'], [self::SERVICES_JSON_SLICE, self::SERVICES_JSON_IN_ARR, self::SERVICES_JSON_IN_OBJ])) {
array_push($stk, ['what' => self::SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false]);
$c ++;
} elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == self::SERVICES_JSON_IN_CMT)) {
array_pop($stk);
$c ++;
for ($i = $top['where']; $i <= $c; ++ $i)
$chrs = substr_replace($chrs, ' ', $i, 1);
}
}
if (reset($stk) == self::SERVICES_JSON_IN_ARR) {
return $arr;
} elseif (reset($stk) == self::SERVICES_JSON_IN_OBJ) {
return $obj;
}
}
}
}
/**
* 清除特殊格式
*
* @access private
* @param string $str 待处理字符串
* @return string
*/
private static function _reduce_string($str)
{
$str = preg_replace([
'#^\s*//(.+)$#m',
'#^\s*/\*(.+)\*/#Us',
'#/\*(.+)\*/\s*$#Us'
], '', $str);
return trim($str);
}
/**
* 将utf16转换为utf8
*
* @access private
* @param string $utf16 utf16字符串
* @return string
*/
private static function utf162utf8($utf16)
{
if (function_exists('mb_convert_encoding')) {
return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
}
$bytes = (ord($utf16[0]) << 8) | ord($utf16[1]);
switch (true) {
case ((0x7F & $bytes) == $bytes):
return chr(0x7F & $bytes);
case (0x07FF & $bytes) == $bytes:
return chr(0xC0 | (($bytes >> 6) & 0x1F))
. chr(0x80 | ($bytes & 0x3F));
case (0xFFFF & $bytes) == $bytes:
return chr(0xE0 | (($bytes >> 12) & 0x0F))
. chr(0x80 | (($bytes >> 6) & 0x3F))
. chr(0x80 | ($bytes & 0x3F));
}
return '';
}
}

View File

@ -1,65 +0,0 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* Markdown解析
*
* @package Markdown
* @copyright Copyright (c) 2014 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
*/
class Markdown
{
/**
* convert
*
* @param string $text
* @return string
*/
public static function convert($text)
{
static $parser;
if (empty($parser)) {
$parser = new HyperDown();
$parser->hook('afterParseCode', function ($html) {
return preg_replace("/<code class=\"([_a-z0-9-]+)\">/i", "<code class=\"lang-\\1\">", $html);
});
$parser->enableHtml(true);
}
return str_replace('<p><!--more--></p>', '<!--more-->', $parser->makeHtml($text));
}
/**
* transerCodeClass
*
* @param string $html
* @return string
*/
public static function transerCodeClass($html)
{
return preg_replace("/<code class=\"([_a-z0-9-]+)\">/i", "<code class=\"lang-\\1\">", $html);
}
/**
* @param $html
* @return mixed
*/
public static function transerComment($html)
{
return preg_replace_callback("/<!\-\-(.+?)\-\->/s", ['Markdown', 'transerCommentCallback'], $html);
}
/**
* @param $matches
* @return string
*/
public static function transerCommentCallback($matches)
{
return self::$parser->makeHolder($matches[0]);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,6 @@
<?php
/**
* 配置管理
*
* @category typecho
* @package Config
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id$
*/
namespace Typecho;
/**
* 配置管理类
@ -17,7 +10,7 @@
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
*/
class Typecho_Config implements Iterator
class Config implements \Iterator, \ArrayAccess
{
/**
* 当前配置
@ -25,13 +18,13 @@ class Typecho_Config implements Iterator
* @access private
* @var array
*/
private $_currentConfig = [];
private $currentConfig = [];
/**
* 实例化一个当前配置
*
* @access public
* @param mixed $config 配置列表
* @param array|string|null $config 配置列表
*/
public function __construct($config = [])
{
@ -44,13 +37,13 @@ class Typecho_Config implements Iterator
*
* @access public
*
* @param array|string $config 配置列表
* @param array|string|null $config 配置列表
*
* @return Typecho_Config
* @return Config
*/
public static function factory($config = []): Typecho_Config
public static function factory($config = []): Config
{
return new Typecho_Config($config);
return new self($config);
}
/**
@ -68,7 +61,7 @@ class Typecho_Config implements Iterator
if (empty($config)) {
return;
}
/** 初始化参数 */
if (is_string($config)) {
parse_str($config, $params);
@ -78,12 +71,20 @@ class Typecho_Config implements Iterator
/** 设置默认参数 */
foreach ($params as $name => $value) {
if ($replace || !array_key_exists($name, $this->_currentConfig)) {
$this->_currentConfig[$name] = $value;
if ($replace || !array_key_exists($name, $this->currentConfig)) {
$this->currentConfig[$name] = $value;
}
}
}
/**
* @return bool
*/
public function isEmpty(): bool
{
return empty($this->currentConfig);
}
/**
* 重设指针
*
@ -92,7 +93,7 @@ class Typecho_Config implements Iterator
*/
public function rewind()
{
reset($this->_currentConfig);
reset($this->currentConfig);
}
/**
@ -103,7 +104,7 @@ class Typecho_Config implements Iterator
*/
public function current()
{
return current($this->_currentConfig);
return current($this->currentConfig);
}
/**
@ -114,7 +115,7 @@ class Typecho_Config implements Iterator
*/
public function next()
{
next($this->_currentConfig);
next($this->currentConfig);
}
/**
@ -125,7 +126,7 @@ class Typecho_Config implements Iterator
*/
public function key()
{
return key($this->_currentConfig);
return key($this->currentConfig);
}
/**
@ -148,7 +149,7 @@ class Typecho_Config implements Iterator
*/
public function __get(string $name)
{
return $this->_currentConfig[$name] ?? null;
return $this->offsetGet($name);
}
/**
@ -161,7 +162,7 @@ class Typecho_Config implements Iterator
*/
public function __set(string $name, $value)
{
$this->_currentConfig[$name] = $value;
$this->offsetSet($name, $value);
}
/**
@ -174,7 +175,7 @@ class Typecho_Config implements Iterator
*/
public function __call(string $name, ?array $args)
{
echo $this->_currentConfig[$name];
echo $this->currentConfig[$name];
}
/**
@ -186,7 +187,7 @@ class Typecho_Config implements Iterator
*/
public function __isSet(string $name): bool
{
return isset($this->_currentConfig[$name]);
return $this->offsetExists($name);
}
/**
@ -197,7 +198,7 @@ class Typecho_Config implements Iterator
*/
public function __toString(): string
{
return serialize($this->_currentConfig);
return serialize($this->currentConfig);
}
/**
@ -205,6 +206,41 @@ class Typecho_Config implements Iterator
*/
public function toArray(): array
{
return $this->_currentConfig;
return $this->currentConfig;
}
/**
* @param mixed $offset
* @return bool
*/
public function offsetExists($offset): bool
{
return isset($this->currentConfig[$offset]);
}
/**
* @param mixed $offset
* @return mixed
*/
public function offsetGet($offset)
{
return $this->currentConfig[$offset] ?? null;
}
/**
* @param mixed $offset
* @param mixed $value
*/
public function offsetSet($offset, $value)
{
$this->currentConfig[$offset] = $value;
}
/**
* @param mixed $offset
*/
public function offsetUnset($offset)
{
unset($this->currentConfig[$offset]);
}
}

View File

@ -1,13 +1,6 @@
<?php
/**
* cookie支持
*
* @category typecho
* @package Cookie
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id$
*/
namespace Typecho;
/**
* cookie支持
@ -16,7 +9,7 @@
* @category typecho
* @package Cookie
*/
class Typecho_Cookie
class Cookie
{
/**
* 前缀
@ -24,7 +17,7 @@ class Typecho_Cookie
* @var string
* @access private
*/
private static $_prefix = '';
private static $prefix = '';
/**
* 路径
@ -32,7 +25,7 @@ class Typecho_Cookie
* @var string
* @access private
*/
private static $_path = '/';
private static $path = '/';
/**
* 获取前缀
@ -42,7 +35,7 @@ class Typecho_Cookie
*/
public static function getPrefix(): string
{
return self::$_prefix;
return self::$prefix;
}
/**
@ -55,11 +48,11 @@ class Typecho_Cookie
*/
public static function setPrefix(string $url)
{
self::$_prefix = md5($url);
self::$prefix = md5($url);
$parsed = parse_url($url);
/** 在路径后面强制加上斜杠 */
self::$_path = empty($parsed['path']) ? '/' : Typecho_Common::url(null, $parsed['path']);
self::$path = empty($parsed['path']) ? '/' : Common::url(null, $parsed['path']);
}
/**
@ -70,22 +63,19 @@ class Typecho_Cookie
*/
public static function getPath(): string
{
return self::$_path;
return self::$path;
}
/**
* 获取指定的COOKIE值
*
* @access public
*
* @param string $key 指定的参数
* @param string|null $default 默认的参数
*
* @return mixed
*/
public static function get(string $key, ?string $default = null)
{
$key = self::$_prefix . $key;
$key = self::$prefix . $key;
$value = $_COOKIE[$key] ?? $default;
return is_array($value) ? $default : $value;
}
@ -93,38 +83,30 @@ class Typecho_Cookie
/**
* 设置指定的COOKIE值
*
* @access public
*
* @param string $key 指定的参数
* @param mixed $value 设置的值
* @param integer $expire 过期时间,默认为0,表示随会话时间结束
*
* @return void
*/
public static function set(string $key, $value, int $expire = 0)
{
$key = self::$_prefix . $key;
setrawcookie($key, rawurlencode($value), $expire, self::$_path);
$key = self::$prefix . $key;
$_COOKIE[$key] = $value;
Response::getInstance()->setCookie($key, $value, $expire, self::$path);
}
/**
* 删除指定的COOKIE值
*
* @access public
*
* @param string $key 指定的参数
*
* @return void
*/
public static function delete(string $key)
{
$key = self::$_prefix . $key;
$key = self::$prefix . $key;
if (!isset($_COOKIE[$key])) {
return;
}
setcookie($key, '', time() - 2592000, self::$_path);
Response::getInstance()->setCookie($key, '', -1, self::$path);
unset($_COOKIE[$key]);
}
}

View File

@ -1,5 +1,7 @@
<?php
namespace Typecho;
/**
* 日期处理
*
@ -7,7 +9,7 @@
* @category typecho
* @package Date
*/
class Typecho_Date
class Date
{
/**
* 期望时区偏移
@ -41,26 +43,40 @@ class Typecho_Date
*/
public $timeStamp = 0;
/**
* @var string
*/
public $year;
/**
* @var string
*/
public $month;
/**
* @var string
*/
public $day;
/**
* 初始化参数
*
* @access public
*
* @param integer|null $time 时间戳
*/
public function __construct(?int $time = NULL)
public function __construct(?int $time = null)
{
$this->timeStamp = (NULL === $time ? self::time() : $time) + (self::$timezoneOffset - self::$serverTimezoneOffset);
$this->timeStamp = (null === $time ? self::time() : $time)
+ (self::$timezoneOffset - self::$serverTimezoneOffset);
$this->year = date('Y', $this->timeStamp);
$this->month = date('m', $this->timeStamp);
$this->day = date('d', $this->timeStamp);
}
/**
* 设置当前期望的时区偏移
*
* @access public
*
* @param integer $offset
*
* @return void
*/
public static function setTimezoneOffset(int $offset)
{
@ -71,10 +87,7 @@ class Typecho_Date
/**
* 获取格式化时间
*
* @access public
*
* @param string $format 时间格式
*
* @return string
*/
public function format(string $format): string
@ -85,35 +98,11 @@ class Typecho_Date
/**
* 获取国际化偏移时间
*
* @access public
* @return string
*/
public function word(): string
{
return Typecho_I18n::dateWord($this->timeStamp, self::time() + (self::$timezoneOffset - self::$serverTimezoneOffset));
}
/**
* 获取单项数据
*
* @access public
*
* @param string $name 名称
*
* @return integer
*/
public function __get(string $name)
{
switch ($name) {
case 'year':
return date('Y', $this->timeStamp);
case 'month':
return date('m', $this->timeStamp);
case 'day':
return date('d', $this->timeStamp);
default:
return 0;
}
return I18n::dateWord($this->timeStamp, self::time() + (self::$timezoneOffset - self::$serverTimezoneOffset));
}
/**

View File

@ -1,11 +1,10 @@
<?php
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id: Db.php 107 2008-04-11 07:14:43Z magike.net $
*/
namespace Typecho;
use Typecho\Db\Adapter;
use Typecho\Db\Query;
use Typecho\Db\Exception as DbException;
/**
* 包含获取数据支持方法的类.
@ -14,56 +13,56 @@
*
* @package Db
*/
class Typecho_Db
class Db
{
/** 读取数据库 */
const READ = 1;
public const READ = 1;
/** 写入数据库 */
const WRITE = 2;
public const WRITE = 2;
/** 升序方式 */
const SORT_ASC = 'ASC';
public const SORT_ASC = 'ASC';
/** 降序方式 */
const SORT_DESC = 'DESC';
public const SORT_DESC = 'DESC';
/** 表内连接方式 */
const INNER_JOIN = 'INNER';
public const INNER_JOIN = 'INNER';
/** 表外连接方式 */
const OUTER_JOIN = 'OUTER';
public const OUTER_JOIN = 'OUTER';
/** 表左连接方式 */
const LEFT_JOIN = 'LEFT';
public const LEFT_JOIN = 'LEFT';
/** 表右连接方式 */
const RIGHT_JOIN = 'RIGHT';
public const RIGHT_JOIN = 'RIGHT';
/** 数据库查询操作 */
const SELECT = 'SELECT';
public const SELECT = 'SELECT';
/** 数据库更新操作 */
const UPDATE = 'UPDATE';
public const UPDATE = 'UPDATE';
/** 数据库插入操作 */
const INSERT = 'INSERT';
public const INSERT = 'INSERT';
/** 数据库删除操作 */
const DELETE = 'DELETE';
public const DELETE = 'DELETE';
/**
* 数据库适配器
* @var Typecho_Db_Adapter
* @var Adapter
*/
private $_adapter;
private $adapter;
/**
* 默认配置
*
* @var array
*/
private $_config;
private $config;
/**
* 已经连接
@ -71,7 +70,7 @@ class Typecho_Db
* @access private
* @var array
*/
private $_connectedPool;
private $connectedPool;
/**
* 前缀
@ -79,7 +78,7 @@ class Typecho_Db
* @access private
* @var string
*/
private $_prefix;
private $prefix;
/**
* 适配器名称
@ -87,13 +86,13 @@ class Typecho_Db
* @access private
* @var string
*/
private $_adapterName;
private $adapterName;
/**
* 实例化的数据库对象
* @var Typecho_Db
* @var Db
*/
private static $_instance;
private static $instance;
/**
* 数据库类构造函数
@ -101,32 +100,33 @@ class Typecho_Db
* @param mixed $adapterName 适配器名称
* @param string $prefix 前缀
*
* @throws Typecho_Db_Exception
* @throws DbException
*/
public function __construct($adapterName, string $prefix = 'typecho_')
{
/** 获取适配器名称 */
$this->_adapterName = $adapterName;
$adapterName = $adapterName == 'Mysql' ? 'Mysqli' : $adapterName;
$this->adapterName = $adapterName;
/** 数据库适配器 */
$adapterName = 'Typecho_Db_Adapter_' . $adapterName;
$adapterName = '\Typecho\Db\Adapter\\' . str_replace('_', '\\', $adapterName);
if (!call_user_func([$adapterName, 'isAvailable'])) {
throw new Typecho_Db_Exception("Adapter {$adapterName} is not available");
throw new DbException("Adapter {$adapterName} is not available");
}
$this->_prefix = $prefix;
$this->prefix = $prefix;
/** 初始化内部变量 */
$this->_connectedPool = [];
$this->connectedPool = [];
$this->_config = [
$this->config = [
self::READ => [],
self::WRITE => []
];
//实例化适配器对象
$this->_adapter = new $adapterName();
$this->adapter = new $adapterName();
}
/**
@ -137,7 +137,7 @@ class Typecho_Db
*/
public function getAdapterName(): string
{
return $this->_adapterName;
return $this->adapterName;
}
/**
@ -148,21 +148,21 @@ class Typecho_Db
*/
public function getPrefix(): string
{
return $this->_prefix;
return $this->prefix;
}
/**
* @param Typecho_Config $config
* @param Config $config
* @param int $op
*/
public function addConfig(Typecho_Config $config, int $op)
public function addConfig(Config $config, int $op)
{
if ($op & self::READ) {
$this->_config[self::READ][] = $config;
$this->config[self::READ][] = $config;
}
if ($op & self::WRITE) {
$this->_config[self::WRITE][] = $config;
$this->config[self::WRITE][] = $config;
}
}
@ -171,18 +171,18 @@ class Typecho_Db
*
* @param int $op
*
* @return Typecho_Config
* @throws Typecho_Db_Exception
* @return Config
* @throws DbException
*/
public function getConfig(int $op): Typecho_Config
public function getConfig(int $op): Config
{
if (empty($this->_config[$op])) {
/** Typecho_Db_Exception */
throw new Typecho_Db_Exception('Missing Database Connection');
if (empty($this->config[$op])) {
/** DbException */
throw new DbException('Missing Database Connection');
}
$key = array_rand($this->_config[$op]);
return $this->_config[$op][$key];
$key = array_rand($this->config[$op]);
return $this->config[$op][$key];
}
/**
@ -192,7 +192,7 @@ class Typecho_Db
*/
public function flushPool()
{
$this->_connectedPool = [];
$this->connectedPool = [];
}
/**
@ -201,27 +201,27 @@ class Typecho_Db
* @param int $op
*
* @return mixed
* @throws Typecho_Db_Exception
* @throws DbException
*/
public function selectDb(int $op)
{
if (!isset($this->_connectedPool[$op])) {
if (!isset($this->connectedPool[$op])) {
$selectConnectionConfig = $this->getConfig($op);
$selectConnectionHandle = $this->_adapter->connect($selectConnectionConfig);
$this->_connectedPool[$op] = $selectConnectionHandle;
$selectConnectionHandle = $this->adapter->connect($selectConnectionConfig);
$this->connectedPool[$op] = $selectConnectionHandle;
}
return $this->_connectedPool[$op];
return $this->connectedPool[$op];
}
/**
* 获取SQL词法构建器实例化对象
*
* @return Typecho_Db_Query
* @return Query
*/
public function sql(): Typecho_Db_Query
public function sql(): Query
{
return new Typecho_Db_Query($this->_adapter, $this->_prefix);
return new Query($this->adapter, $this->prefix);
}
/**
@ -234,7 +234,7 @@ class Typecho_Db
*/
public function addServer(array $config, int $op)
{
$this->addConfig(Typecho_Config::factory($config), $op);
$this->addConfig(Config::factory($config), $op);
$this->flushPool();
}
@ -244,40 +244,40 @@ class Typecho_Db
* @param int $op
*
* @return string
* @throws Typecho_Db_Exception
* @throws DbException
*/
public function getVersion(int $op = self::READ): string
{
return $this->_adapter->getVersion($this->selectDb($op));
return $this->adapter->getVersion($this->selectDb($op));
}
/**
* 设置默认数据库对象
*
* @access public
* @param Typecho_Db $db 数据库对象
* @param Db $db 数据库对象
* @return void
*/
public static function set(Typecho_Db $db)
public static function set(Db $db)
{
self::$_instance = $db;
self::$instance = $db;
}
/**
* 获取数据库实例化对象
* 用静态变量存储实例化的数据库对象,可以保证数据连接仅进行一次
*
* @return Typecho_Db
* @throws Typecho_Db_Exception
* @return Db
* @throws DbException
*/
public static function get(): Typecho_Db
public static function get(): Db
{
if (empty(self::$_instance)) {
/** Typecho_Db_Exception */
throw new Typecho_Db_Exception('Missing Database Object');
if (empty(self::$instance)) {
/** DbException */
throw new DbException('Missing Database Object');
}
return self::$_instance;
return self::$instance;
}
/**
@ -285,10 +285,10 @@ class Typecho_Db
*
* @param ...$ags
*
* @return Typecho_Db_Query
* @throws Typecho_Db_Exception
* @return Query
* @throws DbException
*/
public function select(...$ags): Typecho_Db_Query
public function select(...$ags): Query
{
$this->selectDb(self::READ);
@ -301,10 +301,10 @@ class Typecho_Db
*
* @param string $table 需要更新记录的表
*
* @return Typecho_Db_Query
* @throws Typecho_Db_Exception
* @return Query
* @throws DbException
*/
public function update(string $table): Typecho_Db_Query
public function update(string $table): Query
{
$this->selectDb(self::WRITE);
@ -316,10 +316,10 @@ class Typecho_Db
*
* @param string $table 需要删除记录的表
*
* @return Typecho_Db_Query
* @throws Typecho_Db_Exception
* @return Query
* @throws DbException
*/
public function delete(string $table): Typecho_Db_Query
public function delete(string $table): Query
{
$this->selectDb(self::WRITE);
@ -331,10 +331,10 @@ class Typecho_Db
*
* @param string $table 需要插入记录的表
*
* @return Typecho_Db_Query
* @throws Typecho_Db_Exception
* @return Query
* @throws DbException
*/
public function insert(string $table): Typecho_Db_Query
public function insert(string $table): Query
{
$this->selectDb(self::WRITE);
@ -343,12 +343,12 @@ class Typecho_Db
/**
* @param $table
* @throws Typecho_Db_Exception
* @throws DbException
*/
public function truncate($table)
{
$table = preg_replace("/^table\./", $this->_prefix, $table);
$this->_adapter->truncate($table, $this->selectDb(self::WRITE));
$table = preg_replace("/^table\./", $this->prefix, $table);
$this->adapter->truncate($table, $this->selectDb(self::WRITE));
}
/**
@ -359,19 +359,19 @@ class Typecho_Db
* @param string $action 操作动作
*
* @return mixed
* @throws Typecho_Db_Exception
* @throws DbException
*/
public function query($query, int $op = self::READ, string $action = self::SELECT)
{
$table = null;
/** 在适配器中执行查询 */
if ($query instanceof Typecho_Db_Query) {
if ($query instanceof Query) {
$action = $query->getAttribute('action');
$table = $query->getAttribute('table');
$op = (self::UPDATE == $action || self::DELETE == $action
|| self::INSERT == $action) ? self::WRITE : self::READ;
} else if (!is_string($query)) {
} elseif (!is_string($query)) {
/** 如果query不是对象也不是字符串,那么将其判断为查询资源句柄,直接返回 */
return $query;
}
@ -380,7 +380,7 @@ class Typecho_Db
$handle = $this->selectDb($op);
/** 提交查询 */
$resource = $this->_adapter->query($query instanceof Typecho_Db_Query ?
$resource = $this->adapter->query($query instanceof Query ?
$query->prepare($query) : $query, $handle, $op, $action, $table);
if ($action) {
@ -388,9 +388,9 @@ class Typecho_Db
switch ($action) {
case self::UPDATE:
case self::DELETE:
return $this->_adapter->affectedRows($resource, $handle);
return $this->adapter->affectedRows($resource, $handle);
case self::INSERT:
return $this->_adapter->lastInsertId($resource, $handle);
return $this->adapter->lastInsertId($resource, $handle);
case self::SELECT:
default:
return $resource;
@ -405,52 +405,35 @@ class Typecho_Db
* 一次取出所有行
*
* @param mixed $query 查询对象
* @param array|null $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
* @param callable|null $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
*
* @return array
* @throws Typecho_Db_Exception
* @throws DbException
*/
public function fetchAll($query, ?array $filter = null): array
public function fetchAll($query, ?callable $filter = null): array
{
//执行查询
$resource = $this->query($query, self::READ);
$result = [];
$resource = $this->query($query);
$result = $this->adapter->fetchAll($resource);
/** 取出过滤器 */
if (!empty($filter)) {
[$object, $method] = $filter;
}
//取出每一行
while ($rows = $this->_adapter->fetch($resource)) {
//判断是否有过滤器
$result[] = $filter ? call_user_func([&$object, $method], $rows) : $rows;
}
return $result;
return $filter ? array_map($filter, $result) : $result;
}
/**
* 一次取出一行
*
* @param mixed $query 查询对象
* @param array|null $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
*
* @return mixed
* @throws Typecho_Db_Exception
* @param callable|null $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
* @return array|null
* @throws DbException
*/
public function fetchRow($query, ?array $filter = null)
public function fetchRow($query, ?callable $filter = null): ?array
{
$resource = $this->query($query, self::READ);
$resource = $this->query($query);
/** 取出过滤器 */
if ($filter) {
[$object, $method] = $filter;
}
return ($rows = $this->_adapter->fetch($resource)) ?
($filter ? $object->$method($rows) : $rows) :
[];
return ($rows = $this->adapter->fetch($resource)) ?
($filter ? call_user_func($filter, $rows) : $rows) :
null;
}
/**
@ -458,21 +441,15 @@ class Typecho_Db
*
* @param mixed $query 查询对象
* @param array|null $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
*
* @return mixed
* @throws Typecho_Db_Exception
* @return object|null
* @throws DbException
*/
public function fetchObject($query, ?array $filter = null)
public function fetchObject($query, ?array $filter = null): ?object
{
$resource = $this->query($query, self::READ);
$resource = $this->query($query);
/** 取出过滤器 */
if ($filter) {
[$object, $method] = $filter;
}
return ($rows = $this->_adapter->fetchObject($resource)) ?
($filter ? $object->$method($rows) : $rows) :
new stdClass();
return ($rows = $this->adapter->fetchObject($resource)) ?
($filter ? call_user_func($filter, $rows) : $rows) :
null;
}
}

View File

@ -1,11 +1,9 @@
<?php
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id: DbAdapter.php 97 2008-04-04 04:39:54Z magike.net $
*/
namespace Typecho\Db;
use Typecho\Config;
use Typecho\Db;
/**
* Typecho数据库适配器
@ -13,7 +11,7 @@
*
* @package Db
*/
interface Typecho_Db_Adapter
interface Adapter
{
/**
* 判断适配器是否可用
@ -21,15 +19,15 @@ interface Typecho_Db_Adapter
* @access public
* @return boolean
*/
public static function isAvailable();
public static function isAvailable(): bool;
/**
* 数据库连接函数
*
* @param Typecho_Config $config 数据库配置
* @param Config $config 数据库配置
* @return mixed
*/
public function connect(Typecho_Config $config);
public function connect(Config $config);
/**
* 获取数据库版本
@ -37,16 +35,15 @@ interface Typecho_Db_Adapter
* @param mixed $handle
* @return string
*/
public function getVersion($handle);
public function getVersion($handle): string;
/**
* 清空数据表
*
* @param string $table 数据表名
* @param mixed $handle 连接对象
* @return mixed
*/
public function truncate($table, $handle);
public function truncate(string $table, $handle);
/**
* 执行数据库查询
@ -54,35 +51,43 @@ interface Typecho_Db_Adapter
* @param string $query 数据库查询SQL字符串
* @param mixed $handle 连接对象
* @param integer $op 数据库读写状态
* @param string $action 数据库动作
* @param string $table 数据表
* @param string|null $action 数据库动作
* @param string|null $table 数据表
* @return resource
*/
public function query($query, $handle, $op = Typecho_Db::READ, $action = null, $table = null);
public function query(string $query, $handle, int $op = Db::READ, ?string $action = null, ?string $table = null);
/**
* 将数据查询的其中一行作为数组取出,其中字段名对应数组键值
*
* @param resource $resource 查询的资源数据
* @return array|null
*/
public function fetch($resource): ?array;
/**
* 将数据查询的结果作为数组全部取出,其中字段名对应数组键值
*
* @param resource $resource 查询的资源数据
* @return array
*/
public function fetch($resource);
public function fetchAll($resource): array;
/**
* 将数据查询的其中一行作为对象取出,其中字段名对应对象属性
*
* @param resource $resource 查询的资源数据
* @return object
* @return object|null
*/
public function fetchObject($resource);
public function fetchObject($resource): ?object;
/**
* 引号转义函数
*
* @param string $string 需要转义的字符串
* @param mixed $string 需要转义的字符串
* @return string
*/
public function quoteValue($string);
public function quoteValue($string): string;
/**
* 对象引号过滤
@ -91,7 +96,7 @@ interface Typecho_Db_Adapter
* @param string $string
* @return string
*/
public function quoteColumn($string);
public function quoteColumn(string $string): string;
/**
* 合成查询语句
@ -100,7 +105,7 @@ interface Typecho_Db_Adapter
* @param array $sql 查询对象词法数组
* @return string
*/
public function parseSelect(array $sql);
public function parseSelect(array $sql): string;
/**
* 取出最后一次查询影响的行数
@ -109,7 +114,7 @@ interface Typecho_Db_Adapter
* @param mixed $handle 连接对象
* @return integer
*/
public function affectedRows($resource, $handle);
public function affectedRows($resource, $handle): int;
/**
* 取出最后一次插入返回的主键值
@ -118,5 +123,5 @@ interface Typecho_Db_Adapter
* @param mixed $handle 连接对象
* @return integer
*/
public function lastInsertId($resource, $handle);
public function lastInsertId($resource, $handle): int;
}

View File

@ -0,0 +1,18 @@
<?php
namespace Typecho\Db\Adapter;
if (!defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
use Typecho\Db\Exception as DbException;
/**
* 数据库连接异常类
*
* @package Db
*/
class ConnectionException extends DbException
{
}

View File

@ -1,17 +0,0 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id: DbException.php 52 2008-03-18 08:04:01Z magike.net $
*/
/**
* 数据库连接异常类
*
* @package Db
*/
class Typecho_Db_Adapter_Exception extends Typecho_Db_Exception
{}

View File

@ -1,196 +0,0 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id: Mysql.php 103 2008-04-09 16:22:43Z magike.net $
*/
/**
* 数据库Mysql适配器
*
* @package Db
*/
class Typecho_Db_Adapter_Mysql implements Typecho_Db_Adapter
{
/**
* 数据库连接字符串标示
*
* @access private
* @var resource
*/
private $_dbLink;
/**
* 判断适配器是否可用
*
* @access public
* @return boolean
*/
public static function isAvailable()
{
return function_exists('mysql_connect');
}
/**
* 数据库连接函数
*
* @param Typecho_Config $config 数据库配置
* @return mixed
* @throws Typecho_Db_Exception
*/
public function connect(Typecho_Config $config)
{
if ($this->_dbLink = @mysql_connect($config->host . (empty($config->port) ? '' : ':' . $config->port),
$config->user, $config->password, true)) {
if (@mysql_select_db($config->database, $this->_dbLink)) {
if ($config->charset) {
mysql_query("SET NAMES '{$config->charset}'", $this->_dbLink);
}
return $this->_dbLink;
}
}
/** 数据库异常 */
throw new Typecho_Db_Adapter_Exception(@mysql_error($this->_dbLink));
}
/**
* 获取数据库版本
*
* @param mixed $handle
* @return string
*/
public function getVersion($handle)
{
return 'mysql:mysql ' . mysql_get_server_info($handle);
}
/**
* 清空数据表
*
* @param string $table
* @param mixed $handle 连接对象
* @return mixed|void
* @throws Typecho_Db_Exception
*/
public function truncate($table, $handle)
{
$this->query('TRUNCATE TABLE ' . $this->quoteColumn($table), $handle);
}
/**
* 执行数据库查询
*
* @param string $query 数据库查询SQL字符串
* @param mixed $handle 连接对象
* @param integer $op 数据库读写状态
* @param string $action 数据库动作
* @param string $table 数据表
* @return resource
* @throws Typecho_Db_Exception
*/
public function query($query, $handle, $op = Typecho_Db::READ, $action = null, $table = null)
{
if ($resource = @mysql_query($query, $handle)) {
return $resource;
}
/** 数据库异常 */
throw new Typecho_Db_Query_Exception(@mysql_error($this->_dbLink), mysql_errno($this->_dbLink));
}
/**
* 对象引号过滤
*
* @access public
* @param string $string
* @return string
*/
public function quoteColumn($string)
{
return '`' . $string . '`';
}
/**
* 将数据查询的其中一行作为数组取出,其中字段名对应数组键值
*
* @param resource $resource 查询返回资源标识
* @return array
*/
public function fetch($resource)
{
return mysql_fetch_assoc($resource);
}
/**
* 将数据查询的其中一行作为对象取出,其中字段名对应对象属性
*
* @param resource $resource 查询的资源数据
* @return object
*/
public function fetchObject($resource)
{
return mysql_fetch_object($resource);
}
/**
* 引号转义函数
*
* @param string $string 需要转义的字符串
* @return string
*/
public function quoteValue($string)
{
return '\'' . str_replace(['\'', '\\'], ['\'\'', '\\\\'], $string) . '\'';
}
/**
* 合成查询语句
*
* @access public
* @param array $sql 查询对象词法数组
* @return string
*/
public function parseSelect(array $sql)
{
if (!empty($sql['join'])) {
foreach ($sql['join'] as $val) {
[$table, $condition, $op] = $val;
$sql['table'] = "{$sql['table']} {$op} JOIN {$table} ON {$condition}";
}
}
$sql['limit'] = (0 == strlen($sql['limit'])) ? null : ' LIMIT ' . $sql['limit'];
$sql['offset'] = (0 == strlen($sql['offset'])) ? null : ' OFFSET ' . $sql['offset'];
return 'SELECT ' . $sql['fields'] . ' FROM ' . $sql['table'] .
$sql['where'] . $sql['group'] . $sql['having'] . $sql['order'] . $sql['limit'] . $sql['offset'];
}
/**
* 取出最后一次查询影响的行数
*
* @param resource $resource 查询的资源数据
* @param mixed $handle 连接对象
* @return integer
*/
public function affectedRows($resource, $handle)
{
return mysql_affected_rows($handle);
}
/**
* 取出最后一次插入返回的主键值
*
* @param resource $resource 查询的资源数据
* @param mixed $handle 连接对象
* @return integer
*/
public function lastInsertId($resource, $handle)
{
return mysql_insert_id($handle);
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Typecho\Db\Adapter;
trait MysqlTrait
{
use QueryTrait;
/**
* 清空数据表
*
* @param string $table
* @param mixed $handle 连接对象
* @throws SQLException
*/
public function truncate(string $table, $handle)
{
$this->query('TRUNCATE TABLE ' . $this->quoteColumn($table), $handle);
}
/**
* 合成查询语句
*
* @access public
* @param array $sql 查询对象词法数组
* @return string
*/
public function parseSelect(array $sql): string
{
return $this->buildQuery($sql);
}
}

View File

@ -1,27 +1,31 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id: Mysqli.php 103 2008-04-09 16:22:43Z magike.net $
*/
namespace Typecho\Db\Adapter;
use Typecho\Config;
use Typecho\Db;
use Typecho\Db\Adapter;
if (!defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
/**
* 数据库Mysqli适配器
*
* @package Db
*/
class Typecho_Db_Adapter_Mysqli implements Typecho_Db_Adapter
class Mysqli implements Adapter
{
use MysqlTrait;
/**
* 数据库连接字符串标示
*
* @access private
* @var mysqli
* @var \mysqli
*/
private $_dbLink;
private $dbLink;
/**
* 判断适配器是否可用
@ -29,36 +33,38 @@ class Typecho_Db_Adapter_Mysqli implements Typecho_Db_Adapter
* @access public
* @return boolean
*/
public static function isAvailable()
public static function isAvailable(): bool
{
return class_exists('MySQLi');
return extension_loaded('mysqli');
}
/**
* 数据库连接函数
*
* @param Typecho_Config $config 数据库配置
* @return mixed
* @throws Typecho_Db_Exception
* @param Config $config 数据库配置
* @return \mysqli
* @throws ConnectionException
*/
public function connect(Typecho_Config $config)
public function connect(Config $config): \mysqli
{
if ($this->_dbLink = @mysqli_connect(
$config->host,
$config->user,
$config->password,
$config->database,
(empty($config->port) ? null : $config->port))
if (
$this->dbLink = @mysqli_connect(
$config->host,
$config->user,
$config->password,
$config->database,
(empty($config->port) ? null : $config->port)
)
) {
if ($config->charset) {
$this->_dbLink->query("SET NAMES '{$config->charset}'");
$this->dbLink->query("SET NAMES '{$config->charset}'");
}
return $this->_dbLink;
return $this->dbLink;
}
/** 数据库异常 */
throw new Typecho_Db_Adapter_Exception(@$this->_dbLink->error);
throw new ConnectionException(@$this->dbLink->error, @$this->dbLink->errno);
}
/**
@ -67,22 +73,9 @@ class Typecho_Db_Adapter_Mysqli implements Typecho_Db_Adapter
* @param mixed $handle
* @return string
*/
public function getVersion($handle)
public function getVersion($handle): string
{
return 'mysqli:mysql ' . $this->_dbLink->server_version;
}
/**
* 清空数据表
*
* @param string $table
* @param mixed $handle 连接对象
* @return mixed|void
* @throws Typecho_Db_Exception
*/
public function truncate($table, $handle)
{
$this->query('TRUNCATE TABLE ' . $this->quoteColumn($table), $handle);
return 'mysqli:mysql ' . $this->dbLink->server_version;
}
/**
@ -91,19 +84,24 @@ class Typecho_Db_Adapter_Mysqli implements Typecho_Db_Adapter
* @param string $query 数据库查询SQL字符串
* @param mixed $handle 连接对象
* @param integer $op 数据库读写状态
* @param string $action 数据库动作
* @param string $table 数据表
* @return resource
* @throws Typecho_Db_Exception
* @param string|null $action 数据库动作
* @param string|null $table 数据表
* @return \mysqli_result
* @throws SQLException
*/
public function query($query, $handle, $op = Typecho_Db::READ, $action = null, $table = null)
{
if ($resource = @$this->_dbLink->query($query)) {
public function query(
string $query,
$handle,
int $op = Db::READ,
?string $action = null,
?string $table = null
): \mysqli_result {
if ($resource = @$this->dbLink->query($query)) {
return $resource;
}
/** 数据库异常 */
throw new Typecho_Db_Query_Exception($this->_dbLink->error, $this->_dbLink->errno);
throw new SQLException($this->dbLink->error, $this->dbLink->errno);
}
/**
@ -113,29 +111,40 @@ class Typecho_Db_Adapter_Mysqli implements Typecho_Db_Adapter
* @param string $string
* @return string
*/
public function quoteColumn($string)
public function quoteColumn(string $string): string
{
return $this->_dbLink->real_escape_string($string);
return $this->dbLink->real_escape_string($string);
}
/**
* 将数据查询的其中一行作为数组取出,其中字段名对应数组键值
*
* @param resource $resource 查询返回资源标识
* @return array
* @param \mysqli_result $resource 查询返回资源标识
* @return array|null
*/
public function fetch($resource)
public function fetch($resource): ?array
{
return $resource->fetch_assoc();
}
/**
* 将数据查询的结果作为数组全部取出,其中字段名对应数组键值
*
* @param \mysqli_result $resource 查询返回资源标识
* @return array
*/
public function fetchAll($resource): array
{
return $resource->fetch_all(MYSQLI_ASSOC);
}
/**
* 将数据查询的其中一行作为对象取出,其中字段名对应对象属性
*
* @param resource $resource 查询的资源数据
* @return object
* @param \mysqli_result $resource 查询的资源数据
* @return object|null
*/
public function fetchObject($resource)
public function fetchObject($resource): ?object
{
return $resource->fetch_object();
}
@ -143,58 +152,35 @@ class Typecho_Db_Adapter_Mysqli implements Typecho_Db_Adapter
/**
* 引号转义函数
*
* @param string $string 需要转义的字符串
* @param mixed $string 需要转义的字符串
* @return string
*/
public function quoteValue($string)
public function quoteValue($string): string
{
return '\'' . str_replace(['\'', '\\'], ['\'\'', '\\\\'], $string) . '\'';
}
/**
* 合成查询语句
* 取出最后一次查询影响的行数
*
* @access public
* @param array $sql 查询对象词法数组
* @return string
* @param \mysqli_result $resource 查询的资源数据
* @param \mysqli $handle 连接对象
* @return integer
*/
public function parseSelect(array $sql)
public function affectedRows($resource, $handle): int
{
if (!empty($sql['join'])) {
foreach ($sql['join'] as $val) {
[$table, $condition, $op] = $val;
$sql['table'] = "{$sql['table']} {$op} JOIN {$table} ON {$condition}";
}
}
$sql['limit'] = (0 == strlen($sql['limit'])) ? null : ' LIMIT ' . $sql['limit'];
$sql['offset'] = (0 == strlen($sql['offset'])) ? null : ' OFFSET ' . $sql['offset'];
return 'SELECT ' . $sql['fields'] . ' FROM ' . $sql['table'] .
$sql['where'] . $sql['group'] . $sql['having'] . $sql['order'] . $sql['limit'] . $sql['offset'];
return $handle->affected_rows;
}
/**
* 取出最后一次查询影响的行数
*
* @param resource $resource 查询的资源数据
* @param mixed $handle 连接对象
* @return integer
*/
public function affectedRows($resource, $handle)
{
return $this->_dbLink->affected_rows;
}
/*y
* 取出最后一次插入返回的主键值
*
* @param resource $resource 查询的资源数据
* @param mixed $handle 连接对象
* @param \mysqli_result $resource 查询的资源数据
* @param \mysqli $handle 连接对象
* @return integer
*/
public function lastInsertId($resource, $handle)
public function lastInsertId($resource, $handle): int
{
return $this->_dbLink->insert_id;
return $handle->insert_id;
}
}

View File

@ -1,27 +1,29 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id: Mysql.php 89 2008-03-31 00:10:57Z magike.net $
*/
namespace Typecho\Db\Adapter;
use Typecho\Config;
use Typecho\Db;
use Typecho\Db\Adapter;
if (!defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
/**
* 数据库PDOMysql适配器
*
* @package Db
*/
abstract class Typecho_Db_Adapter_Pdo implements Typecho_Db_Adapter
abstract class Pdo implements Adapter
{
/**
* 数据库对象
*
* @access protected
* @var PDO
* @var \PDO
*/
protected $_object;
protected $object;
/**
* 最后一次操作的数据表
@ -29,7 +31,7 @@ abstract class Typecho_Db_Adapter_Pdo implements Typecho_Db_Adapter
* @access protected
* @var string
*/
protected $_lastTable;
protected $lastTable;
/**
* 判断适配器是否可用
@ -37,7 +39,7 @@ abstract class Typecho_Db_Adapter_Pdo implements Typecho_Db_Adapter
* @access public
* @return boolean
*/
public static function isAvailable()
public static function isAvailable(): bool
{
return class_exists('PDO');
}
@ -45,31 +47,31 @@ abstract class Typecho_Db_Adapter_Pdo implements Typecho_Db_Adapter
/**
* 数据库连接函数
*
* @param Typecho_Config $config 数据库配置
* @return PDO
* @throws Typecho_Db_Exception
* @param Config $config 数据库配置
* @return \PDO
* @throws ConnectionException
*/
public function connect(Typecho_Config $config)
public function connect(Config $config): \PDO
{
try {
$this->_object = $this->init($config);
$this->_object->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $this->_object;
} catch (PDOException $e) {
$this->object = $this->init($config);
$this->object->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
return $this->object;
} catch (\PDOException $e) {
/** 数据库异常 */
throw new Typecho_Db_Adapter_Exception($e->getMessage());
throw new ConnectionException($e->getMessage(), $e->getCode());
}
}
/**
* 初始化数据库
*
* @param Typecho_Config $config 数据库配置
* @param Config $config 数据库配置
* @abstract
* @access public
* @return PDO
* @return \PDO
*/
abstract public function init(Typecho_Config $config);
abstract public function init(Config $config): \PDO;
/**
* 获取数据库版本
@ -77,78 +79,94 @@ abstract class Typecho_Db_Adapter_Pdo implements Typecho_Db_Adapter
* @param mixed $handle
* @return string
*/
public function getVersion($handle)
public function getVersion($handle): string
{
return 'pdo:' . $handle->getAttribute(PDO::ATTR_DRIVER_NAME)
. ' ' . $handle->getAttribute(PDO::ATTR_SERVER_VERSION);
return 'pdo:' . $handle->getAttribute(\PDO::ATTR_DRIVER_NAME)
. ' ' . $handle->getAttribute(\PDO::ATTR_SERVER_VERSION);
}
/**
* 执行数据库查询
*
* @param string $query 数据库查询SQL字符串
* @param mixed $handle 连接对象
* @param \PDO $handle 连接对象
* @param integer $op 数据库读写状态
* @param string $action 数据库动作
* @param string $table 数据表
* @return resource
* @throws Typecho_Db_Exception
* @param string|null $action 数据库动作
* @param string|null $table 数据表
* @return \PDOStatement
* @throws SQLException
*/
public function query($query, $handle, $op = Typecho_Db::READ, $action = null, $table = null)
{
public function query(
string $query,
$handle,
int $op = Db::READ,
?string $action = null,
?string $table = null
): \PDOStatement {
try {
$this->_lastTable = $table;
$this->lastTable = $table;
$resource = $handle->prepare($query);
$resource->execute();
} catch (PDOException $e) {
} catch (\PDOException $e) {
/** 数据库异常 */
throw new Typecho_Db_Query_Exception($e->getMessage(), $e->getCode());
throw new SQLException($e->getMessage(), $e->getCode());
}
return $resource;
}
/**
* 将数据查询的其中一行作为数组取出,其中字段名对应数组键值
* 将数据查询的结果作为数组全部取出,其中字段名对应数组键值
*
* @param resource $resource 查询返回资源标识
* @param \PDOStatement $resource 查询的资源数据
* @return array
*/
public function fetch($resource)
public function fetchAll($resource): array
{
return $resource->fetch(PDO::FETCH_ASSOC);
return $resource->fetchAll(\PDO::FETCH_ASSOC);
}
/**
* 将数据查询的其中一行作为数组取出,其中字段名对应数组键值
*
* @param \PDOStatement $resource 查询返回资源标识
* @return array|null
*/
public function fetch($resource): ?array
{
return $resource->fetch(\PDO::FETCH_ASSOC) ?: null;
}
/**
* 将数据查询的其中一行作为对象取出,其中字段名对应对象属性
*
* @param resource $resource 查询的资源数据
* @return object
* @param \PDOStatement $resource 查询的资源数据
* @return object|null
*/
public function fetchObject($resource)
public function fetchObject($resource): ?object
{
return $resource->fetchObject();
return $resource->fetchObject() ?: null;
}
/**
* 引号转义函数
*
* @param string $string 需要转义的字符串
* @param mixed $string 需要转义的字符串
* @return string
*/
public function quoteValue($string)
public function quoteValue($string): string
{
return $this->_object->quote($string);
return $this->object->quote($string);
}
/**
* 取出最后一次查询影响的行数
*
* @param resource $resource 查询的资源数据
* @param mixed $handle 连接对象
* @param \PDOStatement $resource 查询的资源数据
* @param \PDO $handle 连接对象
* @return integer
*/
public function affectedRows($resource, $handle)
public function affectedRows($resource, $handle): int
{
return $resource->rowCount();
}
@ -156,11 +174,11 @@ abstract class Typecho_Db_Adapter_Pdo implements Typecho_Db_Adapter
/**
* 取出最后一次插入返回的主键值
*
* @param resource $resource 查询的资源数据
* @param mixed $handle 连接对象
* @param \PDOStatement $resource 查询的资源数据
* @param \PDO $handle 连接对象
* @return integer
*/
public function lastInsertId($resource, $handle)
public function lastInsertId($resource, $handle): int
{
return $handle->lastInsertId();
}

View File

@ -1,42 +1,33 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id: Mysql.php 89 2008-03-31 00:10:57Z magike.net $
*/
namespace Typecho\Db\Adapter\Pdo;
use Typecho\Config;
use Typecho\Db\Adapter\MysqlTrait;
use Typecho\Db\Adapter\Pdo;
if (!defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
/**
* 数据库Pdo_Mysql适配器
*
* @package Db
*/
class Typecho_Db_Adapter_Pdo_Mysql extends Typecho_Db_Adapter_Pdo
class Mysql extends Pdo
{
use MysqlTrait;
/**
* 判断适配器是否可用
*
* @access public
* @return boolean
*/
public static function isAvailable()
public static function isAvailable(): bool
{
return parent::isAvailable() && in_array('mysql', PDO::getAvailableDrivers());
}
/**
* 清空数据表
*
* @param string $table
* @param mixed $handle 连接对象
* @return mixed|void
* @throws Typecho_Db_Exception
*/
public function truncate($table, $handle)
{
$this->query('TRUNCATE TABLE ' . $this->quoteColumn($table), $handle);
return parent::isAvailable() && in_array('mysql', \PDO::getAvailableDrivers());
}
/**
@ -46,7 +37,7 @@ class Typecho_Db_Adapter_Pdo_Mysql extends Typecho_Db_Adapter_Pdo
* @param string $string
* @return string
*/
public function quoteColumn($string)
public function quoteColumn(string $string): string
{
return '`' . $string . '`';
}
@ -54,50 +45,35 @@ class Typecho_Db_Adapter_Pdo_Mysql extends Typecho_Db_Adapter_Pdo
/**
* 初始化数据库
*
* @param Typecho_Config $config 数据库配置
* @param Config $config 数据库配置
* @access public
* @return PDO
* @return \PDO
*/
public function init(Typecho_Config $config)
public function init(Config $config): \PDO
{
$pdo = new PDO(!empty($config->dsn) ? $config->dsn :
"mysql:dbname={$config->database};host={$config->host};port={$config->port}", $config->user, $config->password);
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
$pdo->exec("SET NAMES '{$config->charset}'");
$pdo = new \PDO(
!empty($config->dsn)
? $config->dsn : "mysql:dbname={$config->database};host={$config->host};port={$config->port}",
$config->user,
$config->password
);
$pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
if ($config->charset) {
$pdo->exec("SET NAMES '{$config->charset}'");
}
return $pdo;
}
/**
* 引号转义函数
*
* @param string $string 需要转义的字符串
* @param mixed $string 需要转义的字符串
* @return string
*/
public function quoteValue($string)
public function quoteValue($string): string
{
return '\'' . str_replace(['\'', '\\'], ['\'\'', '\\\\'], $string) . '\'';
}
/**
* 合成查询语句
*
* @access public
* @param array $sql 查询对象词法数组
* @return string
*/
public function parseSelect(array $sql)
{
if (!empty($sql['join'])) {
foreach ($sql['join'] as $val) {
[$table, $condition, $op] = $val;
$sql['table'] = "{$sql['table']} {$op} JOIN {$table} ON {$condition}";
}
}
$sql['limit'] = (0 == strlen($sql['limit'])) ? null : ' LIMIT ' . $sql['limit'];
$sql['offset'] = (0 == strlen($sql['offset'])) ? null : ' OFFSET ' . $sql['offset'];
return 'SELECT ' . $sql['fields'] . ' FROM ' . $sql['table'] .
$sql['where'] . $sql['group'] . $sql['having'] . $sql['order'] . $sql['limit'] . $sql['offset'];
}
}

View File

@ -1,33 +1,25 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id$
*/
namespace Typecho\Db\Adapter\Pdo;
use Typecho\Config;
use Typecho\Db;
use Typecho\Db\Adapter\SQLException;
use Typecho\Db\Adapter\Pdo;
use Typecho\Db\Adapter\PgsqlTrait;
if (!defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
/**
* 数据库Pdo_Pgsql适配器
*
* @package Db
*/
class Typecho_Db_Adapter_Pdo_Pgsql extends Typecho_Db_Adapter_Pdo
class Pgsql extends Pdo
{
/**
* 主键列表
*
* @var array
*/
private $_pk = [];
/**
* 兼容的插入模式
*
* @var bool
*/
private $_compatibleInsert = false;
use PgsqlTrait;
/**
* 判断适配器是否可用
@ -35,134 +27,51 @@ class Typecho_Db_Adapter_Pdo_Pgsql extends Typecho_Db_Adapter_Pdo
* @access public
* @return boolean
*/
public static function isAvailable()
public static function isAvailable(): bool
{
return parent::isAvailable() && in_array('pgsql', PDO::getAvailableDrivers());
return parent::isAvailable() && in_array('pgsql', \PDO::getAvailableDrivers());
}
/**
* 清空数据表
* 执行数据库查询
*
* @param string $table
* @param mixed $handle 连接对象
* @return mixed|void
* @throws Typecho_Db_Exception
* @param string $query 数据库查询SQL字符串
* @param \PDO $handle 连接对象
* @param integer $op 数据库读写状态
* @param string|null $action 数据库动作
* @param string|null $table 数据表
* @return \PDOStatement
* @throws SQLException
*/
public function truncate($table, $handle)
{
$this->query('TRUNCATE TABLE ' . $this->quoteColumn($table) . ' RESTART IDENTITY', $handle);
}
/**
* 覆盖标准动作
* fix #710
*
* @param string $query
* @param mixed $handle
* @param int $op
* @param null $action
* @param null $table
* @return resource
* @throws Typecho_Db_Exception
*/
public function query($query, $handle, $op = Typecho_Db::READ, $action = null, $table = null)
{
if (Typecho_Db::INSERT == $action && !empty($table)) {
if (!isset($this->_pk[$table])) {
$result = $handle->query("SELECT
pg_attribute.attname,
format_type(pg_attribute.atttypid, pg_attribute.atttypmod)
FROM pg_index, pg_class, pg_attribute, pg_namespace
WHERE
pg_class.oid = " . $this->quoteValue($table) . "::regclass AND
indrelid = pg_class.oid AND
nspname = 'public' AND
pg_class.relnamespace = pg_namespace.oid AND
pg_attribute.attrelid = pg_class.oid AND
pg_attribute.attnum = any(pg_index.indkey)
AND indisprimary")->fetch(PDO::FETCH_ASSOC);
if (!empty($result)) {
$this->_pk[$table] = $result['attname'];
}
}
// 使用兼容模式监听插入结果
if (isset($this->_pk[$table])) {
$this->_compatibleInsert = true;
$query .= ' RETURNING ' . $this->quoteColumn($this->_pk[$table]);
}
}
return parent::query($query, $handle, $op, $action, $table); // TODO: Change the autogenerated stub
}
/**
* 对象引号过滤
*
* @access public
* @param string $string
* @return string
*/
public function quoteColumn($string)
{
return '"' . $string . '"';
public function query(
string $query,
$handle,
int $op = Db::READ,
?string $action = null,
?string $table = null
): \PDOStatement {
$this->prepareQuery($query, $handle, $action, $table);
return parent::query($query, $handle, $op, $action, $table);
}
/**
* 初始化数据库
*
* @param Typecho_Config $config 数据库配置
* @access public
* @return PDO
* @param Config $config 数据库配置
* @return \PDO
*/
public function init(Typecho_Config $config)
public function init(Config $config): \PDO
{
$pdo = new PDO("pgsql:dbname={$config->database};host={$config->host};port={$config->port}", $config->user, $config->password);
$pdo->exec("SET NAMES '{$config->charset}'");
$pdo = new \PDO(
"pgsql:dbname={$config->database};host={$config->host};port={$config->port}",
$config->user,
$config->password
);
if ($config->charset) {
$pdo->exec("SET NAMES '{$config->charset}'");
}
return $pdo;
}
/**
* 合成查询语句
*
* @access public
* @param array $sql 查询对象词法数组
* @return string
*/
public function parseSelect(array $sql)
{
if (!empty($sql['join'])) {
foreach ($sql['join'] as $val) {
[$table, $condition, $op] = $val;
$sql['table'] = "{$sql['table']} {$op} JOIN {$table} ON {$condition}";
}
}
$sql['limit'] = (0 == strlen($sql['limit'])) ? null : ' LIMIT ' . $sql['limit'];
$sql['offset'] = (0 == strlen($sql['offset'])) ? null : ' OFFSET ' . $sql['offset'];
return 'SELECT ' . $sql['fields'] . ' FROM ' . $sql['table'] .
$sql['where'] . $sql['group'] . $sql['having'] . $sql['order'] . $sql['limit'] . $sql['offset'];
}
/**
* 取出最后一次插入返回的主键值
*
* @param resource $resource 查询的资源数据
* @param mixed $handle 连接对象
* @return integer
*/
public function lastInsertId($resource, $handle)
{
if ($this->_compatibleInsert) {
$this->_compatibleInsert = false;
return $resource->fetchColumn(0);
} elseif ($handle->query('SELECT oid FROM pg_class WHERE relname = ' . $this->quoteValue($this->_lastTable . '_seq'))->fetchAll()) {
/** 查看是否存在序列,可能需要更严格的检查 */
return $handle->lastInsertId($this->_lastTable . '_seq');
}
return 0;
}
}

View File

@ -1,24 +1,23 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id$
*/
namespace Typecho\Db\Adapter\Pdo;
use Typecho\Config;
use Typecho\Db\Adapter\Pdo;
use Typecho\Db\Adapter\SQLiteTrait;
if (!defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
/**
* 数据库Pdo_SQLite适配器
*
* @package Db
*/
class Typecho_Db_Adapter_Pdo_SQLite extends Typecho_Db_Adapter_Pdo
class SQLite extends Pdo
{
/**
* @var sqlite version 2.x
*/
private $_isSQLite2 = false;
use SQLiteTrait;
/**
* 判断适配器是否可用
@ -26,94 +25,57 @@ class Typecho_Db_Adapter_Pdo_SQLite extends Typecho_Db_Adapter_Pdo
* @access public
* @return boolean
*/
public static function isAvailable()
public static function isAvailable(): bool
{
return parent::isAvailable() && in_array('sqlite', PDO::getAvailableDrivers());
}
/**
* 清空数据表
*
* @param string $table
* @param mixed $handle 连接对象
* @return mixed|void
* @throws Typecho_Db_Exception
*/
public function truncate($table, $handle)
{
$this->query('DELETE FROM ' . $this->quoteColumn($table), $handle);
}
/**
* 对象引号过滤
*
* @access public
* @param string $string
* @return string
*/
public function quoteColumn($string)
{
return '"' . $string . '"';
return parent::isAvailable() && in_array('sqlite', \PDO::getAvailableDrivers());
}
/**
* 初始化数据库
*
* @param Typecho_Config $config 数据库配置
* @param Config $config 数据库配置
* @access public
* @return PDO
* @return \PDO
*/
public function init(Typecho_Config $config)
public function init(Config $config): \PDO
{
$pdo = new PDO("sqlite:{$config->file}");
$this->_isSQLite2 = version_compare($pdo->getAttribute(PDO::ATTR_SERVER_VERSION), '3.0.0', '<');
$pdo = new \PDO("sqlite:{$config->file}");
$this->isSQLite2 = version_compare($pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '3.0.0', '<');
return $pdo;
}
/**
* @param resource $resource
* @return object
* 将数据查询的其中一行作为对象取出,其中字段名对应对象属性
*
* @param \PDOStatement $resource 查询的资源数据
* @return object|null
*/
public function fetchObject($resource)
public function fetchObject($resource): ?object
{
return (object)$this->fetch($resource);
$result = $this->fetch($resource);
return $result ? (object) $result : null;
}
/**
* @param resource $resource
* 将数据查询的其中一行作为数组取出,其中字段名对应数组键值
*
* @param \PDOStatement $resource 查询返回资源标识
* @return array|null
*/
public function fetch($resource): ?array
{
$result = parent::fetch($resource);
return $result ? $this->filterColumnName($result) : null;
}
/**
* 将数据查询的结果作为数组全部取出,其中字段名对应数组键值
*
* @param \PDOStatement $resource 查询的资源数据
* @return array
*/
public function fetch($resource)
public function fetchAll($resource): array
{
return Typecho_Common::filterSQLite2ColumnName(parent::fetch($resource));
}
/**
* 合成查询语句
*
* @access public
* @param array $sql 查询对象词法数组
* @return string
*/
public function parseSelect(array $sql)
{
if (!empty($sql['join'])) {
foreach ($sql['join'] as $val) {
[$table, $condition, $op] = $val;
$sql['table'] = "{$sql['table']} {$op} JOIN {$table} ON {$condition}";
}
}
$sql['limit'] = (0 == strlen($sql['limit'])) ? null : ' LIMIT ' . $sql['limit'];
$sql['offset'] = (0 == strlen($sql['offset'])) ? null : ' OFFSET ' . $sql['offset'];
$query = 'SELECT ' . $sql['fields'] . ' FROM ' . $sql['table'] .
$sql['where'] . $sql['group'] . $sql['having'] . $sql['order'] . $sql['limit'] . $sql['offset'];
if ($this->_isSQLite2) {
$query = Typecho_Common::filterSQLite2CountQuery($query);
}
return $query;
return array_map([$this, 'filterColumnName'], parent::fetchAll($resource));
}
}

View File

@ -1,34 +1,23 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id$
*/
namespace Typecho\Db\Adapter;
use Typecho\Config;
use Typecho\Db;
use Typecho\Db\Adapter;
if (!defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
/**
* 数据库Pgsql适配器
*
* @package Db
*/
class Typecho_Db_Adapter_Pgsql implements Typecho_Db_Adapter
class Pgsql implements Adapter
{
/**
* 最后一次操作的数据表
*
* @access protected
* @var string
*/
protected $_lastTable;
/**
* 数据库连接字符串标示
*
* @access private
* @var resource
*/
private $_dbLink;
use PgsqlTrait;
/**
* 判断适配器是否可用
@ -36,29 +25,32 @@ class Typecho_Db_Adapter_Pgsql implements Typecho_Db_Adapter
* @access public
* @return boolean
*/
public static function isAvailable()
public static function isAvailable(): bool
{
return function_exists('pg_connect');
return extension_loaded('pgsql');
}
/**
* 数据库连接函数
*
* @param Typecho_Config $config 数据库配置
* @param Config $config 数据库配置
* @return resource
* @throws Typecho_Db_Exception
* @throws ConnectionException
*/
public function connect(Typecho_Config $config)
public function connect(Config $config)
{
if ($this->_dbLink = @pg_connect("host={$config->host} port={$config->port} dbname={$config->database} user={$config->user} password={$config->password}")) {
if (
$dbLink = pg_connect("host={$config->host} port={$config->port}"
. " dbname={$config->database} user={$config->user} password={$config->password}")
) {
if ($config->charset) {
pg_query($this->_dbLink, "SET NAMES '{$config->charset}'");
pg_query($dbLink, "SET NAMES '{$config->charset}'");
}
return $this->_dbLink;
return $dbLink;
}
/** 数据库异常 */
throw new Typecho_Db_Adapter_Exception(@pg_last_error($this->_dbLink));
throw new ConnectionException(pg_last_error($dbLink));
}
/**
@ -67,141 +59,87 @@ class Typecho_Db_Adapter_Pgsql implements Typecho_Db_Adapter
* @param mixed $handle
* @return string
*/
public function getVersion($handle)
public function getVersion($handle): string
{
$version = pg_version($handle);
return 'pgsql:pgsql ' . $version['server'];
}
/**
* 清空数据表
*
* @param string $table
* @param mixed $handle 连接对象
* @return mixed|void
* @throws Typecho_Db_Exception
*/
public function truncate($table, $handle)
{
$this->query('TRUNCATE TABLE ' . $this->quoteColumn($table) . ' RESTART IDENTITY', $handle);
}
/**
* 执行数据库查询
*
* @param string $query 数据库查询SQL字符串
* @param mixed $handle 连接对象
* @param resource $handle 连接对象
* @param integer $op 数据库读写状态
* @param string $action 数据库动作
* @param string $table 数据表
* @param string|null $action 数据库动作
* @param string|null $table 数据表
* @return resource
* @throws Typecho_Db_Exception
* @throws SQLException
*/
public function query($query, $handle, $op = Typecho_Db::READ, $action = null, $table = null)
public function query(string $query, $handle, int $op = Db::READ, ?string $action = null, ?string $table = null)
{
$this->_lastTable = $table;
if ($resource = @pg_query($handle, $query)) {
$this->prepareQuery($query, $handle, $action, $table);
if ($resource = pg_query($handle, $query)) {
return $resource;
}
/** 数据库异常 */
throw new Typecho_Db_Query_Exception(@pg_last_error($this->_dbLink),
pg_result_error_field(pg_get_result($this->_dbLink), PGSQL_DIAG_SQLSTATE));
}
/**
* 对象引号过滤
*
* @access public
* @param string $string
* @return string
*/
public function quoteColumn($string)
{
return '"' . $string . '"';
throw new SQLException(
@pg_last_error($handle),
pg_result_error_field(pg_get_result($handle), PGSQL_DIAG_SQLSTATE)
);
}
/**
* 将数据查询的其中一行作为数组取出,其中字段名对应数组键值
*
* @param resource $resource 查询返回资源标识
* @return array
* @return array|null
*/
public function fetch($resource)
public function fetch($resource): ?array
{
return pg_fetch_assoc($resource);
return pg_fetch_assoc($resource) ?: null;
}
/**
* 将数据查询的其中一行作为对象取出,其中字段名对应对象属性
*
* @param resource $resource 查询的资源数据
* @return object
* @return object|null
*/
public function fetchObject($resource)
public function fetchObject($resource): ?object
{
return pg_fetch_object($resource);
return pg_fetch_object($resource) ?: null;
}
/**
* 合成查询语句
*
* @access public
* @param array $sql 查询对象词法数组
* @return string
* @param resource $resource
* @return array|null
*/
public function parseSelect(array $sql)
public function fetchAll($resource): array
{
if (!empty($sql['join'])) {
foreach ($sql['join'] as $val) {
[$table, $condition, $op] = $val;
$sql['table'] = "{$sql['table']} {$op} JOIN {$table} ON {$condition}";
}
}
$sql['limit'] = (0 == strlen($sql['limit'])) ? null : ' LIMIT ' . $sql['limit'];
$sql['offset'] = (0 == strlen($sql['offset'])) ? null : ' OFFSET ' . $sql['offset'];
return 'SELECT ' . $sql['fields'] . ' FROM ' . $sql['table'] .
$sql['where'] . $sql['group'] . $sql['having'] . $sql['order'] . $sql['limit'] . $sql['offset'];
return pg_fetch_all($resource, PGSQL_ASSOC);
}
/**
* 取出最后一次查询影响的行数
*
* @param resource $resource 查询的资源数据
* @param mixed $handle 连接对象
* @param resource $handle 连接对象
* @return integer
*/
public function affectedRows($resource, $handle)
public function affectedRows($resource, $handle): int
{
return pg_affected_rows($resource);
}
/**
* 取出最后一次插入返回的主键值
*
* @param resource $resource 查询的资源数据
* @param mixed $handle 连接对象
* @return integer
*/
public function lastInsertId($resource, $handle)
{
/** 查看是否存在序列,可能需要更严格的检查 */
if (pg_fetch_assoc(pg_query($handle, 'SELECT oid FROM pg_class WHERE relname = ' . $this->quoteValue($this->_lastTable . '_seq')))) {
return pg_fetch_result(pg_query($handle, 'SELECT CURRVAL(' . $this->quoteValue($this->_lastTable . '_seq') . ')'), 0, 0);
}
return 0;
}
/**
* 引号转义函数
*
* @param string $string 需要转义的字符串
* @param mixed $string 需要转义的字符串
* @return string
*/
public function quoteValue($string)
public function quoteValue($string): string
{
return '\'' . pg_escape_string($string) . '\'';
}

View File

@ -0,0 +1,167 @@
<?php
namespace Typecho\Db\Adapter;
use Typecho\Db;
trait PgsqlTrait
{
use QueryTrait;
/**
* @var array
*/
private $pk = [];
/**
* @var bool
*/
private $compatibleInsert = false;
/**
* @var string|null
*/
private $lastInsertTable = null;
/**
* 清空数据表
*
* @param string $table
* @param resource $handle 连接对象
* @throws SQLException
*/
public function truncate(string $table, $handle)
{
$this->query('TRUNCATE TABLE ' . $this->quoteColumn($table) . ' RESTART IDENTITY', $handle);
}
/**
* 合成查询语句
*
* @access public
* @param array $sql 查询对象词法数组
* @return string
*/
public function parseSelect(array $sql): string
{
return $this->buildQuery($sql);
}
/**
* 对象引号过滤
*
* @access public
* @param string $string
* @return string
*/
public function quoteColumn(string $string): string
{
return '"' . $string . '"';
}
/**
* @param string $query
* @param $handle
* @param string|null $action
* @param string|null $table
* @throws SQLException
*/
protected function prepareQuery(string &$query, $handle, ?string $action = null, ?string $table = null)
{
if (Db::INSERT == $action && !empty($table)) {
$this->compatibleInsert = false;
if (!isset($this->pk[$table])) {
$resource = $this->query("SELECT
pg_attribute.attname,
format_type(pg_attribute.atttypid, pg_attribute.atttypmod)
FROM pg_index, pg_class, pg_attribute, pg_namespace
WHERE
pg_class.oid = " . $this->quoteValue($table) . "::regclass AND
indrelid = pg_class.oid AND
nspname = 'public' AND
pg_class.relnamespace = pg_namespace.oid AND
pg_attribute.attrelid = pg_class.oid AND
pg_attribute.attnum = any(pg_index.indkey)
AND indisprimary", $handle, Db::READ, Db::SELECT, $table);
$result = $this->fetch($resource);
if (!empty($result)) {
$this->pk[$table] = $result['attname'];
}
}
// 使用兼容模式监听插入结果
if (isset($this->pk[$table])) {
$this->compatibleInsert = true;
$this->lastInsertTable = $table;
$query .= ' RETURNING ' . $this->quoteColumn($this->pk[$table]);
}
} else {
$this->lastInsertTable = null;
}
}
/**
* 取出最后一次插入返回的主键值
*
* @param resource $resource 查询的资源数据
* @param resource $handle 连接对象
* @return integer
* @throws SQLException
*/
public function lastInsertId($resource, $handle): int
{
$lastTable = $this->lastInsertTable;
if ($this->compatibleInsert) {
$result = $this->fetch($resource);
$pk = $this->pk[$lastTable];
if (!empty($result) && isset($result[$pk])) {
return (int) $result[$pk];
}
} else {
$resource = $this->query(
'SELECT oid FROM pg_class WHERE relname = '
. $this->quoteValue($lastTable . '_seq'),
$handle,
Db::READ,
Db::SELECT,
$lastTable
);
$result = $this->fetch($resource);
if (!empty($result)) {
$resource = $this->query(
'SELECT CURRVAL(' . $this->quoteValue($lastTable . '_seq') . ') AS last_insert_id',
$handle,
Db::READ,
Db::SELECT,
$lastTable
);
$result = $this->fetch($resource);
if (!empty($result)) {
return (int) $result['last_insert_id'];
}
}
}
return 0;
}
abstract public function query(
string $query,
$handle,
int $op = Db::READ,
?string $action = null,
?string $table = null
);
abstract public function quoteValue(string $string): string;
abstract public function fetch($resource): ?array;
}

View File

@ -0,0 +1,29 @@
<?php
namespace Typecho\Db\Adapter;
/**
* Build Sql
*/
trait QueryTrait
{
/**
* @param array $sql
* @return string
*/
private function buildQuery(array $sql): string
{
if (!empty($sql['join'])) {
foreach ($sql['join'] as $val) {
[$table, $condition, $op] = $val;
$sql['table'] = "{$sql['table']} {$op} JOIN {$table} ON {$condition}";
}
}
$sql['limit'] = (0 == strlen($sql['limit'])) ? null : ' LIMIT ' . $sql['limit'];
$sql['offset'] = (0 == strlen($sql['offset'])) ? null : ' OFFSET ' . $sql['offset'];
return 'SELECT ' . $sql['fields'] . ' FROM ' . $sql['table'] .
$sql['where'] . $sql['group'] . $sql['having'] . $sql['order'] . $sql['limit'] . $sql['offset'];
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace Typecho\Db\Adapter;
if (!defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
use Typecho\Db\Exception as DbException;
/**
* 数据库连接异常类
*
* @package Db
*/
class SQLException extends DbException
{
}

View File

@ -1,27 +1,23 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id: Mysql.php 103 2008-04-09 16:22:43Z magike.net $
*/
namespace Typecho\Db\Adapter;
use Typecho\Config;
use Typecho\Db;
use Typecho\Db\Adapter;
if (!defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
/**
* 数据库SQLite适配器
*
* @package Db
*/
class Typecho_Db_Adapter_SQLite implements Typecho_Db_Adapter
class SQLite implements Adapter
{
/**
* 数据库标示
*
* @access private
* @var resource
*/
private $_dbHandle;
use SQLiteTrait;
/**
* 判断适配器是否可用
@ -29,26 +25,28 @@ class Typecho_Db_Adapter_SQLite implements Typecho_Db_Adapter
* @access public
* @return boolean
*/
public static function isAvailable()
public static function isAvailable(): bool
{
return function_exists('sqlite_open');
return extension_loaded('sqlite3');
}
/**
* 数据库连接函数
*
* @param Typecho_Config $config 数据库配置
* @return resource
* @throws Typecho_Db_Exception
* @param Config $config 数据库配置
* @return \SQLite3
* @throws ConnectionException
*/
public function connect(Typecho_Config $config)
public function connect(Config $config): \SQLite3
{
if ($this->_dbHandle = sqlite_open($config->file, 0666, $error)) {
return $this->_dbHandle;
try {
$dbHandle = new \SQLite3($config->file);
$this->isSQLite2 = version_compare(\SQLite3::version()['versionString'], '3.0.0', '<');
} catch (\Exception $e) {
throw new ConnectionException($e->getMessage(), $e->getCode());
}
/** 数据库异常 */
throw new Typecho_Db_Adapter_Exception($error);
return $dbHandle;
}
/**
@ -57,135 +55,112 @@ class Typecho_Db_Adapter_SQLite implements Typecho_Db_Adapter
* @param mixed $handle
* @return string
*/
public function getVersion($handle)
public function getVersion($handle): string
{
return 'sqlite:sqlite ' . sqlite_libversion();
}
/**
* 清空数据表
*
* @param string $table
* @param mixed $handle 连接对象
* @return mixed|void
* @throws Typecho_Db_Exception
*/
public function truncate($table, $handle)
{
$this->query('DELETE FROM ' . $this->quoteColumn($table), $handle);
return 'sqlite:sqlite ' . \SQLite3::version()['versionString'];
}
/**
* 执行数据库查询
*
* @param string $query
* @param mixed $handle
* @param int $op
* @param null $action
* @param string $table 数据表
* @return resource|SQLiteResult
* @throws Typecho_Db_Query_Exception
* @param string $query 数据库查询SQL字符串
* @param \SQLite3 $handle 连接对象
* @param integer $op 数据库读写状态
* @param string|null $action 数据库动作
* @param string|null $table 数据表
* @return \SQLite3Result
* @throws SQLException
*/
public function query($query, $handle, $op = Typecho_Db::READ, $action = null, $table = null)
{
if ($resource = @sqlite_query($query, $handle)) {
return $resource;
public function query(
string $query,
$handle,
int $op = Db::READ,
?string $action = null,
?string $table = null
): \SQLite3Result {
if ($stm = $handle->prepare($query)) {
if ($resource = $stm->execute()) {
return $resource;
}
}
/** 数据库异常 */
$errorCode = sqlite_last_error($this->_dbHandle);
throw new Typecho_Db_Query_Exception(sqlite_error_string($errorCode), $errorCode);
}
/**
* 对象引号过滤
*
* @access public
* @param string $string
* @return string
*/
public function quoteColumn($string)
{
return '"' . $string . '"';
throw new SQLException($handle->lastErrorMsg(), $handle->lastErrorCode());
}
/**
* 将数据查询的其中一行作为对象取出,其中字段名对应对象属性
*
* @param resource $resource 查询的资源数据
* @return object
* @param \SQLite3Result $resource 查询的资源数据
* @return object|null
*/
public function fetchObject($resource)
public function fetchObject($resource): ?object
{
return (object)$this->fetch($resource);
$result = $this->fetch($resource);
return $result ? (object) $result : null;
}
/**
* 将数据查询的其中一行作为数组取出,其中字段名对应数组键值
*
* @param resource $resource 查询返回资源标识
* @param \SQLite3Result $resource 查询返回资源标识
* @return array|null
*/
public function fetch($resource): ?array
{
$result = $resource->fetchArray(SQLITE3_ASSOC);
return $result ? $this->filterColumnName($result) : null;
}
/**
* 将数据查询的结果作为数组全部取出,其中字段名对应数组键值
*
* @param \SQLite3Result $resource 查询的资源数据
* @return array
*/
public function fetch($resource)
public function fetchAll($resource): array
{
return Typecho_Common::filterSQLite2ColumnName(sqlite_fetch_array($resource, SQLITE_ASSOC));
$result = [];
while ($row = $this->fetch($resource)) {
$result[] = $row;
}
return $result;
}
/**
* 引号转义函数
*
* @param string $string 需要转义的字符串
* @param mixed $string 需要转义的字符串
* @return string
*/
public function quoteValue($string)
public function quoteValue($string): string
{
return '\'' . str_replace('\'', '\'\'', $string) . '\'';
}
/**
* 合成查询语句
*
* @access public
* @param array $sql 查询对象词法数组
* @return string
*/
public function parseSelect(array $sql)
{
if (!empty($sql['join'])) {
foreach ($sql['join'] as $val) {
[$table, $condition, $op] = $val;
$sql['table'] = "{$sql['table']} {$op} JOIN {$table} ON {$condition}";
}
}
$sql['limit'] = (0 == strlen($sql['limit'])) ? null : ' LIMIT ' . $sql['limit'];
$sql['offset'] = (0 == strlen($sql['offset'])) ? null : ' OFFSET ' . $sql['offset'];
return Typecho_Common::filterSQLite2CountQuery('SELECT ' . $sql['fields'] . ' FROM ' . $sql['table'] .
$sql['where'] . $sql['group'] . $sql['having'] . $sql['order'] . $sql['limit'] . $sql['offset']);
}
/**
* 取出最后一次查询影响的行数
*
* @param resource $resource 查询的资源数据
* @param mixed $handle 连接对象
* @param \SQLite3Result $resource 查询的资源数据
* @param \SQLite3 $handle 连接对象
* @return integer
*/
public function affectedRows($resource, $handle)
public function affectedRows($resource, $handle): int
{
return sqlite_changes($handle);
return $handle->changes();
}
/**
* 取出最后一次插入返回的主键值
*
* @param resource $resource 查询的资源数据
* @param mixed $handle 连接对象
* @param \SQLite3Result $resource 查询的资源数据
* @param \SQLite3 $handle 连接对象
* @return integer
*/
public function lastInsertId($resource, $handle)
public function lastInsertId($resource, $handle): int
{
return sqlite_last_insert_rowid($handle);
return $handle->lastInsertRowID();
}
}

View File

@ -0,0 +1,102 @@
<?php
namespace Typecho\Db\Adapter;
/**
* SQLite Special Util
*/
trait SQLiteTrait
{
use QueryTrait;
private $isSQLite2 = false;
/**
* 清空数据表
*
* @param string $table
* @param mixed $handle 连接对象
* @throws SQLException
*/
public function truncate(string $table, $handle)
{
$this->query('DELETE FROM ' . $this->quoteColumn($table), $handle);
}
/**
* 对象引号过滤
*
* @param string $string
* @return string
*/
public function quoteColumn(string $string): string
{
return '"' . $string . '"';
}
/**
* 过滤字段名
*
* @access private
*
* @param array $result
*
* @return array
*/
private function filterColumnName(array $result): array
{
/** 如果结果为空,直接返回 */
if (empty($result)) {
return $result;
}
$tResult = [];
/** 遍历数组 */
foreach ($result as $key => $val) {
/** 按点分隔 */
if (false !== ($pos = strpos($key, '.'))) {
$key = substr($key, $pos + 1);
}
$tResult[trim($key, '"')] = $val;
}
return $tResult;
}
/**
* 处理sqlite2的distinct count
*
* @param string $sql
*
* @return string
*/
private function filterCountQuery(string $sql): string
{
if (preg_match("/SELECT\s+COUNT\(DISTINCT\s+([^\)]+)\)\s+(AS\s+[^\s]+)?\s*FROM\s+(.+)/is", $sql, $matches)) {
return 'SELECT COUNT(' . $matches[1] . ') ' . $matches[2] . ' FROM SELECT DISTINCT '
. $matches[1] . ' FROM ' . $matches[3];
}
return $sql;
}
/**
* 合成查询语句
*
* @access public
* @param array $sql 查询对象词法数组
* @return string
*/
public function parseSelect(array $sql): string
{
$query = $this->filterCountQuery($this->buildQuery($sql));
if ($this->isSQLite2) {
$query = $this->filterCountQuery($query);
}
return $query;
}
}

View File

@ -1,17 +1,18 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id: DbException.php 52 2008-03-18 08:04:01Z magike.net $
*/
namespace Typecho\Db;
if (!defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
use Typecho\Exception as TypechoException;
/**
* 数据库异常类
*
* @package Db
*/
class Typecho_Db_Exception extends Typecho_Exception
{}
class Exception extends TypechoException
{
}

View File

@ -1,16 +1,13 @@
<?php
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id: DbQuery.php 97 2008-04-04 04:39:54Z magike.net $
*/
namespace Typecho\Db;
use Typecho\Db;
/**
* Typecho数据库查询语句构建类
* 使用方法:
* $query = new Typecho_Db_Query(); //或者使用DB积累的sql方法返回实例化对象
* $query = new Query(); //或者使用DB积累的sql方法返回实例化对象
* $query->select('posts', 'post_id, post_title')
* ->where('post_id = %d', 1)
* ->limit(1);
@ -21,10 +18,10 @@
*
* @package Db
*/
class Typecho_Db_Query
class Query
{
/** 数据库关键字 */
const KEYWORDS = '*PRIMARY|AND|OR|LIKE|BINARY|BY|DISTINCT|AS|IN|IS|NULL';
private const KEYWORDS = '*PRIMARY|AND|OR|LIKE|BINARY|BY|DISTINCT|AS|IN|IS|NULL';
/**
* 默认字段
@ -32,7 +29,7 @@ class Typecho_Db_Query
* @var array
* @access private
*/
private static $_default = [
private static $default = [
'action' => null,
'table' => null,
'fields' => '*',
@ -49,16 +46,16 @@ class Typecho_Db_Query
/**
* 数据库适配器
*
* @var Typecho_Db_Adapter
* @var Adapter
*/
private $_adapter;
private $adapter;
/**
* 查询语句预结构,由数组构成,方便组合为SQL查询字符串
*
* @var array
*/
private $_sqlPreBuild;
private $sqlPreBuild;
/**
* 前缀
@ -66,25 +63,25 @@ class Typecho_Db_Query
* @access private
* @var string
*/
private $_prefix;
private $prefix;
/**
* @var array
*/
private $_params = [];
private $params = [];
/**
* 构造函数,引用数据库适配器作为内部数据
*
* @param Typecho_Db_Adapter $adapter 数据库适配器
* @param Adapter $adapter 数据库适配器
* @param string $prefix 前缀
*/
public function __construct(Typecho_Db_Adapter $adapter, $prefix)
public function __construct(Adapter $adapter, string $prefix)
{
$this->_adapter = &$adapter;
$this->_prefix = $prefix;
$this->adapter = &$adapter;
$this->prefix = $prefix;
$this->_sqlPreBuild = self::$_default;
$this->sqlPreBuild = self::$default;
}
/**
@ -94,7 +91,7 @@ class Typecho_Db_Query
*/
public static function setDefault(array $default)
{
self::$_default = array_merge(self::$_default, $default);
self::$default = array_merge(self::$default, $default);
}
/**
@ -102,9 +99,9 @@ class Typecho_Db_Query
*
* @return array
*/
public function getParams()
public function getParams(): array
{
return $this->_params;
return $this->params;
}
/**
@ -114,9 +111,9 @@ class Typecho_Db_Query
* @param string $attributeName 属性名称
* @return string
*/
public function getAttribute($attributeName)
public function getAttribute(string $attributeName): ?string
{
return $this->_sqlPreBuild[$attributeName] ?? null;
return $this->sqlPreBuild[$attributeName] ?? null;
}
/**
@ -124,12 +121,12 @@ class Typecho_Db_Query
*
* @access public
* @param string $attributeName 属性名称
* @return Typecho_Db_Query
* @return Query
*/
public function cleanAttribute($attributeName)
public function cleanAttribute(string $attributeName): Query
{
if (isset($this->_sqlPreBuild[$attributeName])) {
$this->_sqlPreBuild[$attributeName] = self::$_default[$attributeName];
if (isset($this->sqlPreBuild[$attributeName])) {
$this->sqlPreBuild[$attributeName] = self::$default[$attributeName];
}
return $this;
}
@ -140,11 +137,11 @@ class Typecho_Db_Query
* @param string $table 需要连接的表
* @param string $condition 连接条件
* @param string $op 连接方法(LEFT, RIGHT, INNER)
* @return Typecho_Db_Query
* @return Query
*/
public function join($table, $condition, $op = Typecho_Db::INNER_JOIN)
public function join(string $table, string $condition, string $op = Db::INNER_JOIN): Query
{
$this->_sqlPreBuild['join'][] = [$this->filterPrefix($table), $this->filterColumn($condition), $op];
$this->sqlPreBuild['join'][] = [$this->filterPrefix($table), $this->filterColumn($condition), $op];
return $this;
}
@ -154,9 +151,9 @@ class Typecho_Db_Query
* @param string $string 需要解析的字符串
* @return string
*/
private function filterPrefix($string)
private function filterPrefix(string $string): string
{
return (0 === strpos($string, 'table.')) ? substr_replace($string, $this->_prefix, 0, 6) : $string;
return (0 === strpos($string, 'table.')) ? substr_replace($string, $this->prefix, 0, 6) : $string;
}
/**
@ -166,7 +163,7 @@ class Typecho_Db_Query
* @param string $str 待处理字段值
* @return string
*/
private function filterColumn($str)
private function filterColumn(string $str): string
{
$str = $str . ' 0';
$length = strlen($str);
@ -176,16 +173,18 @@ class Typecho_Db_Query
$split = '';
$quotes = 0;
for ($i = 0; $i < $length; $i ++) {
for ($i = 0; $i < $length; $i++) {
$cha = $str[$i];
if (ctype_alnum($cha) || false !== strpos('_*', $cha)) {
if (!$lastIsAlnum) {
if ($quotes > 0 && !ctype_digit($word) && '.' != $split
&& false === strpos(self::KEYWORDS, strtoupper($word))) {
$word = $this->_adapter->quoteColumn($word);
if (
$quotes > 0 && !ctype_digit($word) && '.' != $split
&& false === strpos(self::KEYWORDS, strtoupper($word))
) {
$word = $this->adapter->quoteColumn($word);
} elseif ('.' == $split && 'table' == $word) {
$word = $this->_prefix;
$word = $this->prefix;
$split = '';
}
@ -197,9 +196,7 @@ class Typecho_Db_Query
$word .= $cha;
$lastIsAlnum = true;
} else {
if ($lastIsAlnum) {
if (0 == $quotes) {
if (false !== strpos(' ,)=<>.+-*/', $cha)) {
$quotes = 1;
@ -226,17 +223,17 @@ class Typecho_Db_Query
* @param ...$args
* @return $this
*/
public function where(...$args)
public function where(...$args): Query
{
[$condition] = $args;
$condition = str_replace('?', "%s", $this->filterColumn($condition));
$operator = empty($this->_sqlPreBuild['where']) ? ' WHERE ' : ' AND';
$operator = empty($this->sqlPreBuild['where']) ? ' WHERE ' : ' AND';
if (count($args) <= 1) {
$this->_sqlPreBuild['where'] .= $operator . ' (' . $condition . ')';
$this->sqlPreBuild['where'] .= $operator . ' (' . $condition . ')';
} else {
array_shift($args);
$this->_sqlPreBuild['where'] .= $operator . ' (' . vsprintf($condition, $this->quoteValues($args)) . ')';
$this->sqlPreBuild['where'] .= $operator . ' (' . vsprintf($condition, $this->quoteValues($args)) . ')';
}
return $this;
@ -249,7 +246,7 @@ class Typecho_Db_Query
* @access protected
* @return array
*/
protected function quoteValues(array $values)
protected function quoteValues(array $values): array
{
foreach ($values as &$value) {
if (is_array($value)) {
@ -268,29 +265,29 @@ class Typecho_Db_Query
* @param $value
* @return string
*/
public function quoteValue($value)
public function quoteValue($value): string
{
$this->_params[] = $value;
return '#param:' . (count($this->_params) - 1) . '#';
$this->params[] = $value;
return '#param:' . (count($this->params) - 1) . '#';
}
/**
* OR条件查询语句
*
* @param ...$args
* @return Typecho_Db_Query
* @return Query
*/
public function orWhere(...$args)
public function orWhere(...$args): Query
{
[$condition] = $args;
$condition = str_replace('?', "%s", $this->filterColumn($condition));
$operator = empty($this->_sqlPreBuild['where']) ? ' WHERE ' : ' OR';
$operator = empty($this->sqlPreBuild['where']) ? ' WHERE ' : ' OR';
if (func_num_args() <= 1) {
$this->_sqlPreBuild['where'] .= $operator . ' (' . $condition . ')';
$this->sqlPreBuild['where'] .= $operator . ' (' . $condition . ')';
} else {
array_shift($args);
$this->_sqlPreBuild['where'] .= $operator . ' (' . vsprintf($condition, $this->quoteValues($args)) . ')';
$this->sqlPreBuild['where'] .= $operator . ' (' . vsprintf($condition, $this->quoteValues($args)) . ')';
}
return $this;
@ -299,39 +296,39 @@ class Typecho_Db_Query
/**
* 查询行数限制
*
* @param integer $limit 需要查询的行数
* @return Typecho_Db_Query
* @param mixed $limit 需要查询的行数
* @return Query
*/
public function limit($limit)
public function limit($limit): Query
{
$this->_sqlPreBuild['limit'] = intval($limit);
$this->sqlPreBuild['limit'] = intval($limit);
return $this;
}
/**
* 查询行数偏移量
*
* @param integer $offset 需要偏移的行数
* @return Typecho_Db_Query
* @param mixed $offset 需要偏移的行数
* @return Query
*/
public function offset($offset)
public function offset($offset): Query
{
$this->_sqlPreBuild['offset'] = intval($offset);
$this->sqlPreBuild['offset'] = intval($offset);
return $this;
}
/**
* 分页查询
*
* @param integer $page 页数
* @param integer $pageSize 每页行数
* @return Typecho_Db_Query
* @param mixed $page 页数
* @param mixed $pageSize 每页行数
* @return Query
*/
public function page($page, $pageSize)
public function page($page, $pageSize): Query
{
$pageSize = intval($pageSize);
$this->_sqlPreBuild['limit'] = $pageSize;
$this->_sqlPreBuild['offset'] = (max(intval($page), 1) - 1) * $pageSize;
$this->sqlPreBuild['limit'] = $pageSize;
$this->sqlPreBuild['offset'] = (max(intval($page), 1) - 1) * $pageSize;
return $this;
}
@ -339,12 +336,13 @@ class Typecho_Db_Query
* 指定需要写入的栏目及其值
*
* @param array $rows
* @return Typecho_Db_Query
* @return Query
*/
public function rows(array $rows)
public function rows(array $rows): Query
{
foreach ($rows as $key => $row) {
$this->_sqlPreBuild['rows'][$this->filterColumn($key)] = is_null($row) ? 'NULL' : $this->_adapter->quoteValue($row);
$this->sqlPreBuild['rows'][$this->filterColumn($key)]
= is_null($row) ? 'NULL' : $this->adapter->quoteValue($row);
}
return $this;
}
@ -356,30 +354,30 @@ class Typecho_Db_Query
* @param string $key 栏目名称
* @param mixed $value 指定的值
* @param bool $escape 是否转义
* @return Typecho_Db_Query
* @return Query
*/
public function expression($key, $value, $escape = true)
public function expression(string $key, $value, bool $escape = true): Query
{
$this->_sqlPreBuild['rows'][$this->filterColumn($key)] = $escape ? $this->filterColumn($value) : $value;
$this->sqlPreBuild['rows'][$this->filterColumn($key)] = $escape ? $this->filterColumn($value) : $value;
return $this;
}
/**
* 排序顺序(ORDER BY)
*
* @param string $orderby 排序的索引
* @param string $orderBy 排序的索引
* @param string $sort 排序的方式(ASC, DESC)
* @return Typecho_Db_Query
* @return Query
*/
public function order($orderby, $sort = Typecho_Db::SORT_ASC)
public function order(string $orderBy, string $sort = Db::SORT_ASC): Query
{
if (empty($this->_sqlPreBuild['order'])) {
$this->_sqlPreBuild['order'] = ' ORDER BY ';
if (empty($this->sqlPreBuild['order'])) {
$this->sqlPreBuild['order'] = ' ORDER BY ';
} else {
$this->_sqlPreBuild['order'] .= ', ';
$this->sqlPreBuild['order'] .= ', ';
}
$this->_sqlPreBuild['order'] .= $this->filterColumn($orderby) . (empty($sort) ? null : ' ' . $sort);
$this->sqlPreBuild['order'] .= $this->filterColumn($orderBy) . (empty($sort) ? null : ' ' . $sort);
return $this;
}
@ -387,31 +385,28 @@ class Typecho_Db_Query
* 集合聚集(GROUP BY)
*
* @param string $key 聚集的键值
* @return Typecho_Db_Query
* @return Query
*/
public function group($key)
public function group(string $key): Query
{
$this->_sqlPreBuild['group'] = ' GROUP BY ' . $this->filterColumn($key);
$this->sqlPreBuild['group'] = ' GROUP BY ' . $this->filterColumn($key);
return $this;
}
/**
* HAVING (HAVING)
*
* @return Typecho_Db_Query
* @param string $condition
* @param ...$args
* @return $this
*/
public function having()
public function having(string $condition, ...$args): Query
{
$condition = func_get_arg(0);
$condition = str_replace('?', "%s", $this->filterColumn($condition));
$operator = empty($this->_sqlPreBuild['having']) ? ' HAVING ' : ' AND';
$operator = empty($this->sqlPreBuild['having']) ? ' HAVING ' : ' AND';
if (func_num_args() <= 1) {
$this->_sqlPreBuild['having'] .= $operator . ' (' . $condition . ')';
if (count($args) == 0) {
$this->sqlPreBuild['having'] .= $operator . ' (' . $condition . ')';
} else {
$args = func_get_args();
array_shift($args);
$this->_sqlPreBuild['having'] .= $operator . ' (' . vsprintf($condition, $this->quoteValues($args)) . ')';
$this->sqlPreBuild['having'] .= $operator . ' (' . vsprintf($condition, $this->quoteValues($args)) . ')';
}
return $this;
@ -423,11 +418,11 @@ class Typecho_Db_Query
* @param mixed ...$args 查询字段
* @return $this
*/
public function select(...$args): Typecho_Db_Query
public function select(...$args): Query
{
$this->_sqlPreBuild['action'] = Typecho_Db::SELECT;
$this->sqlPreBuild['action'] = Db::SELECT;
$this->_sqlPreBuild['fields'] = $this->getColumnFromParameters($args);
$this->sqlPreBuild['fields'] = $this->getColumnFromParameters($args);
return $this;
}
@ -438,7 +433,7 @@ class Typecho_Db_Query
* @param array $parameters
* @return string
*/
private function getColumnFromParameters(array $parameters)
private function getColumnFromParameters(array $parameters): string
{
$fields = [];
@ -459,11 +454,11 @@ class Typecho_Db_Query
* 查询记录操作(SELECT)
*
* @param string $table 查询的表
* @return Typecho_Db_Query
* @return Query
*/
public function from($table)
public function from(string $table): Query
{
$this->_sqlPreBuild['table'] = $this->filterPrefix($table);
$this->sqlPreBuild['table'] = $this->filterPrefix($table);
return $this;
}
@ -471,12 +466,12 @@ class Typecho_Db_Query
* 更新记录操作(UPDATE)
*
* @param string $table 需要更新记录的表
* @return Typecho_Db_Query
* @return Query
*/
public function update($table)
public function update(string $table): Query
{
$this->_sqlPreBuild['action'] = Typecho_Db::UPDATE;
$this->_sqlPreBuild['table'] = $this->filterPrefix($table);
$this->sqlPreBuild['action'] = Db::UPDATE;
$this->sqlPreBuild['table'] = $this->filterPrefix($table);
return $this;
}
@ -484,12 +479,12 @@ class Typecho_Db_Query
* 删除记录操作(DELETE)
*
* @param string $table 需要删除记录的表
* @return Typecho_Db_Query
* @return Query
*/
public function delete($table)
public function delete(string $table): Query
{
$this->_sqlPreBuild['action'] = Typecho_Db::DELETE;
$this->_sqlPreBuild['table'] = $this->filterPrefix($table);
$this->sqlPreBuild['action'] = Db::DELETE;
$this->sqlPreBuild['table'] = $this->filterPrefix($table);
return $this;
}
@ -497,23 +492,23 @@ class Typecho_Db_Query
* 插入记录操作(INSERT)
*
* @param string $table 需要插入记录的表
* @return Typecho_Db_Query
* @return Query
*/
public function insert($table)
public function insert(string $table): Query
{
$this->_sqlPreBuild['action'] = Typecho_Db::INSERT;
$this->_sqlPreBuild['table'] = $this->filterPrefix($table);
$this->sqlPreBuild['action'] = Db::INSERT;
$this->sqlPreBuild['table'] = $this->filterPrefix($table);
return $this;
}
/**
* @param $query
* @param string $query
* @return string
*/
public function prepare($query)
public function prepare(string $query): string
{
$params = $this->_params;
$adapter = $this->_adapter;
$params = $this->params;
$adapter = $this->adapter;
return preg_replace_callback("/#param:([0-9]+)#/", function ($matches) use ($params, $adapter) {
if (array_key_exists($matches[1], $params)) {
@ -531,32 +526,32 @@ class Typecho_Db_Query
*/
public function __toString()
{
switch ($this->_sqlPreBuild['action']) {
case Typecho_Db::SELECT:
return $this->_adapter->parseSelect($this->_sqlPreBuild);
case Typecho_Db::INSERT:
switch ($this->sqlPreBuild['action']) {
case Db::SELECT:
return $this->adapter->parseSelect($this->sqlPreBuild);
case Db::INSERT:
return 'INSERT INTO '
. $this->_sqlPreBuild['table']
. '(' . implode(' , ', array_keys($this->_sqlPreBuild['rows'])) . ')'
. $this->sqlPreBuild['table']
. '(' . implode(' , ', array_keys($this->sqlPreBuild['rows'])) . ')'
. ' VALUES '
. '(' . implode(' , ', array_values($this->_sqlPreBuild['rows'])) . ')'
. $this->_sqlPreBuild['limit'];
case Typecho_Db::DELETE:
. '(' . implode(' , ', array_values($this->sqlPreBuild['rows'])) . ')'
. $this->sqlPreBuild['limit'];
case Db::DELETE:
return 'DELETE FROM '
. $this->_sqlPreBuild['table']
. $this->_sqlPreBuild['where'];
case Typecho_Db::UPDATE:
. $this->sqlPreBuild['table']
. $this->sqlPreBuild['where'];
case Db::UPDATE:
$columns = [];
if (isset($this->_sqlPreBuild['rows'])) {
foreach ($this->_sqlPreBuild['rows'] as $key => $val) {
if (isset($this->sqlPreBuild['rows'])) {
foreach ($this->sqlPreBuild['rows'] as $key => $val) {
$columns[] = "$key = $val";
}
}
return 'UPDATE '
. $this->_sqlPreBuild['table']
. $this->sqlPreBuild['table']
. ' SET ' . implode(' , ', $columns)
. $this->_sqlPreBuild['where'];
. $this->sqlPreBuild['where'];
default:
return null;
}

View File

@ -1,17 +1,18 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id: DbException.php 52 2008-03-18 08:04:01Z magike.net $
*/
namespace Typecho\Db\Query;
if (!defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
use Typecho\Db\Exception as DbException;
/**
* 数据库查询异常类
*
* @package Db
*/
class Typecho_Db_Query_Exception extends Typecho_Db_Exception
{}
class Exception extends DbException
{
}

View File

@ -1,11 +1,6 @@
<?php
/**
* Typecho Blog Platform
*
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id: Exception.php 106 2008-04-11 02:23:54Z magike.net $
*/
namespace Typecho;
/**
* Typecho异常基类
@ -13,7 +8,7 @@
*
* @package Exception
*/
class Typecho_Exception extends Exception
class Exception extends \Exception
{
public function __construct($message, $code = 0)

View File

@ -1,43 +1,31 @@
<?php
/**
* 格式化聚合XML数据,整合自Univarsel Feed Writer
*
* @author Anis uddin Ahmad <anisniit@gmail.com>
* @category typecho
* @package Feed
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id: Feed.php 219 2008-05-27 09:06:15Z magike.net $
*/
namespace Typecho;
/**
* Typecho_Feed
* Feed
*
* @author qining
* @category typecho
* @package Feed
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
*/
class Typecho_Feed
class Feed
{
/** 定义RSS 1.0类型 */
const RSS1 = 'RSS 1.0';
public const RSS1 = 'RSS 1.0';
/** 定义RSS 2.0类型 */
const RSS2 = 'RSS 2.0';
public const RSS2 = 'RSS 2.0';
/** 定义ATOM 1.0类型 */
const ATOM1 = 'ATOM 1.0';
public const ATOM1 = 'ATOM 1.0';
/** 定义RSS时间格式 */
const DATE_RFC822 = 'r';
public const DATE_RFC822 = 'r';
/** 定义ATOM时间格式 */
const DATE_W3CDTF = 'c';
public const DATE_W3CDTF = 'c';
/** 定义行结束符 */
const EOL = "\n";
public const EOL = "\n";
/**
* feed状态
@ -45,7 +33,7 @@ class Typecho_Feed
* @access private
* @var string
*/
private $_type;
private $type;
/**
* 字符集编码
@ -53,7 +41,7 @@ class Typecho_Feed
* @access private
* @var string
*/
private $_charset;
private $charset;
/**
* 语言状态
@ -61,7 +49,7 @@ class Typecho_Feed
* @access private
* @var string
*/
private $_lang;
private $lang;
/**
* 聚合地址
@ -69,7 +57,7 @@ class Typecho_Feed
* @access private
* @var string
*/
private $_feedUrl;
private $feedUrl;
/**
* 基本地址
@ -77,7 +65,7 @@ class Typecho_Feed
* @access private
* @var string
*/
private $_baseUrl;
private $baseUrl;
/**
* 聚合标题
@ -85,7 +73,7 @@ class Typecho_Feed
* @access private
* @var string
*/
private $_title;
private $title;
/**
* 聚合副标题
@ -93,7 +81,7 @@ class Typecho_Feed
* @access private
* @var string
*/
private $_subTitle;
private $subTitle;
/**
* 版本信息
@ -101,7 +89,7 @@ class Typecho_Feed
* @access private
* @var string
*/
private $_version;
private $version;
/**
* 所有的items
@ -109,76 +97,62 @@ class Typecho_Feed
* @access private
* @var array
*/
private $_items = [];
private $items = [];
/**
* 创建Feed对象
*
* @access public
* @return void
* @param $version
* @param string $type
* @param string $charset
* @param string $lang
*/
public function __construct($version, $type = self::RSS2, $charset = 'UTF-8', $lang = 'en')
public function __construct($version, string $type = self::RSS2, string $charset = 'UTF-8', string $lang = 'en')
{
$this->_version = $version;
$this->_type = $type;
$this->_charset = $charset;
$this->_lang = $lang;
$this->version = $version;
$this->type = $type;
$this->charset = $charset;
$this->lang = $lang;
}
/**
* 设置标题
*
* @access public
*
* @param string $title 标题
*
* @return void
*/
public function setTitle(string $title)
{
$this->_title = $title;
$this->title = $title;
}
/**
* 设置副标题
*
* @access public
*
* @param string $subTitle 副标题
*
* @return void
* @param string|null $subTitle 副标题
*/
public function setSubTitle(string $subTitle)
public function setSubTitle(?string $subTitle)
{
$this->_subTitle = $subTitle;
$this->subTitle = $subTitle;
}
/**
* 设置聚合地址
*
* @access public
*
* @param string $feedUrl 聚合地址
*
* @return void
*/
public function setFeedUrl(string $feedUrl)
{
$this->_feedUrl = $feedUrl;
$this->feedUrl = $feedUrl;
}
/**
* 设置主页
*
* @access public
*
* @param string $baseUrl 主页地址
*
* @return void
*/
public function setBaseUrl(string $baseUrl)
{
$this->_baseUrl = $baseUrl;
$this->baseUrl = $baseUrl;
}
/**
@ -197,26 +171,23 @@ class Typecho_Feed
* )
* </code>
*
* @access public
*
* @param array $item
*/
public function addItem(array $item)
{
$this->_items[] = $item;
$this->items[] = $item;
}
/**
* 输出字符串
*
* @access public
* @return string
*/
public function __toString()
public function __toString(): string
{
$result = '<?xml version="1.0" encoding="' . $this->_charset . '"?>' . self::EOL;
$result = '<?xml version="1.0" encoding="' . $this->charset . '"?>' . self::EOL;
if (self::RSS1 == $this->_type) {
if (self::RSS1 == $this->type) {
$result .= '<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://purl.org/rss/1.0/"
@ -226,7 +197,7 @@ xmlns:dc="http://purl.org/dc/elements/1.1/">' . self::EOL;
$links = [];
$lastUpdate = 0;
foreach ($this->_items as $item) {
foreach ($this->items as $item) {
$content .= '<item rdf:about="' . $item['link'] . '">' . self::EOL;
$content .= '<title>' . htmlspecialchars($item['title']) . '</title>' . self::EOL;
$content .= '<link>' . $item['link'] . '</link>' . self::EOL;
@ -244,10 +215,10 @@ xmlns:dc="http://purl.org/dc/elements/1.1/">' . self::EOL;
}
}
$result .= '<channel rdf:about="' . $this->_feedUrl . '">
<title>' . htmlspecialchars($this->_title) . '</title>
<link>' . $this->_baseUrl . '</link>
<description>' . htmlspecialchars($this->_subTitle) . '</description>
$result .= '<channel rdf:about="' . $this->feedUrl . '">
<title>' . htmlspecialchars($this->title) . '</title>
<link>' . $this->baseUrl . '</link>
<description>' . htmlspecialchars($this->subTitle) . '</description>
<items>
<rdf:Seq>' . self::EOL;
@ -260,8 +231,7 @@ xmlns:dc="http://purl.org/dc/elements/1.1/">' . self::EOL;
</channel>' . self::EOL;
$result .= $content . '</rdf:RDF>';
} else if (self::RSS2 == $this->_type) {
} elseif (self::RSS2 == $this->type) {
$result .= '<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
@ -273,13 +243,14 @@ xmlns:wfw="http://wellformedweb.org/CommentAPI/">
$content = '';
$lastUpdate = 0;
foreach ($this->_items as $item) {
foreach ($this->items as $item) {
$content .= '<item>' . self::EOL;
$content .= '<title>' . htmlspecialchars($item['title']) . '</title>' . self::EOL;
$content .= '<link>' . $item['link'] . '</link>' . self::EOL;
$content .= '<guid>' . $item['link'] . '</guid>' . self::EOL;
$content .= '<pubDate>' . $this->dateFormat($item['date']) . '</pubDate>' . self::EOL;
$content .= '<dc:creator>' . htmlspecialchars($item['author']->screenName) . '</dc:creator>' . self::EOL;
$content .= '<dc:creator>' . htmlspecialchars($item['author']->screenName)
. '</dc:creator>' . self::EOL;
if (!empty($item['category']) && is_array($item['category'])) {
foreach ($item['category'] as $category) {
@ -288,11 +259,12 @@ xmlns:wfw="http://wellformedweb.org/CommentAPI/">
}
if (!empty($item['excerpt'])) {
$content .= '<description><![CDATA[' . strip_tags($item['excerpt']) . ']]></description>' . self::EOL;
$content .= '<description><![CDATA[' . strip_tags($item['excerpt'])
. ']]></description>' . self::EOL;
}
if (!empty($item['content'])) {
$content .= '<content:encoded xml:lang="' . $this->_lang . '"><![CDATA['
$content .= '<content:encoded xml:lang="' . $this->lang . '"><![CDATA['
. self::EOL .
$item['content'] . self::EOL .
']]></content:encoded>' . self::EOL;
@ -318,28 +290,27 @@ xmlns:wfw="http://wellformedweb.org/CommentAPI/">
}
}
$result .= '<title>' . htmlspecialchars($this->_title) . '</title>
<link>' . $this->_baseUrl . '</link>
<atom:link href="' . $this->_feedUrl . '" rel="self" type="application/rss+xml" />
<language>' . $this->_lang . '</language>
<description>' . htmlspecialchars($this->_subTitle) . '</description>
$result .= '<title>' . htmlspecialchars($this->title) . '</title>
<link>' . $this->baseUrl . '</link>
<atom:link href="' . $this->feedUrl . '" rel="self" type="application/rss+xml" />
<language>' . $this->lang . '</language>
<description>' . htmlspecialchars($this->subTitle) . '</description>
<lastBuildDate>' . $this->dateFormat($lastUpdate) . '</lastBuildDate>
<pubDate>' . $this->dateFormat($lastUpdate) . '</pubDate>' . self::EOL;
$result .= $content . '</channel>
</rss>';
} else if (self::ATOM1 == $this->_type) {
} elseif (self::ATOM1 == $this->type) {
$result .= '<feed xmlns="http://www.w3.org/2005/Atom"
xmlns:thr="http://purl.org/syndication/thread/1.0"
xml:lang="' . $this->_lang . '"
xml:base="' . $this->_baseUrl . '"
xml:lang="' . $this->lang . '"
xml:base="' . $this->baseUrl . '"
>' . self::EOL;
$content = '';
$lastUpdate = 0;
foreach ($this->_items as $item) {
foreach ($this->items as $item) {
$content .= '<entry>' . self::EOL;
$content .= '<title type="html"><![CDATA[' . $item['title'] . ']]></title>' . self::EOL;
$content .= '<link rel="alternate" type="text/html" href="' . $item['link'] . '" />' . self::EOL;
@ -353,26 +324,31 @@ xml:base="' . $this->_baseUrl . '"
if (!empty($item['category']) && is_array($item['category'])) {
foreach ($item['category'] as $category) {
$content .= '<category scheme="' . $category['permalink'] . '" term="' . $category['name'] . '" />' . self::EOL;
$content .= '<category scheme="' . $category['permalink'] . '" term="'
. $category['name'] . '" />' . self::EOL;
}
}
if (!empty($item['excerpt'])) {
$content .= '<summary type="html"><![CDATA[' . htmlspecialchars($item['excerpt']) . ']]></summary>' . self::EOL;
$content .= '<summary type="html"><![CDATA[' . htmlspecialchars($item['excerpt'])
. ']]></summary>' . self::EOL;
}
if (!empty($item['content'])) {
$content .= '<content type="html" xml:base="' . $item['link'] . '" xml:lang="' . $this->_lang . '"><![CDATA['
$content .= '<content type="html" xml:base="' . $item['link']
. '" xml:lang="' . $this->lang . '"><![CDATA['
. self::EOL .
$item['content'] . self::EOL .
']]></content>' . self::EOL;
}
if (isset($item['comments']) && strlen($item['comments']) > 0) {
$content .= '<link rel="replies" type="text/html" href="' . $item['link'] . '#comments" thr:count="' . $item['comments'] . '" />' . self::EOL;
$content .= '<link rel="replies" type="text/html" href="' . $item['link']
. '#comments" thr:count="' . $item['comments'] . '" />' . self::EOL;
if (!empty($item['commentsFeedUrl'])) {
$content .= '<link rel="replies" type="application/atom+xml" href="' . $item['commentsFeedUrl'] . '" thr:count="' . $item['comments'] . '"/>' . self::EOL;
$content .= '<link rel="replies" type="application/atom+xml" href="'
. $item['commentsFeedUrl'] . '" thr:count="' . $item['comments'] . '"/>' . self::EOL;
}
}
@ -387,13 +363,13 @@ xml:base="' . $this->_baseUrl . '"
}
}
$result .= '<title type="text">' . htmlspecialchars($this->_title) . '</title>
<subtitle type="text">' . htmlspecialchars($this->_subTitle) . '</subtitle>
$result .= '<title type="text">' . htmlspecialchars($this->title) . '</title>
<subtitle type="text">' . htmlspecialchars($this->subTitle) . '</subtitle>
<updated>' . $this->dateFormat($lastUpdate) . '</updated>
<generator uri="http://typecho.org/" version="' . $this->_version . '">Typecho</generator>
<link rel="alternate" type="text/html" href="' . $this->_baseUrl . '" />
<id>' . $this->_feedUrl . '</id>
<link rel="self" type="application/atom+xml" href="' . $this->_feedUrl . '" />
<generator uri="http://typecho.org/" version="' . $this->version . '">Typecho</generator>
<link rel="alternate" type="text/html" href="' . $this->baseUrl . '" />
<id>' . $this->feedUrl . '</id>
<link rel="self" type="application/atom+xml" href="' . $this->feedUrl . '" />
';
$result .= $content . '</feed>';
}
@ -404,18 +380,17 @@ xml:base="' . $this->_baseUrl . '"
/**
* 获取Feed时间格式
*
* @access public
*
* @param integer $stamp 时间戳
*
* @return string
*/
public function dateFormat(int $stamp): string
{
if (self::RSS2 == $this->_type) {
if (self::RSS2 == $this->type) {
return date(self::DATE_RFC822, $stamp);
} else if (self::RSS1 == $this->_type || self::ATOM1 == $this->_type) {
} elseif (self::RSS1 == $this->type || self::ATOM1 == $this->type) {
return date(self::DATE_W3CDTF, $stamp);
}
return '';
}
}

View File

@ -1,14 +1,8 @@
<?php
/**
* Http客户端
*
* @author qining
* @category typecho
* @package Http
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id$
*/
namespace Typecho\Http;
use Typecho\Http\Client\Adapter;
/**
* Http客户端
@ -17,39 +11,29 @@
* @category typecho
* @package Http
*/
class Typecho_Http_Client
class Client
{
/** POST方法 */
const METHOD_POST = 'POST';
public const METHOD_POST = 'POST';
/** GET方法 */
const METHOD_GET = 'GET';
public const METHOD_GET = 'GET';
/** 定义行结束符 */
const EOL = "\r\n";
public const EOL = "\r\n";
private const ADAPTERS = [Adapter\Curl::class, Adapter\Socket::class];
/**
* 获取可用的连接
*
* @access public
* @return ?Typecho_Http_Client_Adapter
* @return ?Adapter
*/
public static function get(): ?Typecho_Http_Client_Adapter
public static function get(): ?Adapter
{
$adapters = func_get_args();
if (empty($adapters)) {
$adapters = [];
$adapterFiles = glob(dirname(__FILE__) . '/Client/Adapter/*.php');
foreach ($adapterFiles as $file) {
$adapters[] = substr(basename($file), 0, - 4);
}
}
foreach ($adapters as $adapter) {
$adapterName = 'Typecho_Http_Client_Adapter_' . $adapter;
if (Typecho_Common::isAvailableClass($adapterName) && call_user_func([$adapterName, 'isAvailable'])) {
return new $adapterName();
foreach (self::ADAPTERS as $adapter) {
if (call_user_func([$adapter, 'isAvailable'])) {
return new $adapter();
}
}

View File

@ -1,14 +1,9 @@
<?php
/**
* 客户端适配器
*
* @author qining
* @category typecho
* @package Http
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id$
*/
namespace Typecho\Http\Client;
use Typecho\Common;
use Typecho\Http\Client;
/**
* 客户端适配器
@ -17,7 +12,7 @@
* @category typecho
* @package Http
*/
abstract class Typecho_Http_Client_Adapter
abstract class Adapter
{
/**
* 方法名
@ -25,7 +20,7 @@ abstract class Typecho_Http_Client_Adapter
* @access protected
* @var string
*/
protected $method = Typecho_Http_Client::METHOD_GET;
protected $method = Client::METHOD_GET;
/**
* 传递参数
@ -47,7 +42,7 @@ abstract class Typecho_Http_Client_Adapter
* 需要在body中传递的值
*
* @access protected
* @var array
* @var array|string
*/
protected $data = [];
@ -161,10 +156,7 @@ abstract class Typecho_Http_Client_Adapter
* @access public
* @return boolean
*/
public static function isAvailable()
{
return true;
}
abstract public static function isAvailable(): bool;
/**
* 设置指定的COOKIE值
@ -172,9 +164,9 @@ abstract class Typecho_Http_Client_Adapter
* @access public
* @param string $key 指定的参数
* @param mixed $value 设置的值
* @return Typecho_Http_Client_Adapter
* @return $this
*/
public function setCookie($key, $value)
public function setCookie(string $key, $value): Adapter
{
$this->cookies[$key] = $value;
return $this;
@ -185,9 +177,9 @@ abstract class Typecho_Http_Client_Adapter
*
* @access public
* @param mixed $query 传递参数
* @return Typecho_Http_Client_Adapter
* @return $this
*/
public function setQuery($query)
public function setQuery($query): Adapter
{
$query = is_array($query) ? http_build_query($query) : $query;
$this->query = empty($this->query) ? $query : $this->query . '&' . $query;
@ -198,13 +190,13 @@ abstract class Typecho_Http_Client_Adapter
* 设置需要POST的数据
*
* @access public
* @param array $data 需要POST的数据
* @return Typecho_Http_Client_Adapter
* @param array|string $data 需要POST的数据
* @return $this
*/
public function setData($data)
public function setData($data): Adapter
{
$this->data = $data;
$this->setMethod(Typecho_Http_Client::METHOD_POST);
$this->setMethod(Client::METHOD_POST);
return $this;
}
@ -213,9 +205,9 @@ abstract class Typecho_Http_Client_Adapter
*
* @access public
* @param string $method
* @return Typecho_Http_Client_Adapter
* @return $this
*/
public function setMethod($method)
public function setMethod(string $method): Adapter
{
$this->method = $method;
return $this;
@ -226,12 +218,12 @@ abstract class Typecho_Http_Client_Adapter
*
* @access public
* @param array $files 需要POST的文件
* @return Typecho_Http_Client_Adapter
* @return $this
*/
public function setFiles(array $files)
public function setFiles(array $files): Adapter
{
$this->files = empty($this->files) ? $files : array_merge($this->files, $files);
$this->setMethod(Typecho_Http_Client::METHOD_POST);
$this->setMethod(Client::METHOD_POST);
return $this;
}
@ -240,9 +232,9 @@ abstract class Typecho_Http_Client_Adapter
*
* @access public
* @param integer $timeout 超时时间
* @return Typecho_Http_Client_Adapter
* @return $this
*/
public function setTimeout($timeout)
public function setTimeout(int $timeout): Adapter
{
$this->timeout = $timeout;
return $this;
@ -253,9 +245,9 @@ abstract class Typecho_Http_Client_Adapter
*
* @access public
* @param string $rfc http协议
* @return Typecho_Http_Client_Adapter
* @return $this
*/
public function setRfc($rfc)
public function setRfc(string $rfc): Adapter
{
$this->rfc = $rfc;
return $this;
@ -266,9 +258,9 @@ abstract class Typecho_Http_Client_Adapter
*
* @access public
* @param string $ip ip地址
* @return Typecho_Http_Client_Adapter
* @return $this
*/
public function setIp($ip)
public function setIp(string $ip): Adapter
{
$this->ip = $ip;
return $this;
@ -279,21 +271,21 @@ abstract class Typecho_Http_Client_Adapter
*
* @access public
* @param string $url 请求地址
* @return string
* @throws Typecho_Http_Client_Exception
* @return string|null
* @throws Exception
*/
public function send($url)
public function send(string $url): ?string
{
$params = parse_url($url);
if (!empty($params['host'])) {
$this->host = $params['host'];
} else {
throw new Typecho_Http_Client_Exception('Unknown Host', 500);
throw new Exception('Unknown Host', 500);
}
if (!in_array($params['scheme'], ['http', 'https'])) {
throw new Typecho_Http_Client_Exception('Unknown Scheme', 500);
throw new Exception('Unknown Scheme', 500);
}
if (!empty($params['path'])) {
@ -313,7 +305,7 @@ abstract class Typecho_Http_Client_Adapter
$this->scheme = $params['scheme'];
$this->port = ('https' == $params['scheme']) ? 443 : 80;
$url = Typecho_Common::buildUrl($params);
$url = Common::buildUrl($params);
if (!empty($params['port'])) {
$this->port = $params['port'];
@ -327,7 +319,7 @@ abstract class Typecho_Http_Client_Adapter
$response = $this->httpSend($url);
if (!$response) {
return;
return null;
}
str_replace("\r", '', $response);
@ -374,9 +366,9 @@ abstract class Typecho_Http_Client_Adapter
* @access public
* @param string $key 参数名称
* @param string $value 参数值
* @return Typecho_Http_Client_Adapter
* @return $this
*/
public function setHeader($key, $value)
public function setHeader(string $key, string $value): Adapter
{
$key = str_replace(' ', '-', ucwords(str_replace('-', ' ', $key)));
$this->headers[$key] = $value;
@ -390,7 +382,7 @@ abstract class Typecho_Http_Client_Adapter
* @param string $url 请求地址
* @return string
*/
abstract protected function httpSend($url);
abstract protected function httpSend(string $url): string;
/**
* 获取回执的头部信息
@ -399,7 +391,7 @@ abstract class Typecho_Http_Client_Adapter
* @param string $key 头信息名称
* @return string
*/
public function getResponseHeader($key)
public function getResponseHeader(string $key): ?string
{
$key = strtolower($key);
return $this->responseHeader[$key] ?? null;
@ -411,7 +403,7 @@ abstract class Typecho_Http_Client_Adapter
* @access public
* @return integer
*/
public function getResponseStatus()
public function getResponseStatus(): int
{
return $this->responseStatus;
}
@ -422,7 +414,7 @@ abstract class Typecho_Http_Client_Adapter
* @access public
* @return string
*/
public function getResponseBody()
public function getResponseBody(): string
{
return $this->responseBody;
}

View File

@ -1,15 +1,13 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* CURL适配器
*
* @author qining
* @category typecho
* @package Http
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
* @license GNU General Public License 2.0
* @version $Id$
*/
namespace Typecho\Http\Client\Adapter;
use Typecho\Http\Client;
use Typecho\Http\Client\Adapter;
if (!defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
/**
* CURL适配器
@ -18,7 +16,7 @@ if (!defined('__TYPECHO_ROOT_DIR__')) exit;
* @category typecho
* @package Http
*/
class Typecho_Http_Client_Adapter_Curl extends Typecho_Http_Client_Adapter
class Curl extends Adapter
{
/**
* 判断适配器是否可用
@ -26,7 +24,7 @@ class Typecho_Http_Client_Adapter_Curl extends Typecho_Http_Client_Adapter
* @access public
* @return boolean
*/
public static function isAvailable()
public static function isAvailable(): bool
{
return function_exists('curl_version');
}
@ -37,8 +35,9 @@ class Typecho_Http_Client_Adapter_Curl extends Typecho_Http_Client_Adapter
* @access public
* @param string $url 请求地址
* @return string
* @throws Client\Exception
*/
protected function httpSend($url)
protected function httpSend(string $url): string
{
$ch = curl_init();
@ -93,17 +92,21 @@ class Typecho_Http_Client_Adapter_Curl extends Typecho_Http_Client_Adapter
}
/** POST模式 */
if (Typecho_Http_Client::METHOD_POST == $this->method) {
if (Client::METHOD_POST == $this->method) {
if (!isset($this->headers['content-type'])) {
curl_setopt($ch, CURLOPT_POST, true);
}
if (!empty($this->data)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, is_array($this->data) ? http_build_query($this->data) : $this->data);
curl_setopt(
$ch,
CURLOPT_POSTFIELDS,
is_array($this->data) ? http_build_query($this->data) : $this->data
);
}
if (!empty($this->files)) {
foreach ($this->files as $key => &$file) {
foreach ($this->files as &$file) {
$file = '@' . $file;
}
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->files);
@ -112,7 +115,7 @@ class Typecho_Http_Client_Adapter_Curl extends Typecho_Http_Client_Adapter
$response = curl_exec($ch);
if (false === $response) {
throw new Typecho_Http_Client_Exception(curl_error($ch), 500);
throw new Client\Exception(curl_error($ch), 500);
}
curl_close($ch);

Some files were not shown because too many files have changed in this diff Show More