1<?php 2/** 3 * Matomo - free/libre analytics platform 4 * 5 * @link https://matomo.org 6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later 7 * 8 */ 9namespace Piwik\Plugins\Live; 10 11use Piwik\API\Request; 12use Piwik\Common; 13use Piwik\Config; 14use Piwik\Piwik; 15use Piwik\DataTable; 16use Piwik\Plugins\Goals\API as APIGoals; 17use Piwik\Plugins\Live\Visualizations\VisitorLog; 18use Piwik\Url; 19use Piwik\View; 20 21/** 22 */ 23class Controller extends \Piwik\Plugin\Controller 24{ 25 const SIMPLE_VISIT_COUNT_WIDGET_LAST_MINUTES_CONFIG_KEY = 'live_widget_visitor_count_last_minutes'; 26 27 private $profileSummaryProvider; 28 29 public function __construct(ProfileSummaryProvider $profileSummaryProvider) 30 { 31 $this->profileSummaryProvider = $profileSummaryProvider; 32 parent::__construct(); 33 } 34 35 function index() 36 { 37 return $this->widget(); 38 } 39 40 public function widget() 41 { 42 Piwik::checkUserHasViewAccess($this->idSite); 43 Live::checkIsVisitorLogEnabled($this->idSite); 44 45 $view = new View('@Live/index'); 46 $view->idSite = $this->idSite; 47 $view->isWidgetized = Common::getRequestVar('widget', 0, 'int'); 48 $view = $this->setCounters($view); 49 $view->liveRefreshAfterMs = (int)Config::getInstance()->General['live_widget_refresh_after_seconds'] * 1000; 50 $view->visitors = $this->getLastVisitsStart(); 51 $view->liveTokenAuth = Piwik::getCurrentUserTokenAuth(); 52 return $this->render($view); 53 } 54 55 public function ajaxTotalVisitors() 56 { 57 Piwik::checkUserHasViewAccess($this->idSite); 58 59 $view = new View('@Live/ajaxTotalVisitors'); 60 $view = $this->setCounters($view); 61 $view->idSite = $this->idSite; 62 return $this->render($view); 63 } 64 65 private function render(View $view) 66 { 67 $rendered = $view->render(); 68 69 return $rendered; 70 } 71 72 public function indexVisitorLog() 73 { 74 Piwik::checkUserHasViewAccess($this->idSite); 75 Live::checkIsVisitorLogEnabled($this->idSite); 76 77 $view = new View('@Live/indexVisitorLog.twig'); 78 $view->visitorLog = $this->renderReport('getLastVisitsDetails'); 79 return $view->render(); 80 } 81 82 /** 83 * Widget 84 */ 85 public function getVisitorLog() 86 { 87 return $this->renderReport('getLastVisitsDetails'); 88 } 89 90 public function getLastVisitsStart() 91 { 92 Piwik::checkUserHasViewAccess($this->idSite); 93 Live::checkIsVisitorLogEnabled($this->idSite); 94 95 // hack, ensure we load today's visits by default 96 $_GET['date'] = 'today'; 97 \Piwik\Period\Factory::checkPeriodIsEnabled('day'); 98 $_GET['period'] = 'day'; 99 100 $view = new View('@Live/getLastVisitsStart'); 101 $view->idSite = (int) $this->idSite; 102 $error = ''; 103 $visitors = new DataTable(); 104 try { 105 $api = new Request("method=Live.getLastVisitsDetails&idSite={$this->idSite}&filter_limit=10&format=original&serialize=0&disable_generic_filters=1"); 106 $visitors = $api->process(); 107 } catch (\Exception $e) { 108 $error = $e->getMessage(); 109 } 110 $view->error = $error; 111 $view->visitors = $visitors; 112 113 return $this->render($view); 114 } 115 116 private function setCounters($view) 117 { 118 $segment = Request::getRawSegmentFromRequest(); 119 $last30min = Request::processRequest('Live.getCounters', [ 120 'idSite' => $this->idSite, 121 'lastMinutes' => 30, 122 'segment' => $segment, 123 'showColumns' => 'visits,actions', 124 ], $default = []); 125 $last30min = $last30min[0]; 126 $today = Request::processRequest('Live.getCounters', [ 127 'idSite' => $this->idSite, 128 'lastMinutes' => 24 * 60, 129 'segment' => $segment, 130 'showColumns' => 'visits,actions', 131 ], $default = []); 132 $today = $today[0]; 133 $view->visitorsCountHalfHour = $last30min['visits']; 134 $view->visitorsCountToday = $today['visits']; 135 $view->pisHalfhour = $last30min['actions']; 136 $view->pisToday = $today['actions']; 137 return $view; 138 } 139 140 /** 141 * Echo's HTML for visitor profile popup. 142 */ 143 public function getVisitorProfilePopup() 144 { 145 Piwik::checkUserHasViewAccess($this->idSite); 146 Live::checkIsVisitorProfileEnabled($this->idSite); 147 148 $visitorData = Request::processRequest('Live.getVisitorProfile'); 149 150 if (empty($visitorData)) { 151 throw new \Exception('Visitor could not be found'); // for example when URL parameter is not set 152 } 153 154 VisitorLog::groupActionsByPageviewId($visitorData['lastVisits']); 155 156 $view = new View('@Live/getVisitorProfilePopup.twig'); 157 $view->idSite = $this->idSite; 158 $view->goals = Request::processRequest('Goals.getGoals', ['idSite' => $this->idSite, 'filter_limit' => '-1'], $default = []); 159 $view->visitorData = $visitorData; 160 $view->exportLink = $this->getVisitorProfileExportLink(); 161 162 $this->setWidgetizedVisitorProfileUrl($view); 163 164 $summaryEntries = array(); 165 166 $profileSummaries = $this->profileSummaryProvider->getAllInstances(); 167 foreach ($profileSummaries as $profileSummary) { 168 $profileSummary->setProfile($view->visitorData); 169 $summaryEntries[] = [$profileSummary->getOrder(), $profileSummary->render()]; 170 } 171 172 usort($summaryEntries, function($a, $b) { 173 return version_compare($a[0], $b[0]); 174 }); 175 176 $summary = ''; 177 178 foreach ($summaryEntries AS $summaryEntry) { 179 $summary .= $summaryEntry[1]; 180 } 181 182 $view->profileSummary = $summary; 183 184 return $view->render(); 185 } 186 187 public function getVisitList() 188 { 189 $this->checkSitePermission(); 190 Piwik::checkUserHasViewAccess($this->idSite); 191 192 $filterLimit = Common::getRequestVar('filter_offset', 0, 'int'); 193 $startCounter = Common::getRequestVar('start_number', 0, 'int'); 194 $limit = Config::getInstance()->General['live_visitor_profile_max_visits_to_aggregate']; 195 196 if ($startCounter >= $limit) { 197 return ''; // do not return more visits than configured for profile 198 } 199 200 $nextVisits = Request::processRequest('Live.getLastVisitsDetails', array( 201 'segment' => Live::getSegmentWithVisitorId(), 202 'filter_limit' => VisitorProfile::VISITOR_PROFILE_MAX_VISITS_TO_SHOW, 203 'filter_offset' => $filterLimit, 204 'period' => false, 205 'date' => false 206 )); 207 208 if (empty($nextVisits)) { 209 return ''; 210 } 211 212 VisitorLog::groupActionsByPageviewId($nextVisits); 213 214 $view = new View('@Live/getVisitList.twig'); 215 $view->idSite = $this->idSite; 216 $view->startCounter = $startCounter < $nextVisits->getRowsCount() ? $nextVisits->getRowsCount() : $startCounter; 217 $view->visits = $nextVisits; 218 return $view->render(); 219 } 220 221 private function getVisitorProfileExportLink() 222 { 223 return Url::getCurrentQueryStringWithParametersModified(array( 224 'module' => 'API', 225 'action' => 'index', 226 'method' => 'Live.getVisitorProfile', 227 'format' => 'XML', 228 'expanded' => 1 229 )); 230 } 231 232 private function setWidgetizedVisitorProfileUrl($view) 233 { 234 if (\Piwik\Plugin\Manager::getInstance()->isPluginLoaded('Widgetize')) { 235 $view->widgetizedLink = Url::getCurrentQueryStringWithParametersModified(array( 236 'module' => 'Widgetize', 237 'action' => 'iframe', 238 'moduleToWidgetize' => 'Live', 239 'actionToWidgetize' => 'getVisitorProfilePopup' 240 )); 241 } 242 } 243} 244