1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36:
37:
38: 39: 40: 41: 42:
43: class SearchController extends x2base {
44:
45: 46: 47: 48: 49:
50: public function accessRules(){
51: return array(
52: array('allow',
53: 'actions' => array('search', 'buildIndex'),
54: 'users' => array('@'),
55: ),
56: array('deny',
57: 'users' => array('*'),
58: ),
59: );
60: }
61:
62: public function filters(){
63: return array(
64: 'setPortlets',
65: 'accessControl',
66: );
67: }
68:
69: 70: 71:
72: public function actionBuildIndex(){
73:
74: $contact = new Contacts;
75: $fieldData = $contact->getFields();
76:
77:
78:
79: $fields = array();
80: for($i = 0; $i < count($fieldData); $i++){
81: if(in_array($fieldData[$i]->type, array('dropdown', 'text', 'varchar', 'assignment'))
82: && !in_array($fieldData[$i]->fieldName, array('firstName', 'lastName', 'updatedBy', 'priority', 'id'))
83: ){
84:
85: if($fieldData[$i]->relevance == 'High')
86: $relevance = 3;
87: elseif($fieldData[$i]->relevance == 'Medium')
88: $relevance = 2;
89: else
90: $relevance = 1;
91:
92: $fields[$fieldData[$i]->fieldName] = array(
93: 'type' => $fieldData[$i]->type,
94: 'linkType' => $fieldData[$i]->linkType,
95: 'relevance' => $relevance
96: );
97: }
98: }
99:
100: $t0 = microtime(true);
101:
102:
103: $totalCount = Yii::app()->db->createCommand('SELECT count(*) from x2_contacts;')->queryScalar();
104:
105: $dataProvider = new CSqlDataProvider('SELECT '.implode(',', array_merge(array_keys($fields), array('id', 'visibility'))).' FROM x2_contacts', array(
106:
107:
108:
109: 'totalItemCount' => $totalCount,
110: 'sort' => array('defaultOrder' => 'id ASC'),
111: 'pagination' => array(
112: 'pageSize' => 500,
113: ),
114: ));
115: $dataProvider->getData();
116:
117:
118: $pages = $dataProvider->pagination->getPageCount();
119: echo $pages.' pages.<br>';
120: $searchTerms = array();
121:
122:
123:
124: ob_end_flush();
125:
126: $keys = array();
127: $tokenChars = " \n\r\t!$%^&*()_+-=~[]{}\\|:;'\",.<>?/`‘’•–—“”";
128: $noiseWords = array(
129: 'a', 'about', 'after', 'all', 'also', 'an', 'and', 'another', 'any', 'are', 'arent', 'as', 'at', 'back', 'be', 'because', 'been', 'before',
130: 'being', 'between', 'both', 'but', 'by', 'came', 'can', 'cant', 'come', 'contact', 'contacts', 'contacted', 'could', 'data', 'did', 'didnt',
131: 'do', 'dont', 'does', 'doesnt', 'each', 'for', 'from', 'get', 'go', 'going', 'goes', 'got', 'has', 'hasnt', 'had', 'hadnt', 'he', 'hes', 'his',
132: 'hed', 'have', 'havent', 'her', 'hers', 'here', 'heres', 'him', 'himself', 'how', 'i', 'if', 'in', 'into', 'is', 'it', 'its', 'like', 'make',
133: 'made', 'makes', 'many', 'me', 'might', 'mightnt', 'more', 'most', 'much', 'must', 'mustnt', 'my', 'mine', 'never', 'no', 'now', 'not', 'of',
134: 'on', 'only', 'onto', 'or', 'other', 'our', 'out', 'over', 'said', 'same', 'see', 'she', 'shes', 'should', 'shouldnt', 'since', 'some', 'still',
135: 'such', 'take', 'than', 'that', 'the', 'their', 'them', 'then', 'there', 'theres', 'these', 'they', 'theyre', 'this', 'those', 'through', 'to',
136: 'too', 'today', 'under', 'up', 'very', 'want', 'wants', 'wanted', 'was', 'wasnt', 'way', 'ways', 'we', 'well', 'were', 'what', 'whats', 'where',
137: 'which', 'while', 'who', 'why', 'will', 'with', 'would', 'wont', 'you', 'your', 'youre'
138: );
139:
140:
141: for($i = 1; $i <= $pages; ++$i){
142:
143:
144: $links = array();
145:
146: $dataProvider->pagination->setCurrentPage($i);
147:
148: foreach($dataProvider->getData($i > 1) as $record){
149:
150: foreach($fields as $fieldName => &$field){
151:
152:
153: if(!empty($record[$fieldName])){
154:
155: $token = strtok(preg_replace('/(?<=\w)\'(?=\w)/u', '', $record[$fieldName]), $tokenChars);
156: while($token !== false){
157: $token = strtolower($token);
158:
159: if(strlen($token) <= 50 && !in_array($token, $noiseWords)){
160: $links[] = array(
161: $token,
162: 'Contacts',
163: $record['id'],
164: $field['relevance'],
165: $record['assignedTo'],
166: $record['visibility']
167: );
168: }
169: $token = strtok($tokenChars);
170: }
171: }
172: }
173: unset($field);
174: }
175:
176: $sql = 'INSERT INTO x2_search (keyword, modelType, modelId, relevance, assignedTo, visibility) VALUES ';
177: for($j = 0; $j < count($links); ++$j){
178: $sql .= '(?,?,?,?,?,?)';
179: if($j < count($links) - 1)
180: $sql .= ',';
181: }
182:
183:
184:
185:
186:
187: $query = Yii::app()->db->createCommand($sql);
188: for($j = 0; $j < count($links); ++$j){
189: $query = $query->bindValues(array(
190: 6 * $j + 1 => $links[$j][0],
191: 6 * $j + 2 => $links[$j][1],
192: 6 * $j + 3 => $links[$j][2],
193: 6 * $j + 4 => $links[$j][3],
194: 6 * $j + 5 => $links[$j][4],
195: 6 * $j + 6 => $links[$j][5]
196: ));
197: }
198:
199:
200: $query->execute();
201:
202:
203: echo "Page $i...done<br>";
204: flush();
205: }
206:
207:
208:
209: echo 'Time: '.(microtime(true) - $t0).'<br>';
210: }
211:
212: public function actionFastSearch(){
213:
214: }
215:
216: 217: 218: 219: 220:
221: public function actionSearch(){
222: ini_set('memory_limit', -1);
223:
224: $term = isset($_GET['term']) ? $_GET['term'] : "";
225: if (empty($term)) {
226: $dataProvider = new CArrayDataProvider(array());
227: Yii::app()->user->setFlash ('error', Yii::t('app', "Search term cannot be empty."));
228: $this->render('search', array(
229: 'dataProvider' => $dataProvider,
230: ));
231: } else {
232:
233: if(substr($term, 0, 1) != "#"){
234:
235: $modules = Modules::model()->findAllByAttributes(array('searchable' => 1));
236: $comparisons = array();
237: $other = array();
238: foreach($modules as $module){
239: $module->name == 'products' ? $type = ucfirst('Product') : $type = ucfirst($module->name);
240: $module->name == 'quotes' ? $type = ucfirst('Quote') : $type = $type;
241: $module->name == 'opportunities' ? $type = ucfirst('Opportunity') : $type = $type;
242: $criteria = new CDbCriteria();
243: $fields = Fields::model()->findAllByAttributes(array('modelName' => $type, 'searchable' => 1));
244: $temp = array();
245: $fieldNames = array();
246: if(count($fields) < 1){
247: $criteria->compare('id', '<0', true, 'AND');
248: }
249: foreach($fields as $field){
250: $temp[] = $field->id;
251: $fieldNames[] = $field->fieldName;
252: $criteria->compare($field->fieldName, $term, true, "OR");
253: if($field->type == 'phone'){
254: $tempPhone = preg_replace('/\D/', '', $term);
255: $phoneLookup = PhoneNumber::model()->findByAttributes(array('modelType' => $field->modelName, 'number' => $tempPhone, 'fieldName' => $field->fieldName));
256: if(isset($phoneLookup)){
257: $criteria->compare('id', $phoneLookup->modelId, true, "OR");
258: }
259: }
260: }
261: if(Yii::app()->user->getName() != 'admin' && X2Model::model($type)->hasAttribute('visibility') && X2Model::model($type)->hasAttribute('assignedTo')){
262: $condition = 'visibility="1" OR (assignedTo="Anyone" AND visibility!="0") OR assignedTo="'.Yii::app()->user->getName().'"';
263:
264: $groupLinks = Yii::app()->db->createCommand()->select('groupId')->from('x2_group_to_user')->where('userId='.Yii::app()->user->getId())->queryColumn();
265: if(!empty($groupLinks))
266: $condition .= ' OR assignedTo IN ('.implode(',', $groupLinks).')';
267:
268: $condition .= 'OR (visibility=2 AND assignedTo IN
269: (SELECT username FROM x2_group_to_user WHERE groupId IN
270: (SELECT groupId FROM x2_group_to_user WHERE userId='.Yii::app()->user->getId().')))';
271: $criteria->addCondition($condition);
272: }
273: if($module->name == 'actions'){
274: $criteria->with = array('actionText');
275: $criteria->compare('actionText.text', $term, true, "OR");
276: }
277: if(class_exists($type)){
278: $arr = X2Model::model($type)->findAll($criteria);
279: $comparisons[$type] = $temp;
280: $other[$type] = $arr;
281: }
282: }
283: $high = array();
284: $medium = array();
285: $low = array();
286:
287: $userHigh = array();
288: $userMedium = array();
289: $userLow = array();
290:
291: $records = array();
292: $userRecords = array();
293:
294: $regEx = "/".preg_quote($term, '/')."/i";
295:
296: foreach($other as $key => $recordType){
297: $fieldList = $comparisons[$key];
298: foreach($recordType as $otherRecord){
299: if($key == 'Actions'){
300: if($otherRecord->hasAttribute('assignedTo') && $otherRecord->assignedTo == Yii::app()->user->getName())
301: $userHigh[] = $otherRecord;
302: else
303: $high[] = $otherRecord;
304: }else{
305: foreach($fieldList as $field){
306: $fieldRecord = Fields::model()->findByPk($field);
307: $fieldName = $fieldRecord->fieldName;
308: if(preg_match($regEx, $otherRecord->$fieldName) > 0){
309: switch($fieldRecord->relevance){
310: case "High":
311: if(!in_array($otherRecord, $high, true) && !in_array($otherRecord, $medium, true) && !in_array($otherRecord, $low, true) &&
312: !in_array($otherRecord, $userHigh, true) && !in_array($otherRecord, $userMedium, true) && !in_array($otherRecord, $userLow, true)){
313: if($otherRecord->hasAttribute('assignedTo') && $otherRecord->assignedTo == Yii::app()->user->getName())
314: $userHigh[] = $otherRecord;
315: else
316: $high[] = $otherRecord;
317: }
318: break;
319: case "Medium":
320: if(!in_array($otherRecord, $high, true) && !in_array($otherRecord, $medium, true) && !in_array($otherRecord, $low, true) &&
321: !in_array($otherRecord, $userHigh, true) && !in_array($otherRecord, $userMedium, true) && !in_array($otherRecord, $userLow, true)){
322: if($otherRecord->hasAttribute('assignedTo') && $otherRecord->assignedTo == Yii::app()->user->getName())
323: $userMedium[] = $otherRecord;
324: else
325: $medium[] = $otherRecord;
326: }
327: break;
328: case "Low":
329: if(!in_array($otherRecord, $high, true) && !in_array($otherRecord, $medium, true) && !in_array($otherRecord, $low, true) &&
330: !in_array($otherRecord, $userHigh, true) && !in_array($otherRecord, $userMedium, true) && !in_array($otherRecord, $userLow, true)){
331: if($otherRecord->hasAttribute('assignedTo') && $otherRecord->assignedTo == Yii::app()->user->getName())
332: $userLow[] = $otherRecord;
333: else
334: $low[] = $otherRecord;
335: }
336: break;
337: default:
338: if($otherRecord->hasAttribute('assignedTo') && $otherRecord->assignedTo == Yii::app()->user->getName())
339: $userLow[] = $otherRecord;
340: else
341: $low[] = $otherRecord;
342: }
343: }elseif($fieldRecord->type == 'phone'){
344: $tempPhone = preg_replace('/\D/', '', $term);
345:
346: if(strlen($tempPhone) == 10){
347: $phoneLookup = PhoneNumber::model()->findByAttributes(array('modelType' => $fieldRecord->modelName, 'number' => $tempPhone, 'fieldName' => $fieldName));
348: if(!in_array($otherRecord, $high, true) && !in_array($otherRecord, $medium, true) && !in_array($otherRecord, $low, true) &&
349: !in_array($otherRecord, $userHigh, true) && !in_array($otherRecord, $userMedium, true) && !in_array($otherRecord, $userLow, true)){
350: if(isset($phoneLookup) && $otherRecord->id == $phoneLookup->modelId){
351: if($otherRecord->hasAttribute('assignedTo') && $otherRecord->assignedTo == Yii::app()->user->getName())
352: $userHigh[] = $otherRecord;
353: else
354: $high[] = $otherRecord;
355: }
356: }
357: }
358: }
359: }
360: }
361: }
362: }
363: $records = array_merge($high, $medium);
364: $records = array_merge($records, $low);
365:
366: $userRecords = array_merge($userHigh, $userMedium);
367: $userRecords = array_merge($userRecords, $userLow);
368:
369: $records = array_merge($userRecords, $records);
370:
371: $records = Record::convert($records, false);
372: if(count($records) == 1){
373:
374:
375:
376:
377: if(!empty($records[0]['#recordUrl'])) {
378: $this->redirect($records[0]['#recordUrl']);
379: }
380: }
381: $dataProvider = new CArrayDataProvider($records, array(
382: 'id' => 'id',
383: 'pagination' => array(
384: 'pageSize' => Profile::getResultsPerPage(),
385: ),
386: ));
387:
388: $this->render('search', array(
389: 'records' => $records,
390: 'dataProvider' => $dataProvider,
391: 'term' => $term,
392: ));
393: }else{
394: Yii::app()->user->setState('vcr-list', $term);
395: $_COOKIE['vcr-list'] = $term;
396: $tagQuery = "
397: SELECT *
398: FROM x2_tags
399: WHERE tag=:tag
400: group BY tag, type, itemId";
401: $params = array (':tag' => $term);
402:
403:
404: $sql = Yii::app()->db->createCommand ($tagQuery);
405: $totalItemCount = Yii::app()->db->createCommand ("
406: SELECT count(*)
407: FROM ($tagQuery) as t1;
408: ")->queryScalar ($params);
409:
410: $results = new CSqlDataProvider ($sql, array (
411: 'totalItemCount' => $totalItemCount,
412: 'sort' => array(
413: 'defaultOrder' => 'timestamp DESC',
414: ),
415: 'pagination' => array(
416: 'pageSize' => Profile::getResultsPerPage(),
417: ),
418: 'params' => $params,
419: ));
420: $this->render('searchTags', array(
421: 'tags' => $results,
422: 'term' => $term,
423: ));
424: }
425: }
426: }
427:
428: }
429:
430: ?>
431: