Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add link capability to Cover block #428

Merged
merged 4 commits into from
Oct 29, 2024
Merged

Conversation

ZaredRogers
Copy link
Contributor

@ZaredRogers ZaredRogers commented Oct 28, 2024

Description

This pull request adds link functionality to the core Cover block in our WordPress plugin. Users can now make the entire Cover block clickable by specifying a link URL and choosing whether it opens in the same tab or a new tab. This enhancement provides greater flexibility for creating interactive content without affecting existing functionalities.

Changes Made

1. Modified init.php

  • Location: src/init.php
  • Changes:
    • Enqueued a new script linked-cover.js

2. Created linked-cover.js

  • Location: assets/js/blocks/linked-cover.js
  • Purpose: Adds link capabilities to the core Cover block.
  • Functionality:
    • Adds new attributes linkUrl and linkTarget to the Cover block.
    • Extends the block's edit component to include link settings in the inspector controls.
    • Modifies the save function to wrap the Cover block's content in an <a> tag if a link URL is provided.

Testing

  • Inserted a core Cover block and verified that the new "Cover Link Settings" panel appears in the block's inspector controls.
  • Set a link URL and target, and confirmed that the entire Cover block becomes clickable.
  • Previewed on the frontend to ensure the Cover block is wrapped in an <a> tag with the correct href and target attributes.
  • Confirmed that other blocks and functionalities remain unaffected.

Conclusion

This enhancement allows users to add link functionality to the core Cover block, providing more interactive options without altering existing code or block variations.


Please review the changes and merge if approved.

Closes #422

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a search functionality for the app.
    • Added link attributes and controls for the WordPress cover block.
    • Implemented toggle controls for managing post metadata, including "Featured" and "Disable Single" statuses.
    • Added new block variations for itinerary, accommodation units, gallery, and pricing in the WordPress block editor.
    • Enhanced the settings management system with new options and improved organization.
  • Bug Fixes

    • Resolved issues with image selection and tab navigation logic.
    • Improved handling of "Read More" functionality for multiple languages.
  • Documentation

    • Updated the changelog to reflect significant changes and version updates.
  • Refactor

    • Simplified the admin class and settings management structure.
    • Streamlined the layout and styling of various components for better maintainability.
  • Chores

    • Increased the minimum required WordPress version to 6.1.
    • Removed deprecated files and classes to enhance performance and clarity.

@ZaredRogers ZaredRogers added the [Component] Block Variations Block development issues or pulls. label Oct 28, 2024
@ZaredRogers ZaredRogers added this to the 2.0.0 milestone Oct 28, 2024
@ZaredRogers ZaredRogers self-assigned this Oct 28, 2024
Copy link

coderabbitai bot commented Oct 28, 2024

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The pull request introduces multiple changes across various files, focusing on enhancing the WordPress plugin's functionality. Key modifications include adding a clickable Cover block variation, updating styles and settings in SCSS files, refining JavaScript functionalities for managing post metadata, and restructuring settings management. Several deprecated files and classes have been removed, while new classes and configurations have been introduced to streamline the plugin's architecture. Additionally, updates to the .gitignore and changelog reflect ongoing maintenance and improvements.

Changes

File Change Summary
.gitignore Added entries for .DS_Store files and vendor directories.
.mergify.yml Removed rule for deleting head branch after PR merge.
assets/css/scss/admin.scss Modified styles for body class and removed .uix-field-wrapper; added new .form-field class.
assets/js/blocks/linked-cover.js Introduced functionality for clickable Cover block with link attributes.
assets/js/blocks/slotfills.js Added components for managing post metadata with toggle controls.
assets/js/blocks/variations.js Registered new block variations for 'core/group' and 'core/gallery' blocks.
assets/js/src/admin.js Updated image selection and tab navigation logic.
assets/js/src/custom.js Expanded "more link" functionality to support multiple languages.
changelog.md Updated to reflect version 2.0.0 and changes in settings management.
includes/classes/admin/class-admin.php Removed several methods related to admin page management.
includes/classes/admin/class-settings.php Restructured settings management methods and added new ones.
includes/classes/admin/class-setup.php Introduced new class for managing custom fields and post types.
includes/classes/blocks/class-bindings.php Added class for registering custom fields and handling block types.
includes/classes/blocks/class-patterns.php Introduced class for managing block patterns.
includes/classes/blocks/class-templates.php Added class for registering block templates.
includes/classes/blocks/class-variations.php Introduced class for managing block variations.
includes/template-tags/general.php Removed function for Envira video output.
includes/template-tags/helpers.php Removed function for displaying connected tours; updated custom field query function.
includes/taxonomies/config-accommodation-brand.php Added description and REST API support for accommodation brand taxonomy.
includes/taxonomies/config-accommodation-type.php Added description and REST API support for accommodation type taxonomy.
includes/taxonomies/config-continent.php Added description and REST API support for continent taxonomy.
includes/taxonomies/config-facility.php Added description and REST API support for facility taxonomy.
includes/taxonomies/config-travel-style.php Added description for travel styles taxonomy.
readme.txt Updated minimum WordPress version and stable tag.
src/init.php Added function for enqueuing block assets and updated block registration.
templates/archive-accommodation.html Introduced new HTML template for accommodation archive page.
templates/archive-tour.html Introduced new HTML template for tour archive page.
Various legacy files Multiple legacy files related to post types, taxonomies, and settings have been deleted.

Assessment against linked issues

