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