<commit_before><?php
namespace UNL\UCBCN\Frontend;

class OutputController extends \Savvy
{
    protected $theme = 'default';

    public function __construct($options = array())
    {
        \Savvy_ClassToTemplateMapper::$classname_replacement = __NAMESPACE__ . '\\';
        parent::__construct();
        $this->initialize($options);
    }

    public function initialize($options = array())
    {

        switch ($options['format']) {
            case 'json':
                header('Content-type:application/json');
                $this->sendCORSHeaders();
                $this->setTemplateFormatPaths($options['format']);
                break;

            case 'ics':
            case 'ical':
            case 'icalendar':
                header('Content-type:text/calendar');
                header('Content-Disposition: attachment; filename="events.ics"');
                $this->setTemplateFormatPaths('icalendar');
                break;

            case 'pdf':
                header('Content-type:application/pdf');
                $this->setTemplateFormatPaths($options['format']);
                break;

            case 'xml':
                header('Content-type:text/xml');
                $this->setTemplateFormatPaths($options['format']);
                break;

            case 'rss':
                header('Content-type:application/rss+xml');
                $this->sendCORSHeaders();
                $this->setTemplateFormatPaths($options['format']);
                break;

            case 'csv':
                if (!isset($this->options['delimiter'])) {
                    $this->options['delimiter'] = ',';
                }

                $this->addGlobal('delimiter', $this->options['delimiter']);
                $this->addGlobal('delimitArray', function($delimiter, $array){
                    $out = fopen('php://output', 'w');
                    fputcsv($out, $array, $delimiter);
                });

                $filename = str_replace("\\", "_", $options['model']) . "." . $options['format'];
                header('Content-disposition: attachment; filename=' . $filename);

            case 'txt':
                header('Content-type:text/plain;charset=UTF-8');
                $this->setTemplateFormatPaths($options['format']);
                break;

            case 'partial':
            case 'hcalendar':
                $this->sendCORSHeaders();
                \Savvy_ClassToTemplateMapper::$output_template[__NAMESPACE__ . '\Controller'] = 'Controller-partial';
                // intentional no-break

            case 'html':
                // Always escape output, use $context->getRaw('var'); to get the raw data.
                $this->setEscape(function($data) {
                    return htmlspecialchars($data, ENT_QUOTES, 'UTF-8', false);
                });
                header('Content-type:text/html;charset=UTF-8');
                $this->setTemplateFormatPaths('html');
                $this->addFilters(array(new OutputController\PostRunFilter\HTML($options), 'postRun'));
                break;
            default:
                throw new UnexpectedValueException('Invalid/unsupported output format', 500);
        }
    }

    /**
     * Set a specific theme for this instance
     * 
     * @param string $theme Theme name, which corresponds to a directory in www/
     * 
     * @throws Exception
     */
    public function setTheme($theme)
    {
        if (!is_dir($this->getWebDir() . '/themes/'.$theme)) {
            throw new Exception('Invalid theme, there are no files in '.$dir);
        }
        $this->theme = $theme;
    }

    /**
     * Set the array of template paths necessary for this format
     * 
     * @param string $format Format to use
     */
    public function setTemplateFormatPaths($format)
    {
        $web_dir = $this->getWebDir();

        // The 'default' theme is always on the path as a fallback
        $themes = array($web_dir . '/templates/default/' . $format);

        // If we've customized the theme, add that directory to the path
        if ($this->theme != 'default') {
            $themes[] = $web_dir . '/templates/' . $this->theme . '/' . $format;
        }

        $this->setTemplatePath($themes);
    }

    /**
     * Get the path to the root web directory
     *
     * @return string
     */
    protected function getWebDir()
    {
        return dirname(dirname(dirname(dirname(__DIR__)))) . '/www';
    }

