Compare commits

...

10 Commits

Author SHA1 Message Date
23eb896c71 Merge pull request 'dev' (#3) from dev into main
Reviewed-on: #3
2025-06-14 00:14:42 +00:00
05c4e67266 Merge pull request '001-gutenberg-block' (#2) from 001-gutenberg-block into dev
Reviewed-on: #2
2025-06-14 00:10:17 +00:00
5bd7dcd9d2 change Block icon to building 2025-06-14 01:02:38 +01:00
88b145d6b3 change Block icon to door 2025-06-14 00:51:49 +01:00
b21a0f03aa fix 1 2025-06-14 00:37:12 +01:00
55c20df3b5 first try 2025-06-13 23:36:21 +01:00
0ed97819fe improve readme 2025-06-02 02:15:42 +01:00
6fa42e8f45 remove non ASCII chars 2025-06-02 00:44:43 +01:00
42345c47b9 major refactor, numenculature change
remove mentions to "door" status, to space
2025-06-02 00:17:55 +01:00
f0f2814d35 make user agent dynamic with changes to plugin's Text Domainand Version 2025-06-01 19:19:36 +01:00
14 changed files with 175 additions and 52 deletions

6
.gitignore vendored
View File

@@ -47,3 +47,9 @@ wp-config.php
# Note: If you wish to whitelist themes, # Note: If you wish to whitelist themes,
# uncomment the next line # uncomment the next line
#/wp-content/themes #/wp-content/themes
# ---> Node.js
/node_modules/
/package-lock.json

View File

@@ -2,4 +2,23 @@
# wp-spaceapi-consumer # wp-spaceapi-consumer
Small WordPress plugin to consume an SpaceAPI endpoint and indicate on the WordPress website if the Space is Open or Closed Small WordPress plugin to consume an SpaceAPI endpoint and indicate on the WordPress website if the Space is Open or Closed
## Usage
### WordPress Editor Block (Gutenberg)
You can use the `Space Status` block in the WordPress editor to display the status of the SpaceAPI endpoint.
### Shortcode
You can use the shortcode `[space_status]` to display the status of the SpaceAPI endpoint on your WordPress site.
### Widget
You can also use the widget `SpaceAPI Status` to display the status of the SpaceAPI endpoint in your WordPress sidebar or footer.
## Changes
### 0.4.x
- Added WordPress Editor Block (Gutenberg) support

21
blocks-register.php Normal file
View File

@@ -0,0 +1,21 @@
<?php
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
return;
}
function ssi_register_space_status_block() : void {
$asset_path = plugin_dir_path( __FILE__ ) . 'build/space-status';
register_block_type( $asset_path, [
'render_callback' => 'ssi_render_block',
] );
}
add_action( 'init', 'ssi_register_space_status_block' );
/**
* Serverside markup for the block.
*/
function ssi_render_block( array $attributes, string $content ) : string {
// Reuse existing helper & CSS class logic.
return ssi_shortcode();
}

View File

@@ -0,0 +1,15 @@
{
"apiVersion": 3,
"name": "wp-spaceapi-consumer/space-status",
"title": "Space Status",
"description": "Show whether the space is open or closed (SpaceAPI consumer).",
"category": "widgets",
"icon": "building",
"textdomain": "wp-spaceapi-consumer",
"style": "file:./style.css",
"editorStyle": "file:./editor.css",
"editorScript": "file:./index.js",
"supports": {
"html": false
}
}

View File

@@ -0,0 +1 @@
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-blocks', 'wp-i18n', 'wp-server-side-render'), 'version' => 'e81eff0b8644d0be4dac');

View File

@@ -0,0 +1 @@
(()=>{"use strict";var e={n:r=>{var s=r&&r.__esModule?()=>r.default:()=>r;return e.d(s,{a:s}),s},d:(r,s)=>{for(var t in s)e.o(s,t)&&!e.o(r,t)&&Object.defineProperty(r,t,{enumerable:!0,get:s[t]})},o:(e,r)=>Object.prototype.hasOwnProperty.call(e,r)};window.wp.i18n;const r=window.wp.blocks,s=window.wp.serverSideRender;var t=e.n(s);const o=window.ReactJSXRuntime;(0,r.registerBlockType)("wp-spaceapi-consumer/space-status",{edit:()=>(0,o.jsx)(t(),{block:"wp-spaceapi-consumer/space-status"}),save:()=>null})})();

15
package.json Normal file
View File

@@ -0,0 +1,15 @@
{
"name": "wp-spaceapi-consumer",
"version": "0.0.0-private",
"private": true,
"scripts": {
"build": "wp-scripts build",
"start": "wp-scripts start"
},
"devDependencies": {
"@wordpress/scripts": "^30.18.0"
},
"engines": {
"node": ">=18.0.0"
}
}

View File

@@ -0,0 +1,13 @@
{
"apiVersion": 3,
"name": "wp-spaceapi-consumer/space-status",
"title": "Space Status",
"description": "Show whether the space is open or closed (SpaceAPI consumer).",
"category": "widgets",
"icon": "building",
"textdomain": "wp-spaceapi-consumer",
"style": "file:./style.css",
"editorStyle": "file:./editor.css",
"editorScript": "file:./index.js",
"supports": { "html": false }
}

View File

@@ -0,0 +1,7 @@
/* Editor-only: make the pill obvious & easy to select */
.wp-block-wp-spaceapi-consumer-space-status {
display: inline-block;
padding: 4px 8px;
border: 1px dashed var(--wp-admin-theme-color, #007cba);
border-radius: 9999px;
}

12
src/space-status/index.js Normal file
View File

@@ -0,0 +1,12 @@
import { __ } from '@wordpress/i18n';
import { registerBlockType } from '@wordpress/blocks';
import ServerSideRender from '@wordpress/server-side-render';
registerBlockType( 'wp-spaceapi-consumer/space-status', {
edit: () => (
<ServerSideRender
block="wp-spaceapi-consumer/space-status"
/>
),
save: () => null, // dynamic block — markup comes from PHP
} );

View File

@@ -0,0 +1 @@
@import url('../../wp-spaceapi-consumer-style.css');

View File

@@ -1,5 +1,5 @@
<?php <?php
define( 'DSI_API_URL', 'https://lcdporto.org/api/spaceapi' ); define( 'SSI_API_URL', 'https://lcdporto.org/api/spaceapi' );
define( 'DSI_CACHE_KEY', 'dsi_space_api_status' ); define( 'SSI_CACHE_KEY', 'ssi_space_api_status' );
define( 'DSI_CACHE_TTL', 10 ); define( 'SSI_CACHE_TTL', 10 );

View File

@@ -1,11 +1,11 @@
/* door-status.css styles the indicator as a pillshaped button */ /* space-status.css - styles the indicator as a pill-shaped button */
.door-status-indicator { .space-status-indicator {
display:inline-flex; display:inline-flex;
align-items:center; align-items:center;
gap:0.4em; gap:0.4em;
padding:0.25em 0.75em; padding:0.25em 0.75em;
border-radius:1em; /* fullyrounded corners */ border-radius:1em; /* fully-rounded corners */
font-size:0.95em; font-size:0.95em;
font-weight:600; font-weight:600;
line-height:1; line-height:1;
@@ -15,20 +15,20 @@
} }
/* Open = soft green background + dark green text */ /* Open = soft green background + dark green text */
.door-status-indicator.open { .space-status-indicator.open {
background:#e7f9ec; background:#e7f9ec;
color:#1e7a34; color:#1e7a34;
} }
/* Closed = soft red background + dark red text */ /* Closed = soft red background + dark red text */
.door-status-indicator.closed { .space-status-indicator.closed {
background:#fdeeee; background:#fdeeee;
color:#c03c3c; color:#c03c3c;
} }
/* (Optional) slight hover effect */ /* (Optional) slight hover effect */
.door-status-indicator:hover, .space-status-indicator:hover,
.door-status-indicator:focus { .space-status-indicator:focus {
filter:brightness(1.05); filter:brightness(1.05);
outline:none; outline:none;
} }

View File

@@ -3,8 +3,8 @@
* Plugin Name: WordPress SpaceAPI Consumer * Plugin Name: WordPress SpaceAPI Consumer
* Plugin Slug: wp-spaceapi-consumer * Plugin Slug: wp-spaceapi-consumer
* Plugin URI: https://gitea.alluna.pt/jfig/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 * Description: WordPress plugin to consume a SpaceAPI endpoint and indicate if the Space is Open or Closed
* Version: 1.1.1 * Version: 0.4.2
* Author: Joao Figueiredo, LCD Porto Team, ChatGPT o3 * Author: Joao Figueiredo, LCD Porto Team, ChatGPT o3
* Author URI: https://lcdporto.org * Author URI: https://lcdporto.org
* License: MIT * License: MIT
@@ -20,9 +20,9 @@ if ( ! defined( 'ABSPATH' ) ) {
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Configuration | Configuration
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Constants are expected in door-status-config.php located in the same | 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 | directory. If that file is missing, sane defaults are used so the plugin
| still works outofthebox. | still works out-of-the-box.
*/ */
$config_file = plugin_dir_path( __FILE__ ) . 'wp-spaceapi-consumer-config.php'; $config_file = plugin_dir_path( __FILE__ ) . 'wp-spaceapi-consumer-config.php';
@@ -31,39 +31,44 @@ if ( file_exists( $config_file ) ) {
} }
// Fallback defaults (only if not already defined by the 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( 'SSI_API_URL' ) && define( 'SSI_API_URL', 'https://lcdporto.org/api/spaceapi' );
! defined( 'DSI_CACHE_KEY' ) && define( 'DSI_CACHE_KEY', 'dsi_space_api_status' ); ! defined( 'SSI_CACHE_KEY' ) && define( 'SSI_CACHE_KEY', 'ssi_space_api_status' );
! defined( 'DSI_CACHE_TTL' ) && define( 'DSI_CACHE_TTL', 10 ); // seconds ! defined( 'SSI_CACHE_TTL' ) && define( 'SSI_CACHE_TTL', 10 ); // seconds
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Core fetch & cache | Core - fetch & cache
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
*/ */
/** /**
* Retrieves dooropen status (boolean) with transient caching. * Retrieves space open status (boolean) with transient caching.
* *
* Supported JSON payloads (any case): * Supported JSON payloads (any case):
* true / false (bare boolean) * - true / false (bare boolean)
* {"open": true} * - {"state": {"open": true}} (SpaceAPI standard)
* {"doorOpen": true}
* *
* @return bool True if open, false if closed (or on error). * @return bool True if open, false if closed (or on error).
*/ */
function dsi_get_status() : bool { function ssi_get_status() : bool {
$cached = get_transient( DSI_CACHE_KEY ); $cached = get_transient( SSI_CACHE_KEY );
if ( false !== $cached ) { if ( false !== $cached ) {
return (bool) $cached; return (bool) $cached;
} }
$response = wp_remote_get( DSI_API_URL, [ // 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, 'timeout' => 3,
'user-agent' => 'DoorStatusIndicator/1.1.1 (+https://wordpress.org/)', 'user-agent' => $plugin_data['TextDomain'] . '/' . $plugin_data['Version'] . ' (+https://wordpress.org/)',
] ); ] );
if ( is_wp_error( $response ) ) { if ( is_wp_error( $response ) ) {
set_transient( DSI_CACHE_KEY, false, DSI_CACHE_TTL ); set_transient( SSI_CACHE_KEY, false, SSI_CACHE_TTL );
return false; return false;
} }
@@ -74,14 +79,13 @@ function dsi_get_status() : bool {
if ( is_bool( $decoded ) ) { if ( is_bool( $decoded ) ) {
$status = $decoded; $status = $decoded;
} elseif ( is_array( $decoded ) ) { } elseif ( is_array( $decoded ) ) {
if ( isset( $decoded['open'] ) ) { // SpaceAPI standard format - state.open
$status = (bool) $decoded['open']; if ( isset( $decoded['state']['open'] ) ) {
} elseif ( isset( $decoded['doorOpen'] ) ) { $status = (bool) $decoded['state']['open'];
$status = (bool) $decoded['doorOpen'];
} }
} }
set_transient( DSI_CACHE_KEY, $status, DSI_CACHE_TTL ); set_transient( SSI_CACHE_KEY, $status, SSI_CACHE_TTL );
return $status; return $status;
} }
@@ -91,17 +95,19 @@ function dsi_get_status() : bool {
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
*/ */
function dsi_shortcode() : string { function ssi_shortcode() : string {
$open = dsi_get_status(); $open = ssi_get_status();
$emoji = $open ? '<div class="door-status-indicator open">🟢 Open</div>' : '<div class="door-status-indicator closed">🔴 Closed</div>'; $emoji = $open ? '<div class="space-status-indicator open">🟢 Open</div>' : '<div class="space-status-indicator closed">🔴 Closed</div>';
return sprintf( return sprintf(
'<span class="door-status-indicator" aria-label="Door is %s">%s</span>', '<span class="space-status-indicator" aria-label="Space is %s">%s</span>',
$open ? 'open' : 'closed', $open ? 'open' : 'closed',
$emoji $emoji
); );
} }
add_shortcode( 'door_status', 'dsi_shortcode' ); add_shortcode( 'space_status', 'ssi_shortcode' );
// Keep the old shortcode for backward compatibility
add_shortcode( 'door_status', 'ssi_shortcode' );
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@@ -109,56 +115,62 @@ add_shortcode( 'door_status', 'dsi_shortcode' );
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
*/ */
function dsi_admin_bar( WP_Admin_Bar $bar ) : void { function ssi_admin_bar( WP_Admin_Bar $bar ) : void {
if ( ! current_user_can( 'read' ) ) { if ( ! current_user_can( 'read' ) ) {
return; // Loggedin users only. return; // Logged-in users only.
} }
$open = dsi_get_status(); $open = ssi_get_status();
$emoji = $open ? '🟢' : '🔴'; $emoji = $open ? '🟢' : '🔴';
$text = $open ? __( 'Door Open', 'door-status-indicator' ) : __( 'Door Closed', 'door-status-indicator' ); $text = $open ? __( 'Space Open', 'wp-spaceapi-consumer' ) : __( 'Space Closed', 'wp-spaceapi-consumer' );
$bar->add_node( [ $bar->add_node( [
'id' => 'door-status-indicator', 'id' => 'space-status-indicator',
'title' => "$emoji $text", 'title' => "$emoji $text",
'href' => '#', 'href' => '#',
'meta' => [ 'title' => $text ], 'meta' => [ 'title' => $text ],
] ); ] );
} }
add_action( 'admin_bar_menu', 'dsi_admin_bar', 1000 ); add_action( 'admin_bar_menu', 'ssi_admin_bar', 1000 );
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Frontend inline CSS (kept minimal) | Front-end inline CSS (kept minimal)
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
*/ */
/** /**
* Front-end + admin-bar styles for the indicator. * Front-end + admin-bar styles for the indicator.
*/ */
function dsi_enqueue_assets() : void { function ssi_enqueue_assets() : void {
// register & enqueue the standalone CSS file // register & enqueue the standalone CSS file
wp_enqueue_style( wp_enqueue_style(
'door-status-indicator', 'space-status-indicator',
plugins_url( 'wp-spaceapi-consumer-style.css', __FILE__ ), plugins_url( 'wp-spaceapi-consumer-style.css', __FILE__ ),
[], // no dependencies [], // no dependencies
'1.0.0' // file version '1.0.0' // file version
); );
} }
add_action( 'wp_enqueue_scripts', 'dsi_enqueue_assets' ); add_action( 'wp_enqueue_scripts', 'ssi_enqueue_assets' );
add_action( 'admin_enqueue_scripts', 'dsi_enqueue_assets' ); // so the Admin Bar icon also gets styled add_action( 'admin_enqueue_scripts', 'ssi_enqueue_assets' ); // so the Admin Bar icon also gets styled
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| WPCLI command (optional) | WP-CLI command (optional)
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
*/ */
if ( defined( 'WP_CLI' ) && WP_CLI ) { if ( defined( 'WP_CLI' ) && WP_CLI ) {
WP_CLI::add_command( 'door-status', function() { WP_CLI::add_command( 'space-status', function() {
WP_CLI::success( dsi_get_status() ? 'Door is open 🟢' : 'Door is closed 🔴' ); 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 // End of file