From f628a0714c2380958aa044bcc062e37865fcb626 Mon Sep 17 00:00:00 2001 From: sy-records <52o@qq52o.cn> Date: Tue, 31 Mar 2020 09:15:25 +0800 Subject: [PATCH] add core --- aliyun-oss-wordpress.php | 577 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 577 insertions(+) create mode 100644 aliyun-oss-wordpress.php diff --git a/aliyun-oss-wordpress.php b/aliyun-oss-wordpress.php new file mode 100644 index 0000000..1594aca --- /dev/null +++ b/aliyun-oss-wordpress.php @@ -0,0 +1,577 @@ + "", + 'regional' => "oss-cn-shanghai", + 'accessKeyId' => "", + 'accessKeySecret' => "", + 'is_internal' => "false", + 'nothumb' => "false", // 是否上传缩略图 + 'nolocalsaving' => "false", // 是否保留本地备份 + 'upload_url_path' => "", // URL前缀 + ); + add_option('oss_options', $options, '', 'yes'); +} + +function oss_get_client() +{ + $oss_opt = get_option('oss_options', true); + $accessKeyId = esc_attr($oss_opt['accessKeyId']); + $accessKeySecret = esc_attr($oss_opt['accessKeySecret']); + $endpoint = oss_get_bucket_endpoint($oss_opt); + return new OssClient($accessKeyId, $accessKeySecret, $endpoint); +} + +function oss_get_bucket_endpoint($oss_option) +{ + $oss_regional = esc_attr($oss_option['regional']); + if ($oss_option['is_internal'] == "true") { + return $oss_regional . "-internal.aliyuncs.com"; + } + return $oss_regional . ".aliyuncs.com"; +} + +function oss_get_bucket_name() +{ + $oss_opt = get_option('oss_options', true); + return $oss_opt['bucket']; +} + +/** + * 上传函数 + * + * @param $object + * @param $file + * @param $opt + * @return bool + */ +function oss_file_upload($object, $file) +{ + //如果文件不存在,直接返回false + if (!@file_exists($file)) { + return false; + } + $bucket = oss_get_bucket_name(); + $ossClient = oss_get_client(); + try{ + $ossClient->uploadFile($bucket, ltrim($object, "/"), $file); + } catch ( OssException $e ) { +// echo 'Error Message:' . $e->getMessage() . PHP_EOL; +// echo 'Error Code:' . $e->getCode() . PHP_EOL; + } +} + +/** + * 是否需要删除本地文件 + * + * @return bool + */ +function oss_is_delete_local_file() +{ + $oss_options = get_option('oss_options', true); + return (esc_attr($oss_options['nolocalsaving']) == 'true'); +} + +/** + * 删除本地文件 + * + * @param $file + * @return bool + */ +function oss_delete_local_file($file) +{ + try { + //文件不存在 + if (!@file_exists($file)) { + return true; + } + + //删除文件 + if (!@unlink($file)) { + return false; + } + + return true; + } catch (Exception $ex) { + return false; + } +} + +/** + * 删除oss中的文件 + * @param $file + * @return bool + */ +function oss_delete_oss_file($file) +{ + $bucket = oss_get_bucket_name(); + $ossClient = oss_get_client(); + $ossClient->deleteObject($bucket, $file); +} + +/** + * 上传附件(包括图片的原图) + * + * @param $metadata + * @return array() + */ +function oss_upload_attachments($metadata) +{ + //生成object在oss中的存储路径 + if (get_option('upload_path') == '.') { + //如果含有“./”则去除之 + $metadata['file'] = str_replace("./", '', $metadata['file']); + } + $object = str_replace("\\", '/', $metadata['file']); + $object = str_replace(get_home_path(), '', $object); + + //在本地的存储路径 + $file = get_home_path() . $object; //向上兼容,较早的WordPress版本上$metadata['file']存放的是相对路径 + + //执行上传操作 + oss_file_upload('/' . $object, $file); + + //如果不在本地保存,则删除本地文件 + if (oss_is_delete_local_file()) { + oss_delete_local_file($file); + } + return $metadata; +} + +//避免上传插件/主题时出现同步到oss的情况 +if (substr_count($_SERVER['REQUEST_URI'], '/update.php') <= 0) { + add_filter('wp_handle_upload', 'oss_upload_attachments', 50); +} + +/** + * 上传图片的缩略图 + */ +function oss_upload_thumbs($metadata) +{ + //上传所有缩略图 + if (isset($metadata['sizes']) && count($metadata['sizes']) > 0) { + //获取oss插件的配置信息 + $oss_options = get_option('oss_options', true); + //是否需要上传缩略图 + $nothumb = (esc_attr($oss_options['nothumb']) == 'true'); + //是否需要删除本地文件 + $is_delete_local_file = (esc_attr($oss_options['nolocalsaving']) == 'true'); + //如果禁止上传缩略图,就不用继续执行了 + if ($nothumb) { + return $metadata; + } + //获取上传路径 + $wp_uploads = wp_upload_dir(); + $basedir = $wp_uploads['basedir']; + $file_dir = $metadata['file']; + //得到本地文件夹和远端文件夹 + $file_path = $basedir . '/' . dirname($file_dir) . '/'; + if (get_option('upload_path') == '.') { + $file_path = str_replace("\\", '/', $file_path); + $file_path = str_replace(get_home_path() . "./", '', $file_path); + } else { + $file_path = str_replace("\\", '/', $file_path); + } + + $object_path = str_replace(get_home_path(), '', $file_path); + + //there may be duplicated filenames,so .... + foreach ($metadata['sizes'] as $val) { + //生成object在oss中的存储路径 + $object = '/' . $object_path . $val['file']; + //生成本地存储路径 + $file = $file_path . $val['file']; + + //执行上传操作 + oss_file_upload($object, $file); + + //如果不在本地保存,则删除 + if ($is_delete_local_file) { + oss_delete_local_file($file); + } + + } + } + return $metadata; +} + +//避免上传插件/主题时出现同步到oss的情况 +if (substr_count($_SERVER['REQUEST_URI'], '/update.php') <= 0) { + add_filter('wp_generate_attachment_metadata', 'oss_upload_thumbs', 100); +} + +/** + * 删除远端文件,删除文件时触发 + * @param $post_id + */ +function oss_delete_remote_attachment($post_id) { + $meta = wp_get_attachment_metadata( $post_id ); + + $oss_options = get_option('oss_options', true); + + if (isset($meta['file'])) { + // meta['file']的格式为 "2020/01/wp-bg.png" + $upload_path = get_option('upload_path'); + if ($upload_path == '') { + $upload_path = 'wp-content/uploads'; + } + $file_path = $upload_path . '/' . $meta['file']; + oss_delete_oss_file(str_replace("\\", '/', $file_path)); + $is_nothumb = (esc_attr($oss_options['nothumb']) == 'false'); + if ($is_nothumb) { + // 删除缩略图 + if (isset($meta['sizes']) && count($meta['sizes']) > 0) { + foreach ($meta['sizes'] as $val) { + $size_file = dirname($file_path) . '/' . $val['file']; + oss_delete_oss_file(str_replace("\\", '/', $size_file)); + } + } + } + } +} +add_action('delete_attachment', 'oss_delete_remote_attachment'); + +// 当upload_path为根目录时,需要移除URL中出现的“绝对路径” +function oss_modefiy_img_url($url, $post_id) +{ + $home_path = str_replace(array('/', '\\'), array('', ''), get_home_path()); + $url = str_replace($home_path, '', $url); + return $url; +} + +if (get_option('upload_path') == '.') { + add_filter('wp_get_attachment_url', 'oss_modefiy_img_url', 30, 2); +} + +function oss_function_each(&$array) +{ + $res = array(); + $key = key($array); + if ($key !== null) { + next($array); + $res[1] = $res['value'] = $array[$key]; + $res[0] = $res['key'] = $key; + } else { + $res = false; + } + return $res; +} + +function oss_read_dir_queue($dir) +{ + if (isset($dir)) { + $files = array(); + $queue = array($dir); + while ($data = oss_function_each($queue)) { + $path = $data['value']; + if (is_dir($path) && $handle = opendir($path)) { + while ($file = readdir($handle)) { + if ($file == '.' || $file == '..') { + continue; + } + $files[] = $real_path = $path . '/' . $file; + if (is_dir($real_path)) { + $queue[] = $real_path; + } + //echo explode(get_option('upload_path'),$path)[1]; + } + } + closedir($handle); + } + $i = ''; + foreach ($files as $v) { + $i++; + if (!is_dir($v)) { + $dd[$i]['j'] = $v; + $dd[$i]['x'] = '/' . get_option('upload_path') . explode(get_option('upload_path'), $v)[1]; + } + } + } else { + $dd = ''; + } + return $dd; +} + +// 在插件列表页添加设置按钮 +function oss_plugin_action_links($links, $file) +{ + if ($file == plugin_basename(dirname(__FILE__) . '/aliyun-oss-wordpress.php')) { + $links[] = '设置'; + $links[] = '赞赏'; + } + return $links; +} +add_filter('plugin_action_links', 'oss_plugin_action_links', 10, 2); + +// 在导航栏“设置”中添加条目 +function oss_add_setting_page() +{ + add_options_page('阿里云OSS设置', '阿里云OSS设置', 'manage_options', __FILE__, 'oss_setting_page'); +} + +add_action('admin_menu', 'oss_add_setting_page'); + +// 插件设置页面 +function oss_setting_page() +{ + if (!current_user_can('manage_options')) { + wp_die('Insufficient privileges!'); + } + $options = array(); + if (!empty($_POST) and $_POST['type'] == 'oss_set') { + $options['bucket'] = isset($_POST['bucket']) ? sanitize_text_field($_POST['bucket']) : ''; + $options['regional'] = isset($_POST['regional']) ? sanitize_text_field($_POST['regional']) : ''; + $options['accessKeyId'] = isset($_POST['accessKeyId']) ? sanitize_text_field($_POST['accessKeyId']) : ''; + $options['accessKeySecret'] = isset($_POST['accessKeySecret']) ? sanitize_text_field($_POST['accessKeySecret']) : ''; + $options['is_internal'] = isset($_POST['is_internal']) ? 'true' : 'false'; + $options['nothumb'] = isset($_POST['nothumb']) ? 'true' : 'false'; + $options['nolocalsaving'] = isset($_POST['nolocalsaving']) ? 'true' : 'false'; + //仅用于插件卸载时比较使用 + $options['upload_url_path'] = isset($_POST['upload_url_path']) ? sanitize_text_field(stripslashes($_POST['upload_url_path'])) : ''; + } + + if (!empty($_POST) and $_POST['type'] == 'aliyun_oss_all') { + $synv = oss_read_dir_queue(get_home_path() . get_option('upload_path')); + $i = 0; + foreach ($synv as $k) { + $i++; + oss_file_upload($k['x'], $k['j']); + } + echo '

