where(\Qs_Db::quoteField('deleted', $alias) . ' = "n"'); return; } protected function _getFromDbSelect($primaryKey) { $select = parent::_getFromDbSelect($primaryKey); static::filterEvents($select); return $select; } public function getListSelect() { if (null === $this->_select) { parent::getListSelect(); static::filterEvents($this->_select); } return $this->_select; } public function getAttendeeObj(array $options = array()) { if (null === $this->_attendeeObj) { $options['eventId'] = $this->getPrimaryKey(); $this->_attendeeObj = new AttendeeObj($options); } return $this->_attendeeObj; } public function delete() { $this->_clearErrors(); if (null === $this->getData()) { $this->_addError(static::MSG_INVALID_RECORD_ID); return false; } $this->_deleteDependency(); $this->_deleteFiles(); return $this->_getTable()->updateByKey(array('deleted' => 'y'), $this->getPrimaryKey()); } public function getEventTeams() { $select = $this->_db->select(); $select->from( $this->_getPair('EventTeam', 'et'), array( 'key' => 'id', 'title', 'attendeeCount' => $this->getAttendeeObj()->getTeamAttendeeCountExpr('et.id') ) ); $select->where('`et`.`eventId` = ?', $this->getPrimaryKey(), \Qs_Db::INT_TYPE); $select->order('et.title'); return $this->_db->fetchAll($select, array(), \Qs_Db::FETCH_GROUP | \Qs_Db::FETCH_UNIQUE); } public function getTeamAttendeeCount($teamId) { return $this->_db->fetchOne( $this->getAttendeeObj()->getTeamAttendeeCountExpr($teamId) ); } /** * @return array [['H:i:s', 'H:i:s'], ...] */ protected function _readTimeRanges() { $select = $this->_db->select(); $select->from($this->_getPair('EventTime', 'et'), array('startTime', 'endTime')); $select->where('et.eventId = ?', $this->getPrimaryKey()); $select->order('et.date'); return $this->_db->fetchAll($select, null, \Qs_Db::FETCH_NUM); } /** * @param string $startDate 'Y-m-d' * @param string $endDate 'Y-m-d' * @param array $timeRanges List of startTime, endTime pairs [['H:i:s', 'H:i:s'], ...] * @return $this */ protected function _saveTimeRanges($startDate, $endDate, array $timeRanges) { $list = array(); $date = DateTime::createFromFormat('Y-m-d', $startDate); $duration = 1 + $date->diff(DateTime::createFromFormat('Y-m-d', $endDate))->days; $interval = new \DateInterval('P1D'); for ($i = 0; $i < $duration; ++$i) { list($startTime, $endTime) = current($timeRanges); $list[] = array( 'eventId' => $this->getPrimaryKey(), 'date' => $date->format('Y-m-d'), 'startTime' => $startTime, 'endTime' => $endTime ); $date->add($interval); next($timeRanges); } $eventTime = $this->_getTable('EventTime'); $eventTime->delete(array('eventId = ?' => $this->getPrimaryKey())); $eventTime->insertList($list); return $this; } /** * Returns email to userId map for specified emails * @param array $emails * @return array Map [$email => $userId, ..] */ public function getUsersIds(array $emails) { if (empty($emails)) { return array(); } $select = $this->_db->select(); $select->from($this->_getPair('User', 'u'), array('email', 'id')); $select->where('`u`.`email` IN(?)', $emails); return $this->_db->fetchAll($select, array(), PDO::FETCH_KEY_PAIR); } /** * Returns userId to email to map for specified ids * @param array $userIds * @return array Map [$userId => $email, ..] */ public function getUsersEmails(array $userIds) { if (empty($userIds)) { return array(); } $select = $this->_db->select(); $select->from($this->_getPair('User', 'u'), array('id', 'email')); $select->where('`u`.`id` IN(?)', $userIds); return $this->_db->fetchAll($select, array(), PDO::FETCH_KEY_PAIR); } /** * Returns list of current and future events * @return \Zend_Db_Select */ public function getSignupEventsSelect() { $select = $this->_db->select(); $select->from($this->_getPair(), array('*')); self::filterEvents($select); $select->where('e.type IN(?)', array(self::TYPE_REGULAR, self::TYPE_GROUP)); $select->where('e.registrationStart < ?', date('Y-m-d H:i:s')); $select->where('e.registrationEnd > ?', date('Y-m-d H:i:s')); $select->order('e.startDate'); return $select; } /** * Returns list of current and future events * @return array */ public function getSignupEvents4Select() { $select = $this->getSignupEventsSelect(); $select->reset(\Zend_Db_Select::COLUMNS)->columns(array('id', 'title')); return $this->_db->fetchAll($select, array(), PDO::FETCH_KEY_PAIR); } public function getShowWaiver() { return ('y' === $this->getData('showWaiver')); } public function getGroupsAllowed() { return (self::TYPE_GROUP === $this->getData('type')); } public function getNonMembersAllowed($eventType = null) { $eventType = (null === $eventType) ? $this->getData('type') : $eventType; return in_array($eventType, array(self::TYPE_REGULAR, self::TYPE_GROUP)); } /** * Required additional fields "registeredCount" * @param array $row * @return $this */ protected function _prepareRegistrationAllowed(array &$row) { $registrationStart = strtotime($row['registrationStart']); $registrationEnd = strtotime($row['registrationEnd']); if ((self::TYPE_REGULAR === $row['type'] || self::TYPE_GROUP === $row['type']) && $registrationStart < time() && $registrationEnd > time() && empty($row['registrationUrl']) && (null === $row['registrationLimit'] || $row['registeredCount'] < $row['registrationLimit']) ) { $row['registrationAllowed'] = true; } else { $row['registrationAllowed'] = false; } return $this; } public function setPrimaryKey($_primaryKey) { $this->_eventData = null; $this->_attendeeObj = null; return parent::setPrimaryKey($_primaryKey); } public function clearData() { $this->_eventData = null; $this->_attendeeObj = null; return parent::clearData(); } public function getEventData() { if (null === $this->_eventData) { $this->_eventData = ($this->hasPrimaryKey()) ? $this->_getFromDb($this->getPrimaryKey()) : null; } return $this->_eventData; } /** * @param array $data * [ * 'attendType' => 'myself' | 'myselfOther' | 'other', * 'team' => null | [ * 'type' => 'newTeam' | 'existingTeam' | 'individual', * 'teamName' => null | string, * 'teamId' => null | int, * ], * 'attendee' => [ * [ * 'mode' => 'current' | 'choose', * 'type' => 'member' | 'nonmember', * 'id' => null|int '', * 'firstName' => null|string '', * 'lastName' => null|string '', * 'email' => null|string '', * ] * ] * * ] * @return [] * @throws \Exception * @throws \Qs_Exception_EmptyPropertyException */ protected function _prepareSignupFormData($data) { if (!$this->hasPrimaryKey()) { throw new \Qs_Exception_EmptyPropertyException($this, '_primaryKey'); } if (null == ($event = $this->getEventData())) { throw new Exception('Event not found'); } if (static::TYPE_GROUP === $event['type']) { $teamId = (isset($data['team'])) ? $this->_insertTeam($event['id'], $data['team']) : null; } elseif (static::TYPE_REGULAR === $event['type']) { $teamId = null; } else { throw new Exception('Event with type "' . $event['type'] . '" does not support registration'); } $prepared = array(); $memberPrice = (float) $event['memberPrice']; $regularPrice = (float) $event['regularPrice']; // prepare attendees data, calculate total $userInfoList = null; if (($userIds = array_filter(\Qs_Array::fetchColumn($data['attendee'], 'id')))) { $userInfoList = $this->_getUserInfoList($userIds); } $total = 0; $attendees = array(); foreach ($data['attendee'] as $idx => $row) { $attendee = array( 'teamId' => $teamId, 'userId' => null, 'firstName' => null, 'lastName' => null, 'email' => null, 'amount' => null, 'waiverAgreed' => isset($row['waiverAgreed']) ? $row['waiverAgreed'] : null, ); if (AttendeeForm::TYPE_MEMBER === $row['type']) { $total = bcadd($total, $memberPrice); $userId = $row['id']; $attendee['amount'] = $memberPrice; $attendee['userId'] = $userId; if (array_key_exists($userId, $userInfoList)) { $userInfo = $userInfoList[$userId]; $attendee['firstName'] = $userInfo['firstName']; $attendee['lastName'] = $userInfo['lastName']; $attendee['email'] = $userInfo['email']; } } elseif (AttendeeForm::TYPE_NONMEMBER === $row['type']) { $total = bcadd($total, $regularPrice); $attendee['amount'] = $regularPrice; $attendee['firstName'] = $row['firstName']; $attendee['lastName'] = $row['lastName']; $attendee['email'] = $row['email']; } else { continue; } $attendees[$idx] = $attendee; } $prepared['attendees'] = $attendees; $prepared['total'] = $total; return $prepared; } /** * @param int $eventId * @param array $team * - string $type.type newTeam | existingTeam | individual * - string $type.teamName * - int $type.teamId * @throws \Exception * @return int|null */ protected function _insertTeam($eventId, array $team) { $type = $team['type']; if (TeamForm::TYPE_INDIVIDUAL === $type) { $teamId = null; } elseif (TeamForm::TYPE_EXISTING_TEAM === $type) { $teamId = (int) $team['teamId']; } elseif (TeamForm::TYPE_NEW_TEAM === $type) { $teamId = (int) $this->_getTable('EventTeam')->insert(array( 'eventId' => (int) $eventId, 'title' => $team['teamName'] )); } else { throw new Exception('Unknown team type: "' . $type . '"'); } return $teamId; } /** * @param $userIds * @return array [userId => ['firstName', 'lastName', 'email'], ...] */ protected function _getUserInfoList(array $userIds) { if (empty($userIds)) { return array(); } $select = $this->_db->select(); $select->from($this->_getPair('User', 'u'), array('id', 'firstName', 'lastName', 'email')); $select->where('`u`.`id` IN(?)', $userIds); return $this->_db->fetchAll($select, array(), Qs_Db::FETCH_GROUP | Qs_Db::FETCH_UNIQUE); } protected function _updateParentAttendeeIds() { $_tableName = $this->_getTableName('EventAttendee'); $_eventId = (int) $this->getPrimaryKey(); $sql = "UPDATE {$_tableName} AS ea SET ea.parentAttendeeId = ea.id " . "WHERE ea.eventId = {$_eventId} AND ea.parentAttendeeId = 0"; $this->_db->query($sql); return $this; } protected function _getSignupNotificationData() { /** @var \Qs_Doc $doc */ $doc = Zend_Registry::get('doc'); $event = $this->getEventData(); $data = array( 'title' => htmlspecialchars($event['title']), 'location' => htmlspecialchars($event['location']), 'date' => $doc->getView()->dateRange($event['startDate'], $event['endDate']), 'time' => $doc->getView()->timeRange($event['timeRanges']), 'link' => View::getPageUrlByType(ConfigForm::TYPE_DETAILS) . '/view/' . $event['id'], ); foreach ($data as &$item) { $item = empty($item) ? '-' : $item; } unset($item); return $data; } public function sendSignupNotification($parentAttendeeId) { if (empty($parentAttendeeId) || null == ($teamAttendees = $this->getAttendeeObj()->getTeamGroupedAttendees($parentAttendeeId)) ) { return $this; } if ($teamAttendees && ($firstTeam = reset($teamAttendees)) && ($firstAttendee = reset($firstTeam))) { if ($firstAttendee['eventId'] !== $this->getPrimaryKey()) { $this->setPrimaryKey($firstAttendee['eventId']); } } $event = $this->getEventData(); $prefix = (self::TYPE_GROUP === $event['type']) ? 'eventSignupNotificationGroup' : 'eventSignupNotification'; $from = App_Settings_Obj::get($prefix . 'From'); $subject = App_Settings_Obj::get($prefix . 'Subject'); $template = App_Settings_Obj::get($prefix . 'Body'); $placeholders = array(); foreach ($this->_getSignupNotificationData() as $field => $value) { $placeholders['{' . $field . '}'] = $value; } $template = str_replace(array_keys($placeholders), array_values($placeholders), $template); foreach ($teamAttendees as $attendees) { if (self::TYPE_GROUP === $event['type']) { $attendeeEmails = array(); $attendeesHtml = ''; foreach ($attendees as $attendee) { $attendeeEmails[] = $attendee['email']; $_firstName = htmlspecialchars($attendee['firstName']); $_lastName = htmlspecialchars($attendee['lastName']); $attendeesHtml .= "{$_firstName } {$_lastName}
"; } $placeholders = array( '{teamName}' => (isset($attendee) && $attendee['teamName']) ? htmlspecialchars($attendee['teamName']) : 'Registered as Individual', '{attendees}' => $attendeesHtml, ); $body = str_replace(array_keys($placeholders), array_values($placeholders), $template); } else { $attendeeEmails = \Qs_Array::fetchCol($attendees, 'email'); $body = $template; } foreach ($attendeeEmails as $email) { $mail = new Qs_Mail(); $mail->setFrom($from); $mail->setSubject($subject); Qs_Mail::cutImageBaseUrl($body, constant('BASE_URL')); $mail->setHtml($body, null, constant('WWW_PATH')); $mail->addTo($email); $mail->send(); } } return $this; } protected function _getStartDateTimeExpr($eventAlias) { $select = $this->_db->select(); $select->from( $this->_getPair('EventTime', 'et'), array('start' => new Zend_Db_Expr('CONCAT(et.date, " ", et.startTime)')) ); $select->where("et.eventId = {$eventAlias}.id"); $select->order('id'); $select->limit(1); return new Zend_Db_Expr('(' . $select . ')'); } public function teamExists($title) { $select = $this->_db->select(); $select->from($this->_getPair('EventTeam', 'et'), array('id')); $select->where('et.eventId = ?', $this->getPrimaryKey(), Qs_Db::INT_TYPE); $select->where('et.title = ?', $title); $select->limit(1); return (bool) $this->_db->fetchOne($select); } /** * Returns related events with '2016 PWX' in title available for registration */ public function getRelatedEventIds() { $eventId = $this->getPrimaryKey(); if (!$eventId || !($event = $this->getEventData()) || false === strpos($event['title'], self::PREFIX_2016PWX)) { return null; } $select = $this->getSignupEventsSelect(); $select->reset(\Zend_Db_Select::COLUMNS)->columns(array('id')); $select->where('e.id != ?', $eventId); $select->where('e.type = ?', $event['type']); $select->where('e.title LIKE ?', '%' . self::PREFIX_2016PWX . '%'); return $this->_db->fetchCol($select); } protected function _prepareRowFee(array &$row) { $fee = App_Settings_Obj::get('payPalFee'); $row['memberPriceFee'] = '0.0000'; $row['regularPriceFee'] = '0.0000'; if (0 != $fee) { $row['memberPriceFee'] = $this->calcFee($row['memberPrice']); $row['regularPriceFee'] = $this->calcFee($row['regularPrice']); } return $this; } public function calcFee($price) { static $fee; if (null === $fee) { $fee = App_Settings_Obj::get('payPalFee'); } return Math::Div(Math::Mul($price, $fee, 4), 100, 4); } protected function _prepareRow(array &$row) { $this->_prepareRowFee($row); return parent::_prepareRow($row); } }