<?php
/**
* Test for a key contained in an array.
* @package SimpleTest
* @subpackage UnitTester
*/
class ArrayHasKeyExpectation extends SimpleExpectation {
    var $_array;

    /**
    * Sets the array required for the comparison.
    * @param array $array Array used for testing.
    * @param string $message Customised message on failure.
    * @access public
    */
    function ArrayHasKeyExpectation($array, $message = '%s') {
        $this->SimpleExpectation($message);
        $this->_array = $array;
    }

    /**
    * Tests the expectation. True if it matches the
    * held value.
    * @param string $compare Comparison value.
    * @return boolean True if correct.
    * @access public
    */
    function test($compare) {
        $keys = array_keys ($this->_array);
        foreach ($keys as $key) {
            if ($key === $compare) {
                return true;
            }//if
        }//foreach
        return false;
    }

    /**
    * Returns a human readable test message.
    * @param string $compare Key being tested.
    * @return string Description of success
    * or failure.
    * @access public
    */
    function testMessage($compare) {
        if ($this->test($compare)) {
            return $this->_containsKeyMessage($compare);
        } else {
            return $this->_containsKeyNotMessage($compare);
        }
    }

    /**
    * Creates a the message for the containing case.
    * @param string $compare Key being tested.
    * @access private
    */
    function _containsKeyMessage($compare) {
        return "Array contains key " . $compare;
    }

    /**
    * Creates a the message for the not containing case.
    * @param string $compare Key being tested.
    * @access private
    */
    function _containsKeyNotMessage($compare) {
        return "Array does not contain key " . $compare;
    }
}

/**
* Test for a key not contained in an array.
* @package SimpleTest
* @subpackage UnitTester
*/
class ArrayNotHasKeyExpectation extends ArrayHasKeyExpectation {
    var $_array;

    /**
    * Sets the array required for the comparison.
    * @param array $array Array used for testing.
    * @param string $message Customised message on failure.
    * @access public
    */
    function ArrayNotHasKeyExpectation($array, $message = '%s') {
        $this->ArrayHasKeyExpectation($array, $message);
    }

    /**
    * Tests the expectation. True if it matches the
    * held value.
    * @param string $compare Comparison value.
    * @return boolean True if correct.
    * @access public
    */
    function test($compare) {
        return ! parent::test($compare);
    }

    /**
    * Returns a human readable test message.
    * @param string $compare Key being tested.
    * @return string Description of success
    * or failure.
    * @access public
    */
    function testMessage($compare) {
        if ($this->test($compare)) {
            return $this->_containsKeyMessage($compare);
        } else {
            return $this->_containsKeyNotMessage($compare);
        }
    }
}

/**
* Test for a value contained in an array.
* @package SimpleTest
* @subpackage UnitTester
*/
class ArrayHasValueExpectation extends SimpleExpectation {
    var $_array;

    /**
    * Sets the array required for the comparison.
    * @param array $array Array used for testing.
    * @param string $message Customised message on failure.
    * @access public
    */
    function ArrayHasValueExpectation($array, $message = '%s') {
        $this->SimpleExpectation($message);
        $this->_array = $array;
    }

    /**
    * Tests the expectation. True if it matches the
    * held value.
    * @param string $compare Comparison value.
    * @return boolean True if correct.
    * @access public
    */
    function test($compare) {
        $keys = array_values ($this->_array);
        foreach ($keys as $key) {
            if ($key === $compare) {
                return true;
            }//if
        }//foreach
        return false;
    }

    /**
    * Returns a human readable test message.
    * @param string $compare Key being tested.
    * @return string Description of success
    * or failure.
    * @access public
    */
    function testMessage($compare) {
        if ($this->test($compare)) {
            return $this->_containsValueMessage($compare);
        } else {
            return $this->_containsValueNotMessage($compare);
        }
    }

    /**
    * Creates a the message for the containing case.
    * @param string $compare Value being tested.
    * @access private
    */
    function _containsValueMessage($compare) {
        return "Array contains value " . $compare;
    }

    /**
    * Creates a the message for the not containing case.
    * @param string $compare Value being tested.
    * @access private
    */
    function _containsValueNotMessage($compare) {
        return "Array does not contain value " . $compare;
    }
}


/**
* Test for a value not contained in an array.
* @package SimpleTest
* @subpackage UnitTester
*/
class ArrayNotHasValueExpectation extends ArrayHasValueExpectation {
    /**
    * Sets the array required for the comparison.
    * @param array $array Array used for testing.
    * @param string $message Customised message on failure.
    * @access public
    */
    function ArrayNotHasValueExpectation($array, $message = '%s') {
        $this->ArrayHasValueExpectation($array, $message);
    }

    /**
    * Tests the expectation. True if it matches the
    * held value.
    * @param string $compare Comparison value.
    * @return boolean True if correct.
    * @access public
    */
    function test($compare) {
        return ! parent::test($compare);
    }

    /**
    * Returns a human readable test message.
    * @param string $compare Key being tested.
    * @return string Description of success
    * or failure.
    * @access public
    */
    function testMessage($compare) {
        if ($this->test($compare)) {
            return $this->_containsValueMessage($compare);
        } else {
            return $this->_containsValueNotMessage($compare);
        }
    }
}

// I tested the above-mentioned code by using the following test function:

public function test_Expectations () {
    $array = array ('foo' => 'bar', 100 => 0, 'color' => 'red', 'elem' => array (0 => 1));

    $this->assert(new ArrayHasValueExpectation($array), 'bar');
    $this->assert(new ArrayNotHasValueExpectation($array), 'blue');
    $this->assert(new ArrayHasKeyExpectation($array), 100);
    $this->assert(new ArrayNotHasKeyExpectation($array), 'colour');
    $this->assert(new ArrayHasKeyExpectation($array), 'elem');
    $this->assert(new ArrayHasValueExpectation($array), array (0 => 1));
    $this->assert(new ArrayNotHasValueExpectation($array), array (1 => 0));
}

