<commit_before><?php
/**
 * @package DF_Web
 */


require_once 'DF/Error/InvalidArgumentException.php';


/**
 * An object instance of this class represents an action to execute in a
 * controller.
 * 
 * Multiple actions can be stacked and will be executed in the order they
 * are stacked.
 * 
 * When forwarding to a method in the same or a new controller, a new action
 * instance is created and placed on top of the stack, to be executed
 * immediately.
 * 
 * An object of this class is immutable. Respect that when subclassing.
 */
class DF_Web_Action {
    public static $LOGGER = NULL;
    
    protected $controller   = NULL;
    protected $method       = NULL;
    protected $arguments    = NULL;


    /**
     * Constructor.
     * 
     * @param string $controller
     * @param string $method
     * @param array $args
     * @return DF_Web_Action
     */
    public function __construct($controller, $method, $args) {
        if (!is_string($controller)) {
            throw new DF_Error_InvalidArgumentException('controller', $controller, 'string');
        }

        if (!is_string($method)) {
            # TODO Could this parameter be anything other than string?
            throw new DF_Error_InvalidArgumentException('method', $method, 'string');
        }

        if ($args && !is_array($args)) {
            throw new DF_Error_InvalidArgumentException('args', $args, 'array');
        }
    
        $this->controller   = $controller;
        $this->method       = $method;
        $this->arguments    = $args;
    }


    public function get_controller() {
        return $this->controller;
    }


    public function get_method() {
        return $this->method;
    }


    public function get_arguments() {
        return $this->arguments;
    }


    public function dispatch($c) {
        if (!$c instanceof DF_Web) {
            throw new DF_Error_InvalidArgumentException("c", $c, DF_Web);
        }
        
        return $c->execute_action($this);
    }


    public function execute($controller, $c) {
        if (!$controller instanceof DF_Web_Controller) {
            throw new DF_Error_InvalidArgumentException("controller", $controller, DF_Web_Controller);
        }

        if (!$c instanceof DF_Web) {
            throw new DF_Error_InvalidArgumentException("c", $c, DF_Web);
        }
        
        $method_name    = $this->get_method();
        $arguments      = $this->get_arguments();

        # Prepend the context object to the argumentlist
        if ($arguments == NULL) {
            $arguments = array();
        }
        array_unshift($arguments, $c);

        if (!method_exists($controller, $method_name)) {
            $argstr = DF_Web_Utils_Arguments::flatten_arguments_list($arguments);
            throw new DF_Web_Exception("No such method: ${ctrl_name}->${method_name}($argstr)");
        }
        # TODO how can I check the PHP access level of a method?
        #elseif (!is_callable($controller, $method_name)) {
        #    throw new DF_Web_Exception("Method is not public: $ctrl_name::$method_name");
        #}

        try {
            $ret = call_user_func_array(
                array($controller, $method_name),
                $arguments
            );

            return $ret;
        }
        catch (DF_Web_Detach_Exception $ex) {
            // Rethrow the exception to continue breaking the chain
            throw $ex;
        }
        catch (DF_Web_Exception $ex) {
            $c->add_error($ex);
            self::$LOGGER->error("Fatal exception: ".$ex->getMessage());
        }
        catch (Exception $ex) {
            $c->add_error($ex);
            self::$LOGGER->error("Fatal exception, breaking off chain: ".$ex->getMessage());
            throw new DF_Web_Detach_Exception(
                $this,
                "Got an error we cannot handle"
            );
        }

        return false;
    }


    public function equals($action) {
        if (NULL === $action) {
            return false;
        }
        
        if ($this === $action) {
            return true;
        }

        if (get_class($action) !== get_class($this)) {
            return false;
        }

        if ($this->get_controller() != $action->get_controller()) {
            return false;
        }

        if ($this->get_method() != $action->get_method()) {
            return false;
        }

        if ($this->get_arguments() != $action->get_arguments()) {
            return false;
        }

        return true;
    }


    public function toString() {
        $args = DF_Web_Utils_Arguments::flatten_arguments_list($this->arguments);
        $ctrl   = $this->controller;
        $method = $this->method;

        return "{$ctrl}->{$method}({$args})";
    }
}

DF_Web_Action::$LOGGER = DF_Web_Logger::logger('DF_Web_Action');
<commit_msg>Added a tostring method. Only flatten arguments list if the action has any arguments<commit_after><?php
/**
 * @package DF_Web
 */


require_once 'DF/Error/InvalidArgumentException.php';


/**
 * An object instance of this class represents an action to execute in a
 * controller.
 * 
 * Multiple actions can be stacked and will be executed in the order they
 * are stacked.
 * 
 * When forwarding to a method in the same or a new controller, a new action
 * instance is created and placed on top of the stack, to be executed
 * immediately.
 * 
 * An object of this class is immutable. Respect that when subclassing.
 */
class DF_Web_Action {
    public static $LOGGER = NULL;
    
    protected $controller   = NULL;
    protected $method       = NULL;
    protected $arguments    = NULL;


    /**
     * Constructor.
     * 
     * @param string $controller
     * @param string $method
     * @param array $args
     * @return DF_Web_Action
     */
    public function __construct($controller, $method, $args) {
        if (!is_string($controller)) {
            throw new DF_Error_InvalidArgumentException('controller', $controller, 'string');
        }

        if (!is_string($method)) {
            # TODO Could this parameter be anything other than string?
            throw new DF_Error_InvalidArgumentException('method', $method, 'string');
        }

        if (NULL === $args) {
            // ok
        }
        elseif (!is_array($args)) {
            throw new DF_Error_InvalidArgumentException('args', $args, 'array');
        }
    
        $this->controller   = $controller;
        $this->method       = $method;
        $this->arguments    = $args;
    }


    public function get_controller() {
        return $this->controller;
    }


    public function get_method() {
        return $this->method;
    }


    public function get_arguments() {
        return $this->arguments;
    }


    public function dispatch($c) {
        if (!$c instanceof DF_Web) {
            throw new DF_Error_InvalidArgumentException("c", $c, DF_Web);
        }
        
        return $c->execute_action($this);
    }


    public function execute($controller, $c) {
        if (!$controller instanceof DF_Web_Controller) {
            throw new DF_Error_InvalidArgumentException("controller", $controller, DF_Web_Controller);
        }

        if (!$c instanceof DF_Web) {
            throw new DF_Error_InvalidArgumentException("c", $c, DF_Web);
        }
        
        $method_name    = $this->get_method();
        $arguments      = $this->get_arguments();

        # Prepend the context object to the argumentlist
        if ($arguments == NULL) {
            $arguments = array();
        }
        array_unshift($arguments, $c);

        if (!method_exists($controller, $method_name)) {
            $argstr = DF_Web_Utils_Arguments::flatten_arguments_list($arguments);
            throw new DF_Web_Exception("No such method: ${ctrl_name}->${method_name}($argstr)");
        }
        # TODO how can I check the PHP access level of a method?
        #elseif (!is_callable($controller, $method_name)) {
        #    throw new DF_Web_Exception("Method is not public: $ctrl_name::$method_name");
        #}

        try {
            $ret = call_user_func_array(
                array($controller, $method_name),
                $arguments
            );

            return $ret;
        }
        catch (DF_Web_Detach_Exception $ex) {
            // Rethrow the exception to continue breaking the chain
            throw $ex;
        }
        catch (DF_Web_Exception $ex) {
            $c->add_error($ex);
            self::$LOGGER->error("Fatal exception: ".$ex->getMessage());
        }
        catch (Exception $ex) {
            $c->add_error($ex);
            self::$LOGGER->error("Fatal exception, breaking off chain: ".$ex->getMessage());
            throw new DF_Web_Detach_Exception(
                $this,
                "Got an error we cannot handle"
            );
        }

        return false;
    }


    public function equals($action) {
        if (NULL === $action) {
            return false;
        }
        
        if ($this === $action) {
            return true;
        }

        if (get_class($action) !== get_class($this)) {
            return false;
        }

        if ($this->get_controller() != $action->get_controller()) {
            return false;
        }

        if ($this->get_method() != $action->get_method()) {
            return false;
        }

        if ($this->get_arguments() != $action->get_arguments()) {
            return false;
        }

        return true;
    }


    public function toString() {
        $args = "";
        if ($this->arguments) {
            $args = DF_Web_Utils_Arguments::flatten_arguments_list($this->arguments);
        }
        $ctrl   = $this->controller;
        $method = $this->method;

        return "{$ctrl}->{$method}({$args})";
    }


    public function __toString() {
        return $this->toString();
    }
}

DF_Web_Action::$LOGGER = DF_Web_Logger::logger('DF_Web_Action');

{'fraction_non_alphanumeric': 0.11884379091550006, 'fraction_numerical': 0.0, 'mean_word_length': 2.0209917858229387, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4692619', 'n_tokens_mistral': 2800, 'n_tokens_neox': 2680, 'n_words': 712}