| 1 |
<?php |
| 2 |
|
| 3 |
/** |
| 4 |
* Gallery Form (add / edit). |
| 5 |
* |
| 6 |
* @link https://plugins360.com |
| 7 |
* @since 2.8.0 |
| 8 |
* |
| 9 |
* @package Automatic_YouTube_Gallery |
| 10 |
*/ |
| 11 |
|
| 12 |
// Exit if accessed directly |
| 13 |
if ( ! defined( 'WPINC' ) ) { |
| 14 |
die; |
| 15 |
} |
| 16 |
|
| 17 |
$action = isset( $_GET['action'] ) ? sanitize_text_field( $_GET['action'] ) : ''; |
| 18 |
$gallery_id = ( 'edit' === $action ) ? absint( isset( $_GET['id'] ) ? $_GET['id'] : 0 ) : 0; |
| 19 |
$source_value_fields = array( 'channel', 'playlist', 'username', 'search', 'video', 'videos' ); |
| 20 |
$no_schedule_types = array( 'search', 'livestream', 'video', 'videos' ); |
| 21 |
$live_types = array( 'search', 'livestream', 'video' ); // Rendered live at display time — nothing is imported/stored. |
| 22 |
$date_format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' ); |
| 23 |
$is_new = ( 0 === $gallery_id ) ? true : false; |
| 24 |
|
| 25 |
// Get the editor fields. |
| 26 |
$fields = ayg_get_editor_fields(); |
| 27 |
$excluded = array(); |
| 28 |
|
| 29 |
foreach ( $fields as $key => $section ) { |
| 30 |
foreach ( $section['fields'] as $index => $field ) { |
| 31 |
// Exclude certain fields from the form |
| 32 |
if ( in_array( $field['name'], $excluded, true ) ) { |
| 33 |
unset( $fields[ $key ]['fields'][ $index ] ); |
| 34 |
continue; |
| 35 |
} |
| 36 |
|
| 37 |
// Add the exclude + schedule fields to the end of the source section. |
| 38 |
if ( 'order' === $field['name'] ) { |
| 39 |
$fields[ $key ]['fields'][] = array( |
| 40 |
'name' => 'exclude', |
| 41 |
'label' => __( 'Exclude Videos', 'automatic-youtube-gallery' ), |
| 42 |
'description' => __( 'Enter the video IDs or URLs you want to exclude, one per line. These videos will never be imported into this gallery.', 'automatic-youtube-gallery' ), |
| 43 |
'type' => 'textarea', |
| 44 |
'placeholder' => __( 'Enter one video ID or URL per line', 'automatic-youtube-gallery' ), |
| 45 |
'value' => '', |
| 46 |
'sanitize_callback' => 'sanitize_textarea_field' |
| 47 |
); |
| 48 |
|
| 49 |
$fields[ $key ]['fields'][] = array( |
| 50 |
'name' => 'schedule', |
| 51 |
'label' => __( 'Import Schedule', 'automatic-youtube-gallery' ), |
| 52 |
'description' => __( 'How often we automatically check your YouTube source for new videos and import them in the background. Choose "Pause Automatic Imports" to stop these background imports — you can still import on demand by saving the gallery.', 'automatic-youtube-gallery' ), |
| 53 |
'type' => 'select', |
| 54 |
'options' => ayg_get_import_schedule_options(), |
| 55 |
'value' => 86400, |
| 56 |
'sanitize_callback' => 'absint' |
| 57 |
); |
| 58 |
} |
| 59 |
|
| 60 |
// Add the sort and duration filter fields to the gallery section. |
| 61 |
if ( 'gallery' === $key && 'per_page' === $field['name'] ) { |
| 62 |
// Builder galleries render from our own table, so "Videos per Page" can go beyond the |
| 63 |
// 50-video API cap here — 0 shows all videos on one page. (The shared field keeps its 50 |
| 64 |
// limit elsewhere, e.g. the global settings page.) |
| 65 |
$fields[ $key ]['fields'][ $index ]['description'] = __( 'Enter the number of videos to show per page, or 0 to show all videos on a single page.', 'automatic-youtube-gallery' ); |
| 66 |
unset( $fields[ $key ]['fields'][ $index ]['max'] ); |
| 67 |
|
| 68 |
// Add the display-time sort fields right after the per_page field in the gallery section. |
| 69 |
array_splice( $fields[ $key ]['fields'], $index + 1, 0, array( |
| 70 |
array( |
| 71 |
'name' => 'sort_by', |
| 72 |
'label' => __( 'Order Videos By', 'automatic-youtube-gallery' ), |
| 73 |
'description' => __( 'Select how imported videos are ordered in this gallery.', 'automatic-youtube-gallery' ), |
| 74 |
'type' => 'select', |
| 75 |
'options' => array( |
| 76 |
'date' => __( 'Published Date', 'automatic-youtube-gallery' ), |
| 77 |
'title' => __( 'Title', 'automatic-youtube-gallery' ), |
| 78 |
'duration' => __( 'Duration', 'automatic-youtube-gallery' ), |
| 79 |
'random' => __( 'Random', 'automatic-youtube-gallery' ) |
| 80 |
), |
| 81 |
'value' => 'date', |
| 82 |
'sanitize_callback' => 'sanitize_key' |
| 83 |
), |
| 84 |
array( |
| 85 |
'name' => 'sort_order', |
| 86 |
'label' => __( 'Order', 'automatic-youtube-gallery' ), |
| 87 |
'description' => __( 'Descending shows newest, Z–A or longest first. Ascending shows oldest, A–Z or shortest first.', 'automatic-youtube-gallery' ), |
| 88 |
'type' => 'select', |
| 89 |
'options' => array( |
| 90 |
'desc' => __( 'Descending', 'automatic-youtube-gallery' ), |
| 91 |
'asc' => __( 'Ascending', 'automatic-youtube-gallery' ) |
| 92 |
), |
| 93 |
'value' => 'desc', |
| 94 |
'sanitize_callback' => 'sanitize_key' |
| 95 |
), |
| 96 |
array( |
| 97 |
'name' => 'duration_filter', |
| 98 |
'label' => __( 'Filter by Duration', 'automatic-youtube-gallery' ), |
| 99 |
'description' => __( 'Show only videos longer or shorter than the duration below — handy for including or excluding Shorts.', 'automatic-youtube-gallery' ), |
| 100 |
'type' => 'select', |
| 101 |
'options' => array( |
| 102 |
'' => '— ' . __( 'No Filter', 'automatic-youtube-gallery' ) . ' —', |
| 103 |
'long' => __( 'Longer Than', 'automatic-youtube-gallery' ), |
| 104 |
'short' => __( 'Shorter Than', 'automatic-youtube-gallery' ) |
| 105 |
), |
| 106 |
'value' => '', |
| 107 |
'sanitize_callback' => 'sanitize_key' |
| 108 |
), |
| 109 |
array( |
| 110 |
'name' => 'duration', |
| 111 |
'label' => __( 'Duration (Seconds)', 'automatic-youtube-gallery' ), |
| 112 |
'description' => __( 'The duration threshold in seconds for the filter above. Shorts are typically up to 60 seconds long, so enter 60 to include or exclude Shorts. Has no effect when the filter is set to "No Filter".', 'automatic-youtube-gallery' ), |
| 113 |
'type' => 'text', |
| 114 |
'value' => '', |
| 115 |
'sanitize_callback' => 'ayg_sanitize_int' |
| 116 |
) |
| 117 |
) ); |
| 118 |
} |
| 119 |
|
| 120 |
// Add a description to the search form field in the search section. |
| 121 |
if ( 'search' === $key && 'search_form' === $field['name'] ) { |
| 122 |
$fields[ $key ]['fields'][ $index ]['description'] = __( 'Check this option to enable the search form.', 'automatic-youtube-gallery' ); |
| 123 |
} |
| 124 |
} |
| 125 |
} |
| 126 |
|
| 127 |
// Load gallery config when editing |
| 128 |
$form_data = array( |
| 129 |
'id' => $gallery_id, |
| 130 |
'title' => '', |
| 131 |
'type' => 'playlist', |
| 132 |
'theme' => 'classic', |
| 133 |
'import_status' => 'idle', |
| 134 |
'import_error' => '', |
| 135 |
'import_log' => '', |
| 136 |
'last_imported_at' => '', |
| 137 |
'next_import_at' => '', |
| 138 |
'video_count' => 0, |
| 139 |
'schedule' => 86400 |
| 140 |
); |
| 141 |
|
| 142 |
if ( $gallery_id > 0 ) { |
| 143 |
$gallery = ayg_get_gallery( $gallery_id ); |
| 144 |
|
| 145 |
if ( ! $gallery ) { |
| 146 |
?> |
| 147 |
<div class="ayg-notice ayg-notice-error"> |
| 148 |
<span class="dashicons dashicons-dismiss" aria-hidden="true"></span> |
| 149 |
<?php esc_html_e( 'Gallery not found.', 'automatic-youtube-gallery' ); ?> |
| 150 |
</div> |
| 151 |
<?php |
| 152 |
return; |
| 153 |
} |
| 154 |
|
| 155 |
// Override default values with saved gallery data |
| 156 |
$form_data['title'] = $gallery->title; |
| 157 |
$form_data['import_status'] = $gallery->import_status; |
| 158 |
$form_data['import_error'] = $gallery->import_error; |
| 159 |
$form_data['import_log'] = $gallery->import_log; |
| 160 |
$form_data['last_imported_at'] = $gallery->last_imported_at; |
| 161 |
$form_data['next_import_at'] = $gallery->next_import_at; |
| 162 |
$form_data['video_count'] = absint( $gallery->video_count ); |
| 163 |
|
| 164 |
$allowed_source_types = ayg_get_source_types(); |
| 165 |
$source_type = array_key_exists( $gallery->source_type, $allowed_source_types ) ? $gallery->source_type : 'playlist'; |
| 166 |
$form_data['type'] = $source_type; |
| 167 |
|
| 168 |
if ( 'livestream' === $source_type ) { |
| 169 |
$form_data['channel'] = $gallery->source_value; |
| 170 |
} else { |
| 171 |
$form_data[ $source_type ] = $gallery->source_value; |
| 172 |
} |
| 173 |
|
| 174 |
if ( ! empty( $gallery->params ) ) { |
| 175 |
$params = json_decode( $gallery->params, true ) ?: array(); |
| 176 |
$form_data = array_merge( $form_data, $params ); |
| 177 |
} |
| 178 |
} |
| 179 |
|
| 180 |
// The source locks only once videos have been imported. Until then it stays editable |
| 181 |
// so a bad source (e.g. a failed first import) can be corrected without recreating. |
| 182 |
// Live types (search / livestream / single video) never import, so their source never locks. |
| 183 |
$source_locked = ( ! $is_new && $form_data['video_count'] > 0 && ! in_array( $form_data['type'], $live_types, true ) ); |
| 184 |
?> |
| 185 |
<div id="ayg-gallery-form" class="ayg-gallery-form"> |
| 186 |
<div class="ayg-back-to-galleries-link"> |
| 187 |
<a href="<?php echo esc_url( admin_url( 'admin.php?page=automatic-youtube-gallery' ) ); ?>"> |
| 188 |
<?php esc_html_e( '← Back to Galleries', 'automatic-youtube-gallery' ); ?> |
| 189 |
</a> |
| 190 |
</div> |
| 191 |
|
| 192 |
<?php if ( $is_new ) : ?> |
| 193 |
<h1 class="ayg-gallery-form-heading"><?php esc_html_e( 'Add New Gallery', 'automatic-youtube-gallery' ); ?></h1> |
| 194 |
<?php else : ?> |
| 195 |
<h1 class="ayg-gallery-form-heading"> |
| 196 |
<?php esc_html_e( 'Edit Gallery', 'automatic-youtube-gallery' ); ?> |
| 197 |
<a href="<?php echo esc_url( admin_url( 'admin.php?page=automatic-youtube-gallery&action=new' ) ); ?>" class="ayg-button button button-small"> |
| 198 |
<?php esc_html_e( 'Add New Gallery', 'automatic-youtube-gallery' ); ?> |
| 199 |
</a> |
| 200 |
</h1> |
| 201 |
|
| 202 |
<?php if ( isset( $_GET['saved'] ) ) : ?> |
| 203 |
<div class="ayg-notice ayg-notice-success"> |
| 204 |
<span class="dashicons dashicons-yes-alt" aria-hidden="true"></span> |
| 205 |
<?php esc_html_e( 'Gallery created successfully.', 'automatic-youtube-gallery' ); ?> |
| 206 |
</div> |
| 207 |
<?php elseif ( isset( $_GET['updated'] ) ) : ?> |
| 208 |
<div class="ayg-notice ayg-notice-success"> |
| 209 |
<span class="dashicons dashicons-yes-alt" aria-hidden="true"></span> |
| 210 |
<?php esc_html_e( 'Gallery updated successfully.', 'automatic-youtube-gallery' ); ?> |
| 211 |
</div> |
| 212 |
<?php endif; ?> |
| 213 |
|
| 214 |
<?php if ( ! empty( $form_data['import_error'] ) ) : ?> |
| 215 |
<div class="ayg-notice ayg-notice-error"> |
| 216 |
<span class="dashicons dashicons-dismiss" aria-hidden="true"></span> |
| 217 |
<strong><?php esc_html_e( 'Import Error', 'automatic-youtube-gallery' ); ?>:</strong> <?php echo esc_html( $form_data['import_error'] ); ?> |
| 218 |
</div> |
| 219 |
<?php elseif ( 'running' === $form_data['import_status'] ) : ?> |
| 220 |
<div class="ayg-notice ayg-notice-info"> |
| 221 |
<span class="dashicons dashicons-update" aria-hidden="true"></span> |
| 222 |
<?php esc_html_e( 'An import is in progress for this gallery. It continues automatically in the background and may take a few minutes for large channels. Refresh this page to check the latest status.', 'automatic-youtube-gallery' ); ?> |
| 223 |
</div> |
| 224 |
<?php endif; ?> |
| 225 |
|
| 226 |
<?php $shortcode = sprintf( '[automatic_youtube_gallery id="%d"]', $gallery_id ); ?> |
| 227 |
<div class="ayg-notice ayg-notice-info ayg-notice-shortcode"> |
| 228 |
<div class="ayg-notice-shortcode-text"> |
| 229 |
<span> |
| 230 |
<span class="dashicons dashicons-awards" aria-hidden="true"></span> |
| 231 |
<?php esc_html_e( 'Your gallery is ready! Copy the shortcode below and paste it into any post, page, or widget to display it.', 'automatic-youtube-gallery' ); ?> |
| 232 |
</span> |
| 233 |
<code><?php echo esc_html( $shortcode ); ?></code> |
| 234 |
</div> |
| 235 |
<button type="button" class="ayg-button ayg-button-copy-shortcode button" data-clipboard-text="<?php echo esc_attr( $shortcode ); ?>"> |
| 236 |
<?php esc_html_e( 'Copy Shortcode', 'automatic-youtube-gallery' ); ?> |
| 237 |
</button> |
| 238 |
</div> |
| 239 |
|
| 240 |
<?php |
| 241 |
// KPI cards show for imported source types only. Live types (search / livestream / single |
| 242 |
// video) store nothing, so they're excluded. 'videos' (multiple) keeps the cards since the |
| 243 |
// imported count is useful. |
| 244 |
if ( ! in_array( $form_data['type'], $live_types, true ) ) : |
| 245 |
?> |
| 246 |
<div class="ayg-kpi-cards"> |
| 247 |
<div class="ayg-card ayg-card-kpi"> |
| 248 |
<span class="ayg-kpi-icon dashicons dashicons-dashboard" aria-hidden="true"></span> |
| 249 |
<div class="ayg-kpi-body"> |
| 250 |
<?php $import_status_label = ayg_get_import_status_label( $form_data['import_status'], $form_data['video_count'], ! empty( $form_data['page_token'] ) ); ?> |
| 251 |
<span class="ayg-badge ayg-badge-<?php echo esc_attr( $form_data['import_status'] ); ?>"><?php echo esc_html( $import_status_label ); ?></span> |
| 252 |
<span class="ayg-kpi-label"><?php esc_html_e( 'Status', 'automatic-youtube-gallery' ); ?></span> |
| 253 |
</div> |
| 254 |
</div> |
| 255 |
|
| 256 |
<div class="ayg-card ayg-card-kpi"> |
| 257 |
<span class="ayg-kpi-icon dashicons dashicons-editor-video" aria-hidden="true"></span> |
| 258 |
<div class="ayg-kpi-body"> |
| 259 |
<strong class="ayg-kpi-value"><?php echo number_format_i18n( $form_data['video_count'] ); ?></strong> |
| 260 |
<span class="ayg-kpi-label"><?php esc_html_e( 'Videos Imported', 'automatic-youtube-gallery' ); ?></span> |
| 261 |
</div> |
| 262 |
</div> |
| 263 |
|
| 264 |
<?php if ( ! in_array( $form_data['type'], $no_schedule_types, true ) ) : ?> |
| 265 |
<div class="ayg-card ayg-card-kpi"> |
| 266 |
<span class="ayg-kpi-icon dashicons dashicons-clock" aria-hidden="true"></span> |
| 267 |
<div class="ayg-kpi-body"> |
| 268 |
<strong class="ayg-kpi-value ayg-kpi-value-date"> |
| 269 |
<?php |
| 270 |
if ( ! empty( $form_data['last_imported_at'] ) ) { |
| 271 |
echo esc_html( wp_date( $date_format, strtotime( $form_data['last_imported_at'] ) ) ); |
| 272 |
} elseif ( $form_data['video_count'] > 0 ) { |
| 273 |
// Videos are stored but no run has completed yet (import still in progress / was interrupted). |
| 274 |
esc_html_e( 'In progress', 'automatic-youtube-gallery' ); |
| 275 |
} else { |
| 276 |
esc_html_e( 'Never', 'automatic-youtube-gallery' ); |
| 277 |
} |
| 278 |
?> |
| 279 |
</strong> |
| 280 |
<span class="ayg-kpi-label"><?php esc_html_e( 'Last Imported', 'automatic-youtube-gallery' ); ?></span> |
| 281 |
<?php if ( ! empty( $form_data['next_import_at'] ) ) : ?> |
| 282 |
<span class="ayg-kpi-sublabel"> |
| 283 |
<strong><?php esc_html_e( 'Next', 'automatic-youtube-gallery' ); ?>: </strong> |
| 284 |
<?php echo esc_html( wp_date( $date_format, strtotime( $form_data['next_import_at'] ) ) ); ?></span> |
| 285 |
<?php endif; ?> |
| 286 |
</div> |
| 287 |
</div> |
| 288 |
<?php endif; ?> |
| 289 |
</div> |
| 290 |
<?php endif; ?> |
| 291 |
<?php endif; ?> |
| 292 |
|
| 293 |
<form class="ayg-form ayg-form-field-type-<?php echo esc_attr( $form_data['type'] ); ?> ayg-form-field-theme-<?php echo esc_attr( $form_data['theme'] ); ?>" method="post"> |
| 294 |
<details class="ayg-form-section-title" open> |
| 295 |
<summary> |
| 296 |
<span><?php esc_html_e( 'Gallery Title', 'automatic-youtube-gallery' ); ?></span> |
| 297 |
</summary> |
| 298 |
|
| 299 |
<div class="ayg-form-controls"> |
| 300 |
<div class="ayg-form-control ayg-form-control-title"> |
| 301 |
<input type="text" name="title" id="ayg-form-field-title" class="ayg-form-field ayg-form-field-title widefat" value="<?php echo esc_attr( $form_data['title'] ); ?>" placeholder="<?php esc_attr_e( 'Enter a title or leave blank to auto-generate', 'automatic-youtube-gallery' ); ?>"<?php if ( $is_new ) echo ' autofocus'; ?>> |
| 302 |
</div> |
| 303 |
</div> |
| 304 |
</details> |
| 305 |
|
| 306 |
<?php foreach ( $fields as $key => $section ) : ?> |
| 307 |
<details class="ayg-form-section-<?php echo esc_attr( $key ); ?>"<?php if ( 'source' == $key ) echo ' open'; ?>> |
| 308 |
<summary> |
| 309 |
<span><?php echo esc_html( $section['label'] ); ?></span> |
| 310 |
</summary> |
| 311 |
|
| 312 |
<div class="ayg-form-controls"> |
| 313 |
<?php if ( 'source' === $key ) : ?> |
| 314 |
<p class="description"> |
| 315 |
<span class="ayg-text-info dashicons dashicons-info" aria-hidden="true"></span> |
| 316 |
<?php |
| 317 |
// The live / importable text (not the locked text) is kept in sync with the |
| 318 |
// source-type dropdown by admin.js — the strings are mirrored in ayg_admin.i18n |
| 319 |
// (source_live / source_importable). Keep the three in sync when editing copy. |
| 320 |
?> |
| 321 |
<span class="ayg-source-hint"><?php |
| 322 |
if ( $source_locked ) { |
| 323 |
esc_html_e( 'The video source is locked because videos have been imported. Please create a new gallery to use a different source type.', 'automatic-youtube-gallery' ); |
| 324 |
} elseif ( in_array( $form_data['type'], $live_types, true ) ) { |
| 325 |
esc_html_e( 'This is a live source — you can change it anytime. Updates take effect immediately the next time the gallery is viewed.', 'automatic-youtube-gallery' ); |
| 326 |
} else { |
| 327 |
esc_html_e( 'The video source can’t be changed once videos are imported. So please make sure you select the right source before saving.', 'automatic-youtube-gallery' ); |
| 328 |
} |
| 329 |
?> |
| 330 |
</span> |
| 331 |
</p> |
| 332 |
<?php endif; ?> |
| 333 |
|
| 334 |
<?php |
| 335 |
foreach ( $section['fields'] as $field ) : |
| 336 |
if ( ! isset( $field['placeholder'] ) ) { |
| 337 |
$field['placeholder'] = ''; |
| 338 |
} |
| 339 |
|
| 340 |
// Source settings lock once videos are imported. Fields that don't define the |
| 341 |
// source itself stay editable: the exclude list, the import schedule, and the |
| 342 |
// popup display options (popup mode + its custom trigger). |
| 343 |
$is_locked = ( $source_locked && 'source' === $key && ! in_array( $field['name'], array( 'exclude', 'schedule', 'popup', 'content' ), true ) ); |
| 344 |
|
| 345 |
// Required-field marker (asterisk) appended after the label. |
| 346 |
$required_mark = ! empty( $field['required'] ) ? ' <span class="ayg-form-required" aria-hidden="true">*</span>' : ''; |
| 347 |
|
| 348 |
if ( isset( $form_data[ $field['name'] ] ) ) { |
| 349 |
$field['value'] = $form_data[ $field['name'] ]; |
| 350 |
|
| 351 |
if ( is_array( $field['value'] ) ) { |
| 352 |
$field['value'] = implode( "\n", $field['value'] ); |
| 353 |
} |
| 354 |
} |
| 355 |
?> |
| 356 |
<div class="ayg-form-control ayg-form-control-<?php echo esc_attr( $field['name'] ); ?>"> |
| 357 |
<?php if ( 'text' == $field['type'] || 'url' == $field['type'] || 'number' == $field['type'] ) : ?> |
| 358 |
<label class="ayg-form-label" for="ayg-form-field-<?php echo esc_attr( $field['name'] ); ?>"><?php echo esc_html( $field['label'] ); echo $required_mark; ?></label> |
| 359 |
<input type="text" name="<?php echo esc_attr( $field['name'] ); ?>" id="ayg-form-field-<?php echo esc_attr( $field['name'] ); ?>" class="ayg-form-field ayg-form-field-<?php echo esc_attr( $field['name'] ); ?> widefat" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>" value="<?php echo esc_attr( $field['value'] ); ?>"<?php disabled( $is_locked ); ?> /> |
| 360 |
<?php elseif ( 'textarea' == $field['type'] ) : ?> |
| 361 |
<label class="ayg-form-label" for="ayg-form-field-<?php echo esc_attr( $field['name'] ); ?>"><?php echo esc_html( $field['label'] ); echo $required_mark; ?></label> |
| 362 |
<textarea name="<?php echo esc_attr( $field['name'] ); ?>" id="ayg-form-field-<?php echo esc_attr( $field['name'] ); ?>" rows="8" class="ayg-form-field ayg-form-field-<?php echo esc_attr( $field['name'] ); ?> widefat" placeholder="<?php echo esc_attr( $field['placeholder'] ); ?>"<?php disabled( $is_locked ); ?>><?php echo esc_textarea( $field['value'] ); ?></textarea> |
| 363 |
<?php elseif ( 'select' == $field['type'] || 'radio' == $field['type'] ) : ?> |
| 364 |
<label class="ayg-form-label" for="ayg-form-field-<?php echo esc_attr( $field['name'] ); ?>"><?php echo esc_html( $field['label'] ); echo $required_mark; ?></label> |
| 365 |
<select name="<?php echo esc_attr( $field['name'] ); ?>" id="ayg-form-field-<?php echo esc_attr( $field['name'] ); ?>" class="ayg-form-field ayg-form-field-<?php echo esc_attr( $field['name'] ); ?> widefat"<?php disabled( $is_locked ); ?>> |
| 366 |
<?php |
| 367 |
foreach ( $field['options'] as $value => $label ) { |
| 368 |
printf( |
| 369 |
'<option value="%s"%s>%s</option>', |
| 370 |
esc_attr( $value ), |
| 371 |
selected( $value, $field['value'], false ), |
| 372 |
esc_html( $label ) |
| 373 |
); |
| 374 |
} |
| 375 |
?> |
| 376 |
</select> |
| 377 |
<?php elseif ( 'checkbox' == $field['type'] ) : ?> |
| 378 |
<label class="ayg-form-label" for="ayg-form-field-<?php echo esc_attr( $field['name'] ); ?>"> |
| 379 |
<input type="checkbox" name="<?php echo esc_attr( $field['name'] ); ?>" id="ayg-form-field-<?php echo esc_attr( $field['name'] ); ?>" class="ayg-form-field ayg-form-field-<?php echo esc_attr( $field['name'] ); ?>" value="1" <?php checked( $field['value'], 1 ); disabled( $is_locked ); ?> /> |
| 380 |
<?php echo esc_html( $field['label'] ); ?> |
| 381 |
</label> |
| 382 |
<?php elseif ( 'color' == $field['type'] ) : ?> |
| 383 |
<label class="ayg-form-label" for="ayg-form-field-<?php echo esc_attr( $field['name'] ); ?>"><?php echo esc_html( $field['label'] ); echo $required_mark; ?></label> |
| 384 |
<input type="text" name="<?php echo esc_attr( $field['name'] ); ?>" id="ayg-form-field-<?php echo esc_attr( $field['name'] ); ?>" class="ayg-form-field ayg-form-field-<?php echo esc_attr( $field['name'] ); ?> ayg-color-picker widefat" value="<?php echo esc_attr( $field['value'] ); ?>"<?php disabled( $is_locked ); ?> /> |
| 385 |
<?php endif; ?> |
| 386 |
|
| 387 |
<?php if ( 'source' === $key && in_array( $field['name'], $source_value_fields, true ) ) : ?> |
| 388 |
<span class="ayg-form-status"></span> |
| 389 |
<?php endif; ?> |
| 390 |
|
| 391 |
<?php if ( ! empty( $field['description'] ) ) : ?> |
| 392 |
<p class="description"><?php echo wp_kses_post( $field['description'] ); ?></p> |
| 393 |
<?php endif; ?> |
| 394 |
</div> |
| 395 |
<?php |
| 396 |
endforeach; |
| 397 |
?> |
| 398 |
</div> |
| 399 |
</details> |
| 400 |
<?php endforeach; ?> |
| 401 |
|
| 402 |
<?php |
| 403 |
$logs = ! $is_new ? json_decode( (string) $form_data['import_log'], true ) : array(); |
| 404 |
$logs = is_array( $logs ) ? array_reverse( $logs ) : array(); |
| 405 |
|
| 406 |
if ( $logs ) : ?> |
| 407 |
<details class="ayg-form-section-import-history"> |
| 408 |
<summary> |
| 409 |
<span><?php esc_html_e( 'Import History', 'automatic-youtube-gallery' ); ?></span> |
| 410 |
</summary> |
| 411 |
|
| 412 |
<div class="ayg-form-controls"> |
| 413 |
<table class="wp-list-table widefat fixed striped"> |
| 414 |
<thead> |
| 415 |
<tr> |
| 416 |
<th scope="col" class="column-number">#</th> |
| 417 |
<th scope="col" class="column-date column-primary"><?php esc_html_e( 'Date', 'automatic-youtube-gallery' ); ?></th> |
| 418 |
<th scope="col" class="column-videos"><?php esc_html_e( 'Videos', 'automatic-youtube-gallery' ); ?></th> |
| 419 |
<th scope="col" class="column-status"><?php esc_html_e( 'Status', 'automatic-youtube-gallery' ); ?></th> |
| 420 |
</tr> |
| 421 |
</thead> |
| 422 |
<tbody> |
| 423 |
<?php foreach ( $logs as $index => $log ) : ?> |
| 424 |
<tr> |
| 425 |
<th scope="row" class="column-number"><?php echo (int) $index + 1; ?></th> |
| 426 |
<td class="column-date column-primary" data-colname="<?php esc_attr_e( 'Date', 'automatic-youtube-gallery' ); ?>"> |
| 427 |
<?php echo esc_html( ! empty( $log['date'] ) ? wp_date( $date_format, strtotime( $log['date'] ) ) : '' ); ?> |
| 428 |
<button type="button" class="toggle-row"><span class="screen-reader-text"><?php esc_html_e( 'Show more details', 'automatic-youtube-gallery' ); ?></span></button> |
| 429 |
</td> |
| 430 |
<td class="column-videos" data-colname="<?php esc_attr_e( 'Videos', 'automatic-youtube-gallery' ); ?>"> |
| 431 |
<ul> |
| 432 |
<li> |
| 433 |
<span><?php esc_html_e( 'Imported', 'automatic-youtube-gallery' ); ?>:</span> |
| 434 |
<span class="ayg-text-info"><?php echo isset( $log['imported'] ) ? (int) $log['imported'] : 0; ?></span> |
| 435 |
</li> |
| 436 |
<?php if ( ! empty( $log['updated'] ) ) : ?> |
| 437 |
<li> |
| 438 |
<span><?php esc_html_e( 'Updated', 'automatic-youtube-gallery' ); ?>:</span> |
| 439 |
<span class="ayg-text-info"><?php echo (int) $log['updated']; ?></span> |
| 440 |
</li> |
| 441 |
<?php endif; ?> |
| 442 |
<?php if ( ! empty( $log['deleted'] ) ) : ?> |
| 443 |
<li> |
| 444 |
<span><?php esc_html_e( 'Deleted', 'automatic-youtube-gallery' ); ?>:</span> |
| 445 |
<span class="ayg-text-info"><?php echo (int) $log['deleted']; ?></span> |
| 446 |
</li> |
| 447 |
<?php endif; ?> |
| 448 |
</ul> |
| 449 |
</td> |
| 450 |
<td class="column-status" data-colname="<?php esc_attr_e( 'Status', 'automatic-youtube-gallery' ); ?>"> |
| 451 |
<?php |
| 452 |
$log_status = isset( $log['status'] ) ? $log['status'] : 'idle'; |
| 453 |
|
| 454 |
// A recurring success is stored as 'idle'; render it with the green "completed" |
| 455 |
// badge so both success rows match. Live-state 'idle' badges (KPI card, list) are |
| 456 |
// unaffected — this mapping is local to the history table. |
| 457 |
$log_badge_class = ( 'idle' === $log_status ) ? 'completed' : $log_status; |
| 458 |
?> |
| 459 |
<span class="ayg-badge ayg-badge-<?php echo esc_attr( $log_badge_class ); ?>"><?php echo esc_html( ayg_get_import_status_label( $log_status, null, false, 'log' ) ); ?></span> |
| 460 |
<?php if ( ! empty( $log['error'] ) ) : ?> |
| 461 |
<p class="ayg-text-error"><?php echo esc_html( sanitize_text_field( $log['error'] ) ); ?></p> |
| 462 |
<?php endif; ?> |
| 463 |
</td> |
| 464 |
</tr> |
| 465 |
<?php endforeach; ?> |
| 466 |
</tbody> |
| 467 |
</table> |
| 468 |
</div> |
| 469 |
</details> |
| 470 |
<?php endif; ?> |
| 471 |
|
| 472 |
<?php if ( ! $is_new && ! in_array( $form_data['type'], $live_types, true ) ) : ?> |
| 473 |
<p class="description"> |
| 474 |
<label> |
| 475 |
<input type="checkbox" id="ayg-can-import-videos" checked /> |
| 476 |
<?php esc_html_e( 'Import videos from YouTube now, when you save — adds new videos, updates titles/descriptions, and removes deleted ones. Uncheck to save display settings only. This is a one-time import on save and is separate from the Import Schedule above.', 'automatic-youtube-gallery' ); ?> |
| 477 |
</label> |
| 478 |
</p> |
| 479 |
<?php endif; ?> |
| 480 |
|
| 481 |
<div class="ayg-form-actions"> |
| 482 |
<input type="hidden" name="gallery_id" value="<?php echo absint( $gallery_id ); ?>"> |
| 483 |
|
| 484 |
<button type="button" id="ayg-button-save-gallery" class="ayg-button ayg-button-save-gallery button button-primary button-hero" data-id="<?php echo absint( $gallery_id ); ?>"> |
| 485 |
<?php echo $is_new ? esc_html__( 'Create Gallery', 'automatic-youtube-gallery' ) : esc_html__( 'Update Gallery', 'automatic-youtube-gallery' ); ?> |
| 486 |
</button> |
| 487 |
|
| 488 |
<?php if ( ! $is_new ) : ?> |
| 489 |
<button type="button" id="ayg-button-delete-gallery" class="ayg-button ayg-button-delete-gallery button button-hero" data-id="<?php echo absint( $gallery_id ); ?>"> |
| 490 |
<?php esc_html_e( 'Delete Gallery', 'automatic-youtube-gallery' ); ?> |
| 491 |
</button> |
| 492 |
<?php endif; ?> |
| 493 |
|
| 494 |
<span class="ayg-form-status"></span> |
| 495 |
</div> |
| 496 |
</form> |
| 497 |
</div> |
| 498 |
|