From: Chuck Hagenbuch Date: Sat, 26 Sep 2009 03:39:17 +0000 (-0400) Subject: Add a Constraint-based log filter X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=8eb1f925ecdac726df0ff192da7ee9649d87cfc6;p=horde.git Add a Constraint-based log filter --- diff --git a/framework/Log/lib/Horde/Log/Filter/Constraint.php b/framework/Log/lib/Horde/Log/Filter/Constraint.php new file mode 100644 index 000000000..06fb66f6b --- /dev/null +++ b/framework/Log/lib/Horde/Log/Filter/Constraint.php @@ -0,0 +1,96 @@ + + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * Filters log events using defined constraints on one or more fields of the + * $event array + * + * @category Horde + * @package Horde_Log + * @subpackage Filters + * @author James Pepin + * @license http://opensource.org/licenses/bsd-license.php BSD + * + * @todo Implement constraint objects for the different types of filtering ie + * regex,required,type..etc.. so we can add different constaints ad infinitum. + */ +class Horde_Log_Filter_Constraint implements Horde_Log_Filter_Interface +{ + private $_constraints = array(); + + /** + * Add a constraint to the filter + * + * @param string $field The field to apply the constraint to + * @param Horde_Constraint $constraint The constraint to apply + */ + public function addConstraint($field, Horde_Constraint $constraint) + { + if ($this->_constraints[$field] instanceof Horde_Constraint) { + $this->_constraints[$field] = new Horde_Constraint_And($this->_constraints[$field], $constraint); + } else { + $this->_constraints[$field] = $constraint; + } + } + + /** + * Add a regular expression to filter by + * + * Takes a field name and a regex, if the regex does not match then the + * event is filtered. + * + * @param string $field The name of the field that should be part of the event + * @param string $regex The regular expression to filter by + */ + public function addRegex($field, $regex) + { + $constraint = new Horde_Constraint_PregMatch($regex); + $this->addConstraint($field, $constraint); + } + + /** + * Add a required field to the filter + * + * If the field does not exist on the event, then it is filtered. + * + * @param string $field The name of the field that should be part of the event + */ + public function addRequiredField($field) + { + $notNull = new Horde_Constraint_Not(new Horde_Constraint_Null()); + $this->addConstraint($field, $notNull); + } + + /** + * Adds all arguments passed as required fields + */ + public function addRequiredFields() + { + $fields = func_get_args(); + foreach ($fields as $f) { + $this->addRequiredField($f); + } + } + + /** + * Returns TRUE to accept the message, FALSE to block it. + * + * @param array $event Log event + * @return boolean accepted? + */ + public function accept($event) + { + foreach ($this->_constraints as $field => $constraint) { + if (!$constraint->evaluate($event[$field])) { + return false; + } + } + return true; + } +} diff --git a/framework/Log/package.xml b/framework/Log/package.xml index 78551113e..65609b88e 100644 --- a/framework/Log/package.xml +++ b/framework/Log/package.xml @@ -20,10 +20,10 @@ http://pear.php.net/dtd/package-2.0.xsd"> mike@maintainable.com yes - 2009-02-09 - + 2009-09-25 + - 0.2.0 + 0.3.0 0.2.0 @@ -31,7 +31,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> beta BSD - * Added Horde_Log_Filter_Suppress. + * Added Horde_Log_Filter_Constraint, for flexible filtering per-field by the Horde_Constraint package @@ -39,6 +39,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + @@ -72,13 +73,18 @@ http://pear.php.net/dtd/package-2.0.xsd"> 5.2 - 1.5.0 + 1.7.0 + + Constraint + pear.horde.org + + diff --git a/framework/Log/test/Horde/Log/Filter/ConstraintTest.php b/framework/Log/test/Horde/Log/Filter/ConstraintTest.php new file mode 100644 index 000000000..0e51483ee --- /dev/null +++ b/framework/Log/test/Horde/Log/Filter/ConstraintTest.php @@ -0,0 +1,111 @@ + + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage UnitTests + * @author James Pepin + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Filter_ConstraintTest extends Horde_Test_Case +{ + public function testFilterDoesNotAcceptWhenRequiredFieldIsMissing() + { + $event = array( + 'someotherfield' => 'other value', + ); + $filterator = new Horde_Log_Filter_Constraint(); + $filterator->addRequiredField('required_field'); + + $this->assertFalse($filterator->accept($event)); + } + + public function testFilterAcceptsWhenRequiredFieldisPresent() + { + $event = array( + 'required_field' => 'somevalue', + 'someotherfield' => 'other value', + ); + $filterator = new Horde_Log_Filter_Constraint(); + $filterator->addRequiredField('required_field'); + + $this->assertTrue($filterator->accept($event)); + } + + public function testFilterAcceptsWhenRegexMatchesField() + { + $event = array( + 'regex_field' => 'somevalue', + 'someotherfield' => 'other value', + ); + $filterator = new Horde_Log_Filter_Constraint(); + $filterator->addRegex('regex_field', '/somevalue/'); + + $this->assertTrue($filterator->accept($event)); + } + + public function testFilterAcceptsWhenRegex_DOESNOT_MatcheField() + { + $event = array( + 'regex_field' => 'somevalue', + 'someotherfield' => 'other value', + ); + $filterator = new Horde_Log_Filter_Constraint(); + $filterator->addRegex('regex_field', '/someothervalue/'); + + $this->assertFalse($filterator->accept($event)); + } + + private function getConstraintMock($returnVal) + { + $const = $this->getMock('Horde_Constraint', array('evaluate')); + $const->expects($this->once()) + ->method('evaluate') + ->will($this->returnValue($returnVal)); + return $const; + } + + public function testFilterCallsEvalOnAllConstraintsWhenTheyAreAllTrue() + { + $filterator = new Horde_Log_Filter_Constraint(); + $filterator->addConstraint('fieldname', $this->getConstraintMock(true)); + $filterator->addConstraint('fieldname', $this->getConstraintMock(true)); + + $filterator->accept(array('fieldname' => 'foo')); + } + + public function testFilterStopsWhenItFindsAFalseCondition() + { + $filterator = new Horde_Log_Filter_Constraint(); + $filterator->addConstraint('fieldname', $this->getConstraintMock(true)); + $filterator->addConstraint('fieldname', $this->getConstraintMock(true)); + $filterator->addConstraint('fieldname', new Horde_Constraint_AlwaysFalse()); + + $const = $this->getMock('Horde_Constraint', array('evaluate')); + $const->expects($this->never()) + ->method('evaluate'); + $filterator->addConstraint('fieldname', $const); + $filterator->accept(array('fieldname' => 'foo')); + + } + + public function testFilterAcceptCallsConstraintOnNullWhenFieldDoesnotExist() + { + $filterator = new Horde_Log_Filter_Constraint(); + $const = $this->getMock('Horde_Constraint', array('evaluate')); + $const->expects($this->once()) + ->method('evaluate') + ->with(null); + $filterator->addConstraint('fieldname', $const); + $filterator->accept(array('someotherfield' => 'foo')); + } +}