Files
DevelopmentHistory/Action.php
2026-02-23 17:23:48 +08:00

386 lines
12 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
class DevelopmentHistory_Action
{
/**
* 数据库对象
*/
private $db;
private $prefix;
/**
* 请求对象
*/
private $request;
/**
* 响应对象
*/
private $response;
/**
* 构造函数
*/
public function __construct($request = null, $response = null)
{
$this->db = Typecho_Db::get();
$this->prefix = $this->db->getPrefix();
$this->request = $request ?: Typecho_Request::getInstance();
$this->response = $response ?: Typecho_Response::getInstance();
}
/**
* 添加历史记录 - 修复使用Typecho正确的SQL构建方法
*/
public function addHistory($data)
{
try {
$now = new Typecho_Date(Typecho_Date::gmtTime());
$insert = array(
'content' => $data['content'],
'event_date' => $data['event_date'],
'post_cids' => isset($data['post_cids']) ? $this->cleanCids($data['post_cids']) : '',
'created' => $now->format('Y-m-d H:i:s'),
'modified' => $now->format('Y-m-d H:i:s'),
'status' => 1
);
// 使用Typecho的查询构建器但先验证数据
$this->validateInsertData($insert);
// 修复:正确构建并执行插入查询
// 在Typecho中insert()->rows()需要调用query()方法来执行
$query = $this->db->insert($this->prefix . 'development_history')->rows($insert);
// 执行查询
$this->db->query($query);
// 获取最后插入的ID - Typecho的方式
$row = $this->db->fetchRow($this->db->select('LAST_INSERT_ID() as id'));
return $row ? $row['id'] : 0;
} catch (Exception $e) {
error_log("addHistory Error: " . $e->getMessage());
error_log("Data: " . print_r($data, true));
throw new Exception("发布失败: " . $e->getMessage());
}
}
/**
* 验证插入数据
*/
private function validateInsertData(&$data)
{
// 确保所有必需字段都有值
if (empty($data['content'])) {
throw new Exception("内容不能为空");
}
if (empty($data['event_date'])) {
throw new Exception("日期不能为空");
}
// 验证日期格式
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $data['event_date'])) {
throw new Exception("日期格式错误应为YYYY-MM-DD");
}
// 清理和转义内容
$data['content'] = trim($data['content']);
if (empty($data['content'])) {
throw new Exception("内容不能为空");
}
// 确保所有字段都是字符串
foreach ($data as $key => $value) {
if (!is_string($value) && !is_numeric($value)) {
$data[$key] = (string)$value;
}
}
}
/**
* 批量添加历史记录按事件时间排序插入越近的ID越大
*/
public function batchAddHistories($histories)
{
// 按事件时间排序越近的时间越晚插入这样ID越大
usort($histories, function($a, $b) {
return strtotime($a['event_date']) - strtotime($b['event_date']);
});
$now = new Typecho_Date(Typecho_Date::gmtTime());
$nowStr = $now->format('Y-m-d H:i:s');
foreach ($histories as $history) {
$insert = array(
'content' => $history['content'],
'event_date' => $history['event_date'],
'post_cids' => '',
'created' => $nowStr,
'modified' => $nowStr,
'status' => 1
);
$query = $this->db->insert($this->prefix . 'development_history')->rows($insert);
$this->db->query($query);
}
}
/**
* 更新历史记录
*/
public function updateHistory($data)
{
try {
$now = new Typecho_Date(Typecho_Date::gmtTime());
$update = array(
'content' => $data['edit_content'],
'event_date' => $data['edit_event_date'],
'post_cids' => isset($data['edit_post_cids']) ? $this->cleanCids($data['edit_post_cids']) : '',
'modified' => $now->format('Y-m-d H:i:s')
);
$query = $this->db->update($this->prefix . 'development_history')
->rows($update)
->where('id = ?', intval($data['edit_id']));
$this->db->query($query);
} catch (Exception $e) {
error_log("updateHistory Error: " . $e->getMessage());
throw new Exception("更新失败: " . $e->getMessage());
}
}
/**
* 删除历史记录
*/
public function deleteHistory($id)
{
$query = $this->db->delete($this->prefix . 'development_history')->where('id = ?', intval($id));
$this->db->query($query);
}
/**
* 批量删除
*/
public function deleteHistories($ids)
{
foreach ($ids as $id) {
$this->deleteHistory(intval($id));
}
}
/**
* 获取历史记录
*/
public function getHistories($page = 1, $perPage = 10)
{
$offset = ($page - 1) * $perPage;
$query = $this->db->select()
->from($this->prefix . 'development_history')
->where('status = ?', 1)
->order('id', Typecho_Db::SORT_DESC)
->limit($perPage)
->offset($offset);
return $this->db->fetchAll($query);
}
/**
* 获取所有历史记录(用于导出)
*/
public function getAllHistories()
{
$query = $this->db->select()
->from($this->prefix . 'development_history')
->where('status = ?', 1)
->order('id', Typecho_Db::SORT_DESC);
return $this->db->fetchAll($query);
}
/**
* 获取总记录数
*/
public function getTotalCount()
{
$query = $this->db->select('COUNT(*) as count')
->from($this->prefix . 'development_history')
->where('status = ?', 1);
$result = $this->db->fetchRow($query);
return $result['count'];
}
/**
* 获取单条记录
*/
public function getHistory($id)
{
$query = $this->db->select()
->from($this->prefix . 'development_history')
->where('id = ?', $id)
->limit(1);
return $this->db->fetchRow($query);
}
/**
* 根据文章CID获取文章信息
*/
public function getPostByCid($cid)
{
try {
$query = $this->db->select('cid, title, slug, created')
->from($this->prefix . 'contents')
->where('cid = ?', intval($cid))
->where('type = ?', 'post')
->where('status = ?', 'publish')
->limit(1);
$post = $this->db->fetchRow($query);
if ($post) {
$options = Typecho_Widget::widget('Widget_Options');
if (!empty($post['slug'])) {
$post['url'] = Typecho_Common::url($post['slug'] . '.html', $options->index);
} else {
$post['url'] = Typecho_Common::url('archives/' . $post['cid'], $options->index);
}
}
return $post;
} catch (Exception $e) {
return null;
}
}
/**
* 清理CID字符串
*/
private function cleanCids($cids)
{
if (empty($cids)) {
return '';
}
$cidsArray = array_filter(array_map('trim', explode(',', $cids)));
$validCids = array();
foreach ($cidsArray as $cid) {
if (is_numeric($cid) && $cid > 0) {
$validCids[] = intval($cid);
}
}
// 去重并返回逗号分隔的字符串
return implode(',', array_unique($validCids));
}
/**
* 导出数据为文本格式
*/
public function exportData()
{
$histories = $this->getAllHistories();
$content = '';
foreach ($histories as $history) {
// 使用 Y.m.d 格式导出
$date = date('Y.m.d', strtotime($history['event_date']));
$text = str_replace(array("\r\n", "\r", "\n"), " ", $history['content']);
$content .= $date . ' ' . $text . "\n";
}
return $content;
}
/**
* 导入数据(增强版,支持调试)
*/
public function importData($text)
{
// 标准化换行符
$text = str_replace("\r\n", "\n", $text);
$text = str_replace("\r", "\n", $text);
$lines = explode("\n", $text);
$imported = 0;
$failed = 0;
$failReasons = array(); // 记录失败原因
$histories = array();
foreach ($lines as $lineNum => $line) {
$line = trim($line);
if (empty($line)) continue;
// 移除行尾的分号(如果有)
if (substr($line, -1) === ';') {
$line = substr($line, 0, -1);
$line = trim($line);
}
// 找到第一个空格的位置来分割日期和内容
$firstSpacePos = strpos($line, ' ');
if ($firstSpacePos === false) {
$failed++;
$failReasons[] = "" . ($lineNum + 1) . " 行:找不到空格分隔日期和内容 - '{$line}'";
continue;
}
$date = trim(substr($line, 0, $firstSpacePos));
$content = trim(substr($line, $firstSpacePos + 1));
// 验证日期格式 - 支持单个数字的月份和日期
// 允许的格式YYYY.M.D, YYYY.MM.D, YYYY.M.DD, YYYY.MM.DD
$datePattern = '/^(\d{4})\.(\d{1,2})\.(\d{1,2})$/';
if (!preg_match($datePattern, $date, $matches)) {
$failed++;
$failReasons[] = "" . ($lineNum + 1) . " 行:日期格式错误,应为 YYYY.M[M].D[D] - '{$date}'";
continue;
}
// 检查日期是否有效
$year = intval($matches[1]);
$month = intval($matches[2]);
$day = intval($matches[3]);
if (!checkdate($month, $day, $year)) {
$failed++;
$failReasons[] = "" . ($lineNum + 1) . " 行:无效的日期 - {$date}";
continue;
}
// 转换日期格式为 Y-m-d 以便数据库存储,补零成两位数字
$dbDate = sprintf('%04d-%02d-%02d', $year, $month, $day);
// 验证内容
if (empty($content)) {
$failed++;
$failReasons[] = "" . ($lineNum + 1) . " 行:内容为空";
continue;
}
$histories[] = array(
'event_date' => $dbDate,
'content' => $content
);
$imported++;
}
if (!empty($histories)) {
$this->batchAddHistories($histories);
}
// 返回包含失败原因的结果
return array(
'imported' => $imported,
'failed' => $failed,
'fail_reasons' => $failReasons
);
}
}