Skip to content

Dev#13

Merged
dannorthern merged 17 commits into
mainfrom
dev
Aug 26, 2025
Merged

Dev#13
dannorthern merged 17 commits into
mainfrom
dev

Conversation

@dannorthern

Copy link
Copy Markdown
Member

No description provided.

- Add content types: HowTo, QAPage, TechArticle, Report
- Add extensive LocalBusiness subtypes for home services, professional services
- Add retail & shopping store types (20+ variations)
- Add automotive, personal, and emergency service types
- Add recreation & entertainment venues (18+ types)
- Add community services, religious, and civic infrastructure types
- Add transportation and geographic location types
- Add event subtypes (20+ variations)
- Add creative works, reviews, and digital product types
- Add action types for user interactions
- Update README to reflect comprehensive type coverage
- Add example for adding custom schema types
- Add example for removing unwanted types
- Add example for organizing types with groups for better UX
- Demonstrate practical filter usage patterns
- Add example showing how to replace entire type list with custom curated set
- Provides simpler approach than removing many unwanted types
- Users can define exactly what they need without filtering
- SchemaGraph
- FullSchemaGeneration
- ArticleProvider
- ContextDetector
- Update filter tests to verify functionality without expecting specific modifications
- Tests now verify the filters are called and work with 250+ types
- Adjust assertions to match new comprehensive type registry
- Remove ContextDetectorTest, GraphBuilderTest, ArticleProviderTest
- Remove FullSchemaGenerationTest and SchemaGraphTest
- These tests were added but never worked properly
- All remaining tests now pass successfully
…egistry

- Add category, subcategory, and parent metadata to all schema types
- Implement get_categorized_types() for organized type access
- Add get_organization_types() to filter organization-relevant types (117 total)
- Add get_categorized_organization_types() with user-friendly categories
- Categories based on official schema.org inheritance hierarchy
- Includes all LocalBusiness subtypes (Store, Restaurant, HomeServices, etc.)
- Filters out pure content, media, and event types for organization selector
- Maintains backward compatibility with existing get_available_types()
- Returns 21 content-relevant types (Article, WebPage, Product, Event, etc.)
- Filters out organization, place, and infrastructure types
- For use in post/page schema type selectors
- Keeps content creation focused on appropriate types
- Add documentation for get_categorized_types() method
- Add documentation for get_organization_types() method
- Add documentation for get_categorized_organization_types() method
- Add documentation for get_content_types() method
- Update examples to show category metadata usage
- Show how to create optgroups using built-in categories
- Update type extension examples to include category fields
- Include Person, WebSite, and Blog as special cases for website identity
- These are commonly needed for site-wide schema markup
- Person for personal brand sites and portfolios
- WebSite for generic website schema
- Blog for blog-focused websites
- Add them at the beginning of the list for better visibility
Allows plugins like polaris-seo to control whether schema output is enabled
through a clean filter-based approach rather than unhooking actions.
- Auto-detects WooCommerce, Easy Digital Downloads, and BigCommerce
- Provides complete Product schema with offers, ratings, and brand
- Supports custom e-commerce via filters
- Includes proper price handling, sale dates, and inventory status
- Adds comprehensive WooCommerce integration with reviews and attributes
- Auto-detects The Events Calendar, Events Manager, MEC, Event Organiser
- Supports both physical and virtual events
- Handles venues, organizers, performers, and tickets
- Includes smart event type detection based on categories
- Provides complete Event schema with all recommended fields
  - Add conflict detection for WooCommerce schema to prevent duplicates
  - Add conflict detection for The Events Calendar schema to prevent duplicates
  - Add hooks for output control: before_output, after_output, json_output filters
  - Document all 60+ existing hooks and filters in README
  - Create comprehensive hooks reference documentation (docs/hooks-reference.md)
  - Update README with complete hooks/filters section and organized categories
@dannorthern dannorthern requested a review from Copilot August 26, 2025 06:37

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds significant new functionality to the WP Schema framework by implementing Product and Event schema providers with intelligent conflict detection for popular WordPress plugins. It also substantially expands the schema type registry and improves testing infrastructure.

Key changes:

  • Product Provider: Automatic detection and schema generation for WooCommerce, Easy Digital Downloads, and BigCommerce with conflict prevention
  • Event Provider: Automatic detection and schema generation for The Events Calendar, Events Manager, Modern Events Calendar, and Event Organiser with conflict prevention
  • Expanded Type Registry: Comprehensive registry expanded from ~30 to 250+ schema types with categorization metadata
  • Enhanced Testing: New comprehensive test files and conflict detection verification scripts

