INFRA-132 - CRM/Contact - Misc
[civicrm-core.git] / CRM / Contact / Form / Search / Custom / DateAdded.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
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 *
30 * @package CRM
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35class CRM_Contact_Form_Search_Custom_DateAdded extends CRM_Contact_Form_Search_Custom_Base implements CRM_Contact_Form_Search_Interface {
36
430ae6dd
TO
37 protected $_debug = 0;
38
86538308
EM
39 /**
40 * @param $formValues
41 */
00be9182 42 public function __construct(&$formValues) {
6a488035
TO
43 parent::__construct($formValues);
44
45 $this->_includeGroups = CRM_Utils_Array::value('includeGroups', $formValues, array());
46 $this->_excludeGroups = CRM_Utils_Array::value('excludeGroups', $formValues, array());
47
48 $this->_columns = array(
7b99ead3 49 ts('Contact ID') => 'contact_id',
6a488035
TO
50 ts('Contact Type') => 'contact_type',
51 ts('Name') => 'sort_name',
52 ts('Date Added') => 'date_added',
53 );
54 }
55
86538308 56 /**
11cac306 57 * @param CRM_Core_Form $form
86538308 58 */
00be9182 59 public function buildForm(&$form) {
6a488035
TO
60 $form->addDate('start_date', ts('Start Date'), FALSE, array('formatType' => 'custom'));
61 $form->addDate('end_date', ts('End Date'), FALSE, array('formatType' => 'custom'));
62
24431f7b 63 $groups = CRM_Core_PseudoConstant::nestedGroup();
11cac306
CW
64
65 $select2style = array(
66 'multiple' => TRUE,
67 'style' => 'width: 100%; max-width: 60em;',
68 'class' => 'crm-select2',
69 'placeholder' => ts('- select -'),
6a488035
TO
70 );
71
11cac306
CW
72 $form->add('select', 'includeGroups',
73 ts('Include Group(s)'),
74 $groups,
75 FALSE,
76 $select2style
6a488035
TO
77 );
78
11cac306
CW
79 $form->add('select', 'excludeGroups',
80 ts('Exclude Group(s)'),
81 $groups,
82 FALSE,
83 $select2style
84 );
6a488035
TO
85
86 $this->setTitle('Search by date added to CiviCRM');
87
88 //redirect if group not available for search criteria
89 if (count($groups) == 0) {
90 CRM_Core_Error::statusBounce(ts("Atleast one Group must be present for search."),
91 CRM_Utils_System::url('civicrm/contact/search/custom/list',
92 'reset=1'
93 )
94 );
95 }
96
97 /**
98 * if you are using the standard template, this array tells the template what elements
99 * are part of the search criteria
100 */
101 $form->assign('elements', array('start_date', 'end_date', 'includeGroups', 'excludeGroups'));
102 }
103
86538308
EM
104 /**
105 * @return null
106 */
00be9182 107 public function summary() {
6a488035
TO
108 return NULL;
109 }
110
00be9182 111 public function contactIDs($offset = 0, $rowcount = 0, $sort = NULL, $returnSQL = FALSE) {
26a9b6ab
C
112 return $this->all($offset, $rowcount, $sort, FALSE, TRUE);
113 }
114
86538308
EM
115 /**
116 * @param int $offset
117 * @param int $rowcount
118 * @param null $sort
119 * @param bool $includeContactIDs
120 * @param bool $justIDs
121 *
122 * @return string
123 */
51ccfbbe
TO
124 function all(
125 $offset = 0, $rowcount = 0, $sort = NULL,
6a488035
TO
126 $includeContactIDs = FALSE, $justIDs = FALSE
127 ) {
128
129 $this->_includeGroups = CRM_Utils_Array::value('includeGroups', $this->_formValues, array());
130
131 $this->_excludeGroups = CRM_Utils_Array::value('excludeGroups', $this->_formValues, array());
132
133 $this->_allSearch = FALSE;
134 $this->_groups = FALSE;
135
136 if (empty($this->_includeGroups) && empty($this->_excludeGroups)) {
137 //empty search
138 $this->_allSearch = TRUE;
139 }
140
141 if (!empty($this->_includeGroups) || !empty($this->_excludeGroups)) {
142 //group(s) selected
143 $this->_groups = TRUE;
144 }
145
146 if ($justIDs) {
26a9b6ab
C
147 $selectClause = "contact_a.id as contact_id";
148 $groupBy = " GROUP BY contact_a.id";
149 $sort = "contact_a.id";
6a488035
TO
150 }
151 else {
152 $selectClause = "contact_a.id as contact_id,
153 contact_a.contact_type as contact_type,
154 contact_a.sort_name as sort_name,
155 d.date_added as date_added";
26a9b6ab 156 $groupBy = " GROUP BY contact_id ";
6a488035
TO
157 }
158
6a488035
TO
159 return $this->sql($selectClause,
160 $offset, $rowcount, $sort,
161 $includeContactIDs, $groupBy
162 );
163 }
164
86538308
EM
165 /**
166 * @return string
167 */
00be9182 168 public function from() {
6a488035
TO
169 //define table name
170 $randomNum = md5(uniqid());
171 $this->_tableName = "civicrm_temp_custom_{$randomNum}";
172
173 //grab the contacts added in the date range first
174 $sql = "CREATE TEMPORARY TABLE dates_{$this->_tableName} ( id int primary key, date_added date ) ENGINE=HEAP";
175 if ($this->_debug > 0) {
176 print "-- Date range query: <pre>";
177 print "$sql;";
178 print "</pre>";
179 }
180 CRM_Core_DAO::executeQuery($sql);
181
182 $startDate = CRM_Utils_Date::mysqlToIso(CRM_Utils_Date::processDate($this->_formValues['start_date']));
183 $endDateFix = NULL;
184 if (!empty($this->_formValues['end_date'])) {
185 $endDate = CRM_Utils_Date::mysqlToIso(CRM_Utils_Date::processDate($this->_formValues['end_date']));
186 # tack 11:59pm on to make search inclusive of the end date
187 $endDateFix = "AND date_added <= '" . substr($endDate, 0, 10) . " 23:59:00'";
188 }
189
190 $dateRange = "INSERT INTO dates_{$this->_tableName} ( id, date_added )
191 SELECT
192 civicrm_contact.id,
193 min(civicrm_log.modified_date) AS date_added
194 FROM
195 civicrm_contact LEFT JOIN civicrm_log
196 ON (civicrm_contact.id = civicrm_log.entity_id AND
197 civicrm_log.entity_table = 'civicrm_contact')
198 GROUP BY
199 civicrm_contact.id
200 HAVING
201 date_added >= '$startDate'
202 $endDateFix";
203
204 if ($this->_debug > 0) {
205 print "-- Date range query: <pre>";
206 print "$dateRange;";
207 print "</pre>";
208 }
209
210 CRM_Core_DAO::executeQuery($dateRange, CRM_Core_DAO::$_nullArray);
211
212 // Only include groups in the search query of one or more Include OR Exclude groups has been selected.
213 // CRM-6356
214 if ($this->_groups) {
215 //block for Group search
216 $smartGroup = array();
217 $group = new CRM_Contact_DAO_Group();
218 $group->is_active = 1;
219 $group->find();
220 while ($group->fetch()) {
221 $allGroups[] = $group->id;
222 if ($group->saved_search_id) {
223 $smartGroup[$group->saved_search_id] = $group->id;
224 }
225 }
226 $includedGroups = implode(',', $allGroups);
227
228 if (!empty($this->_includeGroups)) {
229 $iGroups = implode(',', $this->_includeGroups);
230 }
231 else {
232 //if no group selected search for all groups
233 $iGroups = $includedGroups;
234 }
235 if (is_array($this->_excludeGroups)) {
236 $xGroups = implode(',', $this->_excludeGroups);
237 }
238 else {
239 $xGroups = 0;
240 }
241
242 $sql = "DROP TEMPORARY TABLE IF EXISTS Xg_{$this->_tableName}";
243 CRM_Core_DAO::executeQuery($sql, CRM_Core_DAO::$_nullArray);
244 $sql = "CREATE TEMPORARY TABLE Xg_{$this->_tableName} ( contact_id int primary key) ENGINE=HEAP";
245 CRM_Core_DAO::executeQuery($sql, CRM_Core_DAO::$_nullArray);
246
247 //used only when exclude group is selected
248 if ($xGroups != 0) {
249 $excludeGroup = "INSERT INTO Xg_{$this->_tableName} ( contact_id )
250 SELECT DISTINCT civicrm_group_contact.contact_id
251 FROM civicrm_group_contact, dates_{$this->_tableName} AS d
252 WHERE
253 d.id = civicrm_group_contact.contact_id AND
254 civicrm_group_contact.status = 'Added' AND
255 civicrm_group_contact.group_id IN( {$xGroups})";
256
257 CRM_Core_DAO::executeQuery($excludeGroup, CRM_Core_DAO::$_nullArray);
258
259 //search for smart group contacts
260 foreach ($this->_excludeGroups as $keys => $values) {
261 if (in_array($values, $smartGroup)) {
262 $ssId = CRM_Utils_Array::key($values, $smartGroup);
263
264 $smartSql = CRM_Contact_BAO_SavedSearch::contactIDsSQL($ssId);
265
266 $smartSql = $smartSql . " AND contact_a.id NOT IN (
267 SELECT contact_id FROM civicrm_group_contact
268 WHERE civicrm_group_contact.group_id = {$values} AND civicrm_group_contact.status = 'Removed')";
269
270 $smartGroupQuery = " INSERT IGNORE INTO Xg_{$this->_tableName}(contact_id) $smartSql";
271
272 CRM_Core_DAO::executeQuery($smartGroupQuery, CRM_Core_DAO::$_nullArray);
273 }
274 }
275 }
276
277 $sql = "DROP TEMPORARY TABLE IF EXISTS Ig_{$this->_tableName}";
278 CRM_Core_DAO::executeQuery($sql, CRM_Core_DAO::$_nullArray);
279 $sql = "CREATE TEMPORARY TABLE Ig_{$this->_tableName}
280 ( id int PRIMARY KEY AUTO_INCREMENT,
281 contact_id int,
282 group_names varchar(64)) ENGINE=HEAP";
283
284 if ($this->_debug > 0) {
285 print "-- Include groups query: <pre>";
286 print "$sql;";
287 print "</pre>";
288 }
289
290 CRM_Core_DAO::executeQuery($sql, CRM_Core_DAO::$_nullArray);
291
292 $includeGroup = "INSERT INTO Ig_{$this->_tableName} (contact_id, group_names)
293 SELECT d.id as contact_id, civicrm_group.name as group_name
294 FROM dates_{$this->_tableName} AS d
295 INNER JOIN civicrm_group_contact
296 ON civicrm_group_contact.contact_id = d.id
297 LEFT JOIN civicrm_group
298 ON civicrm_group_contact.group_id = civicrm_group.id";
299
300 //used only when exclude group is selected
301 if ($xGroups != 0) {
302 $includeGroup .= " LEFT JOIN Xg_{$this->_tableName}
303 ON d.id = Xg_{$this->_tableName}.contact_id";
304 }
305 $includeGroup .= " WHERE
306 civicrm_group_contact.status = 'Added' AND
307 civicrm_group_contact.group_id IN($iGroups)";
308
309 //used only when exclude group is selected
310 if ($xGroups != 0) {
311 $includeGroup .= " AND Xg_{$this->_tableName}.contact_id IS null";
312 }
313
314 if ($this->_debug > 0) {
315 print "-- Include groups query: <pre>";
316 print "$includeGroup;";
317 print "</pre>";
318 }
319
320 CRM_Core_DAO::executeQuery($includeGroup, CRM_Core_DAO::$_nullArray);
321
322 //search for smart group contacts
323 foreach ($this->_includeGroups as $keys => $values) {
324 if (in_array($values, $smartGroup)) {
325
326 $ssId = CRM_Utils_Array::key($values, $smartGroup);
327
328 $smartSql = CRM_Contact_BAO_SavedSearch::contactIDsSQL($ssId);
329
330 $smartSql .= " AND contact_a.id IN (
331 SELECT id AS contact_id
332 FROM dates_{$this->_tableName} )";
333
334 $smartSql .= " AND contact_a.id NOT IN (
335 SELECT contact_id FROM civicrm_group_contact
336 WHERE civicrm_group_contact.group_id = {$values} AND civicrm_group_contact.status = 'Removed')";
337
338 //used only when exclude group is selected
339 if ($xGroups != 0) {
340 $smartSql .= " AND contact_a.id NOT IN (SELECT contact_id FROM Xg_{$this->_tableName})";
341 }
342
343 $smartGroupQuery = " INSERT IGNORE INTO
344 Ig_{$this->_tableName}(contact_id)
345 $smartSql";
346
347 CRM_Core_DAO::executeQuery($smartGroupQuery, CRM_Core_DAO::$_nullArray);
348 if ($this->_debug > 0) {
349 print "-- Smart group query: <pre>";
350 print "$smartGroupQuery;";
351 print "</pre>";
352 }
353 $insertGroupNameQuery = "UPDATE IGNORE Ig_{$this->_tableName}
354 SET group_names = (SELECT title FROM civicrm_group
355 WHERE civicrm_group.id = $values)
356 WHERE Ig_{$this->_tableName}.contact_id IS NOT NULL
357 AND Ig_{$this->_tableName}.group_names IS NULL";
358 CRM_Core_DAO::executeQuery($insertGroupNameQuery, CRM_Core_DAO::$_nullArray);
359 if ($this->_debug > 0) {
360 print "-- Smart group query: <pre>";
361 print "$insertGroupNameQuery;";
362 print "</pre>";
363 }
364 }
365 }
366 }
367 // end if( $this->_groups ) condition
368
369 $from = "FROM civicrm_contact contact_a";
370
371 /* We need to join to this again to get the date_added value */
372
373 $from .= " INNER JOIN dates_{$this->_tableName} d ON (contact_a.id = d.id)";
374
375 // Only include groups in the search query of one or more Include OR Exclude groups has been selected.
376 // CRM-6356
377 if ($this->_groups) {
378 $from .= " INNER JOIN Ig_{$this->_tableName} temptable1 ON (contact_a.id = temptable1.contact_id)";
379 }
380
381 return $from;
382 }
383
86538308
EM
384 /**
385 * @param bool $includeContactIDs
386 *
387 * @return string
388 */
00be9182 389 public function where($includeContactIDs = FALSE) {
6a488035
TO
390 return '(1)';
391 }
392
86538308
EM
393 /**
394 * @return string
395 */
00be9182 396 public function templateFile() {
6a488035
TO
397 return 'CRM/Contact/Form/Search/Custom.tpl';
398 }
399
86538308
EM
400 /**
401 * @param $title
402 */
00be9182 403 public function setTitle($title) {
6a488035
TO
404 if ($title) {
405 CRM_Utils_System::setTitle($title);
406 }
407 else {
408 CRM_Utils_System::setTitle(ts('Search'));
409 }
410 }
411
e0ef6999
EM
412 /**
413 * @return mixed
414 */
00be9182 415 public function count() {
6a488035
TO
416 $sql = $this->all();
417
418 $dao = CRM_Core_DAO::executeQuery($sql,
419 CRM_Core_DAO::$_nullArray
420 );
421 return $dao->N;
422 }
423
00be9182 424 public function __destruct() {
6a488035
TO
425 //drop the temp. tables if they exist
426 if (!empty($this->_includeGroups)) {
427 $sql = "DROP TEMPORARY TABLE IF EXISTS Ig_{$this->_tableName}";
428 CRM_Core_DAO::executeQuery($sql, CRM_Core_DAO::$_nullArray);
429 }
430
431 if (!empty($this->_excludeGroups)) {
432 $sql = "DROP TEMPORARY TABLE IF EXISTS Xg_{$this->_tableName}";
433 CRM_Core_DAO::executeQuery($sql, CRM_Core_DAO::$_nullArray);
434 }
435 }
436}