<?php

declare(strict_types=1);

namespace GroundLevel\Testing;

use GroundLevel\Testing\Traits\BaseTestCase;
use GroundLevel\Testing\Traits\ReadsProperties;
use ReflectionProperty;
use WP_UnitTestCase;

/**
 * Base test case class including all default traits and utilities which extends
 * the default WordPress WP_UnitTestCase class.
 */
abstract class WPTestCase extends WP_UnitTestCase
{
    use BaseTestCase;
    use ReadsProperties {
        ReadsProperties::getProperty as grdLvlGetProperty;
        ReadsProperties::getPropertyValue as grdLvlGetPropertyValue;
    }

    /**
     * Retrieves a private or protected property of an object.
     *
     * This overloads the method patched into WP_UnitTestCase by the
     * Yoast\PHPUnitPolyfills\Helpers\AssertAttributeHelper trait. It's overloaded
     * in this way to allow our own trait to be used instead of the Yoast one withnout
     * requiring modification to our trait which is incompatible with the Yoast
     * definition but actually is compatible. Our version allows passing in static
     * class names in addition to instantiated objects.
     *
     * @param  object|string $objInstance  The object or classname.
     * @param  string        $propertyName The name of property to retrieve.
     * @return ReflectionProperty
     */
    public static function getProperty($objInstance, $propertyName): ReflectionProperty // phpcs:ignore Squiz.Commenting.FunctionComment.ScalarTypeHintMissing -- for compatibility with Yoast Polyfill
    {
        $class = get_called_class();
        return (new $class())->grdLvlGetProperty($objInstance, $propertyName);
    }

    /**
     * Retrieves the current value of a private or protected property of an object.
     *
     * This overloads the method patched into WP_UnitTestCase by the
     * Yoast\PHPUnitPolyfills\Helpers\AssertAttributeHelper trait. It's overloaded
     * in this way to allow our own trait to be used instead of the Yoast one withnout
     * requiring modification to our trait which is incompatible with the Yoast
     * definition but actually is compatible. Our version allows passing in static
     * class names in addition to instantiated objects.
     *
     * @param  object|string $objInstance  The object or classname.
     * @param  string        $propertyName The name of property for which to retrieve the value.
     * @return mixed
     */
    public static function getPropertyValue($objInstance, $propertyName) // phpcs:ignore Squiz.Commenting.FunctionComment.ScalarTypeHintMissing -- for compatibility with Yoast Polyfill
    {
        $class = get_called_class();
        return (new $class())->grdLvlGetPropertyValue($objInstance, $propertyName);
    }

    /**
     * Sets up the test case.
     */
    public function set_up() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        parent::set_up();
        remove_filter('query', [$this, '_create_temporary_table']);
        remove_filter('query', [$this, '_drop_temporary_table']);
    }
}
