1<?php 2 3use ComboStrap\Analytics; 4use Combostrap\AnalyticsMenuItem; 5use ComboStrap\Auth; 6use ComboStrap\LogUtility; 7use ComboStrap\Page; 8use ComboStrap\Sqlite; 9 10/** 11 * Copyright (c) 2021. ComboStrap, Inc. and its affiliates. All Rights Reserved. 12 * 13 * This source code is licensed under the GPL license found in the 14 * COPYING file in the root directory of this source tree. 15 * 16 * @license GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html) 17 * @author ComboStrap <support@combostrap.com> 18 * 19 */ 20 21require_once(__DIR__ . '/../class/' . 'Analytics.php'); 22require_once(__DIR__ . '/../class/' . 'Auth.php'); 23require_once(__DIR__ . '/../class/' . 'AnalyticsMenuItem.php'); 24 25/** 26 * Class action_plugin_combo_analytics 27 * Update the analytics data 28 */ 29class action_plugin_combo_analytics extends DokuWiki_Action_Plugin 30{ 31 32 33 public function register(Doku_Event_Handler $controller) 34 { 35 36 /** 37 * Analytics to refresh because they have lost or gain a backlinks 38 * are done via Sqlite table (The INDEXER_TASKS_RUN gives a way to 39 * manipulate this queue) 40 * 41 * There is no need to do it at page write 42 * https://www.dokuwiki.org/devel:event:io_wikipage_write 43 * because after the page is written, the page is shown and trigger the index tasks run 44 * 45 * We do it after because if there is an error 46 * We will not stop the Dokuwiki Processing 47 */ 48 $controller->register_hook('INDEXER_TASKS_RUN', 'AFTER', $this, 'handle_refresh_analytics', array()); 49 50 /** 51 * Add a icon in the page tools menu 52 * https://www.dokuwiki.org/devel:event:menu_items_assembly 53 */ 54 $controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'handle_page_tools'); 55 56 } 57 58 public function handle_refresh_analytics(Doku_Event $event, $param) 59 { 60 61 /** 62 * Check that the actual page has analytics data 63 * (if there is a cache, it's pretty quick) 64 */ 65 global $ID; 66 $page = new Page($ID); 67 if ($page->shouldAnalyticsProcessOccurs()) { 68 $page->processAnalytics(); 69 } 70 71 /** 72 * Process the analytics to refresh 73 */ 74 $this->analyticsBatchBackgroundRefresh(); 75 76 } 77 78 public function handle_page_tools(Doku_Event $event, $param) 79 { 80 81 if (!Auth::isWriter()) { 82 return; 83 } 84 85 /** 86 * The `view` property defines the menu that is currently built 87 * https://www.dokuwiki.org/devel:menus 88 * If this is not the page menu, return 89 */ 90 if ($event->data['view'] != 'page') return; 91 92 global $INFO; 93 if (!$INFO['exists']) { 94 return; 95 } 96 array_splice($event->data['items'], -1, 0, array(new AnalyticsMenuItem())); 97 98 } 99 100 private function analyticsBatchBackgroundRefresh() 101 { 102 $sqlite = Sqlite::getSqlite(); 103 $res = $sqlite->query("SELECT ID FROM ANALYTICS_TO_REFRESH"); 104 if (!$res) { 105 LogUtility::msg("There was a problem during the select: {$sqlite->getAdapter()->getDb()->errorInfo()}"); 106 } 107 $rows = $sqlite->res2arr($res, true); 108 $sqlite->res_close($res); 109 110 /** 111 * In case of a start or if there is a recursive bug 112 * We don't want to take all the resources 113 */ 114 $maxRefresh = 5; 115 $maxRefreshLow = 2; 116 if (sizeof($rows) > $maxRefresh) { 117 LogUtility::msg("There is more than {$maxRefresh} page to refresh in the queue (table `ANALYTICS_TO_REFRESH`). Batch background Analytics refresh was reduced to {$maxRefreshLow} page to not hit the computer resources.", LogUtility::LVL_MSG_ERROR, "analytics"); 118 $maxRefresh = $maxRefreshLow; 119 } 120 $refreshCounter = 0; 121 foreach ($rows as $row) { 122 $page = new Page($row['ID']); 123 $page->processAnalytics(); 124 $refreshCounter++; 125 if ($refreshCounter>=$maxRefresh){ 126 break; 127 } 128 } 129 130 } 131} 132 133 134 135