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\Goals\Visualizations; 10 11use Piwik\API\DataTablePostProcessor; 12use Piwik\API\Request; 13use Piwik\Common; 14use Piwik\DataTable; 15use Piwik\DataTable\Filter\AddColumnsProcessedMetricsGoal; 16use Piwik\Piwik; 17use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; 18use Piwik\Plugins\Goals\API as APIGoals; 19use Piwik\Site; 20use Piwik\View; 21 22require_once PIWIK_INCLUDE_PATH . '/core/Twig.php'; 23 24/** 25 * DataTable Visualization that derives from HtmlTable and sets show_goals_columns to true. 26 */ 27class Goals extends HtmlTable 28{ 29 const ID = 'tableGoals'; 30 const FOOTER_ICON = 'icon-goal'; 31 const FOOTER_ICON_TITLE = 'General_DisplayTableWithGoalMetrics'; 32 33 public function beforeLoadDataTable() 34 { 35 parent::beforeLoadDataTable(); 36 37 $this->config->show_totals_row = false; 38 39 if ($this->config->disable_subtable_when_show_goals) { 40 $this->config->subtable_controller_action = null; 41 } 42 43 $this->setShowGoalsColumnsProperties(); 44 } 45 46 public function beforeRender() 47 { 48 $this->config->show_totals_row = false; 49 $this->config->show_goals = true; 50 $this->config->show_goals_columns = true; 51 $this->config->datatable_css_class = 'dataTableVizGoals'; 52 $this->config->show_exclude_low_population = true; 53 54 $this->config->metrics_documentation['nb_visits'] = Piwik::translate('Goals_ColumnVisits'); 55 56 if (1 == Common::getRequestVar('documentationForGoalsPage', 0, 'int')) { 57 // TODO: should not use query parameter 58 $this->config->documentation = Piwik::translate('Goals_ConversionByTypeReportDocumentation', 59 array('<br />', '<br />', '<a href="https://matomo.org/docs/tracking-goals-web-analytics/" rel="noreferrer noopener" target="_blank">', '</a>')); 60 } 61 62 parent::beforeRender(); 63 } 64 65 private function setShowGoalsColumnsProperties() 66 { 67 // set view properties based on goal requested 68 $idSite = Common::getRequestVar('idSite', null, 'int'); 69 $idGoal = Common::getRequestVar('idGoal', AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW, 'string'); 70 71 $goalsToProcess = null; 72 if (Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER == $idGoal) { 73 $this->setPropertiesForEcommerceView(); 74 75 $goalsToProcess = array($idGoal); 76 } else if (AddColumnsProcessedMetricsGoal::GOALS_FULL_TABLE == $idGoal) { 77 $this->setPropertiesForGoals($idSite, 'all'); 78 79 $goalsToProcess = $this->getAllGoalIds($idSite); 80 } else if (AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW == $idGoal) { 81 $this->setPropertiesForGoalsOverview($idSite); 82 83 $goalsToProcess = $this->getAllGoalIds($idSite); 84 } else { 85 $this->setPropertiesForGoals($idSite, array($idGoal)); 86 87 $goalsToProcess = array($idGoal); 88 } 89 90 // add goals columns 91 $this->requestConfig->request_parameters_to_modify['filter_update_columns_when_show_all_goals'] = $idGoal; 92 $this->requestConfig->request_parameters_to_modify['filter_show_goal_columns_process_goals'] = implode(',', $goalsToProcess); 93 } 94 95 private function setPropertiesForEcommerceView() 96 { 97 $this->requestConfig->filter_sort_column = 'goal_ecommerceOrder_revenue'; 98 $this->requestConfig->filter_sort_order = 'desc'; 99 100 $this->config->columns_to_display = array( 101 'label', 'nb_visits', 'goal_ecommerceOrder_nb_conversions', 'goal_ecommerceOrder_revenue', 102 'goal_ecommerceOrder_conversion_rate', 'goal_ecommerceOrder_avg_order_revenue', 'goal_ecommerceOrder_items', 103 'goal_ecommerceOrder_revenue_per_visit' 104 ); 105 106 $this->config->translations = array_merge($this->config->translations, array( 107 'goal_ecommerceOrder_nb_conversions' => Piwik::translate('General_EcommerceOrders'), 108 'goal_ecommerceOrder_revenue' => Piwik::translate('General_TotalRevenue'), 109 'goal_ecommerceOrder_revenue_per_visit' => Piwik::translate('General_ColumnValuePerVisit') 110 )); 111 112 $goalName = Piwik::translate('General_EcommerceOrders'); 113 $this->config->metrics_documentation['revenue_per_visit'] = 114 Piwik::translate('Goals_ColumnRevenuePerVisitDocumentation', $goalName); 115 } 116 117 private function setPropertiesForGoalsOverview($idSite) 118 { 119 $allGoals = $this->getGoals($idSite); 120 121 // set view properties 122 $this->config->columns_to_display = array('label', 'nb_visits'); 123 124 foreach ($allGoals as $goal) { 125 $column = "goal_{$goal['idgoal']}_conversion_rate"; 126 $this->config->columns_to_display[] = $column; 127 } 128 129 $this->config->columns_to_display[] = 'revenue_per_visit'; 130 } 131 132 private function setPropertiesForGoals($idSite, $idGoals) 133 { 134 $allGoals = $this->getGoals($idSite); 135 136 if ('all' == $idGoals) { 137 $idGoals = array_keys($allGoals); 138 } else { 139 // only sort by a goal's conversions if not showing all goals (for FULL_REPORT) 140 $this->requestConfig->filter_sort_column = 'goal_' . reset($idGoals) . '_nb_conversions'; 141 $this->requestConfig->filter_sort_order = 'desc'; 142 } 143 144 $this->config->columns_to_display = array('label', 'nb_visits'); 145 146 $goalColumnTemplates = array( 147 'goal_%s_nb_conversions', 148 'goal_%s_conversion_rate', 149 'goal_%s_revenue', 150 'goal_%s_revenue_per_visit', 151 ); 152 153 // set columns to display (columns of same type but different goals will be next to each other, 154 // ie, goal_0_nb_conversions, goal_1_nb_conversions, etc.) 155 foreach ($goalColumnTemplates as $columnTemplate) { 156 foreach ($idGoals as $idGoal) { 157 $this->config->columns_to_display[] = sprintf($columnTemplate, $idGoal); 158 } 159 } 160 161 $this->config->columns_to_display[] = 'revenue_per_visit'; 162 } 163 164 private $goalsForCurrentSite = null; 165 166 private function getGoals($idSite) 167 { 168 if ($this->goalsForCurrentSite === null) { 169 // get all goals to display info for 170 $allGoals = array(); 171 172 // add the ecommerce goal if ecommerce is enabled for the site 173 if (Site::isEcommerceEnabledFor($idSite)) { 174 $ecommerceGoal = array( 175 'idgoal' => Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER, 176 'name' => Piwik::translate('Goals_EcommerceOrder'), 177 'quoted_name' => false 178 ); 179 $allGoals[$ecommerceGoal['idgoal']] = $ecommerceGoal; 180 } 181 182 // add the site's goals (and escape all goal names) 183 $siteGoals = Request::processRequest('Goals.getGoals', ['idSite' => $idSite, 'filter_limit' => '-1'], $default = []); 184 185 foreach ($siteGoals as &$goal) { 186 $goal['name'] = Common::sanitizeInputValue($goal['name']); 187 188 $goal['quoted_name'] = '"' . $goal['name'] . '"'; 189 $allGoals[$goal['idgoal']] = $goal; 190 } 191 192 $this->goalsForCurrentSite = $allGoals; 193 } 194 195 return $this->goalsForCurrentSite; 196 } 197 198 private function getAllGoalIds($idSite) 199 { 200 $allGoals = $this->getGoals($idSite); 201 return array_map(function ($data) { 202 return $data['idgoal']; 203 }, $allGoals); 204 } 205} 206