Objective Addressed Explanation
Develop a block variation of the Cover block that supports assigning a link to the entire block. (#422)
Ensure the block variation allows users to add links via the block settings in the editor. (#422)
Test the block in various scenarios to ensure full functionality on both desktop and mobile devices. (#422) Testing details are not provided in the PR.
Implement a fallback mechanism to ensure proper behaviour if the block variation is not supported in specific contexts. (#422) No mention of fallback mechanisms in the provided changes.
Update relevant documentation and examples to showcase the clickable Cover block variation. (#422) Documentation updates are not included in the PR.

Poem

🐇 In the garden where changes bloom,
A Cover block now finds its room.
Clickable links for all to see,
A hop, a jump, so user-friendly!
With styles anew and functions bright,
The plugin shines, a true delight! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

}

public function register_block_bindings() {
if ( ! function_exists( 'register_block_bindings_source' ) ) {
Copy link

Choose a reason for hiding this comment

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

Expected 0 spaces after opening bracket; 1 found.

Suggested change
if ( ! function_exists( 'register_block_bindings_source' ) ) {
if (! function_exists( 'register_block_bindings_source' )) {

if ( is_array( $value ) && ! empty( $value ) ) {
$values = array();
foreach( $value as $pid ) {
if ( true === $only_parents ) {
Copy link

Choose a reason for hiding this comment

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

Expected 0 spaces after opening bracket; 1 found.

Suggested change
if ( true === $only_parents ) {
if (true === $only_parents) {

*
* @param array $source_args Arguments provided by the source.
* @param object $block_instance Instance of the block currently being processed.
*
Copy link

Choose a reason for hiding this comment

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

Whitespace found at end of line.

Suggested change
*
*

// Determine if this is the custom block variation.
if ( ! isset( $parsed_block['blockName'] ) || ! isset( $parsed_block['attrs'] ) ) {
return $block_content;
}
Copy link

Choose a reason for hiding this comment

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

No blank line found after control structure.

Suggested change
}

return $block_content;
}

if ( ! isset( $parsed_block['attrs']['metadata']['bindings']['content']['source'] ) ) {
Copy link

Choose a reason for hiding this comment

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

Expected 0 spaces after opening bracket; 1 found.

Suggested change
if ( ! isset( $parsed_block['attrs']['metadata']['bindings']['content']['source'] ) ) {
if (! isset( $parsed_block['attrs']['metadata']['bindings']['content']['source'] )) {

lsx_to_accommodation_room_loop_item();

$build = $pattern;
foreach ( $this->unit_fields as $field ) {
Copy link

Choose a reason for hiding this comment

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

Expected 0 spaces after opening bracket; 1 found.

Suggested change
foreach ( $this->unit_fields as $field ) {
foreach ($this->unit_fields as $field) {

case 'type':
// Regular expression to match any paragraph tag with class "unit-type"
$pattern = '/(<p\s+[^>]*\bclass="[^"]*\bunit-type\b[^"]*"[^>]*>).*?(<\/p>)/is';

Copy link

Choose a reason for hiding this comment

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

Tabs must be used to indent lines; spaces are not allowed.

Suggested change

* @return string Returns an empty string if the block is of type 'core/group', otherwise no return value.
*/
public function gallery_callback( $source_args, $block_instance ) {
if ( 'core/group' === $block_instance->parsed_block['blockName'] ) {
Copy link

Choose a reason for hiding this comment

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

Expected 0 spaces before closing bracket; 1 found.

Suggested change
if ( 'core/group' === $block_instance->parsed_block['blockName'] ) {
if ('core/group' === $block_instance->parsed_block['blockName']) {

@@ -385,9 +366,9 @@
$this->map_post_types = array( 'accommodation', 'activity', 'destination' );
$this->markers = new \stdClass();

if ( ( false !== $this->options && isset( $this->options['api']['googlemaps_key'] ) ) || defined( 'GOOGLEMAPS_API_KEY' ) ) {
if ( ( false !== $this->options && isset( $this->options['googlemaps_key'] ) ) || defined( 'GOOGLEMAPS_API_KEY' ) ) {
Copy link

Choose a reason for hiding this comment

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

Expected 0 spaces before closing bracket; 1 found.

Suggested change
if ( ( false !== $this->options && isset( $this->options['googlemaps_key'] ) ) || defined( 'GOOGLEMAPS_API_KEY' ) ) {
if (( false !== $this->options && isset( $this->options['googlemaps_key'] ) ) || defined( 'GOOGLEMAPS_API_KEY' )) {

if ( ! self::compatible_theme() ) {
if ( is_plugin_active( plugin_basename( LSX_TO_CORE ) ) ) {
if ( empty( get_option( 'lsx-to-theme-notice-dismissed' ) ) ) {
add_action( 'admin_notices', array( $this, 'compatible_theme_notice' ), 199 );
Copy link

Choose a reason for hiding this comment

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

No space found before comment text; expected "// add_action( 'admin_notices', array( $this, 'compatible_theme_notice' ), 199 );" but found "//add_action( 'admin_notices', array( $this, 'compatible_theme_notice' ), 199 );".

Suggested change
add_action( 'admin_notices', array( $this, 'compatible_theme_notice' ), 199 );
// add_action( 'admin_notices', array( $this, 'compatible_theme_notice' ), 199 );

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

🛑 Comments failed to post (131)
.gitignore (1)

7-14: ⚠️ Potential issue

Simplify and optimize .gitignore entries

Strewth! There are several duplicate entries for .DS_Store files. We can make this more efficient by using a single global pattern.

Here's how to optimize the entries:

-vendor/cmb-field-select2/.DS_Store
-vendor/cmb2-field-map/.DS_Store
-vendor/.DS_Store
-.DS_Store
-vendor/.DS_Store
-.DS_Store
-.DS_Store
-vendor/.DS_Store
+**/.DS_Store

This single pattern will match all .DS_Store files in any directory, including the vendor directory and its subdirectories.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

**/.DS_Store
.mergify.yml (1)

19-19: 🧹 Nitpick (assertive)

Looks good, but mind the formatting.

The explicit merge method specification for ImgBot is proper, but please add a newline at the end of the file.

   merge:
-        method: merge
+        method: merge
+
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        method: merge

🧰 Tools
🪛 yamllint

[error] 19-19: no new line character at the end of file

(new-line-at-end-of-file)

includes/partials/settings.php (4)

2-4: ⚠️ Potential issue

Add error handling for tour_operator() function call

The code assumes the tour_operator() function exists and returns a valid object. Consider adding proper error handling to gracefully handle cases where the function might not be available.

Apply this diff to add error handling:

 <?php
+if ( ! function_exists( 'tour_operator' ) ) {
+    wp_die( esc_html__( 'LSX Tour Operator plugin is required but not active.', 'tour-operator' ) );
+}
 $settings_pages = tour_operator()->legacy->get_post_types();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

<?php
if ( ! function_exists( 'tour_operator' ) ) {
    wp_die( esc_html__( 'LSX Tour Operator plugin is required but not active.', 'tour-operator' ) );
}
$settings_pages = tour_operator()->legacy->get_post_types();
?>

16-18: 🛠️ Refactor suggestion

Enhance form submission UX

The submit button could benefit from proper WordPress styling and feedback mechanisms.

Apply these enhancements:

-		<input name="submit" class="button button-primary" type="submit" value="Save Settings" />
+		<?php
+		submit_button( __( 'Save Settings', 'tour-operator' ), 'primary large', 'submit', false );
+		settings_errors(); // Display settings errors/updates
+		?>
 	</form>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		<?php
		submit_button( __( 'Save Settings', 'tour-operator' ), 'primary large', 'submit', false );
		settings_errors(); // Display settings errors/updates
		?>
	</form>
</div>

5-7: ⚠️ Potential issue

Implement WordPress security best practices for form handling

The form lacks crucial WordPress security features such as nonce verification and settings API integration.

Apply these security enhancements:

 <div class="wrap lsx-to-settings">
 	<h1><?php echo esc_html__( 'LSX Tour Operator Settings', 'tour-operator' ); ?></h1>
-	<form method="post">
+	<form method="post" action="options.php">
+		<?php
+		settings_fields( 'lsx_to_settings' );
+		wp_nonce_field( 'lsx_to_settings_action', 'lsx_to_settings_nonce' );
+		?>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

<div class="wrap lsx-to-settings">
	<h1><?php echo esc_html__( 'LSX Tour Operator Settings', 'tour-operator' ); ?></h1>
	<form method="post" action="options.php">
		<?php
		settings_fields( 'lsx_to_settings' );
		wp_nonce_field( 'lsx_to_settings_action', 'lsx_to_settings_nonce' );
		?>

8-15: ⚠️ Potential issue

Enhance file inclusion safety and path handling

The current implementation uses hard-coded paths and lacks file existence validation.

Apply this enhancement:

 		<?php
-		include( LSX_TO_PATH . 'includes/partials/navigation.php' );
-		include( LSX_TO_PATH . 'includes/partials/general.php' );
+		$partials = array(
+			'navigation.php',
+			'general.php'
+		);
+		
+		foreach ( $partials as $partial ) {
+			$partial_path = LSX_TO_PATH.'includes/partials/'.$partial;
+			if ( file_exists( $partial_path ) ) {
+				include $partial_path;
+			} else {
+				wp_die( sprintf( esc_html__( 'Required partial %s is missing.', 'tour-operator' ), $partial ) );
+			}
+		}
 		
 		foreach ( $settings_pages as $tab_index => $tab ) {
-			include( LSX_TO_PATH . 'includes/partials/post-type.php' );
+			$post_type_partial = LSX_TO_PATH.'includes/partials/post-type.php';
+			if ( file_exists( $post_type_partial ) ) {
+				include $post_type_partial;
+			}
 		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		<?php
		$partials = array(
			'navigation.php',
			'general.php'
		);
		
		foreach ( $partials as $partial ) {
			$partial_path = LSX_TO_PATH.'includes/partials/'.$partial;
			if ( file_exists( $partial_path ) ) {
				include $partial_path;
			} else {
				wp_die( sprintf( esc_html__( 'Required partial %s is missing.', 'tour-operator' ), $partial ) );
			}
		}
		
		foreach ( $settings_pages as $tab_index => $tab ) {
			$post_type_partial = LSX_TO_PATH.'includes/partials/post-type.php';
			if ( file_exists( $post_type_partial ) ) {
				include $post_type_partial;
			}
		}
		?>
🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis

[notice] 13-13: includes/partials/settings.php#L13
Concat operator must not be surrounded by spaces

includes/partials/navigation.php (4)

1-3: ⚠️ Potential issue

Add error handling for legacy object access

Chap, we should add some defensive programming here to handle cases where the tour operator object or its methods might not be available.

Here's a safer implementation:

 <?php
+if ( ! function_exists( 'tour_operator' ) || ! is_object( tour_operator()->legacy ) ) {
+    return;
+}
 $settings_pages = tour_operator()->legacy->get_post_types();
+if ( empty( $settings_pages ) ) {
+    $settings_pages = array();
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

<?php
if ( ! function_exists( 'tour_operator' ) || ! is_object( tour_operator()->legacy ) ) {
    return;
}
$settings_pages = tour_operator()->legacy->get_post_types();
if ( empty( $settings_pages ) ) {
    $settings_pages = array();
}

6-9: 🧹 Nitpick (assertive)

Proper sanitisation implemented, but let's improve the code structure

Good job on using sanitize_key() for the GET parameter. However, we can improve the code structure.

Consider these improvements:

-	$current_tab = 'general';
-	if ( isset( $_GET['tab'] ) ) {
-		$current_tab = sanitize_key( $_GET['tab'] );	
-	}
+    // Define default tab as a constant
+    const DEFAULT_TAB = 'general';
+    $current_tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : DEFAULT_TAB;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    // Define default tab as a constant
    const DEFAULT_TAB = 'general';
    $current_tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : DEFAULT_TAB;
🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis

[notice] 6-6: includes/partials/navigation.php#L6
Line indented incorrectly; expected at least 4 spaces, found 1


[notice] 9-9: includes/partials/navigation.php#L9
Line indented incorrectly; expected 4 spaces, found 1


11-18: 🛠️ Refactor suggestion

Enhance internationalisation and HTML structure

The security measures are spot on with wp_kses_post(), but we can improve the code's maintainability and internationalisation.

Consider this improved implementation:

-	echo wp_kses_post( '<a class="nav-tab nav-tab-active" href="#ui-general">' . esc_html__( 'General', 'tour-operator' ) . '</a>' );
+	printf(
+		'<a class="nav-tab nav-tab-active" href="#ui-%1$s">%2$s</a>',
+		'general',
+		esc_html__( 'General', 'tour-operator' )
+	);

-		echo wp_kses_post( '<a class="nav-tab ' . $class . '" href="#ui-' . $tab_index . '">' . $tab . '</a>' );
+		printf(
+			'<a class="nav-tab %1$s" href="#ui-%2$s">%3$s</a>',
+			esc_attr( $class ),
+			esc_attr( $tab_index ),
+			esc_html( $tab )
+		);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	printf(
		'<a class="nav-tab nav-tab-active" href="#ui-%1$s">%2$s</a>',
		'general',
		esc_html__( 'General', 'tour-operator' )
	);
	foreach ( $settings_pages as $tab_index => $tab ) {
		$class = '';
		if ( $tab_index === $current_tab ) {
			$class = 'nav-tab-active';
		}
		printf(
			'<a class="nav-tab %1$s" href="#ui-%2$s">%3$s</a>',
			esc_attr( $class ),
			esc_attr( $tab_index ),
			esc_html( $tab )
		);
	}

1-20: ⚠️ Potential issue

Add security checks for admin capabilities

Mate, we should add some security checks to ensure only authorized users can access this navigation.

Add these checks at the beginning of the file:

 <?php
+if ( ! current_user_can( 'manage_options' ) ) {
+    return;
+}
+
+// Add nonce for form submissions
+wp_nonce_field( 'tour_operator_settings', 'tour_operator_settings_nonce' );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

<?php
if ( ! current_user_can( 'manage_options' ) ) {
    return;
}

// Add nonce for form submissions
wp_nonce_field( 'tour_operator_settings', 'tour_operator_settings_nonce' );

$settings_pages = tour_operator()->legacy->get_post_types();
?>
<h2 class="nav-tab-wrapper">
	<?php
	$current_tab = 'general';
	if ( isset( $_GET['tab'] ) ) {
		$current_tab = sanitize_key( $_GET['tab'] );	
	}

	echo wp_kses_post( '<a class="nav-tab nav-tab-active" href="#ui-general">' . esc_html__( 'General', 'tour-operator' ) . '</a>' );
	foreach ( $settings_pages as $tab_index => $tab ) {
		$class = '';
		if ( $tab_index === $current_tab ) {
			$class = 'nav-tab-active';
		}
		echo wp_kses_post( '<a class="nav-tab ' . $class . '" href="#ui-' . $tab_index . '">' . $tab . '</a>' );
	}
	?>
</h2>
🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis

[notice] 6-6: includes/partials/navigation.php#L6
Line indented incorrectly; expected at least 4 spaces, found 1


[notice] 9-9: includes/partials/navigation.php#L9
Line indented incorrectly; expected 4 spaces, found 1

includes/partials/post-type.php (2)

1-2: 🧹 Nitpick (assertive)

Enhance accessibility with ARIA attributes, mate!

The tab panel structure could be more accessible. Consider adding ARIA attributes to improve screen reader support.

Apply these changes:

-<div id="ui-<?php echo esc_attr( $tab_index ); ?>" class="ui-tab tabs-content">
+<div id="ui-<?php echo esc_attr( $tab_index ); ?>" class="ui-tab tabs-content" role="tabpanel" aria-labelledby="tab-<?php echo esc_attr( $tab_index ); ?>">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

<div id="ui-<?php echo esc_attr( $tab_index ); ?>" class="ui-tab tabs-content" role="tabpanel" aria-labelledby="tab-<?php echo esc_attr( $tab_index ); ?>">
	<table class="form-table">

4-11: ⚠️ Potential issue

Improve heading structure, hey!

The nested <label> and <h3> structure isn't semantic. The heading should stand alone.

Apply this change:

 <tr class="form-field">
   <th scope="row" colspan="2">
-    <label>
       <h3> <?php echo esc_html( $tab ); ?> <?php esc_html_e( 'Placeholder Settings', 'tour-operator' ); ?></h3>
-    </label>
   </th>
 </tr>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

			<tr class="form-field">
				<th scope="row" colspan="2">
					<h3> <?php echo esc_html( $tab ); ?> <?php esc_html_e( 'Placeholder Settings', 'tour-operator' ); ?></h3>
				</th>
			</tr>
includes/classes/blocks/class-patterns.php (3)

41-46: 🧹 Nitpick (assertive)

Complete the docblock description, boet.

The docblock comment is incomplete and needs to be finished.

Update the documentation:

 /**
- * Registers our block patterns with the 
+ * Registers our block patterns with WordPress.
  *
  * @return void
  */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	/**
	 * Registers our block patterns with WordPress.
	 *
	 * @return void
	 */
	public function register_block_patterns() {

1-12: 🧹 Nitpick (assertive)

Add file-level documentation, mate.

Proper documentation helps other developers understand the purpose of this file. Let's add a file-level docblock.

Add this documentation at the start of the file:

+/**
+ * LSX Tour Operator Block Patterns.
+ *
+ * @package lsx\blocks
+ */
 <?php
 namespace lsx\blocks;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

/**
 * LSX Tour Operator Block Patterns.
 *
 * @package lsx\blocks
 */
<?php
namespace lsx\blocks;


class Patterns {

	/**
	 * Holds the slug of the projects pattern category.
	 *
	 * @var string
	 */
	private $pattern_category = 'lsx-tour-operator';
🧰 Tools
🪛 GitHub Check: CodeFactor

[warning] 1-1: includes/classes/blocks/class-patterns.php#L1
Missing file doc comment. (Squiz.Commenting.FileComment)


21-27: 🧹 Nitpick (assertive)

Minor formatting improvements needed, hey.

The code is functionally sound, but let's tidy up the formatting.

Apply these changes:

 public function __construct() {
-		//Register our pattern category
+		// Register our pattern category.
 		add_action( 'init', array( $this, 'register_block_category' ) );
 
 		// Register our block patterns
 		add_action( 'init', array( $this, 'register_block_patterns' ), 10 );
+
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	public function __construct() {
		// Register our pattern category.
		add_action( 'init', array( $this, 'register_block_category' ) );

		// Register our block patterns
		add_action( 'init', array( $this, 'register_block_patterns' ), 10 );

	}
🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis

[notice] 27-27: includes/classes/blocks/class-patterns.php#L27
Expected 1 blank line before closing function brace; 0 found

🪛 GitHub Check: CodeFactor

[warning] 22-22: includes/classes/blocks/class-patterns.php#L22
Inline comments must end in full-stops, exclamation marks, or question marks. (Squiz.Commenting.InlineComment)

includes/taxonomies/config-facility.php (1)

33-33: 🧹 Nitpick (assertive)

Good addition of REST API support!

Adding REST API support is essential for modern WordPress development, especially with the block editor. Consider documenting the REST API endpoints in your technical documentation for frontend developers.

includes/taxonomies/config-continent.php (1)

33-33: 🧹 Nitpick (assertive)

Well done on adding REST API support!

Adding REST API support is essential for Gutenberg compatibility and modern WordPress development practices. This change aligns perfectly with WordPress's direction towards full-site editing.

Consider documenting the REST API endpoints in your technical documentation to help frontend developers integrate with this taxonomy.

includes/partials/general.php (4)

1-51: 🧹 Nitpick (assertive)

Consider implementing progressive enhancement.

The current structure assumes all settings are equally important. Consider implementing progressive disclosure patterns for advanced settings like Fusion Table and API configurations.

Would you like assistance in implementing a progressive disclosure pattern for these settings?


7-13: ⚠️ Potential issue

Enhance heading structure for better organisation.

The current implementation uses h3 within a label, which isn't semantically correct. Consider restructuring this pattern across all sections.

-<label>
-    <h3><?php esc_html_e( 'Currency Settings', 'tour-operator' ); ?></h3>
-</label>
+<h3><?php esc_html_e( 'Currency Settings', 'tour-operator' ); ?></h3>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

				<th scope="row" colspan="2">
					<h3><?php esc_html_e( 'Currency Settings', 'tour-operator' ); ?></h3>
				</th>
			</tr>
			<?php do_action( 'lsx_to_framework_dashboard_tab_content', 'currency' ); ?>

53-55: 🧹 Nitpick (assertive)

Remove unnecessary blank lines.

There are multiple blank lines at the end of the file. Maintain a single blank line at the end of the file as per PHP standards.

 </div>

-

-

Committable suggestion was skipped due to low confidence.


4-6: 🧹 Nitpick (assertive)

Consider semantic HTML improvements.

The form-table structure is standard WordPress admin styling, but consider adding ARIA landmarks for improved accessibility.

-<table class="form-table">
+<table class="form-table" role="presentation">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	<table class="form-table" role="presentation">
		<tbody>
			<tr class="form-field">
includes/taxonomies/config-accommodation-type.php (1)

33-33: 🧹 Nitpick (assertive)

Consider aligning array keys consistently.

The show_in_rest parameter's indentation differs from other parameters in the array. While this doesn't affect functionality, consistent alignment improves code readability.

Apply this formatting change:

-		'show_in_rest'        => true,
+                     'show_in_rest'        => true,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

                     'show_in_rest'        => true,
🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis

[notice] 33-33: includes/taxonomies/config-accommodation-type.php#L33
Array key not aligned correctly; expected 21 spaces but found 2

assets/js/blocks/slotfills.js (5)

34-54: 🛠️ Refactor suggestion

Consider extracting common toggle logic

Shame, there's quite a bit of duplicated code between the toggle components. We could make this lekker by creating a reusable toggle component.

Here's a suggested approach:

const MetaToggle = ({ metaKey, label }) => {
  const { editPost } = useDispatch("core/editor");
  const handleChange = (newChecked) => {
    editPost({ meta: { [metaKey]: newChecked } });
  };

  const isChecked = useSelect(function (select) {
    return select('core/editor').getEditedPostAttribute('meta')[metaKey];
  }, [metaKey]);

  return createElement(ToggleControl, {
    label: i18n.__(label),
    checked: isChecked,
    onChange: handleChange
  });
};

// Usage:
const StickyToggle = () => createElement(MetaToggle, {
  metaKey: 'featured',
  label: 'Featured'
});

const DisableSingleToggle = () => createElement(MetaToggle, {
  metaKey: 'disable_single',
  label: 'Disable Single'
});

56-84: 🛠️ Refactor suggestion

Consider using JSX for better readability

Eish, these nested createElement calls are a bit hectic to follow. Using JSX would make this much more readable.

Here's how it could look with JSX:

const LsxToStatusPlugin = () => (
  <PluginPostStatusInfo
    name="lsx-to-toggles"
    className="lsx-to-toggles"
  >
    <div className="lsx-to-toggles__inner">
      <div className="toggle-row">
        <StickyToggle />
      </div>
      <div className="toggle-row">
        <DisableSingleToggle />
      </div>
    </div>
  </PluginPostStatusInfo>
);

40-44: 🧹 Nitpick (assertive)

Rename variable to match its purpose

Same issue here, boet. The variable name isSticky should reflect the "Disable Single" status.

-const isSticky = useSelect( function ( select ) {
+const isDisableSingle = useSelect( function ( select ) {
   return select( 'core/editor' ).getEditedPostAttribute(
     'meta'
   )[ 'disable_single' ];
 }, [] );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		const isDisableSingle = useSelect( function ( select ) {
			return select( 'core/editor' ).getEditedPostAttribute(
				'meta'
			)[ 'disable_single' ];
		}, [] );

17-21: 🧹 Nitpick (assertive)

Rename variable to match its purpose

Howzit! The variable name isSticky doesn't quite match what it represents. Since this is for the "Featured" status, let's make it more clear.

-const isSticky = useSelect( function ( select ) {
+const isFeatured = useSelect( function ( select ) {
   return select( 'core/editor' ).getEditedPostAttribute(
     'meta'
   )[ 'featured' ];
 }, [] );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		const isFeatured = useSelect( function ( select ) {
			return select( 'core/editor' ).getEditedPostAttribute(
				'meta'
			)[ 'featured' ];
		}, [] );

1-8: 🧹 Nitpick (assertive)

Remove unused HStack import

Chap, I notice you've imported the HStack component but it's not being used anywhere in the code. Let's keep our imports tidy.

-const { HStack } = wp.components;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

(function (wp) {
	const { registerPlugin } = wp.plugins;
	const { PluginPostStatusInfo } = wp.editPost;
	const { ToggleControl } = wp.components;
	const { useSelect, useDispatch } = wp.data;
	const { createElement, useState } = wp.element;
	const i18n = window.wp.i18n;
assets/js/src/admin.js (3)

15-15: 🛠️ Refactor suggestion

Lekker improvements to the image selection logic, but let's add some error handling.

The changes to use attr() instead of creating new elements and the improved class extraction are more efficient, but we should add some defensive programming.

Here's a suggested improvement:

- image_class = $image.attr('class');
- image_class = image_class.split('wp-image-');
- $td.find('.thumbnail-preview img').attr('src', image_src).parent().show();
- $td.find('input.input_image').val(image_class[1]);
+ const imageClass = $image.attr('class') || '';
+ const imageIdMatch = imageClass.match(/wp-image-(\d+)/);
+ if (imageIdMatch && imageIdMatch[1]) {
+   $td.find('.thumbnail-preview img').attr('src', image_src).parent().show();
+   $td.find('input.input_image').val(imageIdMatch[1]);
+ } else {
+   console.warn('Could not extract image ID from class:', imageClass);
+ }

Also applies to: 29-30


69-70: 🛠️ Refactor suggestion

Ja, good alignment with WordPress UI patterns, but we can make it more efficient.

The changes to use WordPress's standard nav-tab classes are spot on, but let's cache our jQuery selectors and add some accessibility improvements.

Here's a more efficient version:

jQuery(document).on('click', '.nav-tab-wrapper a', function(e) {
    e.preventDefault();
    e.stopPropagation();

-   var $this = jQuery(this);
+   var $this = jQuery(this),
+       $wrapper = jQuery('.nav-tab-wrapper'),
+       $tabs = jQuery('.ui-tab'),
+       targetId = $this.attr('href');

-   jQuery('.nav-tab-wrapper a.nav-tab-active').removeClass('nav-tab-active');
-   $this.addClass('nav-tab-active');
-   jQuery('.ui-tab.active').removeClass('active');
-   jQuery($this.attr('href')).addClass('active');
+   $wrapper.find('a.nav-tab-active').removeClass('nav-tab-active').attr('aria-selected', 'false');
+   $this.addClass('nav-tab-active').attr('aria-selected', 'true');
+   $tabs.removeClass('active').attr('aria-hidden', 'true');
+   jQuery(targetId).addClass('active').attr('aria-hidden', 'false');

Also, please ensure your HTML includes these ARIA attributes:

<div class="nav-tab-wrapper" role="tablist">
    <a class="nav-tab" role="tab" aria-controls="tab-1">...</a>
</div>
<div id="tab-1" class="ui-tab" role="tabpanel">...</div>

Also applies to: 76-77, 79-79


55-55: 🧹 Nitpick (assertive)

Shame, this could be more efficient.

Instead of setting an empty src attribute and then hiding the parent, we could just hide the parent element.

- $td.find('.thumbnail-preview img' ).attr('src','').parent().hide();
+ $td.find('.thumbnail-preview').hide();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

			$td.find('.thumbnail-preview').hide();
includes/classes/admin/class-pages.php (1)

75-75: 🧹 Nitpick (assertive)

Lekker addition of the action hook, but let's add some documentation, hey?

The hook placement is spot on, allowing for proper extension of the menu page registration. Consider adding a docblock to document this hook's purpose and parameters for other developers.

Add this docblock above the hook:

+/**
+ * Action hook fired before registering the main menu pages.
+ *
+ * @since 1.x.x
+ */
 do_action( 'lsx_to_register_menu_pages' );

Committable suggestion was skipped due to low confidence.

assets/js/blocks/variations.js (4)

1-1: 🛠️ Refactor suggestion

Consider adding defensive programming checks.

Blimey! The code assumes the wp object is always available. Consider adding a check to prevent potential runtime errors.

+if (typeof wp === 'undefined') {
+    return;
+}
+
 wp.domReady(() => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

if (typeof wp === 'undefined') {
    return;
}

wp.domReady(() => {

86-132: 🛠️ Refactor suggestion

Enhance price formatting and validation.

Shame, the price block needs some improvements:

  1. Consider using CSS custom properties instead of hardcoded padding values
  2. Add currency formatting support
  3. Implement validation for the price metadata
 metadata: {
     bindings: {
         content: {
             source: 'lsx/post-meta',
-            args: { key: 'price' }
+            args: { 
+                key: 'price',
+                format: 'currency',
+                validate: (value) => !isNaN(parseFloat(value))
+            }
         }
     }
 },

Committable suggestion was skipped due to low confidence.


2-27: 🧹 Nitpick (assertive)

Add internationalisation support and documentation.

Howzit! A few suggestions to improve this block variation:

  1. The title and placeholder should be translatable
  2. The metadata binding source 'lsx/tour-itinerary' needs documentation
 wp.blocks.registerBlockVariation('core/group', {
     name: 'lsx/itinerary',
-    title: 'Itinerary',
+    title: wp.i18n.__('Itinerary', 'lsx-blocks'),
     icon: 'list-view',
     // ... other attributes
     innerBlocks: [
         ['core/paragraph', {
-            placeholder: 'Insert your Itinerary pattern here.',
+            placeholder: wp.i18n.__('Insert your Itinerary pattern here.', 'lsx-blocks'),
             align: 'center'
         }]
     ],

Committable suggestion was skipped due to low confidence.


56-84: ⚠️ Potential issue

Replace hardcoded image URLs and improve accessibility.

Eish! The gallery block has a few issues:

  1. Hardcoded placeholder image URLs should be moved to constants or configuration
  2. Missing alt text for accessibility compliance
  3. Consider making the number of placeholder images configurable
+const PLACEHOLDER_IMAGE_URL = 'https://tour-operator.lsx.design/wp-content/plugins/tour-operator/assets/img/placeholders/placeholder-general-350x350.jpg';
+
 wp.blocks.registerBlockVariation('core/gallery', {
     // ... other attributes
     innerBlocks: [
         ['core/image', {
-            href: 'https://tour-operator.lsx.design/wp-content/plugins/tour-operator/assets/img/placeholders/placeholder-general-350x350.jpg'
+            href: PLACEHOLDER_IMAGE_URL,
+            alt: wp.i18n.__('Placeholder image', 'lsx-blocks')
         }],
         // ... repeat for other images
     ],

Committable suggestion was skipped due to low confidence.

src/init.php (3)

95-95: 🛠️ Refactor suggestion

Consider renaming the function for clarity

The current function name lsx_enqueue_block_assets is too generic for its specific purpose.

Rename to be more specific:

-function lsx_enqueue_block_assets() {
+function lsx_enqueue_linked_cover_block_assets() {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

function lsx_enqueue_linked_cover_block_assets() {

92-94: 🧹 Nitpick (assertive)

Enhance function documentation

The docblock should include more details about the function's purpose and dependencies.

Add comprehensive documentation:

 /**
  * Enqueues linked cover block.
+ *
+ * Registers and enqueues the JavaScript required for the linked cover block functionality
+ * in the block editor. This script extends the core Cover block with linking capabilities.
+ *
+ * @since 1.0.0
+ * @return void
  */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

/**
 * Enqueues linked cover block.
 *
 * Registers and enqueues the JavaScript required for the linked cover block functionality
 * in the block editor. This script extends the core Cover block with linking capabilities.
 *
 * @since 1.0.0
 * @return void
 */

95-104: ⚠️ Potential issue

Add error handling for file existence

The script enqueuing lacks proper error handling. Consider adding file existence checks to prevent potential errors.

Apply this improvement:

 function lsx_enqueue_block_assets() {
+    $script_path = plugin_dir_path( dirname( __FILE__ ) ) . 'assets/js/blocks/linked-cover.js';
+    if ( ! file_exists( $script_path ) ) {
+        return;
+    }
 
     wp_enqueue_script(
         'lsx-linked-cover',
         plugins_url( 'assets/js/blocks/linked-cover.js', dirname( __FILE__ ) ),
         array( 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-data', 'wp-hooks' ),
-        filemtime( plugin_dir_path( dirname( __FILE__ ) ) . 'assets/js/blocks/linked-cover.js' )
+        filemtime( $script_path )
     );
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

function lsx_enqueue_block_assets() {
    $script_path = plugin_dir_path( dirname( __FILE__ ) ) . 'assets/js/blocks/linked-cover.js';
    if ( ! file_exists( $script_path ) ) {
        return;
    }

    wp_enqueue_script(
        'lsx-linked-cover',
        plugins_url( 'assets/js/blocks/linked-cover.js', dirname( __FILE__ ) ),
        array( 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-data', 'wp-hooks' ),
        filemtime( $script_path )
    );
}
includes/classes/blocks/class-variations.php (4)

68-97: 🧹 Nitpick (assertive)

Performance and maintainability improvements needed

The variation handling could be optimised in several ways:

  1. The custom field query runs on every block render, which might impact performance
  2. The allowed blocks and classes are hardcoded
  3. Missing validation for the custom field value

Consider these improvements:

  1. Cache the custom field query results:
$cache_key = 'lsx_to_price_' . get_the_ID();
$value = wp_cache_get( $cache_key );
if ( false === $value ) {
    $value = lsx_to_custom_field_query( 'price', '', '', false );
    wp_cache_set( $cache_key, $value );
}
  1. Make the arrays configurable via filters:
$allowed_blocks = apply_filters( 'lsx_to_variation_allowed_blocks', array(
    'core/group',
) );

4-9: 🧹 Nitpick (assertive)

Documentation needs improvement

The class documentation could be enhanced to better follow WordPress standards:

  1. Add proper @SInCE tags
  2. Include @return annotations for methods
  3. Better describe the class purpose and responsibilities

Would you like me to generate improved documentation for the class?


10-18: ⚠️ Potential issue

Singleton implementation is incomplete, mate!

The class has a private static instance variable but lacks the getInstance() method typically required for the singleton pattern. This could lead to multiple instances being created.

Here's how to properly implement the singleton pattern:

private static $instance;

+ /**
+  * Returns instance of the class
+  *
+  * @return \lsx\blocks\Variations
+  */
+ public static function get_instance() {
+     if ( null === self::$instance ) {
+         self::$instance = new self();
+     }
+     return self::$instance;
+ }

- public function __construct() {
+ private function __construct() {

Committable suggestion was skipped due to low confidence.

🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis

[notice] 14-14: includes/classes/blocks/class-variations.php#L14
@SInCE tag is not allowed in member variable comment


36-57: 🛠️ Refactor suggestion

Consider enhancing script handling security and flexibility

A few suggestions to improve this section:

  1. The hardcoded paths could break if the plugin directory name changes
  2. Missing nonce verification for potential AJAX requests
  3. Consider using wp_localize_script() to pass dynamic data

Here's a suggested improvement:

+ $script_path = 'assets/js/blocks/variations.js';
+ $script_url = LSX_TO_URL . $script_path;
+ $script_file = LSX_TO_PATH . $script_path;

wp_enqueue_script(
    'lsx-to-block-variations',
-   LSX_TO_URL . 'assets/js/blocks/variations.js',
+   $script_url,
    array( 'wp-blocks', 'wp-dom-ready', 'wp-edit-post' ),
-   filemtime( LSX_TO_PATH . 'assets/js/blocks/variations.js' ),
+   file_exists( $script_file ) ? filemtime( $script_file ) : '1.0.0',
    true
);

+ wp_localize_script(
+     'lsx-to-block-variations',
+     'lsxToVariations',
+     array(
+         'nonce' => wp_create_nonce( 'lsx_to_variations' ),
+         'ajaxurl' => admin_url( 'admin-ajax.php' )
+     )
+ );

Committable suggestion was skipped due to low confidence.

🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis

[notice] 36-36: includes/classes/blocks/class-variations.php#L36
Line indented incorrectly; expected 4 spaces, found 1


[notice] 41-41: includes/classes/blocks/class-variations.php#L41
Comments may not appear after statements


[notice] 42-42: includes/classes/blocks/class-variations.php#L42
Array with multiple values cannot be declared on a single line

assets/css/scss/admin.scss (2)

69-75: 🛠️ Refactor suggestion

Consider adding smooth transitions for tab switching.

The current implementation could benefit from a fade transition to create a more polished user experience.

 .ui-tab {
-  display: none;
+  opacity: 0;
+  visibility: hidden;
+  transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out;
+  height: 0;
+  overflow: hidden;

   &.active {
-    display: block;
+    opacity: 1;
+    visibility: visible;
+    height: auto;
   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	.ui-tab {
		opacity: 0;
		visibility: hidden;
		transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out;
		height: 0;
		overflow: hidden;

		&.active {
			opacity: 1;
			visibility: visible;
			height: auto;
		}
	}

60-67: 🛠️ Refactor suggestion

Consider using SCSS variables for consistent dimensions.

The max-width value could be moved to a variable for better maintainability. This would make it easier to adjust the form field widths across the entire application.

+// At the top of the file
+$form-field-max-width: 300px;
+
 .wrap.lsx-to-settings {
   .form-field {
     input[type="text"],
     input[type="number"],
     select {
-      max-width: 300px;
+      max-width: $form-field-max-width;
     }
   }
 }

Committable suggestion was skipped due to low confidence.

includes/classes/blocks/class-templates.php (6)

17-17: ⚠️ Potential issue

Remove unused property $templates

Blimey! The public property $templates is declared but never utilised throughout the class. Consider removing it to avoid confusion, or if it's intended for future use, add a TODO comment explaining its purpose.

-	public $templates = [];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.



119-121: ⚠️ Potential issue

Fix incorrect return type documentation

Haibo! The method documentation states @return void but actually returns a string. Please update the documentation:

- * @param [type] $template
- * @return void
+ * @param string $template The template file name
+ * @return string The template content
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	 * @param string $template The template file name
	 * @return string The template content
	 */
🧰 Tools
🪛 GitHub Check: CodeFactor

[warning] 120-120: includes/classes/blocks/class-templates.php#L120
Function return type is void, but function contains return statement. (Squiz.Commenting.FunctionComment)


24-26: ⚠️ Potential issue

Fix incorrect method visibility documentation

Ag shame! The docblock indicates this method is private (@access private), but it's actually declared as public. Please update the documentation to match the implementation.

- * @access private
+ * @access public
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	 * @access public
	 */
	public function __construct() {
🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis

[notice] 26-26: includes/classes/blocks/class-templates.php#L26
Expected 2 blank lines before function; 1 found


122-126: ⚠️ Potential issue

Add path validation for template inclusion

Yoh! The template path concatenation could be unsafe. Consider adding validation to prevent directory traversal:

 	protected function get_template_content( $template ) {
+		$template_path = LSX_TO_PATH . "/templates/{$template}";
+		if ( ! file_exists( $template_path ) || ! is_readable( $template_path ) ) {
+			return '';
+		}
 		ob_start();
-		include LSX_TO_PATH . "/templates/{$template}";
+		include $template_path;
 		return ob_get_clean();
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	protected function get_template_content( $template ) {
		$template_path = LSX_TO_PATH . "/templates/{$template}";
		if ( ! file_exists( $template_path ) || ! is_readable( $template_path ) ) {
			return '';
		}
		ob_start();
		include $template_path;
		return ob_get_clean();
	}

40-101: 🛠️ Refactor suggestion

Consider defining post type slugs as constants

Eish! The post type slugs are scattered throughout the array. Consider defining them as class constants for better maintainability and reusability.

+	private const POST_TYPE_ACCOMMODATION = 'accommodation';
+	private const POST_TYPE_DESTINATION = 'destination';
+	private const POST_TYPE_TOUR = 'tour';

 	$post_types = [
 		'single-accommodation'  => [
 			'title'       => __( 'Single Accommodations', 'tour-operator' ),
 			'description' => __( 'Displays a single accommodation', 'tour-operator' ),
-			'post_types'  => ['accommodation'],
+			'post_types'  => [self::POST_TYPE_ACCOMMODATION],
 		],

Committable suggestion was skipped due to low confidence.

🧰 Tools
🪛 GitHub Check: CodeFactor

[notice] 56-56: includes/classes/blocks/class-templates.php#L56
Array double arrow not aligned correctly; expected 3 space(s) between "'archive-destination'" and double arrow, but found 1. (WordPress.Arrays.MultipleStatementAlignment-[fixable])


[warning] 44-44: includes/classes/blocks/class-templates.php#L44
Expected 1 space before the array closer in a single line array. Found: no spaces. (NormalizedArrays.Arrays.ArrayBraceSpacing-[fixable])


[warning] 97-97: includes/classes/blocks/class-templates.php#L97
Short array syntax is not allowed. (Universal.Arrays.DisallowShortArraySyntax-[fixable])


[notice] 61-61: includes/classes/blocks/class-templates.php#L61
Array double arrow not aligned correctly; expected 11 space(s) between "'single-tour'" and double arrow, but found 2. (WordPress.Arrays.MultipleStatementAlignment-[fixable])


103-113: ⚠️ Potential issue

Add error handling for template registration

Shame! The template registration could fail silently. Consider adding error handling to log failures and notify developers.

-			register_block_template( 'lsx-tour-operator//' . $key, $args );
+			$result = register_block_template( 'lsx-tour-operator//' . $key, $args );
+			if ( is_wp_error( $result ) ) {
+				error_log( sprintf( 'Failed to register template %s: %s', $key, $result->get_error_message() ) );
+			}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		foreach ( $post_types as $key => $labels ) {
			$args = [
				'title'       => $labels['title'],
				'description' => $labels['description'],
				'content'     => $this->get_template_content( $key . '.html' ),
			];
			if ( isset( $labels['post_types'] ) ) {
				$args['post_types'] = $labels['post_types'];
			}
			$result = register_block_template( 'lsx-tour-operator//' . $key, $args );
			if ( is_wp_error( $result ) ) {
				error_log( sprintf( 'Failed to register template %s: %s', $key, $result->get_error_message() ) );
			}
		}
includes/constants/settings-fields.php (5)

99-104: ⚠️ Potential issue

Add Google Maps API key validation

The Google Maps API key field lacks validation and security measures.

Add validation and sanitization:

 'googlemaps_key' => array(
     'label'   => esc_html__( 'Google Maps API', 'tour-operator' ),
     'type'    => 'text',
+    'sanitize_callback' => 'sanitize_text_field',
+    'desc'    => esc_html__( 'Enter a valid Google Maps API key', 'tour-operator' ),
+    'pattern' => '^[A-Za-z0-9_-]+$',
 )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	'api' => array(
		'googlemaps_key' => array(
			'label'   => esc_html__( 'Google Maps API', 'tour-operator' ),
			'type'    => 'text',
			'sanitize_callback' => 'sanitize_text_field',
			'desc'    => esc_html__( 'Enter a valid Google Maps API key', 'tour-operator' ),
			'pattern' => '^[A-Za-z0-9_-]+$',
		)
	),

106-125: ⚠️ Potential issue

Eliminate duplicate placeholder configuration

The placeholder settings under post_types are duplicated from the top-level placeholder section.

Consider refactoring to use a single configuration:

-'post_types' => array(
-    'placeholder' => array(
-        'featured_placeholder' => array(
-            'label'     => esc_html__( 'Upload a placeholder', 'tour-operator' ),
-            'type'      => 'image',
-            'default'   => 0,
-            'preview_w' => 300,
-        ),
-        // ... other duplicate settings
-    ),
+'post_types' => array(
+    'placeholder' => 'global', // Reference global placeholder settings

Committable suggestion was skipped due to low confidence.


74-98: ⚠️ Potential issue

Enhance Fusion Tables colour validation

The colour inputs for border and background lack proper validation for hex colour codes.

Add validation for hex colour codes:

 'fusion_tables_colour_border' => array(
     'label'   => esc_html__( 'Border Colour', 'tour-operator' ),
     'desc'    => esc_html__( 'Default value: #000000', 'tour-operator' ),
-    'type'    => 'text',
+    'type'    => 'color',
     'default' => '#000000',
 ),

Committable suggestion was skipped due to low confidence.


126-139: 🛠️ Refactor suggestion

Add archive/single redirect configuration

The disable options need additional configuration for redirect behaviour.

Add redirect configuration:

 'disable_archives' => array(
     'label'   => esc_html__( 'Disable Archives', 'tour-operator' ),
     'desc'    => esc_html__( 'This disables the "post type archive", if you create your own custom loop it will still work.', 'tour-operator' ),
     'type'    => 'checkbox',
     'default' => 0,
+    'redirect_to' => array(
+        'type'    => 'select',
+        'options' => array(
+            'home'     => esc_html__( 'Homepage', 'tour-operator' ),
+            'custom'   => esc_html__( 'Custom URL', 'tour-operator' ),
+        ),
+        'default' => 'home',
+    ),
 ),

Committable suggestion was skipped due to low confidence.


3-21: 🛠️ Refactor suggestion

Review currency configuration settings

The currency settings look good, but considering this is a South African tour operator application, I notice a few regional currencies are missing.

Consider adding these relevant African currencies:

 'options' => array(
     'USD' => esc_html__( 'USD (united states dollar)', 'tour-operator' ),
     'GBP' => esc_html__( 'GBP (british pound)', 'tour-operator' ),
     'ZAR' => esc_html__( 'ZAR (south african rand)', 'tour-operator' ),
     'NAD' => esc_html__( 'NAD (namibian dollar)', 'tour-operator' ),
+    'BWP' => esc_html__( 'BWP (botswana pula)', 'tour-operator' ),
+    'MZN' => esc_html__( 'MZN (mozambican metical)', 'tour-operator' ),
+    'ZMW' => esc_html__( 'ZMW (zambian kwacha)', 'tour-operator' ),
     'CAD' => esc_html__( 'CAD (canadian dollar)', 'tour-operator' ),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	'currency' => array(
		'currency' => array(
			'label'   => esc_html__( 'Currency', 'tour-operator' ),
			'type'    => 'select',
			'default' => 'ZAR',
			'options' => array(
				'USD' => esc_html__( 'USD (united states dollar)', 'tour-operator' ),
				'GBP' => esc_html__( 'GBP (british pound)', 'tour-operator' ),
				'ZAR' => esc_html__( 'ZAR (south african rand)', 'tour-operator' ),
				'NAD' => esc_html__( 'NAD (namibian dollar)', 'tour-operator' ),
				'BWP' => esc_html__( 'BWP (botswana pula)', 'tour-operator' ),
				'MZN' => esc_html__( 'MZN (mozambican metical)', 'tour-operator' ),
				'ZMW' => esc_html__( 'ZMW (zambian kwacha)', 'tour-operator' ),
				'CAD' => esc_html__( 'CAD (canadian dollar)', 'tour-operator' ),
				'EUR' => esc_html__( 'EUR (euro)', 'tour-operator' ),
				'HKD' => esc_html__( 'HKD (hong kong dollar)', 'tour-operator' ),
				'SGD' => esc_html__( 'SGD (singapore dollar)', 'tour-operator' ),
				'NZD' => esc_html__( 'NZD (new zealand dollar)', 'tour-operator' ),
				'AUD' => esc_html__( 'AUD (australian dollar)', 'tour-operator' ),
			),
		),
	),
🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis

[notice] 17-17: includes/constants/settings-fields.php#L17
Array key not aligned correctly; expected 17 spaces but found 4

includes/classes/legacy/class-unit-query.php (1)

177-206: 🛠️ Refactor suggestion

Enhance price handling with proper formatting

The new item_price() method outputs the raw price value without any currency formatting. Consider using WordPress's built-in price formatting capabilities or implementing proper currency handling.

Consider this implementation:

 public function item_price( $before = '', $after = '', $echo = false ) {
     if ( $this->have_query && false !== $this->query_item ) {
         if ( false !== $this->query_item['price'] ) {
-            $return = $before . $this->query_item['price'] . $after;
+            $price = apply_filters( 'lsx_format_price', $this->query_item['price'] );
+            $return = $before . $price . $after;
             if ( $echo ) {
                 echo wp_kses_post( $return );
             } else {
                 return $return;
             }
         }
     }
 }

Committable suggestion was skipped due to low confidence.

includes/classes/legacy/class-itinerary-query.php (2)

145-159: 🛠️ Refactor suggestion

Refactor array handling and remove commented code

A few suggestions to improve this section:

  1. The array conversion logic can be simplified
  2. Remove the commented-out code instead of leaving it in place
  3. Consider using early returns to reduce nesting

Here's a suggested refactor:

-			$gallery = get_post_meta( $accommodation_id, 'gallery', true );
-			if ( false !== $gallery && ! empty( $gallery ) ) {
-				if ( ! is_array( $gallery ) ) {
-					$gallery = array( $gallery );
-				} else {
-					$gallery = array_keys( $gallery );
-				}
-
-				/*if ( 'accommodation_to_tour' === $meta_key ) {
-					$gallery = $this->append_room_images( $accommodation_id, $gallery );
-				} else if ( 'destination_to_tour' === $meta_key ) {
-					$gallery = $this->maybe_append_parent( $accommodation_id, $gallery );
-				}*/
-
-				$this->current_attachments[ $accommodation_id ] = $gallery;
-			}
+			$gallery = get_post_meta( $accommodation_id, 'gallery', true );
+			if ( empty( $gallery ) ) {
+				return;
+			}
+			
+			$gallery = is_array( $gallery ) ? array_keys( $gallery ) : array( $gallery );
+			$this->current_attachments[ $accommodation_id ] = $gallery;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

			$gallery = get_post_meta( $accommodation_id, 'gallery', true );
			if ( empty( $gallery ) ) {
				return;
			}
			
			$gallery = is_array( $gallery ) ? array_keys( $gallery ) : array( $gallery );
			$this->current_attachments[ $accommodation_id ] = $gallery;

173-179: 🛠️ Refactor suggestion

Extract array conversion logic to a utility method

The array conversion logic is duplicated across methods. Consider extracting this into a utility method.

Here's a suggested implementation:

+	/**
+	 * Ensures a value is an array
+	 *
+	 * @param mixed $value The value to convert
+	 * @return array
+	 */
+	private function ensure_array( $value ) {
+		if ( empty( $value ) ) {
+			return array();
+		}
+		return is_array( $value ) ? $value : array( $value );
+	}

 	public function append_room_images( $accommodation_id = false, $gallery = array() ) {
 		if ( false !== $accommodation_id ) {
 			$room_images = get_post_meta( $accommodation_id, 'units', true );
-			if ( false !== $room_images && ! empty( $room_images ) ) {
-				if ( ! is_array( $room_images ) ) {
-					$room_images = array( $room_images );
-				}
+			$room_images = $this->ensure_array( $room_images );
+			if ( ! empty( $room_images ) ) {

Committable suggestion was skipped due to low confidence.

includes/metaboxes/config-destination.php (3)

181-214: 🛠️ Refactor suggestion

Optimise multiselect fields for better performance.

The multiselect fields for posts, accommodation, and tours might become slow with large datasets since AJAX is disabled (use_ajax => false).

Enable AJAX loading and add pagination:

 'type'       => 'pw_multiselect',
-'use_ajax'   => false,
+'use_ajax'   => true,
+'ajax_args'  => array(
+    'posts_per_page' => 10,
+    'paged'         => 1
+),

This will improve performance when dealing with large numbers of posts.

Committable suggestion was skipped due to low confidence.


125-133: ⚠️ Potential issue

Add file size restrictions to gallery uploads.

While the gallery configuration is good, it's missing file size restrictions. This could lead to performance issues if users upload very large images.

Add size restrictions to the query args:

 'query_args' => array(
     'type' => 'image',
+    'post_mime_type' => array('image/jpeg', 'image/png'),
+    'post_status' => 'inherit',
+    'posts_per_page' => 50,
 ),

Also consider adding a note about recommended image dimensions in the description.

Committable suggestion was skipped due to low confidence.


148-169: ⚠️ Potential issue

Add proper API key validation for maps.

The current implementation doesn't properly validate the Google Maps API key. A missing or invalid key could cause issues on the frontend.

Add validation before rendering the map field:

 if ( isset( tour_operator()->options['googlemaps_key'] ) && ! empty( tour_operator()->options['googlemaps_key'] ) ) {
     $google_api_key = tour_operator()->options['googlemaps_key'];
+    // Validate API key format
+    if ( ! preg_match('/^[A-Za-z0-9_-]+$/', $google_api_key) ) {
+        add_action( 'admin_notices', function() {
+            echo '<div class="error"><p>' . esc_html__( 'Invalid Google Maps API key format', 'tour-operator' ) . '</p></div>';
+        });
+        $google_api_key = '';
+    }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	if ( isset( tour_operator()->options['googlemaps_key'] ) && ! empty( tour_operator()->options['googlemaps_key'] ) ) {
		$google_api_key = tour_operator()->options['googlemaps_key'];
		// Validate API key format
		if ( ! preg_match('/^[A-Za-z0-9_-]+$/', $google_api_key) ) {
			add_action( 'admin_notices', function() {
				echo '<div class="error"><p>' . esc_html__( 'Invalid Google Maps API key format', 'tour-operator' ) . '</p></div>';
			});
			$google_api_key = '';
		}
	}
	$metabox['fields'][] = array(
		'id'             => 'location',
		'name'           => esc_html__( 'Address', 'tour-operator' ),
		'type'           => 'pw_map',
		'api_key' => $google_api_key,
	);
	$metabox['fields'][] = array(
		'id'         => 'map_placeholder',
		'name'       => esc_html__( 'Map Placeholder', 'tour-operator' ),
		'type'       => 'file',
		'repeatable' => false,
		'show_size'  => false,
		'query_args' => array(
			'type' => array(
				'image/gif',
				'image/jpeg',
				'image/png',
		   ),
	   ), 
includes/metaboxes/config-accommodation.php (3)

177-184: 🧹 Nitpick (assertive)

Lovely improvements to related content selection!

The switch to pw_multiselect with clear descriptions improves usability. Consider adding a maximum selection limit to prevent performance issues with too many related items.

Add a selection limit:

 'options'  => array(
 	'post_type_args' => 'post',
+	'limit' => 10, // Prevent performance issues with too many related items
 ),

Also applies to: 190-197, 203-210


98-106: ⚠️ Potential issue

Lovely improvements to the gallery implementation!

The new file_list implementation with proper file type restrictions and preview handling is a significant improvement. However, there are some formatting inconsistencies:

  1. Line 98 uses spaces instead of tabs
  2. Some lines need proper indentation

Apply this formatting fix:

-    'name' => esc_html__( 'Gallery', 'tour-operator' ),
+	'name' => esc_html__( 'Gallery', 'tour-operator' ),

Committable suggestion was skipped due to low confidence.

🧰 Tools
🪛 GitHub Check: CodeFactor

[warning] 103-103: includes/metaboxes/config-accommodation.php#L103
Tabs must be used to indent lines; spaces are not allowed. (Generic.WhiteSpace.DisallowSpaceIndent-[fixable])


42-48: 💡 Codebase verification

⚠️ Potential issue

Required field setting needs attention

The verification confirms potential issues with making the Accommodation Expert field mandatory:

  • The schema class (class-schema.php) relies on the team_to_accommodation meta value for displaying expert information
  • There's no default value handling or fallback mechanism implemented
  • The field configuration doesn't provide error handling for cases where team members are unavailable

Recommendations:

  • Add a default value or make the field optional by setting allow_none to true
  • Implement validation logic to handle cases where the team post type is unavailable
  • Add error handling in the schema class when $accommodation_expert_id is empty
🔗 Analysis chain

Please review the required field setting

Setting allow_none to false makes the Accommodation Expert field mandatory. This might cause issues if:

  1. No team members are available in the system
  2. The team plugin is deactivated after accommodations are created

Consider adding a fallback mechanism or making this field optional.

Let's verify the team plugin integration:


Let me analyze the team integration more thoroughly to verify the concerns about the required field setting.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there are any accommodations with team members assigned
rg -l "team_to_accommodation.*meta_value" wp-content/uploads

Length of output: 257


Script:

#!/bin/bash
# Check for team post type registration and usage
rg -l "register_post_type.*team"

# Check for team-related meta fields or connections
rg -l "team_to_accommodation"

# Look for any team-related functions or hooks
rg -l "team.*accommodation"

# Check metabox configuration patterns
ast-grep --pattern 'array(
  $$$
  '\''type'\'' => '\''pw_select'\'',
  $$$
)'

Length of output: 411


Script:

#!/bin/bash
# Check the implementation details of team post type and its usage
rg -A 10 "register_post_type.*team"

# Examine the schema class for team accommodation relationship handling
rg -A 5 "team_to_accommodation" includes/classes/legacy/class-schema.php

# Look for any fallback or validation logic
rg -A 5 "team.*accommodation" includes/metaboxes/config-accommodation.php

# Check if there's any default value handling
ast-grep --pattern 'array(
  $$$
  '\''type'\'' => '\''pw_select'\'',
  '\''default'\'' => $_,
  $$$
)'

Length of output: 897

includes/metaboxes/config-tour.php (3)

165-175: 🧹 Nitpick (assertive)

Enhanced itinerary group configuration

The addition of group title formatting and custom button labels improves the user interface for managing itineraries.

Consider adding a description for the itinerary group to match the documentation pattern used in other fields:

-'desc'        => '',
+'desc'        => esc_html__( 'Add daily itinerary details including activities, meals, and accommodations.', 'tour-operator' ),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	'single_name' => __( 'Day(s)', 'tour-operator' ),
	'type'        => 'group',
	'repeatable'  => true,
	'fields'      => lsx\legacy\Tour::get_instance()->itinerary_fields(),
	'desc'        => esc_html__( 'Add daily itinerary details including activities, meals, and accommodations.', 'tour-operator' ),
    'options'     => array(
        'group_title'       => __( 'Itinerary {#}', 'tour-operator' ), // since version 1.1.4, {#} gets replaced by row number
        'add_button'        => __( 'Add Another', 'tour-operator' ),
        'remove_button'     => __( 'Remove', 'tour-operator' ),
        'sortable'          => false,
    ),

139-153: 🧹 Nitpick (assertive)

Improved media handling implementation

The switch from gallery to file_list type with preview capabilities and custom text is a good improvement. However, there's a potential performance consideration.

Consider adding image size restrictions or implementing lazy loading for the gallery preview to prevent performance issues with large galleries. You might want to add:

 'query_args' => array( 
   'type' => 'image',
+  'post_mime_type' => array('image/jpeg', 'image/png'),
+  'post_status' => 'inherit',
+  'posts_per_page' => 50
 ),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	'id'   => 'media_title',
	'name' => esc_html__( 'Media', 'tour-operator' ),
	'type' => 'title',
);

$metabox['fields'][] = array(
    'name' => esc_html__( 'Gallery', 'tour-operator' ),
	'desc' => esc_html__( 'Add images related to the tour to be displayed in the Tour gallery.', 'tour-operator' ),
    'id'   => 'gallery',
    'type' => 'file_list',
    'preview_size' => 'thumbnail', // Image size to use when previewing in the admin.
    'query_args' => array( 
        'type' => 'image',
        'post_mime_type' => array('image/jpeg', 'image/png'),
        'post_status' => 'inherit',
        'posts_per_page' => 50
    ), // Only images attachment
    'text' => array(
        'add_upload_files_text' => esc_html__( 'Add new image', 'tour-operator' ), // default: "Add or Upload Files"
    ),
🧰 Tools
🪛 GitHub Check: CodeFactor

[notice] 147-147: includes/metaboxes/config-tour.php#L147
Array double arrow not aligned correctly; expected 11 space(s) between "'id'" and double arrow, but found 3. (WordPress.Arrays.MultipleStatementAlignment-[fixable])


179-219: ⚠️ Potential issue

Improved related content selection

The switch to pw_multiselect for related content improves the user interface, but there's an inconsistency in the allow_none settings.

The allow_none setting is inconsistent across related content fields:

  • Posts: false
  • Accommodation: false
  • Destinations: true

This might cause confusion. Consider standardising the approach:

 'id'         => 'post_to_tour',
 'allow_none' => false,

Should be changed to true to match the destinations field, as related content should be optional.

Committable suggestion was skipped due to low confidence.

includes/classes/legacy/class-schema.php (1)

124-125: 🛠️ Refactor suggestion

Consider adding validation for coordinate values.

The code assumes the latitude and longitude values will always be present. Consider adding validation to handle cases where these values might be missing.

-			$lat_address = $address_accommodation['latitude'];
-			$long_address = $address_accommodation['longitude'];
+			$lat_address = isset($address_accommodation['latitude']) ? $address_accommodation['latitude'] : '';
+			$long_address = isset($address_accommodation['longitude']) ? $address_accommodation['longitude'] : '';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

			$lat_address = isset($address_accommodation['latitude']) ? $address_accommodation['latitude'] : '';
			$long_address = isset($address_accommodation['longitude']) ? $address_accommodation['longitude'] : '';
includes/patterns/itinerary-card.php (4)

36-36: ⚠️ Potential issue

Replace placeholder icons with actual SVG icons.

I see you've used the text "Icon" as a placeholder. Let's rather use proper SVG icons for better visual presentation:

Consider replacing the icon placeholders with actual SVG icons:

-		<p class="has-senary-color has-text-color has-link-color"><strong>Icon</strong></p>
+		<div class="icon-wrapper">
+			<?php echo wp_kses( lsx_to_get_svg_icon( 'location' ), lsx_to_allowed_svg_tags() ); ?>
+		</div>

Apply similar changes for accommodation, type, drinks, and room icons using appropriate SVG icons from your icon set.

Also applies to: 52-52, 68-68, 84-84, 100-100


1-119: 🧹 Nitpick (assertive)

Enhance documentation and accessibility.

A few suggestions to improve the pattern's usability and accessibility:

  1. Add comments to explain placeholder replacement
  2. Ensure colour contrast meets WCAG guidelines
  3. Add ARIA labels where necessary

Consider adding a documentation block at the top:

/**
 * Itinerary Card Pattern
 *
 * Displays a detailed itinerary card with customizable fields:
 * - Day title
 * - Description
 * - Location
 * - Accommodation
 * - Type
 * - Drinks Basis
 * - Room Basis
 *
 * Replace placeholder text marked with <strong> tags with dynamic content.
 * Ensure colour variables are defined in your theme:
 * - primary
 * - septenary
 * - senary
 * - base
 */

Also, consider adding ARIA labels to improve accessibility:

-		<div class="wp-block-group alignwide" style="border-bottom-color:var(--wp--preset--color--primary);
+		<div class="wp-block-group alignwide" style="border-bottom-color:var(--wp--preset--color--primary);" aria-label="Itinerary day details"

2-7: ⚠️ Potential issue

Please enhance the pattern configuration.

Chap, I've noticed a few concerns with the pattern configuration:

  1. The description is empty, which makes it tricky for users to understand the pattern's purpose.
  2. The pattern category reference ($this->pattern_category) might cause issues if the class property isn't properly defined.

Consider applying these improvements:

 return array(
 	'title'         => __( 'Itinerary (list)', 'tour-operator' ),
-	'description'   => __( '', 'tour-operator' ),
+	'description'   => __( 'Displays a detailed itinerary card with location, accommodation, and other travel details.', 'tour-operator' ),
 	'categories'    => array( $this->pattern_category ),
 	'blockTypes'    => array( 'lsx/itinerary' ),
 	'templateTypes' => array( 'single' ),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

return array(
	'title'         => __( 'Itinerary (list)', 'tour-operator' ),
	'description'   => __( 'Displays a detailed itinerary card with location, accommodation, and other travel details.', 'tour-operator' ),
	'categories'    => array( $this->pattern_category ),
	'blockTypes'    => array( 'lsx/itinerary' ),
	'templateTypes' => array( 'single' ),

11-13: ⚠️ Potential issue

Fix image configuration for production use.

Right, there are several issues with the image block that need sorting:

  1. The image URL (beta.local) is pointing to a local environment
  2. The image lacks proper alt text for accessibility
  3. The hardcoded image ID (2981) might not exist in other installations

Consider using placeholder values and proper alt text:

-		<figure class="wp-block-image size-full itinerary-image"><img src="https://beta.local/wp-content/uploads/2024/09/R0I3460.jpg" alt="" class="wp-image-2981" title=""/></figure>
+		<figure class="wp-block-image size-full itinerary-image"><img src="<?php echo esc_url( plugins_url( 'assets/images/placeholder-itinerary.jpg', LSX_TO_ITINERARY_CORE ) ); ?>" alt="<?php esc_attr_e( 'Itinerary day preview image', 'tour-operator' ); ?>" class="wp-image-placeholder"/></figure>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		<div class="wp-block-column" style="flex-basis:20%"><!-- wp:image {"id":2981,"sizeSlug":"full","linkDestination":"none","className":"itinerary-image"} -->
		<figure class="wp-block-image size-full itinerary-image"><img src="<?php echo esc_url( plugins_url( 'assets/images/placeholder-itinerary.jpg', LSX_TO_ITINERARY_CORE ) ); ?>" alt="<?php esc_attr_e( 'Itinerary day preview image', 'tour-operator' ); ?>" class="wp-image-placeholder"/></figure>
		<!-- /wp:image --></div>
templates/archive.html (5)

47-51: 🧹 Nitpick (assertive)

Enhance the no-results message with helpful suggestions.

The current message is a bit light on helping users, né? Consider adding suggestions like checking spelling, trying different search terms, or browsing popular tour categories.

Here's a more helpful message:

- <p class="has-text-align-center">Sorry, there are no results matching your search at the moment. Check back later for new updates and exciting options.</p>
+ <p class="has-text-align-center">Eish! We couldn't find any tours matching your search. Try checking your spelling, using different keywords, or browse our popular tour categories. You can also contact us for personalised tour recommendations.</p>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

<!-- wp:query-no-results -->
<!-- wp:paragraph {"align":"center","placeholder":"Add text or blocks that will display when the query returns no results."} -->
<p class="has-text-align-center">Eish! We couldn't find any tours matching your search. Try checking your spelling, using different keywords, or browse our popular tour categories. You can also contact us for personalised tour recommendations.</p>
<!-- /wp:paragraph -->
<!-- /wp:query-no-results -->

53-61: ⚠️ Potential issue

Add ARIA labels to pagination controls.

The pagination controls need proper ARIA labels to support screen readers, boet. This will make the template more accessible to all users.

Add ARIA labels to the pagination controls:

- <!-- wp:query-pagination-previous /-->
+ <!-- wp:query-pagination-previous {"label":"Previous page","aria-label":"Navigate to previous page"} /-->

- <!-- wp:query-pagination-next /-->
+ <!-- wp:query-pagination-next {"label":"Next page","aria-label":"Navigate to next page"} /-->
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

<!-- wp:group {"align":"wide","style":{"spacing":{"margin":{"top":"var:preset|spacing|x-small","bottom":"var:preset|spacing|x-small"}}},"layout":{"type":"constrained"}} -->
<div class="wp-block-group alignwide" style="margin-top:var(--wp--preset--spacing--x-small);margin-bottom:var(--wp--preset--spacing--x-small)"><!-- wp:query-pagination {"paginationArrow":"chevron","align":"wide","layout":{"type":"flex","justifyContent":"space-between","flexWrap":"nowrap","orientation":"horizontal"}} -->
<!-- wp:query-pagination-previous {"label":"Previous page","aria-label":"Navigate to previous page"} /-->

<!-- wp:query-pagination-numbers /-->

<!-- wp:query-pagination-next {"label":"Next page","aria-label":"Navigate to next page"} /-->
<!-- /wp:query-pagination --></div>
<!-- /wp:group --></div>

29-62: 🛠️ Refactor suggestion

Add schema markup for tour content.

Lekker template structure overall! But adding schema markup for the tour content would really help with SEO, hey? This is especially important for tour operators in the tourism industry.

Consider wrapping the query block with schema markup:

+ <!-- wp:html -->
+ <script type="application/ld+json">
+ {
+   "@context": "https://schema.org",
+   "@type": "TouristTrip",
+   "name": "Tour Archive",
+   "description": "Collection of available tours"
+ }
+ </script>
+ <!-- /wp:html -->
<!-- wp:query -->

Committable suggestion was skipped due to low confidence.


5-15: ⚠️ Potential issue

Cover block is missing the new link capability.

Howzit! I notice the Cover block isn't implementing the new link functionality that's meant to be the main focus of this PR. The block should include the new linkUrl and linkTarget attributes to make the entire cover area clickable.

Add the link attributes to enable the clickable functionality:

- <!-- wp:cover {"useFeaturedImage":true,"dimRatio":70,"overlayColor":"secondary-900","isUserOverlayColor":true,"minHeight":300,"minHeightUnit":"px","metadata":{"name":"Hero"},"align":"full","style":{"spacing":{"blockGap":"0","margin":{"top":"0","bottom":"0"}}}} -->
+ <!-- wp:cover {"useFeaturedImage":true,"dimRatio":70,"overlayColor":"secondary-900","isUserOverlayColor":true,"minHeight":300,"minHeightUnit":"px","metadata":{"name":"Hero"},"align":"full","style":{"spacing":{"blockGap":"0","margin":{"top":"0","bottom":"0"}}},"linkUrl":"","linkTarget":"_self"} -->
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

<!-- wp:cover {"useFeaturedImage":true,"dimRatio":70,"overlayColor":"secondary-900","isUserOverlayColor":true,"minHeight":300,"minHeightUnit":"px","metadata":{"name":"Hero"},"align":"full","style":{"spacing":{"blockGap":"0","margin":{"top":"0","bottom":"0"}}},"linkUrl":"","linkTarget":"_self"} -->
<div class="wp-block-cover alignfull" style="margin-top:0;margin-bottom:0;min-height:300px"><span aria-hidden="true" class="wp-block-cover__background has-secondary-900-background-color has-background-dim-70 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:group {"align":"full","layout":{"type":"constrained"}} -->
<div class="wp-block-group alignfull"><!-- wp:group {"style":{"spacing":{"padding":{"top":"10px","bottom":"10px"}},"border":{"bottom":{"color":"var:preset|color|primary-200","width":"2px"},"top":[],"right":[],"left":[]},"typography":{"fontStyle":"normal","fontWeight":"600"}},"fontSize":"large","layout":{"type":"default"}} -->
<div class="wp-block-group has-large-font-size" style="border-bottom-color:var(--wp--preset--color--primary-200);border-bottom-width:2px;padding-top:10px;padding-bottom:10px;font-style:normal;font-weight:600"><!-- wp:query-title {"type":"archive","textAlign":"center","showPrefix":false} /--></div>
<!-- /wp:group -->

<!-- wp:paragraph {"align":"center","metadata":{"name":"Tagline"},"style":{"elements":{"link":{"color":{"text":"var:preset|color|primary-200"}}}},"textColor":"primary-200","fontSize":"small"} -->
<p class="has-text-align-center has-primary-200-color has-text-color has-link-color has-small-font-size"></p>
<!-- /wp:paragraph --></div>
<!-- /wp:group --></div></div>
<!-- /wp:cover -->

32-44: ⚠️ Potential issue

Standardise link behaviour across card elements.

Sharp! I've spotted that the featured image opens in a new tab while the title link doesn't. This inconsistency might confuse users, hey? We should align the link behaviour across all clickable elements in the card.

Either remove the linkTarget="_blank" from the featured image or apply it to the title as well:

- <!-- wp:post-featured-image {"isLink":true,"aspectRatio":"3/2","linkTarget":"_blank"
+ <!-- wp:post-featured-image {"isLink":true,"aspectRatio":"3/2","linkTarget":"_self"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

<!-- wp:group {"metadata":{"name":"Archive Card"},"style":{"spacing":{"blockGap":"0px","padding":{"top":"0px","bottom":"0px","left":"0px","right":"0px"}},"border":{"radius":"8px"}},"backgroundColor":"base","layout":{"type":"constrained"}} -->
<div class="wp-block-group has-base-background-color has-background" style="border-radius:8px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px"><!-- wp:post-featured-image {"isLink":true,"aspectRatio":"3/2","linkTarget":"_self","style":{"spacing":{"padding":{"top":"0","bottom":"0"},"margin":{"top":"0","bottom":"0"}},"border":{"radius":{"topLeft":"8px","topRight":"8px"}}}} /-->

<!-- wp:group {"metadata":{"name":"Content"},"style":{"spacing":{"margin":{"top":"0","bottom":"0"},"padding":{"top":"10px","bottom":"0px","left":"10px","right":"10px"}},"dimensions":{"minHeight":"97px"}},"layout":{"type":"constrained"}} -->
<div class="wp-block-group" style="min-height:97px;margin-top:0;margin-bottom:0;padding-top:10px;padding-right:10px;padding-bottom:0px;padding-left:10px"><!-- wp:group {"metadata":{"name":"Title"},"className":"center-vertically","style":{"dimensions":{"minHeight":"3rem"},"spacing":{"padding":{"top":"5px"}},"border":{"bottom":{"color":"var:preset|color|primary","width":"2px"},"top":[],"right":[],"left":[]}},"layout":{"type":"constrained"}} -->
<div class="wp-block-group center-vertically" style="border-bottom-color:var(--wp--preset--color--primary);border-bottom-width:2px;min-height:3rem;padding-top:5px"><!-- wp:post-title {"textAlign":"center","level":3,"isLink":true,"style":{"spacing":{"padding":{"top":"0","bottom":"0"},"margin":{"top":"0","bottom":"0"}}},"fontSize":"small"} /--></div>
<!-- /wp:group -->

<!-- wp:group {"metadata":{"name":"Text Content"},"style":{"spacing":{"padding":{"right":"10px","left":"10px","top":"0px","bottom":"0px"}},"elements":{"link":{"color":{"text":"var:preset|color|septenary"}}}},"textColor":"septenary","layout":{"type":"constrained"}} -->
<div class="wp-block-group has-septenary-color has-text-color has-link-color" style="padding-top:0px;padding-right:10px;padding-bottom:0px;padding-left:10px"><!-- wp:post-excerpt {"moreText":"View More","excerptLength":40,"style":{"elements":{"link":{"color":{"text":"var:preset|color|contrast"}}}},"textColor":"contrast"} /--></div>
<!-- /wp:group --></div>
<!-- /wp:group --></div>
<!-- /wp:group -->
templates/archive-destination.html (5)

49-53: 🧹 Nitpick (assertive)

Improve the no-results message.

The current no-results message could be more helpful by:

  1. Suggesting alternative actions
  2. Providing contact information
-<p class="has-text-align-center">Unfortunately, there are no destinations listed at the moment. Please check back soon as we regularly update our offerings.</p>
+<p class="has-text-align-center">We're currently updating our destination listings. In the meantime, please contact our travel consultants at [email protected] to discuss your travel plans, or explore our available tours.</p>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

<!-- wp:query-no-results -->
<!-- wp:paragraph {"align":"center","placeholder":"Add text or blocks that will display when the query returns no results."} -->
<p class="has-text-align-center">We're currently updating our destination listings. In the meantime, please contact our travel consultants at [email protected] to discuss your travel plans, or explore our available tours.</p>
<!-- /wp:paragraph -->
<!-- /wp:query-no-results -->

11-13: ⚠️ Potential issue

Empty paragraph block needs fallback content.

The paragraph block with tagline binding is empty. Consider adding fallback content for when the tagline metadata is not available.

-<p class="has-text-align-center has-primary-200-color has-text-color has-link-color has-small-font-size is-style-subheading-3"></p>
+<p class="has-text-align-center has-primary-200-color has-text-color has-link-color has-small-font-size is-style-subheading-3">Explore our handpicked destinations</p>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

<!-- wp:paragraph {"align":"center","metadata":{"bindings":{"content":{"source":"lsx/post-meta","args":{"key":"tagline"}}}},"className":"has-text-align-center has-primary-200-color has-text-color has-link-color has-small-font-size is-style-subheading-3","style":{"elements":{"link":{"color":{"text":"var:preset|color|primary-200"}}}},"textColor":"primary-200"} -->
<p class="has-text-align-center has-primary-200-color has-text-color has-link-color has-small-font-size is-style-subheading-3">Explore our handpicked destinations</p>
<!-- /wp:paragraph --></div>

5-15: 🧹 Nitpick (assertive)

Consider accessibility improvements for the hero section.

The hero section could benefit from the following improvements:

  1. The dimRatio of 70 might affect text readability
  2. Missing aria-label for the cover block to describe the featured image
-<div class="wp-block-cover alignfull" style="margin-top:0;margin-bottom:0;min-height:300px">
+<div class="wp-block-cover alignfull" style="margin-top:0;margin-bottom:0;min-height:300px" aria-label="Featured destination image">

Committable suggestion was skipped due to low confidence.


31-46: 🛠️ Refactor suggestion

Enhance destination card accessibility and UX.

The destination card implementation could be improved:

  1. The card should be fully clickable, not just the image and title
  2. Opening links in new tabs (_blank) requires a warning for users

Consider implementing the Cover block's new link capability from this PR to make the entire card clickable:

-<!-- wp:post-featured-image {"isLink":true,"aspectRatio":"3/2","linkTarget":"_blank"
+<!-- wp:post-featured-image {"aspectRatio":"3/2"

Then wrap the entire card content with a link using the new Cover block link attributes.

Committable suggestion was skipped due to low confidence.


55-63: 🧹 Nitpick (assertive)

Consider pagination improvements.

The pagination implementation could benefit from:

  1. Adding aria-labels for better screen reader support
  2. Including current page information
-<!-- wp:query-pagination {"paginationArrow":"chevron","align":"wide"
+<!-- wp:query-pagination {"paginationArrow":"chevron","align":"wide","aria-label":"Destination pages navigation"

Committable suggestion was skipped due to low confidence.

includes/template-tags/maps.php (1)

382-382: 🛠️ Refactor suggestion

Consider improving the conditional logic

The condition checking could be simplified to improve readability.

Consider refactoring the condition to:

-if ( false !== $location && '' !== $location && is_array( $location ) && isset( $location['latitude'] ) && '' !== $location['latitude'] ) {
+if ( ! empty( $location ) && is_array( $location ) && ! empty( $location['latitude'] ) ) {

Similarly for line 397:

-else if ( is_array( $location ) && ( ( isset( $location['latitude'] ) && '' !== $location['latitude'] ) || ( isset( $location['kml'] ) && '' !== $location['kml'] ) ) ) {
+else if ( is_array( $location ) && ( ! empty( $location['latitude'] ) || ! empty( $location['kml'] ) ) ) {

Also applies to: 397-397

templates/archive-tour.html (5)

45-47: ⚠️ Potential issue

Add accessibility attributes to icons

Yoh! The price and duration icons lack proper accessibility attributes.

Add descriptive alt text and ARIA labels:

-<figure class="wp-block-image size-large is-resized"><img src="https://tour-operator.lsx.design/wp-content/uploads/2024/09/from-price-TO-icon-black-20px-1.png" alt="" style="width:20px;height:auto"/></figure>
+<figure class="wp-block-image size-large is-resized"><img src="https://tour-operator.lsx.design/wp-content/uploads/2024/09/from-price-TO-icon-black-20px-1.png" alt="Price indicator icon" aria-label="Tour price" style="width:20px;height:auto"/></figure>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

<div class="wp-block-group"><!-- wp:image {"width":"20px","height":"auto","sizeSlug":"large","metadata":{"name":"From Price Icon"}} -->
<figure class="wp-block-image size-large is-resized"><img src="https://tour-operator.lsx.design/wp-content/uploads/2024/09/from-price-TO-icon-black-20px-1.png" alt="Price indicator icon" aria-label="Tour price" style="width:20px;height:auto"/></figure>
<!-- /wp:image -->

89-93: 🧹 Nitpick (assertive)

Enhance no-results message with user guidance

The current message is good, but we can make it more helpful for users, hey?

Consider adding contact information or search suggestions:

-<p class="has-text-align-center">Unfortunately, there are no tours listed at the moment. Please check back soon as we regularly update our offerings.</p>
+<p class="has-text-align-center">Unfortunately, there are no tours listed at the moment. Please check back soon as we regularly update our offerings. You can also contact our team at <a href="mailto:[email protected]">[email protected]</a> for custom tour arrangements.</p>

Committable suggestion was skipped due to low confidence.


96-102: 🧹 Nitpick (assertive)

Add ARIA labels to pagination controls

Let's make the pagination more accessible, hey?

Add descriptive ARIA labels:

-<!-- wp:query-pagination {"paginationArrow":"chevron","align":"wide","layout":{"type":"flex","justifyContent":"space-between"}} -->
+<!-- wp:query-pagination {"paginationArrow":"chevron","align":"wide","layout":{"type":"flex","justifyContent":"space-between"},"aria-label":"Tour archive navigation"} -->
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

<div class="wp-block-group alignwide" style="margin-top:var(--wp--preset--spacing--x-small);margin-bottom:var(--wp--preset--spacing--x-small);padding-top:var(--wp--preset--spacing--x-small);padding-bottom:var(--wp--preset--spacing--x-small)"><!-- wp:query-pagination {"paginationArrow":"chevron","align":"wide","layout":{"type":"flex","justifyContent":"space-between"},"aria-label":"Tour archive navigation"} -->
<!-- wp:query-pagination-previous /-->

<!-- wp:query-pagination-numbers /-->

<!-- wp:query-pagination-next /-->
<!-- /wp:query-pagination --></div>

32-33: 🛠️ Refactor suggestion

Optimize query parameters for performance

Shame! The query is fetching 9 posts per page with 3 pages, which might impact performance on slower connections.

Consider implementing lazy loading:

-"perPage":"9","pages":"3"
+"perPage":"6","pages":"0"

Committable suggestion was skipped due to low confidence.


5-6: ⚠️ Potential issue

Replace hardcoded image URL with dynamic asset handling

Blimey! The hardcoded URL https://tour-operator.lsx.design/wp-content/uploads/2024/10/tours-archive-banner-image.png could break if the site URL changes or if the image is moved.

Consider using WordPress's media handling functions or block editor's media library integration:

-"url":"https://tour-operator.lsx.design/wp-content/uploads/2024/10/tours-archive-banner-image.png"
+"url":{"source":"media-library","id":61304}

Committable suggestion was skipped due to low confidence.

includes/classes/legacy/class-admin.php (2)

91-91: 🛠️ Refactor suggestion

Improve taxonomy condition check

Eish! The condition could be more idiomatic and clearer:

  1. Use empty() or is_array() instead of comparing with false
  2. Consider extracting taxonomy registration logic to a separate method
-			if ( false !== $this->taxonomies ) {
+			if ( ! empty( $this->taxonomies ) ) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

			if ( ! empty( $this->taxonomies ) ) {

29-48: ⚠️ Potential issue

Strengthen property declarations with type hints and default values

Howzit! The new properties need some attention to prevent potential issues:

  1. They should have default values to prevent undefined notices
  2. Consider using PHP type hints for better type safety
  3. The visibility should be protected since they're only used internally

Here's how to improve the declarations:

-    public $connections;
-    public $single_fields;
-    public $taxonomies;
+    protected array $connections = [];
+    protected array $single_fields = [];
+    protected array $taxonomies = [];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	/**
	 * Holds the post_type connection keys
	 *
	 * @var array
	 */
    protected array $connections = [];

	/**
	 * Holds the array of fields needed for the indexing and search
	 *
	 * @var array
	 */
    protected array $single_fields = [];

	/**
	 * Holds the array of taxonomies.
	 *
	 * @var array
	 */
    protected array $taxonomies = [];
assets/js/src/custom.js (1)

142-142: ⚠️ Potential issue

Internationalise the hardcoded strings, boet!

The hardcoded strings "Read More" and "Lees verder" should be properly internationalised using WordPress i18n functions to support multiple languages properly.

Here's how to fix it:

-			if ( 'Read More' === $( this ).html() || 'Lees verder' === $( this ).html() ) {
+			var readMoreTexts = [
+				wp.i18n.__( 'Read More', 'tour-operator' ),
+				wp.i18n.__( 'Lees verder', 'tour-operator' )
+			];
+			if ( readMoreTexts.includes( $( this ).html() ) ) {

Committable suggestion was skipped due to low confidence.

includes/classes/legacy/class-maps.php (1)

167-168: 🛠️ Refactor suggestion

Define coordinate constants instead of using magic numbers

The default coordinates and validation checks use hard-coded values. Consider extracting these into class constants for better maintainability.

 class Maps {
+    /**
+     * Default map coordinates for Cape Town
+     */
+    const DEFAULT_LATITUDE = '-33.914482';
+    const DEFAULT_LONGITUDE = '18.3758789';
+
     // ... existing code ...
 
     public function map_output( $post_id = false, $args = array() ) {
         $defaults = array(
-            'latitude' => '-33.914482',
-            'longitude' => '18.3758789',
+            'latitude' => self::DEFAULT_LATITUDE,
+            'longitude' => self::DEFAULT_LONGITUDE,
             // ... other defaults ...
         );
         
         // ... existing code ...
         
-        if ( ( '-33.914482' !== $args['latitude'] && '18.3758789' !== $args['longitude'] ) || false !== $args['search'] || 'cluster' === $args['type'] || 'route' === $args['type'] ) {
+        if ( ( self::DEFAULT_LATITUDE !== $args['latitude'] && self::DEFAULT_LONGITUDE !== $args['longitude'] ) || false !== $args['search'] || 'cluster' === $args['type'] || 'route' === $args['type'] ) {

Also applies to: 205-205

changelog.md (2)

3-10: 🧹 Nitpick (assertive)

Consider enhancing the 2.0.0 version entry

As this is a major version bump with breaking changes, please consider:

  1. Adding a placeholder date for the release (e.g. [Unreleased] or specific target date)
  2. Including a migration guide or upgrade instructions for users moving from UIX vendor library to the new settings system
🧰 Tools
🪛 Markdownlint

6-6: (PR #332)[https://github.com//pull/332]
Reversed link syntax

(MD011, no-reversed-links)


7-7: (PR #332)[https://github.com//pull/332]
Reversed link syntax

(MD011, no-reversed-links)


5-5: Expected: 1; Actual: 0; Below
Headings should be surrounded by blank lines

(MD022, blanks-around-headings)


9-9: Expected: 1; Actual: 0; Below
Headings should be surrounded by blank lines

(MD022, blanks-around-headings)


6-6: null
Lists should be surrounded by blank lines

(MD032, blanks-around-lists)


10-10: null
Lists should be surrounded by blank lines

(MD032, blanks-around-lists)

🪛 GitHub Check: Codacy Static Code Analysis

[notice] 6-6: changelog.md#L6
Lists should be surrounded by blank lines


5-7: ⚠️ Potential issue

Fix markdown formatting issues

There are several markdown syntax issues that should be addressed:

Apply these fixes:

 ## [[2.0.0]](https://github.com/lightspeeddevelopment/tour-operator/releases/tag/2.0.0) - IN DEVELOPMENT

 ### Removed
+
-UIX vendor library handling the TO Settings and refactored the settings code - (PR #332)[https://github.com/lightspeedwp/tour-operator/pull/332]
-Various settings which are now handled by Block and Site Editor options. - (PR #332)[https://github.com/lightspeedwp/tour-operator/pull/332]
+- UIX vendor library handling the TO Settings and refactored the settings code - [PR #332](https://github.com/lightspeedwp/tour-operator/pull/332)
+- Various settings which are now handled by Block and Site Editor options - [PR #332](https://github.com/lightspeedwp/tour-operator/pull/332)
+
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

### Removed

- UIX vendor library handling the TO Settings and refactored the settings code - [PR #332](https://github.com/lightspeedwp/tour-operator/pull/332)
- Various settings which are now handled by Block and Site Editor options - [PR #332](https://github.com/lightspeedwp/tour-operator/pull/332)

🧰 Tools
🪛 Markdownlint

6-6: (PR #332)[https://github.com//pull/332]
Reversed link syntax

(MD011, no-reversed-links)


7-7: (PR #332)[https://github.com//pull/332]
Reversed link syntax

(MD011, no-reversed-links)


5-5: Expected: 1; Actual: 0; Below
Headings should be surrounded by blank lines

(MD022, blanks-around-headings)


6-6: null
Lists should be surrounded by blank lines

(MD032, blanks-around-lists)

🪛 GitHub Check: Codacy Static Code Analysis

[notice] 6-6: changelog.md#L6
Lists should be surrounded by blank lines

includes/template-tags/helpers.php (1)

302-304: 🛠️ Refactor suggestion

Consider making the array separator configurable

While the array handling is functional, using a hardcoded comma separator might not suit all use cases. Consider making the separator configurable.

Apply this enhancement:

-			if ( is_array( $value ) ) {
-				$value = implode( ',', $value );
-			}
+			if ( is_array( $value ) ) {
+				$separator = apply_filters( 'lsx_to_custom_field_array_separator', ', ' );
+				$value = implode( $separator, $value );
+			}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

			if ( is_array( $value ) ) {
				$separator = apply_filters( 'lsx_to_custom_field_array_separator', ', ' );
				$value = implode( $separator, $value );
			}
includes/classes/legacy/class-tour-operator.php (2)

983-983: ⚠️ Potential issue

Reconsider commenting out theme compatibility notice

Commenting out the theme compatibility notice could lead to silent failures when using incompatible themes. Consider implementing a less intrusive notification method rather than removing it entirely.

Apply this diff to implement a less intrusive notice:

-//add_action( 'admin_notices', array( $this, 'compatible_theme_notice' ), 199 );
+add_action( 'admin_notices', array( $this, 'compatible_theme_notice' ), 199, 1 );

Committable suggestion was skipped due to low confidence.


183-183: 💡 Codebase verification

Data migration required for option key change

The change from '_lsx-to_settings' to 'lsx_to_settings' requires attention as there's no automatic migration code present. This could lead to settings loss for existing installations.

  • Add migration code in includes/classes/legacy/class-tour-operator.php to transfer data from the old option key
  • Consider adding a fallback to check the old option key if the new one is empty
  • Update any documentation to reflect this change for site administrators
🔗 Analysis chain

Verify data migration for existing installations

The option key change from '_lsx-to_settings' to 'lsx_to_settings' could affect existing installations. Ensure there's a migration strategy in place for existing data.


Let me gather more information to verify if there's any migration code or if this is a breaking change.


Let me check one more thing to see if there's any automatic data transfer or if the old option is still being used as a fallback.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if any files still reference the old option key
# Test: Search for references to the old option key
rg "_lsx-to_settings"

Length of output: 163


Script:

#!/bin/bash
# Check for any migration or upgrade code
rg -i "upgrade|migration|migrate" includes/classes/

# Check for any other references to lsx_to_settings
rg "lsx_to_settings"

# Check for any activation hooks that might handle migration
ast-grep --pattern 'register_activation_hook($$$)'

Length of output: 551


Script:

#!/bin/bash
# Check the context around the option usage to see if there's any fallback logic
rg -B 5 -A 5 "lsx_to_settings" includes/classes/legacy/class-tour-operator.php

# Check for any references to get_option in the same file
ast-grep --pattern 'get_option($_)'

Length of output: 375

includes/layout.php (1)

83-83: 💡 Codebase verification

Change from 'medium' to 'lsx-thumbnail-wide' size is recommended

The codebase analysis reveals that:

  • All other template files consistently use 'lsx-thumbnail-wide' for archive entries
  • The 'lsx_thumbnail' function is used with 'lsx-thumbnail-wide' in multiple templates
  • The size can be filtered via 'lsx_thumbnail_size' filter
  • The current change to 'medium' creates inconsistency with the established pattern

To maintain visual consistency across the plugin, the thumbnail size should match the 'lsx-thumbnail-wide' size used in other archive templates.

🔗 Analysis chain

Verify the impact of thumbnail size change.

The change from 'lsx-thumbnail-square' to 'medium' size for team entries might affect the layout consistency. The 'medium' size might not maintain the same aspect ratio as the custom square size.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if there are any CSS rules or image size definitions that depend on the square thumbnail size

# Search for CSS rules related to team thumbnails
rg -l "lsx-thumbnail-square|team.*thumbnail" "assets/css/"

# Search for image size registrations
rg "add_image_size.*lsx-thumbnail-square" "includes/"

Length of output: 142


Script:

#!/bin/bash
# Let's check the actual CSS rules and any other thumbnail size usages

# Check CSS rules in the style.css file
rg -A 5 -B 5 "thumbnail" "assets/css/style.css"

# Check for other thumbnail function calls
rg "lsx_thumbnail" --type php

# Check for image size registrations in the plugin
rg "add_image_size" --type php

# Check for thumbnail size filters
rg "add_filter.*thumbnail" --type php

Length of output: 1717

assets/js/blocks/linked-cover.js (3)

52-54: ⚠️ Potential issue

Localise all user-facing strings.

To support internationalisation and ensure users can translate your plugin into different languages, please wrap all user-facing strings with translation functions like wp.i18n.__.

Apply this diff to localise the strings:

- { title: 'Cover Link Settings', initialOpen: true },
+ { title: wp.i18n.__( 'Cover Link Settings' ), initialOpen: true },

...

- label: 'Link URL',
+ label: wp.i18n.__( 'Link URL' ),

...

- label: 'Open link in a new tab',
+ label: wp.i18n.__( 'Open link in a new tab' ),

Also applies to: 61-62


86-86: ⚠️ Potential issue

Add rel="noopener noreferrer" to external links opening in a new tab.

When linkTarget is set to '_blank', it's recommended to include rel="noopener noreferrer" on the <a> tag to mitigate security risks associated with the window.opener property.

Apply this diff to add the rel attribute conditionally:

- { href: linkUrl, target: linkTarget },
+ { 
+   href: linkUrl, 
+   target: linkTarget, 
+   rel: linkTarget === '_blank' ? 'noopener noreferrer' : undefined 
+ },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

            { 
              href: linkUrl, 
              target: linkTarget, 
              rel: linkTarget === '_blank' ? 'noopener noreferrer' : undefined 
            },

53-59: 🛠️ Refactor suggestion

Use URLInput component for a better URL input experience.

Consider replacing TextControl with URLInput to provide URL validation and autocomplete, enhancing the user experience when entering URLs.

Apply this diff to utilise URLInput:

- createElement(TextControl, {
-     label: 'Link URL',
-     value: linkUrl,
-     onChange: function (value) {
-         setAttributes({ linkUrl: value });
-     }
- }),
+ createElement(URLInput, {
+     label: wp.i18n.__( 'Link URL' ),
+     value: linkUrl,
+     onChange: function (url, post) {
+         setAttributes({ linkUrl: url });
+     }
+ }),

Ensure you import URLInput at the beginning of your file:

+ const { URLInput } = wp.blockEditor || wp.editor;

Committable suggestion was skipped due to low confidence.

includes/classes/admin/class-setup.php (6)

8-8: ⚠️ Potential issue

Provide a valid URL for the @link annotation

The @link tag in the file header is empty. Including a valid URL enhances documentation and assists developers in finding related resources.


137-137: 🛠️ Refactor suggestion

⚠️ Potential issue

Align array double arrows as per coding standards

Static analysis tools have detected alignment issues in your array declarations at lines 137 and 139. Ensure that the array double arrows are aligned consistently according to the coding standards.

Apply this diff to correct the alignment:

  $cmb[ $metabox_counter ] = new_cmb2_box( array(
      'id'            => 'lsx_to_metabox_' . $post_type . '_' . $metabox_counter,
-     'title'         => $field['name'],
+     'title'        => $field['name'],
      'object_types'  => array( $post_type ), // Post type
-     'context'       => 'normal',
+     'context'      => 'normal',
      'priority'      => 'high',
      'show_names'    => true,
  ) );

Also applies to: 139-139

🧰 Tools
🪛 GitHub Check: CodeFactor

[notice] 137-137: includes/classes/admin/class-setup.php#L137
Array double arrow not aligned correctly; expected 8 space(s) between "'title'" and double arrow, but found 9. (WordPress.Arrays.MultipleStatementAlignment-[fixable])


72-72: ⚠️ Potential issue

Address code formatting issues

Static analysis tools have reported code formatting issues on lines 72 and 77. Adjust the spacing and add blank lines as required to adhere to the coding standards.

Apply this diff to fix the formatting:

  if ( ! isset( self::$instance ) ) {
      self::$instance = new self();
-    }
+    }

+   // Add a blank line before the closing brace
   return self::$instance;
 }

Also applies to: 77-77

🧰 Tools
🪛 GitHub Check: CodeFactor

[warning] 72-72: includes/classes/admin/class-setup.php#L72
Expected 0 spaces before closing bracket; 1 found. (Squiz.WhiteSpace.ControlStructureSpacing-[fixable])


66-68: ⚠️ Potential issue

Correct the @return annotation in the init method

The @return annotation incorrectly specifies Tour_Operator as the return type. It should be Setup, as the method returns an instance of the Setup class.

Apply this diff to fix the annotation:

-	 * @return  Tour_Operator  A single instance
+	 * @return  Setup  A single instance
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	 * @since 1.1.0
	 * @return  Setup  A single instance
	 */

30-36: 🛠️ Refactor suggestion

Remove unused property $options

The property $options is declared but not utilised anywhere in the class. Removing unused properties improves code clarity and maintainability.

Apply this diff to remove the unused property:

-	/**
-	 * Holds the tour operators options
-	 *
-	 * @since   1.1.0
-	 * @var     array
-	 */
-	public $options;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.



117-155: ⚠️ Potential issue

Add checks for undefined $fields and $fields['fields']

Before iterating over $fields['fields'], ensure that $fields is defined and that the 'fields' key exists to prevent potential errors if custom fields are not returned or the included file does not exist.

Apply this diff to add the necessary checks:

  foreach ( $this->post_types as $post_type ) {
      $fields = $this->get_custom_fields( $post_type );

+     if ( empty( $fields ) || ! isset( $fields['fields'] ) ) {
+         continue;
+     }

      $metabox_counter = 1;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		$cmb = [];
		foreach ( $this->post_types as $post_type ) {
			$fields = $this->get_custom_fields( $post_type );

			if ( empty( $fields ) || ! isset( $fields['fields'] ) ) {
				continue;
			}

			$metabox_counter = 1;
			$cmb[ $metabox_counter ] = new_cmb2_box( array(
				'id'            => 'lsx_to_metabox_' . $post_type . '_' . $metabox_counter,
				'title'         => $fields['title'],
				'object_types'  => array( $post_type ), // Post type
				'context'       => 'normal',
				'priority'      => 'high',
				'show_names'    => true,
			) );

			foreach ( $fields['fields'] as $field ) {

				if ( 'title' === $field['type'] ) {
					$metabox_counter++;
					$cmb[ $metabox_counter ] = new_cmb2_box( array(
						'id'            => 'lsx_to_metabox_' . $post_type . '_' . $metabox_counter,
						'title'         => $field['name'],
						'object_types'  => array( $post_type ), // Post type
						'context'       => 'normal',
						'priority'      => 'high',
						'show_names'    => true,
					) );
					continue;
				}

				/**
				 * Fixes for the extensions
				 */
				if ( 'post_select' === $field['type'] || 'post_ajax_search' === $field['type'] ) {
					$field['type'] = 'pw_multiselect';
				}

				$cmb[ $metabox_counter ]->add_field( $field );
			}
		}
🧰 Tools
🪛 GitHub Check: CodeFactor

[notice] 139-139: includes/classes/admin/class-setup.php#L139
Array double arrow not aligned correctly; expected 6 space(s) between "'context'" and double arrow, but found 7. (WordPress.Arrays.MultipleStatementAlignment-[fixable])


[notice] 137-137: includes/classes/admin/class-setup.php#L137
Array double arrow not aligned correctly; expected 8 space(s) between "'title'" and double arrow, but found 9. (WordPress.Arrays.MultipleStatementAlignment-[fixable])

includes/classes/legacy/class-tour.php (4)

233-235: ⚠️ Potential issue

Ensure 'editor_height' is an integer, not a string

The 'editor_height' option should be an integer value, not a string. This ensures that the editor height is properly set.

Apply this diff:

-'editor_height' => '100',
+'editor_height' => 100,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

			'options' => array(
				'editor_height' => 100,
			),

243-245: ⚠️ Potential issue

Ensure 'editor_height' is an integer, not a string

The 'editor_height' option should be an integer value, not a string. This ensures that the editor height is properly set.

Apply this diff:

-'editor_height' => '100',
+'editor_height' => 100,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

			'options' => array(
				'editor_height' => 100,
			),

165-165: ⚠️ Potential issue

Replace curly apostrophe to prevent encoding issues

The description contains a curly apostrophe in 'won’t', which can cause encoding issues. It's recommended to replace it with a straight apostrophe.

Apply this diff to fix the apostrophe:

-'desc' => esc_html__( 'Add an optional tagline for the itinerary entry (if left blank, it won’t display).', 'tour-operator' ),
+'desc' => esc_html__( 'Add an optional tagline for the itinerary entry (if left blank, it won't display).', 'tour-operator' ),

Committable suggestion was skipped due to low confidence.


303-303: ⚠️ Potential issue

Remove extra space before closing bracket

There's an extra space before the closing bracket in the if statement on line 303, as flagged by the static analysis tool.

Apply the following diff to fix the whitespace issue:

-if ( is_object( $tour_operator ) && isset( $tour_operator->options['currency'] ) && ! empty( $tour_operator->options['currency'] ) ) {
+if ( is_object( $tour_operator ) && isset( $tour_operator->options['currency'] ) && ! empty( $tour_operator->options['currency'] )) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

			if ( is_object( $tour_operator ) && isset( $tour_operator->options['currency'] ) && ! empty( $tour_operator->options['currency'] )) {
🧰 Tools
🪛 GitHub Check: CodeFactor

[warning] 303-303: includes/classes/legacy/class-tour.php#L303
Expected 0 spaces before closing bracket; 1 found. (Squiz.WhiteSpace.ControlStructureSpacing-[fixable])

templates/archive-accommodation.html (2)

46-47: ⚠️ Potential issue

Add descriptive alt text to images for better accessibility

The images at lines 46-47, 62-63, and 78-79 have empty alt attributes. Providing meaningful alt text will improve accessibility for users relying on screen readers.

Apply this diff to add appropriate alt text:

-Line 46:
-<img src="https://tour-operator.lsx.design/wp-content/uploads/2024/09/from-price-TO-icon-black-20px.png" alt="" style="object-fit:cover"/>
+<img src="https://tour-operator.lsx.design/wp-content/uploads/2024/09/from-price-TO-icon-black-20px.png" alt="From Price Icon" style="object-fit:cover"/>

-Line 62:
-<img src="https://tour-operator.lsx.design/wp-content/uploads/2024/09/accommodation-type-TO-icon-black-20px.png" alt="" style="object-fit:cover"/>
+<img src="https://tour-operator.lsx.design/wp-content/uploads/2024/09/accommodation-type-TO-icon-black-20px.png" alt="Accommodation Type Icon" style="object-fit:cover"/>

-Line 78:
-<img src="https://tour-operator.lsx.design/wp-content/uploads/2024/09/TO-accommodation-rooms-icon-black-52px.png" alt="" style="width:20px"/>
+<img src="https://tour-operator.lsx.design/wp-content/uploads/2024/09/TO-accommodation-rooms-icon-black-52px.png" alt="Number of Rooms Icon" style="width:20px"/>

Also applies to: 62-63, 78-79


12-13: 🧹 Nitpick (assertive)

Remove empty paragraph to streamline the markup

There's an empty paragraph at lines 12-13 that doesn't serve a purpose and can be removed to clean up the code.

Apply this diff to remove the unnecessary paragraph:

-<!-- wp:paragraph {"align":"center","metadata":{"name":"Tagline"},"style":{"elements":{"link":{"color":{"text":"var:preset|color|primary-200"}}}},"textColor":"primary-200","fontSize":"small"} -->
-<p class="has-text-align-center has-primary-200-color has-text-color has-link-color has-small-font-size"></p>
-<!-- /wp:paragraph -->
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

</div>
includes/functions.php (1)

347-361: ⚠️ Potential issue

Potential undefined offset when accessing $itinerary_accommodation[0]

In the function lsx_to_itinerary_accommodation_type, there is a risk of accessing $itinerary_accommodation[0] when $itinerary_accommodation is an empty array, which could lead to an undefined offset notice.

Apply this diff to ensure the array is not empty before accessing the first element:

 if ( ! is_array( $itinerary_accommodation ) ) {
     $itinerary_accommodation = array( $itinerary_accommodation );
 }
+if ( ! empty( $itinerary_accommodation ) ) {
     $return = get_the_term_list( $itinerary_accommodation[0], 'accommodation-type', $before, ', ', $after );
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

function lsx_to_itinerary_accommodation_type( $before = '', $after = '', $echo = true ) {
	global $tour_itinerary;
	$return = '';

	if ( $tour_itinerary && $tour_itinerary->has_itinerary && ! empty( $tour_itinerary->itinerary ) && ! empty( $tour_itinerary->itinerary['accommodation_to_tour'] ) ) {
		$itinerary_accommodation = $tour_itinerary->itinerary['accommodation_to_tour'];
		if ( ! is_array( $itinerary_accommodation ) ) {
			$itinerary_accommodation = array( $itinerary_accommodation );
		}
		if ( ! empty( $itinerary_accommodation ) ) {
			$return = get_the_term_list( $itinerary_accommodation[0], 'accommodation-type', $before, ', ', $after );
		}
		if ( true === $echo ) {
			echo wp_kses_post( $return );
		}
	}
	return $return;
includes/classes/admin/class-settings.php (8)

533-537: ⚠️ Potential issue

Sanitise user input from $_POST data before processing.

User inputs from $_POST should be sanitised to prevent security vulnerabilities. Use appropriate sanitisation functions based on the expected data types.

Apply this diff to sanitise the input:

             if ( isset( $_POST[ $key ] ) ) {
-                $save = $_POST[ $key ];
+                $save = sanitize_text_field( $_POST[ $key ] );
             } else if ( isset( $field['default'] ) ) {
                 $save = $field['default'];
             }

...

             if ( isset( $_POST[ $tab_index . '_' . $key ] ) ) {
-                $save = $_POST[ $tab_index . '_' . $key ];
+                $save = sanitize_text_field( $_POST[ $tab_index . '_' . $key ] );
             } else if ( isset( $field['default'] ) ) {
                 $save = $field['default'];
             }

Also applies to: 554-558


83-84: 🧹 Nitpick (assertive)

Remove unnecessary initialisation of '$settings' variable.

The variable '$settings' is initialised to an empty array but is immediately overwritten. You can remove the redundant initialisation.

Apply this diff to remove the unnecessary line:

-        $settings = array();
         $settings = include( LSX_TO_PATH . 'includes/constants/settings-fields.php' );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		$settings = include( LSX_TO_PATH . 'includes/constants/settings-fields.php' );

310-311: ⚠️ Potential issue

Correct syntax error in 'default' case of 'switch' statement.

In the 'switch' statement, the 'default' case should be followed by a colon ':' instead of a semicolon ';'.

Apply this diff to fix the syntax:

-                    default;
+                    default:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

					default:
				}

343-356: ⚠️ Potential issue

Properly escape variables when outputting HTML in 'select_field' method.

Variables such as '$field_id', '$params['label']', and option values should be properly escaped using 'esc_attr' and 'esc_html' functions to prevent XSS attacks.

Apply this diff to properly escape the variables:

-        $field[] = '<th scope="row"><label for="' . $field_id . '">' . $params['label'] . '</label></th>';
+        $field[] = '<th scope="row"><label for="' . esc_attr( $field_id ) . '">' . esc_html( $params['label'] ) . '</label></th>';

-        $field[] = '<select type="' . $params['type'] . '" name="' . $field_id . '" />';
+        $field[] = '<select type="' . esc_attr( $params['type'] ) . '" name="' . esc_attr( $field_id ) . '" />';

...

-            $field[] = '<option ' . $select_param . ' value="' . $o_key . '">' . $o_val . '</option>';
+            $field[] = '<option ' . $select_param . ' value="' . esc_attr( $o_key ) . '">' . esc_html( $o_val ) . '</option>';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		$field[] = '<th scope="row"><label for="' . esc_attr( $field_id ) . '">' . esc_html( $params['label'] ) . '</label></th>';
		$field[] = '<td>';
		$field[] = '<select type="' . esc_attr( $params['type'] ) . '" name="' . esc_attr( $field_id ) . '" />';

		$selected = $this->get_value( $field_id, $params );

		foreach ( $params['options'] as $o_key => $o_val ) {
			$select_param = '';
			if ( $o_key === $selected ) {
				$select_param = 'selected="selected"';
			}
			$field[] = '<option ' . $select_param . ' value="' . esc_attr( $o_key ) . '">' . esc_html( $o_val ) . '</option>';
		}
		$field[] = '</select>';

546-546: ⚠️ Potential issue

Remove unused variable '$tab' in 'foreach' loop.

The variable '$tab' is not used within the loop. Removing it will clean up the code and avoid confusion.

Apply this diff to remove the unused variable:

-            foreach ( $settings_pages as $tab_index => $tab ) {
+            foreach ( $settings_pages as $tab_index ) {

Committable suggestion was skipped due to low confidence.

🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis

[warning] 546-546: includes/classes/admin/class-settings.php#L546
Avoid unused local variables such as '$tab'.


427-438: ⚠️ Potential issue

Ensure variables are escaped when outputting HTML in 'text_field' method.

Variables used in HTML attributes should be escaped to prevent XSS vulnerabilities.

Apply this diff to properly escape the variables:

-        $field[] = '<th scope="row"><label for="' . $field_id . '">' . $params['label'] . '</label></th>';
+        $field[] = '<th scope="row"><label for="' . esc_attr( $field_id ) . '">' . esc_html( $params['label'] ) . '</label></th>';

...

-        $field[] = '<input value="' . $value . '" type="' . $params['type'] . '" name="' . $field_id . '" />';
+        $field[] = '<input value="' . esc_attr( $value ) . '" type="' . esc_attr( $params['type'] ) . '" name="' . esc_attr( $field_id ) . '" />';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		$field[] = '<th scope="row"><label for="' . esc_attr( $field_id ) . '">' . esc_html( $params['label'] ) . '</label></th>';
		$field[] = '<td>';

		$value = $this->get_value( $field_id, $params );

		$field[] = '<input value="' . esc_attr( $value ) . '" type="' . esc_attr( $params['type'] ) . '" name="' . esc_attr( $field_id ) . '" />';
		if ( '' !== $params['desc'] ) {
			$field[] = '<br /><small>' . $params['desc'] . '</small>';
		}
		$field[] = '</td>';
		
		return implode( '', $field );

372-402: ⚠️ Potential issue

Escape variables when generating HTML in 'checkbox_field' method.

Variables should be properly escaped to prevent security vulnerabilities.

Apply this diff to properly escape the variables:

-        $field[] = '<th scope="row"><label for="' . $field_id . '">' . $params['label'] . '</label></th>';
+        $field[] = '<th scope="row"><label for="' . esc_attr( $field_id ) . '">' . esc_html( $params['label'] ) . '</label></th>';

...

-        $field[] = '<input ' . $checked_param . ' value="1" type="' . $params['type'] . '" name="' . $field_id . '" />';
+        $field[] = '<input ' . $checked_param . ' value="1" type="' . esc_attr( $params['type'] ) . '" name="' . esc_attr( $field_id ) . '" />';

Committable suggestion was skipped due to low confidence.


466-500: ⚠️ Potential issue

Escape variables when rendering HTML in 'image_field' method.

Properly escape variables to prevent security issues.

Apply this diff to properly escape the variables:

-        $field[] = '<th scope="row"><label for="' . $field_id . '">' . $params['label'] . '</label></th>';
+        $field[] = '<th scope="row"><label for="' . esc_attr( $field_id ) . '">' . esc_html( $params['label'] ) . '</label></th>';

...

-        $field[] = '<input class="input_image" type="hidden" value="' . $image_id . '" name="' . $field_id . '" />';
+        $field[] = '<input class="input_image" type="hidden" value="' . esc_attr( $image_id ) . '" name="' . esc_attr( $field_id ) . '" />';

...

-        $field[] = '<div class="thumbnail-preview" style="' . $prev_css . '"><img src="' . $image[0] . '" width="' . $params['preview_w'] . '" style="color:black;" /></div>';
+        $field[] = '<div class="thumbnail-preview" style="' . esc_attr( $prev_css ) . '"><img src="' . esc_url( $image[0] ) . '" width="' . esc_attr( $params['preview_w'] ) . '" style="color:black;" /></div>';

Committable suggestion was skipped due to low confidence.

includes/classes/legacy/class-frontend.php (2)

682-682: ⚠️ Potential issue

Ensure $current_destinations is an array before iterating

Changing the third parameter of get_post_meta to true means $current_destinations may now be a single value instead of an array. However, the subsequent foreach loop expects $current_destinations to be an array, which could lead to errors if it's not.

Apply this diff to ensure $current_destinations is always an array:

 $current_destinations = get_post_meta( get_the_ID(), 'destination_to_accommodation', true );

+ if ( ! is_array( $current_destinations ) && ! empty( $current_destinations ) ) {
+     $current_destinations = array( $current_destinations );
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		$current_destinations = get_post_meta( get_the_ID(), 'destination_to_accommodation', true );

		if ( ! is_array( $current_destinations ) && ! empty( $current_destinations ) ) {
		    $current_destinations = array( $current_destinations );
		}

742-742: ⚠️ Potential issue

Handle $region correctly when get_post_meta returns a single value

With the third parameter of get_post_meta changed to true, $region may now be a single value rather than an array. The code checks isset( $region[0] ), which could cause issues if $region is not an array.

Modify the code to handle both cases:

 $region = get_post_meta( get_the_ID(), 'departs_from', true );
- if ( false !== $region && isset( $region[0] ) ) {
-     $country = wp_get_post_parent_id( $region[0] );
+ if ( ! empty( $region ) ) {
+     if ( is_array( $region ) ) {
+         $region_id = $region[0];
+     } else {
+         $region_id = $region;
+     }
+     $country = wp_get_post_parent_id( $region_id );

Committable suggestion was skipped due to low confidence.

includes/classes/blocks/class-bindings.php (7)

178-182: ⚠️ Potential issue

Fix inconsistency between code and documentation in itinerary_callback

The documentation specifies checking for 'core/paragraph', but the code checks for 'core/group'. Please update the documentation to reflect the actual code logic.

Apply this diff to correct the documentation:

- * This function checks if the given block instance is of type 'core/paragraph'
+ * This function checks if the given block instance is of type 'core/group'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	 * Callback function to process itinerary-related blocks.
	 *
	 * This function checks if the given block instance is of type 'core/group'
	 * and returns an empty string if it is. It serves as a conditional handler
	 * based on the block type.

40-40: ⚠️ Potential issue

Adjust opening brace placement to match coding standards

According to coding standards, the opening brace should be on a new line for class methods.

Apply this diff to fix the issue:

-    public function __construct() {
+    public function __construct()
+    {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	public function __construct()
	{
🧰 Tools
🪛 GitHub Check: Codacy Static Code Analysis

[notice] 40-40: includes/classes/blocks/class-bindings.php#L40
Opening brace should be on a new line


522-528: ⚠️ Potential issue

Add visibility modifier to purge_class_attribute method

The method purge_class_attribute lacks a visibility modifier. All class methods should have an explicit visibility for clarity.

Apply this diff:

-    function purge_class_attribute( $content ) {
+    public function purge_class_attribute( $content ) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	public function purge_class_attribute( $content ) {
		// Regular expression to match class attributes
		$pattern = '/\s*class="[^"]*"/i';
		// Replace matched class attributes with an empty string
		$result = preg_replace($pattern, '', $content);
		return $result;
	}

548-548: ⚠️ Potential issue

Remove unused parameter $block_obj in render_gallery_block

The parameter $block_obj in render_gallery_block is not utilised. Consider removing it to clean up the code.

Apply this diff:

-    public function render_gallery_block( $block_content, $parsed_block, $block_obj ) {
+    public function render_gallery_block( $block_content, $parsed_block ) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	public function render_gallery_block( $block_content, $parsed_block ) {
🧰 Tools
🪛 GitHub Check: CodeFactor

[notice] 548-548: includes/classes/blocks/class-bindings.php#L548
The method parameter $block_obj is never used. (Generic.CodeAnalysis.UnusedFunctionParameter)


189-194: ⚠️ Potential issue

Ensure consistent return values in itinerary_callback

The function itinerary_callback does not return a value when the condition is not met. Consider adding a return statement to ensure consistent behaviour.

Apply this diff:

         if ( 'core/group' === $block_instance->parsed_block['blockName'] ) {
             return '';
         }
+        return null;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	public function itinerary_callback( $source_args, $block_instance ) {
		if ( 'core/group' === $block_instance->parsed_block['blockName'] ) {
			return '';
		}
		return null;
	}


512-512: ⚠️ Potential issue

Separate class names with spaces

When combining multiple class names, they should be separated by spaces for proper CSS recognition.

Apply this diff:

-            $classes = implode( '', $matches[1] );
+            $classes = implode( ' ', $matches[1] );

Committable suggestion was skipped due to low confidence.


403-403: ⚠️ Potential issue

Use strict comparison in in_array

When using in_array, it's advisable to enable strict comparison to prevent unintended type coercion.

Apply this diff:

-        if ( ! in_array( $parsed_block['attrs']['metadata']['bindings']['content']['source'], $allowed_sources ) ) {
+        if ( ! in_array( $parsed_block['attrs']['metadata']['bindings']['content']['source'], $allowed_sources, true ) ) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		if ( ! in_array( $parsed_block['attrs']['metadata']['bindings']['content']['source'], $allowed_sources, true ) ) {
🧰 Tools
🪛 GitHub Check: CodeFactor

[notice] 403-403: includes/classes/blocks/class-bindings.php#L403
Not using strict comparison for in_array; supply true for $strict argument. (WordPress.PHP.StrictInArray)

@krugazul krugazul changed the base branch from master to update/2.0.0 October 29, 2024 06:38
@krugazul krugazul self-requested a review October 29, 2024 06:53
Copy link
Collaborator

@krugazul krugazul left a comment

Choose a reason for hiding this comment

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

@ZaredRogers I have reviewed and tested, thanks it works well. I have moved the enqueue script to the new location.

Screenshot 2024-10-29 at 08 52 51

@krugazul krugazul merged commit ef23fd8 into update/2.0.0 Oct 29, 2024
3 of 6 checks passed
@krugazul krugazul deleted the linked-cover-block branch October 29, 2024 06:57
@krugazul krugazul mentioned this pull request Nov 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Component] Block Variations Block development issues or pulls.
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Clickable Cover Block Variation
2 participants