本次操作成功同步' . $i . '个文件

'; + } + + // 替换数据库链接 + if(!empty($_POST) and $_POST['type'] == 'aliyun_oss_replace') { + global $wpdb; + $table_name = $wpdb->prefix .'posts'; + $oldurl = esc_url_raw($_POST['old_url']); + $newurl = esc_url_raw($_POST['new_url']); + $result = $wpdb->query("UPDATE $table_name SET post_content = REPLACE( post_content, '$oldurl', '$newurl') "); + + echo '

替换成功!共批量执行'.$result.'条!

'; + } + + // 若$options不为空数组,则更新数据 + if ($options !== array()) { + //更新数据库 + update_option('oss_options', $options); + + $upload_path = sanitize_text_field(trim(stripslashes($_POST['upload_path']), '/')); + $upload_path = ($upload_path == '') ? ('wp-content/uploads') : ($upload_path); + update_option('upload_path', $upload_path); + $upload_url_path = sanitize_text_field(trim(stripslashes($_POST['upload_url_path']), '/')); + update_option('upload_url_path', $upload_url_path); + echo '

设置已保存!

'; + } + + $oss_options = get_option('oss_options', true); + $upload_path = get_option('upload_path'); + $upload_url_path = get_option('upload_url_path'); + + $oss_bucket = esc_attr($oss_options['bucket']); + $oss_regional = esc_attr($oss_options['regional']); + $oss_accessKeyId = esc_attr($oss_options['accessKeyId']); + $oss_accessKeySecret = esc_attr($oss_options['accessKeySecret']); + + $oss_is_internal = esc_attr($oss_options['is_internal']); + $oss_is_internal = ($oss_is_internal == 'true'); + + $oss_nothumb = esc_attr($oss_options['nothumb']); + $oss_nothumb = ($oss_nothumb == 'true'); + + $oss_nolocalsaving = esc_attr($oss_options['nolocalsaving']); + $oss_nolocalsaving = ($oss_nolocalsaving == 'true'); + + $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; + ?> +
+