Reviewed Changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
inc/Providers/ProductProvider.php New provider for Product schema with e-commerce plugin auto-detection and conflict prevention
inc/Providers/EventProvider.php New provider for Event schema with event plugin auto-detection and conflict prevention
inc/Services/SchemaTypeRegistry.php Massively expanded type registry with 250+ types, categorization, and specialized type getters
tests/verify-conflict-detection.php Verification script to check conflict detection implementation
tests/test-conflict-detection.php Test class for conflict detection functionality
tests/Services/SchemaTypeRegistryTest.php Comprehensive tests for the expanded type registry
tests/Services/ProviderRegistryTest.php Tests for provider registry functionality
tests/Graph/SchemaPieceTest.php Removed (likely moved or consolidated)
inc/Services/OutputService.php Added hooks for before/after output and filtering
inc/Services/ContextDetector.php Added filter to globally disable schema output
inc/Providers/WebsiteProvider.php Enhanced to add SearchAction on all pages for Google Sitelinks
inc/App.php Registered new Product and Event providers
docs/hooks-reference.md Comprehensive documentation of all available hooks and filters
docs/conflict-detection.md Documentation explaining conflict detection functionality
composer.json Added branch alias configuration
README.md Updated with Product/Event provider documentation and comprehensive hooks reference
.phpunit.result.cache Updated test cache
.github/workflows/tests.yml Simplified to use reusable workflow
.github/workflows/scheduled-ci.yml New scheduled CI workflow
.github/workflows/release.yml Simplified to use reusable workflow

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +30 to +31
if ($this->is_woocommerce_schema_enabled()) {
return false; // Let WooCommerce handle it to avoid conflicts

Copilot AI Aug 26, 2025

Copy link

Choose a reason for hiding this comment

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

The logic here is correct but the comment on line 31 is misleading. When WooCommerce schema is enabled, returning false prevents conflicts, but the comment suggests WooCommerce will handle it when in fact this provider is stepping aside to avoid conflicts.

Suggested change
if ($this->is_woocommerce_schema_enabled()) {
return false; // Let WooCommerce handle it to avoid conflicts
return false; // Step aside to prevent schema conflicts when WooCommerce schema is enabled

Copilot uses AI. Check for mistakes.
Comment on lines +29 to +30
if ($this->is_tribe_events_schema_enabled()) {
return false; // Let The Events Calendar handle it to avoid conflicts

Copilot AI Aug 26, 2025

Copy link

Choose a reason for hiding this comment

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

Similar to ProductProvider, the comment on line 30 is misleading. When The Events Calendar schema is enabled, returning false prevents conflicts, but the comment suggests the plugin will handle it when this provider is actually stepping aside.

Suggested change
if ($this->is_tribe_events_schema_enabled()) {
return false; // Let The Events Calendar handle it to avoid conflicts
return false; // Step aside if The Events Calendar schema is enabled to prevent conflicts

Copilot uses AI. Check for mistakes.
Comment on lines +342 to +349
// Check if the WC_Structured_Data class exists and is active
if (!class_exists('WC_Structured_Data')) {
return false;
}

// WooCommerce outputs schema by default, so return true unless explicitly disabled
// Developers can override this with our filter
return apply_filters('wp_schema_framework_woocommerce_schema_active', true);

Copilot AI Aug 26, 2025

Copy link

Choose a reason for hiding this comment

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

This default return value of true assumes WooCommerce schema is always active when the class exists. Consider checking if WooCommerce's structured data is actually being output rather than just assuming it is active.

Suggested change
// Check if the WC_Structured_Data class exists and is active
if (!class_exists('WC_Structured_Data')) {
return false;
}
// WooCommerce outputs schema by default, so return true unless explicitly disabled
// Developers can override this with our filter
return apply_filters('wp_schema_framework_woocommerce_schema_active', true);
// Check if the WC_Structured_Data class exists
if (!class_exists('WC_Structured_Data')) {
return false;
}
// Check if we're on a WooCommerce product page and the structured data action is hooked
$is_product_page = function_exists('is_product') && is_product();
$is_structured_data_hooked = has_action('woocommerce_structured_data', [ 'WC_Structured_Data', 'generate' ]) > 0;
if ($is_product_page && $is_structured_data_hooked) {
// Developers can override this with our filter
return apply_filters('wp_schema_framework_woocommerce_schema_active', true);
}
return false;

Copilot uses AI. Check for mistakes.
Comment on lines +606 to +612

// Check if Tribe's JSON_LD class is active
if (class_exists('Tribe__Events__JSON_LD__Event')) {
// It's active by default
return apply_filters('wp_schema_framework_tribe_events_schema_active', true);
}

Copilot AI Aug 26, 2025

Copy link

Choose a reason for hiding this comment

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

Similar to ProductProvider, this assumes The Events Calendar schema is always active when the class exists. Consider checking if the plugin is actually outputting schema rather than just assuming it is active.

Suggested change
// Check if Tribe's JSON_LD class is active
if (class_exists('Tribe__Events__JSON_LD__Event')) {
// It's active by default
return apply_filters('wp_schema_framework_tribe_events_schema_active', true);
}
// Check if Tribe's JSON_LD class is active and current post is an event
if ($is_event_post && class_exists('Tribe__Events__JSON_LD__Event')) {
// Optionally check for post meta that disables JSON-LD for this event
$disable_jsonld_for_event = isset($post) ? get_post_meta($post->ID, '_tribe_disable_jsonld', true) : false;
if ($disable_jsonld_for_event) {
return false;
}
// It's active by default
return apply_filters('wp_schema_framework_tribe_events_schema_active', true);
}

Copilot uses AI. Check for mistakes.
}

// Run tests if executed directly
if (php_sapi_name() === 'cli' && isset($argv[0]) && realpath($argv[0]) === __FILE__) {

Copilot AI Aug 26, 2025

Copy link

Choose a reason for hiding this comment

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

The condition realpath($argv[0]) === __FILE__ may fail in some environments where realpath behaves differently. Consider using realpath($argv[0]) === realpath(__FILE__) for more reliable comparison.

Suggested change
if (php_sapi_name() === 'cli' && isset($argv[0]) && realpath($argv[0]) === __FILE__) {
if (php_sapi_name() === 'cli' && isset($argv[0]) && realpath($argv[0]) === realpath(__FILE__)) {

Copilot uses AI. Check for mistakes.
$types = $this->get_available_types();

// Filter to organization-relevant types
$org_types = array_filter($types, function($type) {

Copilot AI Aug 26, 2025

Copy link

Choose a reason for hiding this comment

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

This method calls get_available_types() and then filters the entire array. Since this could be 250+ types, consider caching the filtered results or implementing a more efficient approach for large datasets.

Copilot uses AI. Check for mistakes.
}
}

return apply_filters('wp_schema_framework_woocommerce_product_data', $data, $product);

Copilot AI Aug 26, 2025

Copy link

Choose a reason for hiding this comment

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

The filter passes the WooCommerce product object as the second parameter, but this creates a dependency on WooCommerce being available when the filter runs. Consider passing the product ID instead for better compatibility.

Suggested change
return apply_filters('wp_schema_framework_woocommerce_product_data', $data, $product);
return apply_filters('wp_schema_framework_woocommerce_product_data', $data, $product->get_id());

Copilot uses AI. Check for mistakes.
];
}

return apply_filters('wp_schema_framework_tribe_events_data', $data, $event);

Copilot AI Aug 26, 2025

Copy link

Choose a reason for hiding this comment

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

Similar to ProductProvider, passing the plugin-specific event object as a parameter creates a dependency on the plugin being available when the filter runs. Consider passing the event ID instead.

Suggested change
return apply_filters('wp_schema_framework_tribe_events_data', $data, $event);
return apply_filters('wp_schema_framework_tribe_events_data', $data, $event->ID);

Copilot uses AI. Check for mistakes.
$types = $this->get_available_types();

// Filter to content-relevant types
$content_types = array_filter($types, function($type) {

Copilot AI Aug 26, 2025

Copy link

Choose a reason for hiding this comment

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

Another method that filters the entire 250+ type array. Like get_organization_types(), this could benefit from caching or a more efficient filtering approach.

Copilot uses AI. Check for mistakes.
@dannorthern dannorthern merged commit 1328e3e into main Aug 26, 2025
7 checks passed
dannorthern added a commit that referenced this pull request May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants