PageRenderTime 24ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/sites/all/modules/contrib/civicrm/CRM/Report/Form/Mailing/Clicks.php

https://gitlab.com/virtualrealms/d7civicrm
PHP | 399 lines | 285 code | 39 blank | 75 comment | 14 complexity | d1d1d823aba7854f5619cf2ce57fb48f MD5 | raw file
  1. <?php
  2. /*
  3. +--------------------------------------------------------------------+
  4. | CiviCRM version 5 |
  5. +--------------------------------------------------------------------+
  6. | Copyright CiviCRM LLC (c) 2004-2019 |
  7. +--------------------------------------------------------------------+
  8. | This file is a part of CiviCRM. |
  9. | |
  10. | CiviCRM is free software; you can copy, modify, and distribute it |
  11. | under the terms of the GNU Affero General Public License |
  12. | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
  13. | |
  14. | CiviCRM is distributed in the hope that it will be useful, but |
  15. | WITHOUT ANY WARRANTY; without even the implied warranty of |
  16. | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
  17. | See the GNU Affero General Public License for more details. |
  18. | |
  19. | You should have received a copy of the GNU Affero General Public |
  20. | License and the CiviCRM Licensing Exception along |
  21. | with this program; if not, contact CiviCRM LLC |
  22. | at info[AT]civicrm[DOT]org. If you have questions about the |
  23. | GNU Affero General Public License or the licensing of CiviCRM, |
  24. | see the CiviCRM license FAQ at http://civicrm.org/licensing |
  25. +--------------------------------------------------------------------+
  26. */
  27. /**
  28. *
  29. * @package CRM
  30. * @copyright CiviCRM LLC (c) 2004-2019
  31. * $Id$
  32. *
  33. */
  34. class CRM_Report_Form_Mailing_Clicks extends CRM_Report_Form {
  35. protected $_summary = NULL;
  36. protected $_emailField = FALSE;
  37. protected $_phoneField = FALSE;
  38. protected $_customGroupExtends = [
  39. 'Contact',
  40. 'Individual',
  41. 'Household',
  42. 'Organization',
  43. ];
  44. protected $_charts = [
  45. '' => 'Tabular',
  46. 'barChart' => 'Bar Chart',
  47. 'pieChart' => 'Pie Chart',
  48. ];
  49. /**
  50. * This report has not been optimised for group filtering.
  51. *
  52. * The functionality for group filtering has been improved but not
  53. * all reports have been adjusted to take care of it. This report has not
  54. * and will run an inefficient query until fixed.
  55. *
  56. * CRM-19170
  57. *
  58. * @var bool
  59. */
  60. protected $groupFilterNotOptimised = TRUE;
  61. /**
  62. * Class constructor.
  63. */
  64. public function __construct() {
  65. $this->_columns = [];
  66. $this->_columns['civicrm_contact'] = [
  67. 'dao' => 'CRM_Contact_DAO_Contact',
  68. 'fields' => [
  69. 'id' => [
  70. 'title' => ts('Contact ID'),
  71. 'required' => TRUE,
  72. ],
  73. 'sort_name' => [
  74. 'title' => ts('Contact Name'),
  75. 'required' => TRUE,
  76. ],
  77. ],
  78. 'filters' => [
  79. 'sort_name' => [
  80. 'title' => ts('Contact Name'),
  81. ],
  82. 'source' => [
  83. 'title' => ts('Contact Source'),
  84. 'type' => CRM_Utils_Type::T_STRING,
  85. ],
  86. 'id' => [
  87. 'title' => ts('Contact ID'),
  88. 'no_display' => TRUE,
  89. ],
  90. ],
  91. 'order_bys' => [
  92. 'sort_name' => [
  93. 'title' => ts('Contact Name'),
  94. 'default' => TRUE,
  95. 'default_order' => 'ASC',
  96. ],
  97. ],
  98. 'grouping' => 'contact-fields',
  99. ];
  100. $this->_columns['civicrm_mailing'] = [
  101. 'dao' => 'CRM_Mailing_DAO_Mailing',
  102. 'fields' => [
  103. 'mailing_name' => [
  104. 'name' => 'name',
  105. 'title' => ts('Mailing Name'),
  106. 'default' => TRUE,
  107. ],
  108. 'mailing_name_alias' => [
  109. 'name' => 'name',
  110. 'required' => TRUE,
  111. 'no_display' => TRUE,
  112. ],
  113. 'mailing_subject' => [
  114. 'name' => 'subject',
  115. 'title' => ts('Mailing Subject'),
  116. 'default' => TRUE,
  117. ],
  118. ],
  119. 'filters' => [
  120. 'mailing_id' => [
  121. 'name' => 'id',
  122. 'title' => ts('Mailing Name'),
  123. 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
  124. 'type' => CRM_Utils_Type::T_INT,
  125. 'options' => CRM_Mailing_BAO_Mailing::getMailingsList(),
  126. 'operator' => 'like',
  127. ],
  128. 'mailing_subject' => [
  129. 'name' => 'subject',
  130. 'title' => ts('Mailing Subject'),
  131. 'type' => CRM_Utils_Type::T_STRING,
  132. 'operator' => 'like',
  133. ],
  134. ],
  135. 'order_bys' => [
  136. 'mailing_name' => [
  137. 'name' => 'name',
  138. 'title' => ts('Mailing Name'),
  139. ],
  140. 'mailing_subject' => [
  141. 'name' => 'subject',
  142. 'title' => ts('Mailing Subject'),
  143. ],
  144. ],
  145. 'grouping' => 'mailing-fields',
  146. ];
  147. $this->_columns['civicrm_email'] = [
  148. 'dao' => 'CRM_Core_DAO_Email',
  149. 'fields' => [
  150. 'email' => [
  151. 'title' => ts('Email'),
  152. 'no_repeat' => TRUE,
  153. ],
  154. ],
  155. 'grouping' => 'contact-fields',
  156. ];
  157. $this->_columns['civicrm_phone'] = [
  158. 'dao' => 'CRM_Core_DAO_Phone',
  159. 'fields' => ['phone' => NULL],
  160. 'grouping' => 'contact-fields',
  161. ];
  162. $this->_columns['civicrm_mailing_trackable_url'] = [
  163. 'dao' => 'CRM_Mailing_DAO_TrackableURL',
  164. 'fields' => [
  165. 'url' => [
  166. 'title' => ts('Click through URL'),
  167. ],
  168. ],
  169. // To do this filter should really be like mailing id filter a multi select, However
  170. // Not clear on how to make filter dependant on selected mailings at this stage so have set a
  171. // text filter which works for now
  172. 'filters' => [
  173. 'url' => [
  174. 'title' => ts('URL'),
  175. 'type' => CRM_Utils_Type::T_STRING,
  176. 'operator' => 'like',
  177. ],
  178. ],
  179. 'order_bys' => [
  180. 'url' => ['title' => ts('Click through URL')],
  181. ],
  182. 'grouping' => 'mailing-fields',
  183. ];
  184. $this->_columns['civicrm_mailing_event_trackable_url_open'] = [
  185. 'dao' => 'CRM_Mailing_Event_DAO_TrackableURLOpen',
  186. 'fields' => [
  187. 'time_stamp' => [
  188. 'title' => ts('Click Date'),
  189. 'default' => TRUE,
  190. ],
  191. ],
  192. 'filters' => [
  193. 'time_stamp' => [
  194. 'title' => ts('Click Date'),
  195. 'operatorType' => CRM_Report_Form::OP_DATE,
  196. 'type' => CRM_Utils_Type::T_DATE,
  197. ],
  198. ],
  199. 'order_bys' => [
  200. 'time_stamp' => [
  201. 'title' => ts('Click Date'),
  202. ],
  203. ],
  204. 'grouping' => 'mailing-fields',
  205. ];
  206. $this->_groupFilter = TRUE;
  207. $this->_tagFilter = TRUE;
  208. parent::__construct();
  209. }
  210. public function preProcess() {
  211. $this->assign('chartSupported', TRUE);
  212. parent::preProcess();
  213. }
  214. public function select() {
  215. $select = [];
  216. $this->_columnHeaders = [];
  217. foreach ($this->_columns as $tableName => $table) {
  218. if (array_key_exists('fields', $table)) {
  219. foreach ($table['fields'] as $fieldName => $field) {
  220. if (!empty($field['required']) ||
  221. !empty($this->_params['fields'][$fieldName])
  222. ) {
  223. if ($tableName == 'civicrm_email') {
  224. $this->_emailField = TRUE;
  225. }
  226. elseif ($tableName == 'civicrm_phone') {
  227. $this->_phoneField = TRUE;
  228. }
  229. $select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
  230. $this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
  231. $this->_columnHeaders["{$tableName}_{$fieldName}"]['no_display'] = CRM_Utils_Array::value('no_display', $field);
  232. $this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
  233. }
  234. }
  235. }
  236. }
  237. if (!empty($this->_params['charts'])) {
  238. $select[] = "COUNT({$this->_aliases['civicrm_event_trackable_url_open']}.id) as civicrm_mailing_click_count";
  239. $this->_columnHeaders["civicrm_mailing_click_count"]['title'] = ts('Click Count');
  240. }
  241. $this->_selectClauses = $select;
  242. $this->_select = "SELECT " . implode(', ', $select) . " ";
  243. }
  244. /**
  245. * @param $fields
  246. * @param $files
  247. * @param $self
  248. *
  249. * @return array
  250. */
  251. public static function formRule($fields, $files, $self) {
  252. $errors = $grouping = [];
  253. return $errors;
  254. }
  255. public function from() {
  256. $this->_from = "
  257. FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}";
  258. $this->_from .= "
  259. INNER JOIN civicrm_mailing_event_queue
  260. ON civicrm_mailing_event_queue.contact_id = {$this->_aliases['civicrm_contact']}.id
  261. LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
  262. ON civicrm_mailing_event_queue.email_id = {$this->_aliases['civicrm_email']}.id
  263. INNER JOIN civicrm_mailing_event_trackable_url_open {$this->_aliases['civicrm_mailing_event_trackable_url_open']}
  264. ON {$this->_aliases['civicrm_mailing_event_trackable_url_open']}.event_queue_id = civicrm_mailing_event_queue.id
  265. INNER JOIN civicrm_mailing_trackable_url {$this->_aliases['civicrm_mailing_trackable_url']}
  266. ON {$this->_aliases['civicrm_mailing_event_trackable_url_open']}.trackable_url_id = {$this->_aliases['civicrm_mailing_trackable_url']}.id
  267. INNER JOIN civicrm_mailing_job
  268. ON civicrm_mailing_event_queue.job_id = civicrm_mailing_job.id
  269. INNER JOIN civicrm_mailing {$this->_aliases['civicrm_mailing']}
  270. ON civicrm_mailing_job.mailing_id = {$this->_aliases['civicrm_mailing']}.id
  271. AND civicrm_mailing_job.is_test = 0
  272. ";
  273. $this->joinPhoneFromContact();
  274. }
  275. public function where() {
  276. parent::where();
  277. $this->_where .= " AND {$this->_aliases['civicrm_mailing']}.sms_provider_id IS NULL";
  278. }
  279. public function groupBy() {
  280. $this->_groupBy = '';
  281. if (!empty($this->_params['charts'])) {
  282. $groupBy = "{$this->_aliases['civicrm_mailing']}.id";
  283. }
  284. else {
  285. $groupBy = "{$this->_aliases['civicrm_mailing_event_trackable_url_open']}.id";
  286. }
  287. $this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
  288. }
  289. public function postProcess() {
  290. $this->beginPostProcess();
  291. // get the acl clauses built before we assemble the query
  292. $this->buildACLClause($this->_aliases['civicrm_contact']);
  293. $sql = $this->buildQuery(TRUE);
  294. $rows = $graphRows = [];
  295. $this->buildRows($sql, $rows);
  296. $this->formatDisplay($rows);
  297. $this->doTemplateAssignment($rows);
  298. $this->endPostProcess($rows);
  299. }
  300. /**
  301. * @param $rows
  302. */
  303. public function buildChart(&$rows) {
  304. if (empty($rows)) {
  305. return;
  306. }
  307. $chartInfo = [
  308. 'legend' => ts('Mail Click-Through Report'),
  309. 'xname' => ts('Mailing'),
  310. 'yname' => ts('Clicks'),
  311. 'xLabelAngle' => 20,
  312. 'tip' => ts('Clicks: %1', [1 => '#val#']),
  313. ];
  314. foreach ($rows as $row) {
  315. $chartInfo['values'][$row['civicrm_mailing_mailing_name_alias']] = $row['civicrm_mailing_click_count'];
  316. }
  317. // build the chart.
  318. CRM_Utils_OpenFlashChart::buildChart($chartInfo, $this->_params['charts']);
  319. $this->assign('chartType', $this->_params['charts']);
  320. }
  321. /**
  322. * Alter display of rows.
  323. *
  324. * Iterate through the rows retrieved via SQL and make changes for display purposes,
  325. * such as rendering contacts as links.
  326. *
  327. * @param array $rows
  328. * Rows generated by SQL, with an array for each row.
  329. */
  330. public function alterDisplay(&$rows) {
  331. $entryFound = FALSE;
  332. foreach ($rows as $rowNum => $row) {
  333. // If the email address has been deleted
  334. if (array_key_exists('civicrm_email_email', $row)) {
  335. if (empty($rows[$rowNum]['civicrm_email_email'])) {
  336. $rows[$rowNum]['civicrm_email_email'] = '<del>' . ts('Email address deleted.') . '</del>';
  337. }
  338. $entryFound = TRUE;
  339. }
  340. // make count columns point to detail report
  341. // convert display name to links
  342. if (array_key_exists('civicrm_contact_sort_name', $row) &&
  343. array_key_exists('civicrm_contact_id', $row)
  344. ) {
  345. $url = CRM_Utils_System::url('civicrm/contact/view',
  346. 'reset=1&cid=' . $row['civicrm_contact_id'],
  347. $this->_absoluteUrl
  348. );
  349. $rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
  350. $rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact details for this contact.");
  351. $entryFound = TRUE;
  352. }
  353. // skip looking further in rows, if first row itself doesn't
  354. // have the column we need
  355. if (!$entryFound) {
  356. break;
  357. }
  358. }
  359. }
  360. }