diff --git a/CHANGELOG.md b/CHANGELOG.md index 839a6ad..d23e39f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ Individual plugin versions are tracked separately in their respective plugin hea ## [Unreleased] +### Added +- **community-listings:** Admin meta box ("Provider Listings") on the `community` post type editor, city-level posts only — lets editors view/update the `provider_listings` JSON without CLI access. JSON-safe save via `$wpdb->update()`/`insert()` (avoids `update_post_meta()`'s `wp_unslash()` corrupting `\"` escapes), with byte/provider counts, client-side validation, and post-meta cache invalidation after the direct write (#2) + +### Changed +- Adopted the `SilverAssistWP` PHPCS ruleset and composed shared `silverassist/coding-standards` + `silverassist/wp-coding-standards` PHPStan base configs across all three sub-plugins, replacing hand-rolled rulesets and duplicated static-analysis baselines (#3) + +### Fixed +- **community-listings:** Resolved all 3 pre-existing PHPStan errors — dead-code truthy check in `SettingsPage::render_settings_page()`, a `register_graphql_field()` call missing its own `function_exists()` guard, and an unreachable array-offset fallback in the GraphQL type-mapping refactored to a `match` expression +- **Makefile:** `phpcs`, `phpstan`, `install`, `install-dev`, and `build` targets no longer silently ignore failures in any sub-plugin but the last one in `$(PLUGINS)` — each `for` loop now propagates a non-zero exit status, so CI actually fails when any sub-plugin has a real violation (`phpcs`/`phpstan` previously didn't: the 3 PHPStan errors above went undetected by CI since this repo's first PHPStan adoption) +- **Makefile:** `phpcs` target now calls `vendor/bin/phpcs --warning-severity=0` directly instead of `composer run phpcs`, matching exactly what CI's own PHPCS step runs — previously `make phpcs` treated pre-existing warnings (discouraged `json_encode()`/`file_get_contents()` calls, a missing nonce-verification annotation) as failures that CI itself was configured to ignore, so the two disagreed on what counted as passing + --- ## [v1.2.5] — 2026-03-02 diff --git a/Makefile b/Makefile index ea1ed2e..219cb75 100644 --- a/Makefile +++ b/Makefile @@ -21,18 +21,22 @@ help: ## Show this help message install: ## Install production dependencies for all plugins @echo "$(BLUE)Installing production dependencies...$(NC)" - @for plugin in $(PLUGINS); do \ + @status=0; \ + for plugin in $(PLUGINS); do \ echo "Installing dependencies for $$plugin..."; \ - (cd $$plugin && composer install --no-dev --optimize-autoloader); \ - done + (cd $$plugin && composer install --no-dev --optimize-autoloader) || status=1; \ + done; \ + exit $$status @echo "$(GREEN)✅ Production dependencies installed!$(NC)" install-dev: ## Install development dependencies for all plugins @echo "$(BLUE)Installing development dependencies...$(NC)" - @for plugin in $(PLUGINS); do \ + @status=0; \ + for plugin in $(PLUGINS); do \ echo "Installing dev dependencies for $$plugin..."; \ - (cd $$plugin && composer install); \ - done + (cd $$plugin && composer install) || status=1; \ + done; \ + exit $$status @echo "$(GREEN)✅ Development dependencies installed!$(NC)" clean: ## Clean vendor directories and caches @@ -45,10 +49,12 @@ clean: ## Clean vendor directories and caches phpcs: ## Run PHP CodeSniffer on all plugins @echo "$(BLUE)Running PHPCS on all plugins...$(NC)" - @for plugin in $(PLUGINS); do \ + @status=0; \ + for plugin in $(PLUGINS); do \ echo "Checking $$plugin..."; \ - (cd $$plugin && composer run phpcs); \ - done + (cd $$plugin && ./vendor/bin/phpcs --standard=phpcs.xml --warning-severity=0 .) || status=1; \ + done; \ + exit $$status @echo "$(GREEN)✅ PHPCS completed!$(NC)" phpcs-fix: ## Fix PHP CodeSniffer issues automatically @@ -61,10 +67,12 @@ phpcs-fix: ## Fix PHP CodeSniffer issues automatically phpstan: ## Run PHPStan static analysis on all plugins @echo "$(BLUE)Running PHPStan on all plugins...$(NC)" - @for plugin in $(PLUGINS); do \ + @status=0; \ + for plugin in $(PLUGINS); do \ echo "Analyzing $$plugin..."; \ - (cd $$plugin && composer run phpstan); \ - done + (cd $$plugin && composer run phpstan) || status=1; \ + done; \ + exit $$status @echo "$(GREEN)✅ PHPStan analysis completed!$(NC)" test: install-dev phpcs phpstan ## Run all quality assurance tests @@ -73,7 +81,8 @@ test: install-dev phpcs phpstan ## Run all quality assurance tests build: clean install ## Build production-ready plugins @echo "$(BLUE)Building production plugins...$(NC)" @mkdir -p dist - @for plugin in $(PLUGINS); do \ + @status=0; \ + for plugin in $(PLUGINS); do \ echo "Building $$plugin..."; \ version=$$(grep "Version:" $$plugin/$$plugin.php | sed 's/.*Version: *//'); \ zip -r "dist/$$plugin-v$$version.zip" "$$plugin" \ @@ -81,8 +90,9 @@ build: clean install ## Build production-ready plugins "$$plugin/phpcs.xml" "$$plugin/phpstan.neon" \ "$$plugin/composer.lock" "$$plugin/tests/*" \ "$$plugin/.DS_Store" "$$plugin/vendor/*/tests/*" \ - "$$plugin/vendor/*/*/tests/*"; \ - done + "$$plugin/vendor/*/*/tests/*" || status=1; \ + done; \ + exit $$status @echo "$(GREEN)✅ Build completed! Check dist/ directory.$(NC)" release: test build ## Create release packages diff --git a/community-listings/includes/Admin/SettingsPage.php b/community-listings/includes/Admin/SettingsPage.php index da69cb5..e2f5d03 100644 --- a/community-listings/includes/Admin/SettingsPage.php +++ b/community-listings/includes/Admin/SettingsPage.php @@ -114,11 +114,9 @@ public function render_settings_page(): void { return; } - $community_count = \wp_count_posts( 'community' ); - $total = 0; - if ( $community_count ) { - $total = (int) $community_count->publish; - } + // wp_count_posts() always returns an object per its own type signature, never + // false — the previous truthy-check here was unreachable dead code. + $total = (int) \wp_count_posts( 'community' )->publish; ?>
diff --git a/community-listings/includes/Service/CptRegistrar.php b/community-listings/includes/Service/CptRegistrar.php index b5cdc8e..7101f36 100644 --- a/community-listings/includes/Service/CptRegistrar.php +++ b/community-listings/includes/Service/CptRegistrar.php @@ -167,18 +167,10 @@ public function register_meta(): void { * @return void */ public function register_graphql_meta_fields(): void { - if ( ! \function_exists( 'register_graphql_object_type' ) ) { + if ( ! \function_exists( 'register_graphql_object_type' ) || ! \function_exists( 'register_graphql_field' ) ) { return; } - // Map PHP meta types to GraphQL scalar types. - $type_map = array( - 'string' => 'String', - 'boolean' => 'Boolean', - 'integer' => 'Int', - 'number' => 'Float', - ); - // Build the fields array for the CommunityMeta object type. $graphql_fields = array(); foreach ( self::META_FIELDS as $key => $type ) { @@ -186,7 +178,14 @@ public function register_graphql_meta_fields(): void { $camel_key = \lcfirst( \str_replace( '_', '', \ucwords( $key, '_' ) ) ); $graphql_fields[ $camel_key ] = array( - 'type' => $type_map[ $type ] ?? 'String', + // Maps PHP meta types to GraphQL scalar types. The default arm is a + // Only 'boolean' and 'string' occur in META_FIELDS today; the default + // arm is a real fallback for a future entry using another type + // (e.g. 'integer'/'number') rather than dead code. + 'type' => match ( $type ) { + 'boolean' => 'Boolean', + default => 'String', + }, 'description' => \sprintf( 'The %s meta field.', \str_replace( '_', ' ', $key ) ), 'resolve' => static function ( $source ) use ( $key, $type ) { $post_id = 0;