晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。 林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。 见渔人,乃大惊,问所从来。具答之。便要还家,设酒杀鸡作食。村中闻有此人,咸来问讯。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”(间隔 一作:隔绝) 既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。 南阳刘子骥,高尚士也,闻之,欣然规往。未果,寻病终。后遂无问津者。
|
Server : Apache System : Linux srv.rainic.com 4.18.0-553.47.1.el8_10.x86_64 #1 SMP Wed Apr 2 05:45:37 EDT 2025 x86_64 User : rainic ( 1014) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/stando/www/wp-content/plugins/wpseo-video/detail-retrieval/ |
Upload File : |
<?php
/**
* @package Internals
* @since 1.8.0
* @version 1.8.0
*/
// Avoid direct calls to this file.
if ( ! class_exists( 'WPSEO_Video_Sitemap' ) ) {
header( 'Status: 403 Forbidden' );
header( 'HTTP/1.1 403 Forbidden' );
exit();
}
/**
*****************************************************************
* Local_File Video SEO Details
*
* I.e. try and retrieve details from a locally saved file or attachment
*
* Example response format [WP 3.9.2 / GetID3 v 1.9.7-20130705]:
*
* Array:
* (
* [lossless (string)] => bool : ( = false )
* [bitrate (string)] => int : 76266
* [bitrate_mode (string)] => string[3] : �cbr�
* [filesize (string)] => int : 388042
* [mime_type (string)] => string[14] : �video/x-ms-wmv�
* [length (string)] => int : 34
* [length_formatted (string)] => string[4] : �0:33�
* [width (string)] => int : 320
* [height (string)] => int : 240
* [fileformat (string)] => string[3] : �asf�
* [dataformat (string)] => string[3] : �wmv�
* [encoder (string)] => string[21] : �Windows Media Video 9�
* [audio (string)] => Array:
* (
* [codec (string)] => string[21] : �Windows Media Audio 9�
* [channels (string)] => int : 1
* [sample_rate (string)] => int : 16000
* [bitrate (string)] => int : 17396
* [bits_per_sample (string)] => int : 16
* [dataformat (string)] => string[3] : �wma�
* [bitrate_mode (string)] => string[3] : �cbr�
* [lossless (string)] => bool : ( = false )
* [encoder (string)] => string[21] : �Windows Media Audio 9�
* [encoder_options (string)] => string[32] : �16 kbps, 16 kHz, mono 1-pass CBR�
* [channelmode (string)] => string[4] : �mono�
* [compression_ratio (string)] => float : 0.067953125
* )
* )
*/
if ( ! class_exists( 'WPSEO_Video_Details_Localfile' ) ) {
/**
* Class WPSEO_Video_Details_Local_File
*
* {@internal This class works slightly different from the other detail retrieval service classes
* in that no remote call is done, but that the details are retrieved are file metadata.
*
* This also means that this class uses a few extra $vid keys to a) pass things to this class and
* b) retain the information found.
*
* The 'maybe_local' (bool) key is used to determine whether to call this class. It would be nicer to
* use 'type' = 'localfile' for this to be in line with the other detail retrieval classes, but that
* could break existing filters on types 'jwplayer', 'mediaelementjs' etc which have been used up to
* now for local files from various sources.
*
* The 'attachment_id' (int) key is used to refer to local attachment posts.
* The 'file_path' (string) key is used to remember the path to the file we determined exists.
*
* The local property file_url always *has* to be set, of the local properties file_path and
* attachment_id only one or the other is expected.}}
*/
class WPSEO_Video_Details_Localfile extends WPSEO_Video_Details {
/**
* File path to a local file, which *may be* a video file (unconfirmed).
*
* @var string
*/
protected $file_path = '';
/**
* URL for a local file, which *may be* a video file (unconfirmed).
*
* @var string
*/
protected $file_url = '';
/**
* Attachment ID, which *may be* a video file (unconfirmed).
*
* @var string
*/
protected $attachment_id = 0;
/**
* Instantiate the class, main routine.
*
* @param array $vid The video array with all the data.
* @param array $old_vid The video array with all the data of the previous "fetch", if available.
*
* @return \WPSEO_Video_Details_Localfile
*/
public function __construct( $vid, $old_vid = array() ) {
if ( $this->could_be_local_video_file( $vid ) === true ) {
parent::__construct( $vid, $old_vid );
}
else {
// @todo [JRF -> Yoast] Why not use (merge with) oldvid data here if available ? The api key might be removed, but old data might still be better than none.
$this->vid = $vid;
}
}
/**
* Determine whether an absolute or relative url is a local file and possibly a video file.
*
* @param array $vid Currently available video info.
*
* @return bool
*/
protected function could_be_local_video_file( $vid ) {
$is_local = false;
if ( ! empty( $vid['file_path'] ) ) {
$this->file_path = $vid['file_path'];
if ( isset( $vid['url'] ) ) {
$this->file_url = $vid['url'];
}
else {
$this->file_url = str_replace( ABSPATH, site_url( '/' ), $this->file_path );
}
$is_local = true;
}
elseif ( ! empty( $vid['attachment_id'] ) ) {
$this->attachment_id = $vid['attachment_id'];
$is_local = true;
}
elseif ( isset( $vid['url'] ) && is_string( $vid['url'] ) && $vid['url'] !== '' ) {
$is_local = $this->is_attachment_or_local_file( $vid['url'] );
}
return $is_local;
}
/**
* Try and determine if a url refers to a local file.
*
* For relative urls, this method recurses onto itself while trying to find the file with a variety
* of absolute versions of the relative url.
*
* @todo This one could do with some refactoring, but at least got it working ;-)
*
* @param string $url The url to test.
*
* @return bool
*/
private function is_attachment_or_local_file( $url ) {
static $uploads;
static $site_url;
static $network_url;
static $search;
static $extensions;
// Set statics.
if ( ! isset( $uploads ) ) {
$uploads = wp_upload_dir();
}
if ( ! isset( $site_url ) ) {
$site_url = preg_replace( '`^http[s]?:`', '', site_url() );
}
if ( ! isset( $network_url ) ) {
if ( is_multisite() ) {
$network_url = preg_replace( '`^http[s]?:`', '', network_site_url() );
}
else {
$network_url = false;
}
}
if ( ! isset( $search ) ) {
$search = array( $site_url . '/' );
if ( ! empty( $network_url ) ) {
$search[] = $network_url . '/';
}
}
if ( ! isset( $extensions ) ) {
$extensions = explode( '|', WPSEO_Video_Sitemap::$video_ext_pattern );
}
/**
* Absolute url
*/
if ( strpos( $url, 'http' ) === 0 || strpos( $url, '//' ) === 0 ) {
$is_local = false;
// Make it protocol relative so we don't have to worry about that.
$url = preg_replace( '`^http[s]?:`', '', $url );
$url = rtrim( $url, '\/' );
// Is this a url on our site/network ?
if ( strpos( $url, $site_url ) === 0 || ( ! empty( $network_url ) && strpos( $url, $network_url ) === 0 ) ) {
$parsed_url = WPSEO_Video_Analyse_Post::parse_url( $url );
if ( $parsed_url['file'] !== '' ) {
$ext = strrchr( $parsed_url['file'], '.' );
if ( $ext !== false && in_array( substr( $ext, 1 ), $extensions, true ) ) {
$base_url = preg_replace( '`^http[s]?:`', '', $uploads['baseurl'] );
if ( strpos( $url, $base_url ) === 0 ) {
$this->file_path = str_replace( $base_url, $uploads['basedir'], $url );
}
else {
$this->file_path = str_replace( $search, ABSPATH, $url );
}
if ( file_exists( $this->file_path ) ) {
$this->file_url = 'http:' . $url;
$is_local = true;
}
}
elseif ( $ext === false ) {
/*
* {@internal At some point in the future we may want to switch this over to the
* attachment_url_to_postid( $url ) function which is introduced in WP 4.0.}}
*/
$path_parts = explode( '/', trim( $parsed_url['path'], '\/' ) );
$last_bit = array_pop( $path_parts );
$query_arg = array(
'post_status' => 'any',
'post_type' => 'attachment',
'name' => $last_bit,
);
$query = new WP_Query( $query_arg );
if ( $query->post_count === 1 ) {
$this->attachment_id = $query->post->ID;
$is_local = true;
}
else {
// Last ditch effort - can we find the file if we add an extension?
$base_url = preg_replace( '`^http[s]?:`', '', $uploads['baseurl'] );
if ( strpos( $url, $base_url ) === 0 ) {
$file_path = str_replace( $base_url, $uploads['basedir'], $url );
}
else {
$file_path = str_replace( $search, ABSPATH, $url );
}
foreach ( $extensions as $extension ) {
if ( file_exists( $file_path . '.' . $extension ) ) {
$this->file_path = $file_path . '.' . $extension;
$this->file_url = 'http:' . $url . '.' . $extension;
$is_local = true;
break;
}
}
}
}
}
elseif ( $parsed_url['query'] !== '' ) {
parse_str( $parsed_url['query'], $query );
if ( ! empty( $query['attachment_id'] ) ) {
$post_id = $query['attachment_id'];
}
elseif ( ! empty( $query['p'] ) ) {
$post_id = $query['p'];
}
if ( isset( $post_id ) && get_post_type( $post_id ) === 'attachment' ) {
$this->attachment_id = $post_id;
$is_local = true;
}
}
}
return $is_local;
}
else {
/**
* Relative path - try and see if we can find the absolute url
*/
if ( $this->is_attachment_or_local_file( site_url( $url ) ) === true ) {
return true;
}
elseif ( is_multisite() && $this->is_attachment_or_local_file( network_site_url( $url ) ) === true ) {
return true;
}
elseif ( $this->is_attachment_or_local_file( $uploads['baseurl'] . '/' . ltrim( $url, '\/' ) ) === true ) {
return true;
}
elseif ( $this->is_attachment_or_local_file( $uploads['url'] . '/' . ltrim( $url, '\/' ) ) === true ) {
return true;
}
elseif ( $this->is_attachment_or_local_file( content_url( $url ) ) === true ) {
return true;
}
elseif ( $this->is_attachment_or_local_file( get_stylesheet_directory_uri() . '/' . ltrim( $url, '\/' ) ) === true ) {
return true;
}
elseif ( $this->is_attachment_or_local_file( get_template_directory_uri() . '/' . ltrim( $url, '\/' ) ) === true ) {
return true;
}
elseif ( $this->is_attachment_or_local_file( plugins_url( $url ) ) === true ) {
return true;
}
return false;
}
}
/**
* Use the "new" post data with the old video data, to prevent the need for an external video
* API call when the video hasn't changed.
*
* Match whether old data can be used on url rather than video id
*
* @param string $match_on Array key to use in the $vid array to determine whether or not to use the old data
* Defaults to 'url' for this implementation.
*
* @return bool Whether or not valid old data was found (and used)
*/
protected function maybe_use_old_video_data( $match_on = 'url' ) {
return parent::maybe_use_old_video_data( $match_on );
}
/**
* Retrieve information on a local video via GetID3.
*
* @uses WPSEO_Video_Details::$remote_url
*
* @return void|string
*/
protected function get_remote_video_info() {
$response = null;
if ( ! empty( $this->attachment_id ) ) {
$response = wp_get_attachment_metadata( $this->attachment_id );
if ( is_array( $response ) && $response !== array() ) {
$this->remote_response = $response;
}
}
elseif ( ! empty( $this->file_path ) ) {
if ( ! function_exists( 'wp_read_video_metadata' ) ) {
require_once ABSPATH . 'wp-admin/includes/media.php';
}
$response = wp_read_video_metadata( $this->file_path );
if ( is_array( $response ) && $response !== array() ) {
$this->remote_response = $response;
}
}
return $response;
}
/**
* Check to see if this is really a video.
*
* @return bool
*/
protected function is_video_response() {
if ( isset( $this->decoded_response['mime_type'] ) && strpos( $this->decoded_response['mime_type'], 'video' ) !== false ) {
if ( ! empty( $this->attachment_id ) ) {
if ( empty( $this->file_url ) ) {
$this->file_url = wp_get_attachment_url( $this->attachment_id );
}
if ( empty( $this->file_path ) ) {
$this->file_path = get_attached_file( $this->attachment_id );
}
}
return true;
}
else {
unset( $this->vid['attachment_id'], $this->vid['file_path'] );
return false;
}
}
/**
* Set video details to their new values
*/
protected function put_video_details() {
// Only save the determined details to the vid array if we're sure it's a video.
$this->set_file_path();
$this->set_file_url();
$this->set_attachment_id();
parent::put_video_details();
}
/**
* Set the attachment id
*/
protected function set_attachment_id() {
if ( ! empty( $this->attachment_id ) ) {
$this->vid['attachment_id'] = $this->attachment_id;
}
}
/**
* Set the content location
*/
protected function set_content_loc() {
if ( ! empty( $this->file_url ) ) {
$this->vid['content_loc'] = $this->file_url;
}
}
/**
* Set the video duration
*
* {@internal In some rare cases this may result in a video time * 1000. This is a GetID3 bug.
* The value will in that case be a string, which is why we use length_formatted in that case.}}
*
* @link https://core.trac.wordpress.org/ticket/29176
*/
protected function set_duration() {
if ( ! empty( $this->decoded_response['length'] ) && ! is_string( $this->decoded_response['length'] ) && $this->decoded_response['length'] > 0 ) {
$this->vid['duration'] = $this->decoded_response['length'];
}
elseif ( ! empty( $this->decoded_response['length_formatted'] ) && $this->decoded_response['length_formatted'] > 0 ) {
// The presumption is made that no videos longer than 24 hours will be posted.
$duration = 0;
$time = explode( ':', $this->decoded_response['length_formatted'] );
if ( count( $time ) === 2 ) {
$duration += $time[1];
$duration += ( $time[0] * MINUTE_IN_SECONDS );
}
elseif ( count( $time ) === 3 ) {
$duration += $time[2];
$duration += ( $time[1] * MINUTE_IN_SECONDS );
$duration += ( $time[0] * HOUR_IN_SECONDS );
}
if ( $duration > 0 ) {
$this->vid['duration'] = $duration;
}
}
}
/**
* Set the file path
*/
protected function set_file_path() {
if ( ! empty( $this->file_path ) ) {
$this->vid['file_path'] = $this->file_path;
}
}
/**
* Set the file url
*/
protected function set_file_url() {
if ( ! empty( $this->file_url ) ) {
$this->vid['file_url'] = $this->file_url;
}
}
/**
* Set the video height
*/
protected function set_height() {
if ( ! empty( $this->decoded_response['height'] ) ) {
$this->vid['height'] = $this->decoded_response['height'];
}
}
/**
* (Don't) Set the player location
*/
protected function set_player_loc() {
return;
}
/**
* Set the thumbnail location - try and find a local image file for the video
*/
protected function set_thumbnail_loc() {
if ( ! empty( $this->file_path ) && ! empty( $this->file_url ) ) {
// @todo transform from path to url.
$img_file = preg_replace( '`\.(' . WPSEO_Video_Sitemap::$video_ext_pattern . ')$`', '', $this->file_path );
$img_url = preg_replace( '`\.(' . WPSEO_Video_Sitemap::$video_ext_pattern . ')$`', '', $this->file_url );
if ( file_exists( $img_file . '.jpg' ) ) {
$this->vid['thumbnail_loc'] = $img_url . '.jpg';
}
elseif ( file_exists( $img_file . '.jpeg' ) ) {
$this->vid['thumbnail_loc'] = $img_url . '.jpeg';
}
elseif ( file_exists( $img_file . '.png' ) ) {
$this->vid['thumbnail_loc'] = $img_url . '.png';
}
elseif ( file_exists( $img_file . '.gif' ) ) {
$this->vid['thumbnail_loc'] = $img_url . '.gif';
}
}
}
/**
* (Don't) Set the video type - leave as is to prevent filters failing
*/
protected function set_type() {
return;
}
/**
* Set the video width
*/
protected function set_width() {
if ( ! empty( $this->decoded_response['width'] ) ) {
$this->vid['width'] = $this->decoded_response['width'];
}
}
} /* End of class */
} /* End of class-exists wrapper */