Advertisement
Greenice

Zend Framework Model Example

Jan 31st, 2019
429
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 151.80 KB | None | 0 0
  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.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement