xref: /plugin/combo/ComboStrap/LogUtility.php (revision e7bbc4b8899abf27ca24f9e5cf9b7d23dd40e28e)
1<?php
2/**
3 * Copyright (c) 2020. ComboStrap, Inc. and its affiliates. All Rights Reserved.
4 *
5 * This source code is licensed under the GPL license found in the
6 * COPYING  file in the root directory of this source tree.
7 *
8 * @license  GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html)
9 * @author   ComboStrap <support@combostrap.com>
10 *
11 */
12
13namespace ComboStrap;
14
15require_once(__DIR__ . '/PluginUtility.php');
16
17class LogUtility
18{
19
20    /**
21     * Constant for the function {@link msg()}
22     * -1 = error, 0 = info, 1 = success, 2 = notify
23     * (Not even in order of importance)
24     */
25    const LVL_MSG_ERROR = 4; //-1;
26    const LVL_MSG_WARNING = 3; //2;
27    const LVL_MSG_SUCCESS = 2; //1;
28    const LVL_MSG_INFO = 1; //0;
29    const LVL_MSG_DEBUG = 0; //3;
30
31
32    /**
33     * Id level to name
34     */
35    const LVL_NAME = array(
36        0 => "debug",
37        1 => "info",
38        3 => "warning",
39        2 => "success",
40        4 => "error"
41    );
42
43    /**
44     * Id level to name
45     * {@link msg()} constant
46     */
47    const LVL_TO_MSG_LEVEL = array(
48        0 => 3,
49        1 => 0,
50        2 => 1,
51        3 => 2,
52        4 => -1
53    );
54
55
56    const LOGLEVEL_URI_QUERY_PROPERTY = "loglevel";
57
58    /**
59     * Send a message to a manager and log it
60     * Fail if in test
61     * @param string $message
62     * @param int $level - the level see LVL constant
63     * @param string $canonical - the canonical
64     */
65    public static function msg(string $message, int $level = self::LVL_MSG_ERROR, string $canonical = "support")
66    {
67
68        $message = trim($message);
69        if ($message === "") {
70            $level = LogUtility::LVL_MSG_ERROR;
71            $message = "The passed message to the log was empty. BackTrace: \n";
72            ob_start();
73            debug_print_backtrace();
74            $trace = ob_get_contents();
75            ob_end_clean();
76            $message .= $trace;
77            self::log2file($message, $level, $canonical);
78            self::throwErrorIfTest($level, $message);
79            return;
80        }
81
82        /**
83         * Log to frontend
84         */
85        self::log2FrontEnd($message, $level, $canonical);
86
87        /**
88         * Log level passed for a page (only for file used)
89         * to not allow an attacker to see all errors in frontend
90         */
91        global $INPUT;
92        $loglevelProp = $INPUT->str(self::LOGLEVEL_URI_QUERY_PROPERTY, null);
93        if (!empty($loglevelProp)) {
94            $level = $loglevelProp;
95        }
96        /**
97         * TODO: Make it a configuration ?
98         */
99        if ($level >= self::LVL_MSG_WARNING) {
100            self::log2file($message, $level, $canonical);
101        }
102
103        /**
104         * If test, we throw an error
105         */
106        self::throwErrorIfTest($level, $message);
107    }
108
109    /**
110     * Print log to a  file
111     *
112     * Adapted from {@link dbglog}
113     * Note: {@link dbg()} dbg print to the web page
114     *
115     * @param string $msg
116     * @param int $logLevel
117     * @param null $canonical
118     */
119    static function log2file($msg, $logLevel = self::LVL_MSG_INFO, $canonical = null)
120    {
121
122        if (PluginUtility::isTest() || $logLevel >= self::LVL_MSG_WARNING) {
123
124            $prefix = PluginUtility::$PLUGIN_NAME;
125            if (!empty($canonical)) {
126                $prefix .= ' - ' . $canonical;
127            }
128            $msg = $prefix . ' - ' . $msg;
129
130            global $INPUT;
131            global $conf;
132
133            /**
134             * Adding page - context information
135             * We are not using {@link Page::createPageFromRequestedPage()}
136             * because it throws an error message when the environment
137             * is not good, creating a recursive call.
138             */
139            $id = PluginUtility::getMainPageDokuwikiId();
140
141            $file = $conf['cachedir'] . '/debug.log';
142            $fh = fopen($file, 'a');
143            if ($fh) {
144                $sep = " - ";
145                fwrite($fh, date('c') . $sep . self::LVL_NAME[$logLevel] . $sep . $msg . $sep . $INPUT->server->str('REMOTE_ADDR') . $sep . $id . "\n");
146                fclose($fh);
147            }
148
149
150            self::throwErrorIfTest($logLevel, $msg);
151
152
153        }
154
155    }
156
157    /**
158     * @param $message
159     * @param $level
160     * @param $canonical
161     * @param bool $withIconURL
162     */
163    public static function log2FrontEnd($message, $level, $canonical = "support", $withIconURL = true)
164    {
165        /**
166         * If we are not in the console
167         * and not in test
168         * we test that the message comes in the front end
169         * (example {@link \plugin_combo_frontmatter_test}
170         */
171        $isTerminal = Console::isConsoleRun();
172        if ($isTerminal) {
173            if (!defined('DOKU_UNITTEST')) {
174                /**
175                 * such as {@link cli_plugin_combo}
176                 */
177                $userAgent = "cli";
178            } else {
179                $userAgent = "phpunit";
180            }
181        } else {
182            $userAgent = "browser";
183        }
184
185        switch ($userAgent) {
186            case "cli":
187                echo "$message\n";
188                break;
189            case "phpunit":
190            case "browser":
191            default:
192                $htmlMsg = PluginUtility::getDocumentationHyperLink("", PluginUtility::$PLUGIN_NAME, $withIconURL);
193                if ($canonical != null) {
194                    $htmlMsg = PluginUtility::getDocumentationHyperLink($canonical, ucfirst(str_replace(":", " ", $canonical)));
195                }
196
197                /**
198                 * Adding page - context information
199                 * We are not creating the page
200                 * direction from {@link Page::createPageFromRequestedPage()}
201                 * because it throws an error message when the environment
202                 * is not good, creating a recursive call.
203                 */
204                $id = PluginUtility::getMainPageDokuwikiId();
205                if ($id != null) {
206
207                    /**
208                     * We don't use any Page object to not
209                     * create a cycle while building it
210                     */
211                    $url = wl($id, [], true);
212                    $htmlMsg .= " - <a href=\"$url\">$id</a>";
213
214                }
215
216                /**
217                 *
218                 */
219                $htmlMsg .= " - " . $message;
220                if ($level > self::LVL_MSG_DEBUG) {
221                    $dokuWikiLevel = self::LVL_TO_MSG_LEVEL[$level];
222                    msg($htmlMsg, $dokuWikiLevel, '', '', MSG_USERS_ONLY);
223                }
224        }
225    }
226
227    /**
228     * Log a message to the browser console
229     * @param $message
230     */
231    public static function log2BrowserConsole($message)
232    {
233        // TODO
234    }
235
236    private static function throwErrorIfTest($level, $message)
237    {
238        if (PluginUtility::isTest()
239            && ($level >= self::LVL_MSG_WARNING)
240        ) {
241            throw new LogException($message);
242        }
243    }
244}
245