File: /www/wwwroot/www.213n.cn/wp-content/plugins/wpturbo/module/storage.php
<?php
/**
* Class WPTurbo_Storage
* @author quaniz
* Author URI: https://www.wbolt.com
*/
class WPTurbo_Storage extends WPTurbo_Base
{
public $debug = false;
public function __construct()
{
if(is_admin()){
add_action('wp_ajax_wpturbo', [$this,'wpturbo_ajax']);
}
$opt = self::cnf();
if($opt['switch']){
add_filter('wp_generate_attachment_metadata',[$this,'generate_attachment_metadata'],100,3);
add_action( 'delete_attachment', [$this,'delete_attachment'],10,2 );
$oss_domain = $this->oss_domain();
if($oss_domain && ($opt['oss_mode'] == 'server' || $opt['oss_mode'] == 'server_adv')){// && $opt['domain']
add_filter('wp_get_attachment_metadata',[$this,'get_attachment_metadata'],900,2);
add_filter('wp_calculate_image_srcset',[$this,'calculate_image_srcset'],20,5);
add_filter('wp_get_attachment_url',[$this,'get_attachment_url'],20,2);
//add_filter('wp_get_attachment_image_src',[$this,'get_attachment_image_src'],20,4);
//add_filter('image_get_intermediate_size',[$this,'get_intermediate_size'],20,3);
//add_filter('image_downsize',[$this,'image_downsize'],20,2);
/*add_filter('wp_calculate_image_srcset_meta',function ($image_meta, $size_array, $image_src, $attachment_id){
print_r($image_meta);
return $image_meta;
},20,4);*/
}
}
//add_filter('the_content',[$this,'the_content'],10);
}
public function the_content($content)
{
$opt = self::cnf();
if($opt['switch']){
return $content;
}
//oss domain
$oss_domain = $this->oss_domain();
if(!$oss_domain){
return $content;
}
$content = preg_replace('#https?://'.preg_quote($oss_domain).'/#i',home_url('/'),$content);
//print_r([$opt['domain']]);
/*if(preg_match_all("#<img.+?src=('|\")(.+?".preg_quote($opt['domain']).".+?)\\1.+?>#is",$content,$match)){
//print_r($match);
foreach($match[2] as $src){
$src_new = preg_replace('#https?://'.preg_quote($opt['domain']).'/#i',home_url('/wp-content/uploads/'),$src);
$src_new = preg_replace('#\?.+#','',$src_new);
$content = str_replace($src,$src_new,$content);
}
//$content = preg_replace('#https?://'.preg_quote($opt['domain']).'/#i',home_url('/wp-content/uploads/'),$content);
//$content = preg_replace('#\?x-oss-[^\s\'"]+#i','',$content);
}*/
return $content;
}
public function get_intermediate_size($data, $post_id, $size)
{
//print_r($data);
return $data;
}
public function get_attachment_image_src($image, $attachment_id, $size, $icon)
{
$oss = get_post_meta($attachment_id,'wb-oss',1);
if(!$oss){
return $image;
}
//print_r($image);
return $image;
}
public function get_attachment_url($url,$post_id)
{
//print_r([$url]);
$oss = get_post_meta($post_id,'wb-oss',true);
if(!$oss){
return $url;
}
$file = get_post_meta( $post_id, '_wp_attached_file', true );
if(!$file){
return $url;
}
$base_path = preg_replace('#https?://[^/]+/#','',$url);
//$opt = self::cnf();
$new = 'http://';
if(is_ssl()){
$new = 'https://';
}
$oss_domain = $this->oss_domain();
return $new.trailingslashit( $oss_domain).$base_path;
//$new .= trailingslashit( $opt['domain']).'/'.$file;
//print_r([$new]);
//return $new;
}
public function calculate_image_srcset($sources, $size_array, $image_src, $image_meta, $attachment_id)
{
//print_r([$sources, $size_array, $image_src, $image_meta, $attachment_id]);
//print_r($sources);
$oss = get_post_meta($attachment_id,'wb-oss',true);
if(!$oss){
return $sources;
}
if(empty($sources) || !is_array($sources)){
return $sources;
}
//$opt = self::cnf();
$oss_domain = $this->oss_domain();
$new_base = 'http://';
if(is_ssl()){
$new_base = 'https://';
}
$new_base .= trailingslashit( $oss_domain);
//$upload_dir = wp_get_upload_dir();
//$image_baseurl = trailingslashit( $upload_dir['baseurl'] );
//print_r([$image_baseurl,$new_base]);
foreach($sources as $k=>$r){
$sources[$k]['url'] = preg_replace('#^https?://[^/]+/#',$new_base,$r['url']);
}
//print_r($sources);
return $sources;
}
public function get_attachment_metadata($data,$attachment_id)
{
$oss = get_post_meta($attachment_id,'wb-oss',true);
if(!$oss){
return $data;
}
if(!isset($data['sizes']) || empty($data['sizes'])){
return $data;
}
$file = $data['file'] ?? '';
if(!$file){
$file = get_post_meta($attachment_id,'_wp_attached_file',true);
}
if(preg_match('#\.pdf$#',$file)){
return $data;
}
$opt = self::cnf();
$vendor = $opt['vendor'];
$name = basename($file);
if(!isset($data['sizes'])){
return $data;
}
foreach($data['sizes'] as $s=>$r){
if(!isset($r['file'])){
continue;
}
if(!preg_match('#\.(png|jpg|jpeg|webp|gif)$#i',$r['file'])){
continue;
}
$rule = '';
if(isset($r['width'],$r['height'])){
if($vendor == 'aliyun'){
$rule = '?x-oss-process=image/resize,m_lfit';
if($r['width']>0){
$rule .= ',w_'.$r['width'];
}
if($r['height']>0){
$rule .= ',h_'.$r['height'];
}
}else if($vendor == 'tencent'){
$rule = '?imageMogr2/thumbnail/';
if($r['width']>0){
$rule .= $r['width'];
}
if($r['height']>0){
$rule .= 'x'.$r['height'];
}else{
$rule .= 'x';
}
}else if($vendor == 'huawei'){
$rule = '?x-image-process=image/resize,m_lfit';
if($r['width']>0){
$rule .= ',w_'.$r['width'];
}
if($r['height']>0){
$rule .= ',h_'.$r['height'];
}
}else if($vendor == 'baidu'){
$rule = '?x-bce-process=image/resize,m_lfit';
if($r['width']>0){
$rule .= ',w_'.$r['width'];
}
if($r['height']>0){
$rule .= ',h_'.$r['height'];
}
}
}
$data['sizes'][$s]['file'] = $name.''.$rule;
}
//print_r($data);
return $data;
}
public function delete_attachment($post_id, $post)
{
$oss = get_post_meta($post_id,'wb-oss',1);
if(!$oss){
return;
}
try{
do{
$file = get_post_meta($post_id,'_wp_attached_file',true);
if(!$file){
break;
}
$upload = wp_get_upload_dir();
$baseurl = preg_replace('#https?://[^/]+/#','',$upload['baseurl'].'/');
$this->delete($baseurl.$file);
if(preg_match('#\.(png|jpg|jpeg|webp|gif)$#i',$file)){
break;
}
$base_path = dirname($file);
$meta = get_post_meta($post_id,'_wp_attachment_metadata',true);
if(isset($meta['sizes']))foreach($meta['sizes'] as $s=>$r){
if(!isset($r['file']))continue;
$this->delete($baseurl.$base_path.'/'.$r['file']);
}
}while(0);
}catch (Exception $ex){
}
}
public function generate_attachment_metadata($metadata, $attachment_id, $state)
{
if($state != 'create'){
return $metadata;
}
try{
do{
//2022/06/filename
$file = get_post_meta($attachment_id,'_wp_attached_file',true);
if(!$file){
break;
}
$upload = wp_get_upload_dir();
/*Array
(
[path] => /home/www/wordpress/wp-content/uploads/2022/03
[url] => http://domain.com/wp-content/uploads/2022/03
[subdir] => /2022/03
[basedir] => /home/www/wordpress/wp-content/uploads
[baseurl] => http://domain.com/wp-content/uploads
[error] =>
)*/
$baseurl = preg_replace('#https?://[^/]+/#','',$upload['baseurl'].'/');
$local_file = $upload['basedir'].'/'.$file;
if(!file_exists($local_file)){
break;
}
$opt = self::cnf();
$result = $this->upload($baseurl.$file,$local_file);
$base_path = dirname($file);
update_post_meta($attachment_id,'wb-oss','1');
$sizes = $metadata['sizes'] ?? [];
$folder = dirname($local_file);
if(!preg_match('#\.(png|jpg|jpeg|webp|gif)$#i',$file)){
foreach($sizes as $r){
$thumb_file = $folder.'/'.$r['file'];
$this->upload($baseurl.$base_path.'/'.$r['file'],$thumb_file);
}
}
$del_local = $opt['oss_mode'] == 'server' && $opt['local'] == 'delete';
if($opt['oss_mode'] == 'server_adv' || $del_local){
// unlink($local_file);
wp_delete_file($local_file);
copy(WPTURBO_ROOT.'/assets/empty.gif',$local_file);
foreach($sizes as $r){
$thumb_file = $folder.'/'.$r['file'];
// unlink($thumb_file);
wp_delete_file($thumb_file);
}
}
}while(0);
}catch (Exception $ex){
$this->txt_log($ex->getMessage());
}
return $metadata;
}
public function txt_log($msg)
{
if(!$this->debug){
return;
}
error_log($msg."\n", 3, __DIR__.'/storage_run.log');
}
public function delete($path)
{
$opt = self::cnf();
$client = $this->get_client();
if(is_wp_error($client)){
throw new Exception(esc_html($client->get_error_message()));
}
$vendor = $opt['vendor'];
$oss = $opt[$vendor] ?? [];
$result = null;
switch ($vendor)
{
case 'aliyun':
$result = $client->deleteObject($oss['bucket'], $path);
break;
case 'tencent':
$result = $client->deleteObject(array(
'Bucket' => $oss['bucket'],
'Key' => $path
));
break;
case 'huawei':
$result = $client->deleteObject(
[
'Bucket' => $oss['bucket'],
'Key' => $path
]
);
break;
case 'baidu':
try{
$result = $client->deleteObject($oss['bucket'],$path);
}catch (BaiduBce\Exception\BceServiceException $ex){
}
break;
}
return $result;
}
/**
* 上传
* @param $path
* @param $local_file
* @throws Exception
*/
public function upload($path,$local_file)
{
$opt = self::cnf();
$client = $this->get_client();
if(is_wp_error($client)){
throw new Exception(esc_html($client->get_error_message()));
}
$vendor = $opt['vendor'];
$oss = $opt[$vendor] ?? [];
$result = null;
switch ($vendor)
{
case 'aliyun':
$result = $client->uploadFile($oss['bucket'], $path, $local_file);
break;
case 'tencent':
$result = $client->upload($oss['bucket'], $path, fopen($local_file, 'rb'));
break;
case 'huawei':
$result = $client->putObject([
'Bucket' => $oss['bucket'],
'Key' => $path,
'SourceFile' => $local_file
]);
break;
case 'baidu':
$result = $client->putObjectFromFile($oss['bucket'],$path,$local_file);
break;
}
return $result;
}
public function exists($path)
{
$opt = self::cnf();
$client = $this->get_client();
if(is_wp_error($client)){
throw new Exception(esc_html($client->get_error_message()));
}
$vendor = $opt['vendor'];
$oss = $opt[$vendor] ?? [];
$result = null;
switch ($vendor)
{
case 'aliyun':
$result = $client->doesObjectExist($oss['bucket'], $path);
break;
case 'tencent':
$result = $client->doesObjectExist($oss['bucket'], $path);
break;
case 'huawei':
try{
$result = $client->getObjectMetadata([
'Bucket' => $oss['bucket'],
'Key' => $path,
]);
return true;
}catch (Obs\ObsException $ex){
return false;
}
break;
case 'baidu':
try {
$result = $client->getObjectMetadata($oss['bucket'], $path);
return true;
}catch(BaiduBce\Exception\BceServiceException $ex){
return false;
}
break;
}
return $result;
}
public function get_client()
{
static $instance = null;
if($instance!=null){
return $instance;
}
$opt = self::cnf();
$vendor = $opt['vendor'];
$oss = $opt[$vendor] ?? [];
if(empty($oss)){
return new WP_Error('500','没有找到OSS配置');
}
$empty = 0;
foreach ($oss as $v){
if(empty($v)){
$empty = 1;
break;
}
}
if($empty){
return new WP_Error('500','没有找到OSS配置');
}
require_once WPTURBO_ROOT.'/vendor/autoload.php';
$client = null;
switch ($vendor){
case 'aliyun':
try {
$client = new OSS\OssClient($oss['id'], $oss['key'], $oss['endpoint']);
} catch (OSS\Core\OssException $e) {
return new WP_Error('500',$e->getMessage());
}
break;
case 'tencent':
$client = new Qcloud\Cos\Client(
[
'region' => $oss['endpoint'],
//'schema' => is_ssl()?'https':'http', //协议头部,默认为http
'credentials'=> [
'secretId' => $oss['id'] ,
'secretKey' => $oss['key']
]
]);
break;
case 'huawei':
$client = Obs\ObsClient::factory ( [
'key' => $oss['id'],
'secret' => $oss['key'],
'endpoint' => $oss['endpoint'],
'socket_timeout' => 30,
'connect_timeout' => 10
] );
break;
case 'baidu':
require_once WPTURBO_ROOT.'/vendor/BaiduBce.phar';
$client = new BaiduBce\Services\Bos\BosClient(
[
'credentials' => [
'accessKeyId' => $oss['id'],
'secretAccessKey' => $oss['key'],
//'sessionToken' => 'your session token'
],
'endpoint' => str_replace($oss['bucket'].'.','',$oss['endpoint']),
//'endpoint' => $oss['endpoint'],
//'stsEndpoint' => 'sts host',
]
);
break;
}
if(!$client){
$client = new WP_Error('500','OSS初始化错误');
}else{
$instance = $client;
}
return $client;
}
public function wpturbo_ajax()
{
$op = trim(self::param('op'));
if(!$op){
return;
}
$allow = [
'storage_update', 'storage_setting', 'storage_upload_media_to_oss'
];
if(!in_array($op, $allow)){
return;
}
if(!current_user_can('manage_options')){
self::ajax_resp(['code' => 1, 'desc' => 'deny']);
return;
}
if (!wp_verify_nonce(sanitize_text_field(self::param('_ajax_nonce')), 'wp_ajax_wpturbo')) {
self::ajax_resp(['code'=>1,'desc'=>'illegal']);
return;
}
switch ($op)
{
case 'storage_update':
$ret = ['code'=>1,'desc'=>'fail'];
do{
$opt = $this->sanitize_text_array(self::param('opt', []));
if(empty($opt) || !is_array($opt)){
$ret['desc'] = 'illegal';
break;
}
if($opt['conf'] == 'file'){
$vendor = $opt['vendor'];
$oss = $opt[$vendor] ?? [];
if($oss){
$this->update_conf_file($oss);
$opt[$vendor]['id'] = '';
$opt[$vendor]['key'] = '';
$opt[$vendor]['bucket'] = '';
$opt[$vendor]['endpoint'] = '';
}
}
if($opt){
if(empty($opt['switch']) || $opt['switch'] === 'false'){
$opt['switch'] = 0;
}else{
$opt['switch'] = 1;
}
update_option( 'wpturbo_storage', $opt );
}
$ret['code'] = 0;
$ret['desc'] = 'success';
}while(0);
self::ajax_resp($ret);
break;
case 'storage_setting':
$ret = [];
$ret['opt'] = self::cnf();
$ret['dir'] = wp_upload_dir();
$ret['media_num'] = $this->media_count();
$ret['code'] = 0;
$ret['desc'] = 'success';
self::ajax_resp($ret);
break;
case 'storage_upload_media_to_oss':
do {
$total = intval(self::param('total'));
if($total < 1){
$ret = ['code'=>0,'data'=>0,'desc'=>'success'];
break;
}
$this->upload_media_to_oss(20);
$ret = ['code'=>0,'data'=>max($total - 20,0),'desc'=>'success'];
}while(0);
self::ajax_resp($ret);
break;
}
}
public function upload_media_to_oss($num)
{
// global $wpdb;
$db = self::db();
$sql = "SELECT ID
FROM $db->posts a
WHERE a.post_type = 'attachment' AND a.post_mime_type LIKE 'image/%' AND (
NOT EXISTS (SELECT 1 FROM $db->postmeta mt1 WHERE mt1.post_ID = a.ID AND mt1.meta_key = 'wb-oss' LIMIT 1)
)";
$list = $db->get_col($sql." LIMIT $num");
if($list)foreach($list as $ID){
$meta = get_post_meta($ID,'_wp_attachment_metadata',true);
if(!$meta)continue;
$this->generate_attachment_metadata($meta,$ID,'create');
}
}
public function media_count()
{
/// global $wpdb;
$db = self::db();
$sql = "SELECT COUNT(1)
FROM $db->posts a
WHERE a.post_type = 'attachment' AND a.post_mime_type LIKE 'image/%' AND (
NOT EXISTS (SELECT 1 FROM $db->postmeta mt1 WHERE mt1.post_ID = a.ID AND mt1.meta_key = 'wb-oss' LIMIT 1)
)";
return $db->get_var($sql);
/*
$param = [
'post_type'=>'attachment',
'post_status'=>'any',
'no_found_rows'=>true,
'nopaging'=>true,
'post_mime_type'=>'image/*',
'meta_query'=>[
['key'=>'wb-oss','compare_key'=>'NOT EXISTS']
]
];
query_posts($param);
return 0;*/
}
public function update_conf_file($conf)
{
if(!file_exists(ABSPATH.'/wp-config.php')){
return;
}
$content = file_get_contents(ABSPATH.'/wp-config.php');
$content = preg_replace('#define\(\'WPTURBO_OSS.+;\s*#i','',$content);
$s = "define('WP_DEBUG'";
$row = preg_split('#define\(\'WP_DEBUG\'#',$content,2);
if(count($row) != 2){
$s = "\$table_prefix";
$row = preg_split('#\$table_prefix#',$content,2);
}
if(!isset($row[1])){
return;
}
$new = [];
$oss_id = $conf['id'] ?? '';
$oss_key = $conf['key'] ?? '';
$oss_bucket = $conf['bucket'] ?? '';
$oss_endpoint = $conf['endpoint'] ?? '';
$new[] = $row[0].sprintf("define('WPTURBO_OSS_ID', '%s');",$oss_id);
$new[] = sprintf("define('WPTURBO_OSS_KEY', '%s');",$oss_key);
$new[] = sprintf("define('WPTURBO_OSS_BUCKET', '%s');",$oss_bucket);
$new[] = sprintf("define('WPTURBO_OSS_ENDPOINT', '%s');",$oss_endpoint);
$new[] = $s.$row[1];
file_put_contents(ABSPATH.'/wp-config.php',implode("\n",$new));
}
public static function def()
{
$default_conf = array(
'switch' => 0,
'conf' => 'db',
'vendor' => 'aliyun',
'aliyun' => [
'id' => '',
'key' => '',
'bucket' => '',
'endpoint' => '',
],
'tencent' => [
'id' => '',
'key' => '',
'bucket' => '',
'endpoint' => '',
],
'upyun' => [
'id' => '',
'key' => '',
'bucket' => '',
'endpoint' => '',
],
'huawei' => [
'id' => '',
'key' => '',
'bucket' => '',
'endpoint' => '',
],
'baidu' => [
'id' => '',
'key' => '',
'bucket' => '',
'endpoint' => '',
],
'oss_mode' => 'back',
'local' => 'keep',
'domain' => '',
);
return $default_conf;
}
private function oss_domain()
{
$cnf = self::cnf();
$vendor = $cnf['vendor'] ?? 'aliyun';
$oss = $cnf[$vendor] ?? $cnf['aliyun'];
$domain = $oss['domain'] ?? ($cnf['domain'] ?? '');
if($domain){
$domain = preg_replace('#^https?://#','',$domain);
$domain = preg_replace('#/.+#','',$domain);
$domain = trim($domain,'/');
}
return $domain;
}
//sve
public static function cnf($key=null,$default=null){
static $_option = array();
if(!$_option){
$_option = get_option('wpturbo_storage');
if(!$_option || !is_array($_option)){
$_option = [];
}
$default_conf = self::def();
foreach ($default_conf as $k=>$v){
if(!isset($_option[$k]))$_option[$k] = $v;
}
if($_option['conf'] == 'file'){
$vendor = $_option['vendor'];
$oss = $_option[$vendor] ?? [];
if($oss){
$oss['id'] = defined('WPTURBO_OSS_ID') ? WPTURBO_OSS_ID : $oss['id'];
$oss['key'] = defined('WPTURBO_OSS_KEY') ? WPTURBO_OSS_KEY : $oss['key'];
$oss['bucket'] = defined('WPTURBO_OSS_BUCKET') ? WPTURBO_OSS_BUCKET : $oss['bucket'];
$oss['endpoint'] = defined('WPTURBO_OSS_ENDPOINT') ? WPTURBO_OSS_ENDPOINT : $oss['endpoint'];
$_option[$vendor] = $oss;
}
}
$_option['local'] = 'keep';
if($_option['oss_mode'] === 'server_adv'){
$_option['local'] = 'delete';
}
if(empty($_option['switch']) || $_option['switch'] === 'false'){
$_option['switch'] = 0;
}else{
$_option['switch'] = 1;
}
}
if(null === $key){
return $_option;
}
if(isset($_option[$key])){
return $_option[$key];
}
return $default;
}
}