Files
wp-spaceapi-consumer/wp-spaceapi-consumer.php

171 lines
5.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Plugin Name: WordPress SpaceAPI Consumer
* Plugin Slug: wp-spaceapi-consumer
* Plugin URI: https://gitea.alluna.pt/jfig/wp-spaceapi-consumer
* Description: Small WordPress plugin to consume an SpaceAPI endpoint and indicate on the WordPress website if the Space is Open or Closed
* Version: 1.1.1
* Author: Joao Figueiredo, LCD Porto Team, ChatGPT o3
* Author URI: https://lcdporto.org
* License: MIT
* License URI: https://gitea.alluna.pt/jfig/wp-spaceapi-consumer/src/branch/dev/LICENSE
* Text Domain: wp-spaceapi-consumer
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/*
|--------------------------------------------------------------------------
| Configuration
|--------------------------------------------------------------------------
| Constants are expected in door-status-config.php located in the same
| directory. If that file is missing, sane defaults are used so the plugin
| still works outofthebox.
*/
$config_file = plugin_dir_path( __FILE__ ) . 'wp-spaceapi-consumer-config.php';
if ( file_exists( $config_file ) ) {
require_once $config_file;
}
// Fallback defaults (only if not already defined by the config file).
! defined( 'DSI_API_URL' ) && define( 'DSI_API_URL', 'https://lcdporto.org/api/spaceapi' );
! defined( 'DSI_CACHE_KEY' ) && define( 'DSI_CACHE_KEY', 'dsi_space_api_status' );
! defined( 'DSI_CACHE_TTL' ) && define( 'DSI_CACHE_TTL', 10 ); // seconds
/*
|--------------------------------------------------------------------------
| Core fetch & cache
|--------------------------------------------------------------------------
*/
/**
* Retrieves dooropen status (boolean) with transient caching.
*
* Supported JSON payloads (any case):
* true / false (bare boolean)
* {"open": true}
* {"doorOpen": true}
*
* @return bool True if open, false if closed (or on error).
*/
function dsi_get_status() : bool {
$cached = get_transient( DSI_CACHE_KEY );
if ( false !== $cached ) {
return (bool) $cached;
}
// Get plugin data for dynamic user agent
$plugin_data = get_file_data( __FILE__, array(
'Version' => 'Version',
'TextDomain' => 'Text Domain'
), 'plugin' );
$response = wp_remote_get( DSI_API_URL, [
'timeout' => 3,
'user-agent' => $plugin_data['TextDomain'] . '/' . $plugin_data['Version'] . ' (+https://wordpress.org/)',
] );
if ( is_wp_error( $response ) ) {
set_transient( DSI_CACHE_KEY, false, DSI_CACHE_TTL );
return false;
}
$body = wp_remote_retrieve_body( $response );
$decoded = json_decode( $body, true );
$status = false; // default to closed
if ( is_bool( $decoded ) ) {
$status = $decoded;
} elseif ( is_array( $decoded ) ) {
if ( isset( $decoded['open'] ) ) {
$status = (bool) $decoded['open'];
} elseif ( isset( $decoded['doorOpen'] ) ) {
$status = (bool) $decoded['doorOpen'];
}
}
set_transient( DSI_CACHE_KEY, $status, DSI_CACHE_TTL );
return $status;
}
/*
|--------------------------------------------------------------------------
| Shortcode [door_status]
|--------------------------------------------------------------------------
*/
function dsi_shortcode() : string {
$open = dsi_get_status();
$emoji = $open ? '<div class="door-status-indicator open">🟢 Open</div>' : '<div class="door-status-indicator closed">🔴 Closed</div>';
return sprintf(
'<span class="door-status-indicator" aria-label="Door is %s">%s</span>',
$open ? 'open' : 'closed',
$emoji
);
}
add_shortcode( 'door_status', 'dsi_shortcode' );
/*
|--------------------------------------------------------------------------
| Admin Bar indicator
|--------------------------------------------------------------------------
*/
function dsi_admin_bar( WP_Admin_Bar $bar ) : void {
if ( ! current_user_can( 'read' ) ) {
return; // Loggedin users only.
}
$open = dsi_get_status();
$emoji = $open ? '🟢' : '🔴';
$text = $open ? __( 'Door Open', 'door-status-indicator' ) : __( 'Door Closed', 'door-status-indicator' );
$bar->add_node( [
'id' => 'door-status-indicator',
'title' => "$emoji $text",
'href' => '#',
'meta' => [ 'title' => $text ],
] );
}
add_action( 'admin_bar_menu', 'dsi_admin_bar', 1000 );
/*
|--------------------------------------------------------------------------
| Frontend inline CSS (kept minimal)
|--------------------------------------------------------------------------
*/
/**
* Front-end + admin-bar styles for the indicator.
*/
function dsi_enqueue_assets() : void {
// register & enqueue the standalone CSS file
wp_enqueue_style(
'door-status-indicator',
plugins_url( 'wp-spaceapi-consumer-style.css', __FILE__ ),
[], // no dependencies
'1.0.0' // file version
);
}
add_action( 'wp_enqueue_scripts', 'dsi_enqueue_assets' );
add_action( 'admin_enqueue_scripts', 'dsi_enqueue_assets' ); // so the Admin Bar icon also gets styled
/*
|--------------------------------------------------------------------------
| WPCLI command (optional)
|--------------------------------------------------------------------------
*/
if ( defined( 'WP_CLI' ) && WP_CLI ) {
WP_CLI::add_command( 'door-status', function() {
WP_CLI::success( dsi_get_status() ? 'Door is open 🟢' : 'Door is closed 🔴' );
} );
}
// End of file