xref: /plugin/combo/action/qualitymessage.php (revision c3437056399326d621a01da73b649707fbb0ae69)
1<?php
2
3use ComboStrap\AnalyticsDocument;
4use ComboStrap\ExceptionCombo;
5use ComboStrap\Identity;
6use ComboStrap\LogUtility;
7use ComboStrap\Message;
8use ComboStrap\Mime;
9use ComboStrap\Page;
10use ComboStrap\PluginUtility;
11use ComboStrap\QualityMenuItem;
12use ComboStrap\HttpResponse;
13
14if (!defined('DOKU_INC')) die();
15if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
16
17
18require_once(__DIR__ . '/../ComboStrap/PluginUtility.php');
19
20/**
21 *
22 * Show a quality message
23 *
24 *
25 *
26 */
27class action_plugin_combo_qualitymessage extends DokuWiki_Action_Plugin
28{
29
30    // a class can not start with a number
31    const QUALITY_BOX_CLASS = "quality-message";
32
33    /**
34     * The quality rules that will not show
35     * up in the messages
36     */
37    const CONF_EXCLUDED_QUALITY_RULES_FROM_DYNAMIC_MONITORING = "excludedQualityRulesFromDynamicMonitoring";
38    /**
39     * Disable the message totally
40     */
41    const CONF_DISABLE_QUALITY_MONITORING = "disableDynamicQualityMonitoring";
42
43    const CANONICAL = "quality:dynamic_monitoring";
44
45    const META_MANAGER_CALL_ID = "combo-quality-message";
46
47
48    function __construct()
49    {
50        // enable direct access to language strings
51        // ie $this->lang
52        $this->setupLocale();
53    }
54
55    public static function createHtmlQualityNote(Page $page): Message
56    {
57        if ($page->isSlot()) {
58            return Message::createErrorMessage("A has no quality metrics");
59
60        }
61
62        if (!$page->isDynamicQualityMonitored()) {
63            return Message::createErrorMessage("This page is not quality monitored. Change the configuration if you want to.");
64        }
65
66        if (!$page->exists()) {
67            return Message::createInfoMessage("The page does not exist");
68        }
69
70
71        try {
72            $analyticsArray = $page->getAnalyticsDocument()->getJson()->toArray();
73        } catch (ExceptionCombo $e) {
74            return Message::createErrorMessage("Error while trying to read the JSON analytics document. {$e->getMessage()}")
75                ->setStatus(HttpResponse::STATUS_INTERNAL_ERROR);
76        }
77
78        $rules = $analyticsArray[AnalyticsDocument::QUALITY][AnalyticsDocument::RULES];
79
80
81        /**
82         * We may got null
83         * array_key_exists() expects parameter 2 to be array,
84         * null given in /opt/www/datacadamia.com/lib/plugins/combo/action/qualitymessage.php on line 113
85         */
86        if ($rules == null) {
87            return Message::createInfoMessage("No rules found in the analytics document");
88        }
89
90        /**
91         * If there is no info, nothing to show
92         */
93        if (!array_key_exists(AnalyticsDocument::INFO, $rules)) {
94            return Message::createInfoMessage("No quality rules information to show");
95        }
96
97        /**
98         * The error info
99         */
100        $qualityInfoRules = $rules[AnalyticsDocument::INFO];
101
102        /**
103         * Excluding the excluded rules
104         */
105        global $conf;
106        $excludedRulesConf = $conf['plugin'][PluginUtility::PLUGIN_BASE_NAME][self::CONF_EXCLUDED_QUALITY_RULES_FROM_DYNAMIC_MONITORING];
107        $excludedRules = preg_split("/,/", $excludedRulesConf);
108        foreach ($excludedRules as $excludedRule) {
109            if (array_key_exists($excludedRule, $qualityInfoRules)) {
110                unset($qualityInfoRules[$excludedRule]);
111            }
112        }
113
114        if (sizeof($qualityInfoRules) <= 0) {
115            return Message::createInfoMessage("No quality rules information to show");
116        }
117
118        $qualityScore = $analyticsArray[AnalyticsDocument::QUALITY][renderer_plugin_combo_analytics::SCORING][renderer_plugin_combo_analytics::SCORE];
119        $message = "<p>The page has a " . PluginUtility::getDocumentationHyperLink("quality:score", "quality score") . " of {$qualityScore}.</p>";
120
121        $lowQuality = $analyticsArray[AnalyticsDocument::QUALITY][AnalyticsDocument::LOW];
122        if ($lowQuality) {
123
124            $mandatoryFailedRules = $analyticsArray[AnalyticsDocument::QUALITY][AnalyticsDocument::FAILED_MANDATORY_RULES];
125            $rulesUrl = PluginUtility::getDocumentationHyperLink("quality:rule", "rules");
126            $lqPageUrl = PluginUtility::getDocumentationHyperLink("low_quality_page", "low quality page");
127            $message .= "<div class='alert alert-warning'>This is a {$lqPageUrl} because it has failed the following mandatory {$rulesUrl}:";
128            $message .= "<ul style='margin-bottom: 0'>";
129            /**
130             * A low quality page should have
131             * failed mandatory rules
132             * but due to the asycn nature, sometimes
133             * we don't have an array
134             */
135            if (is_array($mandatoryFailedRules)) {
136                foreach ($mandatoryFailedRules as $mandatoryFailedRule) {
137                    $message .= "<li>" . PluginUtility::getDocumentationHyperLink("quality:rule#list", $mandatoryFailedRule) . "</li>";
138                }
139            }
140            $message .= "</ul>";
141            $message .= "</div>";
142        }
143        $message .= "<p>You can still win a couple of points.</p>";
144        $message .= "<ul>";
145        foreach ($qualityInfoRules as $qualityRule => $qualityInfo) {
146            $message .= "<li>$qualityInfo</li>";
147        }
148        $message .= "</ul>";
149        return Message::createInfoMessage($message);
150
151    }
152
153
154    function register(Doku_Event_Handler $controller)
155    {
156
157
158        /**
159         * Add a icon in the page tools menu
160         * https://www.dokuwiki.org/devel:event:menu_items_assembly
161         */
162        $controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'addMenuItem');
163
164
165        /**
166         * The ajax api to return data
167         */
168        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'ajaxCall');
169
170    }
171
172
173    function addMenuItem(Doku_Event $event, $param)
174    {
175
176        if (!Identity::isWriter()) {
177            return;
178        }
179
180        /**
181         * The `view` property defines the menu that is currently built
182         * https://www.dokuwiki.org/devel:menus
183         * If this is not the page menu, return
184         */
185        if ($event->data['view'] != 'page') return;
186
187        global $INFO;
188        if (!$INFO['exists']) {
189            return;
190        }
191        array_splice($event->data['items'], -1, 0, array(new QualityMenuItem()));
192
193    }
194
195    /**
196     * Main function; dispatches the visual comment actions
197     * @param   $event Doku_Event
198     */
199    function ajaxCall(&$event, $param): void
200    {
201        $call = $event->data;
202        if ($call != self::META_MANAGER_CALL_ID) {
203            return;
204        }
205        //no other ajax call handlers needed
206        $event->stopPropagation();
207        $event->preventDefault();
208
209        /**
210         * Shared check between post and get HTTP method
211         */
212        $id = $_GET["id"];
213        if ($id === null) {
214            /**
215             * With {@link TestRequest}
216             * for instance
217             */
218            $id = $_REQUEST["id"];
219        }
220
221        if (empty($id)) {
222            HttpResponse::create(HttpResponse::STATUS_BAD_REQUEST)
223                ->setEvent($event)
224                ->setCanonical(self::CANONICAL)
225                ->send("The page id should not be empty", Mime::HTML);
226            return;
227        }
228
229        /**
230         * Quality is just for the writers
231         */
232        if (!Identity::isWriter($id)) {
233            HttpResponse::create(HttpResponse::STATUS_NOT_AUTHORIZED)
234                ->setEvent($event)
235                ->send("Quality is only for writer", Mime::HTML);
236            return;
237        }
238
239
240        $page = Page::createPageFromId($id);
241
242        $message = self::createHtmlQualityNote($page);
243
244        $status = $message->getStatus();
245        if ($status === null) {
246            $status = HttpResponse::STATUS_ALL_GOOD;
247        }
248
249        HttpResponse::create($status)
250            ->setEvent($event)
251            ->setCanonical(self::CANONICAL)
252            ->send($message->getContent(), Mime::HTML);
253
254    }
255}
256