setKnownProperties( $properties ); $this->setCssWideKeywordsMatcher( $cssWideKeywordsMatcher ?: new NothingMatcher ); } /** * Access the list of known properties * @return Matcher[] */ public function getKnownProperties() { return $this->knownProperties; } /** * Set the list of known properties * @param Matcher[] $properties Array mapping declaration names (lowercase) * to Matchers for the values */ public function setKnownProperties( array $properties ) { foreach ( $properties as $prop => $matcher ) { if ( strtolower( $prop ) !== $prop ) { throw new InvalidArgumentException( "Property name '$prop' must be lowercased" ); } if ( !$matcher instanceof Matcher ) { throw new InvalidArgumentException( "Value for '$prop' is not a Matcher" ); } } $this->knownProperties = $properties; } /** * Merge a list of matchers into the list of known properties * @param Matcher[] $properties Array mapping declaration names (lowercase) * to Matchers for the values * @throws InvalidArgumentException if some property is already defined */ public function addKnownProperties( $props ) { $dups = []; foreach ( $props as $k => $v ) { if ( isset( $this->knownProperties[$k] ) && $props[$k] !== $this->knownProperties[$k] ) { $dups[] = $k; } } if ( $dups ) { throw new InvalidArgumentException( 'Duplicate definitions for properties: ' . join( ' ', $dups ) ); } $this->setKnownProperties( $this->knownProperties + $props ); } /** * Fetch the matcher for keywords that should be recognized for all properties. * @return Matcher */ public function getCssWideKeywordsMatcher() { return $this->cssWideKeywords; } /** * Set the matcher for keywords that should be recognized for all properties. * @param Matcher $matcher */ public function setCssWideKeywordsMatcher( Matcher $matcher ) { $this->cssWideKeywords = $matcher; } protected function doSanitize( CSSObject $object ) { if ( !$object instanceof Declaration ) { $this->sanitizationError( 'expected-declaration', $object ); return null; } $knownProperties = $this->getKnownProperties(); $name = strtolower( $object->getName() ); if ( !isset( $knownProperties[$name] ) ) { $this->sanitizationError( 'unrecognized-property', $object ); return null; } $list = $object->getValue(); if ( !$knownProperties[$name]->match( $list, [ 'mark-significance' => true ] ) && !$this->getCssWideKeywordsMatcher()->match( $list, [ 'mark-significance' => true ] ) ) { $cv = Util::findFirstNonWhitespace( $list ); if ( $cv ) { $this->sanitizationError( 'bad-value-for-property', $cv, [ $name ] ); } else { $this->sanitizationError( 'missing-value-for-property', $object, [ $name ] ); } return null; } return $object; } }