<?php
/**
 * i-doit - Documentation and CMDB solution for IT environments
 *
 * This file is part of the i-doit framework. Modify at your own risk.
 *
 * Please visit http://www.i-doit.com/license for a full copyright and license information.
 *
 * @version     1.10
 * @package     i-doit
 * @author      synetics GmbH
 * @copyright   synetics GmbH
 * @url         http://www.i-doit.com
 * @license     http://www.i-doit.com/license
 */

namespace error_trackers\rollbar;

use error_trackers\Trackable;
use Rollbar\Payload\Level;
use Rollbar\Rollbar;

/**
 * i-doit
 *
 * Error Tracker Module
 *
 * @package     error_trackers\rollbar
 * @subpackage  error_tracker
 * @author      Dennis Stücken <dstuecken@synetics.de>
 * @version     1.5
 * @copyright   synetics GmbH
 * @license     http://www.i-doit.com/license
 * @since       i-doit 1.5
 */
class Tracker extends Rollbar implements Trackable
{
    /**
     * @var string
     */
    private $auth_token = '819c86f54fb74063a6aa9523fda2427e';

    /**
     * @var string
     */
    private $environment = 'Production';

    /**
     * Report an exception
     *
     * @param \Exception $exc
     *
     * @return Trackable
     */
    public function exception(\Exception $exc)
    {
        if (\isys_tenantsettings::get('error-tracker.enabled', true))
        {
            parent::log(Level::ERROR, $exc);
        }

        return $this;
    }

    /**
     * This function must return false so that the default php error handler runs
     *
     * @param $errno
     * @param $errstr
     * @param $errfile
     * @param $errline
     *
     * @return bool
     */
    public static function report_php_error($errno, $errstr, $errfile, $errline)
    {
        // Skip notices and warnings.
        if ($errno === E_NOTICE || $errno === E_WARNING)
        {
            return false;
        }

        return self::log(Level::ERROR, $errstr, $errfile . ' ' . $errline);
    }

    /**
     * Initialize and assign javascript code to track errors
     */
    private function initRollbarJS()
    {
        if (file_exists(__DIR__ . '/rollbar-1.3.2-min.js') && is_readable(__DIR__ . '/rollbar-1.3.2-min.js'))
        {
            $jsCode = str_replace(
                ['%TOKEN%', '%ENVIRONMENT%'],
                [$this->auth_token, $this->environment],
                file_get_contents(__DIR__ . '/rollbar-1.3.2-min.js')
            );

            \isys_application::instance()->template->assign('errorTrackerCode', $jsCode);
        }
    }

    /**
     * Initialize rollbar
     */
    public function initialize($config = [])
    {
        // We use an own error handler to filter notices and warnings.
        set_error_handler([$this, 'report_php_error']);

        // Set environment.
        if (!isset($config['environment']))
        {
            $this->environment = \isys_tenantsettings::get('error-tracker.environment', 'Production');
        }
        else
        {
            $this->environment = $config['environment'];
        }

        // May override the token.
        if (!isset($config['auth_token']))
        {
            $this->auth_token = \isys_tenantsettings::get('error-tracker.auth_token', $this->auth_token);
        }
        else
        {
            $this->auth_token = $config['auth_token'];
        }

        // Fill persondata.
        $userdata             = \isys_application::instance()->session->get_userdata();
        $userdata['username'] = \isys_application::instance()->session->get_current_username();

        $additional_scrubs = [];

        if (\isys_tenantsettings::get('error-tracker.anonymize', 1))
        {
            $additional_scrubs = [
                'Host',
                'host',
                'user_ip',
                'server.host'
            ];
            $userdata          = null;
        }

        // Activate proxy if needed.
        if (\isys_settings::get('proxy.host', false))
        {
            $config['proxy'] = [
                'address'  => \isys_settings::get('proxy.host') . ":" . \isys_settings::get('proxy.port'),
                'username' => \isys_settings::get('proxy.username'),
                'password' => \isys_settings::get('proxy.password')
            ];
        }

        $this->initRollbarJS();

        // Initialize.
        parent::init(
            [
                // required
                'access_token'              => $this->auth_token,
                // optional - environment name. any string will do.
                'environment'               => $this->environment,
                // optional - path to directory your code is in. used for linking stack traces.
                'root'                      => \isys_application::instance()->app_path,
                // i-doit version
                'code_version'              => \isys_application::instance()->info->get('version'),
                // user info
                'person'                    => $userdata,
                // optional - path to directory your code is in. used for linking stack traces.
                'root'                      => \isys_application::instance()->app_path,
                // Sets whether errors suppressed with '@' should be reported or not
                'report_suppressed'         => false,
                // Record full stacktraces for PHP errors.
                'capture_error_stacktraces' => true,
                // Array of field names to scrub out of _POST and _SESSION
                'scrub_fields'              => [
                        'Cookie',
                        'session_data',
                        'user_setting',
                        'username',
                        'user_mandator',
                        'cRecStatusListView',
                        'cmdb_status',
                        'session',
                       //  'headers',
                        'login_password',
                        'login_username',
                        'C__MODULE__LDAP__PASS',
                        'C__CATG__PASSWORD__PASSWORD'
                    ] + $additional_scrubs
            ] + $config,
            true,
            false
        );
    }

    /**
     * Just report a message
     *
     * @param        $message
     * @param string $level
     * @param array  $data
     *
     * @return Trackable
     */
    public function message($message, $level = 'error', $data = [])
    {
        if (\isys_tenantsettings::get('error-tracker.enabled', true))
        {
            try
            {
                $anonymize = \isys_tenantsettings::get('error-tracker.anonymize', 1);
                $that      = $this;

                register_shutdown_function(
                    function () use ($that, $message, $level, $data, $anonymize) {
                        if ($anonymize)
                        {
                            foreach ($_POST as $key => $value)
                            {
                                $GLOBALS['_POST'][$key] = '';
                            }
                        }

                        $that->log(
                            $level,
                            $message,
                            [
                                'package'    => \isys_application::instance()->info->get('type'),
                                'os'         => php_uname(),
                                'phpversion' => phpversion()
                            ] + $data
                        );
                    }
                );
            }
            catch (\Exception $e)
            {
                \isys_application::instance()->logger->addWarning($e->getMessage());
            }
        }

        return $this;
    }

    /**
     * Flush messages and force sending them to the tracking instance
     *
     * @return Trackable
     */
    public function send()
    {
        if (\isys_tenantsettings::get('error-tracker.enabled', true))
        {
            parent::flush();
        }

        return $this;
    }
}