177 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * Plugin Name: WordPress SpaceAPI Consumer
 | |
|  * Plugin Slug: wp-spaceapi-consumer
 | |
|  * Plugin URI:  https://gitea.alluna.pt/jfig/wp-spaceapi-consumer
 | |
|  * Description: WordPress plugin to consume a SpaceAPI endpoint and indicate if the Space is Open or Closed
 | |
|  * Version:     0.4.2
 | |
|  * 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 wp-spaceapi-consumer-config.php located in the same
 | |
| | directory. If that file is missing, sane defaults are used so the plugin
 | |
| | still works out-of-the-box.
 | |
| */
 | |
| 
 | |
| $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( 'SSI_API_URL' )   && define( 'SSI_API_URL',   'https://lcdporto.org/api/spaceapi' );
 | |
| ! defined( 'SSI_CACHE_KEY' ) && define( 'SSI_CACHE_KEY', 'ssi_space_api_status' );
 | |
| ! defined( 'SSI_CACHE_TTL' ) && define( 'SSI_CACHE_TTL', 10 ); // seconds
 | |
| 
 | |
| /*
 | |
| |--------------------------------------------------------------------------
 | |
| | Core - fetch & cache
 | |
| |--------------------------------------------------------------------------
 | |
| */
 | |
| 
 | |
| /**
 | |
|  * Retrieves space open status (boolean) with transient caching.
 | |
|  *
 | |
|  * Supported JSON payloads (any case):
 | |
|  *   - true / false (bare boolean)
 | |
|  *   - {"state": {"open": true}} (SpaceAPI standard)
 | |
|  *
 | |
|  * @return bool True if open, false if closed (or on error).
 | |
|  */
 | |
| function ssi_get_status() : bool {
 | |
|     $cached = get_transient( SSI_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( SSI_API_URL, [
 | |
|         'timeout'    => 3,
 | |
|         'user-agent' => $plugin_data['TextDomain'] . '/' . $plugin_data['Version'] . ' (+https://wordpress.org/)',
 | |
|     ] );
 | |
| 
 | |
|     if ( is_wp_error( $response ) ) {
 | |
|         set_transient( SSI_CACHE_KEY, false, SSI_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 ) ) {
 | |
|         // SpaceAPI standard format - state.open
 | |
|         if ( isset( $decoded['state']['open'] ) ) {
 | |
|             $status = (bool) $decoded['state']['open'];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     set_transient( SSI_CACHE_KEY, $status, SSI_CACHE_TTL );
 | |
|     return $status;
 | |
| }
 | |
| 
 | |
| /*
 | |
| |--------------------------------------------------------------------------
 | |
| | Shortcode [door_status]
 | |
| |--------------------------------------------------------------------------
 | |
| */
 | |
| 
 | |
| function ssi_shortcode() : string {
 | |
|     $open  = ssi_get_status();
 | |
|     $emoji = $open ? '<div class="space-status-indicator open">🟢 Open</div>' : '<div class="space-status-indicator closed">🔴 Closed</div>';
 | |
| 
 | |
|     return sprintf(
 | |
|         '<span class="space-status-indicator" aria-label="Space is %s">%s</span>',
 | |
|         $open ? 'open' : 'closed',
 | |
|         $emoji
 | |
|     );
 | |
| }
 | |
| add_shortcode( 'space_status', 'ssi_shortcode' );
 | |
| // Keep the old shortcode for backward compatibility
 | |
| add_shortcode( 'door_status', 'ssi_shortcode' );
 | |
| 
 | |
| /*
 | |
| |--------------------------------------------------------------------------
 | |
| | Admin Bar indicator
 | |
| |--------------------------------------------------------------------------
 | |
| */
 | |
| 
 | |
| function ssi_admin_bar( WP_Admin_Bar $bar ) : void {
 | |
|     if ( ! current_user_can( 'read' ) ) {
 | |
|         return; // Logged-in users only.
 | |
|     }
 | |
| 
 | |
|     $open  = ssi_get_status();
 | |
|     $emoji = $open ? '🟢' : '🔴';
 | |
|     $text  = $open ? __( 'Space Open', 'wp-spaceapi-consumer' ) : __( 'Space Closed', 'wp-spaceapi-consumer' );
 | |
| 
 | |
|     $bar->add_node( [
 | |
|         'id'    => 'space-status-indicator',
 | |
|         'title' => "$emoji $text",
 | |
|         'href'  => '#',
 | |
|         'meta'  => [ 'title' => $text ],
 | |
|     ] );
 | |
| }
 | |
| add_action( 'admin_bar_menu', 'ssi_admin_bar', 1000 );
 | |
| 
 | |
| /*
 | |
| |--------------------------------------------------------------------------
 | |
| | Front-end inline CSS (kept minimal)
 | |
| |--------------------------------------------------------------------------
 | |
| */
 | |
| 
 | |
| /**
 | |
|  * Front-end + admin-bar styles for the indicator.
 | |
|  */
 | |
| function ssi_enqueue_assets() : void {
 | |
|     // register & enqueue the standalone CSS file
 | |
|     wp_enqueue_style(
 | |
|         'space-status-indicator',
 | |
|         plugins_url( 'wp-spaceapi-consumer-style.css', __FILE__ ),
 | |
|         [],          // no dependencies
 | |
|         '1.0.0'      // file version
 | |
|     );
 | |
| }
 | |
| add_action( 'wp_enqueue_scripts', 'ssi_enqueue_assets' );
 | |
| add_action( 'admin_enqueue_scripts', 'ssi_enqueue_assets' ); // so the Admin Bar icon also gets styled
 | |
| 
 | |
| 
 | |
| /*
 | |
| |--------------------------------------------------------------------------
 | |
| | WP-CLI command (optional)
 | |
| |--------------------------------------------------------------------------
 | |
| */
 | |
| 
 | |
| if ( defined( 'WP_CLI' ) && WP_CLI ) {
 | |
|     WP_CLI::add_command( 'space-status', function() {
 | |
|         WP_CLI::success( ssi_get_status() ? 'Space is open 🟢' : 'Space is closed 🔴' );
 | |
|     } );
 | |
| }
 | |
| 
 | |
| // Gutenberg block support (dynamic Space Status block)
 | |
| if ( function_exists( 'register_block_type' ) ) {
 | |
|     require_once plugin_dir_path( __FILE__ ) . 'blocks-register.php';
 | |
| }
 | |
| 
 | |
| 
 | |
| // End of file
 |