feat: prima versione del plugin, blocco e shortcode con iframe stampato lato server
This commit is contained in:
commit
5c73bbc2b8
20 changed files with 1562 additions and 0 deletions
52
includes/block.php
Normal file
52
includes/block.php
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
/**
|
||||
* The editor block. Dynamic: the markup is produced by PHP at render time, so
|
||||
* the events are always the ones of today and never a copy frozen in the post
|
||||
* content.
|
||||
*
|
||||
* @package PiazzaInFesta
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Registers the block from its block.json.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function pinfesta_register_block() {
|
||||
$type = register_block_type(
|
||||
PINFESTA_DIR . 'blocks/eventi',
|
||||
array( 'render_callback' => 'pinfesta_render_block' )
|
||||
);
|
||||
|
||||
// The editor strings live in JavaScript, so they need their own JSON
|
||||
// catalogue. The handle is read back from the registered block instead of
|
||||
// being guessed: WordPress builds it from block.json and it can change.
|
||||
if ( $type && ! empty( $type->editor_script_handles ) ) {
|
||||
foreach ( $type->editor_script_handles as $handle ) {
|
||||
wp_set_script_translations( $handle, 'piazza-in-festa', PINFESTA_DIR . 'languages' );
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action( 'init', 'pinfesta_register_block' );
|
||||
|
||||
/**
|
||||
* Renders the block on the front end and in the editor preview.
|
||||
*
|
||||
* @param array $attributes Block attributes.
|
||||
* @return string HTML.
|
||||
*/
|
||||
function pinfesta_render_block( $attributes ) {
|
||||
$args = wp_parse_args( (array) $attributes, pinfesta_defaults() );
|
||||
|
||||
$html = pinfesta_render_iframe( $args );
|
||||
|
||||
if ( '' === $html ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$wrapper = get_block_wrapper_attributes();
|
||||
|
||||
return '<div' . ( '' === $wrapper ? '' : ' ' . $wrapper ) . '>' . $html . '</div>';
|
||||
}
|
||||
172
includes/render.php
Normal file
172
includes/render.php
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
<?php
|
||||
/**
|
||||
* Builds the widget URL and renders the iframe. Shared by the shortcode and
|
||||
* the block: both end up here, so there is a single place where parameters are
|
||||
* sanitised and a single place where markup is produced.
|
||||
*
|
||||
* @package PiazzaInFesta
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Default values for every supported parameter.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
function pinfesta_defaults() {
|
||||
return array(
|
||||
'comuni' => '',
|
||||
'regione' => '',
|
||||
'categoria' => '',
|
||||
'limite' => '5',
|
||||
'tema' => 'chiaro',
|
||||
'colore' => '',
|
||||
'titolo' => '',
|
||||
'altezza' => '320',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Categories accepted by the service. Anything else is dropped instead of
|
||||
* being forwarded, so a typo shows every event rather than none.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
function pinfesta_categorie() {
|
||||
return array(
|
||||
'religioso',
|
||||
'sagra_enogastronomica',
|
||||
'musica_concerto',
|
||||
'culturale_mostra',
|
||||
'incontro_conferenza',
|
||||
'fiera_mercato',
|
||||
'mercatini',
|
||||
'sportivo',
|
||||
'natura_escursione',
|
||||
'spettacolo',
|
||||
'teatro',
|
||||
'cinema',
|
||||
'bambini_famiglie',
|
||||
'istituzionale',
|
||||
'altro',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans a comma separated list of town identifiers (the slug you see in the
|
||||
* address of a town page, for instance "la-morra"). Twelve at most, which is
|
||||
* what the service accepts.
|
||||
*
|
||||
* @param string $raw Raw attribute value.
|
||||
* @return string Normalised list, empty when nothing survives.
|
||||
*/
|
||||
function pinfesta_clean_comuni( $raw ) {
|
||||
$out = array();
|
||||
|
||||
foreach ( explode( ',', (string) $raw ) as $item ) {
|
||||
$slug = sanitize_title( trim( $item ) );
|
||||
|
||||
if ( '' !== $slug ) {
|
||||
$out[] = $slug;
|
||||
}
|
||||
}
|
||||
|
||||
return implode( ',', array_slice( array_unique( $out ), 0, 12 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the parameters into the URL of the widget page on the service.
|
||||
*
|
||||
* @param array $args Parameters, already merged with the defaults.
|
||||
* @return string
|
||||
*/
|
||||
function pinfesta_build_url( $args ) {
|
||||
$query = array();
|
||||
|
||||
$comuni = pinfesta_clean_comuni( $args['comuni'] );
|
||||
|
||||
if ( '' !== $comuni ) {
|
||||
$query['comune'] = $comuni;
|
||||
} elseif ( '' !== $args['regione'] ) {
|
||||
$query['regione'] = sanitize_text_field( $args['regione'] );
|
||||
}
|
||||
|
||||
if ( in_array( $args['categoria'], pinfesta_categorie(), true ) ) {
|
||||
$query['categoria'] = $args['categoria'];
|
||||
}
|
||||
|
||||
$limite = absint( $args['limite'] );
|
||||
|
||||
if ( $limite > 0 ) {
|
||||
$query['limite'] = min( $limite, 20 );
|
||||
}
|
||||
|
||||
if ( 'scuro' === $args['tema'] ) {
|
||||
$query['tema'] = 'scuro';
|
||||
}
|
||||
|
||||
$colore = sanitize_hex_color( $args['colore'] );
|
||||
|
||||
if ( $colore ) {
|
||||
// Without the hash: add_query_arg() leaves "#" as it is, and a bare "#"
|
||||
// in a URL opens the fragment, which would swallow this parameter and
|
||||
// every parameter after it. The service accepts the six digits alone.
|
||||
$query['accent'] = ltrim( $colore, '#' );
|
||||
}
|
||||
|
||||
$titolo = sanitize_text_field( $args['titolo'] );
|
||||
|
||||
if ( '' !== $titolo ) {
|
||||
$query['titolo'] = $titolo;
|
||||
}
|
||||
|
||||
// Service key: optional. It only tells the service that this site may ask
|
||||
// for the version without the Piazza in Festa credit line; every feature of
|
||||
// this plugin works exactly the same with or without it.
|
||||
$chiave = pinfesta_get_option( 'chiave' );
|
||||
|
||||
if ( '' !== $chiave ) {
|
||||
$query['chiave'] = $chiave;
|
||||
$query['marchio'] = '0';
|
||||
}
|
||||
|
||||
return add_query_arg( $query, pinfesta_base_url() . '/embed' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the widget.
|
||||
*
|
||||
* An iframe, on purpose: the CSS of the host site cannot break the widget and
|
||||
* the widget cannot break the host site. The height arrives from the framed
|
||||
* page via postMessage (assets/js/resize.js), so nobody has to guess it; the
|
||||
* `altezza` parameter is only the starting height, and what visitors see when
|
||||
* JavaScript is off.
|
||||
*
|
||||
* @param array $args Parameters, already merged with the defaults.
|
||||
* @return string HTML.
|
||||
*/
|
||||
function pinfesta_render_iframe( $args ) {
|
||||
$args = wp_parse_args( $args, pinfesta_defaults() );
|
||||
|
||||
if ( '' === pinfesta_clean_comuni( $args['comuni'] ) && '' === trim( (string) $args['regione'] ) ) {
|
||||
if ( ! current_user_can( 'edit_posts' ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return '<p class="pinfesta-empty">' . esc_html__( 'Piazza in Festa: set at least one town or a region.', 'piazza-in-festa' ) . '</p>';
|
||||
}
|
||||
|
||||
wp_enqueue_style( 'pinfesta-widget' );
|
||||
wp_enqueue_script( 'pinfesta-resize' );
|
||||
|
||||
$altezza = absint( $args['altezza'] );
|
||||
$altezza = ( $altezza >= 120 && $altezza <= 4000 ) ? $altezza : 320;
|
||||
|
||||
return sprintf(
|
||||
'<iframe class="pinfesta-embed" src="%1$s" title="%2$s" height="%3$d" loading="lazy" scrolling="no" referrerpolicy="no-referrer-when-downgrade"></iframe>',
|
||||
esc_url( pinfesta_build_url( $args ) ),
|
||||
esc_attr__( 'Upcoming local events', 'piazza-in-festa' ),
|
||||
$altezza
|
||||
);
|
||||
}
|
||||
148
includes/settings.php
Normal file
148
includes/settings.php
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
/**
|
||||
* Settings screen (Settings > Piazza in Festa).
|
||||
*
|
||||
* One field only: the optional service key. The plugin does everything it can
|
||||
* do without it; the key just lets the service serve the widget without the
|
||||
* small Piazza in Festa credit line at the bottom.
|
||||
*
|
||||
* @package PiazzaInFesta
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Reads one saved option.
|
||||
*
|
||||
* @param string $key Option key.
|
||||
* @return string Empty string when unset.
|
||||
*/
|
||||
function pinfesta_get_option( $key ) {
|
||||
$options = get_option( 'pinfesta_options', array() );
|
||||
|
||||
if ( ! is_array( $options ) || ! isset( $options[ $key ] ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (string) $options[ $key ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the setting and its field.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function pinfesta_register_settings() {
|
||||
register_setting(
|
||||
'pinfesta_settings',
|
||||
'pinfesta_options',
|
||||
array(
|
||||
'type' => 'array',
|
||||
'sanitize_callback' => 'pinfesta_sanitize_options',
|
||||
'default' => array(),
|
||||
)
|
||||
);
|
||||
|
||||
add_settings_section(
|
||||
'pinfesta_section',
|
||||
'',
|
||||
'__return_false',
|
||||
'piazza-in-festa'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'pinfesta_chiave',
|
||||
esc_html__( 'Service key', 'piazza-in-festa' ),
|
||||
'pinfesta_field_chiave',
|
||||
'piazza-in-festa',
|
||||
'pinfesta_section'
|
||||
);
|
||||
}
|
||||
add_action( 'admin_init', 'pinfesta_register_settings' );
|
||||
|
||||
/**
|
||||
* Sanitises the saved options.
|
||||
*
|
||||
* @param mixed $input Raw value coming from the form.
|
||||
* @return array
|
||||
*/
|
||||
function pinfesta_sanitize_options( $input ) {
|
||||
$out = array();
|
||||
|
||||
if ( is_array( $input ) && isset( $input['chiave'] ) ) {
|
||||
// Keys are hexadecimal strings; anything else is not a key.
|
||||
$chiave = preg_replace( '/[^a-zA-Z0-9]/', '', (string) $input['chiave'] );
|
||||
|
||||
$out['chiave'] = substr( (string) $chiave, 0, 128 );
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the key field.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function pinfesta_field_chiave() {
|
||||
printf(
|
||||
'<input type="text" class="regular-text" name="pinfesta_options[chiave]" value="%s" autocomplete="off" />',
|
||||
esc_attr( pinfesta_get_option( 'chiave' ) )
|
||||
);
|
||||
|
||||
echo '<p class="description">' . esc_html__( 'Optional. Leave it empty and the widget works anyway, with a small credit line at the bottom.', 'piazza-in-festa' ) . '</p>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the menu entry.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function pinfesta_admin_menu() {
|
||||
add_options_page(
|
||||
esc_html__( 'Piazza in Festa', 'piazza-in-festa' ),
|
||||
esc_html__( 'Piazza in Festa', 'piazza-in-festa' ),
|
||||
'manage_options',
|
||||
'piazza-in-festa',
|
||||
'pinfesta_settings_page'
|
||||
);
|
||||
}
|
||||
add_action( 'admin_menu', 'pinfesta_admin_menu' );
|
||||
|
||||
/**
|
||||
* Prints the settings page.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function pinfesta_settings_page() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php echo esc_html__( 'Piazza in Festa', 'piazza-in-festa' ); ?></h1>
|
||||
|
||||
<p>
|
||||
<?php echo esc_html__( 'Add the events with the block called Piazza in Festa, or with this shortcode:', 'piazza-in-festa' ); ?>
|
||||
<code>[piazza-in-festa comuni="alba,barolo,la-morra" limite="5"]</code>
|
||||
</p>
|
||||
<p>
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: link to the online configurator. */
|
||||
esc_html__( 'Not sure about the identifiers of your towns? Build the widget here and copy the values: %s', 'piazza-in-festa' ),
|
||||
'<a href="' . esc_url( pinfesta_base_url() . '/widget' ) . '" target="_blank" rel="noopener noreferrer">' . esc_html( pinfesta_base_url() . '/widget' ) . '</a>'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
|
||||
<form action="options.php" method="post">
|
||||
<?php
|
||||
settings_fields( 'pinfesta_settings' );
|
||||
do_settings_sections( 'piazza-in-festa' );
|
||||
submit_button();
|
||||
?>
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
28
includes/shortcode.php
Normal file
28
includes/shortcode.php
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
/**
|
||||
* The [piazza-in-festa] shortcode.
|
||||
*
|
||||
* Attribute names are Italian because the data is Italian: they match the town
|
||||
* identifiers and the parameters documented on piazzainfesta.it, so what you
|
||||
* read there is what you write here.
|
||||
*
|
||||
* [piazza-in-festa comuni="alba,barolo,la-morra" limite="5"]
|
||||
* [piazza-in-festa regione="Piemonte" categoria="sagra_enogastronomica"]
|
||||
*
|
||||
* @package PiazzaInFesta
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Renders the shortcode.
|
||||
*
|
||||
* @param array|string $atts Shortcode attributes.
|
||||
* @return string HTML.
|
||||
*/
|
||||
function pinfesta_shortcode( $atts ) {
|
||||
$args = shortcode_atts( pinfesta_defaults(), $atts, 'piazza-in-festa' );
|
||||
|
||||
return pinfesta_render_iframe( $args );
|
||||
}
|
||||
add_shortcode( 'piazza-in-festa', 'pinfesta_shortcode' );
|
||||
Loading…
Add table
Add a link
Reference in a new issue