$settings Setup settings. * @param array $facts Runtime facts. */ public function run( array $settings, array $facts ): AuditReport { $context = $this->context_factory->create( $settings, $facts ); $resolution = $this->resolver->resolve( $context ); $packs = array(); foreach ( $resolution->get_pack_ids() as $pack_id ) { $pack = $this->registry->get( $pack_id ); if ( null !== $pack ) { $packs[] = $pack; } } $rules = $this->rules_engine->compose( $context, $packs ); $validators = array(); foreach ( $packs as $pack ) { if ( ! $pack instanceof ValidatorProviderInterface ) { continue; } foreach ( $pack->get_validators() as $validator ) { if ( $validator instanceof RuleValidatorInterface ) { $validators[ get_class( $validator ) ] = $validator; } } } $results = array(); if ( $rules->has_conflicts() ) { $results[] = new ValidationResult( 'LEGAL_REVIEW_REQUIRED', ValidationStatus::BLOCKER, __( 'The selected BiH rule packs contain an unresolved conflict. The audit cannot guess which rule should prevail.', 'leanmerce-commerce-assistant' ), __( 'Resolve the conflict through an explicit legal-pack override before production use.', 'leanmerce-commerce-assistant' ), 'RULESET_CONFLICT', array( 'conflicts' => $rules->conflicts() ) ); } foreach ( $validators as $validator ) { foreach ( $validator->validate( $context, $rules, $facts ) as $result ) { if ( $result instanceof ValidationResult ) { $results[] = $result; } } } usort( $results, static function ( ValidationResult $left, ValidationResult $right ): int { $order = array( ValidationStatus::BLOCKER => 0, ValidationStatus::WARNING => 1, ValidationStatus::PASS => 2, ValidationStatus::NOT_APPLICABLE => 3, ); $cmp = ( $order[ $left->get_status() ] ?? 9 ) <=> ( $order[ $right->get_status() ] ?? 9 ); return 0 !== $cmp ? $cmp : strcmp( $left->get_code(), $right->get_code() ); } ); return new AuditReport( $results, $rules->pack_ids(), $resolution->get_reason_codes(), $resolution->get_mode(), $this->combined_ruleset_hash( $packs ), $this->now_mysql() ); } private function combined_ruleset_hash( array $packs ): string { $hashes = array(); foreach ( $packs as $pack ) { $manifest = $pack->get_manifest(); $hashes[] = $manifest->get_id() . ':' . $manifest->get_version() . ':' . $manifest->get_ruleset_hash(); } sort( $hashes ); return hash( 'sha256', implode( '|', $hashes ) ); } private function now_mysql(): string { if ( function_exists( 'current_time' ) ) { return (string) current_time( 'mysql' ); } return gmdate( 'Y-m-d H:i:s' ); } }