write = array('CustomInlineTags_Plugin', 'parseTagsOnSave');
Typecho_Plugin::factory('Widget_Contents_Page_Edit')->write = array('CustomInlineTags_Plugin', 'parseTagsOnSave');
// 添加内容解析钩子
Typecho_Plugin::factory('Widget_Abstract_Contents')->contentEx = array('CustomInlineTags_Plugin', 'parseContent');
Typecho_Plugin::factory('Widget_Abstract_Contents')->excerptEx = array('CustomInlineTags_Plugin', 'parseContent');
// 添加编辑器脚本 - 关键:使用header钩子添加脚本
Typecho_Plugin::factory('admin/header.php')->header = array('CustomInlineTags_Plugin', 'addHeader');
Typecho_Plugin::factory('admin/write-post.php')->bottom = array('CustomInlineTags_Plugin', 'addEditorButton');
Typecho_Plugin::factory('admin/write-page.php')->bottom = array('CustomInlineTags_Plugin', 'addEditorButton');
return _t('插件已激活');
}
/**
* 禁用插件
*/
public static function deactivate()
{
return _t('插件已禁用');
}
/**
* 插件配置面板
*/
public static function config(Typecho_Widget_Helper_Form $form)
{
// 标签样式设置
$style = new Typecho_Widget_Helper_Form_Element_Textarea('tagStyle',
NULL,
"display: inline-block;\nbackground: #f0f0f0;\ncolor: #333;\npadding: 2px 8px;\nmargin: 0 4px;\nborder-radius: 12px;\nfont-size: 0.9em;\nfont-weight: normal;\ntext-decoration: none;",
_t('标签样式'),
_t('自定义标签的CSS样式'));
$form->addInput($style);
// 标签前缀
$prefix = new Typecho_Widget_Helper_Form_Element_Text('tagPrefix',
NULL,
'#',
_t('标签前缀'),
_t('在标签前显示的前缀符号'));
$form->addInput($prefix);
// 是否启用标签链接
$enableLink = new Typecho_Widget_Helper_Form_Element_Radio('enableLink',
array(
'1' => _t('启用'),
'0' => _t('禁用')
),
'1',
_t('启用标签链接'),
_t('点击标签是否跳转到标签页面'));
$form->addInput($enableLink);
// 伪静态标签链接格式
$tagUrlFormat = new Typecho_Widget_Helper_Form_Element_Text('tagUrlFormat',
NULL,
'/tag-{slug}.html',
_t('标签链接格式'),
_t('根据你的伪静态设置填写标签链接格式,{slug}会被替换为标签slug'));
$form->addInput($tagUrlFormat);
// 是否新窗口打开
$openNewWindow = new Typecho_Widget_Helper_Form_Element_Radio('openNewWindow',
array(
'1' => _t('是'),
'0' => _t('否')
),
'1',
_t('新窗口打开'),
_t('点击标签是否在新窗口打开'));
$form->addInput($openNewWindow);
}
/**
* 个人配置面板
*/
public static function personalConfig(Typecho_Widget_Helper_Form $form) {}
/**
* 获取所有标签
*/
private static function getAllTags()
{
if (!empty(self::$_allTags)) {
return self::$_allTags;
}
try {
$db = Typecho_Db::get();
$rows = $db->fetchAll($db->select('name')
->from('table.metas')
->where('type = ?', 'tag')
->order('name', Typecho_Db::SORT_ASC));
foreach ($rows as $row) {
self::$_allTags[] = $row['name'];
}
} catch (Exception $e) {
self::$_allTags = array();
}
return self::$_allTags;
}
/**
* 添加头部资源
*/
public static function addHeader()
{
// 只在写文章/页面页面添加
if (strpos($_SERVER['REQUEST_URI'], 'write-post') !== false ||
strpos($_SERVER['REQUEST_URI'], 'write-page') !== false) {
// 获取所有标签并转为JSON
$allTags = self::getAllTags();
$tagsJson = json_encode($allTags);
echo '';
// 在JavaScript中嵌入标签数据
echo '';
}
}
/**
* 添加编辑器按钮 - 带标签联想搜索(本地搜索版)
*/
public static function addEditorButton()
{
?>
is('single')) {
return $content;
}
// 获取插件配置
$options = Helper::options()->plugin('CustomInlineTags');
$prefix = $options->tagPrefix ?: '#';
$style = $options->tagStyle ?: "display: inline-block; background: #f0f0f0; color: #333; padding: 2px 8px; margin: 0 4px; border-radius: 12px; font-size: 0.9em; font-weight: normal; text-decoration: none;";
$className = 'custom-inline-tag';
$enableLink = isset($options->enableLink) ? $options->enableLink : '1';
$tagUrlFormat = isset($options->tagUrlFormat) ? $options->tagUrlFormat : '/tag-{slug}.html';
$openNewWindow = isset($options->openNewWindow) ? $options->openNewWindow : '1';
// 替换短代码为HTML
$content = preg_replace_callback(
'/\[tag\]([^\[\]]+?)\[\/tag\]/',
function($matches) use ($prefix, $style, $className, $enableLink, $tagUrlFormat, $openNewWindow, $widget) {
$tagName = htmlspecialchars(trim($matches[1]), ENT_QUOTES, 'UTF-8');
$displayName = $prefix . $tagName;
if ($enableLink == '1' && $widget instanceof Widget_Archive) {
// 获取标签链接
$tagUrl = '';
try {
$db = Typecho_Db::get();
$tag = $db->fetchRow($db->select()
->from('table.metas')
->where('type = ?', 'tag')
->where('name = ?', $tagName)
->limit(1));
if ($tag) {
// 使用Typecho的标签链接生成方法
if (method_exists($widget, 'permalink')) {
// 创建临时对象获取标签链接
$reflection = new ReflectionClass($widget);
$params = $reflection->getProperty('_params');
$params->setAccessible(true);
$widgetParams = $params->getValue($widget);
// 临时修改参数获取标签链接
$originalParams = $widgetParams;
$widgetParams['type'] = 'tag';
$widgetParams['slug'] = $tag['slug'];
// 尝试获取标签链接
try {
$tagUrl = $widget->permalink;
} catch (Exception $e) {
// 如果失败,使用自定义格式
$tagSlug = urlencode($tag['slug']);
$tagUrl = str_replace('{slug}', $tagSlug, $tagUrlFormat);
$tagUrl = Typecho_Common::url($tagUrl, Helper::options()->index);
}
// 恢复原始参数
$params->setValue($widget, $originalParams);
} else {
// 使用自定义格式
$tagSlug = urlencode($tag['slug']);
$tagUrl = str_replace('{slug}', $tagSlug, $tagUrlFormat);
$tagUrl = Typecho_Common::url($tagUrl, Helper::options()->index);
}
}
} catch (Exception $e) {
// 出错时不添加链接
error_log('CustomInlineTags Error: ' . $e->getMessage());
}
if ($tagUrl) {
// 构建链接属性
$linkAttributes = sprintf('href="%s" class="%s" data-tag="%s" style="%s" title="查看标签相关文章"',
htmlspecialchars($tagUrl),
$className,
$tagName,
$style
);
// 如果启用了新窗口打开,添加target="_blank"
if ($openNewWindow == '1') {
$linkAttributes .= ' target="_blank"';
}
return sprintf('%s',
$linkAttributes,
$displayName
);
}
}
// 如果不启用链接或找不到标签
return sprintf(
'%s',
$className,
$tagName,
$style,
$displayName
);
},
$content
);
return $content;
}
/**
* 保存文章时提取标签并保存到数据库
*/
public static function parseTagsOnSave($contents, $widget)
{
$content = $contents['text'];
$tags = array();
// 从短代码中提取标签
preg_match_all('/\[tag\]([^\[\]]+?)\[\/tag\]/', $content, $matches);
if (!empty($matches[1])) {
foreach ($matches[1] as $tag) {
$tag = trim($tag);
if (!empty($tag) && !in_array($tag, $tags)) {
$tags[] = $tag;
}
}
}
// 如果找到了标签,添加到文章的标签字段
if (!empty($tags)) {
// 获取现有的标签
$existingTags = isset($contents['tags']) ? $contents['tags'] : '';
$existingTagsArray = array_filter(array_map('trim', explode(',', $existingTags)));
// 合并标签并去重
$allTags = array_unique(array_merge($existingTagsArray, $tags));
// 更新标签字段
$contents['tags'] = implode(',', $allTags);
}
return $contents;
}
}