<?php
if (!defined('ABSPATH')) {
die('No direct access.');
}
/**
* Class to handle slideshows
*/
class MetaSlider_Slideshows
{
/**
* Themes class
*
* @var object
*/
private $themes;
/**
* Theme instance
*
* @var object
* @see get_instance()
*/
protected static $instance = null;
/**
* @var object|null
*/
public $plugin;
/**
* Constructor
*/
public function __construct()
{
if (!class_exists('MetaSlider_Themes')) {
require_once plugin_dir_path(__FILE__) . 'Themes.php';
}
$this->themes = MetaSlider_Themes::get_instance();
$this->plugin = MetaSliderPlugin::get_instance();
}
/**
* Used to access the instance
*/
public static function get_instance()
{
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Method to add a slideshow
*
* @return int
*/
public static function create()
{
// Duplicate settings from their recently modified slideshow, or use defaults.
$last_modified = self::get_last_modified();
$last_modified_id = !empty($last_modified) ? $last_modified['id'] : null;
// TODO: next branch, refactor to slideshow object and extract controller type methods.
// TODO: I want to be able to do $last_modified->settings()
$last_modified_settings = new MetaSlider_Slideshow_Settings($last_modified_id);
$last_modified_settings = $last_modified_settings->get_settings();
$default_settings = MetaSlider_Slideshow_Settings::defaults();
$new_id = wp_insert_post(array(
'post_title' => $default_settings['title'],
'post_status' => 'publish',
'post_type' => 'ml-slider'
));
if (false !== strpos($default_settings['title'], '{id}')) {
wp_update_post(array(
'ID' => $new_id,
'post_title' => str_replace('{id}', $new_id, $default_settings['title'])
));
}
if (is_wp_error($new_id)) {
return $new_id;
}
$overrides = get_option('metaslider_default_settings');
$last_modified_settings = is_array($overrides) ? array_merge($last_modified_settings, $overrides) : $last_modified_settings;
add_post_meta($new_id, 'ml-slider_settings', $last_modified_settings, true);
// TODO: next branch, refactor to slideshow object and extract controller type methods.
// TODO: I want to be able to do $last_modified->theme()
// Get the latest slideshow used
$theme = get_post_meta($last_modified, 'metaslider_slideshow_theme', true);
// Lets users set their own default theme
if (apply_filters('metaslider_default_theme', '')) {
$themes = MetaSlider_Themes::get_instance();
$theme = $themes->get_theme_object(null, apply_filters('metaslider_default_theme', ''));
}
// Set the theme if we found something
if (isset($theme['folder'])) {
update_post_meta($new_id, 'metaslider_slideshow_theme', $theme);
}
// Needed for creating a relationship with slides
wp_insert_term($new_id, 'ml-slider');
return $new_id;
}
/**
* Method to save a slideshow
*
* @param int|string $slideshow_id - The id of the slideshow
* @param array $new_settings - The settings
*
* @return int - id of the slideshow
*/
public function save($slideshow_id, $new_settings)
{
// TODO: This is old code copied over and should eventually be refactored to not require hard-coded values
$old_settings = get_post_meta($slideshow_id, 'ml-slider_settings', true);
// convert submitted checkbox values from 'on' or 'off' to boolean values
$checkboxes = apply_filters("metaslider_checkbox_settings", array('noConflict', 'fullWidth', 'hoverPause', 'links', 'reverse', 'random', 'printCss', 'printJs', 'smoothHeight', 'center', 'carouselMode', 'autoPlay', 'firstSlideFadeIn', 'responsive_thumbs'));
foreach ($checkboxes as $checkbox) {
$new_settings[$checkbox] = (isset($new_settings[$checkbox]) && 'on' == $new_settings[$checkbox]) ? 'true' : 'false';
}
$settings = array_merge((array) $old_settings, $new_settings);
update_post_meta($slideshow_id, 'ml-slider_settings', $settings);
return $slideshow_id;
}
/**
* Method to duplicate a slideshow
*
* @param int|string $slideshow_id - The id of the slideshow to duplicate
*
* @throws Exception - handled within method.
* @return int|boolean - id of the new slideshow to show, or false
*/
public function duplicate($slideshow_id)
{
$new_slideshow_id = 0;
try {
$new_slideshow_id = wp_insert_post(array(
'post_title' => get_the_title($slideshow_id),
'post_status' => 'publish',
'post_type' => 'ml-slider'
), true);
if (is_wp_error($new_slideshow_id)) {
throw new Exception($new_slideshow_id->get_error_message());
}
foreach (get_post_meta($slideshow_id) as $key => $value) {
update_post_meta($new_slideshow_id, $key, maybe_unserialize($value[0]));
}
// Not used at the moment, but indicates this is a copy
update_post_meta($new_slideshow_id, 'metaslider_copy_of', $slideshow_id);
// Slides are associated to a slideshow via post terms
$term = wp_insert_term($new_slideshow_id, 'ml-slider');
// Duplicate each slide
foreach (self::active_slide_ids($slideshow_id) as $slide_id) {
$type = get_post_meta($slide_id, 'ml-slider_type', true);
$new_slide_id = wp_insert_post(array(
'post_title' => "Slider {$new_slideshow_id} - {$type}",
'post_status' => 'publish',
'post_type' => 'ml-slide',
'post_excerpt' => get_post_field('post_excerpt', $slide_id),
'menu_order' => get_post_field('menu_order', $slide_id)
), true);
if (is_wp_error($new_slide_id)) {
throw new Exception($new_slideshow_id->get_error_message());
}
foreach (get_post_meta($slide_id) as $key => $value) {
add_post_meta($new_slide_id, $key, maybe_unserialize($value[0]));
}
wp_set_post_terms($new_slide_id, $term['term_id'], 'ml-slider', true);
}
} catch (Exception $e) {
// If there was a failure somewhere, clean up
wp_trash_post($new_slideshow_id);
$this->delete_all_slides($new_slideshow_id);
return new WP_Error('slide_duplication_failed', $e->getMessage());
}
// External modules manipulate data here
do_action('metaslider_slideshow_duplicated', $slideshow_id, $new_slideshow_id);
return $new_slideshow_id;
}
/**
* Will return an array of information needed to import a slideshow
*
* @param array $slideshow_ids - The ids of the slideshow to export
*
* @return array
*/
public function export($slideshow_ids)
{
$export = array();
$args = array(
'post_type' => 'ml-slider',
'post_status' => array('inherit', 'publish'),
'orderby' => 'modified',
'suppress_filters' => 1, // wpml, ignore language filter
'posts_per_page' => -1,
'post__in' => $slideshow_ids
);
$slideshows = get_posts($args);
foreach ($slideshows as $slideshow) {
$slideshow_export = array(
'title' => $slideshow->post_title,
'original_id' => $slideshow->ID,
'meta' => array(),
'slides' => array()
);
foreach (get_post_meta($slideshow->ID) as $metakey => $value) {
$slideshow_export['meta'][$metakey] = $value[0];
}
if (isset($slideshow_export['meta']['metaslider_extra_slideshow_css'])) {
$slideshow_export['meta']['metaslider_extra_slideshow_css'] = str_replace(
'metaslider-id-' . $slideshow->ID,
'metaslider-id-{#ID#}', // To replace with correct ID during import
$slideshow_export['meta']['metaslider_extra_slideshow_css']
);
}
// Unset unecessary meta
unset($slideshow_export['meta']['metaslider_copy_of']);
$slides = get_posts(array(
'post_type' => array('ml-slide'),
'post_status' => array('publish'),
'lang' => '', // polylang, ingore language filter
'suppress_filters' => 1, // wpml, ignore language filter
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'ml-slider',
'field' => 'slug',
'terms' => $slideshow->ID
)
)
));
$slides_export = array();
foreach ($slides as $key => $slide) {
$image = get_post(get_post_meta($slide->ID, '_thumbnail_id', true));
$image_name = isset($image->post_name) ? $image->post_name : '';
$image_alt_name = isset($image->post_title) ? $image->post_title : '';
// Youtube and Vimeo prepend text to the file name, but not post_name
$slide_type = get_post_meta($slide->ID, 'ml-slider_type', true);
if ($image_name && in_array($slide_type, array('youtube', 'vimeo'))) {
$image_alt_name = $image_name;
$image_name = $slide_type . '_' . $image_name;
}
$slides_export[$key] = array(
'original_id' => $slide->ID,
'order' => $slide->menu_order,
'post_excerpt' => $this->stub_image_urls_from_string($slide->post_excerpt),
'image' => $image_name,
'image_alt' => $image_alt_name,
'meta' => array()
);
// Replace content url with placeholder for easier importing
foreach (get_post_meta($slide->ID) as $metakey => $value) {
$slides_export[$key]['meta'][$metakey] = $this->stub_image_urls_from_string($value[0]);
}
// Unset unnecessary meta
unset($slides_export[$key]['meta']['_thumbnail_id']);
}
$slideshow_export['slides'] = $slides_export;
$export[] = $slideshow_export;
unset($slides_export);
unset($slideshow_export);
}
$export['metadata'] = array(
'version' => $this->plugin->version,
'date' => date("Y/m/d") // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
);
return $export;
}
/**
* Will import slideshows
*
* @param array $slideshows - The data generated by the export method
*
* @throws Exception - handled within method.
* @return WP_Error|array - True on success, WP_Error on failure
*/
public function import($slideshows)
{
$errors = array();
foreach ($slideshows as $index => $slideshow) {
$errors[$index] = array();
$new_slideshow_id = 0;
try {
$new_slideshow_id = wp_insert_post(array(
'post_title' => $slideshow['title'],
'post_status' => 'publish',
'post_type' => 'ml-slider'
), true);
if (is_wp_error($new_slideshow_id)) {
throw new Exception($new_slideshow_id->get_error_message());
}
if (isset($slideshow['meta']) && is_array($slideshow['meta'])) {
foreach ($slideshow['meta'] as $key => $value) {
update_post_meta(
$new_slideshow_id,
$key,
maybe_unserialize(str_replace('{#ID#}', $new_slideshow_id, $value))
);
}
}
// Slides are associated to a slideshow via post terms
$term = wp_insert_term($new_slideshow_id, 'ml-slider');
if (!isset($slideshow['slides']) || !$slideshow['slides']) {
continue;
};
foreach ($slideshow['slides'] as $slide) {
$new_slide_id = wp_insert_post(array(
'post_title' => "Slider {$new_slideshow_id} - {$slide['meta']['ml-slider_type']}",
'post_status' => 'publish',
'post_type' => 'ml-slide',
'post_excerpt' => $this->restore_image_urls_from_string($slide['post_excerpt']),
'menu_order' => $slide['order']
), true);
if (is_wp_error($new_slide_id)) {
throw new Exception($new_slideshow_id->get_error_message());
}
// Update the thumbnail from the computed new image id
if (isset($slide['id'])) {
$slide['meta']['_thumbnail_id'] = $slide['id'];
}
foreach ($slide['meta'] as $key => $value) {
$value = $this->restore_image_urls_from_string($value);
add_post_meta($new_slide_id, $key, maybe_unserialize($value));
}
wp_set_post_terms($new_slide_id, $term['term_id'], 'ml-slider', true);
// This will crop the image so it's ready (and not already cropped)
$settings = maybe_unserialize($slideshow['meta']['ml-slider_settings']);
if (isset($settings['width']) && isset($settings['height'])) {
$image_cropper = new MetaSliderImageHelper(
$new_slide_id,
$settings['width'],
$settings['height'],
isset($settings['smartCrop']) ? $settings['smartCrop'] : 'false'
);
// This crops even though it doesn't sounds like it
$image_cropper->get_image_url();
}
}
} catch (Exception $e) {
array_push($errors[$index], $e->getMessage());
// If there was a failure somewhere, clean up
wp_trash_post($new_slideshow_id);
$this->delete_all_slides($new_slideshow_id);
}
// If no errors, remove the index
if (!count($errors[$index])) {
unset($errors[$index]);
}
// External modules manipulate data here
do_action('metaslider_slideshow_imported', $new_slideshow_id);
}
$errors = reset($errors);
return isset($errors[0]) ? new WP_Error('import_slideshow_error', $errors[0]) : $slideshows;
}
/**
* Function to leve a marker for images that are found in content.
* This can be any string, but it will most likely be HTML
* * Idea: this could keep track of image names that JS can use to search
*
* @param string $string - A string that may contain an image to be replaced
*
* @return string - the filtered string
*/
private function stub_image_urls_from_string($string)
{
// First, replace the media upload url. We only handle images inside there
$dir = wp_upload_dir(null, false);
$string = str_replace($dir['baseurl'], '{#CONTENTURL#}', $string);
// Next, attampt to parse the image and find it's name/slug
return preg_replace_callback('/[\'\"]({#CONTENTURL#}.*?)[\'\"]/', array($this, 'format_image_stub'), $string);
}
/**
* Attempt to locate an image by the image filename, and if not found, just update the content url
*
* @param string $string - A string that may contain a {#CONTENTURL#} to be replaced
*
* @return string - the filtered string
*/
private function restore_image_urls_from_string($string)
{
return preg_replace_callback('/[\'\"]({#CONTENTURL#}.*?)[\'\"]/', array($this, 'unformat_image_stub'), $string);
}
/**
* Used by a callback to replace images with a stub containing the name and title
* Makes it possibel to look up images later
*
* @see stub_image_urls_from_string()
* @param array $matches - The image
*
* @return string - the filtered string
*/
private function format_image_stub($matches)
{
global $wpdb;
$dir = wp_upload_dir(null, false);
$url = str_replace('{#CONTENTURL#}', $dir['baseurl'], $matches[1]);
$content_urlname = str_replace('{#CONTENTURL#}', '', $matches[1]);
$image = $wpdb->get_row($wpdb->prepare("SELECT post_name, post_title FROM $wpdb->posts WHERE guid = %s AND post_type = 'attachment' LIMIT 1", $url));
return '"{#CONTENTURL#}{#URLname:' . $content_urlname . '#}{#filename:' . $image->post_name . '#}{#filetitle:' . $image->post_title . '#}"';
}
/**
* This is the reverse of the above. IT will attempt to find the image locally
* {#CONTENTURL#}{#URLname:/2020/04/imagename.jpg#}{#filename:imagename#}{#filetitle:imagename#}
*
* @see restore_image_urls_from_string()
* @param array $image_data - The image
*
* @return string - the filtered string
*/
private function unformat_image_stub($image_data)
{
$filename = preg_match('{#filename:(.*?)#}', $image_data[1], $matches);
if ($image = MetaSlider_Image::get_image_ids_from_file_name(array($matches[1]))) {
$image = reset($image);
return '"' . $image['url'] . '"';
}
$filetitle = preg_match('{#filetitle:(.*?)#}', $image_data[1], $matches);
if ($image = MetaSlider_Image::get_image_ids_from_file_name(array($matches[1]))) {
$image = reset($image);
return '"' . $image['url'] . '"';
}
// nothing found, so return the image relative to the new media directory
$urlname = preg_match('{#URLname:(.*?)#}', $image_data[1], $matches);
$dir = wp_upload_dir(null, false);
return '"' . $dir['baseurl'] . $matches[1] . '"';
}
/**
* Method to delete a slideshow
*
* @param int|string $slideshow_id - The id of the slideshow to delete
*
* @return int|boolean - id of the next slideshow to show, or false
*/
public function delete($slideshow_id)
{
// Send the post to trash
$id = wp_update_post(array(
'ID' => $slideshow_id,
'post_status' => 'trash'
));
$this->delete_all_slides($slideshow_id);
$last_modified = self::get_last_modified();
return !empty($last_modified) ? $last_modified['id'] : false;
}
/**
* Method to disassociate slides from a slideshow
*
* @param int $slideshow_id - the id of the slideshow
*
* @return int
*/
public function delete_all_slides($slideshow_id)
{
$args = array(
'force_no_custom_order' => true,
'orderby' => 'menu_order',
'order' => 'ASC',
'post_type' => array('ml-slide'),
'post_status' => array('publish'),
'lang' => '', // polylang, ingore language filter
'suppress_filters' => 1, // wpml, ignore language filter
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'ml-slider',
'field' => 'slug',
'terms' => $slideshow_id
)
)
);
// I believe if this fails there's no real harm done
// because slides don't really need to be linked to their parent slideshow
$query = new WP_Query($args);
while ($query->have_posts()) {
$query->next_post();
wp_trash_post($query->post->ID);
}
return $slideshow_id;
}
/**
* Method to get the most recently modified slideshow
*
* @return array The id of the slideshow
*/
public static function get_last_modified()
{
$args = array(
'force_no_custom_order' => true,
'post_type' => 'ml-slider',
'num_posts' => 1,
'post_status' => 'publish',
'suppress_filters' => 1, // wpml, ignore language filter
'orderby' => 'modified',
'order' => 'DESC'
);
$slideshow = get_posts(apply_filters('metaslider_all_meta_sliders_args', $args));
return isset($slideshow[0]) ? self::build_slideshow_object($slideshow[0]) : array();
}
/**
* Method to get a single slideshow from the database
*
* @param int $id How many slideshows to return
*
* @return array
*/
public function get_single($id)
{
$args = array(
'post_type' => 'ml-slider',
'post_status' => array('inherit', 'publish'),
'orderby' => 'modified',
'p' => $id,
'suppress_filters' => 1, // wpml, ignore language filter,
);
$slideshow = new WP_Query(apply_filters('metaslider_get_single_slideshows_args', $args));
if (is_wp_error($slideshow)) {
return $slideshow;
}
return array_map([self::class, 'build_slideshow_object'], $slideshow->posts);
}
/**
* Method to get slideshows from the database
*
* @param int $posts_per_page How many slideshows to return
* @param int $page What page to return
*
* @return array
*/
public function get($posts_per_page = 25, $page = 1)
{
if (!$posts_per_page || !$page) {
return array();
}
$args = array(
'post_type' => 'ml-slider',
'post_status' => array('inherit', 'publish'),
'orderby' => 'modified',
'suppress_filters' => 1, // wpml, ignore language filter,
'paged' => $page,
'posts_per_page' => $posts_per_page
);
$slideshows = new WP_Query(apply_filters('metaslider_get_some_slideshows_args', $args));
if (is_wp_error($slideshows)) {
return $slideshows;
}
$slideshows_formatted = array_map('self::build_slideshow_object', $slideshows->posts);
$remaining_pages = intval($slideshows->max_num_pages) - intval($page);
if ($remaining_pages > 0) {
$slideshows_formatted['page'] = $page;
$slideshows_formatted['remaining_pages'] = $remaining_pages;
}
// Add the total count so we know there are more to fetch
if (1 == $page) {
$slideshows_formatted['totalSlideshows'] = $slideshows->found_posts;
}
return $slideshows_formatted;
}
/**
* Method to get slideshows from the database by term
*
* @param int $term The search term
* @param int $count How many to return
*
* @return array
*/
public function search($term, $count)
{
$args = array(
'post_type' => 'ml-slider',
'post_status' => array('inherit', 'publish'),
'orderby' => $term ? 'relevance' : 'modified',
's' => $term,
'suppress_filters' => 1,
'posts_per_page' => $count
);
$slideshows = new WP_Query(apply_filters('metaslider_get_some_slideshows_args', $args));
if (is_wp_error($slideshows)) {
return $slideshows;
}
return array_map('self::build_slideshow_object', $slideshows->posts);
}
/**
* Method to get all slideshows from the database
*
* @return array
*/
public function get_all_slideshows()
{
$args = array(
'post_type' => 'ml-slider',
'post_status' => array('inherit', 'publish'),
'orderby' => 'modified',
'suppress_filters' => 1, // wpml, ignore language filter
'posts_per_page' => -1
);
$slideshows = get_posts(apply_filters('metaslider_all_meta_sliders_args', $args));
return array_map(array($this, 'build_slideshow_object_simple'), $slideshows);
}
/**
* Method to build out a simple slideshow object
*
* @param object $slideshow - The slideshow object
* @return array
*/
public function build_slideshow_object_simple($slideshow)
{
if (empty($slideshow)) {
return array();
}
$slideshows = array(
'id' => $slideshow->ID,
'title' => $slideshow->post_title ? $slideshow->post_title : '# ' . $slideshow->ID,
);
return $slideshows;
}
/**
* Method to build out the slideshow object
*
* @param object $slideshow - The slideshow object
* @return array
*/
public static function build_slideshow_object($slideshow)
{
if (empty($slideshow)) {
return array();
}
$slideshows = array(
'id' => $slideshow->ID,
'title' => $slideshow->post_title ? $slideshow->post_title : '# ' . $slideshow->ID,
'created_at' => $slideshow->post_date,
'modified_at' => $slideshow->post_modified,
'modified_at_gmt' => $slideshow->post_modified_gmt,
'slides' => self::active_slide_ids($slideshow->ID)
);
foreach (get_post_meta($slideshow->ID) as $key => $value) {
if (in_array($key, array('title', 'id', 'created_at', 'modified_at', 'modified_at_gmt', 'slides'))) {
continue;
}
$key = str_replace('ml-slider_settings', 'settings', $key);
$key = str_replace('metaslider_slideshow_theme', 'theme', $key);
$slideshows[$key] = maybe_unserialize($value[0]);
}
return $slideshows;
}
/**
* Method to get the slide ids
*
* @param int|string $id - The id of the slideshow
* @return array - Returns an array of just the slide IDs
*/
public static function active_slide_ids($id)
{
$slides = get_posts(array(
'force_no_custom_order' => true,
'orderby' => 'menu_order',
'order' => 'ASC',
'post_type' => array('attachment', 'ml-slide'),
'post_status' => array('inherit', 'publish'),
'lang' => '',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'ml-slider',
'field' => 'slug',
'terms' => $id
)
)
));
$slide_ids = array();
foreach ($slides as $slide) {
$type = get_post_meta($slide->ID, 'ml-slider_type', true);
$type = $type ? $type : 'image'; // Default ot image
// If this filter exists, that means the slide type is available (i.e. pro slides)
if (has_filter("metaslider_get_{$type}_slide")) {
array_push($slide_ids, $slide->ID);
}
}
return $slide_ids;
}
/**
* Method to get the latest slideshow
*/
public function recently_modified()
{
}
/**
* Method to get a single slideshow from the database
*
* @param string $id - The id of a slideshow
*/
public function single($id)
{
}
/**
* Returns the shortcode of the slideshow
*
* @param string|int $id - The id of a slideshow
* @param string|int $restrict_to - page to limit the slideshow to
* @param string|null $theme_id - load a theme, defaults to the current theme
*/
public function shortcode($id = null, $restrict_to = null, $theme_id = null)
{
// if no id is given, try to find the first available slideshow
if (is_null($id)) {
if (function_exists('vip_get_random_posts')) {
$ids = vip_get_random_posts(1, 'post', true);
$id = isset($ids[0]) ? $ids[0] : $id;
}
if (! function_exists('vip_get_random_posts')) {
// phpcs:ignore WordPressVIPMinimum.Performance.OrderByRand.orderby_orderby
$the_query = get_posts(array('orderby' => 'rand', 'posts_per_page' => '1'));
$id = isset($the_query[0]) ? $the_query[0]->ID : $id;
}
}
return "[metaslider id='{$id}' restrict_to='{$restrict_to}' theme='{$theme_id}']";
}
/**
* Return the preview
*
* @param int|string $slideshow_id The id of the current slideshow
* @param string $theme_id The folder name of the theme
*
* @return string|WP_Error whether the file was included, or error class
*/
public function preview($slideshow_id, $theme_id = null)
{
if (!class_exists('MetaSlider_Slideshow_Settings')) {
require_once plugin_dir_path(__FILE__) . 'Settings.php';
}
$settings = new MetaSlider_Slideshow_Settings($slideshow_id);
try {
ob_start();
// Remove the admin bar
remove_action('wp_footer', 'wp_admin_bar_render', 1000);
// Load in theme if set. Note that the shortcode below is set to 'none'
$this->themes->load_theme($slideshow_id, $theme_id); ?>
<!DOCTYPE html>
<html>
<head>
<style type='text/css'>
<?php ob_start(); ?>
body, html {
overflow: auto;
height:100%;
margin:0;
padding:0;
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
font-size: 14px;
}
body {
padding: 60px 40px 40px;
}
#preview-container {
min-height: 100%;
max-width: <?php echo (int) $settings->get_single('width'); ?>px;
margin: 0 auto;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
#preview-inner {
width: 100%;
height: 100%;
}
.metaslider {
margin: 0 auto;
}
<?php echo apply_filters('metaslider_preview_styles', ob_get_clean()); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</style>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
</head>
<body>
<div id="preview-container">
<div id="preview-inner">
<?php echo do_shortcode($this->shortcode(absint($slideshow_id), null, $this->themes->theme_id)); ?>
</div>
</div>
<?php wp_footer(); ?>
</body>
</html>
<?php return preg_replace('/\s+/S', " ", ob_get_clean());
} catch (Exception $e) {
ob_clean();
return new WP_Error('preview_failed', $e->getMessage());
}
}
}