Files
MyTrack/Action.php

1133 lines
39 KiB
PHP
Raw Normal View History

2026-02-23 19:45:59 +08:00
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* MyTrack 动作处理器
*
* @package MyTrack
*/
class MyTrack_Action extends Typecho_Widget implements Widget_Interface_Do
{
/**
* 数据库连接
*
* @access private
* @var PDO
*/
private $db;
/**
* 构造函数
*
* @access public
* @param mixed $request request对象
* @param mixed $response response对象
* @param mixed $params 参数列表
* @return void
*/
public function __construct($request, $response, $params = NULL)
{
parent::__construct($request, $response, $params);
$this->db = MyTrack_Plugin::getDbConnection();
}
/**
* 动作入口
*
* @access public
* @return void
*/
public function action()
{
$this->widget('Widget_User')->pass('administrator');
$this->on($this->request->is('do=add'))->add();
$this->on($this->request->is('do=update'))->update();
$this->on($this->request->is('do=delete'))->delete();
$this->on($this->request->is('do=get'))->get();
$this->on($this->request->is('do=getAll'))->getAll();
$this->on($this->request->is('do=getOne'))->get();
$this->on($this->request->is('do=list'))->list();
$this->on($this->request->is('do=batchDelete'))->batchDelete();
$this->on($this->request->is('do=import'))->import();
$this->on($this->request->is('do=export'))->export();
$this->on($this->request->is('do=exportSimple'))->exportSimple();
$this->on($this->request->is('do=getArticleImages'))->getArticleImages();
$this->on($this->request->is('do=getById'))->getById();
$this->on($this->request->is('do=getRelatedArticlesInfo'))->getRelatedArticlesInfo();
// 默认返回列表
$this->response->throwJson(array(
'success' => false,
'message' => '无效的操作'
));
}
/**
* 检测重复数据(基于经纬度)
*
* @access private
* @param float $latitude 纬度
* @param float $longitude 经度
* @param int $excludeId 要排除的ID更新时使用
* @return array|false 返回重复的数据信息false表示无重复
*/
private function checkDuplicate($latitude, $longitude, $excludeId = null)
{
try {
// 根据经纬度进行检测使用较高精度0.000001度约等于0.1米)
$sql = "SELECT id, name FROM plugin_track_footprint
WHERE ABS(latitude - ?) < 0.000001
AND ABS(longitude - ?) < 0.000001";
$params = array($latitude, $longitude);
if ($excludeId !== null) {
$sql .= " AND id != ?";
$params[] = $excludeId;
}
$sql .= " LIMIT 1";
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result ? $result : false;
} catch (PDOException $e) {
error_log('检测重复数据失败: ' . $e->getMessage());
return false;
}
}
public function add()
{
// 原有的参数获取
$latitude = $this->request->get('latitude');
$longitude = $this->request->get('longitude');
$name = $this->request->get('name');
$description = $this->request->get('description');
$tags = $this->request->get('tags');
$article_cid = $this->request->get('article_cid');
$urlLabel = $this->request->get('urlLabel');
$url = $this->request->get('url');
$photos = $this->request->get('photos');
$date = $this->request->get('date');
// 新增字段
$address = $this->request->get('address');
$location_type = $this->request->get('location_type');
$rating_level = $this->request->get('rating_level', 0);
$categories = $this->request->get('categories');
$review = $this->request->get('review');
$markerColor = $this->request->get('markerColor');
$related_articles = $this->request->get('related_articles');
$highlights = $this->request->get('highlights');
// 如果提供了日期,确保格式为 YYYY-MM-DD HH:MM:SS
if (!empty($date)) {
$date = date('Y-m-d H:i:s', strtotime($date));
}
// 验证必填字段
if (empty($latitude) || empty($longitude) || empty($name)) {
$this->response->throwJson(array(
'success' => false,
'message' => '经纬度和地点名称不能为空'
));
}
// 检查重复数据(基于经纬度)
$duplicate = $this->checkDuplicate($latitude, $longitude);
if ($duplicate !== false && isset($duplicate['name']) && isset($duplicate['id'])) {
$this->response->throwJson(array(
'success' => false,
'message' => "该位置已存在地点:{$duplicate['name']}ID: {$duplicate['id']}),请勿重复添加"
));
}
try {
// 如果提供了文章CID获取文章信息和图片
if (!empty($article_cid)) {
$articleInfo = MyTrack_Plugin::getArticleInfo($article_cid);
// 如果没有提供图片链接尝试从文章中提取限制4张
if (empty($photos) && !empty($articleInfo['images'])) {
$limitedImages = array_slice($articleInfo['images'], 0, 4);
$photos = implode(',', $limitedImages);
}
// 如果没有提供文章标题,尝试从文章中获取
if (empty($urlLabel) && !empty($articleInfo['title'])) {
$urlLabel = $articleInfo['title'];
}
// 如果没有提供文章链接,尝试从文章中获取
if (empty($url) && !empty($articleInfo['link'])) {
$url = $articleInfo['link'];
}
// 如果没有提供标签,尝试从文章中获取
if (empty($tags) && !empty($articleInfo['tags'])) {
$tags = implode(',', $articleInfo['tags']);
}
}
$stmt = $this->db->prepare("INSERT INTO plugin_track_footprint
(latitude, longitude, name, address, location_type, rating_level, categories, review, description, tags, article_cid, urlLabel, url, photos, date, markerColor, related_articles, highlights)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute(array(
$latitude,
$longitude,
$name,
$address,
$location_type,
$rating_level,
$categories,
$review,
$description,
$tags,
$article_cid,
$urlLabel,
$url,
$photos,
$date,
$markerColor,
$related_articles,
$highlights
));
$id = $this->db->lastInsertId();
// 清除足迹缓存
$this->clearFootprintCache();
$this->response->throwJson(array(
'success' => true,
'message' => '足迹添加成功',
'data' => array(
'id' => $id
)
));
} catch (PDOException $e) {
$this->response->throwJson(array(
'success' => false,
'message' => '添加失败: ' . $e->getMessage()
));
}
}
public function update()
{
$id = $this->request->get('id');
$latitude = $this->request->get('latitude');
$longitude = $this->request->get('longitude');
$name = $this->request->get('name');
$description = $this->request->get('description');
$tags = $this->request->get('tags');
$article_cid = $this->request->get('article_cid');
$urlLabel = $this->request->get('urlLabel');
$url = $this->request->get('url');
$photos = $this->request->get('photos');
$date = $this->request->get('date');
// 新增字段
$address = $this->request->get('address');
$location_type = $this->request->get('location_type');
$rating_level = $this->request->get('rating_level', 0);
$categories = $this->request->get('categories');
$review = $this->request->get('review');
$markerColor = $this->request->get('markerColor');
$related_articles = $this->request->get('related_articles');
$highlights = $this->request->get('highlights');
// 验证必填字段
if (empty($id) || empty($latitude) || empty($longitude) || empty($name)) {
$this->response->throwJson(array(
'success' => false,
'message' => 'ID、经纬度和地点名称不能为空'
));
}
// 检查重复数据(基于经纬度,排除自身)
$duplicate = $this->checkDuplicate($latitude, $longitude, $id);
if ($duplicate !== false && isset($duplicate['name']) && isset($duplicate['id'])) {
$this->response->throwJson(array(
'success' => false,
'message' => "该位置已存在其他地点:{$duplicate['name']}ID: {$duplicate['id']}),请修改经纬度"
));
}
try {
// 如果提供了文章CID获取文章信息和图片
if (!empty($article_cid)) {
$articleInfo = MyTrack_Plugin::getArticleInfo($article_cid);
if (empty($photos) && !empty($articleInfo['images'])) {
$limitedImages = array_slice($articleInfo['images'], 0, 4);
$photos = implode(',', $limitedImages);
}
if (empty($urlLabel) && !empty($articleInfo['title'])) {
$urlLabel = $articleInfo['title'];
}
if (empty($url) && !empty($articleInfo['link'])) {
$url = $articleInfo['link'];
}
if (empty($tags) && !empty($articleInfo['tags'])) {
$tags = implode(',', $articleInfo['tags']);
}
}
$stmt = $this->db->prepare("UPDATE plugin_track_footprint
SET latitude = ?, longitude = ?, name = ?, address = ?, location_type = ?, rating_level = ?, categories = ?, review = ?, description = ?, tags = ?, article_cid = ?,
urlLabel = ?, url = ?, photos = ?, date = ?, markerColor = ?, related_articles = ?, highlights = ?
WHERE id = ?");
$result = $stmt->execute(array(
$latitude,
$longitude,
$name,
$address,
$location_type,
$rating_level,
$categories,
$review,
$description,
$tags,
$article_cid,
$urlLabel,
$url,
$photos,
$date,
$markerColor,
$related_articles,
$highlights,
$id
));
if ($result) {
// 清除足迹缓存
$this->clearFootprintCache();
$this->response->throwJson(array(
'success' => true,
'message' => '足迹更新成功'
));
} else {
$this->response->throwJson(array(
'success' => false,
'message' => '足迹不存在或更新失败'
));
}
} catch (PDOException $e) {
$this->response->throwJson(array(
'success' => false,
'message' => '更新失败: ' . $e->getMessage()
));
}
}
/**
* 获取关联文章信息
*
* @access public
* @return void
*/
public function getRelatedArticlesInfo()
{
$related_articles = $this->request->get('related_articles');
if (empty($related_articles)) {
$this->response->throwJson(array(
'success' => false,
'message' => '关联文章不能为空'
));
}
try {
$result = MyTrack_Plugin::getRelatedArticlesInfo($related_articles);
$this->response->throwJson(array(
'success' => true,
'data' => $result
));
} catch (Exception $e) {
$this->response->throwJson(array(
'success' => false,
'message' => '获取关联文章信息失败: ' . $e->getMessage()
));
}
}
/**
* 批量删除足迹
*
* @access public
* @return void
*/
public function batchDelete()
{
$ids = $this->request->filter('int')->getArray('footprint');
if (empty($ids)) {
$rawIds = $this->request->get('footprint');
if (!empty($rawIds)) {
$ids = is_array($rawIds) ? $rawIds : array($rawIds);
$ids = array_map('intval', $ids);
}
}
if (empty($ids) || !is_array($ids)) {
$this->response->throwJson(array(
'success' => false,
'message' => '请选择要删除的足迹'
));
}
$ids = array_filter($ids, function($id) {
return is_numeric($id) && $id > 0;
});
if (empty($ids)) {
$this->response->throwJson(array(
'success' => false,
'message' => '无效的足迹ID'
));
}
try {
$placeholders = implode(',', array_fill(0, count($ids), '?'));
$stmt = $this->db->prepare("DELETE FROM plugin_track_footprint WHERE id IN ($placeholders)");
$result = $stmt->execute($ids);
if ($result) {
$this->clearFootprintCache();
$this->response->throwJson(array(
'success' => true,
'message' => '足迹删除成功'
));
} else {
$this->response->throwJson(array(
'success' => false,
'message' => '删除失败,请检查足迹是否存在'
));
}
} catch (PDOException $e) {
$this->response->throwJson(array(
'success' => false,
'message' => '删除失败: ' . $e->getMessage()
));
}
}
/**
* 删除足迹
*
* @access public
* @return void
*/
public function delete()
{
$id = $this->request->get('id');
if (empty($id)) {
$this->response->throwJson(array(
'success' => false,
'message' => 'ID不能为空'
));
}
try {
$stmt = $this->db->prepare("DELETE FROM plugin_track_footprint WHERE id = ?");
$result = $stmt->execute(array($id));
if ($result) {
$this->clearFootprintCache();
$this->response->throwJson(array(
'success' => true,
'message' => '足迹删除成功'
));
} else {
$this->response->throwJson(array(
'success' => false,
'message' => '足迹不存在或删除失败'
));
}
} catch (PDOException $e) {
$this->response->throwJson(array(
'success' => false,
'message' => '删除失败: ' . $e->getMessage()
));
}
}
/**
* 获取单个足迹
*
* @access public
* @return void
*/
public function get()
{
$id = $this->request->get('id');
if (empty($id)) {
$this->response->throwJson(array(
'success' => false,
'message' => 'ID不能为空'
));
}
try {
$stmt = $this->db->prepare("SELECT * FROM plugin_track_footprint WHERE id = ?");
$stmt->execute(array($id));
$footprint = $stmt->fetch(PDO::FETCH_ASSOC);
if ($footprint) {
if (!empty($footprint['related_articles'])) {
$footprint['related_articles_info'] = MyTrack_Plugin::getRelatedArticlesInfo($footprint['related_articles']);
}
$this->response->throwJson(array(
'success' => true,
'data' => $footprint
));
} else {
$this->response->throwJson(array(
'success' => false,
'message' => '足迹不存在'
));
}
} catch (PDOException $e) {
$this->response->throwJson(array(
'success' => false,
'message' => '查询失败: ' . $e->getMessage()
));
}
}
/**
* 通过ID获取单个足迹公开接口
*
* @access public
* @return void
*/
public function getById()
{
$id = $this->request->get('id');
if (empty($id)) {
$this->response->throwJson(array(
'success' => false,
'message' => 'ID不能为空'
));
}
try {
$stmt = $this->db->prepare("SELECT * FROM plugin_track_footprint WHERE id = ?");
$stmt->execute(array($id));
$footprint = $stmt->fetch(PDO::FETCH_ASSOC);
if ($footprint) {
if (!empty($footprint['categories'])) {
$footprint['categories'] = explode(',', $footprint['categories']);
} else {
$footprint['categories'] = array();
}
if (!empty($footprint['highlights'])) {
$footprint['highlights'] = explode(',', $footprint['highlights']);
} else {
$footprint['highlights'] = array();
}
if (!empty($footprint['article_cid'])) {
$articleInfo = MyTrack_Plugin::getArticleInfo($footprint['article_cid']);
if (!empty($articleInfo['title']) && empty($footprint['urlLabel'])) {
$footprint['urlLabel'] = $articleInfo['title'];
}
if (!empty($articleInfo['link']) && empty($footprint['url'])) {
$footprint['url'] = $articleInfo['link'];
}
}
if (!empty($footprint['related_articles'])) {
$footprint['related_articles_info'] = MyTrack_Plugin::getRelatedArticlesInfo($footprint['related_articles']);
}
$this->response->throwJson(array(
'success' => true,
'data' => $footprint
));
} else {
$this->response->throwJson(array(
'success' => false,
'message' => '足迹不存在'
));
}
} catch (PDOException $e) {
$this->response->throwJson(array(
'success' => false,
'message' => '查询失败: ' . $e->getMessage()
));
}
}
/**
* 获取足迹列表
*
* @access public
* @return void
*/
public function list()
{
$page = $this->request->get('page', 1);
$size = $this->request->get('size', 10);
$offset = ($page - 1) * $size;
try {
$countStmt = $this->db->query("SELECT COUNT(*) FROM plugin_track_footprint");
$total = $countStmt->fetchColumn();
$stmt = $this->db->prepare("SELECT * FROM plugin_track_footprint
ORDER BY date DESC, created_at DESC
LIMIT ? OFFSET ?");
$stmt->execute(array($size, $offset));
$footprints = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($footprints as &$footprint) {
if (!empty($footprint['related_articles'])) {
$footprint['related_articles_info'] = MyTrack_Plugin::getRelatedArticlesInfo($footprint['related_articles']);
}
}
$this->response->throwJson(array(
'success' => true,
'data' => array(
'total' => $total,
'page' => $page,
'size' => $size,
'pages' => ceil($total / $size),
'items' => $footprints
)
));
} catch (PDOException $e) {
$this->response->throwJson(array(
'success' => false,
'message' => '查询失败: ' . $e->getMessage()
));
}
}
/**
* 导入足迹
*
* @access public
* @return void
*/
public function import()
{
if (!isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
$this->response->throwJson(array(
'success' => false,
'message' => '请上传有效的文件'
));
}
$file = $_FILES['file'];
$fileType = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!in_array($fileType, array('json'))) {
$this->response->throwJson(array(
'success' => false,
'message' => '只支持JSON格式的文件'
));
}
try {
$content = file_get_contents($file['tmp_name']);
$encoding = mb_detect_encoding($content, array('UTF-8', 'GBK', 'GB2312', 'ASCII'), true);
if ($encoding !== 'UTF-8' && $encoding !== false) {
$content = mb_convert_encoding($content, 'UTF-8', $encoding);
}
$data = json_decode($content, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('JSON格式错误: ' . json_last_error_msg());
}
if (!is_array($data)) {
throw new Exception('JSON格式不正确应该是一个数组');
}
$successCount = 0;
$errorCount = 0;
$errors = array();
$this->db->beginTransaction();
foreach ($data as $index => $item) {
try {
if (empty($item['latitude']) || empty($item['longitude']) || empty($item['name'])) {
$errors[] = "" . ($index + 1) . "行: 缺少经纬度或地点名称";
$errorCount++;
continue;
}
// 导入时检查重复数据(基于经纬度)
$duplicate = $this->checkDuplicate($item['latitude'], $item['longitude']);
if ($duplicate !== false && isset($duplicate['name']) && isset($duplicate['id'])) {
$errors[] = "" . ($index + 1) . "行: 该位置已存在地点:{$duplicate['name']}ID: {$duplicate['id']}),跳过导入";
$errorCount++;
continue;
}
$categories = '';
if (isset($item['categories'])) {
if (is_array($item['categories'])) {
$categories = implode(',', $item['categories']);
} else {
$categories = $item['categories'];
}
}
$highlights = '';
if (isset($item['highlights'])) {
if (is_array($item['highlights'])) {
$highlights = implode(',', $item['highlights']);
} else {
$highlights = $item['highlights'];
}
}
$photos = '';
if (isset($item['photos'])) {
if (is_array($item['photos'])) {
$photos = implode(',', $item['photos']);
} else {
$photos = $item['photos'];
}
}
$related_articles = '';
if (isset($item['related_articles'])) {
if (is_array($item['related_articles'])) {
$related_articles = implode(',', $item['related_articles']);
} else {
$related_articles = $item['related_articles'];
}
}
$stmt = $this->db->prepare("INSERT INTO plugin_track_footprint
(latitude, longitude, name, address, location_type, rating_level, categories, review,
description, tags, article_cid, urlLabel, url, photos, date, markerColor,
related_articles, highlights, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$result = $stmt->execute(array(
$item['latitude'] ?? null,
$item['longitude'] ?? null,
$item['name'] ?? '',
$item['address'] ?? null,
$item['location_type'] ?? null,
$item['rating_level'] ?? 0,
$categories,
$item['review'] ?? null,
$item['description'] ?? null,
$item['tags'] ?? null,
$item['article_cid'] ?? null,
$item['urlLabel'] ?? null,
$item['url'] ?? null,
$photos,
$item['date'] ?? null,
$item['markerColor'] ?? null,
$related_articles,
$highlights,
$item['created_at'] ?? date('Y-m-d H:i:s'),
$item['updated_at'] ?? date('Y-m-d H:i:s')
));
if ($result) {
$successCount++;
} else {
$errors[] = "" . ($index + 1) . "行: 插入失败";
$errorCount++;
}
} catch (PDOException $e) {
$errorCount++;
$errors[] = "" . ($index + 1) . "行: " . $e->getMessage();
}
}
$this->db->commit();
$this->clearFootprintCache();
$this->response->throwJson(array(
'success' => true,
'message' => "导入完成,成功: {$successCount},失败: {$errorCount}",
'data' => array(
'success' => $successCount,
'error' => $errorCount,
'errors' => $errors
)
));
} catch (Exception $e) {
$this->db->rollBack();
$this->response->throwJson(array(
'success' => false,
'message' => '导入失败: ' . $e->getMessage()
));
}
}
/**
* 导出足迹
*
* @access public
* @return void
*/
public function export()
{
$format = $this->request->get('format', 'json');
if (!in_array($format, array('json'))) {
$this->response->throwJson(array(
'success' => false,
'message' => '不支持的导出格式'
));
}
try {
$stmt = $this->db->query("SELECT
id,
latitude,
longitude,
name,
address,
location_type,
rating_level,
categories,
review,
description,
tags,
article_cid,
urlLabel,
url,
photos,
date,
markerColor,
related_articles,
highlights,
created_at,
updated_at
FROM plugin_track_footprint
ORDER BY date DESC, created_at DESC");
$footprints = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($footprints)) {
$this->response->throwJson(array(
'success' => false,
'message' => '没有数据可导出'
));
}
$filename = 'mytrack_footprints_' . date('Ymd_His') . '.json';
$content = json_encode($footprints, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
header('Content-Type: application/json');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Length: ' . strlen($content));
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
echo $content;
exit;
} catch (PDOException $e) {
$this->response->throwJson(array(
'success' => false,
'message' => '导出失败: ' . $e->getMessage()
));
}
}
/**
* 精简导出足迹
*
* @access public
* @return void
*/
public function exportSimple()
{
$format = $this->request->get('format', 'json');
if (!in_array($format, array('json'))) {
$this->response->throwJson(array(
'success' => false,
'message' => '不支持的导出格式'
));
}
try {
$stmt = $this->db->query("SELECT
name,
latitude,
longitude,
date,
url,
urlLabel,
categories,
markerColor,
photos,
related_articles,
highlights
FROM plugin_track_footprint
ORDER BY date DESC");
$footprints = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($footprints)) {
$this->response->throwJson(array(
'success' => false,
'message' => '没有数据可导出'
));
}
$locations = array();
foreach ($footprints as $footprint) {
$coordinates = $footprint['longitude'] . ',' . $footprint['latitude'];
$categories = array();
if (!empty($footprint['categories'])) {
$categoryArray = explode(',', $footprint['categories']);
foreach ($categoryArray as $category) {
$category = trim($category);
switch($category) {
case 'visited':
$categories[] = '去过';
break;
case 'want':
$categories[] = '想去';
break;
case 'plan':
$categories[] = '计划';
break;
default:
$categories[] = $category;
}
}
}
$highlights = !empty($footprint['highlights']) ? explode(',', $footprint['highlights']) : array();
$photos = !empty($footprint['photos']) ? explode(',', $footprint['photos']) : array();
$relatedArticles = !empty($footprint['related_articles']) ? explode(',', $footprint['related_articles']) : array();
$locations[] = array(
'name' => $footprint['name'] ?? '',
'coordinates' => $coordinates,
'date' => $footprint['date'] ?? '',
'url' => $footprint['url'] ?? '',
'urlLabel' => $footprint['urlLabel'] ?? '',
'categories' => $categories,
'highlights' => $highlights,
'markerColor' => $footprint['markerColor'] ?? '',
'photos' => $photos,
'relatedArticles' => $relatedArticles
);
}
$exportData = array('locations' => $locations);
$filename = 'mytrack_simple_' . date('Ymd_His') . '.json';
$content = json_encode($exportData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
header('Content-Type: application/json');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Length: ' . strlen($content));
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
echo $content;
exit;
} catch (PDOException $e) {
$this->response->throwJson(array(
'success' => false,
'message' => '导出失败: ' . $e->getMessage()
));
}
}
/**
* 获取所有足迹(用于前台地图显示)
*
* @access public
* @return void
*/
public function getAll()
{
try {
$options = Typecho_Widget::widget('Widget_Options')->plugin('MyTrack');
$cacheExpire = isset($options->cacheExpire) && is_numeric($options->cacheExpire) && $options->cacheExpire >= 0
? intval($options->cacheExpire) * 24 * 60 * 60
: 7 * 24 * 60 * 60;
$cacheKey = 'mytrack_footprints_data';
if ($cacheExpire > 0) {
$cacheFile = __DIR__ . '/cache/' . md5($cacheKey) . '.cache';
if (file_exists($cacheFile) && filemtime($cacheFile) + $cacheExpire > time()) {
$cachedData = unserialize(file_get_contents($cacheFile));
if ($cachedData !== false) {
$this->response->throwJson(array(
'success' => true,
'data' => $cachedData,
'from_cache' => true
));
return;
}
}
}
$stmt = $this->db->query("SELECT * FROM plugin_track_footprint ORDER BY date ASC, created_at ASC");
$footprints = $stmt->fetchAll(PDO::FETCH_ASSOC);
$validFootprints = array_filter($footprints, function($footprint) {
$longitude = is_numeric($footprint['longitude']) ? floatval($footprint['longitude']) : null;
$latitude = is_numeric($footprint['latitude']) ? floatval($footprint['latitude']) : null;
return $longitude !== null && $latitude !== null &&
!is_nan($longitude) && !is_nan($latitude) &&
$longitude >= -180 && $longitude <= 180 &&
$latitude >= -90 && $latitude <= 90;
});
$validFootprints = array_values($validFootprints);
foreach ($validFootprints as &$footprint) {
if (!empty($footprint['related_articles'])) {
$footprint['related_articles_info'] = MyTrack_Plugin::getRelatedArticlesInfo($footprint['related_articles']);
}
}
if ($cacheExpire > 0) {
$cacheDir = __DIR__ . '/cache';
if (!is_dir($cacheDir)) {
mkdir($cacheDir, 0755, true);
}
$cacheFile = $cacheDir . '/' . md5($cacheKey) . '.cache';
file_put_contents($cacheFile, serialize($validFootprints));
}
$this->response->throwJson(array(
'success' => true,
'data' => $validFootprints,
'from_cache' => false
));
} catch (PDOException $e) {
$this->response->throwJson(array(
'success' => false,
'message' => '查询失败: ' . $e->getMessage()
));
}
}
/**
* 获取文章图片
*
* @access public
* @return void
*/
public function getArticleImages()
{
$article_cid = $this->request->get('article_cid');
if (empty($article_cid)) {
$this->response->throwJson(array(
'success' => false,
'message' => '文章CID不能为空'
));
}
try {
$articleInfo = MyTrack_Plugin::getArticleInfo($article_cid);
if (!empty($articleInfo)) {
$response = array(
'success' => true,
'message' => '获取文章信息成功',
'images' => $articleInfo['images'] ?? array(),
'text' => $articleInfo['text'] ?? ''
);
if (!empty($articleInfo['title'])) {
$response['title'] = $articleInfo['title'];
}
if (!empty($articleInfo['link'])) {
$response['link'] = $articleInfo['link'];
}
if (!empty($articleInfo['tags'])) {
$response['tags'] = $articleInfo['tags'];
}
if (!empty($articleInfo['created'])) {
$response['created'] = $articleInfo['created'];
}
$this->response->throwJson($response);
} else {
$this->response->throwJson(array(
'success' => true,
'message' => '该文章中没有找到内容',
'images' => array(),
'text' => ''
));
}
} catch (Exception $e) {
$this->response->throwJson(array(
'success' => false,
'message' => '获取文章信息失败: ' . $e->getMessage()
));
}
}
/**
* 清除足迹缓存
*
* @access private
* @return void
*/
private function clearFootprintCache()
{
try {
$cacheDir = __DIR__ . '/cache';
if (!is_dir($cacheDir)) {
return;
}
$files = glob($cacheDir . '/*.cache');
foreach ($files as $file) {
if (is_file($file)) {
unlink($file);
}
}
} catch (Exception $e) {
error_log('清除MyTrack缓存失败: ' . $e->getMessage());
}
}
}