<?php
/**
 * DokuWiki Plugin feedback (Action Component)
 *
 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
 * @author  Andreas Gohr <gohr@cosmocode.de>
 */

// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();

class action_plugin_feedback extends DokuWiki_Action_Plugin {

    /*
     * @var true if we are on the detail page
     */
    protected $detail_page = false;

    /**
     * Registers a callback function for a given event
     *
     * @param Doku_Event_Handler $controller DokuWiki's event controller object
     * @return void
     */
    public function register(Doku_Event_Handler $controller) {

        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax');
        $controller->register_hook('DETAIL_STARTED', 'BEFORE', $this, 'handle_detail_started');
        $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'handleDokuStarted');
    }

    /**
     * Chceck if we can give a feedback
     *
     * @return bool
     */
    protected function feedback_possible() {
        global $ACT, $ID;

        // only on show and detail pages
        if($ACT != 'show' && !$this->detail_page) return false;
        // allow anonymous feedback?
        if(!$_SERVER['REMOTE_USER'] && !$this->getConf('allowanon')) return false;
        // any contact defined?
        if(!$this->getFeedbackContact($ID)) return false;

        return true;
    }

    /**
     * [Custom event handler which performs action]
     *
     * @param Doku_Event $event  event object by reference
     * @param mixed $param  [the parameters passed as fifth argument to register_hook() when this
     *                           handler was registered]
     * @return void
     */

    public function handle_ajax(Doku_Event &$event, $param) {
        // our event?
        if($event->data != 'plugin_feedback') return;
        $event->preventDefault();
        $event->stopPropagation();

        // allow anonymous feedback?
        if(!$_SERVER['REMOTE_USER'] && !$this->getConf('allowanon')) {
            http_status(400);
            die('no anonymous access');
        }

        // get submitted data
        global $INPUT;
        $id = $INPUT->str('id');
        $feedback = $INPUT->str('feedback');
        $media = $INPUT->bool('media');

        // get the responsible contact
        $contact = $this->getFeedbackContact($id);
        if(!$contact) {
            http_status(400);
            die('no contact defined');
        }

        // get info on user
        $user = null;
        if($_SERVER['REMOTE_USER']) {
            /** @var DokuWiki_Auth_Plugin $auth */
            global $auth;
            $user = $auth->getUserData($_SERVER['REMOTE_USER']);
            if(!$user) $user = null;
        }

        // send the mail
        $mailer = new Mailer();
        $mailer->to($contact);
        if($user) $mailer->setHeader('Reply-To', $user['mail']);
        $mailer->subject($this->getLang('subject'));
        if ($media) {
            $url = ml($id, '', false, '&amp;', true);
        } else {
            $url = wl($id, '', true);
        }
        $mailer->setBody(
            io_readFile($this->localFN('mail')),
            array('PAGE' => $id, 'FEEDBACK' => $feedback, 'URL' => $url),
            array('FEEDBACK' => nl2br($feedback))
        );
        $success = $mailer->send();
        //send a copy to the author
        if ($success && $user && $this->getConf('send_copy')) {
            //insert headers unseted by send()
            $mailer->to($user['mail']);
            $mailer->subject($this->getLang('subject'));
            $success = $mailer->send();
        }
        header('Content-Type: text/html; charset=utf-8');

        if (!$success) {
            echo $this->getLang('error');
            return;
        }

        echo $this->getLang('thanks');
    }

    /**
     * set our JSINFO isMedia-flag to false
     *
     * this simplifies our js, becuase now window.JSINFO.plugins.feedback.isMedia is always defined
     */
    public function handleDokuStarted() {
        global $JSINFO;

        if (empty($JSINFO['plugins'])) {
            $JSINFO['plugins'] = [];
        }
        $JSINFO['plugins']['feedback'] = [
            'isMedia' => false,
        ];
    }

    /**
     * Set the flag when we are on the detail page
     */
    public function handle_detail_started() {
        global $JSINFO, $ID, $IMG;

        $this->detail_page = true;

        if (empty($JSINFO)) {
            $JSINFO = [
                'id' => $ID,
                'namespace' => getNS($ID),
                'plugins' => [],
            ];
        }
        if (empty($JSINFO['plugins'])) {
            $JSINFO['plugins'] = [];
        }

        $JSINFO['plugins']['feedback'] = [
            'isMedia' => true,
            'mediaID' => $IMG
        ];
    }

    /**
     * Get the responsible contact for givven ID
     *
     * @param $id
     * @return false|string
     */
    public function getFeedbackContact($id) {
        $conf = confToHash(DOKU_CONF . 'plugin_feedback.conf');

        $ns = $id;

        if ($this->getConf('span_translations')) {
            $ns = $this->adjustForTanslations($id);
        }

        if ($this->getConf('include_parent_startpage')) {
            if(isset($conf[$ns])) {
                return $conf[$ns];
            }
        }

        do {
            $ns = getNS($ns);
            if(!$ns) $ns = '*';
            if(isset($conf[$ns])) return $conf[$ns];
        } while($ns != '*');

        return false;
    }

    /**
     * prints or returns the the action link
     *
     * Alternatively you can add the plugin_feedback class to any object in the DOM and it will be used
     * for triggering the feedback dialog
     *
     * @param bool $return
     * @return string
     */
    public function tpl($return = false) {

        if(!$this->feedback_possible()) return;

        $html = '<a href="#" class="plugin_feedback">' . $this->getLang('feedback') . '</a>';
        if($return) return $html;
        echo $html;
        return '';
    }

    /**
     * If this is a translated page, remove the language-prefix
     *
     * @param string $id
     *
     * @return string
     */
    protected function adjustForTanslations($id) {
        /** @var helper_plugin_translation $trans */
        $trans = plugin_load('helper', 'translation', defined('DOKU_UNITTEST'));
        if ($trans) {
            list(, $id) = $trans->getTransParts($id);
        } else {
            msg('Option span_translations has been activated in feedback-plugin, but translation-plugin is not installed/enabled!', -1);
        }
        return $id;
    }

}

// vim:ts=4:sw=4:et:
