· 7 years ago · Jan 31, 2019, 09:36 AM
1<?php
2 require_once APPLICATION_PATH.'/../../../library/Nocowboys/Images/Trait/RotateImage.php';
3 use \Elastica\Document as ElasticDocument;
4
5 /**
6 * Represents a single business object
7 */
8 class Model_DbTableRow_Business extends Nocowboys_Db_Table_Row_Abstract
9 {
10 use Nocowboys_Rotate_Image_EXIF;
11
12 public $categories = NULL;
13 public $areas = NULL;
14 public $locationArea = NULL;
15 public $postalLocationArea = NULL;
16 public $headOfficeBusinesses = NULL;
17 public $headOfficeBusinessIDs = NULL;
18 public $headOffices = NULL;
19 public $headOfficeRatings = NULL;
20 public $headOfficeJobsInterestedIn = NULL;
21 public $colour = NULL;
22 public $images = NULL;
23 public $userType = 'business';
24 protected $_mapHidden = NULL;
25 protected $_accessibleFields = [
26 'AboutUs', 'AccountType', 'ContactPhone1', 'ContactPhone2', 'Facebook', 'Twitter', 'Instagram', 'Youtube', 'Linkedin',
27 'EmailAddress', 'Fax', 'LocationAreaID', 'MapOption',
28 'URLName', 'Username', 'Website', 'WhatWeDo', 'DontCallAgain', 'IsSendText',
29 'Mobile', 'MobilePrefix', 'MobileNumber', 'Phone1Prefix', 'Phone1Number',
30 'Phone2Prefix', 'Phone2Number', 'AddressStreetNumber', 'AddressUnitNumber',
31 'AddressStreetName', 'addressPostcode', 'hideAddress', 'SuburbID',
32 'Suburb', 'businessSuburbId', 'PostalStreetNumber', 'PostalUnitNumber',
33 'PostalStreetName', 'PostalSuburbID', 'postalPostcode', 'hidePostalAddress',
34 'TradeMeMemberID', 'Notes', 'Name', 'lastName', 'ExpiryDate', 'Mobile',
35 'Availability', 'primaryCategoryId', 'salesStatus', 'SalesEmail'
36 ];
37 protected $_metaKeyMeta = NULL;
38
39 const DEFAULT_DATE = '1970-01-01 00:00:00';
40 const SESSION_NAMESPACE_NEW_BUSINESS = 'new_business';
41 const METAKEYAUTOMATEDEMAILSACTIVE = 'automatedEmailsActive';
42 const METAKEYAUTOMATEDEMAILSCONTENT = 'automatedEmailsContent';
43 const METAKEYAUTOMATEDEMAILSSUBJECT = 'automatedEmailsSubject';
44 const METAKEYAUTOMATEDEMAILSCUTOFF = 'automatedEmailsCutoff';
45 const METAKEYPOSITIVERATINGCUTOFF = 'ratingsPositiveCutoff';
46 const METAKEYNEGATIVERATINGCUTOFF = 'ratingsNegativeCutoff';
47 const METAKEYRATINGNOTIFICATIONLEVEL = 'ratingNotificationLevel';
48 const METAKEYJOBAREAS = 'jobAreas';
49 const METAKEYJOBCATEGORIES = 'jobCategories';
50 const METAKEYVIDEO = 'video';
51 const METAKEYHIDEMAP = 'hideMap';
52 const METAKEYMETA = 'meta';
53 const META_KEY_SOCIAL_LINK_FACEBOOK = 'facebook';
54 const META_KEY_SOCIAL_LINK_TWITTER = 'twitter';
55 const META_KEY_SOCIAL_LINK_INSTAGRAM = 'instagram';
56 const META_KEY_SOCIAL_LINK_YOUTUBE = 'youtube';
57 const META_KEY_SOCIAL_LINK_LINKEDIN = 'linkedin'; // it seems not used in any meta keys so changed and by changing to - meta value not assigning to meta key.
58 const META_KEY_SOCIAL_LINK_GOOGLEPLUS = 'googleplus';
59 const META_KEY_SOCIAL_LINK_TRADEME = 'trademe';
60 const CACHE_KEY_PREFIX_AREAS = 'business_areas_';
61 const CACHE_KEY_PREFIX_CATEGORIES = 'business_categories_';
62 const CACHE_KEY_BADGES = 'business_badges_';
63 const BADGE_REGISTERED = 'registered';
64 const BADGE_CUSTOMER_PREFERRED = 'customer_preferred';
65 const BADGE_BRONZE_BUSINESS = 'bronze_business';
66 const BADGE_SILVER_BUSINESS = 'silver_business';
67 const BADGE_GOLD_BUSINESS = 'gold_business';
68 const BADGE_PLATINUM_BUSINESS = 'platinum_business';
69 const BADGE_DEFENDER = 'defender';
70 const BADGE_APPRECIATOR = 'appreciator';
71 const BADGE_SOCAL_STAR = 'social_star';
72 const BADGE_BARON = 'baron';
73 const BADGE_DUKE = 'duke';
74 const BADGE_COLLECTOR = 'collector';
75 const BADGE_HOARDER = 'hoarder';
76 const BADGE_SKEPTIC = 'skeptic';
77 const BADGE_REGISTERED_NZ_COMPANY = 'registered_nz_company';
78 const HIDE_FROM_SEARCH_ENGINES = 1;
79 const HIDE_BUSINESS_INFORMATION = 1;
80 const AVAILABILITY_JOBS_ON = 1;
81 const AVAILABILITY_JOBS_OFF = 0;
82 const FACEBOOK_LEAD_TYPE_1 = 1;
83 const FACEBOOK_LEAD_TYPE_2 = 2;
84 const FACEBOOK_LEAD_TYPE_3 = 3;
85 const FACEBOOK_LEAD_TYPE_4 = 4;
86 const FACEBOOK_LEAD_TYPE_5 = 5;
87 const FACEBOOK_LEAD_TYPE_6 = 6;
88 const AVAILABLE_FOR_RECENT_RATING = 1;
89
90 public static $badges = [
91 self::BADGE_REGISTERED => [
92 'title' => 'Registered',
93 'description' => 'serious about their reputation on NC'
94 ],
95 self::BADGE_CUSTOMER_PREFERRED => [
96 'title' => 'Customer preferred',
97 'description' => 'well liked in the NC community'
98 ],
99 self::BADGE_BRONZE_BUSINESS => [
100 'title' => 'Bronze business',
101 'description' => 'over 50 positive ratings'
102 ],
103 self::BADGE_SILVER_BUSINESS => [
104 'title' => 'Silver business',
105 'description' => 'over 100 positive ratings'
106 ],
107 self::BADGE_GOLD_BUSINESS => [
108 'title' => 'Gold business',
109 'description' => 'over 500 positive ratings'
110 ],
111 self::BADGE_PLATINUM_BUSINESS => [
112 'title' => 'Platinum business',
113 'description' => 'over 1,000 positive ratings'
114 ],
115 self::BADGE_DEFENDER => [
116 'title' => 'Defender',
117 'description' => 'has responded to over 50% of their negative reviews'
118 ],
119 self::BADGE_APPRECIATOR => [
120 'title' => 'Appreciator',
121 'description' => 'Has responded to over 50% of their positive reviews'
122 ],
123 self::BADGE_SOCAL_STAR => [
124 'title' => 'Social star',
125 'description' => 'has at least five Facebook Likes or Google +1s'
126 ],
127 self::BADGE_BARON => [
128 'title' => 'NoCowboys Baron',
129 'description' => 'in the top 50 businesses on NoCowboys'
130 ],
131 self::BADGE_DUKE => [
132 'title' => 'NoCowboys Duke',
133 'description' => 'in the top 10 businesses on NoCowboys'
134 ],
135 self::BADGE_COLLECTOR => [
136 'title' => 'Rating collector',
137 'description' => 'has won NoCowboy\'s Business of the Month award'
138 ],
139 self::BADGE_HOARDER => [
140 'title' => 'Rating hoarder',
141 'description' => 'has won NoCowboy\'s Business of the Year award'
142 ],
143 self::BADGE_SKEPTIC => [
144 'title' => 'Skeptic business',
145 'description' => 'Challenged at least five negative reviews'
146 ],
147 self::BADGE_REGISTERED_NZ_COMPANY => [
148 'title' => 'Registered NZ company',
149 'description' => 'Registered with the NZ Companies Office',
150 'size' => 'double'
151 ]
152 ];
153
154 const REGISTRATION_GRACE_PERIOD_DAYS = 5;
155
156 /**
157 * @var array utm-params
158 */
159 public static $utmParams = [
160 'utm_source' => 'nocowboys-site',
161 'utm_medium' => 'business-profile',
162 'utm_campaign' => 'website'
163 ];
164
165 /**
166 * Gets utm query string.
167 *
168 * @return string
169 *
170 */
171 static public function getUtmQueryString()
172 {
173 return http_build_query(self::$utmParams);
174 }
175
176 /**
177 * Loads the ratings for this business
178 * @param boolean $getCached Set to false to get non-cached ratings
179 * @param boolean $getHidden Set to true to get hidden ratings
180 * @return Zend_Db_Table_Rowset_Abstract
181 */
182 public function getRatings($getCached = true, $getHidden = false)
183 {
184 $ratingTable = new Model_DbTable_Rating();
185 $select = $ratingTable->select()
186 ->where('businessID = ?', $this->ID)
187 ->where('Locked = 0')
188 ->where('need_approve = 0')
189 ->where('ISNULL(deleted)')
190 ->order('RankDate DESC');
191
192 if (!$getHidden)
193 {
194 $select->where('Rating.Hidden = 0');
195 }
196 else
197 {
198 // Hide the ratings that are hidden and aren't querying authenticity
199 // as they're hidden by us
200 $select->where('(Rating.Hidden = 0 OR (Rating.Hidden = 1 AND Rating.IsQueryAuthenticity = 1)) AND NOT (Rating.need_approve = ?)', Model_DbTable_Rating::RATING_STATUS_BLOCKED);
201 }
202
203 if ($getCached)
204 {
205 return $ratingTable->fetchAllCache($select);
206 }
207 else
208 {
209 return $ratingTable->fetchAll($select);
210 }
211 }
212
213 /**
214 * Gets all the replies for ratings for this business
215 * @return Zend_Db_Table_Rowset_Abstract
216 */
217 public function getRatingReplies()
218 {
219 $replyModel = new Model_DbTable_RatingReply();
220 $replySelect = $replyModel->select()
221 ->setIntegrityCheck(false)
222 ->from('RatingReply')
223 ->joinInner('Rating', 'RatingReply.RatingID = Rating.ID')
224 ->order('ReplyDate DESC');
225
226 if ($this->isHeadOffice())
227 {
228 $businessIds = $this->getHeadOfficeBusinessIDs();
229 $replySelect->where('Rating.BusinessID IN ('.implode(',', $businessIds).')');
230 }
231 else
232 {
233 $replySelect->where('Rating.BusinessID = '.$this->ID);
234 }
235
236 return $replyModel->fetchAll($replySelect);
237 }
238
239 /**
240 * Loads the authenticated ratings for this business
241 * @return Zend_Db_Table_Rowset_Abstract
242 */
243 public function getAuthenticatedRatings($getCached = true, $getComments = false, $fromDate = NULL, $toDate = NULL)
244 {
245 $ratingTable = new Model_DbTable_Rating();
246 $select = $ratingTable->select()
247 ->where('businessID = ?', $this->ID)
248 ->where('Rating.Locked <> 1')
249 ->where('Rating.need_approve = ?', Model_DbTable_Rating::RATING_STATUS_APPROVED)
250 ->where('ISNULL(Rating.deleted)')
251 ->where('Rating.Hidden = 0')
252 ->where('Rating.isSpam = 0')
253 ->order('RankDate DESC');
254
255 if (!$getComments)
256 {
257 $select->where('NotUsedBefore = 0');
258 }
259
260 if (!is_null($fromDate))
261 {
262 $select->where('RankDate >= "'.Nocowboys_Tools::databaseSafeDateTime($fromDate).'"');
263 }
264
265 if (!is_null($toDate))
266 {
267 $select->where('RankDate < "'.Nocowboys_Tools::databaseSafeDateTime($toDate).'"');
268 }
269
270 if ($getCached)
271 {
272 $results = $ratingTable->fetchAllCache($select);
273 }
274 else
275 {
276 $results = $ratingTable->fetchAll($select);
277 }
278
279 unset($ratingTable);
280 return $results;
281 }
282
283 /**
284 * Gets comments for this business
285 * @param boolean $getCached Set to false to force-load comments without
286 * caching
287 * @return Zend_Db_Table_Rowset_Abstract A list of ratings
288 */
289 public function getComments($getCached = true)
290 {
291 $ratingTable = new Model_DbTable_Rating();
292 $select = $ratingTable->select()
293 ->where('businessID = ?', $this->ID)
294 ->where('Rating.Locked <> 1')
295 ->where('Rating.Hidden = 0')
296 ->where('Rating.isSpam = 0')
297 ->where('NotUsedBefore = 1')
298 ->order('RankDate DESC');
299
300 if ($getCached)
301 {
302 return $ratingTable->fetchAllCache($select);
303 }
304 else
305 {
306 return $ratingTable->fetchAll($select);
307 }
308 }
309
310 /**
311 *
312 * @return integer
313 */
314 public function isNotPaying()
315 {
316 $notPayingTable = new Model_DbTable_NotPayingBusiness();
317 $select = $notPayingTable->select()
318 ->where('BusinessID = ?', $this->ID);
319 return count($notPayingTable->fetchAll($select)) > 0;
320 }
321
322 /**
323 * Loads the unauthenticated ratings for this business
324 * @return Zend_Db_Table_Rowset_Abstract A list of unauthenticated ratings
325 */
326 public function getUnauthenticatedRatings($getCached = true, $beforeDate = NULL)
327 {
328 $beforeDateText = '';
329
330 $ratingTable = new Model_DbTable_Rating();
331 $select = $ratingTable->select()
332 ->where('BusinessID=?', $this->ID)
333 ->where('Rating.Locked = 1 AND Rating.Hidden = 0 AND NotUsedBefore = 0 '.$beforeDateText)
334 ->order('RankDate DESC');
335
336 if (!is_null($beforeDate))
337 {
338 $select->where('RankDate < "'.Nocowboys_Tools::databaseSafeDateTime($beforeDate).'"');
339 }
340
341 if ($getCached)
342 {
343 return $ratingTable->fetchAllCache($select);
344 }
345 else
346 {
347 return $ratingTable->fetchAll($select);
348 }
349 }
350
351 /**
352 * Calculates the overall rating percentage for this business by counting
353 * the ratings and their values. The total is saved to the business, along
354 * with the positive, negative and netural counts (not used in the new version
355 * but is used with the legacy code)
356 * @return int The overall rating percentage for this business
357 */
358 public function calculateOverallRating()
359 {
360 $ratings = $this->getAuthenticatedRatings(false);
361 $ratingCount = count($ratings);
362 $overall = 0;
363 $negativeRatingCount = 0;
364 $positiveRatingCount = 0;
365
366 foreach ($ratings as $rating)
367 {
368 $ratingValue = $rating->calculateRating();
369 $overall += $ratingValue;
370
371 if ($ratingValue >= Nocowboys_Tools::$ratingPositiveCutoff)
372 {
373 $positiveRatingCount++;
374 }
375
376 if ($ratingValue <= Nocowboys_Tools::$ratingNegativeCutoff)
377 {
378 $negativeRatingCount++;
379 }
380 }
381
382 if ($ratingCount > 0)
383 {
384 $overall = $overall / $ratingCount;
385 }
386
387 $this->TempOverall = $overall;
388 $this->TempNegative = $negativeRatingCount;
389 $this->TempPositive = $positiveRatingCount;
390 $this->TempNeutral = $ratingCount - $negativeRatingCount - $positiveRatingCount;
391 $this->save();
392
393 $this->updateToSolr();
394
395 return $this->TempOverall;
396 }
397
398 /**
399 * Checks if the business is customer preferred or not
400 * @return Boolean True if the business is Customer Preferred
401 */
402 public function isCustomerPreferred()
403 {
404 // Customer preferred is the same requirements as a job access
405 if ($this->OverrideCustomerPreferred == 1)
406 {
407 return false;
408 }
409 else
410 {
411 return $this->checkBusinessPreferred();
412 }
413 }
414
415 /**
416 * Checks if the business has access to jobs
417 * @return Boolean True if the business has access to jobs
418 */
419 public function checkBusinessPreferred() {
420 return ($this->_checkBusinessByOverallRating()
421 and $this->_checkBusinessByRatingCount()
422 and $this->_checkBusinessByRecentRating());
423 }
424
425 /**
426 * Checks if the business meet the requirements by overall rating.
427 *
428 *
429 * @return bool
430 */
431 private function _checkBusinessByOverallRating()
432 {
433
434 $config = Zend_Registry::get('config');
435
436 return (int) $this->TempOverall >= (int) $config->jobs->access->business->overallRating;
437 }
438
439 /**
440 * Checks if the business meet the requirements by rating count.
441 *
442 *
443 * @return bool
444 */
445 private function _checkBusinessByRatingCount()
446 {
447 $config = Zend_Registry::get('config');
448 $ratingCount = $this->getAuthenticatedRatings(false)->count();
449
450 return (int) $ratingCount >= (int) $config->jobs->access->business->ratingCount;
451 }
452
453 /**
454 * Checks if the business meet the requirements by recent rating.
455 *
456 *
457 * @return bool
458 */
459 private function _checkBusinessByRecentRating()
460 {
461 $config = Zend_Registry::get('config');
462 $recentRating = $this->getRecentRating();
463
464 return $recentRating
465 ? ((int) strtotime('+' . $config->jobs->access->business->recentRating->days
466 . ' days', strtotime($recentRating->RankDate)) >= time())
467 : false;
468 }
469
470 /**
471 * Gets the tasks for this business
472 * @return Zend_Db_Table_Rowset_Abstract
473 */
474 public function getTasks()
475 {
476 $taskObject = new Model_Task();
477 $select = $taskObject->select()->where('businessId=?', $this->ID)->where('task.completed = 0');
478
479 return $taskObject->fetchAll($select);
480 }
481
482 /**
483 * Gets the ratings for which more info was requested in the past for this business
484 * @return Zend_Db_Table_Rowset_Abstract
485 */
486 public function getRatingRequestMoreInfo()
487 {
488 $ratingRequestMoreInfoObject = new Model_DbTable_RatingRequestMoreInfo();
489 $select = $ratingRequestMoreInfoObject->select()->where('BusinessID=?', $this->ID);
490
491 return $ratingRequestMoreInfoObject->fetchAll($select);
492 }
493
494 /**
495 * Gets the history for the business
496 * @return Zend_Db_Table_Rowset_Abstract
497 */
498 public function getHistory()
499 {
500 $historyObject = new Model_DbTable_BusinessCorrespondence();
501
502 // History should not contain
503 $select = $historyObject->select()
504 ->where('BusinessID=?', $this->ID)
505 ->where('type <> 2')
506 ->where('type <> 0')
507 ->order(array('DateSent DESC'));
508
509 return $historyObject->fetchAll($select);
510 }
511
512 /**
513 * Gets the current categories this business has selected
514 * @return Zend_Db_Table_Rowset_Abstract
515 * @deprecated use getCategoriesCorrect() instead
516 */
517 public function getCategories()
518 {
519 $categoryObject = new Model_Category();
520 $select = $categoryObject->select()
521 ->setIntegrityCheck(false)
522 ->from(array('category' => 'Category'))
523 ->join(array('businessCategory' => 'BusinessCategory'), 'category.ID = businessCategory.CategoryID', array())
524 ->where('BusinessID=?', $this->ID)
525 ->order(array('category.Name DESC'));
526
527 return $categoryObject->fetchAll($select);
528 }
529
530 /**
531 * Gets the current categories this business has selected. This is the correct
532 * up-to-date method to use. Don't use getCategories()
533 * @return Zend_Db_Table_Rowset_Abstract
534 */
535 public function getCategoriesCorrect($getCached = true)
536 {
537 if ((is_null($this->categories)) or ( !$getCached))
538 {
539 $categoryTable = new Model_DbTable_Category();
540 $select = $categoryTable->select()
541 ->setIntegrityCheck(false)
542 ->from(array('category' => 'Category'))
543 ->join(array('businessCategory' => 'BusinessCategory'), 'category.ID = businessCategory.CategoryID', array())
544 ->where('BusinessID=?', $this->ID)
545 ->order(array('category.Name DESC'));
546
547 if ($getCached)
548 {
549 $this->categories = $categoryTable->fetchAllCache($select, NULL, NULL, NULL, array(), false, 8, self::CACHE_KEY_PREFIX_CATEGORIES.$this->ID);
550 }
551 else
552 {
553 $this->categories = $categoryTable->fetchAll($select);
554 }
555
556 unset($categoryTable);
557 }
558
559 return $this->categories;
560 }
561
562 /**
563 * Gets the current areas this business has selected
564 * @return Zend_Db_Table_Rowset_Abstract
565 */
566 public function getAreas($getCached = true)
567 {
568 if ((is_null($this->areas)) or ( !$getCached))
569 {
570 $areaObject = new Model_DbTable_Area();
571 $select = $areaObject->select()
572 ->setIntegrityCheck(false)
573 ->from(array('area' => 'Area'))
574 ->join(array('businessArea' => 'BusinessArea'), 'area.ID = businessArea.AreaID', array())
575 ->where('BusinessID=?', $this->ID)
576 ->order(array('area.Name DESC'));
577
578 if ($getCached)
579 {
580 $this->areas = $areaObject->fetchAllCache($select, NULL, NULL, NULL, array(), false, 8, self::CACHE_KEY_PREFIX_AREAS.$this->ID);
581 }
582 else
583 {
584 $this->areas = $areaObject->fetchAll($select);
585 }
586
587 unset($areaObject);
588 }
589
590 return $this->areas;
591 }
592
593 /**
594 * Get the relavent jobs for this business
595 * @return Zend_Db_Table_Rowset_Abstract
596 */
597 public function getJobs()
598 {
599 $jobObject = new Model_DbTable_Job();
600
601 $select = $jobObject->select()
602 ->distinct()
603 ->setIntegrityCheck(false)
604 ->from(array('job' => 'Job'))
605 ->joinLeft(array('businessInterestedinJob' => 'BusinessInterestedinJob'), 'businessInterestedinJob.JobID = job.ID And (businessInterestedinJob.IsQuestionAsked = 1 or businessInterestedinJob.IsQuoteSent = 1) and businessInterestedinJob.BusinessID <> 0', array('COUNT(distinct(businessInterestedinJob.ID)) AS InterestedBusinessCount'))
606 ->joinLeft(array('businessCategory' => 'BusinessCategory'), '(CategoryID = job.ParentCategoryID or CategoryID = job.SubCategoryID or CategoryID = job.SubSubCategoryID) and CategoryID <> 0', array())
607 ->joinLeft(array('businessArea' => 'BusinessArea'), '(businessArea.AreaID = job.RegionID or businessArea.AreaID = job.AreaID or businessArea.AreaID = job.SuburbAreaID) and businessArea.AreaID <> 0', array())
608 ->joinLeft(array('business' => 'Business'), 'business.ID = businessCategory.BusinessID and business.ID = businessArea.BusinessID', array())
609 ->where('job.IsOnline = 1')
610 ->where('businessCategory.BusinessID = ?', $this->ID)
611 ->where('businessArea.BusinessID = ?', $this->ID)
612 ->group('job.ID')
613 ->order(array('job.DateAdded DESC'));
614
615 return $jobObject->fetchAll($select);
616 }
617
618 /**
619 * Gets the categories the business prefers for their jobs. If none are set up
620 * then it defaults to their usual categories
621 * @return Zend_Db_Table_Rowset_Abstract
622 */
623 public function getJobCategories()
624 {
625 $jobCategories = $this->getMetaData(self::METAKEYJOBCATEGORIES);
626
627 if (!is_null($jobCategories))
628 {
629 // $jobCategories should be a comma-separated list of category IDs
630 $categoryTable = new Model_DbTable_Category();
631 return $categoryTable->fetchAll('ID IN ('.$jobCategories.')');
632 }
633 else
634 {
635 return $this->getCategories();
636 }
637 }
638
639 /**
640 * Gets the areas the business prefers for their jobs. If none are set up
641 * then it defaults to their usual areas
642 * @return Zend_Db_Table_Rowset_Abstract
643 */
644 public function getJobAreas()
645 {
646 $jobAreas = $this->getMetaData(self::METAKEYJOBAREAS);
647
648 if (!is_null($jobAreas))
649 {
650 // $jobAreas should be a comma-separated list of area IDs
651 $areaTable = new Model_DbTable_Area();
652 return $areaTable->fetchAll('ID IN ('.$jobAreas.')');
653 }
654 else
655 {
656 return $this->getAreas();
657 }
658 }
659
660 /**
661 * Gets the jobs this business has shown interest in
662 * @return Zend_Db_Table_Rowset_Abstract Rowet of jobs the business has
663 * shown interest in
664 */
665 public function getQuotedJobs()
666 {
667 $jobTable = new Model_DbTable_Job();
668 $jobSelect = $jobTable->select()
669 ->setIntegrityCheck(false)
670 ->from('Job')
671 ->joinInner('BusinessInterestedinJob', 'BusinessInterestedinJob.JobID = Job.ID', array('quoteDate' => 'DateAdded'))
672 ->where('BusinessID = '.$this->ID)
673 ->where('IsQuoteSent = 1 OR IsQuestionAsked = 1')
674 ->order('DateAdded DESC');
675
676 return $jobTable->fetchAll($jobSelect);
677 }
678
679 /**
680 * Gets the TM listings for this business
681 * @return Zend_Db_Table_Rowset_Abstract
682 */
683 public function getTMListings()
684 {
685 $tradeMeCategoryListingObject = new Model_DbTable_TradeMeCategoryListing();
686 $select = $tradeMeCategoryListingObject->select()
687 ->where('NoCowboysID=?', $this->ID)
688 ->where('IsOnline = 1')
689 ->order('DateAdded DESC');
690 return $tradeMeCategoryListingObject->fetchAll($select);
691 }
692
693 /**
694 * Gets the date this registration is supposed to expire (if the business is registered)
695 * @return Integer
696 */
697 public function getExpiryDate()
698 {
699 // Get the paymentlist of the business
700 $PaymentList = $this->getAllPaymentsByDatePaidDesc();
701
702 $todays_date = date("Y-m-d");
703 $today = strtotime($todays_date) / (3600 * 24);
704
705 // Check if the busines is registered or not
706 // If it's registered then get the current expiry date of the business
707 if ($this->isRegistered() == 1 or (!empty($this->ExpiryDate) and date(Nocowboys_Tools::DATABASE_DATE_FORMAT, strtotime('+' . self::REGISTRATION_GRACE_PERIOD_DAYS . ' days', strtotime($this->ExpiryDate))) >= $todays_date))
708 {
709 $CurrentExpiryDate = strtotime('-0 days', strtotime($this->ExpiryDate));
710 }
711 else // if not registered then just the registration date (today's date)
712 {
713 // Set the Current Expiry date as Register date + Free days
714 $CurrentExpiryDate = strtotime('+0 days', strtotime($todays_date));
715 }
716
717 $ExpiryDate = $CurrentExpiryDate;
718
719 $expiry_date = $CurrentExpiryDate / (3600 * 24);
720
721 if (count($PaymentList) > 0)
722 {
723 // Loop through all the payments
724 for ($i = 0; $i < 1; $i++)
725 {
726 //if(date('d M Y', $Today) < date('d M Y', strtotime($PaymentList[$i]->DatePaid)))
727 if (($expiry_date + self::REGISTRATION_GRACE_PERIOD_DAYS - $today) <= 0)
728 {
729 // Set the expiry date as payments date + days paid
730 $ExpiryDate = strtotime('+'.$PaymentList[$i]->DaysPaid.' days', strtotime($PaymentList[$i]->DatePaid));
731 }
732 else
733 {
734 // Set the expiry date as current expiry date + paid days
735 $ExpiryDate = strtotime('+'.$PaymentList[$i]->DaysPaid.' days', $CurrentExpiryDate);
736 }
737
738 $expiry_date = $ExpiryDate / 3600 * 24;
739 }
740 }
741
742 if (($expiry_date - $today) <= 0)
743 {
744 if (($this->IsNotPaying == 1) || ($this->IsOnNCJobsTrial == 1))
745 {
746 $ExpiryDate = strtotime($this->ExpiryDate);
747 }
748 }
749
750 return $ExpiryDate;
751 }
752
753 /**
754 * Gets the date this registration is supposed to expire (if the business is registered)
755 * @return Integer
756 */
757 public function getRegistrationExpiryDate()
758 {
759 // Get the paymentlist of the business
760 $PaymentList = $this->getAllPayments();
761
762 // Set the Current Expiry date as Register date + Free days
763 //$CurrentExpiryDate = strtotime('+0 days', strtotime($this->RegisterDate));
764 $CurrentExpiryDate = strtotime('+0 days', strtotime($this->ExpiryDate));
765
766 $ExpiryDate = $CurrentExpiryDate;
767
768 // $ExpiryDate = $CurrentExpiryDate;
769 $todays_date = date("Y-m-d");
770 $today = strtotime($todays_date) / 3600 * 24;
771 $expiry_date = $CurrentExpiryDate / 3600 * 24;
772
773 if (count($PaymentList) > 0)
774 {
775
776 // Loop through all the payments
777 for ($i = 0; $i < count($PaymentList); $i++)
778 {
779 // If this is the first payment object then add it into current expiry date
780 if ($i == 0)
781 {
782 //if(date('d M Y', $Today) < date('d M Y', strtotime($PaymentList[$i]->DatePaid)))
783 if (($expiry_date - $today) <= 0)
784 {
785 // Set the expiry date as payments date + days paid
786 $ExpiryDate = strtotime('+'.$PaymentList[$i]->DaysPaid.' days', strtotime($PaymentList[$i]->DatePaid));
787 }
788 else
789 {
790 // Set the expiry date as current expiry date + paid days
791 $ExpiryDate = strtotime('+'.$PaymentList[$i]->DaysPaid.' days', $CurrentExpiryDate);
792 }
793
794
795 $expiry_date = $ExpiryDate / 3600 * 24;
796 }
797
798 // Else add it into Expiry date
799 if ($i > 0)
800 {
801 $today = strtotime($PaymentList[$i]->DatePaid) / 3600 * 24;
802
803 //if(date('d M Y', strtotime($PaymentList[$i]->DatePaid)) > date('d M Y', $ExpiryDate))
804 if (($expiry_date - $today) <= 0)
805 {
806 // Set the expiry date as payments date + days paid
807 $ExpiryDate = strtotime('+'.$PaymentList[$i]->DaysPaid.' days', strtotime($PaymentList[$i]->DatePaid));
808 }
809 else
810 {
811 $ExpiryDate = strtotime('+'.$PaymentList[$i]->DaysPaid.' days', $ExpiryDate);
812 }
813
814 $expiry_date = $ExpiryDate / 3600 * 24;
815 }
816 }
817
818 $today = strtotime($todays_date) / 3600 * 24;
819 $expiry_date = $ExpiryDate / 3600 * 24;
820 }
821
822 // added by Nik to return expiry date extended manually for the business.
823 // may be becoz of some sort of promotion etc, team have to extend the rego expiry date
824 $actual_expiry_date = strtotime($this->ExpiryDate) / 3600 * 24;
825
826 if (($actual_expiry_date - $expiry_date) > 0)
827 {
828 $ExpiryDate = strtotime($this->ExpiryDate);
829 }
830
831 if (($expiry_date - $today) <= 0)
832 {
833 if (($this->IsNotPaying == 1) || ($this->IsOnNCJobsTrial == 1))
834 //if ($this->IsNotPaying == 1)
835 {
836 $ExpiryDate = strtotime($this->ExpiryDate);
837 }
838 }
839
840 return $ExpiryDate;
841 }
842
843 /**
844 * Gets the date this registration is supposed to expire (if the business is registered) from business table.
845 * @return integer Unix timestamp
846 */
847 public function getRegistrationExpiryDateFromTable()
848 {
849 $ExpiryDate = strtotime($this->ExpiryDate);
850
851 return $ExpiryDate;
852 }
853
854 /**
855 * Loads all the payments for this business
856 * @param boolean $orderAsc Set to false to order descending
857 * @return Zend_Db_Table_Rowset_Abstract
858 */
859 public function getAllPayments($orderAsc = true)
860 {
861
862 $paymentObject = new Model_Payment();
863 $select = $paymentObject->select()
864 ->where('BusinessID=?', $this->ID)
865 ->where('DaysPaid > 0');
866
867 if ($orderAsc)
868 {
869 $select->order(array('DatePaid ASC'));
870 }
871 else
872 {
873 $select->order(array('DatePaid DESC'));
874 }
875
876 return $paymentObject->fetchAll($select);
877 }
878
879 /**
880 * Loads all the payments for this business in datepaid desc order.
881 * @return Array
882 */
883 public function getAllPaymentsByDatePaidDesc()
884 {
885
886 $paymentObject = new Model_Payment();
887 $select = $paymentObject->select()
888 ->where('BusinessID=?', $this->ID)
889 ->where('DaysPaid > 0')
890 ->order(array('DatePaid DESC'));
891
892 return $paymentObject->fetchAll($select);
893 }
894
895 /**
896 * Set the user assigned to this business
897 * @param integer $userId ID of the user that is assigned to the business
898 * @return Boolean
899 */
900 public function setUser($userId)
901 {
902 // Delete any users already assigned
903 $userBusinessObject = new Model_UserBusiness();
904 $select = $userBusinessObject->select()
905 ->where('BusinessID=?', $this->ID);
906
907 $assignedUsers = $userBusinessObject->fetchAll($select);
908 foreach ($assignedUsers as $user)
909 {
910 $user->delete();
911 }
912
913 // Assign the new user
914 $newUserBusiness = $userBusinessObject->createRow();
915
916 $newUserBusiness->userId = $userId;
917 $newUserBusiness->businessId = $this->ID;
918
919 $newUserBusiness->save();
920 }
921
922 /**
923 * Gets the user assigned to this business
924 * @return Integer
925 */
926 public function getUser()
927 {
928 $userBusinessObject = new Model_UserBusiness();
929 $select = $userBusinessObject->select()
930 ->where('BusinessID=?', $this->ID);
931
932 $assignedUser = $userBusinessObject->fetchRow($select);
933 return $assignedUser;
934 }
935
936 /**
937 * Gets the different package options for this business. If they're on an older package,
938 * they get to choose that too (god knows why, but yeah.)
939 * @return array
940 */
941 public function getAvailablePackages()
942 {
943 $productTable = new Model_DbTable_Product();
944
945 $productSelect = $productTable->select()
946 ->setIntegrityCheck(false)
947 //->where($this->quoteInto('ID = ?', $this->SubscribedProductId).' OR (isPackage = 1 AND Active = 1)')
948 ->where('isPackage = 1 AND Active = 1')
949 ->order('displayOrder DESC');
950
951 return $productTable->fetchAll($productSelect);
952 }
953
954 /**
955 * Gets the current package if there's one set
956 * @param string|null $class Product specific class
957 * @return Model_DbTableRow_Product
958 * @return mixed
959 */
960 public function getCurrentPackage($class = null)
961 {
962 $productTable = new Model_DbTable_Product();
963 if ($class) {
964 $productTable->setRowClass($class);
965 }
966
967 $productSelect = $productTable->select()
968 ->where($this->quoteInto('ID = ?', $this->SubscribedProductId));
969
970 return $productTable->fetchRow($productSelect);
971 }
972
973 /**
974 * Gets the current default package if there's one set or return default package if not
975 * @param string|null $class Product specific class
976 * @return Model_DbTableRow_Product
977 * @return mixed
978 */
979 public function getCurrentDefaultPackage($class = null)
980 {
981 $productTable = new Model_DbTable_Product();
982 if ($class) {
983 $productTable->setRowClass($class);
984 }
985
986 if(!empty($this->default_package_id)) {
987 $productSelect = $productTable->select()
988 ->where($this->quoteInto('ID = ?', $this->default_package_id));
989 return $productTable->fetchRow($productSelect);
990 } else {
991 return $this->getDefaultProduct();
992 }
993
994 }
995
996 /**
997 * Handles renewing the current package. Call this if we suspect the
998 * package has expired, or is near expiring. The package itself will
999 * take care of payments and reminders
1000 *
1001 */
1002 public function renewCurrentPackage()
1003 {
1004 $currentPackage = $this->getCurrentPackage();
1005
1006 // Send a reminder for the package
1007 $currentPackage->sendReminder($this);
1008
1009 // Attempt a payment if required
1010 if ($currentPackage->shouldAttemptPaymentToday($this))
1011 {
1012 // Create a new payment and attempt to take it
1013 $newPurchase = new Model_DbTableRow_Purchase();
1014 $newPurchase->BusinessID = $this->ID;
1015 $newPurchase->addProduct($currentPackage);
1016 $newPurchase->save();
1017 }
1018 }
1019
1020 /**
1021 * Suggests a unique URL that can be used for displaying on the website
1022 * @return string URL to use on the website
1023 */
1024 public function suggestUrl()
1025 {
1026 $businessTable = new Model_DbTable_Business();
1027
1028 $firstUrl = $businessTable->cleanUrl($this->CompanyName);
1029 $additionalCounter = 2;
1030
1031 while (!is_null($businessTable->fetchRowByValue('URLName', $firstUrl)))
1032 {
1033 $firstUrl = $businessTable->cleanUrl($this->CompanyName.'-'.$additionalCounter);
1034 $additionalCounter++;
1035 }
1036
1037 return strtolower($firstUrl);
1038 }
1039
1040 /**
1041 * Returns the full URI for this business. Even though this is simple, use this so we
1042 * only need to make a change in one place
1043 * @param boolean $leadingSlash Set to false to remove the leading slash
1044 * @return string
1045 */
1046 public function getURI($leadingSlash = true)
1047 {
1048 $url = 'businesses/'.$this->URLName;
1049
1050 if ($leadingSlash)
1051 {
1052 return '/'.$url;
1053 }
1054 else
1055 {
1056 return $url;
1057 }
1058 }
1059
1060 /**
1061 * Generate a random password. The letter l (lowercase L) and the
1062 * number 1 have been removed, as they can be mistaken for each other,
1063 * as has the zero (0) and the oh (o) for the same reason
1064 * @return string Randomly generated password
1065 */
1066 public function createRandomPassword()
1067 {
1068 $chars = "abcdefghijkmnpqrstuvwxyz23456789";
1069 srand((double) microtime() * 1000000);
1070 $i = 0;
1071 $pass = '';
1072
1073 while ($i <= 8)
1074 {
1075 $num = rand() % 33;
1076 $tmp = substr($chars, $num, 1);
1077 $pass = $pass.$tmp;
1078 $i++;
1079 }
1080
1081 return $pass;
1082 }
1083
1084 /**
1085 * sends welcome email to business for the registration.
1086 * @return true
1087 */
1088 public function sendWelcomeEmail()
1089 {
1090 // this code below sends them a welcome email with login details.
1091 // checks if the username and password are set
1092 // if not then set it
1093 if ($this->Username == '')
1094 {
1095 // set Emailaddress as username
1096 $this->Username = $this->EmailAddress;
1097 }
1098
1099 $passwordToSend = '(the password you set)';
1100
1101 if (trim($this->Password) == '')
1102 {
1103 // Call the function to generate random password for the new businesses
1104 $password = $this->createRandomPassword();
1105
1106 $passwordToSend = $password;
1107
1108 // Set password for new business.
1109 $this->setPassword($password);
1110 }
1111
1112 $this->save();
1113
1114 $emailArray2['companyName'] = $this->CompanyName;
1115 $emailArray2['username'] = $this->Username;
1116 $emailArray2['password'] = $passwordToSend;
1117 $emailArray2['businessId'] = $this->ID;
1118
1119 $config = Zend_Registry::get('config');
1120 $emailArray2['baseUrl'] = str_replace(array('http://', 'https://'), array(''), $config->domain);
1121 $emailArray2['baseLink'] = $config->domain;
1122 $emailArray2['loginLink'] = $config->domain . '/login';
1123 $emailArray2['fillingOutProfileLink'] = $config->email->template->fillingOutProfileLink;
1124 $emailArray2['registrationEmail'] = $config->email->template->registrationEmail;
1125
1126 Nocowboys_Email::sendEmail($this->EmailAddress, 'Welcome to NoCowboys', 'businessLogins', $emailArray2);
1127
1128 return true;
1129 }
1130
1131 /**
1132 * Generic method to send emails to this business. This is just a wrapper, but
1133 * means you don't need to worry about the email address to send it to
1134 * @param string $emailAddress
1135 * @param string $subject
1136 * @param string $emailView
1137 * @param array $emailParameters
1138 * @param type $layout
1139 * @param type $overrideFromAddress
1140 * @param type $overrideFromName
1141 */
1142 public function sendEmail($subject, $emailView, $emailParameters, $layout = 'email', $overrideFromAddress = NULL, $overrideFromName = NULL, $options = [])
1143 {
1144 $emailAddress = $this->getEmailAddress($options);
1145
1146 // Add the business ID so it gets stored against their correspondence
1147 $emailParameters['businessId'] = $this->ID;
1148
1149 return empty($emailAddress)
1150 ? false
1151 : Nocowboys_Email::sendEmail($emailAddress, $subject, $emailView, $emailParameters,
1152 $layout, $overrideFromAddress, $overrideFromName
1153 );
1154
1155 }
1156
1157 /**
1158 * Returns the email address for this business to send emails to. There are a
1159 * couple of email address fields in the database, so this returns the one
1160 * best suited
1161 */
1162 public function getEmailAddress($options = [])
1163 {
1164 if(!empty($options['destination']) and stripos($this->$options['destination'], '@') !== false) {
1165 return $this->$options['destination'];
1166 } elseif (stripos($this->EmailAddress, '@') !== false) {
1167 return $this->EmailAddress;
1168
1169 } elseif (stripos($this->Username, '@') !== false) {
1170 return $this->Username;
1171
1172 } else {
1173 $logger = Zend_Registry::get('logger');
1174 $logger->info("No detected email address for business [BusinessID = $this->ID]",
1175 array('program' => 'business:get_email_address'));
1176 return false;
1177 }
1178 }
1179
1180 /**
1181 * Gets the location area for this business. Returns the area or NULL
1182 * if no area is set
1183 * @return Model_DbTableRow_Area | NULL
1184 */
1185 public function getLocationArea()
1186 {
1187 if (is_null($this->locationArea))
1188 {
1189 if ((isset($this->LocationAreaID)) and ( is_numeric($this->LocationAreaID)) and ( $this->LocationAreaID > 0))
1190 {
1191 $areaTable = new Model_DbTable_Area();
1192 $this->locationArea = $areaTable->fetchRowByValueCache('ID', $this->LocationAreaID);
1193 }
1194 }
1195
1196 return $this->locationArea;
1197 }
1198
1199 /**
1200 * Gets the postal location area for this business. Returns the area or NULL if no area is set
1201 * @return Model_DbTableRow_Area | NULL
1202 */
1203 public function getPostalLocationArea()
1204 {
1205 if (is_null($this->postalLocationArea))
1206 {
1207 if ((isset($this->PostalSuburbID)) and ( is_numeric($this->PostalSuburbID)) and ( $this->PostalSuburbID > 0))
1208 {
1209 $areaTable = new Model_DbTable_Area();
1210 $this->postalLocationArea = $areaTable->fetchRowByValue('ID', $this->PostalSuburbID);
1211 }
1212 }
1213
1214 return $this->postalLocationArea;
1215 }
1216
1217 /**
1218 * Encrypts the password for a user using MD5 and the system salt
1219 * @param string $password Password to encrypt
1220 * @return string
1221 */
1222 static function encryptPassword($password)
1223 {
1224 $passwordSalt = Zend_Registry::get('config')->passwordSalt;
1225
1226 return md5($passwordSalt.$password);
1227 }
1228
1229 /**
1230 * Gets the meta data for a business. Returns NULL if no value is found
1231 * @param string $metaKey The key of the value for this business you want to load
1232 * @return mixed
1233 */
1234 public function getMetaData($metaKey)
1235 {
1236 $existingMetaDataObject = $this->getMetaDataObject();
1237
1238 if (is_null($existingMetaDataObject))
1239 {
1240 return NULL;
1241 }
1242
1243 $metaData = json_decode($existingMetaDataObject->metaValue, true);
1244
1245 if (isset($metaData[$metaKey]))
1246 {
1247 return $metaData[$metaKey];
1248 }
1249 else
1250 {
1251 return NULL;
1252 }
1253 }
1254
1255 /**
1256 * Gets the meta data for a business. Returns NULL if no value is found
1257 * @param string $metaKey The key of the value for this business you want to load
1258 * @return mixed
1259 */
1260 public function getMetaDataObject()
1261 {
1262 if (is_null($this->_metaKeyMeta))
1263 {
1264 $metaTable = new Model_DbTable_BusinessMeta();
1265
1266 $select = $metaTable->select()
1267 ->where('businessId=?', $this->ID)
1268 ->where('metaKey = ?', self::METAKEYMETA);
1269
1270 $this->_metaKeyMeta = $metaTable->fetchRow($select);
1271 }
1272
1273 return $this->_metaKeyMeta;
1274 }
1275
1276 /**
1277 * Sets meta data for a business. IMPORTANT: This will overwrite the value for this key
1278 * if the key already exists
1279 * @param string $metaKey The key of the value for this business you want to load
1280 * @param string $metaValue The value for the key
1281 * @return boolean
1282 */
1283 public function setMetaData($metaKey, $metaValue)
1284 {
1285 $metaTable = new Model_DbTable_BusinessMeta();
1286
1287 // Check if the key exists already
1288 $existingMetaObject = $this->getMetaDataObject($metaKey);
1289
1290 if (is_null($existingMetaObject))
1291 {
1292 // Otherwise create a new meta value
1293 $newMetaValue = $metaTable->createRow();
1294 $newMetaValue->metaKey = self::METAKEYMETA;
1295 $newMetaValue->metaValue = json_encode(array($metaKey => $metaValue));
1296 $newMetaValue->businessId = $this->ID;
1297
1298 return $newMetaValue->save();
1299 }
1300 else
1301 {
1302 $metaData = json_decode($existingMetaObject->metaValue, true);
1303 $metaData[$metaKey] = $metaValue;
1304
1305 $existingMetaObject->metaValue = json_encode($metaData);
1306 return $existingMetaObject->save();
1307 }
1308 }
1309
1310 /**
1311 * Builds an array suitable to be sent to Elastica
1312 *
1313 * @return array
1314 */
1315 public function buildElasticSearchArray()
1316 {
1317 $businessId = $this->ID;
1318
1319 $ratingTable = new Model_DbTable_Rating();
1320 $select = $ratingTable->select()
1321 ->where('businessID = ?', $this->ID)
1322 ->where('Rating.Locked <> 1')
1323 ->where('Rating.Comment <> ""')
1324 ->where('Rating.Hidden = 0')
1325 ->where('Rating.isSpam = 0')
1326 ->where('Rating.NotUsedBefore = 0')
1327 ->order('RankDate DESC')
1328 ->limit(5);
1329
1330 $selectMostRecentDate = $ratingTable->select()
1331 ->where('businessID = ?', $this->ID)
1332 ->where('Rating.Locked <> 1')
1333 ->where('Rating.Hidden = 0')
1334 ->where('Rating.isSpam = 0')
1335 ->where('Rating.NotUsedBefore = 0')
1336 ->order('RankDate DESC')
1337 ->limit(1);
1338
1339 $countSelect = $ratingTable->select()
1340 ->from('Rating', array('ratingCount' => 'COUNT(*)'))
1341 ->where('businessID = ?', $this->ID)
1342 ->where('Rating.Locked <> 1')
1343 ->where('Rating.Hidden = 0')
1344 ->where('Rating.isSpam = 0')
1345 ->where('Rating.NotUsedBefore = 0')
1346 ->limit(1);
1347
1348 $mostRecentRatingDate = $ratingTable->fetchRow($selectMostRecentDate);
1349 $mostRecentRatings = $ratingTable->fetchAll($select);
1350 $ratingCount = $ratingTable->fetchRow($countSelect);
1351
1352 $mostRecentRatingsArray = [];
1353
1354 if ($this->isRegistered())
1355 {
1356 foreach ($mostRecentRatings as $recentRating)
1357 {
1358 $mostRecentRatingsArray[] = $recentRating->Comment;
1359 }
1360 }
1361
1362 unset($ratingTable);
1363 unset($mostRecentRatings);
1364
1365 // Build an array of categories
1366 $categories = $this->getCategoriesCorrect(false);
1367 $categoryArray = [];
1368
1369 foreach ($categories as $category)
1370 {
1371 $categoryArray[] = $category->ID;
1372 }
1373
1374 unset($categories);
1375
1376 // Build an array of areas
1377 $areas = $this->getAreas(false);
1378 $areasArray = array();
1379
1380 foreach ($areas as $area)
1381 {
1382 $areasArray[] = $area->ID;
1383 }
1384
1385 unset($areas);
1386
1387 // Get the badges for this business
1388 $badges = $this->getBadges(false);
1389
1390 // Get the area for the business
1391 $locationArea = $this->getLocationArea();
1392
1393 // Check if this area is in the list of areas for the business. If not, add it.
1394 // This means we can search by the area name
1395 $locationAreaName = !is_null($locationArea) ? $locationArea->Name : '';
1396 $locationAreaId = !is_null($locationArea) ? $locationArea->ID : NULL;
1397
1398 // Get the primary category
1399 $primaryCategory = $this->getPrimaryCategory(true);
1400 $primaryCategoryId = !is_null($primaryCategory) ? $primaryCategory->ID : NULL;
1401 $primaryCategoryName = !is_null($primaryCategory) ? $primaryCategory->Name : NULL;
1402 $categoryArray[] = $primaryCategoryId;
1403
1404 // Add the business' location area ID if it's not already added
1405 if ((!is_null($locationAreaId)) and ( !in_array($locationAreaId, $areasArray)))
1406 {
1407 $areasArray[] = $locationAreaId;
1408 }
1409
1410 // Get the associations
1411 $associations = $this->getAssociations();
1412 $associationsArray = [];
1413
1414 foreach ($associations as $association)
1415 {
1416 $associationsArray[] = ['id' => $association->ID, 'name' => $association->name, 'logoLocation' => $association->logoLocation];
1417 }
1418
1419 unset($associations);
1420
1421 // Update the denomalised categories
1422 $this->denormaliseCategoryIds();
1423
1424// echo $this->isRegistered() . "\n";
1425
1426 // Create and index the business data
1427 $elasticArray = [
1428 'id' => $businessId,
1429 'uri' => $this->getURI(),
1430 'businessName' => $this->CompanyName,
1431 'overallRating' => round($this->TempOverall),
1432 'ratingCount' => $ratingCount->ratingCount,
1433 'about' => $this->AboutUs,
1434 'mostRecentRating' => $mostRecentRatingsArray,
1435 'mostRecentRatingDate' => is_null($mostRecentRatingDate) ? NULL : date('Y-m-d', strtotime($mostRecentRatingDate->RankDate)),
1436 'isOnline' => $this->IsOnline == 1 ? true : false,
1437 'areas' => $areasArray,
1438 'categories' => $categoryArray,
1439 'locationArea' => $locationAreaName,
1440 'locationAreaId' => (integer) $locationAreaId,
1441 'primaryCategoryId' => $primaryCategoryId,
1442 'primaryCategoryName' => $primaryCategoryName,
1443 'customerPreferred' => $this->isCustomerPreferred(),
1444 'registered' => $this->isRegistered() ? true : false,
1445 'denormalisedCategories' => explode(',', $this->categoryIds),
1446 'badges' => $badges,
1447 'associations' => $associationsArray,
1448 'phoneNumber' => $this->ContactPhone1. ' '.$this->ContactPhone2.' '. $this->Mobile.' '.$this->Fax.' '.
1449 $this->Phone1Prefix.$this->Phone1Number.' '.$this->Phone2Prefix.$this->Phone2Number,
1450 'emailAddress' => $this->EmailAddress,
1451 'contactName' => $this->Name.' '.$this->lastName,
1452 'physicalAreaId' => $this->LocationAreaID,
1453 'physicalAddress' => $this->AddressStreetName.' '.$this->AddressStreetNumber,
1454 'addressPostCode' => $this->addressPostcode,
1455 'postAreaId' => $this->PostalSuburbID,
1456 'postAddress' => $this->PostalStreetName.' '.$this->PostalStreetNumber,
1457 'postCode' => $this->postalPostcode,
1458 'postBox' => $this->PostalUnitNumber,
1459 'expiryDate' => $this->ExpiryDate == '0000-00-00 00:00:00' ? self::DEFAULT_DATE : date(Nocowboys_Tools::DATABASE_DATE_TIME_FORMAT , strtotime($this->ExpiryDate)),
1460 'dateAdded' => $this->DateAdded == '0000-00-00 00:00:00' ? self::DEFAULT_DATE : $this->DateAdded,
1461 'salesStatus' => $this->salesStatus,
1462// 'tag_suggest' => [
1463// 'input' => [$this->CompanyName] + explode(' ', $this->CompanyName),
1464// 'output' => $this->CompanyName,
1465// 'payload' => [
1466// 'overallRating' => round($this->TempOverall),
1467// 'ratingCount' => $ratingCount->ratingCount,
1468// 'locationArea' => $locationAreaName,
1469// 'businessId' => $this->ID,
1470// 'uri' => $this->getURI(),
1471// 'badges' => $badges,
1472// 'associations' => $associationsArray
1473// ]
1474// ]
1475 ];
1476
1477 if ($inputForTagSuggest = $this->_getInputForTagSuggest($this->CompanyName)) {
1478 $elasticArray['tag_suggest'] = $inputForTagSuggest;
1479 }
1480
1481 unset($mostRecentRatingDate);
1482
1483 // If there's a location, add it
1484 $location = $this->getMapCoordinates(true);
1485 if (!is_null($location))
1486 {
1487 $elasticArray['location'] = $location->Lat.','.$location->Lang;
1488 }
1489// if (count($mostRecentRatingsArray) > 0)
1490// {
1491// var_dump($elasticArray);
1492// exit();
1493// }
1494 return $elasticArray;
1495 }
1496
1497 /**
1498 * Builds an array for CRM search suitable to be sent to Elastica
1499 *
1500 * @return array
1501 */
1502 public function buildCrmElasticSearchArray()
1503 {
1504 $businessId = $this->ID;
1505
1506 $ratingTable = new Model_DbTable_Rating();
1507 $select = $ratingTable->select()
1508 ->where('businessID = ?', $this->ID)
1509 ->where('Rating.Locked <> 1')
1510 ->where('Rating.Comment <> ""')
1511 ->where('Rating.Hidden = 0')
1512 ->where('Rating.isSpam = 0')
1513 ->where('Rating.NotUsedBefore = 0')
1514 ->order('RankDate DESC')
1515 ->limit(5);
1516
1517 $selectMostRecentDate = $ratingTable->select()
1518 ->where('businessID = ?', $this->ID)
1519 ->where('Rating.Locked <> 1')
1520 ->where('Rating.Hidden = 0')
1521 ->where('Rating.isSpam = 0')
1522 ->where('Rating.need_approve = 0')
1523 ->where('Rating.NotUsedBefore = 0')
1524 ->order('RankDate DESC')
1525 ->limit(1);
1526
1527 $countSelect = $ratingTable->select()
1528 ->from('Rating', array('ratingCount' => 'COUNT(*)'))
1529 ->where('businessID = ?', $this->ID)
1530 ->where('Rating.Locked <> 1')
1531 ->where('Rating.Hidden = 0')
1532 ->where('Rating.need_approve = 0')
1533 ->where('Rating.isSpam = 0')
1534 ->where('Rating.NotUsedBefore = 0')
1535 ->limit(1);
1536
1537 $tasks = NULL;
1538 $countTasks = NULL;
1539
1540 $taskTable = new Model_DbTable_Task();
1541 $taskSelect = $taskTable->select()
1542 ->from('task')
1543 ->where('businessId = ?', $this->ID)
1544 ->where('completed = ?', 0)
1545 ->order('dateTime ASC');
1546 $result = $taskTable->fetchAll($taskSelect)->toArray();
1547 if (!empty($result)) {
1548 $tasks = $result;
1549 $countTasks = count($tasks);
1550 }
1551
1552
1553 $mostRecentRatingDate = $ratingTable->fetchRow($selectMostRecentDate);
1554 $mostRecentRatings = $ratingTable->fetchAll($select);
1555 $ratingCount = $ratingTable->fetchRow($countSelect);
1556
1557 $mostRecentRatingsArray = [];
1558
1559 if ($this->isRegistered())
1560 {
1561 foreach ($mostRecentRatings as $recentRating)
1562 {
1563 $mostRecentRatingsArray[] = $recentRating->Comment;
1564 }
1565 }
1566
1567 unset($ratingTable);
1568 unset($mostRecentRatings);
1569
1570 // Build an array of categories
1571 $categories = $this->getCategoriesCorrect(false);
1572 $categoryArray = [];
1573
1574 foreach ($categories as $category)
1575 {
1576 $categoryArray[] = $category->ID;
1577 }
1578
1579 unset($categories);
1580
1581 // Build an array of areas
1582 $areas = $this->getAreas(false);
1583 $areasArray = array();
1584
1585 foreach ($areas as $area)
1586 {
1587 $areasArray[] = $area->ID;
1588 }
1589
1590 unset($areas);
1591
1592 // Get the badges for this business
1593 $badges = $this->getBadges(false);
1594
1595 // Get the area for the business
1596 $locationArea = $this->getLocationArea();
1597
1598 // Check if this area is in the list of areas for the business. If not, add it.
1599 // This means we can search by the area name
1600 $locationAreaName = !is_null($locationArea) ? $locationArea->Name : '';
1601 $locationAreaId = !is_null($locationArea) ? $locationArea->ID : NULL;
1602
1603 // Get the primary category
1604 $primaryCategory = $this->getPrimaryCategory(true);
1605 $primaryCategoryId = !is_null($primaryCategory) ? $primaryCategory->ID : NULL;
1606 $primaryCategoryName = !is_null($primaryCategory) ? $primaryCategory->Name : NULL;
1607 $categoryArray[] = $primaryCategoryId;
1608
1609 // Add the business' location area ID if it's not already added
1610 if ((!is_null($locationAreaId)) and ( !in_array($locationAreaId, $areasArray)))
1611 {
1612 $areasArray[] = $locationAreaId;
1613 }
1614
1615 // Get the associations
1616 $associations = $this->getAssociations();
1617 $associationsArray = [];
1618
1619 foreach ($associations as $association)
1620 {
1621 $associationsArray[] = ['id' => $association->ID, 'name' => $association->name, 'logoLocation' => $association->logoLocation];
1622 }
1623
1624 unset($associations);
1625
1626 // Update the denomalised categories
1627 $this->denormaliseCategoryIds();
1628
1629 $assignedUser = $this->getUser();
1630
1631 $lastPayment = $this->getLastPayment();
1632
1633 $currentPackage = $this->getCurrentPackage();
1634
1635 // Create and index the business data
1636 $elasticArray = [
1637 'id' => $businessId,
1638 'uri' => $this->getURI(),
1639 'businessName' => $this->CompanyName,
1640 'overallRating' => round($this->TempOverall),
1641 'ratingCount' => $ratingCount->ratingCount,
1642 'about' => $this->AboutUs,
1643 'mostRecentRating' => $mostRecentRatingsArray,
1644 'mostRecentRatingDate' => is_null($mostRecentRatingDate) ? NULL : date('Y-m-d', strtotime($mostRecentRatingDate->RankDate)),
1645 'isOnline' => $this->IsOnline == 1 ? true : false,
1646 'areas' => $areasArray,
1647 'categories' => $categoryArray,
1648 'locationArea' => $locationAreaName,
1649 'locationAreaId' => (integer) $locationAreaId,
1650 'primaryCategoryId' => $primaryCategoryId,
1651 'primaryCategoryName' => $primaryCategoryName,
1652 'customerPreferred' => $this->isCustomerPreferred(),
1653 'registered' => $this->isRegistered() ? true : false,
1654 'denormalisedCategories' => explode(',', $this->categoryIds),
1655 'badges' => $badges,
1656 'associations' => $associationsArray,
1657 'phoneNumber' => $this->ContactPhone1. ' '.$this->ContactPhone2.' '. $this->Mobile.' '.$this->Fax.' '.
1658 $this->Phone1Prefix.$this->Phone1Number.' '.$this->Phone2Prefix.$this->Phone2Number,
1659 'emailAddress' => $this->EmailAddress,
1660 'contactName' => $this->Name.' '.$this->lastName,
1661 'physicalAreaId' => $this->LocationAreaID,
1662 'physicalAddress' => $this->AddressStreetName.' '.$this->AddressStreetNumber,
1663 'addressPostCode' => $this->addressPostcode,
1664 'postAreaId' => $this->PostalSuburbID,
1665 'postAddress' => $this->PostalStreetName.' '.$this->PostalStreetNumber,
1666 'postCode' => $this->postalPostcode,
1667 'postBox' => $this->PostalUnitNumber,
1668 'expiryDate' => $this->ExpiryDate == '0000-00-00 00:00:00' ? self::DEFAULT_DATE : date(Nocowboys_Tools::DATABASE_DATE_TIME_FORMAT , strtotime($this->ExpiryDate)),
1669 'dateAdded' => $this->DateAdded == '0000-00-00 00:00:00' ? self::DEFAULT_DATE : $this->DateAdded,
1670 'salesStatus' => $this->salesStatus,
1671 'task' => $tasks,
1672 'countTask' => $countTasks,
1673 'subscribedProductId' => $this->SubscribedProductId,
1674 'productPrice' => !empty($currentPackage) ? $currentPackage->PricePerUnit : '',
1675 'lastPaymentAmount' => !empty($lastPayment) ? $lastPayment->Amount : NULL,
1676 'assignedTo' => !empty($assignedUser) ? $assignedUser->userId : '',
1677 'closestTaskDate' => (is_array($tasks) and $tasks[0]['dateTime'] !== '0000-00-00 00:00:00') ? $tasks[0]['dateTime'] : NULL,
1678// 'tag_suggest' => [
1679// 'input' => [$this->CompanyName] + explode(' ', $this->CompanyName),
1680// 'output' => $this->CompanyName,
1681// 'payload' => [
1682// 'overallRating' => round($this->TempOverall),
1683// 'ratingCount' => $ratingCount->ratingCount,
1684// 'locationArea' => $locationAreaName,
1685// 'businessId' => $this->ID,
1686// 'uri' => $this->getURI(),
1687// 'badges' => $badges,
1688// 'associations' => $associationsArray
1689// ]
1690// ]
1691 ];
1692
1693 if ($inputForTagSuggest = $this->_getInputForTagSuggest($this->CompanyName)) {
1694 $elasticArray['tag_suggest'] = $inputForTagSuggest;
1695 }
1696
1697 unset($mostRecentRatingDate);
1698
1699 // If there's a location, add it
1700 $location = $this->getMapCoordinates(true);
1701 if (!is_null($location))
1702 {
1703 $elasticArray['location'] = $location->Lat.','.$location->Lang;
1704 }
1705// if (count($mostRecentRatingsArray) > 0)
1706// {
1707// var_dump($elasticArray);
1708// exit();
1709// }
1710 return $elasticArray;
1711 }
1712
1713 protected function _getInputForTagSuggest($companyName = '')
1714 {
1715 $companyName = trim(preg_replace('/\s{2,}/',' ',$companyName));
1716
1717 if ($companyName) {
1718
1719 return [
1720 'input' => [$companyName] + explode(' ', $companyName),
1721 ];
1722 }
1723
1724 return false;
1725 }
1726
1727 /**
1728 * Updates the business to the SOLR search system
1729 *
1730 * @return boolean
1731 */
1732 public function updateToSolr()
1733 {
1734
1735 $businessId = $this->ID;
1736
1737 if($this->showInSearchResult()) {
1738 $elasticArray = $this->buildElasticSearchArray();
1739
1740 // Save the document
1741 $businessDocument = new ElasticDocument($businessId, $elasticArray);
1742 $elasticaIndex = Nocowboys_Elastic::getIndex();
1743 $businessType = $elasticaIndex->getType(Model_DbTable_Business::elasticTypeName);
1744 $businessType->addDocument($businessDocument);
1745 $businessType->getIndex()->refresh();
1746 }
1747
1748 $elasticArrayCRM = $this->buildCrmElasticSearchArray();
1749
1750 // Save the document
1751 $businessDocumentCRM = new ElasticDocument($businessId, $elasticArrayCRM);
1752 $elasticaIndexCRM = Nocowboys_Elastic::getCRMIndex();
1753 $businessTypeCRM = $elasticaIndexCRM->getType(Model_DbTable_Business::elasticTypeName);
1754 $businessTypeCRM->addDocument($businessDocumentCRM);
1755 $businessTypeCRM->getIndex()->refresh();
1756
1757
1758
1759 return true;
1760 }
1761
1762 /**
1763 * Sets the password for this user in the databaes after encrypting it
1764 * @param string $password Password to set
1765 * @return boolean
1766 */
1767 public function setPassword($password)
1768 {
1769 // Can't set an empty password
1770 if (trim($password) != '')
1771 {
1772 $this->Password = Nocowboys_User_Business::encryptPassword($password);
1773 return $this->save();
1774 }
1775 }
1776
1777 /**
1778 * Returns the map coordinates for the business
1779 * @return array | NULL
1780 */
1781 public function getMapCoordinates($includeGeneratedCoordinates = false)
1782 {
1783 $markerTable = new Model_DbTable_Marker();
1784 $select = $markerTable->select()
1785 ->where('businessId=?', $this->ID);
1786
1787 if (!$includeGeneratedCoordinates)
1788 {
1789 $select->where('generatedFromAddress = 0');
1790 }
1791
1792 $id = $this->getCacheKeyForMarker();
1793 $results = $markerTable->fetchRowCache($select, NULL, [], false, 8, $id);
1794
1795 unset($markerTable);
1796 return $results;
1797 }
1798
1799 /**
1800 * Sometimes businesses don't want their address or location shown,
1801 * so we can fall back on the coordinates of the suburb if this is
1802 * the case
1803 * @return Model_DbTableRow_Marker|NULL Array of coordinates or NULL if we can't find
1804 * anything
1805 */
1806 public function getPublicMapCoordinates()
1807 {
1808 $coordinates = NULL;
1809
1810 // If the user doesn't mind us using their location details
1811 if (!$this->mapHidden())
1812 {
1813 $coordinates = $this->getMapCoordinates(true);
1814 }
1815
1816 // If there aren't any coordinates, then let's just use their
1817 // suburb
1818 if (is_null($coordinates))
1819 {
1820 $area = $this->getLocationArea();
1821
1822 if (!is_null($area))
1823 {
1824 $coordinates = new stdClass();
1825 $coordinates->Lat = $area->lat;
1826 $coordinates->Lang = $area->long;
1827 }
1828 }
1829
1830 return $coordinates;
1831 }
1832
1833 /**
1834 * Checks if the map has been hidden explicitly by the business
1835 *
1836 * @return boolean True if the user has explictly hidden their map
1837 */
1838 public function mapHidden()
1839 {
1840 if (is_null($this->_mapHidden))
1841 {
1842 $hideMapMeta = $this->getMetaData(Model_DbTableRow_Business::METAKEYHIDEMAP);
1843 $this->_mapHidden = ((!is_null($hideMapMeta)) and ( $hideMapMeta == 1)) ? true : false;
1844 }
1845
1846 return $this->_mapHidden;
1847 }
1848
1849 /**
1850 * Generates map coordintates for a business using their
1851 * physical location data (if set)
1852 *
1853 * @param boolean $force Set to true to override existing location
1854 * data if there are any
1855 */
1856 public function generateMapCoordinates($force = false)
1857 {
1858 // Get the user-set coordinates (using no parameter)
1859 $existingCoordinates = $this->getMapCoordinates();
1860
1861 if ((is_null($existingCoordinates)) or ( $force))
1862 {
1863 // If the business has a suburb set up, let's try with their
1864 // company name and suburb and see where that gets us
1865 $suburb = $this->getLocationArea();
1866
1867 if (!is_null($suburb))
1868 {
1869 $addressToFind = $this->CompanyName.', '.$suburb->Name.', New Zealand';
1870
1871 if ($this->_findAndSaveMapCoordinates($addressToFind))
1872 {
1873 return true;
1874 }
1875 }
1876
1877 // Next, try with their physical address
1878 $physicalAddress = trim($this->getPhysicalAddress());
1879
1880 if (!empty($physicalAddress))
1881 {
1882 $addressToFind = $physicalAddress.', New Zealand';
1883
1884 if ($this->_findAndSaveMapCoordinates($addressToFind))
1885 {
1886 // Hide the map - assume the user doesn't want
1887 // their exact location shown
1888 if ((isset($this->hideAddress)) and ( $this->hideAddress == 1))
1889 {
1890 $this->setMetaData(Model_DbTableRow_Business::METAKEYHIDEMAP, 1);
1891 }
1892 return true;
1893 }
1894 }
1895
1896 // And finally, just their suburb information should do the
1897 // trick
1898 if (!is_null($suburb))
1899 {
1900 $this->setMapCoordinates($suburb->lat, $suburb->long);
1901 return true;
1902 }
1903 }
1904
1905 return false;
1906 }
1907
1908 /**
1909 * Finds the coordinates using the default geolocator
1910 *
1911 * @param string $addressToFind The address to find
1912 * @return boolean True if an address was found and saved, false if not
1913 */
1914 protected function _findAndSaveMapCoordinates($addressToFind)
1915 {
1916 $geoCoder = Nocowboys_Geocode_Abstract::getDefaultGeocoder();
1917
1918 try
1919 {
1920 $coordinates = $geoCoder->findCoordinatesByAddress($addressToFind);
1921
1922 if (is_null($coordinates))
1923 {
1924 return false;
1925 }
1926
1927 $lat = $coordinates['lat'];
1928 $long = $coordinates['long'];
1929
1930 // Check the coordinates are in NZ
1931 if (Model_DbTable_Marker::coordinatesInNewZealand($lat, $long))
1932 {
1933 $this->setMapCoordinates($lat, $long, true);
1934 return true;
1935 }
1936 else
1937 {
1938 return false;
1939 }
1940 }
1941 catch (Exception $ex)
1942 {
1943 return false;
1944 // Do nothing
1945 }
1946 }
1947
1948 /**
1949 * Sets the given map coordinates for this business
1950 *
1951 * @param float $lat Latitude
1952 * @param float $long Longitude
1953 */
1954 public function setMapCoordinates($lat, $long)
1955 {
1956 // If there's no user-set coordinates, or we're forcing the
1957 // overwrite, get any coordinate
1958 $existingCoordinates = $this->getMapCoordinates(true);
1959
1960 if (is_null($existingCoordinates))
1961 {
1962 $markerTable = new Model_DbTable_Marker();
1963 $existingCoordinates = $markerTable->createRow();
1964 $existingCoordinates->BusinessID = $this->ID;
1965 }
1966 else
1967 {
1968 $existingCoordinates = Model_DbTable_Marker::fetchRowByValueStatic('ID', $existingCoordinates->ID);
1969 }
1970
1971 $existingCoordinates->Lat = $lat;
1972 $existingCoordinates->Lang = $long;
1973 $existingCoordinates->generatedFromAddress = 1;
1974
1975 $existingCoordinates->save();
1976 $this->updateLastUpdatedTime();
1977 }
1978
1979 /**
1980 * Gets the logo for the business. Returns false if
1981 * no logo is available, or otherwise returns the image
1982 * to display
1983 * @return string|false
1984 */
1985 public function getLogo()
1986 {
1987 $location = Zend_Registry::get('config')->images->businessLogo->originalLocation;
1988 if ((isset($this->LogoFileName)) and ( trim($this->LogoFileName) != '') and ( file_exists($location . '/' . $this->LogoFileName)))
1989 {
1990 return $this->LogoFileName;
1991 }
1992
1993 return false;
1994 }
1995
1996 /**
1997 * Gets the images assigned to this business
1998 * @return Zend_Db_Table_Rowset_Abstract Set of images
1999 */
2000 public function getImages()
2001 {
2002 if (is_null($this->images))
2003 {
2004 $imageTable = new Model_DbTable_BusinessPic();
2005 $this->images = $imageTable->fetchAll(
2006 $imageTable->select()
2007 ->where('BusinessID = ?', $this->ID)
2008 ->order('display_order DESC')
2009 );
2010 }
2011
2012 return $this->images;
2013 }
2014
2015 /**
2016 * Gets the competitors for this business
2017 * @param int $count Number of competitors to get
2018 * @param boolean $onlyRegistered Set to true to only gets registered competitors
2019 */
2020 public function getCompetitors($count = 4, $onlyRegistered = true)
2021 {
2022 $businessTable = new Model_DbTable_Business();
2023 $totalCompetitorArray = array();
2024 $totalCompetitorIdArray = array();
2025
2026 $categories = $this->getCategoriesCorrect();
2027 $categoryIdArray = array();
2028
2029 foreach ($categories as $category)
2030 {
2031 $categoryIdArray[] = $category->ID;
2032 }
2033
2034 // Start by trying to get categories in the direct area
2035 $businessQuery = $this->getBusinessSearchSelect(array(), $categoryIdArray);
2036 $businessQuery->where('Business.ID != ?', $this->ID);
2037
2038 // Order randomly
2039 $businessQuery->reset(Zend_Db_Select::ORDER);
2040 $businessQuery->order('RAND()');
2041
2042 $competitors = $businessTable->fetchAll($businessQuery);
2043
2044 foreach ($competitors as $competitor)
2045 {
2046 $totalCompetitorArray[] = $competitor;
2047 $totalCompetitorIdArray[] = $competitor->ID;
2048 }
2049
2050 // Check if there is X competitors to show
2051 if (count($totalCompetitorArray) >= $count)
2052 {
2053 return array_slice($totalCompetitorArray, 0, $count);
2054 }
2055
2056 // Start by seeing if there are competitors in the immediate areas
2057 // and categories
2058 $areas = $this->getAreas();
2059 $areaIdArray = array();
2060
2061 foreach ($areas as $area)
2062 {
2063 $areaIdArray[] = $area->ID;
2064 }
2065
2066 $businessQuery = $this->getBusinessSearchSelect($areaIdArray, $categoryIdArray);
2067 $businessQuery->where('Business.ID != ?', $this->ID);
2068
2069 // Don't include competitors previously added
2070 if (count($totalCompetitorIdArray) > 0)
2071 {
2072 $businessQuery->where('Business.ID NOT IN ('.implode(',', $totalCompetitorIdArray).')');
2073 }
2074
2075 // Order randomly
2076 $businessQuery->reset(Zend_Db_Select::ORDER);
2077 $businessQuery->order('RAND()');
2078
2079 $competitors = $businessTable->fetchAll($businessQuery);
2080
2081 foreach ($competitors as $competitor)
2082 {
2083 $totalCompetitorArray[] = $competitor;
2084 $totalCompetitorIdArray[] = $competitor->ID;
2085 }
2086
2087 // Check if there is X competitors to show
2088 if (count($totalCompetitorArray) >= $count)
2089 {
2090 return array_slice($totalCompetitorArray, 0, $count);
2091 }
2092
2093 // If there isn't enough, go through all the child categories and areas
2094 foreach ($areas as $area)
2095 {
2096 $areaIdArray = array_merge($areaIdArray, $area->getChildAreaIDsForSearch());
2097 }
2098
2099 foreach ($categories as $category)
2100 {
2101 $categoryIdArray = array_merge($categoryIdArray, $category->getChildCategoryIDsForSearch());
2102 }
2103
2104 $businessQuery = $this->getBusinessSearchSelect($areaIdArray, $categoryIdArray);
2105 $businessQuery->where('Business.ID != ?', $this->ID);
2106
2107 // Don't include competitors previously added
2108 if (count($totalCompetitorIdArray) > 0)
2109 {
2110 $businessQuery->where('Business.ID NOT IN ('.implode(',', $totalCompetitorIdArray).')');
2111 }
2112
2113 // Order randomly
2114 $businessQuery->reset(Zend_Db_Select::ORDER);
2115 $businessQuery->order('RAND()');
2116
2117 $competitors = $businessTable->fetchAll($businessQuery);
2118
2119 foreach ($competitors as $competitor)
2120 {
2121 $totalCompetitorArray[] = $competitor;
2122 }
2123
2124 return array_slice($totalCompetitorArray, 0, $count);
2125 }
2126
2127 /**
2128 * Determines if the business can receive text messages
2129 * @return boolean
2130 */
2131 public function canReceiveSms()
2132 {
2133 $wantsSms = $this->getMetaData('IsSendText');
2134
2135 if (((!is_null($wantsSms)) and ( $wantsSms == false)) or ( !isset($this->Mobile)) or ( trim($this->Mobile) == ''))
2136 {
2137 return false;
2138 }
2139 else
2140 {
2141 return true;
2142 }
2143 }
2144
2145 /**
2146 * Sends a message via. SMS to this business
2147 * @param string $message Message to send
2148 * @return int Greater than 0 for success, les than 0 for failure
2149 * @throws Exception
2150 */
2151 public function sendSms($message, $text = '')
2152 {
2153 $messageRegex = '/[^'.Nocowboys_Tools::$smsRegexCharacterset.']/';
2154
2155 if (!$this->canReceiveSms())
2156 {
2157 throw new Exception('Trying to send an SMS to a business that has no contact number or doesn\'t want SMS');
2158 }
2159
2160 // Remove the profanities
2161 $message = str_ireplace(Nocowboys_Tools::$profanities, '****', $message);
2162 $message = preg_replace($messageRegex, '', $message);
2163
2164 $smsResponse = Nocowboys_Sms::send($this->Mobile, $message);
2165
2166 if ($smsResponse > 0)
2167 {
2168 // Create a new text message history object
2169 $SMSTable = new Model_DbTable_Nctext();
2170 $newMessage = $SMSTable->createRow();
2171
2172 $newMessage->BusinessID = $this->ID;
2173 $newMessage->Message = $message;
2174 $newMessage->DateSent = Nocowboys_Tools::databaseSafeDateTime();
2175 $newMessage->message_text = $text;
2176 $newMessage->ip_address = Nocowboys_Tools::getUserIp();
2177 $newMessage->save();
2178
2179 // Increase the number of texts sent to this business
2180 $this->TextCount = $this->TextCount + 1;
2181 $this->save();
2182 }
2183
2184 return $smsResponse;
2185 }
2186
2187 /**
2188 * Returns a Zend select object for selecting businesses with all their
2189 * additional details
2190 * @param array $areaIds Array of area IDs to include
2191 * @param array $categoryIds Array of category IDs to include
2192 * @param boolean $includeThisBusinessArea Set to false to not automatically
2193 * include the business' area ID in the query
2194 * @param boolean $onlyRegistered Set to false to include both registered
2195 * and non-registered businesses
2196 * @param integer $count Number of results to request
2197 * @return Zend_Db_Select A Zend select object representing the query
2198 */
2199 public function getBusinessSearchSelect($areaIds, $categoryIds, $includeThisBusinessArea = true, $onlyRegistered = true, $count = 3)
2200 {
2201 $businessTable = new Model_DbTable_Business();
2202
2203 $areaText = implode('" OR BusinessArea.AreaID = "', $areaIds);
2204 $categoryText = implode('" OR BusinessCategory.CategoryID = "', $categoryIds);
2205
2206 $select = $businessTable->select()
2207 ->from('Business', array('DISTINCT(Business.ID)', 'AccountType', 'CompanyName', 'OverrideCustomerPreferred',
2208 'ContactPhone1', 'ContactPhone2', 'EmailAddress', 'Fax', 'LocationAreaID', 'Registered', 'SearchCount',
2209 'TempNegative', 'TempNeutral', 'TempOverall', 'TempPositive', 'URLName', 'businessCount' => '0'))
2210 ->setIntegrityCheck(false)
2211 ->joinInner('BusinessCategory', 'BusinessCategory.BusinessID = Business.ID', array())
2212 ->joinInner('BusinessArea', 'BusinessArea.BusinessID = Business.ID', array())
2213 ->where('Business.IsOnline = 1')
2214 ->where('Business.NoLongerTrade = 0')
2215 ->where('(BusinessCategory.CategoryID = "'.$categoryText.'")')
2216 ->where('isHeadOffice = 0')
2217 ->order('TempOverall DESC')
2218 ->limit($count);
2219
2220 if (($includeThisBusinessArea) and ( !is_null($this->LocationAreaID)) and ( $this->LocationAreaID > 0))
2221 {
2222 $select->where('((BusinessArea.AreaID = "'.$areaText.'") OR (Business.LocationAreaID = '.$this->LocationAreaID.'))');
2223 }
2224 else
2225 {
2226 $select->where('BusinessArea.AreaID = "'.$areaText.'"');
2227 }
2228
2229 if ($onlyRegistered)
2230 {
2231 $select->where('Business.Registered = 1');
2232 }
2233
2234 return $select;
2235 }
2236
2237 public function isRegistered()
2238 {
2239 return ($this->Registered == 1) and ( $this->isTrading() );
2240 }
2241
2242 public function isTrading()
2243 {
2244 return $this->NoLongerTrade != 1;
2245 }
2246
2247 public function isHeadOffice()
2248 {
2249 return $this->isHeadOffice == 1;
2250 }
2251
2252 public function isOnline()
2253 {
2254 return $this->IsOnline != 0;
2255 }
2256
2257 public function isVerified()
2258 {
2259 return $this->Verified == 1;
2260 }
2261
2262 /**
2263 * Checks if business page is hidden for search engines.
2264 *
2265 *
2266 * @return bool
2267 */
2268 public function isHideFromSearchEngines()
2269 {
2270 return $this->isHideFromSearchEngines == Model_DbTableRow_Business::HIDE_FROM_SEARCH_ENGINES;
2271 }
2272
2273 /**
2274 * Checks if business contacts is hidden.
2275 *
2276 *
2277 * @return bool
2278 */
2279 public function isHideBusinessInformation()
2280 {
2281 return $this->isHideBusinessInformation == Model_DbTableRow_Business::HIDE_BUSINESS_INFORMATION;
2282 }
2283
2284 /**
2285 * Checks if business rating is available as recent rating.
2286 *
2287 *
2288 * @return bool
2289 */
2290 public function availableForRecentRating()
2291 {
2292 return $this->available_for_recent_rating == Model_DbTableRow_Business::AVAILABLE_FOR_RECENT_RATING;
2293 }
2294
2295 /**
2296 * Checks if business name is available for list of search results.
2297 *
2298 *
2299 * @return bool
2300 */
2301 public function availableForListOfSearchResult()
2302 {
2303 return Nocowboys_Elastic::getBusinessFromElastic($this->ID) ? true : false;
2304 }
2305
2306 /**
2307 * Checks if jobs is available.
2308 *
2309 *
2310 * @return bool
2311 */
2312 public function isAvailabilityJobs()
2313 {
2314 return $this->availability_jobs == Model_DbTableRow_Business::AVAILABILITY_JOBS_ON;
2315 }
2316
2317 /**
2318 * Set Social Profile URL in Meta Table - TR-003
2319 * @param type $socialKey
2320 * @param type $SocialValue
2321 */
2322 public function setSocialdata($socialKey, $SocialValue)
2323 {
2324 if (trim($SocialValue) != '')
2325 {
2326 $this->setMetaData($socialKey, $SocialValue);
2327 }
2328 else
2329 {
2330 $this->deleteMetaData($socialKey);
2331 }
2332
2333 $this->updateLastUpdatedTime();
2334 }
2335
2336 /**
2337 * Gets the video key for the business, but only if the business is registered.
2338 * At this point, assume the video is a YouTube key, the video string without
2339 * the YouTube URL
2340 * @return string|NULL The YouTube key if it exists, or NULL otherwise
2341 */
2342 public function getVideoKey()
2343 {
2344 if ($this->isRegistered())
2345 {
2346 return $this->getMetaData('video');
2347 }
2348
2349 return NULL;
2350 }
2351
2352 /**
2353 * Gets the website URL for this business if it exists. Adds a protocol if
2354 * none exist
2355 * @return string|NULL The URL if this business has one, or NULL otherwise
2356 */
2357 public function getWebsite()
2358 {
2359 if ((!is_null($this->Website)) and ( trim($this->Website) != ''))
2360 {
2361 return Nocowboys_Tools::confirmUrlHasProtocol($this->Website);
2362 }
2363 else
2364 {
2365 return NULL;
2366 }
2367 }
2368
2369 /**
2370 * Gets the url with the protocol and subdomain removed. Don't use
2371 * this as an actual link - it's intended for display
2372 *
2373 * @return string Cleaned URL
2374 */
2375 public function getWebsiteShortened()
2376 {
2377 $website = $this->getWebsite();
2378
2379 if (is_null($website))
2380 {
2381 return NULL;
2382 }
2383
2384 $website = trim($website, '/');
2385
2386 // If scheme not included, prepend it
2387 if (!preg_match('#^http(s)?://#', $website))
2388 {
2389 $website = 'http://'.$website;
2390 }
2391
2392 $urlParts = parse_url($website);
2393
2394 // Remove www
2395 return preg_replace('/^www\./', '', $urlParts['host']);
2396 }
2397
2398 /**
2399 * Gets the meta description for use in the meta keyword tag
2400 * @return sgring Description to use in the meta tag. Aim for 155 characters
2401 */
2402 public function getMetaDescription()
2403 {
2404 $area = $this->getLocationArea();
2405 $mostPopularCategory = $this->getPrimaryCategory(true);
2406
2407 // Use the business description if possible
2408 $returnString = trim($this->CompanyName);
2409
2410 if ((!is_null($area)) and ( !is_null($mostPopularCategory)))
2411 {
2412 $returnString .= ' are '.strtolower($mostPopularCategory->Name).' in '.$area->Name.', New Zealand';
2413 }
2414 else
2415 if (!is_null($area))
2416 {
2417 $returnString .= ' are in '.$area->Name.', New Zealand';
2418 }
2419 else
2420 if (!is_null($mostPopularCategory))
2421 {
2422 $returnString .= ' are '.strtolower($mostPopularCategory->Name);
2423 }
2424 else
2425 {
2426 $returnString .= ' are on NoCowboys';
2427 }
2428
2429 $returnString .= '. ';
2430
2431 $aboutUs = trim(htmlspecialchars(strip_tags(stripslashes($this->AboutUs))));
2432 $hasPersonalisedContent = false;
2433
2434 if ($aboutUs != '')
2435 {
2436 $returnString .= str_replace(array("\r", "\n"), '', $aboutUs);
2437 $hasPersonalisedContent = true;
2438 }
2439 else
2440 {
2441 $whatWeDo = trim(htmlspecialchars(strip_tags(stripslashes($this->WhatWeDo))));
2442
2443 if ($whatWeDo != '')
2444 {
2445 $returnString .= '. '.str_replace(array("\r", "\n"), '', $whatWeDo);
2446 $hasPersonalisedContent = true;
2447 }
2448 }
2449
2450 if (!$hasPersonalisedContent)
2451 {
2452 $returnString .= 'Read ratings from other kiwis on NoCowboys.co.nz.';
2453 }
2454
2455 $tools = new Nocowboys_Tools();
2456 $returnString = $tools->trimText($returnString, 300, false);
2457
2458 return trim($returnString);
2459 }
2460
2461 /**
2462 * Gets the title for the business. Use this to improve SEO
2463 *
2464 * @return string String to use as the title
2465 */
2466 public function getTitle()
2467 {
2468 $title = $this->CompanyName;
2469 $area = $this->getLocationArea();
2470 $mostPopularCategory = $this->getPrimaryCategory(true);
2471
2472 if ((!is_null($area)) or ( !is_null($mostPopularCategory)))
2473 {
2474 $title .= ' | ';
2475
2476 if (!is_null($mostPopularCategory))
2477 {
2478 $title .= $mostPopularCategory->Name.' ';
2479 }
2480
2481 if (!is_null($area))
2482 {
2483 $title .= $area->Name;
2484 }
2485 }
2486
2487 return trim($title);
2488 }
2489
2490 /**
2491 * Gets suitable copy for an H2 tag
2492 *
2493 * @return string H2 tag
2494 */
2495 public function getH2()
2496 {
2497 $h2Content = '';
2498 $primaryCategory = $this->getPrimaryCategory(true);
2499 $area = $this->getLocationArea();
2500
2501 if ((!is_null($area)) and ( !is_null($primaryCategory)))
2502 {
2503 $h2Content = $primaryCategory->Name.' in '.$area->Name;
2504 }
2505 else
2506 if (!is_null($primaryCategory))
2507 {
2508 $h2Content = $primaryCategory->Name;
2509 }
2510 else
2511 if (!is_null($area))
2512 {
2513 $h2Content = $area->Name;
2514 }
2515
2516 return $h2Content;
2517 }
2518
2519 /**
2520 * Gets the primary category for this business. If the user hasn't
2521 * selected one, then we select the most popular category out of their
2522 * set categories
2523 *
2524 * @param boolean $getAlternative If no primary category is set by
2525 * the business, pick the most popular category from their other
2526 * selected categories
2527 * @return Model_DbTableRow_Category
2528 */
2529 public function getPrimaryCategory($getAlternative = false)
2530 {
2531 if (!is_null($this->primaryCategoryId))
2532 {
2533 return Model_DbTable_Category::fetchRowByValueStatic('ID', $this->primaryCategoryId);
2534 }
2535 else
2536 {
2537 if ($getAlternative)
2538 {
2539 return $this->getMostPopularCategory();
2540 }
2541 else
2542 {
2543 return NULL;
2544 }
2545 }
2546 }
2547
2548 /**
2549 * Gets the most popular category set for this business
2550 *
2551 * @param integer $popularPosition How far down the list of popular
2552 * categories we want to go before we return that category. Position 1
2553 * is the most popular category. Position 2 is the second and so on.
2554 * If there's no popular category for the number given, the most
2555 * popular category is returned
2556 * @return NULL|Model_DbTableRow_Category The most popular category
2557 * this business has, or NULL if no categories are set up
2558 */
2559 public function getMostPopularCategory($popularPosition = 1)
2560 {
2561 $businessCategories = $this->getCategoriesCorrect();
2562 $mostPopularCategories = [];
2563
2564 foreach (Model_DbTable_Category::$mostPopularCategoryIds as $popularId)
2565 {
2566 foreach ($businessCategories as $category)
2567 {
2568 if ($popularId == $category->ID)
2569 {
2570 $mostPopularCategories[$category->ID] = $category;
2571 }
2572 }
2573 }
2574
2575 $popularCategoryIds = array_keys($mostPopularCategories);
2576
2577 // If there is enough categories to cover the position we want,
2578 // grab it
2579 if (count($mostPopularCategories) >= $popularPosition)
2580 {
2581 return $mostPopularCategories[$popularCategoryIds[$popularPosition - 1]];
2582 }
2583 else
2584 // Otherwise, default to the top category
2585 if (count($mostPopularCategories) > 0)
2586 {
2587 return $mostPopularCategories[$popularCategoryIds[0]];
2588 }
2589 else
2590 {
2591 return NULL;
2592 }
2593 }
2594
2595 /**
2596 * Get the area closest to the business
2597 *
2598 * @param int $closestAreaPosition
2599 * @return Model_DbTableRow_Area|NULL
2600 */
2601 public function getClosestArea($closestAreaPosition = 1)
2602 {
2603 $location = $this->getLocationArea();
2604 if ($location)
2605 {
2606 $areas = $this->getAreas();
2607 if ($areas)
2608 {
2609 $distances = array();
2610 foreach ($areas as $area)
2611 {
2612 $distance = (
2613 (acos(
2614 cos($location->lat * pi() / 180)
2615 * cos($area->lat * pi() / 180)
2616 * cos(($location->long - $area->long) * pi() / 180)
2617 + sin($location->lat * pi() / 180)
2618 * sin($area->lat * pi() / 180)
2619 ) * 180 / pi()
2620 ) * 60 * 1.1515
2621 ) * 1.609344;
2622 $distances[$distance] = $area;
2623 }
2624
2625 if (count($distances))
2626 {
2627 ksort($distances);
2628 $closestAreas = array_values($distances);
2629
2630 if ($closestAreaPosition > 0)
2631 {
2632 $areaPosition = $closestAreaPosition % count($closestAreas);
2633 return $closestAreas[$areaPosition];
2634 }
2635
2636 return $closestAreas[0];
2637 }
2638 }
2639 }
2640
2641 return $location;
2642 }
2643
2644 /**
2645 * Deletes the metadata for this business if it exists
2646 * @param string $metaKey The key of the value for this business to delete
2647 * @return boolean
2648 */
2649 public function deleteMetaData($metaKey)
2650 {
2651 $existingMetaDataObject = $this->getMetaDataObject();
2652
2653 if (is_null($existingMetaDataObject))
2654 {
2655 return true;
2656 }
2657
2658 $metaData = json_decode($existingMetaDataObject->metaValue, true);
2659
2660 if (isset($metaData[$metaKey]))
2661 {
2662 unset($metaData[$metaKey]);
2663
2664 if (empty($metaData))
2665 {
2666 $existingMetaDataObject->delete();
2667 }
2668 else
2669 {
2670 $existingMetaDataObject->metaValue = json_encode($metaData);
2671 $existingMetaDataObject->save();
2672 }
2673 }
2674
2675 return true;
2676 }
2677
2678 /**
2679 * Generates a unique ID used to log the user in automatically if they asked for it
2680 * @return string
2681 */
2682 public function generateSessionId()
2683 {
2684 $metaTable = new Model_DbTable_BusinessMeta();
2685
2686 // Create an ID and check if its being used elsewhere
2687 $sessionID = $metaTable->createRandomString(20);
2688
2689 $sessionIdCheck = $metaTable
2690 ->select()
2691 ->where('metaKey = "'.Model_DbTable_Business::sessionIdName.'"')
2692 ->where($metaTable->quoteInto('metaValue = ?', $sessionID));
2693
2694 // If it is being used, keep looping until we find one that isn't
2695 while (!is_null($metaTable->fetchRow($sessionIdCheck)))
2696 {
2697 $sessionID = $metaTable->createRandomString(15);
2698
2699 $sessionIdCheck = $metaTable
2700 ->select()
2701 ->where('metaKey = "'.Model_DbTable_Business::sessionIdName.'"')
2702 ->where($metaTable->quoteInto('metaValue = ?', $sessionID));
2703 }
2704
2705 // Now save the ID for the business
2706 // Encrypt it first though
2707 $this->setMetaData(Model_DbTable_Business::sessionIdName, Nocowboys_User_Business::encryptPassword($sessionID));
2708
2709 return $sessionID;
2710 }
2711
2712 /**
2713 * Removes the unique ID for this user if there is one
2714 * @return string
2715 */
2716 public function removeSessionId()
2717 {
2718 $this->deleteMetaData(Model_DbTable_Business::sessionIdName);
2719 }
2720
2721 /**
2722 * Checks if the user is close to having their package expire. If so, send
2723 * the reminders
2724 */
2725 public function sendPackageExpiryReminder()
2726 {
2727 $registrationExpiry = $this->getRegistrationExpiryDate();
2728 $currentPackage = $this->getCurrentPackage();
2729 $config = Zend_Registry::get('config');
2730
2731 // If the current package is empty, then default
2732 if (is_null($currentPackage))
2733 {
2734 $defaultProductId = $config->website->defaultProductId;
2735 $packageTable = new Model_DbTable_Product();
2736 $currentPackage = $packageTable->fetchRowByValue('ID', $defaultProductId);
2737
2738 if (is_null($currentPackage))
2739 {
2740 throw new Exception('Default package does not exist');
2741 }
2742 }
2743
2744 // Check if the package has passed, or is near, expiry. This really should
2745 // be done in a more OO way, but the additional work and setup isn't worth
2746 // it at this point. Any additional product-specific code really should be
2747 // put into different product objects and make use of the factory pattern
2748 // to load
2749 }
2750
2751 /**
2752 * Gets all the child businesses for this business, assuming its a Head
2753 * Office. It also sets up the colours for the businesses and stores them
2754 * in the session for future use
2755 * @return Zend_Db_Table_Rowset_Abstract Businesses that are the child
2756 * businesses
2757 */
2758 public function getHeadOfficeBusinesses()
2759 {
2760 if ($this->isHeadOffice != 1)
2761 {
2762 return NULL;
2763 }
2764
2765 if (is_null($this->headOfficeBusinesses))
2766 {
2767 $headOfficeSession = new Zend_Session_Namespace(Nocowboys_Tools::SESSIONIDHEADOFFICE);
2768 $headOfficeSession->businessColours = array();
2769
2770 $businessTable = new Model_DbTable_Business();
2771
2772 $childBusinessSelect = $businessTable->select()
2773 ->setIntegrityCheck(false)
2774 ->from('Business')
2775 ->joinInner('headOfficeBusiness', 'headOfficeBusiness.childBusinessId = Business.ID', array())
2776 ->where('headOfficeBusiness.headOfficeBusinessId = '.$this->ID)
2777 ->order('CompanyName ASC');
2778
2779 $this->headOfficeBusinesses = $businessTable->fetchAll($childBusinessSelect);
2780 $colourCounter = 0;
2781 $colourCount = count(Nocowboys_Tools::$colours);
2782
2783 // Loop through the businesses and assign colours
2784 foreach ($this->headOfficeBusinesses as $business)
2785 {
2786 $headOfficeSession->businessColours[$business->ID] = Nocowboys_Tools::$colours[$colourCounter];
2787
2788 if ($colourCounter >= $colourCount - 1)
2789 {
2790 $colourCounter = 0;
2791 }
2792 else
2793 {
2794 $colourCounter++;
2795 }
2796 }
2797 }
2798
2799 return $this->headOfficeBusinesses;
2800 }
2801
2802 /**
2803 * Gets all the child business IDs for this business, assuming its a Head
2804 * Office
2805 * @return array Array of the child business IDs
2806 */
2807 public function getHeadOfficeBusinessIDs()
2808 {
2809 if (is_null($this->headOfficeBusinessIDs))
2810 {
2811 $childBusinesses = $this->getHeadOfficeBusinesses();
2812 $businessIds = array();
2813
2814 foreach ($childBusinesses as $childBusiness)
2815 {
2816 $businessIds[] = $childBusiness->ID;
2817 }
2818
2819 $this->headOfficeBusinessIDs = $businessIds;
2820 }
2821
2822 return $this->headOfficeBusinessIDs;
2823 }
2824
2825 /**
2826 * Gets any businesses (Head Offices) that have this business as a child
2827 * business
2828 * @return Zend_Db_Table_Rowset_Abstract Head Office business objects
2829 */
2830 public function getHeadOffices()
2831 {
2832 if (is_null($this->headOffices))
2833 {
2834 $businessTable = new Model_DbTable_Business();
2835 $headOfficeBusinessSelect = $businessTable->select()
2836 ->setIntegrityCheck(false)
2837 ->from('Business')
2838 ->joinInner('headOfficeBusiness', 'headOfficeBusiness.headOfficeBusinessId = Business.ID', array())
2839 ->where('headOfficeBusiness.childBusinessId = '.$this->ID);
2840
2841 $this->headOffices = $businessTable->fetchAll($headOfficeBusinessSelect);
2842 }
2843
2844 return $this->headOffices;
2845 }
2846
2847 /**
2848 * Sets the businesses assigned to this HO
2849 * @param array $businessIds Array of IDs for the businesses assigned to
2850 * this HO
2851 * @throws Exception If an array is not passed in
2852 */
2853 public function setHeadOfficeBusinesses($businessIds)
2854 {
2855 if (!is_array($businessIds))
2856 {
2857 throw new Exception('Array expected when setting home office businesses');
2858 }
2859
2860 $headOfficeTable = new Model_DbTable_HeadOfficeBusiness();
2861 $existingLinks = $headOfficeTable->fetchAllByValue('headOfficeBusinessId', $this->ID);
2862
2863 foreach ($existingLinks as $businessToDelete)
2864 {
2865 $businessToDelete->delete();
2866 }
2867
2868 foreach ($businessIds as $newBusinessId)
2869 {
2870 $newLink = $headOfficeTable->createRow();
2871 $newLink->headOfficeBusinessId = $this->ID;
2872 $newLink->childBusinessId = $newBusinessId;
2873 $newLink->save();
2874 }
2875 }
2876
2877 /**
2878 * Sets the categories for this business using the given array of category
2879 * IDs
2880 * @param array $categoryIds Array of category IDs to set for this business
2881 * @throws Exception If an array is not passed in
2882 */
2883 public function setCategoryIds($categoryIds)
2884 {
2885 if (!is_array($categoryIds))
2886 {
2887 throw new Exception('Array expected when setting business categories');
2888 }
2889
2890 // Load the categories that exist and then delete them
2891 $businessCategoryTable = new Model_DbTable_BusinessCategory();
2892 $allLinks = $businessCategoryTable->fetchAll('BusinessID = '.$this->ID);
2893
2894 foreach ($allLinks as $linkToDelete)
2895 {
2896 $linkToDelete->delete();
2897 }
2898
2899 // Add the new categories
2900 foreach ($categoryIds as $categoryID)
2901 {
2902 $newLink = $businessCategoryTable->createRow();
2903 $newLink->BusinessID = $this->ID;
2904 $newLink->CategoryID = $categoryID;
2905 $newLink->save();
2906 }
2907
2908 // Delete any cache relating to the categories
2909 Nocowboys_Db_Table_Cache::deleteCacheKey(self::CACHE_KEY_PREFIX_CATEGORIES.$this->ID);
2910
2911 $this->denormaliseCategoryIds();
2912 $this->save(true, true);
2913
2914 return true;
2915 }
2916
2917 /**
2918 * Goes and gets the category IDs for this business and sets them in
2919 * the DB. It gets the parent category IDs for those categories too
2920 * so we don't need to do additional queries
2921 *
2922 */
2923 public function denormaliseCategoryIds()
2924 {
2925 $businessCategories = $this->getCategoriesCorrect();
2926 $allCategoryIds = [];
2927
2928 $primaryCategory = $this->getPrimaryCategory(true);
2929 if (!is_null($primaryCategory))
2930 {
2931 $allCategoryIds[] = $primaryCategory->ID;
2932 }
2933
2934 foreach ($businessCategories as $category)
2935 {
2936 if (!in_array($category->ID, $allCategoryIds))
2937 {
2938 $allCategoryIds[] = $category->ID;
2939 }
2940
2941 $allChildCategories = explode(',', $category->parentCategoryIds);
2942 $allCategoryIds += $allChildCategories;
2943 }
2944
2945 $this->categoryIds = implode(',', $allCategoryIds);
2946 }
2947
2948 /**
2949 * Sets the associations for this business using the given array of association
2950 * IDs
2951 * @param array $associationIds Array of association IDs to set for this business
2952 * @throws Exception If an array is not passed in
2953 */
2954 public function setAssociationIds($associationIds)
2955 {
2956 if (!is_array($associationIds))
2957 {
2958 throw new Exception('Array expected when setting business categories');
2959 }
2960
2961 // Load the associations that exist and then delete them
2962 $associationTable = new Model_DbTable_BusinessAssociation();
2963 $allLinks = $associationTable->fetchAll('businessId = '.$this->ID);
2964
2965 foreach ($allLinks as $linkToDelete)
2966 {
2967 $linkToDelete->delete();
2968 }
2969
2970 // Add the new associations
2971 foreach ($associationIds as $associationId)
2972 {
2973 $newLink = $associationTable->createRow();
2974 $newLink->businessId = $this->ID;
2975 $newLink->associationId = $associationId;
2976 $newLink->save();
2977 }
2978
2979 $this->save(true, true);
2980
2981 return true;
2982 }
2983
2984 /**
2985 * Gets the associations for this business
2986 * @return Zend_Db_Table_Rowset_Abstract Associations for this business
2987 */
2988 public function getAssociations()
2989 {
2990 $associationTable = new Model_DbTable_Association();
2991 $associationSelect = $associationTable->select()
2992 ->from('association')
2993 ->setIntegrityCheck(false)
2994 ->joinInner('businessAssociation', 'association.ID = businessAssociation.associationId', array())
2995 ->where('businessAssociation.businessId = ?', $this->ID);
2996
2997 $result = $associationTable->fetchAll($associationSelect);
2998
2999 unset($associationTable);
3000 return $result;
3001 }
3002
3003 /**
3004 * Sets the areas for this business using the given array of area
3005 * IDs
3006 * @param array $areaIds Array of area IDs to set for this business
3007 * @throws Exception If an array is not passed in
3008 */
3009 public function setAreaIds($areaIds)
3010 {
3011 if (!is_array($areaIds))
3012 {
3013 throw new Exception('Array expected when setting business areas');
3014 }
3015
3016 // Load the areas that exist and then delete them
3017 $businessAreaTable = new Model_DbTable_BusinessArea();
3018 $allLinks = $businessAreaTable->fetchAll('BusinessID = '.$this->ID);
3019
3020 $areaTable = new Model_DbTable_Area();
3021 $areaLinkTable = new Model_DbTable_AreaLink();
3022
3023 $areaTableSelect = $areaTable->select()
3024 ->setIntegrityCheck(false)
3025 ->from(['a' => $areaTable->getTableName()], ['ID', 'Name'])
3026 ->joinLeft(['al' => $areaLinkTable->getTableName()], 'al.ChildAreaID = a.ID', ['ParentAreaID'])
3027 ->joinLeft(
3028 ['alp' => $areaTable->getTableName()],
3029 'alp.ID = al.ParentAreaID',
3030 ['Name AS ParentAreaName']
3031 )
3032 ->where('al.ParentAreaID IN (?)',
3033 new Zend_Db_Expr('SELECT ID FROM nocowboys.Area WHERE IsParentArea = 1')
3034 )
3035 ->orWhere('a.IsParentArea = ?', 1)
3036 ->group('a.ID')
3037 ->order('ParentAreaName ASC')
3038 ->order('a.Name ASC');
3039 $majorAreas = $areaTable->fetchAll($areaTableSelect);
3040
3041 $majorAreasIds = [];
3042 foreach ($majorAreas as $majorArea) {
3043 $majorAreasIds[] = $majorArea->ID;
3044 }
3045
3046 foreach ($allLinks as $linkToDelete)
3047 {
3048 if(!in_array($linkToDelete->AreaID, $majorAreasIds)) {
3049 $linkToDelete->delete();
3050 }
3051 }
3052 // Add the new categories
3053 foreach ($areaIds as $areaID)
3054 {
3055 $link = $businessAreaTable->fetchAll('BusinessID = ' . $this->ID . ' AND AreaID = ' . $areaID);
3056
3057 if (!$link->count()) {
3058 $newLink = $businessAreaTable->createRow();
3059 $newLink->BusinessID = $this->ID;
3060 $newLink->AreaID = $areaID;
3061 $newLink->save();
3062 }
3063 }
3064
3065 // Delete any cache relating to the categories
3066 Nocowboys_Db_Table_Cache::deleteCacheKey(self::CACHE_KEY_PREFIX_AREAS.$this->ID);
3067
3068 $this->save(true, true);
3069
3070 return true;
3071 }
3072
3073 /**
3074 * Sends an email to the given user using the pre-populated email content
3075 * the business has set up
3076 * @param string $recipientName Name of the recipient
3077 * @param string $recipientEmailAddress Email address of the recipient
3078 * @param $ratingValue Value of the rating (between 0 and 100)
3079 * @param boolean $testEmail Set to true to ignore the active check
3080 */
3081 public function sendAutomatedRatingEmail($recipientName, $recipientEmailAddress, $ratingValue, $testEmail = false)
3082 {
3083 // Make sure we have all the settings we need
3084 $emailContent = $this->getMetaData(self::METAKEYAUTOMATEDEMAILSCONTENT);
3085 $emailSubject = $this->getMetaData(self::METAKEYAUTOMATEDEMAILSSUBJECT);
3086 $canSend = $this->getMetaData(self::METAKEYAUTOMATEDEMAILSACTIVE);
3087 $ratingCutoff = $this->getMetaData(self::METAKEYAUTOMATEDEMAILSCUTOFF);
3088
3089 // Current business gets priority
3090 if ((($canSend == 1) and ( $ratingValue >= $ratingCutoff)) or ( $testEmail))
3091 {
3092 if ((is_null($emailContent)) or ( is_null($emailSubject)))
3093 {
3094 throw new Exception('No content or subject set up for the business automated email');
3095 }
3096
3097 $emailContent = str_replace('##email##', $recipientEmailAddress, $emailContent);
3098 $emailContent = str_replace('##name##', $recipientName, $emailContent);
3099
3100 return Nocowboys_Email::sendEmail($recipientEmailAddress, $emailSubject, 'businesses/automatedRating', array('content' => $emailContent));
3101 }
3102 // And backup is for the head office, if there is one
3103 else
3104 {
3105 $headOffices = $this->getHeadOffices();
3106
3107 foreach ($headOffices as $headOffice)
3108 {
3109 return $headOffice->sendAutomatedRatingEmail($recipientName, $recipientEmailAddress, $ratingValue, $testEmail);
3110 }
3111 }
3112
3113 return false;
3114 }
3115
3116 /**
3117 * Sends an email to the business alerting them of a new rating
3118 * @param Model_DbTableRow_Rating $rating Rating object to send the email for
3119 * @param $receivingBusinessId The ID of the business that ACTUALLY received
3120 * the rating
3121 */
3122 public function sendRatingNotificationEmail(Model_DbTableRow_Rating $rating, $receivingBusinessId = NULL)
3123 {
3124 $ratingValue = $rating->calculateRating();
3125 $raterName = $rating->RaterFirstName;
3126
3127 if ($this->RatingNotification == 1)
3128 {
3129 // Check if there's a rating limit set
3130 $notificationLevel = $this->getMetaData(self::METAKEYRATINGNOTIFICATIONLEVEL);
3131 $send = false;
3132
3133 // Send all ratings
3134 if (is_null($notificationLevel) or ( $notificationLevel == 1))
3135 {
3136 $send = true;
3137 }
3138 else
3139 {
3140 // Check to make sure the rating is below the threshold
3141 $negativeCutoff = $this->getMetaData(self::METAKEYNEGATIVERATINGCUTOFF);
3142
3143 if ($ratingValue <= $negativeCutoff)
3144 {
3145 $send = true;
3146 }
3147 }
3148
3149 // If we should send the email, do so
3150 if ($send)
3151 {
3152 $config = Zend_Registry::get('config');
3153
3154 if (!is_null($receivingBusinessId))
3155 {
3156 $businessTable = new Model_DbTable_Business();
3157 $receivingBusiness = $businessTable->fetchRowByValue('ID', $receivingBusinessId);
3158
3159 $emailParameters = array();
3160 $emailParameters['businessName'] = $receivingBusiness->CompanyName;
3161 $emailParameters['ratingValue'] = $ratingValue;
3162 $emailParameters['raterName'] = $raterName;
3163 $emailParameters['tradesPerson'] = $rating->TradesmanName;
3164 $emailParameters['comment'] = $rating->Comment;
3165 $emailParameters['unsubscribeLink'] = TEMP_DOMAIN.$this->ID.'/rating-opt-out';
3166 $emailParameters['viewBusinessLink'] = TEMP_DOMAIN.$receivingBusiness->getURI(false).'#ratings';
3167
3168 $this->sendEmail('New rating for one of your businesses',
3169 'businesses/newRatingNotificationHeadOffice', $emailParameters, $layout = 'email',
3170 $overrideFromAddress = NULL, $overrideFromName = NULL
3171 );
3172 }
3173 else
3174 {
3175 $emailParameters = array();
3176 $emailParameters['businessName'] = $this->CompanyName;
3177 $emailParameters['ratingValue'] = $ratingValue;
3178 $emailParameters['raterName'] = $raterName;
3179 $emailParameters['unsubscribeLink'] = TEMP_DOMAIN.$this->ID.'/rating-opt-out';
3180 $emailParameters['viewBusinessLink'] = TEMP_DOMAIN.$this->getURI(false).'#ratings';
3181 $emailParameters['nocowboysSiteLink'] = $config->domain;
3182
3183 $this->sendEmail('You have received a new review', 'businesses/newRatingNotification',
3184 $emailParameters, $layout = 'email',
3185 $overrideFromAddress = NULL, $overrideFromName = NULL
3186 );
3187 }
3188 }
3189 }
3190
3191 // Now do the same for all the head offices, if there are any
3192 $headOffices = $this->getHeadOffices();
3193
3194 foreach ($headOffices as $headOffice)
3195 {
3196 $headOffice->sendRatingNotificationEmail($rating, $this->ID);
3197 }
3198 }
3199
3200 /**
3201 * Returns the URI for this business' dashboard
3202 * @return string URI for the current business' dashboard
3203 */
3204 public function getDashboardUri()
3205 {
3206 if ($this->isHeadOffice == 1)
3207 {
3208 $homeUrl = '/business/head-office';
3209 }
3210 else
3211 {
3212 $homeUrl = '/business';
3213 }
3214
3215 return $homeUrl;
3216 }
3217
3218 /**
3219 * Gets the rating values for each month
3220 * @return Zend_Db_Table_Rowset_Abstract A collection of months with the
3221 * associated number of ratings and their score
3222 */
3223 public function getMonthlyRatings()
3224 {
3225 $ratingTable = new Model_DbTable_Rating();
3226 $ratingSelect = $ratingTable->select()
3227 ->from('Rating', array('monthlyTotal' => '(SUM(`RankCommunication`+`RankValue`+`RankReliability`+`RankQuality`)/4)',
3228 'monthDate' => 'CONCAT_WS("-", DATE_FORMAT(`RankDate`, "%m"), DATE_FORMAT(`RankDate`, "%Y"))',
3229 'ratingCount' => 'COUNT("ID")',
3230 'RankDate'))
3231 ->where('Rating.Locked <> 1')
3232 ->where('Rating.Hidden = 0')
3233 ->where('Rating.isSpam = 0')
3234 ->having('ratingCount > 0')
3235 ->group('monthDate')
3236 ->order('RankDate DESC');
3237
3238 if ($this->isHeadOffice == 1)
3239 {
3240 $ratingSelect->where('BusinessID IN ('.implode(',', $this->getHeadOfficeBusinessIDs()).')');
3241 }
3242 else
3243 {
3244 $ratingSelect->where('BusinessID = '.$this->ID);
3245 }
3246
3247 return $ratingTable->fetchAll($ratingSelect);
3248 }
3249
3250 /**
3251 * Gets the jobs this business is interested in for all the available
3252 * months
3253 * @return Zend_Db_Table_Rowset_Abstract A collection of months with the
3254 * associated number of jobs the business has shown interest in
3255 */
3256 public function getMonthlyJobInterests()
3257 {
3258 $interestTable = new Model_DbTable_BusinessInterestedInJob();
3259 $interestSelect = $interestTable->select()
3260 ->from('BusinessInterestedinJob', array('jobCount' => 'COUNT(BusinessInterestedinJob.ID)',
3261 'monthDate' => 'CONCAT_WS("-", DATE_FORMAT(DateAdded, "%m"), DATE_FORMAT(DateAdded, "%Y"))'))
3262 //->where('BusinessID = '.$this->ID)
3263 ->where('IsQuoteSent = 1 OR IsQuestionAsked = 1')
3264 ->having('jobCount > 0')
3265 ->group('monthDate')
3266 ->order('DateAdded DESC');
3267
3268 if ($this->isHeadOffice == 1)
3269 {
3270 $interestSelect->where('BusinessID IN ('.implode(',', $this->getHeadOfficeBusinessIDs()).')');
3271 }
3272 else
3273 {
3274 $interestSelect->where('BusinessID = '.$this->ID);
3275 }
3276
3277 return $interestTable->fetchAll($interestSelect);
3278 }
3279
3280 /**
3281 * Gets the positive ratings for all the businesses this head office manages
3282 * @return integer
3283 */
3284 public function headOfficeGetPositiveRatings()
3285 {
3286 $businessIds = $this->getHeadOfficeBusinessIDs();
3287 $cutoff = $this->getMetaData(self::METAKEYPOSITIVERATINGCUTOFF);
3288
3289 if (is_null($cutoff))
3290 {
3291 $cutoff = Nocowboys_Tools::$ratingPositiveCutoff;
3292 }
3293
3294 $ratingTable = new Model_DbTable_Rating();
3295 $ratingSelect = $ratingTable->select()
3296 ->setIntegrityCheck(false)
3297 ->from('Rating')
3298 ->where('Rating.BusinessID IN ('.implode(',', $businessIds).')')
3299 ->where('((`RankCommunication`+`RankValue`+`RankReliability`+`RankQuality`)/4) >= '.$cutoff)
3300 ->where('Rating.Locked <> 1')
3301 ->where('Rating.Hidden = 0')
3302 ->where('Rating.isSpam = 0')
3303 ->where('Rating.NotUsedBefore = 0');
3304
3305 return $ratingTable->fetchAll($ratingSelect);
3306 }
3307
3308 /**
3309 * Gets the negative ratings for all the businesses this head office manages
3310 * @return integer
3311 */
3312 public function headOfficeGetNegativeRatings()
3313 {
3314 $businessIds = $this->getHeadOfficeBusinessIDs();
3315 $cutoff = $this->getMetaData(self::METAKEYNEGATIVERATINGCUTOFF);
3316
3317 if (is_null($cutoff))
3318 {
3319 $cutoff = Nocowboys_Tools::$ratingNegativeCutoff;
3320 }
3321
3322 $ratingTable = new Model_DbTable_Rating();
3323 $ratingSelect = $ratingTable->select()
3324 ->setIntegrityCheck(false)
3325 ->from('Rating')
3326 ->where('Rating.BusinessID IN ('.implode(',', $businessIds).')')
3327 ->where('((`RankCommunication`+`RankValue`+`RankReliability`+`RankQuality`)/4) <= '.$cutoff)
3328 ->order('RankDate DESC')
3329 ->where('Rating.Locked <> 1')
3330 ->where('Rating.Hidden = 0')
3331 ->where('Rating.isSpam = 0')
3332 ->where('Rating.NotUsedBefore = 0');
3333
3334 return $ratingTable->fetchAll($ratingSelect);
3335 }
3336
3337 /**
3338 * Gets the average of ratings for all the Home Office businesses
3339 * @return float
3340 */
3341 public function headOfficeGetRatingAverage()
3342 {
3343 $businessIds = $this->getHeadOfficeBusinessIDs();
3344
3345 $ratingTable = new Model_DbTable_Rating();
3346 $ratingSelect = $ratingTable->select()
3347 ->from('Rating', array('ratingAverage' => '(SUM(`RankCommunication`+`RankValue`+`RankReliability`+`RankQuality`)/4) / COUNT("ID")'))
3348 ->where('Rating.BusinessID IN ('.implode(',', $businessIds).')')
3349 ->where('Rating.Locked <> 1')
3350 ->where('Rating.Hidden = 0')
3351 ->where('Rating.isSpam = 0')
3352 ->where('Rating.NotUsedBefore = 0');
3353
3354 $result = $ratingTable->fetchRow($ratingSelect);
3355
3356 return $result->ratingAverage;
3357 }
3358
3359 /**
3360 * Gets the number of ratings left in the past month
3361 * @return integer
3362 */
3363 public function getPastMonthsRatings($numberOfMonths = 1)
3364 {
3365 $ratingTable = new Model_DbTable_Rating();
3366 $ratingSelect = $ratingTable->select()
3367 ->from('Rating')
3368 ->where('Rating.RankDate >= "'.Nocowboys_Tools::databaseSafeDateTime(strtotime('-'.$numberOfMonths.' months')).'"')
3369 ->where('Rating.Locked <> 1')
3370 ->where('Rating.Hidden = 0')
3371 ->where('Rating.isSpam = 0')
3372 ->where('Rating.NotUsedBefore = 0');
3373
3374 if ($this->isHeadOffice == 1)
3375 {
3376 $ratingSelect->where('Rating.BusinessID IN ('.implode(',', $this->getHeadOfficeBusinessIDs()).')');
3377 }
3378 else
3379 {
3380 $ratingSelect->where('BusinessID = '.$this->ID);
3381 }
3382
3383 return $ratingTable->fetchAll($ratingSelect);
3384 }
3385
3386 /**
3387 * Gets all the ratings for this head office
3388 * @return Zend_Db_Table_Rowset_Abstract
3389 */
3390 public function headOfficeGetAllRatings()
3391 {
3392 if (is_null($this->headOfficeRatings))
3393 {
3394 $businessIds = $this->getHeadOfficeBusinessIDs();
3395
3396 $ratingTable = new Model_DbTable_Rating();
3397 $ratingSelect = $ratingTable->select()
3398 ->setIntegrityCheck(false)
3399 ->from('Rating')
3400 ->joinInner('Business', 'Rating.BusinessID = Business.ID', array('businessName' => 'CompanyName'))
3401 ->where('Rating.BusinessID IN ('.implode(',', $businessIds).')')
3402 ->where('Rating.Hidden = 0')
3403 //->where('Rating.Locked = 0')// OR Rating.RankDate <= "'.Nocowboys_Tools::databaseSafeDateTime(Model_DbTable_Rating::getUnauthenticatedRatingCutoff()).'"')
3404 ->where('Rating.isSpam = 0')
3405 ->order('Rating.RankDate DESC');
3406
3407 $this->headOfficeRatings = $ratingTable->fetchAll($ratingSelect);
3408 }
3409
3410 return $this->headOfficeRatings;
3411 }
3412
3413 /**
3414 * Gets the jobs this business has shown interest in
3415 * @return Zend_Db_Table_Rowset_Abstract Rowet of jobs the business has
3416 * shown interest in
3417 */
3418 public function headOfficeGetJobsInterestedIn()
3419 {
3420 if (is_null($this->headOfficeJobsInterestedIn))
3421 {
3422 $businessIds = $this->getHeadOfficeBusinessIDs();
3423
3424 $jobTable = new Model_DbTable_Job();
3425 $jobSelect = $jobTable->select()
3426 ->setIntegrityCheck(false)
3427 ->from('Job')
3428 ->joinInner('BusinessInterestedinJob', 'BusinessInterestedinJob.JobID = Job.ID', array('quoteDate' => 'DateAdded'))
3429 ->where('BusinessId IN ('.implode(',', $businessIds).')')
3430 ->where('IsQuoteSent = 1 OR IsQuestionAsked = 1')
3431 ->order('DateAdded DESC');
3432
3433 $this->headOfficeJobsInterestedIn = $jobTable->fetchAllCache($jobSelect);
3434 }
3435
3436 return $this->headOfficeJobsInterestedIn;
3437 }
3438
3439 /**
3440 * Get the relavent jobs for this HO
3441 * @return Zend_Db_Table_Rowset_Abstract
3442 */
3443 public function headOfficeGetRelevantJobs()
3444 {
3445 $childBusinesses = $this->getHeadOfficeBusinesses();
3446 $businessIds = array();
3447 $allAreas = array();
3448 $allCategories = array();
3449
3450 // Get the categories and areas for all businesses
3451 foreach ($childBusinesses as $childBusiness)
3452 {
3453 $businessAreas = $childBusiness->getAreas();
3454 foreach ($businessAreas as $area)
3455 {
3456 $allAreas[] = $area->ID;
3457 }
3458
3459 $businessCategories = $childBusiness->getCategories();
3460 foreach ($businessCategories as $category)
3461 {
3462 $allCategories[] = $category->ID;
3463 }
3464
3465 $businessIds[] = $childBusiness->ID;
3466 }
3467
3468 $allCategories = array_unique($allCategories);
3469 $allAreas = array_unique($allAreas);
3470
3471 // If there's no categories or areas, then we can't find suggested jobs
3472 if ((count($allCategories) == 0) or ( count($allAreas) == 0))
3473 {
3474 return array();
3475 }
3476
3477 $jobObject = new Model_DbTable_Job();
3478
3479 $select = $jobObject->select()
3480 ->distinct()
3481 ->setIntegrityCheck(false)
3482 ->from('Job')
3483 ->where('Job.ParentCategoryID IN ('.implode(',', $allCategories).') OR Job.SubCategoryID IN ('.implode(',', $allCategories).') OR Job.SubSubCategoryID IN ('.implode(',', $allCategories).')')
3484 ->where('Job.RegionID IN ('.implode(',', $allAreas).') OR Job.AreaID IN ('.implode(',', $allAreas).') OR Job.SuburbAreaID IN ('.implode(',', $allAreas).')')
3485 ->where('Job.IsOnline = 1')
3486 ->order(array('Job.DateAdded DESC'));
3487
3488 return $jobObject->fetchAll($select);
3489 }
3490
3491 /**
3492 * Gets the positive ratings for this business
3493 * @return array Array of ratings
3494 */
3495 public function getPositiveRatings($positiveRatingCutoff = NULL)
3496 {
3497 // See if this business has a personal cutoff
3498 $positiveRatingCutoff = $this->getPositiveRatingCutoff($positiveRatingCutoff);
3499
3500 $ratings = $this->getAuthenticatedRatings();
3501 $results = array();
3502
3503 foreach ($ratings as $rating)
3504 {
3505 if ($rating->calculateRating() >= $positiveRatingCutoff)
3506 {
3507 $results[] = $rating;
3508 }
3509 }
3510
3511 return $results;
3512 }
3513
3514 /**
3515 * Gets the negative ratings for this business
3516 * @return array Array of ratings
3517 */
3518 public function getNegativeRatings($negativeRatingCutoff = NULL)
3519 {
3520 $negativeRatingCutoff = $this->getNegativeRatingCutoff($negativeRatingCutoff);
3521
3522 $ratings = $this->getAuthenticatedRatings();
3523 $results = array();
3524
3525 foreach ($ratings as $rating)
3526 {
3527 if ($rating->calculateRating() <= $negativeRatingCutoff)
3528 {
3529 $results[] = $rating;
3530 }
3531 }
3532
3533 return $results;
3534 }
3535
3536 /**
3537 * Gets the negative rating cutoff for any ratings, based on the business'
3538 * peferences (if they have any). Defaults to the overall system cutoff
3539 * @param integer $negativeRatingCutoff Override the negative value by
3540 * passing in a value
3541 * @return integer Percentge below which ratings are
3542 * considered negative
3543 */
3544 public function getNegativeRatingCutoff($overrideCutoff = NULL)
3545 {
3546 // See if this business cutoff is getting overridden
3547 if (is_null($overrideCutoff))
3548 {
3549 $negativeRatingCutoff = $this->getMetaData(self::METAKEYNEGATIVERATINGCUTOFF);
3550
3551 // Default to the overall website cutoff
3552 if (is_null($negativeRatingCutoff))
3553 {
3554 $negativeRatingCutoff = Nocowboys_Tools::$ratingNegativeCutoff;
3555 }
3556 }
3557 else
3558 {
3559 $negativeRatingCutoff = $overrideCutoff;
3560 }
3561
3562 return $negativeRatingCutoff;
3563 }
3564
3565 /**
3566 * Gets the positive rating cutoff for any ratings, based on the business'
3567 * peferences (if they have any). Defaults to the overall system cutoff
3568 * @param integer $positiveRatingCutoff Override the negative value by
3569 * passing in a value
3570 * @return integer Percentge above which ratings are
3571 * considered positive
3572 */
3573 public function getPositiveRatingCutoff($overrideCutoff = NULL)
3574 {
3575 // See if this business cutoff is getting overridden
3576 if (is_null($overrideCutoff))
3577 {
3578 $positiveRatingCutoff = $this->getMetaData(self::METAKEYPOSITIVERATINGCUTOFF);
3579
3580 // Default to the overall website cutoff
3581 if (is_null($positiveRatingCutoff))
3582 {
3583 $positiveRatingCutoff = Nocowboys_Tools::$ratingPositiveCutoff;
3584 }
3585 }
3586 else
3587 {
3588 $positiveRatingCutoff = $overrideCutoff;
3589 }
3590
3591 return $positiveRatingCutoff;
3592 }
3593
3594 /**
3595 * Checks if the given business ID is allowed access by this head office
3596 * @param integer $businessId ID of the business the current business wants
3597 * access to
3598 * @return boolean True if this business is allowed access to the business
3599 * with the given ID
3600 */
3601 public function accessToBusiness($businessId)
3602 {
3603 if ($businessId == $this->ID)
3604 {
3605 return true;
3606 }
3607
3608 $childBusinesses = $this->getHeadOfficeBusinesses();
3609 $ratingBusinessFound = false;
3610
3611 foreach ($childBusinesses as $childBusiness)
3612 {
3613 if ($childBusiness->ID == $businessId)
3614 {
3615 $ratingBusinessFound = true;
3616 break;
3617 }
3618 }
3619
3620 return $ratingBusinessFound;
3621 }
3622
3623 /**
3624 * Increases the viewcount for this business
3625 */
3626 public function profilePageViewed()
3627 {
3628 // Add to the history of viewed businesses
3629 $userSession = new Zend_Session_Namespace('userBehavior');
3630
3631 if (!is_array($userSession->previouslyViewedBusinesses))
3632 {
3633 $userSession->previouslyViewedBusinesses = array();
3634 }
3635
3636 if (isset($userSession->previouslyViewedBusinesses[$this->ID]))
3637 {
3638 unset($userSession->previouslyViewedBusinesses[$this->ID]);
3639 }
3640
3641 if (count($userSession->previouslyViewedBusinesses) >= 5)
3642 {
3643 $userSession->previouslyViewedBusinesses = array_slice($userSession->previouslyViewedBusinesses, 0, 4, true);
3644 }
3645
3646 $userSession->previouslyViewedBusinesses = array($this->ID => array('name' => $this->CompanyName, 'uri' => $this->getURI())) + $userSession->previouslyViewedBusinesses;
3647
3648 $this->ViewCount++;
3649 $this->save();
3650 }
3651
3652 /**
3653 * Increases the times found in a search for this business
3654 * Where this method is called the object isn't a complete business object
3655 * so we can't modify it. Load it again and increase the number of views
3656 */
3657 public function appearedInSearch()
3658 {
3659 $businessTable = new Model_DbTable_Business();
3660 $business = $businessTable->fetchRowByValue('ID', $this->ID);
3661 $business->SearchCount++;
3662 $business->save();
3663 }
3664
3665 /**
3666 * Sets the rating classification settings for this business
3667 * @param array $classificationSettings
3668 */
3669 public function setRatingClassificationSettingsFromArray($classificationSettings)
3670 {
3671 $positiveRatingCutoff = $classificationSettings['positiveRatingCutoff'] ?: + 1;
3672 $negativeRatingCutoff = $positiveRatingCutoff - 1;
3673
3674 $this->setMetaData(Model_DbTableRow_Business::METAKEYPOSITIVERATINGCUTOFF, $positiveRatingCutoff);
3675 $this->setMetaData(Model_DbTableRow_Business::METAKEYNEGATIVERATINGCUTOFF, $negativeRatingCutoff);
3676 }
3677
3678 /**
3679 * Sets the notification settings for this business
3680 * @param array $notificationSettings
3681 */
3682 public function setNotificationSettingsFromArray($notificationSettings)
3683 {
3684 if ($notificationSettings['notificationChoice'] == 0)
3685 {
3686 $this->RatingNotification = 0;
3687 }
3688 else
3689 {
3690 $this->RatingNotification = 1;
3691 }
3692
3693 $this->setMetaData(Model_DbTableRow_Business::METAKEYRATINGNOTIFICATIONLEVEL, $notificationSettings['notificationChoice']);
3694 }
3695
3696 /**
3697 * Sets the meta information for automated emails
3698 * @param type $automatedEmailSettings
3699 * @param type $testing Set to true to set up the variables for a test email
3700 */
3701 public function setAutomatedEmailSettingsFromArray($automatedEmailSettings, $testing = false)
3702 {
3703 $this->setMetaData(Model_DbTableRow_Business::METAKEYAUTOMATEDEMAILSCONTENT, $automatedEmailSettings['automatedEmailContent']);
3704
3705 $this->setMetaData(Model_DbTableRow_Business::METAKEYAUTOMATEDEMAILSSUBJECT, $automatedEmailSettings['automatedEmailSubject']);
3706
3707 if ($testing)
3708 {
3709 $this->setMetaData(Model_DbTableRow_Business::METAKEYAUTOMATEDEMAILSACTIVE, 1);
3710 }
3711 else
3712 {
3713 $this->setMetaData(Model_DbTableRow_Business::METAKEYAUTOMATEDEMAILSACTIVE, $automatedEmailSettings['sendAutomatedEmails']);
3714 $this->setMetaData(Model_DbTableRow_Business::METAKEYAUTOMATEDEMAILSCUTOFF, $automatedEmailSettings['emailCutoff']);
3715 }
3716 }
3717
3718 /**
3719 * Sets the logo for this business
3720 * @param Zend_Form_Element_File $image Image to upload
3721 */
3722 public function setLogo($existingFilename, $rotateValue)
3723 {
3724 if (!file_exists($existingFilename))
3725 {
3726 throw new Exception('Uploaded file does not exist');
3727 }
3728
3729 $this->moveUploadedImage($existingFilename);
3730
3731 if($rotateValue <> 0) {
3732 $this->rotateImg($rotateValue);
3733 }
3734
3735 }
3736
3737 /**
3738 * Returns name of image file
3739 * @return string file name to use
3740 */
3741 protected function _getExistingImage()
3742 {
3743 return Zend_Registry::get('config')->images->businessLogo->originalLocation. '/'. $this->LogoFileName;
3744 }
3745
3746 /**
3747 * Moves an uploaded image to its final resting place, gives it a name
3748 * and scales it if it's too big
3749 * @param string $existingImage The location of the existing image to move
3750 */
3751 public function moveUploadedImage($existingImage)
3752 {
3753 if (!file_exists($existingImage))
3754 {
3755 throw new Exception('Uploaded file does not exist');
3756 }
3757
3758 // Get a suggested name for the image
3759 $imageConfig = Zend_Registry::get('config')->images->businessLogo;
3760 $newFileName = $this->_suggestLogoFileName();
3761 $newFullFileName = $imageConfig->originalLocation.'/'.$newFileName;
3762
3763 // Scale the image down
3764 $options = array(
3765 'resolution-units' => Imagine\Image\ImageInterface::RESOLUTION_PIXELSPERINCH,
3766 'resolution-x' => 72,
3767 'resolution-y' => 72,
3768 'quality' => 100
3769 );
3770
3771 $imagineInstance = new Imagine\Gd\Imagine();
3772 $result = $imagineInstance->open($existingImage)
3773 ->save($newFullFileName, $options);
3774
3775 //remove old business logo
3776 if($result and $imageConfig->originalLocation.'/'.$this->LogoFileName != $existingImage) {
3777 Model_DbTableRow_BusinessPic::deleteFile($imageConfig->originalLocation.'/'.$this->LogoFileName);
3778 }
3779
3780 $this->LogoFileName = $newFileName;
3781 $this->save(true);
3782
3783 // Remove the old image now we've saved our new one
3784 Model_DbTableRow_BusinessPic::deleteFile($existingImage);
3785
3786 return $result;
3787 }
3788
3789 /**
3790 * Suggests a logo filename
3791 * @return string Suggested logo filename
3792 */
3793 private function _suggestLogoFileName()
3794 {
3795 $suggestedName = $this->CompanyName.' logo';
3796 $this->logoVersion++;
3797
3798 if ($this->logoVersion > 1)
3799 {
3800 $suggestedName .= ' v'.$this->logoVersion;
3801 }
3802
3803 return Nocowboys_Db_Table_Abstract::cleanUrl($suggestedName).'.jpg';
3804 }
3805
3806 /**
3807 * Deletes the logo if it exists
3808 */
3809 public function deleteLogo()
3810 {
3811 $imageConfig = Zend_Registry::get('config')->images->businessLogo;
3812
3813 // Delete the existing logo if there is one
3814 $existingLogo = $imageConfig->originalLocation.'/'.$this->LogoFileName;
3815
3816 if ((isset($existingLogo)) and ( is_file($existingLogo)))
3817 {
3818 Model_DbTableRow_BusinessPic::deleteFile($existingLogo);
3819 }
3820
3821 $this->LogoFileName = NULL;
3822 $this->save(true);
3823 }
3824
3825 /**
3826 * Overrides the save method so we can update the last date changed value
3827 * @param boolean $updateLastUpdated Set to true to update the last-updated
3828 * time
3829 * @param boolean $updateSolr Set to true to update SOLR. We don't
3830 * need to do this every time the object is saved, but we need to keep
3831 * the index up-to-date
3832 * @param advanced params. Such as save business changing in history
3833 * @return mixed
3834 */
3835 public function save($updateLastUpdated = false, $updateSolr = false, $params = ['history' => false])
3836 {
3837
3838 $action = $this->_checkBusinessAction();
3839
3840 if ($updateLastUpdated)
3841 {
3842 $this->updateLastUpdatedTime(false);
3843 }
3844
3845 $businessID = parent::save();
3846
3847 if ($updateSolr)
3848 {
3849 $this->updateToSolr();
3850 }
3851
3852 if(!empty($params['history'])) {
3853 $this->_saveBusinessHistory($action);
3854 }
3855
3856 return $businessID;
3857 }
3858
3859 protected function _setHistoryUserInfo(&$historyBusiness) {
3860
3861 if(Nocowboys_User_Administrator::loggedIn()) {
3862 $userInfo = Nocowboys_User_Administrator::getUserObject();
3863 $historyBusiness->user_type = Model_DbTable_BusinessHistory::USER_TYPE_ADMIN;
3864 $historyBusiness->user_id = $userInfo->id;
3865 } elseif(Nocowboys_User_Business::loggedIn()) {
3866 $userInfo = Nocowboys_User_Business::getUserObject();
3867 $historyBusiness->user_type = Model_DbTable_BusinessHistory::USER_TYPE_BUSINESS;
3868 $historyBusiness->user_id = $userInfo->ID;
3869 }
3870
3871 return $historyBusiness;
3872 }
3873
3874 protected function _checkBusinessAction() {
3875 if(!empty($this->ID)) {
3876 $action = Model_DbTable_BusinessHistory::$action['edit'];
3877 }
3878 else {
3879 $action = Model_DbTable_BusinessHistory::$action['add'];
3880 }
3881
3882 return $action;
3883 }
3884
3885 protected function _saveBusinessHistory($action) {
3886 $businessHistory = new Model_DbTable_BusinessHistory();
3887 $newBusinessHistory = $businessHistory->createRow();
3888 $newBusinessHistory->action = $action;
3889 $newBusinessHistory->business_id = $this->ID;
3890 $newBusinessHistory->datetime = date(Model_DbTable_BusinessHistory::DATE_TIME_FORMAT_MYSQL);
3891 $newBusinessHistory->data = json_encode($this->toArray());
3892 $this->_setHistoryUserInfo($newBusinessHistory);
3893
3894 return $newBusinessHistory->save();
3895 }
3896
3897 public function delete()
3898 {
3899 $this->_saveBusinessHistory(Model_DbTable_BusinessHistory::$action['delete']);
3900
3901 $this->removeSalesEmailMailchimpBusinessesRegistered();
3902
3903 $mc = new Nocowboys_MailChimp();
3904 $mc->removeMemberFromList(Nocowboys_MailChimp::getListIdBusinesses(), $this->EmailAddress);
3905 $mc->removeMemberFromList(Nocowboys_MailChimp::getListIdBusinessesRegistered(), $this->EmailAddress);
3906
3907 return parent::delete();
3908
3909 }
3910
3911 /**
3912 * Updates the last-updated time
3913 * @param boolean $saveAfterwards Set to false to not save the business
3914 * object after updating the last-updated time
3915 */
3916 public function updateLastUpdatedTime($saveAfterwards = true)
3917 {
3918 $this->lastUpdated = Nocowboys_Tools::databaseSafeDateTime();
3919
3920 if ($saveAfterwards)
3921 {
3922 $this->save();
3923 }
3924 }
3925
3926 /**
3927 * Fetches all the correspondence for this business
3928 * @param integer $limit Limits the number of items to return
3929 * @param array|NULL $excludeTypes Set this to a number or array of numbers
3930 * of correspondence types to exclude from the query
3931 * @return Zend_Db_Table_Rowset_Abstract
3932 */
3933 public function getCorrespondence($limit = 200, $excludeTypes = NULL)
3934 {
3935 $correspondenceTable = new Model_DbTable_BusinessCorrespondence();
3936 $correspondenceSelect = $correspondenceTable->select()
3937 ->where('BusinessID = ?', $this->ID)
3938 ->order('DateSent DESC')
3939 ->limit($limit);
3940
3941 if (!is_null($excludeTypes))
3942 {
3943 if (is_array($excludeTypes))
3944 {
3945 $correspondenceSelect->where('type NOT IN ('.implode(',', $excludeTypes).')');
3946 }
3947 else
3948 if (is_numeric($excludeTypes))
3949 {
3950 $correspondenceSelect->where('type != ?', $excludeTypes);
3951 }
3952 }
3953
3954 return $correspondenceTable->fetchAll($correspondenceSelect);
3955 }
3956
3957 /**
3958 * Gets all the texts for this business
3959 * @param integer $limit Limits the number of items to return
3960 * @return Zend_Db_Table_Rowset_Abstract
3961 */
3962 public function getTexts($limit = 200)
3963 {
3964 $textTable = new Model_DbTable_Nctext();
3965 return $textTable->fetchAll('BusinessID = '.$this->ID, 'DateSent DESC', $limit);
3966 }
3967
3968 /**
3969 * Gets all the correspondence for the business, including emails and texts.
3970 * Returns them in order of the date they were sent
3971 * @param array|NULL $excludeTypes Set this to a number or array of numbers
3972 * of correspondence types to exclude from the query
3973 */
3974 public function getAllCorrespondence($limit = 200, $excludeTypes = NULL)
3975 {
3976 $correspondence = $this->getCorrespondence($limit, $excludeTypes);
3977 $correspondenceCount = count($correspondence);
3978 $correspondence = $correspondence->toArray();
3979
3980 for ($i = 0; $i < $correspondenceCount; $i++)
3981 {
3982 $correspondence[$i]['correspondenceType'] = Model_DbTable_BusinessCorrespondence::CORRESPONDENCETYPE;
3983 }
3984
3985 $texts = $this->getTexts($limit);
3986 $textCount = count($texts);
3987 $texts = $texts->toArray();
3988
3989 for ($i = 0; $i < $textCount; $i++)
3990 {
3991 $texts[$i]['correspondenceType'] = Model_DbTable_Nctext::CORRESPONDENCETYPE;
3992 }
3993
3994 // Combine and sort all by the date they were sent
3995 $allCorrespondence = array_merge($correspondence, $texts);
3996 usort($allCorrespondence, 'correspondenceSort');
3997
3998 return array_slice($allCorrespondence, 0, $limit);
3999 }
4000
4001 /**
4002 * Sets the video for this business
4003 * @param string $video YouTube video code to display
4004 */
4005 public function setVideo($video)
4006 {
4007 if (trim($video) != '')
4008 {
4009 $this->setMetaData(self::METAKEYVIDEO, $video);
4010 }
4011 else
4012 {
4013 $this->deleteMetaData(self::METAKEYVIDEO);
4014 }
4015
4016 $this->updateLastUpdatedTime();
4017 }
4018
4019 /**
4020 * Gets the number of times the pages have been viewed for the past
4021 * month
4022 * @param integer $numberOfMonths Number of months to search profile
4023 * views for
4024 * @return integer Number of views for the given time frame
4025 */
4026 public function getProfilePageViews()
4027 {
4028 return $this->getPastMonthAnalytics(Model_DbTable_Analytic::PROFILE_VIEW);
4029 }
4030
4031 /**
4032 * Gets the number of times the business has appeared in search results
4033 * @return integer Number of views for the given time frame
4034 */
4035 public function getSearchResultViews()
4036 {
4037 $searchResults = 0;
4038 $searchResults += $this->getPastMonthAnalytics(Model_DbTable_Analytic::SEARCH_RESULTS);
4039 $searchResults += $this->getPastMonthAnalytics(Model_DbTable_Analytic::ADVERTISMENTS);
4040
4041 return $searchResults;
4042 }
4043
4044 /**
4045 * Generic method to get all the analytics for the past month
4046 * @param string $type Type of analytics to fetch
4047 * @return int Aggregated number of analytics for the past month
4048 */
4049 public function getPastMonthAnalytics($type)
4050 {
4051 $startDate = new DateTime();
4052 $endDate = new DateTime('-1 MONTH');
4053
4054 $analyticsTable = new Model_DbTable_AnalyticSummary();
4055 $select = $analyticsTable->select()
4056 ->where('businessId = ?', $this->ID)
4057 ->where('type = ?', $type);
4058
4059 $analyticsResult = $analyticsTable->fetchRow($select);
4060
4061 if (isset($analyticsResult->analytics))
4062 {
4063 $analytics = json_decode($analyticsResult->analytics, true);
4064
4065 if (!isset($analytics[Model_DbTable_AnalyticSummary::DURATION_DAYS]))
4066 {
4067 return 0;
4068 }
4069 else
4070 {
4071 $analyticsCount = 0;
4072
4073 while ($startDate > $endDate)
4074 {
4075 $stringToFind = $startDate->format('Ymd');
4076
4077 if (isset($analytics[Model_DbTable_AnalyticSummary::DURATION_DAYS][$stringToFind]))
4078 {
4079 $analyticsCount += $analytics[Model_DbTable_AnalyticSummary::DURATION_DAYS][$stringToFind];
4080 }
4081
4082 $startDate->modify('-1 DAY');
4083 }
4084
4085 return $analyticsCount;
4086 }
4087 }
4088 else
4089 {
4090 return 0;
4091 }
4092 }
4093
4094 /**
4095 * Gets the number of times the business has appeared in high profile
4096 * positions
4097 * @return integer Number of views for the given time frame
4098 */
4099 public function getHighProfileImpressions()
4100 {
4101 $searchResults = 0;
4102 $searchResults += $this->getPastMonthAnalytics(Model_DbTable_Analytic::ADVERTISMENTS);
4103 $searchResults += $this->getPastMonthAnalytics(Model_DbTable_Analytic::FRONT_PAGE);
4104 $searchResults += $this->getPastMonthAnalytics(Model_DbTable_Analytic::RECENT_RATINGS);
4105
4106 return $searchResults;
4107 }
4108
4109 /**
4110 * Gets the number of times the business' website has been viewed
4111 * @return integer Number of views for the given time frame
4112 */
4113 public function getWebsiteViews()
4114 {
4115 return $this->getPastMonthAnalytics(Model_DbTable_Analytic::WEBSITE_VIEW);
4116 }
4117
4118 /**
4119 * Gets the number of times the business' phone number has been viewed
4120 * @return integer Number of views for the given time frame
4121 */
4122 public function getPhoneNumberViews()
4123 {
4124 return $this->getPastMonthAnalytics(Model_DbTable_Analytic::PHONE_NUMBER_VIEW);
4125 }
4126
4127 /**
4128 * Gets the last time the business registered from a non-registered
4129 * position
4130 * @return integer|false Date first registered or NULL if the business
4131 * has not registered
4132 */
4133 public function getLastRegisteredDate()
4134 {
4135 $payments = $this->getAllPayments(false);
4136 $registered = $this->isRegistered();
4137
4138 if (!$registered)
4139 {
4140 return NULL;
4141 }
4142
4143 $lastRegisteredExpiry = NULL;
4144 $lastPaid = NULL;
4145 $paymentsArray = array();
4146
4147 foreach ($payments as $payment)
4148 {
4149 $daysPaid = $payment->DaysPaid;
4150 $datePaid = strtotime($payment->DatePaid);
4151 $paymentExpiryDate = strtotime('+'.$daysPaid.' days', $datePaid);
4152
4153 $paymentsArray[] = array('daysPaid' => $daysPaid, 'datePaid' => $datePaid, 'expiryDate' => $paymentExpiryDate,
4154 'datePaidActual' => date('r', $datePaid), 'dateExpiredActual' => date('r', $paymentExpiryDate));
4155 }
4156
4157 foreach ($paymentsArray as $paymentItem)
4158 {
4159
4160 if (is_null($lastRegisteredExpiry))
4161 {
4162 $lastRegisteredExpiry = $paymentItem['expiryDate'];
4163 $lastPaid = $paymentItem['datePaid'];
4164 }
4165 else
4166 {
4167 if ($lastPaid <= $paymentItem['expiryDate'])
4168 {
4169 $lastRegisteredExpiry = $paymentItem['expiryDate'];
4170 $lastPaid = $paymentItem['datePaid'];
4171 }
4172 else
4173 {
4174 break;
4175 }
4176 }
4177 }
4178
4179 return $lastPaid;
4180 }
4181
4182 /**
4183 * Returns the physical address for the business
4184 * @return string
4185 */
4186 public function getPhysicalAddress()
4187 {
4188 $return = '';
4189 $suburb = $this->getLocationArea();
4190
4191 if (($this->LocationAreaID > 0) and ( trim($this->AddressStreetName) != ''))
4192 {
4193 if (trim($this->AddressStreetNumber) != '')
4194 {
4195 $return .= trim($this->AddressStreetNumber).' '.trim($this->AddressStreetName);
4196 }
4197 else
4198 {
4199 $return .= trim($this->AddressStreetName);
4200 }
4201
4202 if (!is_null($suburb))
4203 {
4204 $return .= Nocowboys_Tools::lineBreakIfNotEmpty($suburb->Name, NULL, ',');
4205 }
4206
4207 $return .= Nocowboys_Tools::lineBreakIfNotEmpty($this->addressPostcode, NULL, ',');
4208 }
4209
4210 if (trim($return) == '')
4211 {
4212 $return = nl2br($this->PhysicalAddress);
4213 }
4214
4215 if (trim($return) == '')
4216 {
4217 $return = nl2br($this->AddressDetails);
4218 }
4219
4220 return $return;
4221 }
4222
4223 /**
4224 * Returns a list of badges that are attibuted to this business
4225 *
4226 * @return array Array of badges
4227 */
4228 public function getBadges($fromCache = true, $emptyCache = false)
4229 {
4230 $cacheKey = self::CACHE_KEY_BADGES.$this->ID;
4231
4232 // Empty the cache if that's what the user wants to do
4233 if ($emptyCache)
4234 {
4235 return Nocowboys_Db_Table_Cache::deleteCacheKey($cacheKey);
4236 }
4237
4238 // Load from cache if we want to and it exists
4239 if (( $fromCache) and ( Nocowboys_Db_Table_Cache::test($cacheKey)))
4240 {
4241 return Nocowboys_Db_Table_Cache::load($cacheKey);
4242 }
4243
4244 $badges = [];
4245
4246 if ($this->isRegistered())
4247 {
4248 $badges[] = self::BADGE_REGISTERED;
4249 }
4250
4251 if ($this->isCustomerPreferred())
4252 {
4253 $badges[] = self::BADGE_CUSTOMER_PREFERRED;
4254 }
4255
4256 $ratings = $this->getAuthenticatedRatings();
4257
4258 if (count($ratings) >= 1000)
4259 {
4260 $badges[] = self::BADGE_PLATINUM_BUSINESS;
4261 }
4262// else
4263 if (count($ratings) >= 500)
4264 {
4265 $badges[] = self::BADGE_GOLD_BUSINESS;
4266 }
4267// else
4268 if (count($ratings) >= 100)
4269 {
4270 $badges[] = self::BADGE_SILVER_BUSINESS;
4271 }
4272// else
4273 if (count($ratings) >= 50)
4274 {
4275 $badges[] = self::BADGE_BRONZE_BUSINESS;
4276 }
4277
4278 if ($fromCache)
4279 {
4280 Nocowboys_Db_Table_Cache::save($badges, $cacheKey);
4281 }
4282
4283 return $badges;
4284 }
4285
4286 /**
4287 * Returns the billing address for the business
4288 * @return string
4289 */
4290 public function getBillingAddress($fallbackToPhysicalAddress = true)
4291 {
4292 $return = '';
4293 $suburb = $this->getPostalLocationArea();
4294
4295 if (($this->PostalSuburbID > 0) and ( ( trim($this->PostalStreetName) != '') or ( trim($this->PostalUnitNumber) != '')))
4296 {
4297 if (trim($this->PostalStreetNumber) != '')
4298 {
4299 $postalNumberAndStreet = trim($this->PostalStreetNumber).' '.trim($this->PostalStreetName);
4300 }
4301 else
4302 {
4303 $postalNumberAndStreet = trim($this->PostalStreetName);
4304 }
4305
4306 if (trim($this->PostalUnitNumber) != '')
4307 {
4308 $return .= 'PO box '.$this->PostalUnitNumber;
4309 $return .= Nocowboys_Tools::lineBreakIfNotEmpty($postalNumberAndStreet, NULL, ',');
4310 }
4311 else
4312 {
4313 $return .= $postalNumberAndStreet;
4314 }
4315
4316
4317 if (!is_null($suburb))
4318 {
4319 $return .= Nocowboys_Tools::lineBreakIfNotEmpty($suburb->Name, NULL, ',');
4320 }
4321
4322 $return .= Nocowboys_Tools::lineBreakIfNotEmpty($this->postalPostcode, NULL, ',');
4323 }
4324
4325 if (trim($return) == '')
4326 {
4327 $return = nl2br($this->PostageAddress);
4328 }
4329
4330 if (trim($return) == '')
4331 {
4332 $return = nl2br($this->AddressDetails);
4333 }
4334
4335 if ((trim($return) == '') and ( $fallbackToPhysicalAddress))
4336 {
4337 $return = $this->getPhysicalAddress();
4338 }
4339
4340 return $return;
4341 }
4342
4343 /**
4344 * Unsubscribes from any mailing lists the user may be subscribed to
4345 * @return boolean True if the unsubscribe was successful
4346 */
4347 public function unsubscribeFromMailingList()
4348 {
4349 if (trim($this->EmailAddress) == '')
4350 {
4351 return false;
4352 }
4353
4354 $mailChimp = new Nocowboys_MailChimp();
4355 return $mailChimp->unsubscribe(Nocowboys_MailChimp::getListIdBusinesses(), $this->EmailAddress);
4356 }
4357
4358 /**
4359 * Returns data used for the external flair. Cache as much of this
4360 * as possible
4361 * @return array Information for the flair
4362 */
4363 public function getFlairData()
4364 {
4365 $authenticatedRatings = $this->getAuthenticatedRatings();
4366 $overallRating = $this->TempOverall;
4367 $config = Zend_Registry::get('config');
4368 $domain = $config->domain;
4369
4370 $resultArray = array();
4371 $resultArray['ratingCount'] = count($authenticatedRatings);
4372 $resultArray['name'] = $this->CompanyName;
4373 $resultArray['url'] = $domain.$this->getURI();
4374 $resultArray['overall'] = $overallRating;
4375 $resultArray['registered'] = $this->isRegistered() ? 1 : 0;
4376
4377 return $resultArray;
4378 }
4379
4380 /**
4381 * Returns the most recent rating for this business
4382 * @return Model_DbTableRow_Rating
4383 */
4384 public function getMostRecentRating()
4385 {
4386 $ratingTable = new Model_DbTable_Rating();
4387 $ratingSelect = $ratingTable->select(array('Comment'))
4388 ->where('BusinessID = ?', $this->ID)
4389 ->order('RankDate DESC')
4390 ->limit(1);
4391
4392 $result = $ratingTable->fetchRow($ratingSelect);
4393 unset($ratingTable);
4394
4395 if (!is_null($result))
4396 {
4397 return $result->Comment;
4398 }
4399 else
4400 {
4401 return NULL;
4402 }
4403 }
4404
4405 /**
4406 * Returns an array of the properties of this business, but to be given
4407 * to the search listing view helper
4408 *
4409 * @return array
4410 */
4411 public function toArraySearch()
4412 {
4413 $primaryCategory = $this->getPrimaryCategory(true);
4414
4415 $returnArray = $this->toArray();
4416 $returnArray['uri'] = $this->getUri();
4417 $returnArray['businessName'] = $this->CompanyName;
4418 $returnArray['ratingCount'] = count($this->getRatings());
4419 $returnArray['overallRating'] = round($this->TempOverall);
4420 $returnArray['assocations'] = $this->getAssociations()->toArray();
4421 $returnArray['badges'] = $this->getBadges();
4422 $returnArray['registered'] = $this->isRegistered();
4423 $returnArray['customerPreferred'] = $this->isCustomerPreferred();
4424 $returnArray['primaryCategoryId'] = $primaryCategory->ID;
4425 $returnArray['primaryCategoryName'] = $primaryCategory->Name;
4426
4427 return $returnArray;
4428 }
4429
4430 /**
4431 * Gets the breadcrumb for this business
4432 *
4433 * @return array Array of items to give to the breadcrumb helper
4434 */
4435 public function getBreadcrumbArray($additionalCrumb = '')
4436 {
4437 $primaryBusinessCategory = $this->getPrimaryCategory(true);
4438 $breadcrumbArray = [];
4439
4440 if (!is_null($primaryBusinessCategory))
4441 {
4442 // Get the area for the current user
4443 $area = Nocowboys_Controller_V3_Action::getUserLocationData();
4444 $businessArea = $this->getLocationArea();
4445
4446 if ((!is_null($area)) and ( isset($area->suburbSlug)))
4447 {
4448 $areaSlug = $area->suburbSlug;
4449 }
4450 else
4451 if (!is_null($businessArea))
4452 {
4453 $areaSlug = $businessArea->URLName;
4454 }
4455 else
4456 {
4457 $areaSlug = 'new-zealand';
4458 }
4459
4460 $breadcrumb = $primaryBusinessCategory->getBreadcrumb();
4461
4462 foreach ($breadcrumb as $crumb)
4463 {
4464 $breadcrumbArray['/search/'.$areaSlug.'/'.$crumb->URLName] = $crumb->Name;
4465 }
4466
4467 $breadcrumbArray = array_reverse($breadcrumbArray);
4468 $breadcrumbArray['/search/'.$areaSlug.'/'.$primaryBusinessCategory->URLName] = $primaryBusinessCategory->Name;
4469 }
4470
4471 if ($additionalCrumb == '')
4472 {
4473 $breadcrumbArray[] = Nocowboys_Tools::escape($this->CompanyName);
4474 }
4475 else
4476 {
4477 $breadcrumbArray[$this->getURI()] = Nocowboys_Tools::escape($this->CompanyName);
4478 $breadcrumbArray[] = $additionalCrumb;
4479 }
4480
4481 return $breadcrumbArray;
4482 }
4483
4484 /**
4485 * Gets the monthly payment date for this business
4486 *
4487 * @return DateTime|NULL
4488 */
4489 public function getMonthlyPaymentDate()
4490 {
4491 if (!is_null($this->monthlyPaymentDate))
4492 {
4493 return new DateTime($this->monthlyPaymentDate);
4494 }
4495
4496 return NULL;
4497 }
4498
4499 /**
4500 * Sets the monthly payment date if it isn't already set (or overrides
4501 * it if one is passed in)
4502 *
4503 * @param DateTime $date Date to set it to
4504 * @return DateTime The set date
4505 */
4506 public function setMonthlyPaymentDate(DateTime $date = NULL)
4507 {
4508 if (!is_null($date))
4509 {
4510 $this->monthlyPaymentDate = $date->format(Nocowboys_Db_Table_Abstract::DATE_TIME_FORMAT_MYSQL);
4511 $this->save();
4512 }
4513 else
4514 {
4515 if ((!isset($this->monthlyPaymentDate)) or ( is_null($this->monthlyPaymentDate)))
4516 {
4517 // If we have an expiry date for the business, then set that
4518 // as the next payment date
4519 $expiryDate = $this->getRegistrationExpiryDateFromTable();
4520
4521 if ((is_null($expiryDate)) or ( $expiryDate < time()))
4522 {
4523 $now = new DateTime();
4524 $this->monthlyPaymentDate = $now->format(Nocowboys_Db_Table_Abstract::DATE_TIME_FORMAT_MYSQL);
4525 }
4526 else
4527 {
4528 $this->monthlyPaymentDate = date(Nocowboys_Db_Table_Abstract::DATE_TIME_FORMAT_MYSQL, $expiryDate);
4529 }
4530
4531 $this->save();
4532 }
4533 }
4534
4535 return $this->monthlyPaymentDate;
4536 }
4537
4538 /**
4539 * Increments the monthly payment date by a month
4540 *
4541 */
4542 public function incrementMonthlyPaymentDate($numberOfMonths = 1)
4543 {
4544 // If no date is already set, then this one will set it to right
4545 // now before incrementing it
4546 $this->setMonthlyPaymentDate();
4547
4548 $monthlyPaymentDate = new DateTime($this->monthlyPaymentDate);
4549 $monthlyPaymentDate->modify('+'.$numberOfMonths.' MONTH');
4550
4551 $this->setMonthlyPaymentDate($monthlyPaymentDate);
4552 }
4553
4554 /**
4555 * Checks if the business' credit card is expiring soon
4556 *
4557 * @param NULL|DateTime $currentDateTime Used for testing
4558 * @return boolean True if the card is expiring in the next two months
4559 */
4560 public function isCreditCardExpiring($currentDateTime = NULL)
4561 {
4562 if (is_null($this->monthlyPaymentCardExpiryDate))
4563 {
4564 return false;
4565 }
4566
4567 if (is_null($currentDateTime))
4568 {
4569 $currentDateTime = new DateTime();
4570 }
4571
4572 $businessCardExpiryDate = $this->getCreditCardExpiryDate();
4573
4574 $interval = $currentDateTime->diff($businessCardExpiryDate);
4575 $dayDifference = $interval->days;
4576 $inTheFuture = $interval->invert == 0;
4577
4578 return (($dayDifference < 60) and ( $dayDifference > 0) and ( $inTheFuture));
4579 }
4580
4581 /**
4582 * Checks if the business' credit card has expired
4583 *
4584 * @param NULL|DateTime $currentDateTime Used for testing
4585 * @return boolean True if the card has expired
4586 */
4587 public function creditCardHasExpired($currentDateTime = NULL)
4588 {
4589 if (is_null($this->monthlyPaymentCardExpiryDate))
4590 {
4591 return false;
4592 }
4593
4594 if (is_null($currentDateTime))
4595 {
4596 $currentDateTime = new DateTime();
4597 }
4598
4599 $businessCardExpiryDate = $this->getCreditCardExpiryDate();
4600
4601 $interval = $currentDateTime->diff($businessCardExpiryDate);
4602 $inTheFuture = $interval->invert == 0;
4603
4604 return (!$inTheFuture);
4605 }
4606
4607 /**
4608 * Returns the date the business' credit card will expire
4609 *
4610 * @return NULL|DateTime
4611 */
4612 public function getCreditCardExpiryDate()
4613 {
4614 if (is_null($this->monthlyPaymentCardExpiryDate))
4615 {
4616 return NULL;
4617 }
4618
4619 return new DateTime($this->monthlyPaymentCardExpiryDate);
4620 }
4621
4622 /**
4623 * Checks to see if there's a saved card we can use to take purchases
4624 *
4625 * @return boolean True if there is a saved card we can use for future
4626 * purchases
4627 */
4628 public function hasSavedCard()
4629 {
4630 $cardExpiryDate = $this->getCreditCardExpiryDate();
4631
4632 if (!is_null($cardExpiryDate))
4633 {
4634 $now = new DateTime();
4635 return ((!is_null($this->paymentExpressToken)) and ( trim($this->paymentExpressToken) != '') and ( $cardExpiryDate > $now));
4636 }
4637
4638 return false;
4639 }
4640
4641 public function hasCardDataSaved()
4642 {
4643 return ((!is_null($this->paymentExpressToken)) and ( trim($this->paymentExpressToken) != '')and !empty($this->monthlyPaymentCardholderName) and !empty($this->monthlyPaymentCardExpiryDate) and !empty($this->monthlyPaymentCardExpiryDate));
4644
4645 }
4646
4647 /**
4648 * Gets a summary of the saved card information for display
4649 *
4650 * @return array
4651 */
4652 public function getSavedCardInformation()
4653 {
4654 return [
4655 'cardNumber' => $this->monthlyPaymentCardNumber,
4656 'cardExpiryDate' => $this->getCreditCardExpiryDate(),
4657 'cardholderName' => $this->monthlyPaymentCardholderName
4658 ];
4659 }
4660
4661 /**
4662 * Gets the cache key for the business marker
4663 *
4664 * @return string
4665 */
4666 public function getCacheKeyForMarker()
4667 {
4668 return 'marker_fetch_row_business_'.$this->ID;
4669 }
4670
4671 /**
4672 * Resets business payment information to null or empty and stops monthly payment schedule.
4673 * Reason being if monthly payment date is null further payment will not be processed by
4674 * the cron job monthlyRegistrationRunRenewals.php
4675 *
4676 * @return boolean Returns true if the business object is saved successfully otherwise false
4677 */
4678 public function stopMonthlyPayment()
4679 {
4680 $this->monthlyPaymentDate = NULL;
4681 $this->monthlyPaymentCardholderName = '';
4682 $this->monthlyPaymentCardNumber = '';
4683 $this->monthlyPaymentCardExpiryDate = NULL;
4684 $this->paymentExpressToken = '';
4685 $this->allow_auto_monthly_payment = 0;
4686 return $this->save();
4687 }
4688
4689 /**
4690 * Pause any active monthly payments and updates monthly payment date with future date from user
4691 *
4692 * @param string $paymentDate payment date till that the monthly payment is paused
4693 * @return boolean Returns true if the payment date is saved successfully, false
4694 * if the payment date is invalid
4695 */
4696 public function pauseMonthlyPayment($paymentDate)
4697 {
4698 $monthlyPaymentDate = date('Y-m-d', strtotime($paymentDate));
4699
4700 if ((isset($monthlyPaymentDate)) and ($monthlyPaymentDate >= date('Y-m-d')))
4701 {
4702 $this->monthlyPaymentDate = $monthlyPaymentDate;
4703 return $this->save();
4704 }
4705 else
4706 {
4707 return false;
4708 }
4709 }
4710
4711 /**
4712 * Deregisters a business
4713 *
4714 */
4715 public function deregister($notify = true)
4716 {
4717 $config = Zend_Registry::get('config');
4718 $urlHelper = new Zend_View_Helper_Url();
4719
4720 $this->Registered = 0;
4721 $this->SubscribedProductId = 0;
4722 $this->save(true, true);
4723
4724 // Unsubscribe from
4725 $this->removeSalesEmailMailchimpBusinessesRegistered();
4726
4727 // Email the account manager
4728 $emailParameters = [
4729 'contactName' => $this->Name,
4730 'companyName' => $this->CompanyName,
4731 'companyId' => $this->ID,
4732 'businessId' => $this->ID,
4733 'companyCRMLink' => $config->domain.$urlHelper->url(['id' => $this->ID], 'crm-view-business'),
4734 'phoneNumber' => $config->email->template->alternatePhoneNumber,
4735 'registrationEmail' =>$config->email->template->registrationEmail
4736 ];
4737
4738 if ($notify) {
4739 if (Nocowboys_Email::sendEmail(
4740 $config->website->operationsEmail,
4741 'Business registration lapsed',
4742 'internal/businessDeregistrationNotification',
4743 $emailParameters
4744 )) {
4745 Nocowboys_Email::sendEmail(
4746 $this->EmailAddress,
4747 'Your NoCowboys Registration has lapsed',
4748 'product-renewals/registration-lapsed',
4749 $emailParameters
4750 );
4751 }
4752 }
4753 }
4754
4755 /**
4756 * Gets default product ID for this business.
4757 *
4758 *
4759 * @return Model_DbTableRow_Product
4760 */
4761 public function getDefaultProductId()
4762 {
4763 $config = Zend_Registry::get('config')->website;
4764
4765 if (!empty($this->default_package_id)) {
4766 return $this->default_package_id;
4767 }
4768
4769 return $config->defaultProductId;
4770 }
4771
4772 public function getDefaultProduct()
4773 {
4774 if ($defaultProductId = $this->getDefaultProductId()) {
4775 $productTable = new Model_DbTable_Product();
4776
4777 return $productTable->fetchRow($productTable->select()->where('ID = ?', $defaultProductId));
4778 }
4779
4780 return false;
4781 }
4782
4783 /**
4784 * Gets default monthly product ID for this business.
4785 *
4786 *
4787 * @return mixed
4788 */
4789 public function getDefaultMonthlyProductId()
4790 {
4791 if ($this->is_facebook_lead == self::FACEBOOK_LEAD_TYPE_1) {
4792 return Zend_Registry::get('config')->website->defaultMonthlyProductIdForFacebookLeads;
4793 }
4794
4795 return Zend_Registry::get('config')->website->defaultMonthlyProductId;
4796 }
4797
4798 /**
4799 * Gets renewal product row.
4800 *
4801 *
4802 * @return Zend_Db_Table_Row_Abstract
4803 */
4804 public function getRenewalPackage()
4805 {
4806 $currentPackage = $this->getCurrentPackage();
4807
4808 $productTable = new Model_DbTable_Product();
4809
4810 return $currentPackage
4811 ? $productTable->fetchRowByValue(
4812 'ID', Model_DbTable_Product::getProductIdForRenewal($currentPackage->ID)
4813 )
4814 : $productTable->fetchRowByValue('ID', $this->getDefaultProductId());
4815 }
4816
4817 public function getRecentRating()
4818 {
4819 $ratingTable = new Model_DbTable_Rating();
4820 $ratingSelect = $ratingTable->select(array('Comment'))
4821 ->where('BusinessID = ? AND Hidden = 0 AND Locked = 0', $this->ID)
4822 ->where('need_approve = ?', Model_DbTable_Rating::RATING_STATUS_APPROVED)
4823 ->order('RankDate DESC')
4824 ->limit(1);
4825
4826 return $ratingTable->fetchRow($ratingSelect);
4827 }
4828
4829 /**
4830 * Returns business sales email
4831 *
4832 * @return string
4833 */
4834 public function getSalesEmail() {
4835 return $this->SalesEmail;
4836 }
4837
4838 /**
4839 * Sets new product for business.
4840 *
4841 *
4842 * @return bool
4843 */
4844 public function setProduct($productID) {
4845 return $this->SubscribedProductId = $productID;
4846 }
4847
4848 /**
4849 * Sets new default product for business.
4850 *
4851 *
4852 * @return bool
4853 */
4854 public function setDefaultProduct($productID) {
4855 return $this->default_package_id = $productID;
4856 }
4857
4858 /**
4859 * Adds SalesEmail to list of Registered Businesses.
4860 *
4861 *
4862 * @return bool
4863 *
4864 * @throws Exception
4865 */
4866 public function addSalesEmailToListOfBusinessesRegistered($oldEmail = '')
4867 {
4868 !empty($oldEmail) ? $email = $oldEmail : $email = $this->SalesEmail;
4869
4870 $businessMailchimp = new Model_DbTable_BusinessMailchimp($this->ID);
4871
4872 if($email !== $this->EmailAddress) {
4873 $this->removeSalesEmailMailchimpBusinessesRegistered($oldEmail);
4874 }
4875
4876 if(empty($this->SalesEmail) or !$this->isRegistered()) {
4877 return false;
4878 }
4879
4880 $businessMailchimp->createAddSalesTask();
4881 }
4882
4883 public function removeSalesEmailMailchimpBusinessesRegistered($email = '')
4884 {
4885 if(empty($email) and empty($this->SalesEmail)) {
4886 return false;
4887 } elseif(empty($email) and !empty($this->SalesEmail)) {
4888 $email = $this->SalesEmail;
4889 }
4890 $businessMailchimp = new Model_DbTable_BusinessMailchimp($this->ID);
4891
4892 $businessMailchimp->createDeleteSalesTask($email);
4893 }
4894
4895 public function updateSubscriptionForBusiness($oldEmail = '')
4896 {
4897 if (empty($oldEmail)) {
4898 $oldEmail = $this->EmailAddress;
4899 }
4900
4901
4902 if(empty($this->EmailAddress)) {
4903 return false;
4904 }
4905
4906
4907 $businessMailchimp = new Model_DbTable_BusinessMailchimp($this->ID);
4908 $businessMailchimp->createDeleteTask($oldEmail);
4909
4910 $businessMailchimp->createAddTask();
4911
4912 return true;
4913 }
4914
4915 /**
4916 * Checks if businesses should show in search result
4917 *
4918 *
4919 * @return bool
4920 *
4921 */
4922 public function showInSearchResult()
4923 {
4924 return ($this->availableForListOfSearchResult() and intval($this->search_result_show) === 1);
4925 }
4926
4927 /**
4928 * Add business to search result list
4929 *
4930 * @return bool
4931 *
4932 */
4933 public function addToSearchResult()
4934 {
4935 Nocowboys_Elastic::addBusiness($this->ID);
4936 $this->search_result_show = 1;
4937 return $this->save(true);
4938 }
4939
4940 /**
4941 * Remove business from search result list
4942 *
4943 * @return bool
4944 *
4945 */
4946 public function removeFromSearchResult()
4947 {
4948 Nocowboys_Elastic::deleteBusiness($this->ID);
4949 $this->search_result_show = 0;
4950 return $this->save(true);
4951 }
4952
4953 /**
4954 * Get last payment
4955 *
4956 * @return Model_DbTableRow_Purchase
4957 *
4958 */
4959 public function getLastPayment()
4960 {
4961 $purchaseTable = new Model_DbTable_Purchase();
4962 return $purchaseTable->fetchRow($purchaseTable->select()->where('Successful = 1 AND BusinessID = ?', $this->ID)->order('PurchaseDate DESC'));
4963 }
4964
4965 /**
4966 * Set review underway status for business
4967 * @return mixed
4968 */
4969 public function setReviewUnderway()
4970 {
4971 $this->is_review_underway = 1;
4972 return $this->save();
4973 }
4974
4975 /**
4976 * Check if business is on review audit
4977 * @return bool
4978 */
4979 public function isReviewUnderway()
4980 {
4981 return (int) $this->is_review_underway === 1;
4982 }
4983 }
4984
4985 /**
4986 * Sort function to order correspondence by the date they were sent
4987 *
4988 * @param type $itemA
4989 * @param type $itemB
4990 * @return int
4991 */
4992 function correspondenceSort($itemA, $itemB)
4993 {
4994 $itemADateSent = strtotime($itemA['DateSent']);
4995 $itemBDateSent = strtotime($itemB['DateSent']);
4996
4997 if ($itemADateSent == $itemBDateSent)
4998 {
4999 return 0;
5000 }
5001 return ($itemADateSent < $itemBDateSent) ? 1 : -1;
5002 }