PageRenderTime 148ms CodeModel.GetById 61ms app.highlight 42ms RepoModel.GetById 38ms app.codeStats 1ms

/application/models/contacts/Contact.class.php

https://github.com/fb83/Project-Pier
PHP | 843 lines | 334 code | 93 blank | 416 comment | 58 complexity | 0ca5622914bcd61d59b375bd805f1cce MD5 | raw file
  1<?php
  2
  3  /**
  4  * Contact class
  5  *
  6  * @http://www.projectpier.org/
  7  */
  8  class Contact extends BaseContact {
  9    
 10    /**
 11    * Cached associated user
 12    *
 13    * @var User
 14    */
 15    private $user = null;
 16    
 17    /**
 18    * True if user is member of owner company. This value is read on first request and cached
 19    *
 20    * @var boolean
 21    */
 22    private $is_member_of_owner_company = null;
 23    
 24    /**
 25    * Cached is_administrator value. First time value is requested it will be checked and cached. 
 26    * After that every request will return cached value
 27    *
 28    * @var boolean
 29    */
 30    private $is_administrator = null;
 31    
 32    /**
 33    * Cached is_account_owner value. Value is retrieved on first requests
 34    *
 35    * @var boolean
 36    */
 37    private $is_account_owner = null;
 38    
 39    /**
 40    * If true this object will not throw object not taggable exception and will make tag methods available
 41    *
 42    * @var boolean
 43    */
 44    protected $is_taggable = true;
 45    
 46    /**
 47    * Check if this contact is member of specific company
 48    *
 49    * @access public
 50    * @param Company $company
 51    * @return boolean
 52    */
 53    function isMemberOf(Company $company) {
 54      return $this->getCompanyId() == $company->getId();
 55    } // isMemberOf
 56    
 57    /**
 58    * Usually we check if user is member of owner company so this is the shortcut method
 59    *
 60    * @param void
 61    * @return boolean
 62    */
 63    function isMemberOfOwnerCompany() {
 64      if (is_null($this->is_member_of_owner_company)) {
 65        $this->is_member_of_owner_company = $this->isMemberOf(owner_company());
 66      }
 67      return $this->is_member_of_owner_company;
 68    } // isMemberOfOwnerCompany
 69    
 70    /**
 71    * Check if this user is part of specific project
 72    *
 73    * @param Project $project
 74    * @return boolean
 75    */
 76    function isProjectUser(Project $project) {
 77      if (!isset($this->is_project_user_cache[$project->getId()])) {
 78        $project_user = ProjectUsers::findById(array(
 79          'project_id' => $project->getId(), 
 80          'user_id' => $this->getId())
 81        ); // findById
 82        $this->is_project_user_cache[$project->getId()] = $project_user instanceof ProjectUser;
 83      } // if
 84      return $this->is_project_user_cache[$project->getId()];
 85    } // isProjectUser
 86    
 87    /**
 88    * Check if this of specific company website. If must be member of that company and is_admin flag set to true
 89    *
 90    * @param void
 91    * @return boolean
 92    */
 93    function isAdministrator() {
 94      if ($this->getUserAccount()) {
 95        return $this->getUserAccount()->isAdministrator();
 96      }
 97      return false;
 98    } // isAdministrator
 99    
100    /**
101    * Account owner is user account that was created when company website is created
102    *
103    * @param void
104    * @return boolean
105    */
106    function isAccountOwner() {
107      if ($this->getUserAccount()) {
108        return $this->getUserAccount()->isAccountOwner();
109      }
110      return false;
111    } // isAccountOwner
112    
113    /**
114    * Returns if contact is a favorite
115    *
116    * @param void
117    * @return boolean
118    */
119    function isFavorite() {
120      return $this->getIsFavorite();
121    } // isFavorite
122
123    /**
124    * Returns true. Functions to accommodate tags on Contacts
125    *
126    * @param void
127    * @return boolean
128    */
129    function isPrivate() {
130      return false;
131    } // isPrivate
132    
133
134        
135    // ---------------------------------------------------
136    //  Retrieve
137    // ---------------------------------------------------
138    
139    /**
140    * Return owner company
141    *
142    * @access public
143    * @param void
144    * @return Company
145    */
146    function getCompany() {
147      $company = Companies::findById($this->getCompanyId());
148      if ($company) return $company;
149      return new Company();
150    } // getCompany
151    
152    /**
153    * Return associated user account
154    * 
155    * @param void
156    * @return User
157    */
158    function getUserAccount() {
159      if (is_null($this->user)) {
160        $this->user = Users::findById($this->getUserId());
161      } // if
162      return $this->user;
163    } // getUser
164
165    /**
166    * True if contact has an associated user account
167    *
168    * @param void
169    * @return boolean
170    */
171    function hasUserAccount() {
172      return ($this->getUserAccount() ? true : false);
173    } // hasUserAccount
174
175    /**
176    * Return display name for this account. If there is no display name associated username will be used
177    *
178    * @access public
179    * @param void
180    * @return string
181    */
182    function getDisplayName() {
183      $display = parent::getDisplayName();
184      return trim($display) == '' ? $this->getUserAccount()->getUsername() : $display;
185    } // getDisplayName
186    
187    /**
188    * Returns true if we have title value set
189    *
190    * @access public
191    * @param void
192    * @return boolean
193    */
194    function hasTitle() {
195      return trim($this->getTitle()) <> '';
196    } // hasTitle
197    
198    // ---------------------------------------------------
199    //  IMs
200    // ---------------------------------------------------
201    
202    /**
203    * Return true if this contact have at least one IM address
204    *
205    * @access public
206    * @param void
207    * @return boolean
208    */
209    function hasImValue() {
210      return ContactImValues::count('`contact_id` = ' . DB::escape($this->getId()));
211    } // hasImValue
212    
213    /**
214    * Return all IM values
215    *
216    * @access public
217    * @param void
218    * @return array
219    */
220    function getImValues() {
221      return ContactImValues::getByContact($this);
222    } // getImValues
223    
224    /**
225    * Return value of specific IM. This function will return null if IM is not found
226    *
227    * @access public
228    * @param ImType $im_type
229    * @return string
230    */
231    function getImValue(ImType $im_type) {
232      $im_value = ContactImValues::findById(array('contact_id' => $this->getId(), 'im_type_id' => $im_type->getId()));
233      return $im_value instanceof ContactImValue && (trim($im_value->getValue()) <> '') ? $im_value->getValue() : null;
234    } // getImValue
235    
236    /**
237    * Return default IM value. If value was not found NULL is returned
238    *
239    * @access public
240    * @param void
241    * @return string
242    */
243    function getDefaultImValue() {
244      $default_im_type = $this->getDefaultImType();
245      return $this->getImValue($default_im_type);
246    } // getDefaultImValue
247    
248    /**
249    * Return default contact IM type. If there is no default contact IM type NULL is returned
250    *
251    * @access public
252    * @param void
253    * @return ImType
254    */
255    function getDefaultImType() {
256      return ContactImValues::getDefaultContactImType($this);
257    } // getDefaultImType
258    
259    /**
260    * Clear all IM values
261    *
262    * @access public
263    * @param void
264    * @return boolean
265    */
266    function clearImValues() {
267      return ContactImValues::instance()->clearByContact($this);
268    } // clearImValues
269    
270    // ---------------------------------------------------
271    //  Avatars
272    // ---------------------------------------------------
273    
274    /**
275    * Set contact avatar from $source file
276    *
277    * @param string $source Source file
278    * @param integer $max_width Max avatar width
279    * @param integer $max_height Max avatar height
280    * @param boolean $save Save contact object when done
281    * @return string
282    */
283    function setAvatar($source, $max_width = 50, $max_height = 50, $save = true) {
284      if (!is_readable($source)) {
285        return false;
286      }
287      
288      do {
289        $temp_file = ROOT . '/cache/' . sha1(uniqid(rand(), true));
290      } while (is_file($temp_file));
291      
292      try {
293        Env::useLibrary('simplegd');
294        
295        $image = new SimpleGdImage($source);
296        $thumb = $image->scale($max_width, $max_height, SimpleGdImage::BOUNDARY_DECREASE_ONLY, false);
297        $thumb->saveAs($temp_file, IMAGETYPE_PNG);
298        
299        $public_filename = PublicFiles::addFile($temp_file, 'png');
300        if ($public_filename) {
301          $this->setAvatarFile($public_filename);
302          if ($save) {
303            $this->save();
304          } // if
305        } // if
306        
307        $result = true;
308      } catch (Exception $e) {
309        $result = false;
310      } // try
311      
312      // Cleanup
313      if (!$result && $public_filename) {
314        PublicFiles::deleteFile($public_filename);
315      } // if
316      @unlink($temp_file);
317      
318      return $result;
319    } // setAvatar
320    
321    /**
322    * Delete avatar
323    *
324    * @param void
325    * @return null
326    */
327    function deleteAvatar() {
328      if ($this->hasAvatar()) {
329        PublicFiles::deleteFile($this->getAvatarFile());
330        $this->setAvatarFile('');
331      } // if
332    } // deleteAvatar
333    
334    /**
335    * Return path to the avatar file. This function just generates the path, does not check if file really exists
336    *
337    * @access public
338    * @param void
339    * @return string
340    */
341    function getAvatarPath() {
342      return PublicFiles::getFilePath($this->getAvatarFile());
343    } // getAvatarPath
344    
345    /**
346    * Return URL of avatar
347    *
348    * @access public
349    * @param void
350    * @return string
351    */
352    function getAvatarUrl() {
353      if ($this->getUseGravatar()) return 'http://www.gravatar.com/avatar/' . md5( strtolower( trim( $this->getEmail() ))) . '?s=50'; 
354      return $this->hasAvatar() ? PublicFiles::getFileUrl($this->getAvatarFile()) : get_image_url('avatar.gif');
355    } // getAvatarUrl
356    
357    /**
358    * Check if this contact has uploaded an avatar
359    *
360    * @access public
361    * @param void
362    * @return boolean
363    */
364    function hasAvatar() {
365      return (trim($this->getAvatarFile()) <> '') && is_file($this->getAvatarPath());
366    } // hasAvatar
367        
368    // ---------------------------------------------------
369    //  Permissions
370    // ---------------------------------------------------
371    
372    /**
373    * Can specific user add contact to specific company
374    *
375    * @access public
376    * @param User $user
377    * @param Company $to Can user add user to this company
378    * @return boolean
379    */
380    function canAdd(User $user, Company $to = null) {
381      if ($user->isAccountOwner()) {
382        return true;
383      } // if
384      return $user->isAdministrator();
385    } // canAdd
386    
387    /**
388    * Check if specific user can update this contact
389    *
390    * @access public
391    * @param User $user
392    * @return boolean
393    */
394    function canEdit(User $user) {
395      if ($this->hasUserAccount() && $user->getId() == $this->getUserId()) {
396        return true; // own profile
397      } // if
398      if ($user->isAccountOwner()) {
399        return true;
400      } // if
401      return $user->isAdministrator();
402    } // canEdit
403    
404    /**
405    * Check if specific user can delete specific contact
406    *
407    * @param User $user
408    * @return boolean
409    */
410    function canDelete(User $user) {
411      if ($this->isAccountOwner()) {
412        return false; // can't delete accountowner
413      } // if
414      
415      if ($this->getId() == $user->getId()) {
416        return false; // can't delete self
417      } // if
418      
419      return $user->isAdministrator();
420    } // canDelete
421    
422    /**
423    * Returns if this user can add a user account to that contact
424    *
425    * @param User $user
426    * @return boolean
427    */
428    function canAddUserAccount(User $user) {
429      if ($user->isAccountOwner()) {
430        return true; // account owner can manage users
431      } // if
432      
433      return $user->isAdministrator();
434    } // canAddUserAccount
435    
436    /**
437    * Returns if this user can edit the user account linked to that contact
438    *
439    * @param User $user
440    * @return boolean
441    */
442    function canEditUserAccount(User $user) {
443      if ($user->isAccountOwner()) {
444        return true;
445      } // if
446      
447      if ($this->getUserId() == $user->getId()) {
448        return true;
449      } // can edit your own user account
450      
451      return $user->isAdministrator();
452    } // canEditUserAccount
453
454    /**
455    * Returns if this user can delete the user account linked to that contact
456    *
457    * @param User $user
458    * @return boolean
459    */
460    function canDeleteUserAccount(User $user) {
461      if ($this->isAccountOwner()) {
462        return false; // can't delete accountowner
463      } // if
464      
465      if ($this->getUserId() == $user->getId()) {
466        return false;
467      } // can not delete your own user account
468      
469      return $user->isAdministrator();
470    } // canEditUserAccount
471    
472    /**
473    * Check if specific user can update this profile
474    *
475    * @param User $user
476    * @return boolean
477    */
478    function canUpdateProfile(User $user) {
479      if ($this->hasUserAccount() && $this->getUserId() == $user->getId()) {
480        return true;
481      } // if
482      if ($user->isAdministrator()) {
483        return true;
484      } // if
485      return false;
486    } // canUpdateProfile
487
488    // ---------------------------------------------------
489    //  URLs
490    // ---------------------------------------------------
491    
492    // /**
493    // * Return view account URL of this user
494    // *
495    // * @access public
496    // * @param void
497    // * @return string
498    // */
499    // function getAccountUrl() {
500    //   return get_url('account', 'index');
501    // } // getAccountUrl
502    
503    /**
504    * Show contact card page
505    *
506    * @access public
507    * @param void
508    * @return null
509    */
510    function getCardUrl() {
511      return get_url('contacts', 'card', $this->getId());
512    } // getCardUrl
513    
514    /**
515    * Return edit contact URL
516    *
517    * @access public
518    * @param string $redirect_to URL where we need to redirect user when he updates contact
519    * @return string
520    */
521    function getEditUrl($redirect_to = null) {
522      $attributes = array('id' => $this->getId());
523      if (trim($redirect_to) <> '') {
524        $attributes['redirect_to'] = str_replace('&amp;', '&', trim($redirect_to));
525      } // if
526
527      return get_url('contacts', 'edit', $attributes);
528    } // getEditUrl
529
530    /**
531    * Return edit contact URL
532    *
533    * @access public
534    * @param string $redirect_to URL where we need to redirect user when he updates contact avatar
535    * @return string
536    */
537    function getUpdateAvatarUrl($redirect_to = null) {
538      $attributes = array('id' => $this->getId());
539      if (trim($redirect_to) <> '') {
540        $attributes['redirect_to'] = str_replace('&amp;', '&', trim($redirect_to));
541      } // if
542
543      return get_url('contacts', 'edit_avatar', $attributes);
544    } // getEditUrl
545    
546    /**
547    * Return delete contact URL
548    *
549    * @access public
550    * @param void
551    * @return string
552    */
553    function getDeleteUrl() {
554      return get_url('contacts', 'delete', $this->getId());
555    } // getDeleteUrl
556    
557    /**
558    * Returns URL to attach a User account to that contact
559    *
560    * @param void
561    * @return string
562    */
563    function getAddUserAccountUrl() {
564      return get_url('contacts', 'add_user_account', $this->getId());
565    } // getAddUserUrl
566    
567    /**
568    * Returns URL to edit User account linked to that contact
569    *
570    * @param void
571    * @return string
572    */
573    function getEditUserAccountUrl() {
574      return get_url('contacts', 'edit_user_account', $this->getId());
575    } // getEditUserAccountUrl
576    
577    /**
578    * Returns URL to delete User account linked to that contact
579    *
580    * @param void
581    * @return string
582    */
583    function getDeleteUserAccountUrl() {
584      return get_url('contacts', 'delete_user_account', $this->getId());
585    } // getDeleteUserAccountUrl
586
587    /**
588    * Return toggle favorite URL
589    *
590    * @param void
591    * @return string
592    */
593    function getToggleFavoriteUrl($redirect_to = null) {
594      $attributes = array('id' => $this->getId());
595      if (trim($redirect_to) <> '') {
596        $attributes['redirect_to'] = str_replace('&amp;', '&', trim($redirect_to));
597      } // if
598      
599      return get_url('contacts', 'toggle_favorite', $attributes);
600    } // getToggleFavoriteUrl
601
602    /**
603    * Reserve parking space URL
604    *
605    * @access public
606    * @param void
607    * @return null
608    */
609    function getReserveParkingSpaceUrl() {
610      $url = trim(config_option('parking space reservation url', ''));
611      if ($url != '') {
612        $url .= '?license_plate=' . $this->getLicensePlate();
613      }
614      return $url;
615    } // getReserveParkingSpaceUrl
616
617    /**
618    * Show map page
619    *
620    * @access public
621    * @param void
622    * @return null
623    */
624    function getShowMapUrl() {
625      $location = urlencode($this->getLocationDetails());
626      $map_url = config_option('map url', 'http://maps.google.com?q=$location');
627      $map_url = str_replace('$location', $location, $map_url);
628      return $map_url;
629    } // getShowMapUrl
630
631    /**
632    * Show route page
633    *
634    * @access public
635    * @param void
636    * @return null
637    */
638    function getShowRouteUrl($contact) {
639      $to = '';
640      if ($contact instanceof Contact) {
641        $to = urlencode($contact->getLocationDetails());
642      }
643      $route_url = config_option('route url', 'http://maps.google.com?saddr=$from&daddr=$to');
644      $route_url = str_replace('$to', $to, $route_url);
645      $from = urlencode($this->getLocationDetails());
646      $route_url = str_replace('$from', $from, $route_url);
647      return $route_url;
648    } // getShowRouteUrl
649    
650    // ---------------------------------------------------
651    //  Tags
652    // ---------------------------------------------------
653    
654    /**
655    * Returns true if this project is taggable
656    *
657    * @param void
658    * @return boolean
659    */
660    function isTaggable() {
661      return $this->is_taggable;
662    } // isTaggable
663    
664    /**
665    * Return tags for this object
666    *
667    * @param void
668    * @return array
669    */
670    function getTags() {
671      if (plugin_active('tags')) {
672        if (!$this->isTaggable()) {
673          throw new Error('Object not taggable');
674        }
675        return Tags::getTagsByObject($this, get_class($this->manager()));
676      }
677      return array();
678    } // getTags
679    
680    /**
681    * Return tag names for this object
682    *
683    * @access public
684    * @param void
685    * @return array
686    */
687    function getTagNames() {
688      if (plugin_active('tags')) {
689        if (!$this->isTaggable()) {
690          throw new Error('Object not taggable');
691        } // if
692        return Tags::getTagNamesByObject($this, get_class($this->manager()));
693      }
694      return array();
695    } // getTagNames
696    
697    /**
698    * Explode input string and set array of tags
699    *
700    * @param string $input
701    * @return boolean
702    */
703    function setTagsFromCSV($input) {
704      $tag_names = array();
705      if (trim($input)) {
706        $tag_names = explode(',', $input);
707        foreach ($tag_names as $k => $v) {
708          if (trim($v) <> '') {
709            $tag_names[$k] = trim($v);
710          } // if
711        } // foreach
712      } // if
713      return $this->setTags($tag_names);
714    } // setTagsFromCSV
715    
716    /**
717    * Set object tags. This function accepts tags as params
718    *
719    * @access public
720    * @param void
721    * @return boolean
722    */
723    function setTags() {
724      if (plugin_active('tags')) {
725        if (!$this->isTaggable()) {
726          throw new Error('Object not taggable');
727        }
728        $args = array_flat(func_get_args());
729        return Tags::setObjectTags($args, $this, get_class($this->manager()), null);
730      }
731      return array();
732    } // setTags
733    
734    /**
735    * Clear object tags
736    *
737    * @access public
738    * @param void
739    * @return boolean
740    */
741    function clearTags() {
742      if (plugin_active('tags')) {
743        if (!$this->isTaggable()) {
744          throw new Error('Object not taggable');
745        }
746        return Tags::clearObjectTags($this, get_class($this->manager()));
747      }
748      return array();
749    } // clearTags
750    
751    // ---------------------------------------------------
752    //  System functions
753    // ---------------------------------------------------
754    
755    /**
756    * Validate data before save
757    *
758    * @access public
759    * @param array $errors
760    * @return void
761    */
762    function validate(&$errors) {
763      
764      // Validate display_name if present
765      if (!$this->validatePresenceOf('display_name')) {
766        $errors[] = lang('name value required');
767      } // if
768      
769      // Company ID
770      if (!$this->validatePresenceOf('company_id')) {
771        $errors[] = lang('company value required');
772      }
773    } // validate
774    
775    /**
776    * Delete this object
777    *
778    * @param void
779    * @return boolean
780    */
781    function delete() {
782      if ($this->isAccountOwner()) {
783        return false;
784      } // if
785
786      if ($this->isTaggable()) {
787        $this->clearTags();
788      } // if
789      
790      // TODO check all things that need to be deleted
791      // ticket subscriptions
792      // message subscriptions
793      // project-user association
794
795      $this->deleteAvatar();
796      $this->clearImValues();
797      if ($this->hasUserAccount()) {
798        ProjectUsers::clearByUser($this->getUserAccount());
799        MessageSubscriptions::clearByUser($this->getUserAccount());
800        $this->getUserAccount()->delete();
801      } // if
802      return parent::delete();
803    } // delete
804    
805    // ---------------------------------------------------
806    //  ApplicationDataObject implementation
807    // ---------------------------------------------------
808    
809    /**
810    * Return object name
811    *
812    * @access public
813    * @param void
814    * @return string
815    */
816    function getObjectName() {
817      return $this->getDisplayName();
818    } // getObjectName
819    
820    /**
821    * Return object type name
822    *
823    * @param void
824    * @return string
825    */
826    function getObjectTypeName() {
827      return lang('contact');
828    } // getObjectTypeName
829    
830    /**
831    * Return object URl
832    *
833    * @access public
834    * @param void
835    * @return string
836    */
837    function getObjectUrl() {
838      return $this->getCardUrl();
839    } // getObjectUrl
840  
841  } // Contact 
842
843?>