Files
orico-official-website/app/command/DataMigration.php
2025-04-12 14:49:20 +08:00

342 lines
11 KiB
PHP
Raw 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
declare (strict_types = 1);
namespace app\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
class DataMigration extends Command
{
protected $println;
private function println($msg) {
($this->println)($msg);
}
protected function configure()
{
// 指令配置
$this->setName('migrate')
->setDescription('执行数据迁移');
}
protected function execute(Input $input, Output $output)
{
// 指令输出
$this->println = function ($msg) use ($output) {
$output->writeln($msg);
};
// 迁移tock产品分类
// $this->productTcoCategory();
// 迁移产品分类
// $this->productCategory();
// 迁移文章
// $this->migrateArticle([
// 1 => 2,
// 2 => 3,
// 33 => 4,
// 36 => 5,
// 16 => 7,
// 31 => 8,
// 32 => 9
// ]);
// 迁移faq
// $this->migrateFaq();
$output->writeln('success');
}
// 迁移tco产品分类
private function productTcoCategory()
{
$category = Db::connect('old')
->name('product_tco_category')
->select();
foreach ($category as $val) {
$item = [
'id' => $val['id'],
'language_id' => $val['country_code'] == 'ZH' ? 1 : 2,
'name' => $val['name'],
'tco_id' => $val['tco_id'],
'tco_pid' => $val['tco_pid'],
'tco_path' => $val['tco_path'],
'erp_id' => $val['erp_id'],
'erp_pid' => $val['erp_pid'],
'erp_path' => $val['erp_path'],
'erp_code' => $val['erp_code'],
'disabled' => $val['disabled'],
'sync_time' => $val['sync_time'],
];
Db::name('product_tco_category')->insert($item);
}
}
// 迁移产品分类
private function productCategory()
{
$tco_category = Db::connect('old')
->name('product_tco_category')
->select();
$tco_category_map = [];
foreach ($tco_category as $val) {
$key = sprintf("%s_%s", $val['category_id'], $val['country_code']);
if (isset($tco_category_map[$key])) {
$tco_category_map[$key] = [];
}
$tco_category_map[$key][] = $val['id'];
}
$category = Db::connect('old')
->name('product_category')
->select()
->toArray();
// 处理数据
$this->handlerProductCategory(array_to_tree($category, 0, 'pid', 1), $tco_category_map);
}
private function handlerProductCategory($category, $map) {
foreach ($category as $val) {
$key = sprintf("%s_%s", $val['id'], $val['country_code']);
$item = [
'id' => $val['id'],
'language_id' => $val['country_code'] == 'ZH' ? 1 : 2,
'unique_id' => uniqid('PRO_CATE_'),
'pid' => $val['pid'],
'name' => $val['name'],
'icon' => $val['icon'],
'desc' => $val['description'],
'related_tco_category' => isset($map[$key]) ? implode(',', $map[$key]) : '',
'sort' => $val['sort'] == 9999 ? 0 : $val['sort'],
'level' => $val['level'],
'is_show' => $val['isshow'],
];
Db::name('product_category')->insert($item);
if (isset($val['children'])) {
$this->handlerProductCategory($val['children'], $map);
}
}
}
// 迁移文章
private function migrateArticle($category_map = [])
{
$this->println('开始迁移文章......');
if (empty($category_map)) {
throw new \Exception('请确认分类ID');
}
$article = Db::connect('old')
->name('article')
->where('cid', 'in', array_keys($category_map))
->order(['id' => 'asc'])
->cursor();
$uploadMgr = new UploadMannager();
foreach ($article as $v) {
// 处理封面图片
$image = '';
$ret = $uploadMgr->upload($uploadMgr->download($v['picture']), 'image');
if ($ret['code'] == 0) {
$image = $ret['data']['path'];
} else {
$image = $ret['msg'];
}
// 处理详情中图片
$content = $v['content'];
preg_match_all('/<img.*?src=[\'"](.*?)[\'"].*?>/i', $content, $matches);
$content_images = [];
foreach ($matches[1] as $val) {
try {
$ret = $uploadMgr->upload($uploadMgr->download($val), 'image');
if ($ret['code'] == 0) {
$content_images[$val] = $ret['data']['path'];
}
} catch (\Throwable $th) {
continue;
}
}
foreach ($content_images as $key => $val) {
$content = str_replace($key, $val, $content);
}
$item = [
'language_id' => $v['country_code'] == 'ZH' ? 1 : 2,
'category_id' => $category_map[$v['cid']],
'title' => $v['name'],
'author' => $v['writer'],
'source' => $v['source'],
'image' => $image,
'desc' => $v['description'],
'recommend' => $v['recommend'],
'sort' => $v['sort'] == 9999 ? 0 : $v['sort'],
'link' => $v['jump_link'],
'content' => $content,
'view_count' => $v['viewcount'],
'praise_count' => $v['zancount'],
'seo_title' => $v['seo_title'],
'seo_keywords' => $v['seo_keyword'],
'seo_desc' => $v['seo_description'],
'enabled' => $v['stat'],
'release_time' => date('Y-m-d H:i:s', $v['createtime'])
];
Db::name('article')->insert($item);
$this->println('迁移文章ID' . $v['id']);
}
}
// 迁移FAQ
private function migrateFaq()
{
$faq = Db::connect('old')
->name('fq')
->where('id', '>=', 10)
->where('stat', '>=', 0)
->select();
$uploadMgr = new UploadMannager();
foreach ($faq as $key => $val) {
$image = '';
$ret = $uploadMgr->upload($uploadMgr->download($val['picture']), 'image');
if ($ret['code'] == 0) {
$image = $ret['data']['path'];
} else {
$image = $ret['msg'];
}
$content = explode("\n", $val['content']);
$content = '<p>' . implode("</p><p>", $content) . '</p>';
$item = [
'language_id' => $val['country_code'] == 'ZH' ? 1 : 2,
'image' => $image,
'question' => $val['name'],
'answer' => $content,
'recommend' => $val['is_home'],
'sort' => $val['sort'] == 9999 ? 0 : $val['sort']
];
Db::name('faq')->insert($item);
}
}
}
class UploadMannager
{
const UPLOAD_BASE_API = 'http://dev.ow.f2b211.com';
const DOWNLOAD_BASE_API = 'https://www.orico.com.cn';
const DOWNLOAD_TEMP_PATH = '/var/www/html/orico-official-website/public/migrate_temp_images';
private $username = 'admin';
private $password = 'Aa-1221';
private $token = '';
private $retrys = [];
public function __construct()
{
// 登录获取token
$this->token = $this->getAuthorization();
}
// 下载图片
public function download($file_name)
{
if (empty($file_name)) {
return '';
}
$url = $file_name;
if (\think\helper\Str::startsWith($file_name, 'http')) {
$need = 'orico.com.cn';
if (!\think\helper\Str::contains($file_name, $need)) {
return $url;
}
$url = self::DOWNLOAD_BASE_API . \think\helper\Str::substr($file_name, mb_strpos($file_name, $need) + mb_strlen($need));
} else {
$url = self::DOWNLOAD_BASE_API . str_replace(" ", "%20", $file_name);
}
$file_path = self::DOWNLOAD_TEMP_PATH . $file_name;
$opts = [
'http' => [
'method' => 'GET',
'header' => 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
]
];
$context = stream_context_create($opts);
$file = file_get_contents($url, false, $context);
$dir = dirname($file_path);
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
file_put_contents($file_path, $file, FILE_USE_INCLUDE_PATH);
return $file_path;
}
// 上传图片
public function upload($file_path, $field_name) {
if (empty($file_path)) {
return ['code' => 0, 'msg' => 'file_path为空', 'data' => ['path' => '']];
}
$ch = curl_init(self::UPLOAD_BASE_API . '/admapi/v1/images/faq/upload');
$post_data = [
$field_name => new \CURLFile($file_path)
];
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $this->token
]);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// 登录失效
if ($http_code == 401) {
$this->token = $this->getAuthorization();
if (!isset($this->retrys[$file_path])) {
$this->retrys[$file_path] = 0;
}
if ($this->retrys[$file_path] > 0) {
throw new \Exception('[' . $file_path . ']上传重试失败');
}
$this->retrys[$file_path] += 1;
return $this->upload($file_path, $field_name);
}
return json_decode($response, true);
}
// 登录获取token
private function getAuthorization()
{
$ch = curl_init(self::UPLOAD_BASE_API . '/admapi/v1/user/login');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'username' => $this->username,
'password' => md5($this->password)
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code != 200) {
throw new \Exception('获取token失败');
}
$result = json_decode($response, true);
if ($result['code'] != 0) {
throw new \Exception($result['msg']);
}
return $result['data']['token'];
}
}