Merge pull request #171 from yashodha/issue-9394
[civicrm-core.git] / CRM / Report / Form / Member / Lapse.php
1 <?php
2 // $Id$
3
4 /*
5 +--------------------------------------------------------------------+
6 | CiviCRM version 4.3 |
7 +--------------------------------------------------------------------+
8 | Copyright CiviCRM LLC (c) 2004-2013 |
9 +--------------------------------------------------------------------+
10 | This file is a part of CiviCRM. |
11 | |
12 | CiviCRM is free software; you can copy, modify, and distribute it |
13 | under the terms of the GNU Affero General Public License |
14 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
15 | |
16 | CiviCRM is distributed in the hope that it will be useful, but |
17 | WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
19 | See the GNU Affero General Public License for more details. |
20 | |
21 | You should have received a copy of the GNU Affero General Public |
22 | License and the CiviCRM Licensing Exception along |
23 | with this program; if not, contact CiviCRM LLC |
24 | at info[AT]civicrm[DOT]org. If you have questions about the |
25 | GNU Affero General Public License or the licensing of CiviCRM, |
26 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
27 +--------------------------------------------------------------------+
28 */
29
30 /**
31 *
32 * @package CRM
33 * @copyright CiviCRM LLC (c) 2004-2013
34 * $Id$
35 *
36 */
37 class CRM_Report_Form_Member_Lapse extends CRM_Report_Form {
38
39 protected $_summary = NULL;
40 protected $_addressField = FALSE;
41 protected $_emailField = FALSE;
42 protected $_phoneField = FALSE;
43 protected $_charts = array('' => 'Tabular');
44 protected $_customGroupExtends = array(
45 'Membership');
46 public $_drilldownReport = array('member/detail' => 'Link to Detail Report');
47
48 function __construct() {
49 // UI for selecting columns to appear in the report list
50 // array conatining the columns, group_bys and filters build and provided to Form
51 $this->_columns = array(
52 'civicrm_contact' =>
53 array(
54 'dao' => 'CRM_Contact_DAO_Contact',
55 'fields' =>
56 array(
57 'sort_name' =>
58 array('title' => ts('Member Name'),
59 'no_repeat' => TRUE,
60 'required' => TRUE,
61 ),
62 'id' =>
63 array(
64 'no_display' => TRUE,
65 'required' => TRUE,
66 ),
67 'first_name' =>
68 array('title' => ts('First Name'),
69 'no_repeat' => TRUE,
70 ),
71 'id' =>
72 array(
73 'no_display' => TRUE,
74 'required' => TRUE,
75 ),
76 'last_name' =>
77 array('title' => ts('Last Name'),
78 'no_repeat' => TRUE,
79 ),
80 'id' =>
81 array(
82 'no_display' => TRUE,
83 'required' => TRUE,
84 ),
85 ),
86 'grouping' => 'contact-fields',
87 ),
88 'civicrm_membership_type' =>
89 array(
90 'dao' => 'CRM_Member_DAO_MembershipType',
91 'grouping' => 'member-fields',
92 'filters' =>
93 array(
94 'tid' =>
95 array(
96 'name' => 'id',
97 'title' => ts('Membership Types'),
98 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
99 'options' => CRM_Member_PseudoConstant::membershipType(),
100 ),
101 ),
102 ),
103 'civicrm_membership' =>
104 array(
105 'dao' => 'CRM_Member_DAO_Membership',
106 'grouping' => 'member-fields',
107 'fields' =>
108 array(
109 'membership_type_id' =>
110 array(
111 'title' => 'Membership Type',
112 'required' => TRUE,
113 'type' => CRM_Utils_Type::T_STRING,
114 ),
115 'membership_start_date' => array('title' => ts('Current Cycle Start Date'),
116 ),
117 'membership_end_date' => array('title' => ts('Membership Lapse Date'),
118 'required' => TRUE,
119 ),
120 ),
121 'filters' =>
122 array(
123 'membership_end_date' =>
124 array(
125 'title' => 'Lapsed Memberships',
126 'operatorType' => CRM_Report_Form::OP_DATE,
127 ),
128 ),
129 ),
130 'civicrm_membership_status' =>
131 array(
132 'dao' => 'CRM_Member_DAO_MembershipStatus',
133 'alias' => 'mem_status',
134 'fields' =>
135 array(
136 'name' => array('title' => ts('Current Status'),
137 'required' => TRUE,
138 ),
139 ),
140 'grouping' => 'member-fields',
141 ),
142 'civicrm_address' =>
143 array(
144 'dao' => 'CRM_Core_DAO_Address',
145 'fields' =>
146 array(
147 'street_address' => NULL,
148 'city' => NULL,
149 'postal_code' => NULL,
150 'state_province_id' =>
151 array('title' => ts('State/Province'),
152 ),
153 'country_id' =>
154 array('title' => ts('Country'),
155 'default' => TRUE,
156 ),
157 ),
158 'grouping' => 'contact-fields',
159 ),
160 'civicrm_phone' =>
161 array(
162 'dao' => 'CRM_Core_DAO_Phone',
163 'alias' => 'phone',
164 'fields' =>
165 array('phone' => NULL),
166 'grouping' => 'contact-fields',
167 ),
168 'civicrm_email' =>
169 array(
170 'dao' => 'CRM_Core_DAO_Email',
171 'fields' =>
172 array('email' => NULL),
173 'grouping' => 'contact-fields',
174 ),
175 'civicrm_group' =>
176 array(
177 'dao' => 'CRM_Contact_DAO_GroupContact',
178 'alias' => 'cgroup',
179 'filters' =>
180 array(
181 'gid' =>
182 array(
183 'name' => 'group_id',
184 'title' => ts('Group'),
185 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
186 'group' => TRUE,
187 'options' => CRM_Core_PseudoConstant::group(),
188 ),
189 ),
190 ),
191 );
192
193 $this->_tagFilter = TRUE;
194 parent::__construct();
195 }
196
197 function preProcess() {
198 parent::preProcess();
199 }
200
201 function select() {
202 $select = array();
203 $this->_columnHeaders = array();
204 foreach ($this->_columns as $tableName => $table) {
205 if (array_key_exists('fields', $table)) {
206 foreach ($table['fields'] as $fieldName => $field) {
207 if (CRM_Utils_Array::value('required', $field) ||
208 CRM_Utils_Array::value($fieldName, $this->_params['fields'])
209 ) {
210 // to include optional columns address ,email and phone only if checked
211 if ($tableName == 'civicrm_address') {
212 $this->_addressField = TRUE;
213 }
214 elseif ($tableName == 'civicrm_email') {
215 $this->_emailField = TRUE;
216 }
217 elseif ($tableName == 'civicrm_phone') {
218 $this->_phoneField = TRUE;
219 }
220 $select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
221 $this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
222 $this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
223 }
224 }
225 }
226 }
227 $this->_select = "SELECT " . implode(', ', $select) . " ";
228 }
229
230 static function formRule($fields, $files, $self) {
231 $errors = $grouping = array();
232 //check for searching combination of dispaly columns and
233 //grouping criteria
234
235 return $errors;
236 }
237
238 function from() {
239 $this->_from = NULL;
240
241 $this->_from = "
242 FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}
243 INNER JOIN civicrm_membership {$this->_aliases['civicrm_membership']}
244 ON {$this->_aliases['civicrm_contact']}.id =
245 {$this->_aliases['civicrm_membership']}.contact_id AND {$this->_aliases['civicrm_membership']}.is_test = 0
246 LEFT JOIN civicrm_membership_status {$this->_aliases['civicrm_membership_status']}
247 ON {$this->_aliases['civicrm_membership_status']}.id =
248 {$this->_aliases['civicrm_membership']}.status_id
249 LEFT JOIN civicrm_membership_type {$this->_aliases['civicrm_membership_type']}
250 ON {$this->_aliases['civicrm_membership']}.membership_type_id =
251 {$this->_aliases['civicrm_membership_type']}.id";
252
253 // include address field if address column is to be included
254 if ($this->_addressField) {
255 $this->_from .= "
256 LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
257 ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND {$this->_aliases['civicrm_address']}.is_primary = 1\n";
258 }
259
260 // include email field if email column is to be included
261 if ($this->_emailField) {
262 $this->_from .= "
263 LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
264 ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND {$this->_aliases['civicrm_email']}.is_primary = 1\n";
265 }
266
267 // include phone field if phone column is to be included
268 if ($this->_phoneField) {
269 $this->_from .= "
270 LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
271 ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id
272 AND {$this->_aliases['civicrm_phone']}.is_primary = 1\n";
273 }
274 }
275
276 function where() {
277 $clauses = array();
278 foreach ($this->_columns as $tableName => $table) {
279 if (array_key_exists('filters', $table)) {
280 foreach ($table['filters'] as $fieldName => $field) {
281 $clause = NULL;
282
283 if ($field['operatorType'] & CRM_Utils_Type::T_DATE) {
284 $relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
285 $from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
286 $to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
287
288 if ($relative || $from || $to) {
289 $clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
290 }
291 }
292 else {
293 $op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
294 if ($op) {
295 $clause = $this->whereClause($field,
296 $op,
297 CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
298 CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
299 CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
300 );
301 }
302 }
303 if (!empty($clause)) {
304 $clauses[$fieldName] = $clause;
305 }
306 }
307 }
308 }
309
310 if (empty($clauses)) {
311 $this->_where = "WHERE end_date < '" . date('Y-m-d') . "' AND {$this->_aliases['civicrm_membership_status']}.name = 'Expired'";
312 }
313 else {
314 if (!array_key_exists('end_date', $clauses)) {
315 $this->_where = "WHERE end_date < '" . date('Y-m-d') . "' AND " . implode(' AND ', $clauses);
316 }
317 else {
318 $this->_where = "WHERE " . implode(' AND ', $clauses);
319 }
320 }
321
322 if ($this->_aclWhere) {
323 $this->_where .= " AND {$this->_aclWhere} ";
324 }
325 }
326
327 function orderBy() {
328 $this->_orderBy = " ORDER BY {$this->_aliases['civicrm_contact']}.sort_name, {$this->_aliases['civicrm_contact']}.id, {$this->_aliases['civicrm_membership']}.membership_type_id";
329 }
330
331 function postProcess() {
332 $this->beginPostProcess();
333
334 // get the acl clauses built before we assemble the query
335 $this->buildACLClause($this->_aliases['civicrm_contact']);
336 $sql = $this->buildQuery(TRUE);
337
338 $dao = CRM_Core_DAO::executeQuery($sql);
339 $rows = $graphRows = array();
340 $count = 0;
341 while ($dao->fetch()) {
342 $row = array();
343 foreach ($this->_columnHeaders as $key => $value) {
344 $row[$key] = $dao->$key;
345 }
346
347 $rows[] = $row;
348 }
349 $this->formatDisplay($rows);
350
351 // assign variables to templates
352 $this->doTemplateAssignment($rows);
353
354 $this->endPostProcess($rows);
355 }
356
357 function alterDisplay(&$rows) {
358 // custom code to alter rows
359 $entryFound = FALSE;
360 $checkList = array();
361
362 foreach ($rows as $rowNum => $row) {
363
364 if (!empty($this->_noRepeats) && $this->_outputMode != 'csv') {
365 // not repeat contact display names if it matches with the one
366 // in previous row
367
368 $repeatFound = FALSE;
369 foreach ($row as $colName => $colVal) {
370 if (CRM_Utils_Array::value($colName, $checkList) &&
371 is_array($checkList[$colName]) &&
372 in_array($colVal, $checkList[$colName])
373 ) {
374 $rows[$rowNum][$colName] = "";
375 $repeatFound = TRUE;
376 }
377 if (in_array($colName, $this->_noRepeats)) {
378 $checkList[$colName][] = $colVal;
379 }
380 }
381 }
382
383 //handle the Membership Type Ids
384 if (array_key_exists('civicrm_membership_membership_type_id', $row)) {
385 if ($value = $row['civicrm_membership_membership_type_id']) {
386 $rows[$rowNum]['civicrm_membership_membership_type_id'] = CRM_Member_PseudoConstant::membershipType($value, FALSE);
387 }
388 $entryFound = TRUE;
389 }
390
391 // handle state province
392 if (array_key_exists('civicrm_address_state_province_id', $row)) {
393 if ($value = $row['civicrm_address_state_province_id']) {
394 $rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value, FALSE);
395 }
396 $entryFound = TRUE;
397 }
398
399 // handle country
400 if (array_key_exists('civicrm_address_country_id', $row)) {
401 if ($value = $row['civicrm_address_country_id']) {
402 $rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
403 }
404 $entryFound = TRUE;
405 }
406
407 // convert display name to links
408 if (array_key_exists('civicrm_contact_sort_name', $row) &&
409 array_key_exists('civicrm_contact_id', $row)
410 ) {
411 $url = CRM_Report_Utils_Report::getNextUrl('member/detail',
412 'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_contact_id'],
413 $this->_absoluteUrl, $this->_id, $this->_drilldownReport
414 );
415 $rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
416 $rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Membership Detail for this Contact.");
417 }
418
419 // skip looking further in rows, if first row itself doesn't
420 // have the column we need
421 if (!$entryFound) {
422 break;
423 }
424 }
425 }
426 }
427