BAsic functionality
This commit is contained in:
parent
b772c26822
commit
fd9a0311a6
6 changed files with 3304 additions and 0 deletions
213
src/fwp-calendar.php
Normal file
213
src/fwp-calendar.php
Normal file
|
@ -0,0 +1,213 @@
|
|||
<?php
|
||||
/**
|
||||
* Plugin Name: Free WordPress Calendar
|
||||
* Plugin URI: https://example.com/
|
||||
* Description: Display multiple iCal feeds in a calendar and show upcoming events with a shortcode.
|
||||
* Version: 1.0
|
||||
* Author: Your Name
|
||||
* License: GPL2
|
||||
* Text Domain: fwp-calendar
|
||||
*/
|
||||
|
||||
require_once plugin_dir_path(__FILE__) . 'ical/ical.php';
|
||||
require_once plugin_dir_path(__FILE__) . 'ical/event.php';
|
||||
|
||||
use ICal\ICal;
|
||||
|
||||
class FWP_Calendar {
|
||||
|
||||
private $option_name = 'fwp_calendar_urls';
|
||||
|
||||
public function __construct() {
|
||||
add_action('admin_menu', [$this, 'admin_menu']);
|
||||
add_action('admin_init', [$this, 'register_settings']);
|
||||
add_action('wp_enqueue_scripts', [$this, 'enqueue_assets']);
|
||||
add_shortcode('event-calendar', [$this, 'shortcode_handler']);
|
||||
}
|
||||
|
||||
public function admin_menu() {
|
||||
add_options_page('FWP Calendar', 'FWP Calendar', 'manage_options', 'fwp-calendar', [$this, 'settings_page']);
|
||||
}
|
||||
|
||||
public function register_settings() {
|
||||
register_setting('fwp-calendar-settings-group', $this->option_name);
|
||||
}
|
||||
|
||||
public function enqueue_assets() {
|
||||
// Enqueue FullCalendar JS and CSS from plugin folder (ensure these files exist)
|
||||
wp_enqueue_script(
|
||||
'fwp-calendar-fullcalendar-js',
|
||||
plugins_url('fullcalendar.min.js', __FILE__),
|
||||
[],
|
||||
'6.1.8',
|
||||
true
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'fwp-calendar-js',
|
||||
plugins_url('calendar.js', __FILE__),
|
||||
['fwp-calendar-fullcalendar-js'],
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public function settings_page() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1>Free WordPress Calendar Settings</h1>
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
settings_fields('fwp-calendar-settings-group');
|
||||
$urls = get_option($this->option_name, []);
|
||||
if (!is_array($urls)) {
|
||||
$urls = array_filter(array_map('trim', explode("\n", $urls)));
|
||||
}
|
||||
?>
|
||||
<table class="form-table">
|
||||
<tr valign="top">
|
||||
<th scope="row">iCal URLs</th>
|
||||
<td>
|
||||
<div id="fwp-calendar-url-list">
|
||||
<?php foreach ($urls as $i => $url): ?>
|
||||
<div class="fwp-url-entry" style="margin-bottom: 5px;">
|
||||
<input type="text" name="<?php echo esc_attr($this->option_name); ?>[]" value="<?php echo esc_attr($url); ?>" style="width: 90%;" />
|
||||
<button type="button" class="button button-small" onclick="this.parentNode.remove()">Remove</button>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<button type="button" class="button" onclick="fwpAddUrlField()">Add URL</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php submit_button(); ?>
|
||||
</form>
|
||||
</div>
|
||||
<script>
|
||||
function fwpAddUrlField() {
|
||||
const container = document.getElementById('fwp-calendar-url-list');
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'fwp-url-entry';
|
||||
wrapper.style = 'margin-bottom: 5px;';
|
||||
wrapper.innerHTML = `
|
||||
<input type="text" name="<?php echo esc_attr($this->option_name); ?>[]" style="width: 90%;" />
|
||||
<button type="button" class="button button-small" onclick="this.parentNode.remove()">Remove</button>
|
||||
`;
|
||||
container.appendChild(wrapper);
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
public function shortcode_handler($atts) {
|
||||
$atts = shortcode_atts([
|
||||
'id' => '',
|
||||
'show_upcoming' => 'true',
|
||||
], $atts);
|
||||
|
||||
$show_upcoming = filter_var($atts['show_upcoming'], FILTER_VALIDATE_BOOLEAN);
|
||||
$urls = get_option($this->option_name, []);
|
||||
if (!is_array($urls)) $urls = [];
|
||||
|
||||
if ($atts['id'] !== '') {
|
||||
$key = intval($atts['id']) - 1;
|
||||
if (isset($urls[$key])) {
|
||||
$urls = [$urls[$key]];
|
||||
} else {
|
||||
return '<p>Invalid calendar ID.</p>';
|
||||
}
|
||||
}
|
||||
|
||||
$events = [];
|
||||
foreach ($urls as $url) {
|
||||
$url = trim($url);
|
||||
$ics_content = @file_get_contents(trim($url));
|
||||
|
||||
if (!$ics_content) {
|
||||
error_log("FWP Calendar: Failed to fetch ICS from $url");
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$parser = new ICal();
|
||||
$parser->initString($ics_content); // <-- This is the fix
|
||||
} catch (Exception $e) {
|
||||
error_log('FWP Calendar: Failed to parse ICS: ' . $e->getMessage());
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($parser->events() as $event) {
|
||||
$start_ts = method_exists($parser, 'iCalDateToTimestamp')
|
||||
? $parser->iCalDateToTimestamp($event->dtstart)
|
||||
: strtotime($event->dtstart);
|
||||
$end_ts = isset($event->dtend)
|
||||
? (method_exists($parser, 'iCalDateToTimestamp') ? $parser->iCalDateToTimestamp($event->dtend) : strtotime($event->dtend))
|
||||
: $start_ts;
|
||||
|
||||
$events[] = [
|
||||
'title' => $event->summary ?? 'No Title',
|
||||
'start' => date('c', $start_ts),
|
||||
'end' => date('c', $end_ts),
|
||||
'url' => $event->url ?? '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<div id="event-calendar" style="max-width: 900px; margin: auto; height: 600px;"></div>
|
||||
<script>
|
||||
var EventCalendar = {
|
||||
events: <?php echo json_encode($events); ?>
|
||||
};
|
||||
</script>
|
||||
<?php
|
||||
|
||||
if ($show_upcoming && !empty($events)) {
|
||||
usort($events, function ($a, $b) {
|
||||
return strtotime($a['start']) - strtotime($b['start']);
|
||||
});
|
||||
|
||||
$now = time();
|
||||
$count = 0;
|
||||
|
||||
echo '<div class="upcoming-events" style="max-width: 900px; margin: 2rem auto;">';
|
||||
echo '<h2>Upcoming Events</h2><ul>';
|
||||
|
||||
foreach ($events as $event) {
|
||||
$start_ts = strtotime($event['start']);
|
||||
if ($start_ts >= $now) {
|
||||
$start_attr = esc_attr($event['start']);
|
||||
$end_attr = isset($event['end']) ? esc_attr($event['end']) : '';
|
||||
|
||||
echo '<li class="event-item" data-title="'.$event['title'].'" data-start="' . $start_attr . '"';
|
||||
if ($end_attr !== '') {
|
||||
echo ' data-end="' . $end_attr . '"';
|
||||
}
|
||||
echo '>';
|
||||
|
||||
if (!empty($event['url'])) {
|
||||
echo '<a href="' . esc_url($event['url']) . '" target="_blank" rel="noopener noreferrer">' . esc_html($event['title']) . '</a>';
|
||||
} else {
|
||||
echo esc_html($event['title']);
|
||||
}
|
||||
|
||||
echo '</li>';
|
||||
|
||||
$count++;
|
||||
if ($count >= 5) break;
|
||||
}
|
||||
}
|
||||
|
||||
echo '</ul></div>';
|
||||
}
|
||||
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
new FWP_Calendar();
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue