private function handle($method, array $arguments, $default)
    {
        // Target property (drop set or get word)
        $property = substr($method, 3);

        // Convert to snake case
        $property = TextUtils::snakeCase($property);

        $start = substr($method, 0, 3);

        // Are we dealing with a getter?
        if ($start == 'get') {
            if ($property === false) {
                throw new LogicException('Attempted to call a getter on undefined property');
            }

            // getter is being used
            if ($this->has($property)) {
                return $this->container[$property];
            } else {
                return $default;
            }

        // Are we dealing with a setter?
        } else if ($start == 'set') {
            if ($this->once === true && $this->has($property)) {
                throw new RuntimeException(sprintf('You can write to "%s" only once', $property));
            }

            // Make sure the first argument is supplied
            if (array_key_exists(0, $arguments)) {
                $value = $arguments[0];
            } else {
                throw new UnderflowException(sprintf(
                    'The virtual setter for "%s" expects at least one argument, which would be a value. None supplied.', $property
                ));
            }

            // If filter is defined, then use it
            if (isset($arguments[1])) {
                // Override value with filtered one
                $value = Filter::sanitize($value, $arguments[1]);
            }

            // setter is being used
            $this->container[$property] = $value;
            return $this;

        } else {
            // Throw exception only on strict mode
            if ($this->strict == true) {
                throw new RuntimeException(sprintf(
                    'Virtual method name must start either from "get" or "set". You provided "%s"', $method
                ));
            }
        }
    }