    public function setReplacementData($field, $data)
    {
        foreach ($this->getConfig('filters') as $filter) {
            $filter[0]->setReplacementData($field, $data);<commit_msg>Allow custom templates for the hcalendar format<commit_after><?php
namespace UNL\UCBCN\Frontend;

class OutputController extends \Savvy
{
    protected $theme = 'default';

    public function __construct($options = array())
    {
        \Savvy_ClassToTemplateMapper::$classname_replacement = __NAMESPACE__ . '\\';
        parent::__construct();
        $this->initialize($options);
    }

    public function initialize($options = array())
    {

        switch ($options['format']) {
            case 'json':
                header('Content-type:application/json');
                $this->sendCORSHeaders();
                $this->setTemplateFormatPaths($options['format']);
                break;

            case 'ics':
            case 'ical':
            case 'icalendar':
                header('Content-type:text/calendar');
                header('Content-Disposition: attachment; filename="events.ics"');
                $this->setTemplateFormatPaths('icalendar');
                break;

            case 'pdf':
                header('Content-type:application/pdf');
                $this->setTemplateFormatPaths($options['format']);
                break;

            case 'xml':
                header('Content-type:text/xml');
                $this->setTemplateFormatPaths($options['format']);
                break;

            case 'rss':
                header('Content-type:application/rss+xml');
                $this->sendCORSHeaders();
                $this->setTemplateFormatPaths($options['format']);
                break;

            case 'csv':
                if (!isset($this->options['delimiter'])) {
                    $this->options['delimiter'] = ',';
                }

                $this->addGlobal('delimiter', $this->options['delimiter']);
                $this->addGlobal('delimitArray', function($delimiter, $array){
                    $out = fopen('php://output', 'w');
                    fputcsv($out, $array, $delimiter);
                });

                $filename = str_replace("\\", "_", $options['model']) . "." . $options['format'];
                header('Content-disposition: attachment; filename=' . $filename);

            case 'txt':
                header('Content-type:text/plain;charset=UTF-8');
                $this->setTemplateFormatPaths($options['format']);
                break;

            case 'partial':
            case 'hcalendar':
                $this->sendCORSHeaders();
                \Savvy_ClassToTemplateMapper::$output_template[__NAMESPACE__ . '\Controller'] = 'Controller-partial';
                // intentional no-break

            case 'html':
                // Always escape output, use $context->getRaw('var'); to get the raw data.
                $this->setEscape(function($data) {
                    return htmlspecialchars($data, ENT_QUOTES, 'UTF-8', false);
                });
                header('Content-type:text/html;charset=UTF-8');
                $this->setTemplateFormatPaths('html');
                if ($options['format'] == 'hcalendar') {
                    //For the hcalendar format, we may want to customize some templates, but we should fall back on html.
                    $themes = $this->getTemplateFormatPaths('hcalendar');
                    $this->addTemplatePath($themes);
                }
                $this->addFilters(array(new OutputController\PostRunFilter\HTML($options), 'postRun'));
                break;
            default:
                throw new UnexpectedValueException('Invalid/unsupported output format', 500);
        }
    }

    /**
     * Set a specific theme for this instance
     * 
     * @param string $theme Theme name, which corresponds to a directory in www/
     * 
     * @throws Exception
     */
    public function setTheme($theme)
    {
        if (!is_dir($this->getWebDir() . '/themes/'.$theme)) {
            throw new Exception('Invalid theme, there are no files in '.$dir);
        }
        $this->theme = $theme;
    }

    /**
     * Set the array of template paths necessary for this format
     * 
     * @param string $format Format to use
     */
    public function setTemplateFormatPaths($format)
    {
        $themes = $this->getTemplateFormatPaths($format);

        $this->setTemplatePath($themes);
    }
    
    public function getTemplateFormatPaths($format)
    {
        $web_dir = $this->getWebDir();

        // The 'default' theme is always on the path as a fallback
        $themes = array(
            $web_dir . '/templates/default/', //add the default as a path so that we can reference other formats when rendering
            $web_dir . '/templates/default/' . $format
        );

        // If we've customized the theme, add that directory to the path
        if ($this->theme != 'default') {
            $themes[] = $web_dir . '/templates/' . $this->theme . '/' . $format;
        }
        
        return $themes;
    }

    /**
     * Get the path to the root web directory
     *
     * @return string
     */
    protected function getWebDir()
    {
        return dirname(dirname(dirname(dirname(__DIR__)))) . '/www';
    }

    public function setReplacementData($field, $data)
    {
        foreach ($this->getConfig('filters') as $filter) {
            $filter[0]->setReplacementData($field, $data);
{'fraction_non_alphanumeric': 0.1373394863563403, 'fraction_numerical': 0.0014044943820224719, 'mean_word_length': 1.8312979267253622, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 6}, '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': '3822410', 'n_tokens_mistral': 2635, 'n_tokens_neox': 2476, 'n_words': 552}