阿里云 OSS 设置 当前版本:

+

如果觉得此插件对你有所帮助,不妨到 Github 上点个StarWatch关注更新;

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Bucket名称 + + + +

请先访问 阿里云控制台 创建Bucket,再填写以上内容。

+
+ 区域 + +

请选择您创建的Bucket所在区域

+
+ AccessKeyId +
+ AccessKeySecret + + +
+ 是否使用内网传输 + + /> +

如果你的服务器是在阿里云并且区域和Bucket所在区域一致,请勾选。

+
+ 不上传缩略图 + + /> +

建议不勾选

+
+ 不在本地保留备份 + + /> +

建议不勾选

+
+ 本地文件夹 + + +

附件在服务器上的存储位置,例如: wp-content/uploads (注意不要以“/”开头和结尾),根目录请输入.

+
+ URL前缀 + + + +

注意:

+ +

1)URL前缀的格式为 {OSS外网访问Bucket域名}/{本地文件夹} ,“本地文件夹”务必与上面保持一致(结尾无 / ),或者“本地文件夹”为 .{OSS外网访问域名}

+ +

2)OSS中的存放路径(即“文件夹”)与上述 本地文件夹 中定义的路径是相同的(出于方便切换考虑)。

+ +

3)如果需要使用 用户域名 ,直接将 {OSS外网访问Bucket域名} 替换为 用户域名 即可。

+
保存/更新选项
+ +
+
+ + + + + + +
+ 同步历史附件 + + +

注意:如果是首次同步,执行时间将会十分十分长(根据你的历史附件数量),有可能会因执行时间过长,页面显示超时或者报错。
所以,建议那些几千上万附件的大神们,考虑官方的 同步工具

+
+
+
+
+ + + + + + + + + + + + + + +
+ 数据库原链接替换 + + +
+ + + +
+ + + +

注意:如果是首次替换,请注意备份!此功能只限于替换文章中使用的资源链接

+
+
+
+