Files
Hi-School-Slide-Manager/includes/class-hssm-shortcode.php
T

212 lines
7.1 KiB
PHP

<?php
/**
* HSSM Shortcode Class
*
* Handles the [hssm_slider] shortcode
*
* @package Hi_School_Slide_Manager
* @since 1.1.0
*/
// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
exit( 'Direct access forbidden.' );
}
class HSSM_Shortcode {
/**
* Constructor
*
* @since 1.1.0
*/
public function __construct() {
add_shortcode( 'hssm_slider', array( $this, 'render_shortcode' ) );
add_shortcode( 'hssm_slides', array( $this, 'render_shortcode' ) );
}
/**
* Render the [hssm_slider] shortcode
*
* @since 1.1.0
* @param array $atts Shortcode attributes
* @return string Shortcode output
*/
public function render_shortcode( $atts ) {
$plugin_mode = get_option( 'hssm_plugin_mode', 'manager' );
$slides = array();
if ( 'client' === $plugin_mode ) {
// Fetch from remote API
$api_client = new HSSM_API_Client();
$result = $api_client->get_slides();
if ( is_wp_error( $result ) ) {
if ( current_user_can( 'manage_options' ) ) {
return '<div class="hssm-error">' . sprintf( __( 'HSSM API Error: %s', 'hi-school-slide-manager' ), $result->get_error_message() ) . '</div>';
}
return '';
}
$slides = $result;
} else {
// Manager mode - Fetch locally
if ( isset( $atts['count'] ) && ! isset( $atts['limit'] ) ) {
$atts['limit'] = $atts['count'];
}
$atts = shortcode_atts(
array(
'site' => get_option( 'hssm_client_site_slug', 'hi-school' ),
'date' => current_time( 'Y-m-d' ),
'limit' => 10,
'slide' => 0,
'include_pending' => '0',
),
$atts,
'hssm_slider'
);
$site_slug = sanitize_text_field( $atts['site'] );
$date = sanitize_text_field( $atts['date'] );
$focus_slide_id = absint( $atts['slide'] );
$include_pending = filter_var( $atts['include_pending'], FILTER_VALIDATE_BOOLEAN );
$post_status = array( 'publish', 'future' );
if ( $include_pending ) {
$post_status[] = 'pending';
}
// Build query args similar to what's in the REST API or Frontend class
$args = array(
'post_type' => 'hssm_slide',
'posts_per_page' => intval( $atts['limit'] ),
'post_status' => $post_status,
'meta_key' => '_hssm_order',
'orderby' => 'meta_value_num',
'order' => 'ASC',
);
if ( ! empty( $site_slug ) ) {
$args['tax_query'] = array(
array(
'taxonomy' => 'hssm_site',
'field' => 'slug',
'terms' => $site_slug,
),
);
}
// Add date filtering
$target_date = $date . ' 23:59:59';
$args['meta_query'] = array(
'relation' => 'AND',
array(
'relation' => 'OR',
array( 'key' => '_hssm_start_date', 'value' => '', 'compare' => '=' ),
array( 'key' => '_hssm_start_date', 'value' => $target_date, 'compare' => '<=' ),
array( 'key' => '_hssm_start_date', 'compare' => 'NOT EXISTS' )
),
array(
'relation' => 'OR',
array( 'key' => '_hssm_end_date', 'value' => '', 'compare' => '=' ),
array( 'key' => '_hssm_end_date', 'value' => $target_date, 'compare' => '>=' ),
array( 'key' => '_hssm_end_date', 'compare' => 'NOT EXISTS' )
)
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
$slides[] = $this->format_slide_for_slider( get_the_ID() );
}
wp_reset_postdata();
}
if ( $focus_slide_id ) {
$slides = $this->prepend_focus_slide( $slides, $focus_slide_id, $include_pending );
}
}
if ( empty( $slides ) ) {
return '';
}
$slider = new HSSM_Slider();
return $slider->render( $slides, $atts );
}
/**
* Format a slide for the public slider.
*
* @since 1.1.3
* @param int $slide_id Slide ID.
* @return array|null
*/
private function format_slide_for_slider( $slide_id ) {
$slide = get_post( $slide_id );
if ( ! $slide || 'hssm_slide' !== $slide->post_type ) {
return null;
}
return array(
'id' => $slide->ID,
'title' => $slide->post_title,
'subtitle' => get_post_meta( $slide->ID, '_hssm_subtitle', true ),
'content' => $slide->post_content,
'buttons' => get_post_meta( $slide->ID, '_hssm_buttons', true ),
'featured_image' => get_the_post_thumbnail_url( $slide->ID, 'full' ),
'hide_all_text' => get_post_meta( $slide->ID, '_hssm_hide_all_text', true ) === '1',
);
}
/**
* Put a specific slide first in the slider.
*
* Pending and draft slides are only prepended when include_pending is true
* (preview). The public slider stays publish + future.
*
* @since 1.1.3
* @param array $slides Existing slides.
* @param int $slide_id Focus slide ID.
* @param bool $include_pending Whether pending/draft focus slides are allowed.
* @return array
*/
private function prepend_focus_slide( $slides, $slide_id, $include_pending = false ) {
foreach ( $slides as $index => $slide ) {
if ( (int) $slide['id'] === (int) $slide_id ) {
if ( 0 !== $index ) {
$focus = $slides[ $index ];
unset( $slides[ $index ] );
array_unshift( $slides, $focus );
}
return array_values( $slides );
}
}
$post = get_post( $slide_id );
if ( ! $post || 'hssm_slide' !== $post->post_type ) {
return $slides;
}
$allowed_statuses = array( 'publish', 'future' );
if ( $include_pending ) {
$allowed_statuses[] = 'pending';
if ( current_user_can( 'edit_post', $slide_id ) ) {
$allowed_statuses[] = 'draft';
}
}
if ( ! in_array( $post->post_status, $allowed_statuses, true ) ) {
return $slides;
}
$formatted = $this->format_slide_for_slider( $slide_id );
if ( $formatted ) {
array_unshift( $slides, $formatted );
}
return $slides;
}
}