Skip to content

Commit 9f392b5

Browse files
raytileyclaude
andcommitted
Fix 6 bugs from tester feedback
BUG-1: Timezone 8-hours-ahead issue - Add run_timestamp to schedule data for timezone-safe comparisons instead of using strtotime() on already converted time strings BUG-2: Weekly Guide channel switcher - Remove inline onchange handler, let JavaScript handle URL building properly with URL API BUG-3: Settings checkbox won't disable - Add sanitization callback to explicitly handle unchecked checkboxes BUG-4: Cablecast Home channel buttons - Add JavaScript click handlers and URL parameter support for channel tabs BUG-5: Categories grid breaks with long names - Add CSS overflow handling with word-break and hyphens BUG-6: Cablecast Home browse links - Fix undefined $shows_archive variable 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 11214dc commit 9f392b5

5 files changed

Lines changed: 104 additions & 21 deletions

File tree

assets/css/shortcodes.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,8 @@ a.cablecast-shows__title:hover {
671671
border-radius: 0.375rem;
672672
padding: 0.75rem 1rem;
673673
border-left: 3px solid #e5e7eb;
674+
min-width: 0;
675+
overflow: hidden;
674676
}
675677

676678
.cablecast-categories__color {
@@ -682,6 +684,10 @@ a.cablecast-shows__title:hover {
682684

683685
.cablecast-categories__name {
684686
flex: 1;
687+
min-width: 0;
688+
overflow-wrap: break-word;
689+
word-break: break-word;
690+
hyphens: auto;
685691
}
686692

687693
.cablecast-categories__count {

assets/js/shortcodes.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
document.addEventListener('DOMContentLoaded', function() {
1414
initWeeklyGuide();
1515
initNowPlayingProgress();
16+
initCablecastHome();
1617
});
1718

1819
/**
@@ -87,4 +88,24 @@
8788
}, 30000);
8889
}
8990

91+
/**
92+
* Initialize Cablecast Home functionality.
93+
*/
94+
function initCablecastHome() {
95+
var homeContainers = document.querySelectorAll('.cablecast-home');
96+
97+
homeContainers.forEach(function(container) {
98+
var tabs = container.querySelectorAll('.cablecast-home__channel-tab');
99+
100+
tabs.forEach(function(tab) {
101+
tab.addEventListener('click', function() {
102+
var channelId = this.dataset.channel;
103+
var url = new URL(window.location.href);
104+
url.searchParams.set('channel', channelId);
105+
window.location.href = url.toString();
106+
});
107+
});
108+
});
109+
}
110+
90111
})();

includes/settings.php

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,49 @@ function cablecast_get_custom_taxonomies() {
107107
return $custom_taxonomies;
108108
}
109109

110+
/**
111+
* Sanitize the cablecast options.
112+
* Ensures checkbox fields are properly saved as false when unchecked.
113+
*/
114+
function cablecast_sanitize_options($input) {
115+
$current_options = get_option('cablecast_options', []);
116+
117+
// Define checkbox fields that need explicit false handling
118+
$checkbox_fields = [
119+
'shortcode_styles',
120+
'delete_local_thumbnails',
121+
'enable_category_colors',
122+
];
123+
124+
// If input is not an array, return current options
125+
if (!is_array($input)) {
126+
return $current_options;
127+
}
128+
129+
// Merge with current options
130+
$output = array_merge($current_options, $input);
131+
132+
// Handle checkbox fields - if not present in input, set to false
133+
foreach ($checkbox_fields as $field) {
134+
if (!isset($input[$field])) {
135+
$output[$field] = false;
136+
} else {
137+
$output[$field] = (bool) $input[$field];
138+
}
139+
}
140+
141+
return $output;
142+
}
143+
110144
/**
111145
* custom option and settings
112146
*/
113147
function cablecast_settings_init()
114148
{
115-
// register a new setting for "cablecast" page
116-
register_setting('cablecast', 'cablecast_options');
149+
// register a new setting for "cablecast" page with sanitization callback
150+
register_setting('cablecast', 'cablecast_options', [
151+
'sanitize_callback' => 'cablecast_sanitize_options',
152+
]);
117153

118154
// register a new section in the "cablecast" page
119155
add_settings_section(
@@ -579,7 +615,8 @@ function cablecast_section_shortcodes_cb($args)
579615
function cablecast_field_shortcode_styles_cb($args)
580616
{
581617
$options = get_option('cablecast_options');
582-
$styles_enabled = !isset($options['shortcode_styles']) || $options['shortcode_styles'];
618+
// Default to true if never saved, otherwise use the saved value
619+
$styles_enabled = !isset($options['shortcode_styles']) ? true : (bool) $options['shortcode_styles'];
583620
?>
584621
<fieldset>
585622
<label>

includes/shortcodes.php

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -342,18 +342,19 @@ function cablecast_schedule_shortcode($atts) {
342342
continue;
343343
}
344344

345-
$item_time = strtotime($item->run_date_time);
345+
// Use run_timestamp for timezone-safe comparisons
346+
$item_timestamp = $item->run_timestamp;
346347

347348
switch ($mode) {
348349
case 'remaining':
349350
// Only shows that haven't ended yet (assuming 30min default)
350-
if ($item_time + 1800 > $now_timestamp) {
351+
if ($item_timestamp + 1800 > $now_timestamp) {
351352
$filtered_items[] = $item;
352353
}
353354
break;
354355
case 'next':
355356
// Only future shows
356-
if ($item_time > $now_timestamp) {
357+
if ($item_timestamp > $now_timestamp) {
357358
$filtered_items[] = $item;
358359
}
359360
break;
@@ -515,7 +516,8 @@ function cablecast_now_playing_shortcode($atts) {
515516

516517
for ($i = 0; $i < count($items); $i++) {
517518
$item = $items[$i];
518-
$item_start = strtotime($item->run_date_time);
519+
// Use run_timestamp for timezone-safe comparisons
520+
$item_start = $item->run_timestamp;
519521

520522
// Get runtime from show meta if available
521523
$show = cablecast_get_show_from_schedule($item);
@@ -710,12 +712,11 @@ function cablecast_weekly_guide_shortcode($atts) {
710712

711713
$output = '<div class="' . implode(' ', $classes) . '">';
712714

713-
// Channel switcher
715+
// Channel switcher (JavaScript in shortcodes.js handles the change event)
714716
if ($show_channel_switcher && count($channels) > 1) {
715-
$current_url = remove_query_arg('channel');
716717
$output .= '<div class="cablecast-weekly-guide__channel-switcher">';
717718
$output .= '<label for="cablecast-channel-select">' . __('Channel:', 'cablecast') . '</label>';
718-
$output .= '<select id="cablecast-channel-select" onchange="window.location.href=\'' . esc_url($current_url) . '&channel=\' + this.value">';
719+
$output .= '<select id="cablecast-channel-select">';
719720
foreach ($channels as $channel) {
720721
$selected = ($channel->ID === $channel_id) ? ' selected' : '';
721722
$output .= '<option value="' . esc_attr($channel->ID) . '"' . $selected . '>';
@@ -762,8 +763,8 @@ function cablecast_weekly_guide_shortcode($atts) {
762763
$show = cablecast_get_show_from_schedule($item);
763764
$item_time = date('g:i A', strtotime($item->run_date_time));
764765

765-
// Determine if this is the current program
766-
$item_timestamp = strtotime($item->run_date_time);
766+
// Determine if this is the current program using run_timestamp for timezone-safe comparisons
767+
$item_timestamp = $item->run_timestamp;
767768
$is_current = false;
768769
if ($is_today) {
769770
$runtime = $show ? (int) get_post_meta($show->ID, 'cablecast_show_trt', true) : 1800;
@@ -1927,7 +1928,21 @@ function cablecast_home_shortcode($atts) {
19271928

19281929
// Get channels
19291930
$channels = cablecast_get_all_channels();
1930-
$default_channel = !empty($channels) ? $channels[0]->ID : 0;
1931+
1932+
// Check for channel in URL parameter, otherwise use first channel
1933+
$selected_channel = 0;
1934+
if (isset($_GET['channel'])) {
1935+
$selected_channel = absint($_GET['channel']);
1936+
}
1937+
// Validate the channel exists in our list
1938+
$valid_channel = false;
1939+
foreach ($channels as $channel) {
1940+
if ($channel->ID === $selected_channel) {
1941+
$valid_channel = true;
1942+
break;
1943+
}
1944+
}
1945+
$default_channel = $valid_channel ? $selected_channel : (!empty($channels) ? $channels[0]->ID : 0);
19311946

19321947
// Get section headings from settings
19331948
$now_playing_heading = isset($home_settings['now_playing_heading']) ? $home_settings['now_playing_heading'] : __('Now Playing', 'cablecast');
@@ -1948,11 +1963,11 @@ function cablecast_home_shortcode($atts) {
19481963
$output .= '<section class="cablecast-home__section cablecast-home__section--now-playing">';
19491964
$output .= '<h2 class="cablecast-home__section-heading">' . esc_html($now_playing_heading) . '</h2>';
19501965

1951-
// If multiple channels, show tabs
1966+
// If multiple channels, show tabs (JavaScript in shortcodes.js handles click events)
19521967
if (count($channels) > 1) {
19531968
$output .= '<div class="cablecast-home__channel-tabs">';
1954-
foreach ($channels as $index => $channel) {
1955-
$active = $index === 0 ? ' cablecast-home__channel-tab--active' : '';
1969+
foreach ($channels as $channel) {
1970+
$active = ($channel->ID === $default_channel) ? ' cablecast-home__channel-tab--active' : '';
19561971
$output .= '<button type="button" class="cablecast-home__channel-tab' . $active . '" data-channel="' . esc_attr($channel->ID) . '">';
19571972
$output .= esc_html($channel->post_title);
19581973
$output .= '</button>';
@@ -2028,11 +2043,13 @@ function cablecast_home_shortcode($atts) {
20282043
$output .= '<h3 class="cablecast-home__browse-heading">' . esc_html__('Producers', 'cablecast') . '</h3>';
20292044
$output .= do_shortcode('[cablecast_producers count="10" orderby="count" layout="list"]');
20302045

2031-
$producers_link = get_term_link('cablecast_producer');
2032-
// Note: get_term_link with just taxonomy returns WP_Error, so we link to shows archive instead
2033-
$output .= '<a href="' . esc_url($shows_archive ?? '#') . '" class="cablecast-home__browse-link">';
2034-
$output .= __('All Producers', 'cablecast') . ' &rarr;';
2035-
$output .= '</a>';
2046+
// Link to shows archive with browse parameter
2047+
$producers_archive = get_post_type_archive_link('show');
2048+
if ($producers_archive) {
2049+
$output .= '<a href="' . esc_url(add_query_arg('browse', 'producers', $producers_archive)) . '" class="cablecast-home__browse-link">';
2050+
$output .= __('All Producers', 'cablecast') . ' &rarr;';
2051+
$output .= '</a>';
2052+
}
20362053
$output .= '</div>';
20372054

20382055
$output .= '</div>'; // browse-grid

theme-functions.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ function cablecast_get_schedules($channel_id, $date_start, $date_end = NULL) {
3535
));
3636

3737
// Convert the retrieved run_date_time from UTC to the site timezone
38+
// Also add run_timestamp for timezone-safe comparisons in shortcodes
3839
foreach ($results as $result) {
3940
$run_date_time_utc = new DateTime($result->run_date_time, new DateTimeZone('UTC'));
41+
$result->run_timestamp = $run_date_time_utc->getTimestamp();
4042
$run_date_time_utc->setTimezone(new DateTimeZone($timezone));
4143
$result->run_date_time = $run_date_time_utc->format('Y-m-d H:i:s');
4244
}

0 commit comments

Comments
 (0)