]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/Contacts/Contact.php
Release 6.1.4
[Github/sugarcrm.git] / modules / Contacts / Contact.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38 /*********************************************************************************
39
40  * Description:  TODO: To be written.
41  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
42  * All Rights Reserved.
43  * Contributor(s): ______________________________________..
44  ********************************************************************************/
45
46 require_once('include/SugarObjects/templates/person/Person.php');
47
48
49
50
51
52
53
54
55
56
57
58
59 require_once('include/SugarObjects/templates/person/Person.php');
60 // Contact is used to store customer information.
61 class Contact extends Person {
62     var $field_name_map;
63         // Stored fields
64         var $id;
65         var $name = '';
66         var $lead_source;
67         var $date_entered;
68         var $date_modified;
69         var $modified_user_id;
70         var $assigned_user_id;
71         var $created_by;
72         var $created_by_name;
73         var $modified_by_name;
74
75         var $description;
76         var $salutation;
77         var $first_name;
78         var $last_name;
79         var $title;
80         var $department;
81         var $birthdate;
82         var $reports_to_id;
83         var $do_not_call;
84         var $phone_home;
85         var $phone_mobile;
86         var $phone_work;
87         var $phone_other;
88         var $phone_fax;
89         var $email1;
90         var $email_and_name1;
91         var $email_and_name2;
92         var $email2;
93         var $assistant;
94         var $assistant_phone;
95         var $email_opt_out;
96         var $primary_address_street;
97         var $primary_address_city;
98         var $primary_address_state;
99         var $primary_address_postalcode;
100         var $primary_address_country;
101         var $alt_address_street;
102         var $alt_address_city;
103         var $alt_address_state;
104         var $alt_address_postalcode;
105         var $alt_address_country;
106         var $portal_name;
107         var $portal_app;
108         var $portal_active;
109         var $contacts_users_id;
110         // These are for related fields
111         var $bug_id;
112         var $account_name;
113         var $account_id;
114         var $report_to_name;
115         var $opportunity_role;
116         var $opportunity_rel_id;
117         var $opportunity_id;
118         var $case_role;
119         var $case_rel_id;
120         var $case_id;
121         var $task_id;
122         var $note_id;
123         var $meeting_id;
124         var $call_id;
125         var $email_id;
126         var $assigned_user_name;
127         var $accept_status;
128     var $accept_status_id;
129     var $accept_status_name;
130     var $alt_address_street_2;
131     var $alt_address_street_3;
132     var $opportunity_role_id;
133     var $portal_password;
134     var $primary_address_street_2;
135     var $primary_address_street_3;
136     var $campaign_id;
137     var $sync_contact;
138         var $full_name; // l10n localized name
139         var $invalid_email;
140         var $table_name = "contacts";
141         var $rel_account_table = "accounts_contacts";
142         //This is needed for upgrade.  This table definition moved to Opportunity module.
143         var $rel_opportunity_table = "opportunities_contacts";
144
145         var $object_name = "Contact";
146         var $module_dir = 'Contacts';
147         var $emailAddress;
148         var $new_schema = true;
149         var $importable = true;
150
151         // This is used to retrieve related fields from form posts.
152         var $additional_column_fields = Array('bug_id', 'assigned_user_name', 'account_name', 'account_id', 'opportunity_id', 'case_id', 'task_id', 'note_id', 'meeting_id', 'call_id', 'email_id'
153         );
154
155         var $relationship_fields = Array('account_id'=> 'accounts','bug_id' => 'bugs', 'call_id'=>'calls','case_id'=>'cases','email_id'=>'emails',
156                                                                 'meeting_id'=>'meetings','note_id'=>'notes','task_id'=>'tasks', 'opportunity_id'=>'opportunities', 'contacts_users_id' => 'user_sync'
157                                                                 );
158
159         function Contact() {
160                 parent::Person();
161         }
162
163
164
165
166         function add_list_count_joins(&$query, $where)
167         {
168                 // accounts.name
169                 if(stristr($where, "accounts.name"))
170                 {
171                         // add a join to the accounts table.
172                         $query .= "
173                     LEFT JOIN accounts_contacts
174                     ON contacts.id=accounts_contacts.contact_id
175                     LEFT JOIN accounts
176                     ON accounts_contacts.account_id=accounts.id
177                         ";
178                 }
179                 $custom_join = $this->custom_fields->getJOIN();
180                 if($custom_join){
181                                 $query .= $custom_join['join'];
182                 }
183
184
185         }
186
187         function listviewACLHelper(){
188                 $array_assign = parent::listviewACLHelper();
189                 $is_owner = false;
190                 //MFH BUG 18281; JChi #15255
191                 $is_owner = !empty($this->assigned_user_id) && $this->assigned_user_id == $GLOBALS['current_user']->id;
192                         if(!ACLController::moduleSupportsACL('Accounts') || ACLController::checkAccess('Accounts', 'view', $is_owner)){
193                                 $array_assign['ACCOUNT'] = 'a';
194                         }else{
195                                 $array_assign['ACCOUNT'] = 'span';
196
197                         }
198                 return $array_assign;
199         }
200
201         function create_new_list_query($order_by, $where,$filter=array(),$params=array(), $show_deleted = 0,$join_type='', $return_array = false,$parentbean=null, $singleSelect = false)
202         {
203                 //if this is from "contact address popup" action, then process popup list query
204                 if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'ContactAddressPopup'){
205                         return $this->address_popup_create_new_list_query($order_by, $where, $filter, $params, $show_deleted, $join_type, $return_array, $parentbean, $singleSelect);
206                         
207                 }else{
208                         //any other action goes to parent function in sugarbean
209                         if(strpos($order_by,'sync_contact') !== false){
210                                 //we have found that the user is ordering by the sync_contact field, it would be troublesome to sort by this field
211                                 //and perhaps a performance issue, so just remove it
212                                 $order_by = '';
213                         }
214                         return parent::create_new_list_query($order_by, $where, $filter, $params, $show_deleted, $join_type, $return_array, $parentbean, $singleSelect);
215                 }               
216
217
218         }
219
220
221
222         function address_popup_create_new_list_query($order_by, $where,$filter=array(),$params=array(), $show_deleted = 0,$join_type='', $return_array = false,$parentbean=null, $singleSelect = false)
223         {
224                 //if this is any action that is not the contact address popup, then go to parent function in sugarbean
225                 if(isset($_REQUEST['action']) && $_REQUEST['action'] !== 'ContactAddressPopup'){
226                         return parent::create_new_list_query($order_by, $where, $filter, $params, $show_deleted, $join_type, $return_array, $parentbean, $singleSelect);
227                 }
228
229                 $custom_join = $this->custom_fields->getJOIN();
230                 // MFH - BUG #14208 creates alias name for select
231                 $select_query = "SELECT ";
232                 $select_query .= db_concat($this->table_name,array('first_name','last_name')) . " name, ";
233                 $select_query .= "
234                                 $this->table_name.*,
235                 accounts.name as account_name,
236                 accounts.id as account_id,
237                 accounts.assigned_user_id account_id_owner,
238                 users.user_name as assigned_user_name ";
239                 if($custom_join){
240                                 $select_query .= $custom_join['select'];
241                 }
242                 $ret_array['select'] = $select_query;
243
244                 $from_query = "
245                 FROM contacts ";
246
247                 $from_query .=          "LEFT JOIN users
248                             ON contacts.assigned_user_id=users.id
249                             LEFT JOIN accounts_contacts
250                             ON contacts.id=accounts_contacts.contact_id  and accounts_contacts.deleted = 0
251                             LEFT JOIN accounts
252                             ON accounts_contacts.account_id=accounts.id AND accounts.deleted=0 ";
253                 $from_query .= "LEFT JOIN email_addr_bean_rel eabl  ON eabl.bean_id = contacts.id AND eabl.bean_module = 'Contacts' and eabl.primary_address = 1 and eabl.deleted=0 ";
254         $from_query .= "LEFT JOIN email_addresses ea ON (ea.id = eabl.email_address_id) ";
255                 if($custom_join){
256                                 $from_query .= $custom_join['join'];
257                 }
258                 $ret_array['from'] = $from_query;
259                 $ret_array['from_min'] = 'from contacts'; 
260
261                 $where_auto = '1=1';
262                 if($show_deleted == 0){
263                 $where_auto = " $this->table_name.deleted=0 ";
264                 //$where_auto .= " AND accounts.deleted=0  ";
265                 }else if($show_deleted == 1){
266                                 $where_auto = " $this->table_name.deleted=1 ";
267                 }
268
269
270                 if($where != ""){
271                         $where_query = "where ($where) AND ".$where_auto;
272                 }else{
273                         $where_query = "where ".$where_auto;
274                 }
275
276                         
277                 $ret_array['where'] = $where_query;
278                 $orderby_query = ''; 
279                 if(!empty($order_by)){
280                     $orderby_query =  " ORDER BY ". $this->process_order_by($order_by, null);
281                 }
282                 $ret_array['order_by'] = $orderby_query ;
283                 
284                 if($return_array)
285         {
286                 return $ret_array;
287         }               
288                 
289             return $ret_array['select'] . $ret_array['from'] . $ret_array['where']. $ret_array['order_by'];
290
291         }
292
293
294         
295         
296                 function create_export_query(&$order_by, &$where, $relate_link_join='')
297         {
298                 $custom_join = $this->custom_fields->getJOIN(true, true,$where);
299                         if($custom_join)
300                                 $custom_join['join'] .= $relate_link_join;
301                          $query = "SELECT
302                                 contacts.*,email_addresses.email_address email1,
303                                 accounts.name as account_name,
304                                 users.user_name as assigned_user_name ";
305                                                 if($custom_join){
306                                                         $query .= $custom_join['select'];
307                                                 }
308                                                  $query .= " FROM contacts ";
309                          $query .= "LEFT JOIN users
310                                         ON contacts.assigned_user_id=users.id ";
311                              $query .= "LEFT JOIN accounts_contacts
312                                         ON ( contacts.id=accounts_contacts.contact_id and (accounts_contacts.deleted is null or accounts_contacts.deleted = 0))
313                                         LEFT JOIN accounts
314                                         ON accounts_contacts.account_id=accounts.id ";
315                                                 
316                                                 //join email address table too.
317                                                 $query .=  ' LEFT JOIN  email_addr_bean_rel on contacts.id = email_addr_bean_rel.bean_id and email_addr_bean_rel.bean_module=\'Contacts\' and email_addr_bean_rel.deleted=0 and email_addr_bean_rel.primary_address=1 ';
318                                                 $query .=  ' LEFT JOIN email_addresses on email_addresses.id = email_addr_bean_rel.email_address_id ' ;
319                                                 
320                                                 if($custom_join){
321                                                         $query .= $custom_join['join'];
322                                                 }
323
324                 $where_auto = "( accounts.deleted IS NULL OR accounts.deleted=0 )
325                       AND contacts.deleted=0 ";
326
327                 if($where != "")
328                         $query .= "where ($where) AND ".$where_auto;
329                 else
330                         $query .= "where ".$where_auto;
331
332                 if(!empty($order_by))
333                         $query .=  " ORDER BY ". $this->process_order_by($order_by, null);
334
335                 return $query;
336         }
337
338         function fill_in_additional_list_fields() {     
339                 parent::fill_in_additional_list_fields();
340                 $this->_create_proper_name_field();
341                 // cn: bug 8586 - l10n names for Contacts in Email TO: field
342                 $this->email_and_name1 = "{$this->full_name} &lt;".$this->email1."&gt;";
343                 $this->email_and_name2 = "{$this->full_name} &lt;".$this->email2."&gt;";
344                 
345                 if($this->force_load_details == true) {
346                         $this->fill_in_additional_detail_fields();
347                 }
348         }
349
350         function fill_in_additional_detail_fields() {
351                 parent::fill_in_additional_detail_fields();
352                 global $locale, $app_list_strings, $current_user;
353                 
354
355                 // retrieve the account information and the information about the person the contact reports to.
356                 $query = "SELECT acc.id, acc.name, con_reports_to.first_name, con_reports_to.last_name
357                 from contacts
358                 left join accounts_contacts a_c on a_c.contact_id = '".$this->id."' and a_c.deleted=0
359                 left join accounts acc on a_c.account_id = acc.id and acc.deleted=0
360                 left join contacts con_reports_to on con_reports_to.id = contacts.reports_to_id
361                 where contacts.id = '".$this->id."'";
362
363                 $result = $this->db->query($query,true," Error filling in additional detail fields: ");
364
365                 // Get the id and the name.
366                 $row = $this->db->fetchByAssoc($result);
367
368                 if($row != null)
369                 {
370                         $this->account_name = $row['name'];
371                         $this->account_id = $row['id'];
372                         $this->report_to_name = $locale->getLocaleFormattedName($row['first_name'], $row['last_name'],'','','',null,true);
373                 }
374                 else
375                 {
376                         $this->account_name = '';
377                         $this->account_id = '';
378                         $this->report_to_name = '';
379                 }
380                 $this->load_contacts_users_relationship();
381                 /** concating this here because newly created Contacts do not have a
382                  * 'name' attribute constructed to pass onto related items, such as Tasks
383                  * Notes, etc.
384                  */
385                 $this->name = $locale->getLocaleFormattedName($this->first_name, $this->last_name);
386         if(!empty($this->contacts_users_id)) {
387                    $this->sync_contact = true;
388                 }
389
390                 if(!empty($this->portal_active) && $this->portal_active == 1) {
391                    $this->portal_active = true;
392                 }
393         // Set campaign name if there is a campaign id
394                 if( !empty($this->campaign_id)){
395                         
396                         $camp = new Campaign();
397                     $where = "campaigns.id='{$this->campaign_id}'";
398                     $campaign_list = $camp->get_full_list("campaigns.name", $where, true);
399                     $this->campaign_name = $campaign_list[0]->name;     
400                 }
401         }
402
403                 /**
404                 loads the contacts_users relationship to populate a checkbox
405                 where a user can select if they would like to sync a particular
406                 contact to Outlook
407         */
408         function load_contacts_users_relationship(){
409                 global $current_user;
410
411                 $this->load_relationship("user_sync");
412                 $query_array=$this->user_sync->getQuery(true);
413
414                 $query_array['where'] .= " AND users.id = '$current_user->id'";
415
416                 $query='';
417                 foreach ($query_array as $qstring) {
418                         $query.=' '.$qstring;
419                 }
420
421                 $list = $this->build_related_list($query, new User());
422                 if(!empty($list)){
423                         //this should only return one possible value so set it
424                         $this->contacts_users_id = $list[0]->id;
425                 }
426         }
427
428         function get_list_view_data($filter_fields = array()) {
429                 global $system_config;
430                 global $current_user;
431
432                 $this->_create_proper_name_field();
433                 $temp_array = $this->get_list_view_array();
434                 $temp_array['NAME'] = $this->name;
435                 $temp_array['ENCODED_NAME'] = $this->name;
436
437                 if(isset($system_config->settings['system_skypeout_on'])
438                         && $system_config->settings['system_skypeout_on'] == 1)
439                 {
440                         if(!empty($temp_array['PHONE_WORK'])
441                                 && skype_formatted($temp_array['PHONE_WORK']))
442                         {
443                                 $temp_array['PHONE_WORK'] = '<a href="callto://'
444                                         . $temp_array['PHONE_WORK']. '">'
445                                         . $temp_array['PHONE_WORK']. '</a>' ;
446                         }
447                 }
448                 if($filter_fields && !empty($filter_fields['sync_contact'])){
449                         $this->load_contacts_users_relationship();
450                         $temp_array['SYNC_CONTACT'] = !empty($this->contacts_users_id) ? 1 : 0;
451                 }
452                 $temp_array['EMAIL1'] = $this->emailAddress->getPrimaryAddress($this);
453                 $this->email1 = $temp_array['EMAIL1'];
454                 $temp_array['EMAIL1_LINK'] = $current_user->getEmailLink('email1', $this, '', '', 'ListView');
455                 $temp_array['EMAIL_AND_NAME1'] = "{$this->full_name} &lt;".$temp_array['EMAIL1']."&gt;";
456                 return $temp_array;
457         }
458
459         /**
460                 builds a generic search based on the query string using or
461                 do not include any $this-> because this is called on without having the class instantiated
462         */
463         function build_generic_where_clause ($the_query_string)
464         {
465                 $where_clauses = Array();
466                 $the_query_string = $this->db->quote($the_query_string);
467
468                 array_push($where_clauses, "contacts.last_name like '$the_query_string%'");
469                 array_push($where_clauses, "contacts.first_name like '$the_query_string%'");
470                 array_push($where_clauses, "accounts.name like '$the_query_string%'");
471                 array_push($where_clauses, "contacts.assistant like '$the_query_string%'");
472                 array_push($where_clauses, "ea.email_address like '$the_query_string%'");
473
474                 if (is_numeric($the_query_string))
475                 {
476                         array_push($where_clauses, "contacts.phone_home like '%$the_query_string%'");
477                         array_push($where_clauses, "contacts.phone_mobile like '%$the_query_string%'");
478                         array_push($where_clauses, "contacts.phone_work like '%$the_query_string%'");
479                         array_push($where_clauses, "contacts.phone_other like '%$the_query_string%'");
480                         array_push($where_clauses, "contacts.phone_fax like '%$the_query_string%'");
481                         array_push($where_clauses, "contacts.assistant_phone like '%$the_query_string%'");
482                 }
483
484                 $the_where = "";
485                 foreach($where_clauses as $clause)
486                 {
487                         if($the_where != "") $the_where .= " or ";
488                         $the_where .= $clause;
489                 }
490
491
492                 return $the_where;
493         }
494
495         function set_notification_body($xtpl, $contact)
496         {
497             global $locale;
498             
499                 $xtpl->assign("CONTACT_NAME", trim($locale->getLocaleFormattedName($contact->first_name, $contact->last_name)));
500                 $xtpl->assign("CONTACT_DESCRIPTION", $contact->description);
501
502                 return $xtpl;
503         }
504
505         function get_contact_id_by_email($email)
506         {
507                 $email = trim($email);
508                 if(empty($email)){
509                         //email is empty, no need to query, return null
510                         return null;
511                 }
512
513                 $where_clause = "(email1='$email' OR email2='$email') AND deleted=0";
514
515                 $query = "SELECT * FROM $this->table_name WHERE $where_clause";
516                 $GLOBALS['log']->debug("Retrieve $this->object_name: ".$query);
517                         //requireSingleResult has beeen deprecated.
518                 //$result = $this->db->requireSingleResult($query, true, "Retrieving record $where_clause:");
519                                 $result = $this->db->limitQuery($query,0,1,true, "Retrieving record $where_clause:");
520
521                 if( empty($result))
522                 {
523                         return null;
524                 }
525
526                 $row = $this->db->fetchByAssoc($result, -1, true);
527                 return $row['id'];
528
529         }
530
531         function save_relationship_changes($is_update) {
532
533                 //if account_id was replaced unlink the previous account_id.
534                 //this rel_fields_before_value is populated by sugarbean during the retrieve call.
535                 if (!empty($this->account_id) and !empty($this->rel_fields_before_value['account_id']) and
536                                 (trim($this->account_id) != trim($this->rel_fields_before_value['account_id']))) {
537                                 //unlink the old record.
538                                 $this->load_relationship('accounts');
539                                 $this->accounts->delete($this->id,$this->rel_fields_before_value['account_id']);
540                 }
541                 parent::save_relationship_changes($is_update);
542         }
543
544         function bean_implements($interface){
545                 switch($interface){
546                         case 'ACL':return true;
547                 }
548                 return false;
549         }
550         function get_unlinked_email_query($type=array()) {
551                 
552                 return get_unlinked_email_query($type, $this);
553         }
554         
555     /**
556      * used by import to add a list of users
557      *
558      * Parameter can be one of the following:
559      * - string 'all': add this contact for all users
560      * - comma deliminated lists of teams and/or users
561      *
562      * @param string $list_of_user
563      */
564     
565     function process_sync_to_outlook(
566         $list_of_users
567         ) 
568     {
569         static $focus_user;
570         
571         // cache this object since we'll be reusing it a bunch
572         if ( !($focus_user instanceof User) ) {
573             
574             $focus_user = new User();
575         }
576         
577         
578                 if ( empty($list_of_users) ) {
579             return;
580                 }
581         if ( !isset($this->users) ) {
582             $this->load_relationship('user_sync');
583         }
584                 
585                 if ( strtolower($list_of_users) == 'all' ) {
586             // add all non-deleted users
587                         $sql = "SELECT id FROM users WHERE deleted=0 AND is_group=0 AND portal_only=0";
588                         $result=$this->db->query($sql);
589                         while ( $hash = $this->db->fetchByAssoc($result) ) {
590                 $this->user_sync->add($hash['id']);
591                         }
592                 } 
593         else {
594             $theList = explode(",",$list_of_users);
595             foreach ($theList as $eachItem) {
596                 if ( $focus_user->retrieve_user_id($eachItem)
597                         || $focus_user->retrieve($eachItem)) {
598                     // it is a user, add user
599                     $this->user_sync->add($this->id);
600                     return;
601                 }
602                         }
603                 }
604         }
605
606 }
607
608
609
610 ?>