Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ item (Added, Changed, Depreciated, Removed, Fixed, Security).
- Fixed: Vertical Tabs block now scrolls the selected tab into view on mobile, respecting reduced motion preferences. [MOOSE-333](https://moderntribe.atlassian.net/browse/MOOSE-333)
- Fixed: Removed top margin from spacer block
- Added: Yoast Duplicate Post plugin v4.5 for easier content duplication in the editor.
- Updated: Dynamic blocks now pass data to PHP controller classes for processing, moving toward a more OOP/MVC approach.
- Updated: Login logo styling

## [2025.12]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php declare(strict_types=1);

namespace Tribe\Plugin\Components\Abstracts;

use Tribe\Plugin\Blocks\Helpers\Block_Animation_Attributes;

abstract class Abstract_Block_Controller extends Abstract_Controller {

/**
* @var array <mixed>
*/
protected array $attributes;
protected string $block_classes;
protected string $block_styles;
private Block_Animation_Attributes|false $block_animation_attributes;
private string $block_animation_classes;
private string $block_animation_styles;

public function __construct( array $args = [] ) {
$this->attributes = $args['attributes'] ?? [];
$this->block_classes = $args['block_classes'] ?? '';
$this->block_styles = $args['block_styles'] ?? '';
$this->block_animation_attributes = $this->attributes ? new Block_Animation_Attributes( $this->attributes ) : false;
$this->block_animation_classes = $this->block_animation_attributes ? $this->block_animation_attributes->get_classes() : '';
$this->block_animation_styles = $this->block_animation_attributes ? $this->block_animation_attributes->get_styles() : '';
}

public function get_block_classes(): string {
$classes = $this->block_classes;

if ( '' !== $this->block_animation_classes ) {
$classes .= ' ' . $this->block_animation_classes;
}

return $classes;
}

public function get_block_styles(): string {
$styles = $this->block_styles;

if ( '' !== $this->block_animation_styles ) {
$styles .= ' ' . $this->block_animation_styles;
}

return $styles;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php declare(strict_types=1);

namespace Tribe\Plugin\Components\Abstracts;

abstract class Abstract_Card_Controller extends Abstract_Block_Controller {

private int $media_id;
private string $media_url;
private string $title;
private string $description;
private string $link_url;
private bool $link_opens_in_new_tab;
private string $link_text;
private string $link_a11y_label;

public function __construct( array $args = [] ) {
parent::__construct( $args );

$this->media_id = isset( $this->attributes['mediaId'] ) ? (int) $this->attributes['mediaId'] : 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$this->media_id = isset( $this->attributes['mediaId'] ) ? (int) $this->attributes['mediaId'] : 0;
$this->media_id = absint( $this->attributes['mediaId'] ?? 0 );

$this->media_url = $this->attributes['mediaUrl'] ?? '';
$this->title = $this->attributes['title'] ?? '';
$this->description = $this->attributes['description'] ?? '';
$this->link_url = $this->attributes['linkUrl'] ?? '';
$this->link_opens_in_new_tab = $this->attributes['linkOpensInNewTab'] ?? false;
$this->link_text = $this->attributes['linkText'] ?? '';
$this->link_a11y_label = $this->attributes['linkA11yLabel'] ?? '';
}

public function has_media(): bool {
return 0 !== $this->media_id || '' !== $this->media_url;
}

public function get_media( string $image_size = 'large' ): string {
if ( 0 !== $this->media_id ) {
return wp_get_attachment_image( $this->media_id, $image_size );
}

if ( '' !== $this->media_url ) {
return '<img src="' . esc_url( $this->media_url ) . '" alt="' . esc_attr__( 'Block placeholder image', 'tribe' ) . '">';
}

return '';
}

public function get_title(): string {
return $this->title;
}

public function has_description(): bool {
return '' !== $this->description;
}

public function get_description(): string {
return $this->description;
}

public function has_link_url(): bool {
return '' !== $this->link_url;
}

public function get_link_url(): string {
return $this->link_url;
}

public function does_link_open_in_new_tab(): bool {
return $this->link_opens_in_new_tab;
}

public function get_link_text(): string {
return $this->link_text;
}

public function get_link_a11y_label(): string {
return $this->link_a11y_label;
}

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<?php declare(strict_types=1);

namespace Tribe\Plugin\Components;
namespace Tribe\Plugin\Components\Abstracts;

/**
* Base class for other controllers to extend.
*/
abstract class Abstract_Controller {

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php declare(strict_types=1);

namespace Tribe\Plugin\Components\Blocks;

use Tribe\Plugin\Blocks\Helpers\Icon_Picker;
use Tribe\Plugin\Components\Abstracts\Abstract_Card_Controller;

class Icon_Card_Controller extends Abstract_Card_Controller {

private Icon_Picker $icon_picker;
private string $icon_wrapper_styles;
private string $icon_svg;
Comment on lines +10 to +12
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think properties on controllers should be private, in the event that another class wants to extend these classes. Recommend protected. 🤔


public function __construct( array $args = [] ) {
parent::__construct( $args );

$this->icon_picker = new Icon_Picker( $this->attributes );
$this->icon_wrapper_styles = $this->icon_picker->get_icon_wrapper_styles();
$this->icon_svg = $this->icon_picker->get_svg();
}

public function get_icon_wrapper_styles(): string {
return $this->icon_wrapper_styles;
}

public function has_icon(): bool {
return ! empty( $this->icon_svg );
}

public function get_icon_svg(): string {
return $this->icon_svg;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php declare(strict_types=1);

namespace Tribe\Plugin\Components\Blocks;

use Tribe\Plugin\Components\Abstracts\Abstract_Card_Controller;

class Image_Card_Controller extends Abstract_Card_Controller {

public function __construct( array $args = [] ) {
parent::__construct( $args );
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php declare(strict_types=1);

namespace Tribe\Plugin\Components\Blocks;

use Tribe\Plugin\Components\Abstracts\Abstract_Card_Controller;

class Image_Overlay_Card_Controller extends Abstract_Card_Controller {

private string $overlay_color;
private string $overlay_hover_color;
private bool $card_uses_dark_theme;

public function __construct( array $args = [] ) {
parent::__construct( $args );

$this->overlay_color = $this->attributes['overlayColor'] ?? '#0000001C';
$this->overlay_hover_color = $this->attributes['overlayHoverColor'] ?? '#00000033';
$this->card_uses_dark_theme = $this->attributes['cardUsesDarkTheme'] ?? false;
$this->block_styles .= sprintf(
'--card-image-overlay-color: %s;--card-image-overlay-hover-color: %s;',
$this->overlay_color,
$this->overlay_hover_color
);

if ( ! $this->card_uses_dark_theme ) {
return;
}

$this->block_classes .= ' b-image-overlay-card--dark-theme';
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php declare(strict_types=1);

namespace Tribe\Plugin\Components\Blocks;

use Tribe\Plugin\Components\Abstracts\Abstract_Block_Controller;

class Masthead_Search_Controller extends Abstract_Block_Controller {

private string|false $search_icon;
private string $search_icon_uri;
private string $search_icon_path;

public function __construct( array $args = [] ) {
parent::__construct( $args );

$this->search_icon = '';
$this->search_icon_uri = trailingslashit( get_stylesheet_directory_uri() ) . '/assets/media/icons/search.svg';
$this->search_icon_path = trailingslashit( get_stylesheet_directory() ) . '/assets/media/icons/search.svg';
}

public function get_search_icon(): string {
// If the file doesn't exist or we have already loaded it, return early
if ( ! file_exists( $this->search_icon_path ) || $this->search_icon !== '' ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Micro-optimization:

Suggested change
if ( ! file_exists( $this->search_icon_path ) || $this->search_icon !== '' ) {
if ( '' !== $this->search_icon || ! file_exists( $this->search_icon_path ) ) {

return $this->search_icon;
}

// Attempt to get the file contents from the file system
$this->search_icon = file_get_contents( $this->search_icon_path );

// Fallback to wp_remote_get if file_get_contents fails
if ( $this->search_icon === false ) {
$response = wp_remote_get( $this->search_icon_uri );

if ( ! is_wp_error( $response ) ) {
// wp_remote_retrieve_body returns an empty string on failure, so it's fine to end here
$this->search_icon = wp_remote_retrieve_body( $response );
}
}

return $this->search_icon;
}

public function get_toggle_button_a11y_label(): string {
return __( 'Toggle Search Overlay', 'tribe' );
}

public function get_form_action(): string {
return home_url();
}

public function get_label_text(): string {
return __( 'Search', 'tribe' );
}

public function get_input_placeholder(): string {
return __( 'What are you looking for?', 'tribe' );
}

public function get_submit_button_text(): string {
return __( 'Search', 'tribe' );
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php declare(strict_types=1);

namespace Tribe\Plugin\Components\Blocks;

use Tribe\Plugin\Components\Abstracts\Abstract_Block_Controller;
use Tribe\Plugin\Components\Traits\Post_Data;

class Post_Card_Controller extends Abstract_Block_Controller {

use Post_Data;

private string $layout;
private string $heading_level;

public function __construct( array $args = [] ) {
parent::__construct( $args );
$this->set_post( $args['post_id'] ?? 0 );

$this->layout = $this->attributes['layout'] ?? 'vertical';
$this->heading_level = $this->attributes['heading_level'] ?? 'h3';
$this->block_classes .= " c-post-card--layout-{$this->layout}";
}

public function get_heading_level(): string {
return $this->heading_level;
}

}
Loading