Current File : /home/resuelf/www/wp-content/plugins/auto-post-thumbnail/includes/class-apt.php |
<?php
namespace WBCR\APT;
use Exception;
use WP_Query;
use WP_Error;
/**
* Class AutoPostThumbnails
*
* @author Artem Prihodko <[email protected]>, Github: https://github.com/temyk
* @copyright (c) 2019, Webcraftic Ltd
*/
class AutoPostThumbnails {
/**
* @var self
*/
public static $instance;
/**
* @var \WAPT_Plugin
*/
private $plugin;
/**
* После какой по счёту колонки вставлять новую (если 0, то в самом начале)
*
* @var integer
*/
public $numberOfColumn;
/**
* @var AutoPostThumbnails
*/
private $nonce;
/**
* Массив с параметрами сервисов
*
* @var array(string)
*/
public $sources;
/**
* Открывается в медиабиблиотеке?
*
* @var bool
*/
public $is_in_medialibrary = false;
/**
* @var
*/
public $allowed_generate_post_types;
/**
* AutoPostThumbnails constructor.
*/
public function __construct() {
$this->numberOfColumn = 4;
$this->plugin = \WAPT_Plugin::app();
$this->sources = [
'google' => WAPT_PLUGIN_SLUG,
'recommend' => '',
'pixabay' => '',
'unsplash' => '',
];
if ( $this->plugin->is_premium() ) {
$this->sources = [
'recommend' => '',
'google' => WAPT_PLUGIN_SLUG,
'pixabay' => '',
'unsplash' => '',
];
}
$this->init_includes();
$this->init();
}
/**
* Get existing instance or create new one.
*
* @return AutoPostThumbnails
*/
public static function instance() {
if ( null === static::$instance ) {
static::$instance = new self();
}
return static::$instance;
}
/**
* Init includes.
*/
private function init_includes() {
// require __DIR__ . '/src/class.template.php';
require_once WAPT_PLUGIN_DIR . '/includes/class-processing.php';
}
/**
* Initiate all required hooks.
*/
private function init() {
$is_auto_generate = $this->plugin->getPopulateOption( 'auto_generation', true );
$is_auto_upload = $this->plugin->getPopulateOption( 'auto_upload_images' );
$allowed_import_post_types = explode( ',', $this->plugin->getPopulateOption( 'import_post_types', 'post' ) );
$this->allowed_generate_post_types = explode( ',', $this->plugin->getPopulateOption( 'auto_post_types', 'post,page' ) );
add_filter( 'mime_types', [ $this, 'allow_upload_webp' ] );
if ( $is_auto_upload && $this->plugin->is_premium() ) {
add_filter( 'wp_insert_post_data', [ $this, 'auto_upload' ], 10, 2 );
// This hook handle update post via rest api. for example WordPress mobile apps
foreach ( $allowed_import_post_types as $post_type ) {
add_action( "rest_after_insert_{$post_type}", [ $this, 'auto_upload' ], 10, 2 );
}
}
if ( $is_auto_generate ) {
// add_action( 'publish_post', [ $this, 'publish_post' ], 10, 1 );
add_action( 'save_post', [ $this, 'save_post' ], 10, 3 );
// This hook handle update post via rest api. for example WordPress mobile apps
foreach ( $this->allowed_generate_post_types as $post_type ) {
add_action( "rest_after_insert_{$post_type}", [ $this, 'rest_after_insert' ], 10, 3 );
}
// This hook will now handle all sort publishing including posts, custom types, scheduled posts, etc.
add_action( 'transition_post_status', [ $this, 'check_required_transition' ], 10, 3 );
} else {
if ( $this->plugin->getPopulateOption( 'auto_generation_notice', 1 ) ) {
add_action( 'admin_notices', [ $this, 'notice_auto_generation' ] );
}
}
add_action( 'wbcr/factory/admin_notices', [ $this, 'check_api_notice' ], 10, 2 );
$this->ajax_actions();
}
private function ajax_actions() {
// AJAX actions
add_action( 'wp_ajax_generatepostthumbnail', [ $this, 'ajax_process_post' ] );
add_action( 'wp_ajax_delete_post_thumbnails', [ $this, 'ajax_delete_post_thumbnails' ] );
add_action( 'wp_ajax_get-posts-ids', [ $this, 'get_posts_ids' ] );
add_action( 'wp_ajax_apt_replace_thumbnail', [ $this, 'apt_replace_thumbnail' ] );
add_action( 'wp_ajax_apt_get_thumbnail', [ $this, 'apt_get_thumbnail' ] );
add_action( 'wp_ajax_source_content', [ $this, 'source_content' ] );
add_action( 'wp_ajax_upload_to_library', [ $this, 'upload_to_library' ] );
add_action( 'wp_ajax_wapt_upload_font', [ $this, 'upload_font' ] );
// APIs
add_action( 'wp_ajax_apt_api_google', [ $this, 'apt_api_google' ] );
add_action( 'wp_ajax_apt_check_api_key', [ $this, 'apt_check_api_key' ] );
add_action( 'wp_ajax_hide_notice_auto_generation', [ $this, 'hide_notice_auto_generation' ] );
}
public function allow_upload_webp( $existing_mimes ) {
$existing_mimes['webp'] = 'image/webp';
return $existing_mimes;
}
/**
* Get posts id's
*
* @return void
*/
public function get_posts_ids() {
if ( ! current_user_can( 'manage_options' ) ) {
die( '-1' );
}
check_ajax_referer( 'get-posts' );
$generate = $this->plugin->getPopulateOption( 'generate_autoimage', 'find' );
$this->plugin->logger->info( "START generate in mode: {$generate}" );
switch ( $generate ) {
case 'generate':
case 'both':
case 'google':
case 'find_google':
$auto_generate = true;
break;
default:
$auto_generate = false;
break;
}
$has_thumb = sanitize_text_field( wp_unslash( $_POST['withThumb'] ?? false ) );
$type = sanitize_text_field( wp_unslash( $_POST['posttype'] ?? '' ) );
if ( $this->plugin->is_premium() ) {
$status = sanitize_text_field( wp_unslash( $_POST['poststatus'] ?? '' ) );
$category = sanitize_text_field( wp_unslash( $_POST['category'] ?? '' ) );
$date_start = sanitize_text_field( wp_unslash( $_POST['date_start'] ?? '' ) );
$date_end = sanitize_text_field( wp_unslash( $_POST['date_end'] ?? '' ) );
$date_start = $date_start ? \DateTime::createFromFormat( 'd.m.Y', $date_start )->format( 'd.m.Y' ) : 0;
$date_end = $date_end ? \DateTime::createFromFormat( 'd.m.Y', $date_end )->setTime( 23, 59 )->format( 'd.m.Y H:i' ) : 0;
// Get id's of the posts that satisfy the filters
//$query = $this->get_posts_query( $has_thumb, $type, $status, $category, $date_start, $date_end );
$query = $this->get_posts_query( [
'has_thumb' => $has_thumb,
'type' => $type,
'status' => $status,
'category' => $category,
'date_start' => $date_start,
'date_end' => $date_end,
] );
} else {
// Get id's of all the published posts for which post thumbnails exist or does not exist
$query = $this->get_posts_query( [
'has_thumb' => $has_thumb,
'type' => $type,
] );
}
$ids = [];
if ( ! empty( $query->posts ) ) {
// Generate the list of IDs
foreach ( $query->posts as $post ) {
$ids[] = $post;
}
}
$ids_str = implode( ',', $ids );
$this->plugin->logger->info( "Queried posts IDs: {$ids_str}" );
wp_send_json_success( $ids );
}
/**
* Process single post to generate the post thumbnail
*
* @return void
*/
public function ajax_process_post() {
if ( ! current_user_can( 'manage_options' ) ) {
die( '-1' );
}
check_ajax_referer( 'generate-post-thumbnails' );
if ( isset( $_POST['id'] ) && ! empty( $_POST['id'] ) ) {
$id = intval( $_POST['id'] );
if ( empty( $id ) ) {
die( '-2' );
}
set_time_limit( 60 );
$this->plugin->logger->info( "--Start processing post ID = {$id}" );
$result = $this->publish_post( $id );
$this->plugin->logger->info( "--End processing post ID = {$id}" );
$thumb_id = $result->thumbnail_id;
if ( $thumb_id ) {
//$result->write_to_log();
wp_send_json_success( $result->getData() );
} else {
$result->write_to_log();
wp_send_json_error( $result->getData() );
}
}
die( '-3' );
}
/**
* Process single post to delete the post thumbnail
*
* @return void
*/
public function ajax_delete_post_thumbnails() {
if ( ! current_user_can( 'manage_options' ) ) {
die( '-1' );
}
check_ajax_referer( 'delete-post-thumbnails' );
if ( isset( $_POST['id'] ) && ! empty( $_POST['id'] ) ) {
$id = intval( $_POST['id'] );
if ( empty( $id ) ) {
die( '-1' );
}
set_time_limit( 60 );
// Pass on the id to our 'publish' callback function.
echo (bool) delete_post_thumbnail( $id );
die( - 1 );
}
die( - 1 );
}
/**
*
*/
public function notice_auto_generation() {
?>
<div class="notice notice-warning is-dismissible" id="notice_auto_generation">
<p><b>Auto Featured Image:</b> Do you want to enable automatic post thumbnail generation? Enable this option
in
<a href="<?php echo esc_url_raw( admin_url( 'admin.php?page=wapt_settings-wbcr_apt&tab=general' ) ); ?>">settings</a><br>
<a href="#" id="hide_notice_auto_generation">Don't ask again</a>
</p>
</div>
<?php
}
/**
*
*/
public function hide_notice_auto_generation() {
if ( isset( $_POST['action'] ) && 'hide_notice_auto_generation' === $_POST['action'] ) {
$this->plugin->updateOption( 'auto_generation_notice', 0 );
}
}
/**
* Function to check whether scheduled post is being published. If so, apt_publish_post should be called.
*
* @param string $new_status
* @param string $old_status
* @param \WP_Post $post Instance of post.
*
* @return void
*/
public function check_required_transition( $new_status = '', $old_status = '', $post = '' ) {
if ( 'publish' === $new_status ) {
$this->publish_post( $post->ID );
}
}
/**
* Return sql query, which allows to receive all the posts without thumbnails
*
* @param array $args
*
* @return WP_Query
*/
public function get_posts_query( $params ) {
$default_params = [
'has_thumb' => false,
'type' => 'post',
'status' => 'publish',
'category' => 0,
'date_start' => 0,
'date_end' => 0,
'is_log' => true,
'count' => 0,
];
$params = wp_parse_args( $params, $default_params );
// phpcs:disable WordPress.PHP.DevelopmentFunctions
if ( $params['is_log'] ) {
$this->plugin->logger->info( 'Posts query: ' . var_export( [
'has_thumb' => $params['has_thumb'],
'type' => $params['is_log'],
'status' => $params['type'],
'category' => $params['category'],
'date_start' => $params['date_start'],
'date_end' => $params['date_end'],
], true ) );
}
// phpcs:enable
$q_status = $params['status'] ? $params['status'] : 'any';
$q_type = $params['type'] ? $params['type'] : 'any';
$q_has_thumb = $params['has_thumb'] ? 'EXISTS' : 'NOT EXISTS';
$args = [
'posts_per_page' => $params['count'] ? $params['count'] : - 1,
'post_status' => $q_status,
'post_type' => $q_type,
'suppress_filters' => true,
'fields' => 'ids',
'meta_query' => [
'relation' => ' and ',
[
'key' => '_thumbnail_id',
'compare' => $q_has_thumb,
],
[
'key' => 'skip_post_thumb',
'compare' => 'NOT EXISTS',
],
],
];
if ( $params['category'] ) {
$args['cat'] = $params['category'];
}
if ( $params['date_start'] && $params['date_end'] ) {
$args['date_query'][] = [
'after' => $params['date_start'],
'before' => $params['date_end'],
'inclusive' => true,
];
}
$query = new WP_Query( $args );
// $this->plugin->logger->debug( "Posts SQL: " . $query->request );
return $query;
}
/**
* Return count of the posts
*
* @return int
*/
public function get_posts_count( $has_thumb = false, $type = 'post' ) {
$query = $this->get_posts_query( [
'has_thumb' => $has_thumb,
'type' => $type,
] );
return $query->post_count ?? 0;
}
/**
* Get thumbnail id for image
*
* @param array $image
*
* @return bool|int
*/
public function get_thumbnail_id( $image ) {
global $wpdb;
$thumb_id = 0;
/**
* If the image is from the WordPress own media gallery, then it appends the thumbnail id to a css class.
* Look for this id in the IMG tag.
*/
if ( isset( $image['tag'] ) && ! empty( $image['tag'] ) ) {
preg_match( '/wp-image-([\d]*)/i', $image['tag'], $thumb_id );
if ( $thumb_id ) {
$thumb_id = $thumb_id[1];
if ( ! get_post( $thumb_id ) ) {
$thumb_id = false;
}
}
}
if ( ! $thumb_id ) {
// If thumb id is not found, try to look for the image in DB.
if ( isset( $image['url'] ) && ! empty( $image['url'] ) ) {
$image_url = $image['url'];
// если ссылка на миниатюру, то регулярка сделает ссылку на оригинал. убирает в конце названия файла -150x150
$image_url = preg_replace( '/-[0-9]{1,}x[0-9]{1,}\./', ' . ', $image_url );
$thumb_id = $wpdb->get_var( "SELECT ID FROM {$wpdb->posts} WHERE guid LIKE ' % " . esc_sql( $image_url ) . " % '" );
}
}
return is_numeric( $thumb_id ) ? $thumb_id : false;
}
/**
* @param \WP_Post $post
* @param \WP_REST_Request $request
* @param bool $is_insert
*
* @throws Exception
*/
public function rest_after_insert( $post, $request, $is_insert ) {
$this->publish_post( $post->ID, $post, ! $is_insert );
}
/**
* Function for 'save_post' hook
*
* @param int $post_id Post ID.
* @param \WP_Post $post
* @param bool $update
*
* @throws Exception
*/
public function save_post( $post_id, $post = null, $update = true ) {
if ( 'revision' === $post->post_type ) {
return;
}
if ( ! in_array( $post->post_type, $this->allowed_generate_post_types ) ) {
$this->plugin->logger->warning( "The post type ({$post->post_type}) is not allowed for generation in settings" );
} else {
$this->publish_post( $post_id, $post, $update );
}
}
/**
* Function to save first image in post as post thumbnail.
*
* @param int $post_id Post ID.
* @param \WP_Post $post
* @param bool $update
*
* @return GenerateResult|null
* @throws Exception
*/
public function publish_post( $post_id, $post = null, $update = true ) {
global $wpdb;
$autoimage = $this->plugin->getPopulateOption( 'generate_autoimage', 'find' );
$generation = new GenerateResult( $post_id, $autoimage );
if ( ! $post ) {
$post = get_post( $post_id );
if ( ! $post ) {
$this->plugin->logger->warning( "The post was not found (post ID = {$post_id})" );
return $generation->result( __( 'The post was not found', 'apt' ) );
}
}
if ( $post->post_status === 'auto-draft' ) {
return null;
}
if ( ! $update ) {
return $generation->result();
}
// First check whether Post Thumbnail is already set for this post.
$_thumbnail_id = get_post_meta( $post_id, '_thumbnail_id', true );
if ( $_thumbnail_id && $wpdb->get_var( "SELECT ID FROM {$wpdb->posts} WHERE id = '" . esc_sql( $_thumbnail_id ) . "' AND post_type = 'attachment'" ) || get_post_meta( $post_id, 'skip_post_thumb', true ) ) {
$this->plugin->logger->warning( "The post ({$post_id}) has already been assigned a featured image" );
return $generation->result( __( 'The post has already been assigned a featured image', 'apt' ) );
}
$thumb_id = 0;
$images = new \WBCR\APT\PostImages( $post_id );
if ( ( $images->is_images() && $images->count_images() ) && $autoimage !== 'generate' && $autoimage !== 'google' ) {
foreach ( $images->get_images() as $image ) {
$thumb_id = $this->get_thumbnail_id( $image );
// If we succeed in generating thumb, let's update post meta
if ( $thumb_id ) {
$this->plugin->logger->info( "An attachment ({$thumb_id}) was found in the text of the post." );
update_post_meta( $post_id, '_thumbnail_id', $thumb_id );
$this->plugin->logger->info( "Featured image ($thumb_id) is set for post ($post_id)" );
} else {
if ( $this->plugin->is_premium() ) {
$thumb_id = apply_filters( 'wapt/generate_post_thumb', $image, $post_id );
if ( $thumb_id ) {
$this->plugin->logger->info( "An image was found in the text of the post and uploaded to medialibrary ({$thumb_id})." );
update_post_meta( $post_id, '_thumbnail_id', $thumb_id );
} else {
$this->plugin->logger->info( "An image was not found in the text of the post" );
}
}
}
return $generation->result( '', $thumb_id );
}
} else {
// создаём свою картинку с заголовком на цветном фоне
if ( $autoimage === 'generate' || $autoimage === 'both' ) {
$thumb_id = $this->generate_and_attachment( $post_id );
if ( $thumb_id ) {
update_post_meta( $post_id, '_thumbnail_id', $thumb_id );
return $generation->result( '', $thumb_id );
}
} elseif ( $autoimage === 'google' || $autoimage === 'find_google' ) {
$response = ( new GoogleImages() )->search( $post->post_title, 1 );
if ( ! empty( $response->images ) ) {
$this->plugin->logger->info( 'Google image search result = ' . var_export( $response->images[0], true ) );
$thumb_id = apply_filters( 'wapt/download_from_google', 0, $response->images, $post_id );
}
if ( $thumb_id ) {
update_post_meta( $post_id, '_thumbnail_id', $thumb_id );
$this->plugin->logger->info( "Successful download from google. Attachment ID = {$thumb_id}" );
return $generation->result( '', $thumb_id );
}
$this->plugin->logger->error( 'Error download from google. ' . var_export( $thumb_id, true ) );
} elseif ( $autoimage === 'use_default' ) {
$thumb_id = $this->UseDefault( $post_id );
if ( $thumb_id ) {
update_post_meta( $post_id, '_thumbnail_id', $thumb_id );
return $generation->result( '', $thumb_id );
}
}
}
return $generation->result( __( 'No images found or generated', 'apt' ) );
}
/**
* Function to save first image in post as post thumbnail.
*
* @param \WP_Post|array $post
* @param array $postarr
*/
public function auto_upload( $data, $postarr = [] ) {
$allowed_post_types = explode( ',', $this->plugin->getPopulateOption( 'import_post_types', '' ) );
if ( $data instanceof \WP_Post ) {
$post_type = $data->post_type ?? '';
} else {
$post_type = $data['post_type'] ?? '';
}
if ( $post_type && in_array( $post_type, $allowed_post_types ) ) {
$data = apply_filters( 'wapt/upload_and_replace_post_images', $data );
}
return $data;
}
/**
* Search through an array for a matching key.
*
* Examples:
* <code>
* $array = array(
* "database.name" => "my_db_name",
* "database.host" => "myhost.com",
* "database.user" => "admin",
* "database.pass" => "a secret."
* );
*
* $search = array_contains_key($array, "database");
* var_dump($search);
*
* Result:
* array (size=4)
* 'database.name' => string 'my_db_name' (length=10)
* 'database.host' => string 'myhost.com' (length=10)
* 'database.user' => string 'admin' (length=5)
* 'database.pass' => string 'a secret.' (length=9)
* </code>
*
* https://gist.github.com/steve-todorov/3671626
*
* @param array $input_array
* @param string $search_value
* @param bool $case_sensitive
*
* @return array
*/
function array_contains_key( array $input_array, $search_value, $case_sensitive = false ) {
if ( $case_sensitive ) {
$preg_match = '/' . $search_value . '/';
} else {
$preg_match = '/' . $search_value . '/i';
}
$return_array = [];
$keys = array_keys( $input_array );
foreach ( $keys as $k ) {
if ( preg_match( $preg_match, $k ) ) {
$return_array[ $k ] = $input_array[ $k ];
}
}
return $return_array;
}
/**
* Fetch image from URL and generate required thumbnails.
*
* @param string $image
* @param string $title
* @param int $post_id
*
* @return int|WP_Error|null
*/
public function generate_post_thumb( $image, $title, $post_id ) {
// Get the URL now for further processing
$imageUrl = $image;
if ( $imageUrl === wp_make_link_relative( $imageUrl ) ) {
$imageUrl = home_url( $imageUrl );
}
$imageTitle = $title;
// Get the file name
$filename = substr( $imageUrl, ( strrpos( $imageUrl, '/' ) ) + 1 );
// исключаем параметры после имени файла
if ( strrpos( $filename, '?' ) ) {
$filename = substr( $filename, 0, strrpos( $filename, '?' ) );
}
if ( ! ( ( $uploads = wp_upload_dir( current_time( 'mysql' ) ) ) && false === $uploads['error'] ) ) {
return null;
}
// Generate unique file name
$filename = wp_unique_filename( $uploads['path'], $filename );
$new_file = $uploads['path'] . "/$filename";
$ext = pathinfo( $new_file, PATHINFO_EXTENSION );
if ( empty( $ext ) ) {
$ext = 'jpg';
$filename .= ".{$ext}";
$new_file .= ".{$ext}";
}
// Move the file to the uploads dir
if ( ! ini_get( 'allow_url_fopen' ) ) {
$file_data = $this->get_file_contents( $imageUrl );
} else {
$arrContextOptions = [
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
],
];
$file_data = file_get_contents( $imageUrl, false, stream_context_create( $arrContextOptions ) );
}
if ( ! $file_data ) {
$this->plugin->logger->debug( "Failed to download the file from the link {$imageUrl}" );
return null;
}
// Fix for checking file extensions
$exts = explode( '.', $filename );
if ( count( $exts ) > 2 ) {
// return null;
}
$allowed = get_allowed_mime_types();
if ( ! $this->array_contains_key( $allowed, $ext ) ) {
$this->plugin->logger->debug( "File type ({$ext}) is not allowed for upload" );
return null;
}
file_put_contents( $new_file, $file_data );
// Set correct file permissions
$stat = stat( dirname( $new_file ) );
$perms = $stat['mode'] & 0000666;
@ chmod( $new_file, $perms );
// Get the file type. Must to use it as a post thumbnail.
$wp_filetype = wp_check_filetype( $filename );
extract( $wp_filetype );
// No file type! No point to proceed further
if ( ( ! $type || ! $ext ) && ! current_user_can( 'unfiltered_upload' ) ) {
return null;
}
// Compute the URL
$url = $uploads['url'] . "/$filename";
// Construct the attachment array
$attachment = [
'post_mime_type' => $type,
'guid' => $url,
'post_parent' => null,
'post_title' => $imageTitle,
'post_content' => '',
];
$thumb_id = wp_insert_attachment( $attachment, $new_file, $post_id );
if ( ! is_wp_error( $thumb_id ) ) {
require_once ABSPATH . '/wp-admin/includes/image.php';
// Added fix by misthero as suggested
wp_update_attachment_metadata( $thumb_id, wp_generate_attachment_metadata( $thumb_id, $new_file ) );
update_attached_file( $thumb_id, $new_file );
return $thumb_id;
} else {
$this->plugin->logger->error( "Failed to add an attachment ({$new_file}) " . var_export( $attachment ) );
}
return null;
}
/**
* Function to fetch the contents of URL using HTTP API in absence of allow_url_fopen.
*/
public function get_file_contents( $URL ) {
$response = wp_remote_get( $URL );
$contents = '';
if ( wp_remote_retrieve_response_code( $response ) === 200 ) {
$contents = wp_remote_retrieve_body( $response );
}
return $contents ? $contents : false;
}
/**
* Используется для динамического обновления столбца "Image" после выбора изображения в общем списке постов
*
* @return array|bool
*
* @uses apt_thumb
*/
public function apt_replace_thumbnail() {
if ( isset( $_POST['post_id'] ) && ! empty( $_POST['post_id'] ) ) {
$post_id = intval( $_POST['post_id'] );
if ( ! current_user_can( 'edit_post', $post_id ) ) {
wp_die( - 1 );
} else {
check_ajax_referer( 'set_post_thumbnail-' . $post_id );
if ( isset( $_POST['thumbnail_id'] ) && ! empty( $_POST['thumbnail_id'] ) ) {
$thumb_id = intval( $_POST['thumbnail_id'] );
if ( $thumb_id === - 1 ) {
// generate image
$thumb_id = $this->generate_and_attachment( $post_id );
}
} elseif ( isset( $_POST['image'] ) && ! empty( $_POST['image'] ) ) {
$img = $_POST['image'];
// Совместимость с NextGen
$img = preg_replace( '/(thumbs\/thumbs_)/', '.', $img );
// Find image in medialibrary
$thumb_id = $this->get_thumbnail_id( [ 'url' => $img ] );
if ( ! $thumb_id ) {
$thumb_id = $this->generate_post_thumb( $img, '', $post_id );
}
} else {
$thumb_id = 0;
}
if ( $thumb_id ) {
update_post_meta( $post_id, '_thumbnail_id', $thumb_id );
}
echo $this->apt_getThumbHtml( $post_id, $thumb_id ); // phpcs:ignore
}
}
die();
}
/**
* Используется для динамической загрузки изображений поста в окно выбора
*
* @return array|bool
* @uses apt_thumb
*/
public function apt_get_thumbnail() {
if ( isset( $_POST['post_id'] ) && ! empty( $_POST['post_id'] ) ) {
$post_id = intval( $_POST['post_id'] );
if ( ! current_user_can( 'edit_post', $post_id ) ) {
wp_die( - 1 );
} else {
check_ajax_referer( 'set_post_thumbnail-' . $post_id );
$nonce = $_POST['_ajax_nonce'];
?>
<div class='apt_thumbs' id='wapt_thumbs'>
<div class='wapt-grid-item'>
<div class="wapt-image-box-library"
data-choose='<?php echo __( 'Choose featured image', 'apt' ); ?>'
data-update='<?php echo __( 'Select image', 'apt' ); ?>'
data-postid='<?php echo $post_id; ?>'
data-nonce='<?php echo $nonce; ?>'
style="background-color: #a3d2ff;">
<div class="wapt-item-generated"><?php echo __( 'Set featured image from medialibrary', 'apt' ); ?></div>
</div>
</div>
</div>
<?php
}
}
include WAPT_ABSPATH . '/admin/views/pro_column.php';
die();
}
/**
* Формирует HTML конструкцию для вывода картинки поста в общей таблице постов
*
* @param $post_id
* @param $thumb_id
*
* @return string HTML конструкция готовая для вывода
*/
public function apt_getThumbHtml( $post_id, $thumb_id ) {
$imgTag = get_the_post_thumbnail( $post_id, [ 100, 0 ], [ 'class' => 'img' ] );
if ( empty( $imgTag ) ) {
$imgTag = esc_html__( 'No image', 'apt' );
}
$title = esc_attr__( 'Change featured image', 'apt' );
$wpnonce = wp_create_nonce( 'set_post_thumbnail-' . $post_id );
$ajaxloader = WAPT_PLUGIN_URL . '/admin/assets/img/ajax-loader.gif';
$content = '';
$html = "<a title='{$title}' href='#' class='modal-init-js' id='modal-init-js_{$post_id}' onclick='return window.aptModalShow(this, {$post_id}, \"$wpnonce\");'>{$imgTag}</a>" . "<span id='loader_{$post_id}' style='display:none;'><img src='{$ajaxloader}' width='100px' alt=''></span><div id='post_imgs_{$post_id}' class='imgs' style='display:none;'><span style='display:none;'><img src='{$ajaxloader}' alt=''></span><div>{$content}</div></div>";
return $html;
}
/**
* Контент подпункта меню в Медиафайлы
*/
public function addToMediaFromApt() {
// media_upload_header();
$this->is_in_medialibrary = true;
$this->sources = apply_filters( 'wapt/sources', $this->sources, 'add_to_media_from_apt' );
require_once WAPT_ABSPATH . '/admin/views/media-library.php';
}
/**
* Контент вкладки
*/
public function media_AptTabContent() {
media_upload_header();
$this->sources = apply_filters( 'wapt/sources', $this->sources, 'tab_content' );
require_once WAPT_ABSPATH . '/admin/views/media-library.php';
}
/**
* AJAX вывод содержимого вкладки сервиса
*/
public function source_content() {
if ( ! wp_verify_nonce( $_POST['wpnonce'], 'apt_content' ) ) {
die( 'Error: Invalid request.' );
}
$this->sources = apply_filters( 'wapt/sources', $this->sources, 'source_content' );
if ( isset( $_POST['source'] ) && ! empty( $_POST['source'] ) ) {
$source = str_replace( 'tab-', '', sanitize_text_field( $_POST['source'] ) );
// if( empty($this->sources[$source]) && !$this->plugin->premium->is_activate() )
if ( empty( $this->sources[ $source ] ) ) {
require_once WAPT_PLUGIN_DIR . '/admin/views/pro.php';
} else {
require_once WP_PLUGIN_DIR . '/' . $this->sources[ $source ] . '/admin/views/sources/' . $source . '.php';
}
}
die();
}
/**
* AJAX загрузка выбранного изображения
*/
public function upload_to_library() {
if ( ! wp_verify_nonce( $_POST['wpnonce'], 'apt_api' ) ) {
die( 'Error: Invalid request.' );
}
if ( isset( $_POST['is_upload'] ) ) {
$postid = intval( $_POST['postid'] );
// get image file
$response = wp_remote_get( $_POST['image_url'], [ 'timeout' => 100 ] );
if ( is_wp_error( $response ) ) {
die( 'Error: ' . esc_html( $response->get_error_message() ) );
}
$file_ext = '';
$image_title = '';
switch ( $_POST['service'] ) {
case 'pixabay':
$path_info = pathinfo( esc_url_raw( $_POST['image_url'] ) );
$file_ext = $path_info['extension'];
$image_title = sanitize_text_field( $_POST['q'] );
break;
case 'unsplash':
parse_str( parse_url( $_POST['image_url'], PHP_URL_QUERY ), $url_query );
$file_ext = $url_query['fm'];
if ( ! $file_ext ) {
$file_ext = 'jpg';
}
$image_title = sanitize_text_field( $_POST['title'] );
break;
case 'google':
$path_info = pathinfo( esc_url_raw( $_POST['image_url'] ) );
$file_ext = $path_info['extension'];
if ( $file_ext !== 'jpg' && $file_ext !== 'jpeg' && $file_ext !== 'png' && $file_ext !== 'gif' ) {
$file_ext = 'jpg';
}
if ( empty( $file_ext ) ) {
$file_ext = 'jpg';
}
$image_title = sanitize_text_field( wp_unslash( $_POST['title'] ?? '' ) );
break;
}
if ( ! $this->is_allowed_file_ext( $file_ext ) ) {
die( 'Error: File extension is not allowed' );
}
$q = sanitize_text_field( wp_unslash( $_POST['q'] ?? '' ) );
$file_name = sanitize_file_name( implode( '_', explode( ' ', $q ) ) . '_' . time() . '.' . $file_ext );
$wp_upload_dir = wp_upload_dir();
$image_upload_path = $wp_upload_dir['path'];
if ( ! is_dir( $image_upload_path ) ) {
// phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged
if ( ! @mkdir( $image_upload_path, 0777, true ) ) {
die( 'Error: Failed to create upload folder ' . esc_html( $image_upload_path ) );
}
// phpcs:enable
}
global $wp_filesystem;
if ( ! $wp_filesystem ) {
if ( ! function_exists( 'WP_Filesystem' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
WP_Filesystem();
}
$target_file_name = $image_upload_path . '/' . $file_name;
$result = $wp_filesystem->put_contents( $target_file_name, $response['body'] );
//$result = @file_put_contents( $target_file_name, $response['body'] );
unset( $response['body'] );
if ( false === $result ) {
die( 'Error: Failed to write file ' . esc_html( $target_file_name ) );
}
// are we dealing with an image
require_once ABSPATH . 'wp-admin/includes/image.php';
if ( ! wp_read_image_metadata( $target_file_name ) ) {
unlink( $target_file_name );
die( 'Error: File is not an image.' );
}
$attachment_caption = '';
// insert attachment
$wp_filetype = wp_check_filetype( basename( $target_file_name ), null );
$attachment = [
'guid' => $wp_upload_dir['url'] . '/' . basename( $target_file_name ),
'post_mime_type' => $wp_filetype['type'],
'post_title' => preg_replace( '/\.[^.]+$/', '', $image_title ),
'post_status' => 'inherit',
];
$attach_id = wp_insert_attachment( $attachment, $target_file_name, $postid );
if ( 0 === $attach_id ) {
die( 'Error: File attachment error' );
}
$attach_data = wp_generate_attachment_metadata( $attach_id, $target_file_name );
$result = wp_update_attachment_metadata( $attach_id, $attach_data );
update_attached_file( $attach_id, $target_file_name );
if ( ! $result ) {
// die( 'Error: File attachment metadata error' );
}
$image_data = [];
$image_data['ID'] = $attach_id;
$image_data['post_excerpt'] = sanitize_text_field( wp_unslash( $_POST['excerpt'] ?? '' ) );
wp_update_post( $image_data );
echo (int) $attach_id;
exit;
}
}
/**
* AJAX загрузка шрифта
*/
public function upload_font() {
if ( ! wp_verify_nonce( $_POST['wpnonce'], 'wapt_upload_font' ) ) {
die( 'Error: Invalid request.' );
}
if ( isset( $_POST['is_font_upload'] ) && count( $_FILES ) > 0 ) {
$file = $_FILES[0];
$upload_dir = wp_upload_dir();
$upload_dir = $upload_dir['basedir'] . '/apt_fonts';
if ( ! is_dir( $upload_dir ) ) {
mkdir( $upload_dir, 0777 );
}
$done_files = [];
$file_name = $file['name'];
// Проверка, что файл является шрифтом TrueType
$header = file_get_contents( $file['tmp_name'], false, null, null, 4 );
if ( $header !== "\x00\x01\x00\x00" && $header !== 'true' && $header !== 'typ1' ) {
die( json_encode( [ 'error' => 'The uploaded file is not a TrueType font' ] ) );
}
// -----
$path = pathinfo( $file['tmp_name'] );
if ( $path['extension'] === 'php' || $path['extension'] === 'js' ) {
die( json_encode( [ 'error' => 'The uploaded file is not a TrueType font.' ] ) );
}
add_filter( 'upload_mimes', function ( $mime_types ) {
$mime_types['ttf'] = 'font/sfnt';
return $mime_types;
}, 10, 1 );
add_filter( 'upload_dir', [ $this, 'set_fonts_upload_dir' ], 10, 1 );
$data = wp_handle_upload( $file, [ 'action' => $_POST['action'] ] );
remove_filter( 'upload_dir', [ $this, 'set_fonts_upload_dir' ], 10 );
if ( ! isset( $data['error'] ) ) {
if ( realpath( $data['file'] ) ) {
$result = [ 'files' => $file ];
} else {
$result = [ 'error' => "Unable to copy the file to the font folder: $upload_dir" ];
}
} else {
$result = [ 'error' => $data['error'] ];
}
die( json_encode( $result ) );
}
}
public function set_fonts_upload_dir( $upload ) {
$upload['subdir'] = '/apt_fonts';
$upload['path'] = $upload['basedir'] . $upload['subdir'];
$upload['url'] = $upload['baseurl'] . $upload['subdir'];
return $upload;
}
/**
* AJAX загрузка google
*/
public function apt_api_google() {
if ( ! wp_verify_nonce( $_POST['nonce'], 'apt_api' ) ) {
die( 'Error: Invalid request.' );
}
if ( isset( $_POST['query'] ) ) {
if ( isset( $_POST['page'] ) ) {
$page = intval( $_POST['page'] );
} else {
$page = 1;
}
$post_title = '';
if ( isset( $_POST['post_id'] ) && is_numeric( $_POST['post_id'] ) ) {
$post = get_post( (int) $_POST['post_id'] );
if ( is_object( $post ) ) {
$post_title = $post->post_title;
}
}
if ( isset( $_POST['watson'] ) ) {
$query = isset( $_POST['query'] ) && ! empty( $_POST['query'] ) && (bool) $_POST['watson'] ? sanitize_text_field( $_POST['query'] ) : $post_title;
} else {
$query = sanitize_text_field( $_POST['query'] ?? '' );
}
try {
$response = ( new GoogleImages() )->search( $query, $query === $post_title ? $page + 1 : $page );
if ( isset( $_POST['limit'] ) && is_numeric( $_POST['limit'] ) ) {
$response->limit( (int) $_POST['limit'] );
}
if ( ! $response->is_error() && isset( $_POST['post_id'] ) && is_numeric( $_POST['post_id'] ) ) {
$post = get_post( (int) $_POST['post_id'] );
if ( $post ) {
$response2 = ( new GoogleImages() )->search( $post->post_title, $page );
if ( isset( $_POST['limit'] ) && is_numeric( $_POST['limit'] ) ) {
$response2->limit( (int) $_POST['limit'] );
}
$response->images = array_merge( $response2->images, $response->images );
}
}
} catch ( Exception $e ) {
die( esc_html( $e->getMessage() ) );
}
if ( $response->is_error() ) {
wp_send_json_error( $response );
}
wp_send_json_success( $response );
}
}
/**
* Проверка API ключей
*/
public function apt_check_api_key() {
if ( ! wp_verify_nonce( $_POST['nonce'], 'check-api-key' ) ) {
die( 'Error: Invalid request.' );
}
if ( isset( $_POST['provider'] ) && isset( $_POST['key'] ) && isset( $_POST['key2'] ) ) {
$provider = trim( $_POST['provider'] );
$key = trim( $_POST['key'] );
$cx = trim( $_POST['key2'] );
switch ( $provider ) {
case 'google':
$url = "https://www.googleapis.com/customsearch/v1?q=cat&key={$key}&cx={$cx}";
$response = wp_remote_get( $url, [ 'timeout' => 100 ] );
if ( is_wp_error( $response ) ) {
die( 'Error: ' . esc_html( $response->get_error_message() ) );
}
$result = json_decode( $response['body'] );
echo (bool) ! isset( $result->error->errors );
break;
}
exit;
}
}
public function check_api_notice( $notices, $plugin_name ) {
// Если экшен вызывал не этот плагин, то не выводим это уведомления
if ( $plugin_name !== $this->plugin->getPluginName() ) {
return $notices;
}
// Получаем заголовок плагина
$plugin_title = $this->plugin->getPluginTitle();
if ( ! $this->plugin->getPopulateOption( 'google_apikey' ) && ! $this->plugin->getPopulateOption( 'google_cse' ) ) {
// Задаем текст уведомления
$notice_text = '<p><b>' . $plugin_title . ':</b> <br>' . sprintf( __( "To download images from Google, specify Google API keys in the <a href='%s'>settings</a>.", 'apt' ), admin_url( 'admin.php?page=wapt_settings-wbcr_apt' ) ) . '</p>';
// Задаем настройки уведомления
$notices[] = [
'id' => 'apt_check_api',
// error, success, warning
'type' => 'warning',
'dismissible' => true,
// На каких страницах показывать уведомление ('plugins', 'dashboard', 'edit')
'where' => [ 'plugins', 'dashboard', 'edit' ],
// Через какое время уведомление снова появится?
'dismiss_expires' => 0,
'text' => $notice_text,
'classes' => [],
];
}
return $notices;
}
/**
* Получение списка шрифтов из папок
*
* @return array
*/
public static function get_fonts() {
$upload_dir = wp_upload_dir();
$upload_dir_fonts = $upload_dir['basedir'] . '/apt_fonts';
$plugin_dir_fonts = WAPT_PLUGIN_DIR . '/fonts';
$fonts = [];
$fonts[] = [
'title' => __( 'Standard', 'apt' ),
'type' => 'group',
];
$files = scandir( $plugin_dir_fonts );
foreach ( $files as $file ) {
if ( $file === '.' || $file === '..' ) {
continue;
}
$name = pathinfo( $plugin_dir_fonts . '/' . $file );
$name = $name['filename'];
$fonts[] = [
'value' => $file,
'title' => $name,
];
}
if ( is_dir( $upload_dir_fonts ) ) {
$files = scandir( $upload_dir_fonts );
}
if ( count( $files ) && \WAPT_Plugin::app()->is_premium() ) {
$fonts[] = [
'title' => __( 'Uploaded', 'apt' ),
'type' => 'group',
];
foreach ( $files as $file ) {
if ( $file === '.' || $file === '..' ) {
continue;
}
$name = pathinfo( $upload_dir_fonts . '/' . $file );
$name = $name['filename'];
$fonts[] = [
'value' => $file,
'title' => $name,
];
}
}
return $fonts;
}
/**
* Генерация изображения с текстом.
* Если $pathToSave задан, то файл сохранится по этому пути.
*
* @param string $text
* @param string $pathToSave
* @param string $format
* @param int $width
* @param int $height
*
* @return Image
*/
public static function generate_image_with_text( $text, $pathToSave = '', $format = 'jpg', $width = 0, $height = 0 ) {
$font = WAPT_PLUGIN_DIR . '/fonts/arial.ttf';
$font_size = \WAPT_Plugin::app()->getPopulateOption( 'font-size', 25 );
$font_color = \WAPT_Plugin::app()->getPopulateOption( 'font-color', '#ffffff' );
if ( $width === 0 ) {
$width = (int) \WAPT_Plugin::app()->getPopulateOption( 'image-width', 800 );
}
if ( $height === 0 ) {
$height = (int) \WAPT_Plugin::app()->getPopulateOption( 'image-height', 600 );
}
$before_text = '';
$after_text = '';
$shadow = \WAPT_Plugin::app()->getPopulateOption( 'shadow', 0 );
if ( ! $shadow ) {
$shadow_color = '';
} else {
$shadow_color = \WAPT_Plugin::app()->getPopulateOption( 'shadow-color', '#ffffff' );
}
$background_type = 'color';
$background = \WAPT_Plugin::app()->getPopulateOption( 'background-color', '#ff6262' );
$text_transform = \WAPT_Plugin::app()->getPopulateOption( 'text-transform', 'no' );
switch ( $text_transform ) {
case 'upper':
$text = mb_strtoupper( $text );
break;
case 'lower':
$text = mb_strtolower( $text );
break;
}
$text_crop = \WAPT_Plugin::app()->getPopulateOption( 'text-crop', 100 );
if ( $text_crop > 0 ) {
if ( strlen( $text ) > $text_crop ) {
$temp = substr( $text, 0, $text_crop );
$text = substr( $temp, 0, strrpos( $temp, ' ' ) );
}
}
$align = 'center';
$valign = 'center';
$padding_tb = 15;
$padding_lr = 15;
$line_spacing = \WAPT_Plugin::app()->getPopulateOption( 'text-line-spacing', 1.5 );
$params = [
'text' => $text,
'pathToSave' => $pathToSave,
'format' => $format,
'width' => $width,
'height' => $height,
];
$image = new Image( $width, $height, $background, $font, $font_size, $font_color );
$image->params = $params;
$image->setPadding( $padding_lr, $padding_tb );
$image->write_text( $before_text . $text . $after_text, '', '', '', $align, $valign, $line_spacing, $shadow_color );
if ( ! empty( $pathToSave ) ) {
$image->save( $pathToSave, 100, $format );
}
return $image;
}
public function find_from_text_category( $post_id ) {
$post = get_post( $post_id );
$response = ( new \WAPT_IBMWatson( strip_tags( $post->post_content ) ) )->categories()->analyze();
}
/**
* Генерация изображения с текстом.
*
* @param integer $post_id
*
* @return integer $thumb_id
*/
public function generate_and_attachment( $post_id ) {
$this->plugin->logger->info( "Start generate attachment for post ID = {$post_id}" );
$format = $this->plugin->getPopulateOption( 'image-type', 'jpg' );
switch ( $format ) {
case 'png':
$extension = 'png';
$mime_type = 'image/png';
break;
case 'jpg':
case 'jpeg':
default:
$extension = 'jpg';
$mime_type = 'image/jpeg';
break;
}
$post = get_post( $post_id, 'OBJECT' );
$uploads = wp_upload_dir( current_time( 'mysql' ) );
$title = apply_filters( 'wapt/generate/title', $post->post_title, $post_id );
// Generate unique file name
$slug = wp_unique_post_slug( sanitize_title( $title ), $post->ID, $post->post_status, $post->post_type, $post->post_parent );
$filename = wp_unique_filename( $uploads['path'], "{$slug}_{$post_id}.{$extension}" );
$file_path = "{$uploads['path']}/{$filename}";
$this->plugin->logger->info( "Generated file path = {$file_path}" );
// Move the file to the uploads dir
$image = apply_filters( 'wapt/generate/image', false, $title, $uploads['path'] . "/$filename", $extension );
if ( ! $image ) {
$image = apply_filters( 'wapt/generate/image', $this->generate_image_with_text( $title, $uploads['path'] . "/$filename", $extension ), $title, $uploads['path'] . "/$filename", $extension );
}
$thumb_id = self::insert_attachment( $post, $file_path, $mime_type );
if ( ! is_wp_error( $thumb_id ) ) {
$this->plugin->logger->info( "Successful generate attachment ID = {$thumb_id}" );
$this->plugin->logger->info( "End generate attachment for post ID = {$post_id}" );
return $thumb_id;
} else {
$this->plugin->logger->error( 'Error generate attachment: ' . var_export( $thumb_id, true ) );
}
return 0;
}
public function UseDefault( $post_id ) {
$this->plugin->logger->info( "Start set default attachment for post ID = {$post_id}" );
$thumb_id = $this->plugin->getPopulateOption( 'default-background', '' );
if ( ! is_wp_error( $thumb_id ) ) {
$this->plugin->logger->info( "Successful set default attachment ID = {$thumb_id}" );
return $thumb_id;
} else {
$this->plugin->logger->error( 'Error set default attachment: ' . var_export( $thumb_id, true ) );
}
return 0;
}
/**
* Insert WP attachment
*
* @param \WP_Post|int $post
* @param string $file_path
* @param string $mime_type
*
* @return int|WP_Error
*/
public static function insert_attachment( $post, $file_path, $mime_type = '' ) {
if ( is_int( $post ) ) {
$post = get_post( $post, 'OBJECT' );
}
if ( ! $post ) {
return new WP_Error( 'apt_attachment', 'Post not found (insert_attachment)' );
}
if ( empty( $mime_type ) ) {
$mime_type = wp_get_image_mime( $file_path );
if ( ! $mime_type ) {
$mime_type = 'image/jpeg';
}
}
$file_url = str_replace( wp_get_upload_dir()['basedir'], wp_get_upload_dir()['baseurl'], $file_path );
if ( file_exists( $file_path ) ) {
$attachment = [
'post_mime_type' => $mime_type,
'guid' => $file_url,
'post_parent' => $post->ID,
'post_title' => $post->post_title,
'post_content' => '',
];
$thumb_id = wp_insert_attachment( $attachment, $file_path, $post->ID );
if ( ! is_wp_error( $thumb_id ) ) {
require_once ABSPATH . '/wp-admin/includes/image.php';
// Added fix by misthero as suggested
wp_update_attachment_metadata( $thumb_id, wp_generate_attachment_metadata( $thumb_id, $file_path ) );
update_attached_file( $thumb_id, $file_path );
return $thumb_id;
}
}
return new WP_Error( 'apt_attachment', 'File not exists (insert_attachment)' );
}
/**
* @param $file_ext
*
* @return bool
*/
public function is_allowed_file_ext( $file_ext ) {
$mimes = get_allowed_mime_types();
foreach ( $mimes as $type => $mime ) {
if ( strpos( $type, $file_ext ) !== false ) {
return true;
}
}
return false;
}
}