| Server IP : 172.67.159.97 / Your IP : 216.73.217.154 Web Server : nginx/1.24.0 System : Linux wordpress-sites 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64 User : www-data ( 33) PHP Version : 8.1.34 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /var/www/rebeccaone.com/wp-content/plugins/envira-gallery/src/Frontend/ |
Upload File : |
<?php
/**
* Handles all background proccessing interactions for the Envira Gallery plugin.
*
* @since 1.7.0
*
* @package Envira Gallery
* @author Envira Gallery Team <[email protected]>
*/
namespace Envira\Frontend;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Envira\Utils\Cropping;
use WP_REST_Response;
/**
* Background Processing Class.
*
* @since 1.7.0
*/
class Background {
/**
* API Namespace
*
* (default value: 'envira')
*
* @since 1.7.0
*
* @var string
* @access public
*/
public $domain = 'envira-background';
/**
* API Version
*
* (default value: 'v1')
*
* @since 1.7.0
*
* @var string
* @access public
*/
public $version = 'v1';
/**
* Holds API Request
*
* (default value: null)
*
* @var mixed
* @access public
*/
public $request = null;
/**
* Class Constructor.
*
* @since 1.7.0
*
* @access public
*/
public function __construct() {
// Actions.
add_action( 'rest_api_init', [ $this, 'register_api_routes' ] );
}
/**
* Permission callback for background processing endpoints.
*
* @since 1.7.0
*
* @param WP_REST_Request $request Request object.
* @return bool|WP_REST_Response
*/
public function verify_background_permission( $request ) {
// Check if user is logged in.
if ( ! is_user_logged_in() ) {
return new WP_REST_Response( [ 'message' => __( 'You must be logged in to access this feature.', 'envira-gallery' ) ], 401 );
}
// Check if user can edit posts (basic capability for gallery management).
$required_capability = apply_filters( 'envira_background_processing_capability', 'edit_posts' );
if ( ! current_user_can( $required_capability ) ) {
return new WP_REST_Response( [ 'message' => __( 'You do not have permission to access this feature.', 'envira-gallery' ) ], 403 );
}
// Validate the request using existing validation method.
$valid = $this->validate_request( $request );
if ( ! $valid ) {
return new WP_REST_Response( [ 'message' => __( 'Invalid request. Security check failed.', 'envira-gallery' ) ], 403 );
}
return true;
}
/**
* Register API Routes used for background proccessing.
*
* @since 1.7.0
*
* @access public
* @return void
*/
public function register_api_routes() {
$name = $this->domain;
$version = $this->version;
register_rest_route(
$name . '/' . $version,
'/insert-gallery',
[
'methods' => 'POST',
'callback' => [ $this, 'maybe_insert_gallery' ],
'permission_callback' => [ $this, 'verify_background_permission' ],
]
);
register_rest_route(
$name . '/' . $version,
'/insert-album',
[
'methods' => 'POST',
'callback' => [ $this, 'maybe_insert_album' ],
'permission_callback' => [ $this, 'verify_background_permission' ],
]
);
register_rest_route(
$name . '/' . $version,
'/insert-image',
[
'methods' => 'POST',
'callback' => [ $this, 'insert_image' ],
'permission_callback' => [ $this, 'verify_background_permission' ],
]
);
register_rest_route(
$name . '/' . $version,
'/crop-images',
[
'methods' => 'POST',
'callback' => [ $this, 'crop_images' ],
'permission_callback' => [ $this, 'verify_background_permission' ],
]
);
register_rest_route(
$name . '/' . $version,
'/resize-image',
[
'methods' => 'POST',
'callback' => [ $this, 'resize' ],
'permission_callback' => [ $this, 'verify_background_permission' ],
]
);
do_action( 'envira_gallery_routes', $name, $version );
}
/**
* Insert_gallery function.
*
* @since 1.7.0
*
* @access public
* @param \WP_REST_Request $request Request.
* @return void
*/
public function maybe_insert_gallery( \WP_REST_Request $request ) {
// Set the request.
$this->request = $request;
// Get the body.
$body = $request->get_body_params();
// Validate the request.
$valid = $this->validate_request( $request );
// Setup the ID Var.
$post_id = '';
// Return if request not valid.
if ( ! $valid ) {
return;
}
$defaults = [
'ID' => 0,
'post_type' => 'envira',
'post_status' => 'publish',
'post_title' => '',
];
$post_args = wp_parse_args( $body['data']['gallery'], $defaults );
if ( isset( $body['data']['id'] ) ) {
$post_id = get_post( $body['data']['id'] );
}
if ( ! $post_id ) {
$post = wp_insert_post( $post_args );
} else {
$post = wp_update_post( $post_args );
}
// make a request to insert images is.
if ( is_array( $body['data']['images'] ) ) {
$images = $body['data']['images'];
foreach ( $images as $image => $data ) {
// Build the Image Data.
$image_data = [
'gallery' => $post,
'image' => $data,
];
// Make the background request for inserting each image.
$this->background_request( $image_data, 'insert-image' );
}
}
die();
}
/**
* Background request to insert images into a gallery.
*
* @since 1.7.0
*
* @access public
* @param \WP_REST_Request $request Request.
* @return void
*/
public function insert_image( \WP_REST_Request $request ) {
global $wp_filesystem;
if ( empty( $wp_filesystem ) ) {
require_once ABSPATH . '/wp-admin/includes/file.php';
WP_Filesystem();
}
// Set the request.
$this->request = $request;
// Get the body.
$body = $request->get_body_params();
// Validate the request.
$valid = $this->validate_request( $request );
// Return if request not valid.
if ( ! $valid ) {
return;
}
// Require if the function doesnt exist.
if ( ! function_exists( 'wp_handle_sideload' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
include ABSPATH . 'wp-admin/includes/image.php';
}
$post_id = $body['data']['gallery'];
$image = $body['data']['image'];
// Check that $post_id is a envira post_type.
if ( 'envira' !== get_post_type( $post_id ) ) {
return false;
}
$in_gallery = get_post_meta( $post_id, '_eg_in_gallery', true );
if ( empty( $in_gallery ) ) {
$in_gallery = [];
}
$gallery_data = get_post_meta( $post_id, '_eg_gallery_data', true );
// If Gallery Data is emptyy prepare it.
if ( empty( $gallery_data ) ) {
$gallery_data = [];
}
// Set the File name from the API.
$new_attachment = $image['title'];
// Grab the Upload Directory.
$upload_dir = wp_upload_dir();
// Set the upload path.
$upload_path = str_replace( '/', DIRECTORY_SEPARATOR, $upload_dir['path'] ) . DIRECTORY_SEPARATOR;
// Decode the returned image.
$image_upload = $wp_filesystem->put_contents( $upload_path . $new_attachment, $wp_filesystem->get_contents( $image['src'] ) );
// Prep the new file.
$file = [];
$file['error'] = '';
$file['tmp_name'] = $upload_path . $new_attachment;
$file['name'] = $new_attachment;
$file['type'] = $gallery_data;
$file['size'] = wp_filesize( $upload_path . $new_attachment );
$file_return = wp_handle_sideload( $file, [ 'test_form' => false ] );
// Setup the Attachment Data.
$attachment = [
'post_type' => 'attachment',
'post_mime_type' => 'image/jpeg',
'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $new_attachment ) ),
'post_content' => '',
'post_status' => 'inherit',
'post_parent' => $post_id,
];
// Insert new attachment - check.
$attachment_id = wp_insert_attachment( $attachment, $file_return['file'], $post_id );
// Generate Attachment Metadata.
$meta_data = wp_generate_attachment_metadata( $attachment_id, $file_return['file'] );
// Update Attachments metadata.
$update_data = wp_update_attachment_metadata( $attachment_id, $meta_data );
// Update the attachment image post meta first.
$has_slider = get_post_meta( $attachment_id, '_eg_has_gallery', true );
if ( empty( $has_slider ) ) {
$has_slider = [];
}
$has_slider[] = $post_id;
// Now add the image to the slider for this particular post.
$in_slider[] = $attachment_id;
$slider_data = envira_prepare_gallery_data( $gallery_data, $attachment_id );
// Update the slider data.
update_post_meta( $attachment_id, '_eg_has_gallery', $has_slider );
update_post_meta( $post_id, '_eg_in_gallery', $in_slider );
update_post_meta( $post_id, '_eg_gallery_data', $slider_data );
die();
}
/**
* Maybe insert album function.
*
* @since 1.7.0
*
* @access public
* @param \WP_REST_Request $request Request.
* @return void
*/
public function maybe_insert_album( \WP_REST_Request $request ) {
// Set the request.
$this->request = $request;
// Get the body.
$body = $request->get_body_params();
// Validate the request.
$valid = $this->validate_request( $request );
// Setup the ID Var.
$post_id = '';
// Return if request not valid.
if ( ! $valid ) {
die();
}
$defaults = [
'ID' => 0,
'post_type' => 'envira-album',
'post_status' => 'publish',
'post_title' => '',
];
$post_args = wp_parse_args( $body['data']['album'], $defaults );
if ( isset( $body['data']['id'] ) ) {
$post_id = get_post( $body['data']['id'] );
}
if ( ! $post_id ) {
$post = wp_insert_post( $post_args );
} else {
$post = wp_update_post( $post_args );
}
// make a request to insert images is.
if ( is_array( $body['data']['galleries'] ) ) {
$galleries = $body['data']['galleries'];
foreach ( $galleries as $gallery => $data ) {
// Build the Image Data.
$image_data = [
'album' => $post,
'galleries' => $data,
];
// Make the background request for inserting each image.
$this->background_request( $image_data, 'insert-gallery' );
}
}
die();
}
/**
* Crop and image via background request.
*
* @since 1.7.0
*
* @access public
* @param \WP_REST_Request $request Request.
* @return void
*/
public function crop_images( \WP_REST_Request $request ) {
// Set the request.
$this->request = $request;
// Get the body.
$body = $request->get_body_params();
// Validate the request.
$valid = $this->validate_request( $request );
// Return if request not valid.
if ( ! $valid ) {
die();
}
$data = $body['data'];
$gallery_data = _envira_get_gallery( $body['data']['id'] );
$gallery_id = $body['data']['id'];
$images = ! empty( $gallery_data['gallery'] ) ? $gallery_data['gallery'] : false;
$align = envira_get_config( 'crop_position', $gallery_data );
// Loop through the images and crop them.
if ( $images ) {
foreach ( $images as $id => $item ) {
// Get the full image attachment. If it does not return the data we need, skip over it.
$image = wp_get_attachment_image_src( $id, 'full' );
if ( ! is_array( $image ) ) {
continue;
}
// Check the image is a valid URL.
// Some plugins decide to strip the blog's URL.
if ( ! filter_var( $image[0], FILTER_VALIDATE_URL ) ) {
$image[0] = get_bloginfo( 'url' ) . '/' . $image[0];
}
// If the thumbnails option is checked, crop images accordingly.
if ( isset( $gallery_data['config']['thumbnails'] ) && $gallery_data['config']['thumbnails'] ) {
$args = [
'align' => $align,
'width' => apply_filters( 'envira_gallery_lightbox_thumbnail_width', $gallery_data['config']['thumbnails_width'], $gallery_data ),
'height' => apply_filters( 'envira_gallery_lightbox_thumbnail_height', $gallery_data['config']['thumbnails_height'], $gallery_data ),
'quality' => 100,
'retina' => false,
];
$crop_data = [
'args' => $args,
'gallery_id' => $gallery_id,
'image_url' => $image[0],
];
// Generate the cropped image.
$this->background_request( $crop_data, 'resize-image' );
$args['retina'] = true;
$crop_data = [
'args' => $args,
'gallery_id' => $gallery_id,
'image_url' => $image[0],
];
// Generate the cropped image.
$this->background_request( $crop_data, 'resize-image' );
}
// If the mobile thumbnails option is checked, crop images accordingly.
if ( isset( $gallery_data['config']['mobile_thumbnails'] ) && $gallery_data['config']['mobile_thumbnails'] ) {
$args = [
'align' => $align,
'width' => apply_filters( 'envira_gallery_mobile_lightbox_thumbnail_width', $gallery_data['config']['mobile_thumbnails_width'], $gallery_data ),
'height' => apply_filters( 'envira_gallery_mobile_lightbox_thumbnail_height', $gallery_data['config']['mobile_thumbnails_height'], $gallery_data ),
'quality' => 100,
'retina' => false,
];
$crop_data = [
'args' => $args,
'gallery_id' => $gallery_id,
'image_url' => $image[0],
];
// Generate the cropped image.
$this->background_request( $crop_data, 'resize-image' );
$args['retina'] = true;
$crop_data = [
'args' => $args,
'gallery_id' => $gallery_id,
'image_url' => $image[0],
];
// Generate the cropped image.
$this->background_request( $crop_data, 'resize-image' );
}
// If the crop option is checked, crop images accordingly.
if ( isset( $gallery_data['config']['crop'] ) && $gallery_data['config']['crop'] ) {
$args = [
'align' => $align,
'width' => envira_get_config( 'crop_width', $gallery_data ),
'height' => envira_get_config( 'crop_height', $gallery_data ),
'quality' => 100,
'retina' => false,
];
$crop_data = [
'args' => $args,
'gallery_id' => $gallery_id,
'image_url' => $image[0],
];
// Generate the cropped image.
$this->background_request( $crop_data, 'resize-image' );
$args['retina'] = true;
$crop_data = [
'args' => $args,
'gallery_id' => $gallery_id,
'image_url' => $image[0],
];
// Generate the cropped image.
$this->background_request( $crop_data, 'resize-image' );
}
// If the mobile option is checked, crop images accordingly.
if ( isset( $gallery_data['config']['mobile'] ) && $gallery_data['config']['mobile'] ) {
$args = [
'align' => $align,
'width' => envira_get_config( 'mobile_width', $gallery_data ),
'height' => envira_get_config( 'mobile_height', $gallery_data ),
'quality' => 100,
'retina' => false,
];
$crop_data = [
'args' => $args,
'gallery_id' => $gallery_id,
'image_url' => $image[0],
];
// Generate the cropped image.
$this->background_request( $crop_data, 'resize-image' );
$args['retina'] = true;
$crop_data = [
'args' => $args,
'gallery_id' => $gallery_id,
'image_url' => $image[0],
];
// Generate the cropped image.
$this->background_request( $crop_data, 'resize-image' );
}
}
}
die();
}
/**
* Helper Request to resize images in the background.
*
* @since 1.7.0
*
* @access public
* @param \WP_REST_Request $request Request.
* @return void
*/
public function resize( \WP_REST_Request $request ) {
// Set the request.
$this->request = $request;
// Validate the request.
$valid = $this->validate_request( $request );
// Get the body.
$body = $request->get_body_params();
// Return if request not valid.
if ( ! $valid ) {
wp_send_json_error();
}
$defaults = [
'url' => '',
'id' => '',
'gallery_id' => '',
'width' => null,
'height' => null,
'crop' => true,
'align' => 'c',
'quality' => 100,
'retina' => false,
'data' => [],
'force_overwrite' => false,
];
$args = wp_parse_args( $body['data']['args'], $defaults );
$cropped_image = envira_resize_image( $body['data']['image_url'], $args['width'], $args['height'], true, $args['align'], $args['quality'], $args['retina'], null, $args['force_overwrite'] );
if ( $cropped_image ) {
wp_send_json_success( $cropped_image );
} else {
wp_send_json_error( $cropped_image );
}
}
/**
* Validates the API request.
*
* @since 1.7.0
*
* @param \WP_REST_Request $request Request.
* @return bool True if valid, false otherwise.
*/
public function validate_request( $request ) {
$body = $request->get_body_params();
if ( ! is_array( $body ) ) {
return false;
}
// Verify the request is comming from the site.
$site_url = get_home_url();
if ( strpos( $body['site'], $site_url ) === false ) {
return false;
}
$token = get_option( 'envira_rest_token' );
// hash_equals() prevents timing-oracle attacks that allow brute-forcing the token character by character.
if ( ! hash_equals( (string) $token, (string) $request->get_header( 'X-Envira-Token' ) ) ) {
return false;
}
do_action( 'envira_gallery_validate_bp' );
// All checks passed.
return true;
}
/**
* Self generated token to validate background requests.
*
* @access public
* @return string
*/
public function generate_token() {
$rest_token = wp_generate_password( 45, false, false );
$hash = hash( 'sha256', $rest_token );
update_option( 'envira_rest_token', $hash );
return $hash;
}
/**
* Helper function to call background requests.
*
* @since 1.7.0
*
* @access public
* @param mixed $data Request Data.
* @param mixed $type Request Type.
* @return void
*/
public function background_request( $data, $type ) {
// Bail if nothing set.
if ( ! is_array( $data ) || ! isset( $type ) ) {
return;
}
$name = $this->domain;
$version = $this->version;
$rest_url = get_rest_url();
$nonce = wp_create_nonce( 'wp_rest' );
$token = get_option( 'envira_rest_token' );
if ( ! $token ) {
$token = $this->generate_token();
}
$defaults = [
'data' => $data,
'site' => get_home_url(),
'nonce' => $nonce,
];
$body = wp_parse_args( $data, $defaults );
$headers = [
'X-Envira-Token' => $token,
];
// Generate the background request url.
$url = trailingslashit( $rest_url ) . $name . '/' . $version . '/' . $type;
$args = [
'headers' => $headers,
'body' => $body,
'user-agent' => 'Envira/' . ENVIRA_VERSION,
'timeout' => 0.5,
'blocking' => false,
'sslverify' => apply_filters( 'envira_background_ssl_verify', false ),
];
$callit = wp_remote_post( $url, $args );
}
}