inner = $inner; $this->cache = $cache; $this->ttl = $ttl; } /** * @inheritDoc */ public function get_vulnerabilities( array $installed ): array { $all_vulns = array(); $uncached = array(); $provider_name = $this->inner->get_source_name(); // Try cache first for each item. foreach ( $installed as $item ) { $cached = $this->cache->get( $item['slug'], $item['type'], $provider_name ); if ( null !== $cached ) { // Filter by installed version. foreach ( $cached as $vuln ) { if ( isset( $vuln['fix_version'] ) && version_compare( $item['version'], $vuln['fix_version'], '<' ) ) { $vuln['installed_version'] = $item['version']; $vuln['slug'] = $item['slug']; $vuln['software_type'] = $item['type']; $vuln['source'] = $provider_name . ' (cached)'; $all_vulns[] = $vuln; } } } else { $uncached[] = $item; } } // Fetch uncached items from the inner provider. if ( ! empty( $uncached ) ) { $fresh = $this->inner->get_vulnerabilities( $uncached ); // Group results by slug for caching. $by_slug = array(); foreach ( $fresh as $vuln ) { $slug = $vuln['slug'] ?? ''; if ( ! isset( $by_slug[ $slug ] ) ) { $by_slug[ $slug ] = array(); } $by_slug[ $slug ][] = $vuln; } // Cache each slug's results. foreach ( $uncached as $item ) { $slug_data = isset( $by_slug[ $item['slug'] ] ) ? $by_slug[ $item['slug'] ] : array(); $this->cache->set( $item['slug'], $item['type'], $provider_name, $slug_data, $this->ttl ); } $all_vulns = array_merge( $all_vulns, $fresh ); } return $all_vulns; } /** * @inheritDoc */ public function get_source_name(): string { return $this->inner->get_source_name(); } /** * @inheritDoc */ public function is_available(): bool { return $this->inner->is_available(); } }