From: Steve Sutton Date: Thu, 17 Jul 2014 20:16:10 +0000 (-0400) Subject: Setting up Events X-Git-Tag: VV1^2~87 X-Git-Url: http://cvs2.gaslightmedia.com/gitweb/?a=commitdiff_plain;h=f10f620ab6450266028f54d33bdfada85c30341b;p=web%2FCityofMI.git Setting up Events Output into template --- diff --git a/Toolkit/Events/SmallCal.php b/Toolkit/Events/SmallCal.php index 279c7c1..713a7ac 100644 --- a/Toolkit/Events/SmallCal.php +++ b/Toolkit/Events/SmallCal.php @@ -82,9 +82,10 @@ class Toolkit_Events_SmallCal */ public function __construct(PDO $pdo, $month, $year) { - $this->dbh = $pdo; - $this->_month = ctype_digit($month) ? $month: date('n'); - $this->_year = ctype_digit($year) ? $year: date('Y'); + $this->dbh = $pdo; + $this->_month = filter_var($month, FILTER_VALIDATE_INT) ? $month: date('n'); + $this->_year = filter_var($year, FILTER_VALIDATE_INT) ? $year: date('Y'); + $this->baseURL = MEDIA_BASE_URL; } // }}} // {{{ getEventsForMonth() @@ -130,236 +131,36 @@ class Toolkit_Events_SmallCal $this->_year ) ); - // $sDates will be our $this->_selectedDays array; - $sDates = array(); - // get all event for this month only - $sql = " - SELECT id,bdate,edate,daysow,dayom,reacur,weekom - FROM event - WHERE bdate <= :end - AND edate >= :begin - AND visable = 't' - ORDER BY bdate,edate"; - - try { - $stmt = $this->dbh->prepare($sql); - $stmt->bindParam(":begin", $begin, PDO::PARAM_STR); - $stmt->bindParam(":end", $end, PDO::PARAM_STR); - $stmt->execute(); - while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { - // timestamp of events starting date - $bdate = strtotime($row['bdate']); - // timestamp of events ending date - $edate = strtotime($row['edate']); - // if the dates are the same then add it to the - // selected dates array - if ($bdate == $edate) { - $sDates[] = new Calendar_Day( - date('Y', $bdate), - date('n', $bdate), - date('d', $bdate) - ); - } else if ($edate > $bdate) { - // if the end date is larger than the starting one - // only work in this month - // timestamp for start of month - $startOfMonth = mktime( - 0, - 0, - 1, - $this->_month, - 1, - $this->_year - ); - // timestamp for end of month - $endOfMonth = mktime( - 0, - 0, - 1, - $this->_month, - date('t', $startOfMonth), - $this->_year - ); - // update the start date if needed - if ($startOfMonth >= $bdate) { - $bdate = $startOfMonth; - } - // update the end date if needed - if ($endOfMonth <= $edate) { - $edate = $endOfMonth; - } - // find events ord - if ($row['weekom']) { - if ($row['daysow']) { - $ri = 1; - for ($r = 0; $r < 7; $r++) { - if ($row['daysow'] & $ri) { - $ord[] = $this->ordinalDay( - $row['weekom'], - $r, - $this->_month, - $this->_year - ); - } - $ri = $ri << 1; - } - } else { - $ord = null; - } - } else { - $ord = null; - } - // seconds in one day = 86400 - // loop through the days in this month - for ($i = $bdate; $i <= $edate; $i = $i + 86400) { - $cur_dow = date("w", $i); - switch($cur_dow) { - case 0: - $cur_dow = 1; - break; - case 1: - $cur_dow = 2; - break; - case 2: - $cur_dow = 4; - break; - case 3: - $cur_dow = 8; - break; - case 4: - $cur_dow = 16; - break; - case 5: - $cur_dow = 32; - break; - case 6: - $cur_dow = 64; - break; - } - // if the event is not a recurring one then add it as - // selectedDay - if (!$row['reacur']) { - $sDates[] = new Calendar_Day( - date('Y', $i), - date('n', $i), - date('d', $i) - ); - } else if ($row['reacur'] - && !$row['dayom'] - && $row['daysow'] - && (int)$cur_dow & $row['daysow'] - ) { - // if the event is recurring and the daysow are set - if ($row['weekom'] == 9) { - // every other week - unset($eWeeks); - $fWeekNum = date("W", $bdate); - if (date('w', $bdate) == 0) { - $fWeekNum++; - } - $lWeekNum = date("W", $edate); - if (date('w', $edate) == 0) { - $lWeekNum++; - } - for ($fi = $fWeekNum; - $fi <= $lWeekNum; - $fi = $fi + 2 - ) { - $eWeeks[] = $fi; - } - $cDateWeek = date("W", $i); - if (date('w', $i) == 0) { - $cDateWeek++; - } - if (in_array($cDateWeek, $eWeeks)) { - $sDates[] = new Calendar_Day( - date('Y', $i), - date('n', $i), - date('d', $i) - ); - } - } else if ($row['weekom'] && is_array($ord)) { - // if the ord is set (every 1st 2nd 3rd etc.) - foreach ($ord as $ordinal) { - if (date('m-d-Y', $i) == date('m-d-Y', $ordinal)) { - $sDates[] = new Calendar_Day( - date('Y', $i), - date('n', $i), - date('d', $i) - ); - } - } - } else if (!$row['weekom'] - && (int)$cur_dow & $row['daysow'] - ) { - // if daysow is set but not weekom - $sDates[] = new Calendar_Day( - date('Y', $i), - date('n', $i), - date('d', $i) - ); - } - } else if ($row['reacur'] && $row['dayom'] - && (int)$row['dayom'] == (int)date('j', $i) - ) { - // if the dayom is set - $sDates[] = new Calendar_Day( - date('Y', $i), - date('n', $i), - date('d', $i) - ); - } - } - } - } - $this->_selectedDays = $sDates; - } catch(PDOException $e) { - die($e->getMessage()); + if (!defined('COMMON_EVENTS_SCHEMA')) { + define('COMMON_EVENTS_SCHEMA', 'events'); } - } - // }}} - // {{{ ordinalDay( - /** - * ordinalDay - * get ordinal (th) day for given timestamp - * - * @param int $ord 1-5 1st 2nd 3rd (etc.) - * @param int $day day - * @param int $month month - * @param int $year year - * - * @access public - * @return int - */ - function ordinalDay($ord, $day, $month, $year) - { - $firstOfMonth = mktime( - 0, - 0, - 1, - $month, - $day, - $year - ); - $lastOfMonth = mktime( - 0, - 0, - 1, - $month, - date("t", $firstOfMonth), - $year - ); - $dayOccurs = 0; + if (!defined('COMMON_APP_BASE')) { + define('COMMON_APP_BASE', '/var/www/server/CommonApps/'); + } + require_once COMMON_APP_BASE . 'EventCalendar/V1/models/EventMapper.php'; + $eventMapper = new EventMapper(Toolkit_Database::getInstance()); - for ($i = $firstOfMonth; $i < $lastOfMonth ; $i += 86400) { - if (date("w", $i) == $day) { - $dayOccurs++; - if ($dayOccurs == $ord) { - $ordDay = $i; - } + $events = $eventMapper->fetchFilteredEventsFromTimes( + "et.ending >= '{$begin}' AND et.starting <= '{$end}'", + null, + false, + false + ); + $this->_selectedDays = array(); + foreach ($events as $event) { + //echo '
'.print_r($events, true).'
'; + if(preg_match('%([0-9]{2})/([0-9]{2})/([0-9]{4})%', $event->getStarting(), $dateParts)) { + //echo '
'.print_r($dateParts, true).'
'; + $this->_selectedDays[] = new Calendar_Day( + $dateParts[3], + $dateParts[1], + $dateParts[2] + ); } } - return $ordDay; + //echo '
'.print_r($this->_selectedDays, true).'
'; + //echo '
'.print_r($events, true).'
'; + //exit; } // }}} // {{{ toHtml() @@ -374,11 +175,12 @@ class Toolkit_Events_SmallCal { $GLOBALS['bottomScripts'][] = $this->baseURL . 'Toolkit/Events/libjs/calendar.js'; - $linkPage = MEDIA_BASE_URL . 'index.php?'; + $linkPage = BASE_URL . 'index.php?'; $page = $linkPage; - $page .= 'catid=' . EVENT_PAGE . '&flat=1&'; + $page .= 'catid=' . EVENT_PAGE . '&'; // create the class array with events $this->getEventsForMonth(); + //var_dump($this->_selectedDays);exit; // create the calendar_month_weekdays object $Month = new Calendar_Month_Weekdays( $this->_year, // year @@ -398,9 +200,17 @@ class Toolkit_Events_SmallCal $out = "
\n"; if ($this->showPrevNextLinks) { - $prevLink = '<<'; + $currentCalendar + = ($Month->thisMonth() == date('n') && $Month->thisYear() == date('Y')) + ? true + : false; + if (!$currentCalendar) { + $prevLink = '<<'; + } else { + $prevLink = ' '; + } $nextLink = '>>'; @@ -410,7 +220,7 @@ class Toolkit_Events_SmallCal } $out .= ' - ', 'descr'); + $renderer->setElementTemplate('', 'submit_rmv'); + + if ($this->useCaptcha) { + $renderer->setElementTemplate('', 'captcha_question'); + $renderer->setElementTemplate('', 'captcha_rmv'); + } + } + + // }}} + // {{{ toHtml() + + /** + * Handles how to display the current step the user is at in the form + * + * destroying and resetting the captcha value dis-allows someone from + * re-sending a form on a previous captcha. + * + * @return string form HTML state + * @access public + */ + public function toHtml() + { + $this->setupRenderers(); + if ($this->validate()) { + $this->captchaQuestion->destroy(); + $this->cleanForm(); + + if ($this->process(array(&$this, 'processData'), $this->mergeFiles)) { + $this->freeze(); + $this->emailOwner(); + $output = $this->successMsg; + } + $this->sent = true; + } elseif ($this->isSubmitted()) { + if ($this->useCaptcha) { + $this->captchaQuestion->destroy(); + $this->captchaAnswer->setValue(''); + } + $output = $this->errorMsg; + $GLOBALS['topScripts'][] + = MEDIA_APP_BASE_URL + . 'libjs/jqueryui/1.8.13/js/jquery-ui-1.8.13.custom.min.js'; + $GLOBALS['styleSheets'][] + = MEDIA_APP_BASE_URL + . 'libjs/jqueryui/1.8.13/development-bundle/themes/base/jquery.ui.all.css'; + $GLOBALS['bottomScripts'][] = MEDIA_APP_BASE_URL . 'libjs/textlimit.js'; + $GLOBALS['topScripts'][] + = 'http://maps.googleapis.com/maps/api/js?sensor=true'; + $GLOBALS['bottomScripts'][] + = MEDIA_BASE_URL . 'Toolkit/Maps/geoCoder.js'; + $GLOBALS['bottomScripts'][] + = MEDIA_BASE_URL . 'Toolkit/Events/libjs/addEvent.js'; + $output .= parent::toHtml(); + } else { + if ($this->useCaptcha) { + $this->captchaQuestion->destroy(); + $this->captchaAnswer->setValue(''); + } + $GLOBALS['topScripts'][] + = MEDIA_APP_BASE_URL + . 'libjs/jqueryui/1.8.13/js/jquery-ui-1.8.13.custom.min.js'; + $GLOBALS['styleSheets'][] + = MEDIA_APP_BASE_URL + . 'libjs/jqueryui/1.8.13/development-bundle/themes/base/jquery.ui.all.css'; + $GLOBALS['bottomScripts'][] = MEDIA_APP_BASE_URL . 'libjs/textlimit.js'; + $GLOBALS['topScripts'][] + = 'http://maps.googleapis.com/maps/api/js?sensor=true'; + $GLOBALS['bottomScripts'][] + = MEDIA_BASE_URL . 'Toolkit/Maps/geoCoder.js'; + $GLOBALS['bottomScripts'][] + = MEDIA_BASE_URL . 'Toolkit/Events/libjs/addEvent.js'; + $output = parent::toHtml(); + } + return $output; + } + + // }}} +} + +?> diff --git a/Toolkit/Events/libjs/smallCal.js b/Toolkit/Events/libjs/smallCal.js new file mode 100644 index 0000000..aa46048 --- /dev/null +++ b/Toolkit/Events/libjs/smallCal.js @@ -0,0 +1,24 @@ +var Calendar = +{ + init: function() + { + Calendar.setLinks(); + }, + setLinks: function() + { + $(".calLink").click(function(){ + $.ajax({ + type: "GET", + url: "calendar.php", + data: $(this).attr('rel'), + success: function(msg){ + $("#eventCalendar").html(msg); + Calendar.setLinks(); + } + }); + return false; + }); + } +}; + +$(document).ready(Calendar.init); diff --git a/Toolkit/Events/showCalendar.php b/Toolkit/Events/showCalendar.php new file mode 100644 index 0000000..8ac643a --- /dev/null +++ b/Toolkit/Events/showCalendar.php @@ -0,0 +1,10 @@ +toHtml(); diff --git a/Toolkit/Page.php b/Toolkit/Page.php index e34db36..27dbf6a 100755 --- a/Toolkit/Page.php +++ b/Toolkit/Page.php @@ -147,6 +147,9 @@ class Toolkit_Page $GLOBALS['styleSheets'] = array(); // Resources needed for every page. $GLOBALS['topScripts'][] = JQUERY_CDN_JS; + $GLOBALS['topScripts'][] = MEDIA_BASE_URL . 'js/vendor/modernizr.js'; + $GLOBALS['bottomScripts'][] = MEDIA_BASE_URL . 'js/foundation.min.js'; + $GLOBALS['bottomScripts'][] = MEDIA_BASE_URL . 'js/foundation/foundation.offcanvas.js'; } private function _video() @@ -346,6 +349,16 @@ class Toolkit_Page Toolkit_Toolbox_GatewayAbstract $pageGateway ) { if (defined('COMMON_EVENTS') && COMMON_EVENTS) { + $GLOBALS['bottomScripts'][] + = MEDIA_BASE_URL . 'Toolkit/Events/libjs/smallCal.js'; + $month = filter_var($_REQUEST['month'], FILTER_VALIDATE_INT); + $year = filter_var($_REQUEST['year'], FILTER_VALIDATE_INT); + $cal = new Toolkit_Events_SmallCal( + Toolkit_Database::getInstance(), + $month, + $year + ); + $this->smallCal = $cal->toHtml(); if (!defined('COMMON_APP_BASE')) { define('COMMON_APP_BASE', '/var/www/server/CommonApps/'); } @@ -354,17 +367,68 @@ class Toolkit_Page require_once COMMON_APP_BASE . 'EventCalendar/V1/models/EventMapper.php'; $eventMapper = new EventMapper(Toolkit_Database::getInstance()); - $events = $eventMapper->fetchFilteredEvents( - "slideshow is true" + $events = $eventMapper->fetchFilteredEventsFromTimes( + "slideshow is true", + null, + null, + true ); if (is_array($events)) { foreach ($events as $event) { + if (defined('MEMBERS_DB') && MEMBERS_DB) { + $hasLocation + = (!$event->getHideAddress && ($event->hasLocation() || $event->getMember())); + } else { + $hasLocation + = (!$event->getHideAddress && ($event->hasLocation())); + } + if (defined('MEMBERS_DB') + && MEMBERS_DB + && $hasLocation + && $event->getMember() + && $event->getUseMemberLocation() + ) { + try { + $sql = " + SELECT m.member_name as place,m.street as address, + c.city_name as city,s.state_name as state + FROM member m, city c, state s + WHERE m.city_id = c.city_id + AND s.state_id = s.state_id + AND member_id = :member_id"; + $getMemberLocation = $this->dbh->prepare($sql); + $getMemberLocation->bindParam(':member_id', $event->getMember(), 'PDO::PARAM_INT'); + $getMemberLocation->execute(); + $location = $getMemberLocation->fetch(PDO::FETCH_ASSOC); + } catch(PDOException $e) { + Toolkit_Common::handleError($e); + } + + } else if ($hasLocation && $event->hasLocation()) { + $location = array( + 'place' => $event->getPlace(), + 'address' => $event->getAddress(), + 'city' => $event->getCity(), + 'state' => $event->getState(), + 'zip' => $event->getZip() + ); + } else { + $location = null; + } + $category + = ($event->getCategory()) + ? $event->getCategory()->getName() + : ''; $this->events[] = array( 'id' => $event->getId(), 'href' => $event->getHref(), - 'bdate' => $event->getDates(), + 'dates' => $event->getDates(), 'header' => strip_tags($event->getHeader()), 'descr' => substr(strip_tags($event->getDescription()), 0, 150), + 'intro' => strip_tags($event->getIntro()), + 'loc' => $location, + 'times' => $event->getEventTimes(), + 'cat' => $category, 's-img' => (($event->getImage()) ? FILE_SERVER_URL . IS_OWNER_ID . '/eventSlider/' . $event->getImage() @@ -453,7 +517,7 @@ class Toolkit_Page $this->pageId = $this->_catid; } $this->_navigationFactory->setGateway($this->_pageGateway); - $this->mainNav = $this->_getMainNav($this->_catid); + $this->mainNav = $this->_getMainNav($this->_catid); $this->sideNav = $this->_getSideNav($this->_catid); $this->newsletterAction = Toolkit_Template_Page::getSeoUrl( @@ -566,10 +630,10 @@ class Toolkit_Page { $nav = $this->_navigationFactory->createMainNav(); $mainNavArray = $nav->getNavStructure($this->_pageGateway, $catid); - + return $nav->renderPageNav($mainNavArray, 'tree'); } - + private function _getArrayToListNav($catid) { $sideNav = new Toolkit_Template_Navigation_AllInOneSideNav( @@ -579,7 +643,7 @@ class Toolkit_Page $html = $this->_arrayToListHTML($nav, 0, "mainNav"); return ($html) ? $html : ''; } - + private function _arrayToListHTML($array, $level = 0, $className = null) { static $tab = "\t", $format = '%s'; diff --git a/admin/CommonEvents/.htaccess b/admin/CommonEvents/.htaccess new file mode 100644 index 0000000..7f2df55 --- /dev/null +++ b/admin/CommonEvents/.htaccess @@ -0,0 +1,3 @@ +AddDefaultCharset utf-8 +php_flag register_globals off +php_flag magic_quotes_gpc off diff --git a/admin/CommonEvents/index.php b/admin/CommonEvents/index.php new file mode 100644 index 0000000..36a4a66 --- /dev/null +++ b/admin/CommonEvents/index.php @@ -0,0 +1,28 @@ +getMessage()); +} diff --git a/config/application.ini b/config/application.ini index f0febcc..be611ca 100644 --- a/config/application.ini +++ b/config/application.ini @@ -49,11 +49,11 @@ coupons.application = Off ; Turn the event application On or Off eventdb.application = On ; Turn the Events Common Application On or Off -eventdb.commonEvents = Off +eventdb.commonEvents = On ; The page id in the toolbox that holds the event calendar -eventdb.event_page = Off +eventdb.event_page = 10 ; Turn the home page events module On or Off for the event application -eventdb.home_events = Off +eventdb.home_events = On ; Turn the events management application On or Off event_management.application = Off diff --git a/static/10.phtml b/static/10.phtml new file mode 100755 index 0000000..787519e --- /dev/null +++ b/static/10.phtml @@ -0,0 +1,25 @@ +toHTML($this->keywordReplacement); +} + diff --git a/templates/template.html b/templates/template.html index f8c0a45..b68c934 100644 --- a/templates/template.html +++ b/templates/template.html @@ -1,96 +1,232 @@ - - - -{pageTitle:h} - - - - -{styles:h} -{topScripts:h} - - -
-
-
- - - -
- - -
-
-
-

Page Header

-
- toolboxTMP (26K) -
This is the imagecaption
-
-

Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access.

-

Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access.

-

Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access.

-
-
-

Header

-
- toolboxTMP (26K) -
This is the imagecaption
-
-

Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access.

-

Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access.

-

Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access.

-
-
-

Header

-
- toolboxTMP (26K) -
This is the imagecaption
-
-

Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access.

-

Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access.

-

Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access.

-
-
-
- -
    -
  • AAD
  • -
  • ABD
  • -
  • ACMS
  • -
  • ASDS
  • -
- -
-
-{bottomScripts:h} - - + + + + + + {pageTitle:h} + {styles:h} + + + {topScripts:h} + + + {if:isHomePage} + + {else:} + + {end:} +
+
+ + + + + + +
+
+ +
+ + + + +
+
+
+ {toolboxContent:h} +
+
+ +
+
+
+ + +
+ + + + + +
+
+ {bottomScripts:h} + + + + + \ No newline at end of file
' . $prevLink . '' + ' . $monthText->thisMonthName() . ' ' . $Month->thisYear() @@ -450,4 +260,3 @@ class Toolkit_Events_SmallCal } // }}} } -?> diff --git a/Toolkit/Events/libjs/AddCommonEventForm.php b/Toolkit/Events/libjs/AddCommonEventForm.php new file mode 100644 index 0000000..18e4a6e --- /dev/null +++ b/Toolkit/Events/libjs/AddCommonEventForm.php @@ -0,0 +1,1045 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: AddEventForm.php,v 1.20 2010/07/04 23:58:22 jamie Exp $ + * @link http://demo.gaslightmedia.com + */ + +/** + * New Event Form + * + * @category Toolkit + * @package Events + * @author Steve Sutton + * @copyright 2012 Gaslight Media + * @license http://www.gaslightmedia.com Gaslightmedia + * @link http://demo.gaslightmedia.com + */ +class Toolkit_Events_AddCommonEventForm + extends Toolkit_FormBuilder + implements Toolkit_Form +{ + // {{{ properties + + /** + * Table in Database which holds the contact data + * + * @var string + * @access public + */ + public $tableName = 'events.events'; + + /** + * Table meta data + * + * This is used when inserting/updating data for the records + * so the PDO's can use explicit data types for the parameters. + * + * @var array + * @access public + */ + public $tableMetaData; + + /** + * Who to send the email to when the contact form is submitted + * + * If you leave this blank, its value will get set to the OWNER_EMAIL + * in the constructor. + * + * If you ***DO NOT*** want any emails to go out when the form is submitted + * then set the value to false. Do not set it to 0 for false, because the + * check uses a strict type check to determine if the value is actually + * false. This is what allows for the empty value as an option, which sets + * the value to OWNER_EMAIL and won't override the $email property if + * this class gets subclassed and the value for this property gets set in + * the properties of the subclass and not in the constructor after this + * constructor function is called. + * + * tongue twister...I know. + * + * protected $email = false; + * + * + * @var unknown + * @access protected + */ + protected $email; + + /** + * From header in the owner email + * + * This just sets the From header in the owner email + * SITENAME + * + * It gets set to the constant SITENAME in the constructor if you leave + * empty here, but you can set it to something different here to override + * that if you desire. + * + * @var unknown + * @access protected + */ + protected $siteName; + + /** + * Email subject and

header in email + * + * It gets set in the constructor if you leave empty here, but you + * can set it to something different here to override that if you desire. + * + * @var string + * @access protected + */ + protected $subject = 'New Event Submission'; + + /** + * Message to display if the form is successfully submitted + * + * @var string + * @access protected + */ + protected $successMsg = ' + +
+ Your event has been successfully added to the events calendar, + however will not be visible until it has been approved by + the Web site administrator. Thank You. +
'; + + /** + * Extra rules for processesing + * + * This registers the Zip validation rules (and any others listed) for + * QuickForm. + * + * Zip validation checks both US and Canadian Zip codes + * + * @var array + * @access protected + */ + protected $registeredRules = array( + 'phone', + array( + 'checkEmail', + 'callback', + 'email', + 'Validate' + ), + array( + 'checkURI', + 'callback', + 'uri', + 'Validate' + ) + ); + + /** + * Options for flexy templating engine + * + * Pulls the preset options from the setup.phtml file + * overwrites the templateDir and compileDir to match this classes needs + * + * @var array + * @access protected + */ + protected $flexyOptions; + + protected $eventMapper; + + // }}} + // {{{ __construct() + + /** + * Class constructor + * + * @param PDO $pdo PHP Data Object + * @param string $formName Form's name. + * @param string $method (optional)Form's method defaults to 'POST' + * @param string $action (optional)Form's action + * @param string $target (optional)Form's target defaults to '_self' + * @param mixed $attributes (optional)Extra attributes for
tag + * @param bool $trackSubmit (optional)Whether to track if the form was + * submitted by adding a special hidden field + * + * @access public + */ + public function __construct( + PDO $pdo, + $formName, + $method = 'post', + $action = '', + $target = '', + $attributes = null, + $trackSubmit = false, + EventMapper $eventMapper + ) { + parent::__construct( + $formName, $method, $action, $target, $attributes, $trackSubmit + ); + + $this->dbh = $pdo; + $this->eventMapper = $eventMapper; + + if ($this->email !== false && empty($this->email)) { + // Set to false to turn off email function. + $this->email = ADD_EVENT_EMAIL; + } + if (empty($this->siteName)) { + $this->siteName = SITENAME; + } + if (empty($this->subject)) { + $this->subject = 'Contact Request from website ' . SITENAME; + } + + $this->flexyOptions = $GLOBALS['flexyOptions']; + $this->flexyOptions['templateDir'] = dirname(__FILE__) . "/templates/"; + $this->flexyOptions['compileDir'] = dirname(__FILE__) . "/templates/compiled/"; + + $var = basename(__FILE__, '.php'); + + $callbackUrl = MEDIA_BASE_URL; + + $this->captchaOptions = array( + 'width' => 100, + 'height' => 50, + 'callback' => "{$callbackUrl}Toolkit/qfcaptcha.php?var=$var", + 'sessionVar' => $var, + 'imageOptions' => array( + 'font_size' => 16, + 'font_path' => GLM_APP_BASE . 'glmPEAR/Image/Canvas/Fonts/', + 'font_file' => 'times.ttf', + 'background_color' => '#cccccc', + 'obfuscation' => false, + 'angle' => true, + ), + ); + } + + // }}} + // {{{ checkDate() + + /** + * Validate date input + * + * allows for empty dates to be valid + * + * @param array $date date group from form + * + * @return boolean true if valid, false if not + * @access public + */ + public function checkDate($date) + { + if (!$date) { + return true; + } else { + return Validate::date($date, array('format' => '%m/%d/%Y')); + } + } + + // }}} + // {{{ checkDateRange() + + /** + * Validate date input + * + * allows for empty end date to be valid + * + * @param array $d date group from form + * + * @return boolean true if valid, false if not + * @access public + */ + public function checkDateRange(array $d) + { + if (!$this->hasEndDate($d[1])) { + // no end date is a valid date range + return true; + } + $pattern = '/([0-9]{2})\/([0-9]{2})\/([0-9]{4})/'; + if (preg_match($pattern, $d[0], $m)) { + $t1 = mktime(0, 0, 0, (int) $m[1], (int) $m[2], (int) $m[3]); + $bdate = new Date($t1); + } + if (preg_match($pattern, $d[1], $m)) { + $t2 = mktime(0, 0, 0, (int) $m[1], (int) $m[2], (int) $m[3]); + $edate = new Date($t2); + } + if ($bdate && $edate) { + // 0 if the dates are equal - valid + // -1 if $bdate is before $edate - valid + // 1 if $bdate is after $edate - invalid + $res = Date::compare($bdate, $edate); + return ($res !== 1); + } + return true; + } + + // }}} + // {{{ configureElements() + + /** + * Form element definitions + * + * @return void + * @access public + */ + public function configureElements() + { + $e = array(); + + // All Elements are created here. This includes group element definitions. + $e[] = array( + 'type' => 'header', + 'name' => 'eventInfoHdr', + 'display' => 'Event Information' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'header', + 'display' => 'Event Name' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'starting', + 'display' => 'Start Date', + 'opts' => array('id' => 'sdate') + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'ending', + 'display' => 'End Date', + 'opts' => array('id' => 'edate') + ); + $e[] = array( + 'type' => 'date', + 'req' => false, + 'name' => 'btime', + 'display' => 'Start Time', + 'opts' => array( + 'format' => 'h : i A', + 'addEmptyOption' => true, + 'emptyOptionValue' => '', + 'emptyOptionText' => array( + 'h' => 'hh', + 'i' => 'mm', + 'A' => 'am/pm' + ), + 'optionIncrement' => array( + 'i' => 15, + ), + ), + 'error' => 'ERROR: You must select a start time!', + ); + $e[] = array( + 'type' => 'date', + 'req' => false, + 'name' => 'etime', + 'display' => 'End Time', + 'opts' => array( + 'format' => 'h : i A', + 'addEmptyOption' => true, + 'emptyOptionValue' => '', + 'emptyOptionText' => array( + 'h' => 'hh', + 'i' => 'mm', + 'A' => 'am/pm' + ), + 'optionIncrement' => array( + 'i' => 15, + ), + ), + ); + $e[] = array( + 'type' => 'select', + 'req' => true, + 'name' => 'category', + 'display' => 'Category', + 'opts' => $this->getTopicFields(), + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'website', + 'display' => 'Event Website' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'facebook', + 'display' => 'Facebook', + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'twitter', + 'display' => 'Twitter', + ); + + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'cost', + 'display' => 'Cost', + ); + + $e[] = array( + 'type' => 'textarea', + 'req' => false, + 'name' => 'description', + 'display' => 'Event Description', + 'opts' => array('id' => 'description') + ); + $e[] = array( + 'type' => 'header', + 'name' => 'eventLocationInfoHeader_rmv', + 'display' => 'Event Location Information +
+
+
+ Map It' + ); + $e[] = array( + 'type' => 'hidden', + 'req' => false, + 'name' => 'lat', + 'opts' => array('id' => 'lat') + ); + $e[] = array( + 'type' => 'hidden', + 'req' => false, + 'name' => 'lon', + 'opts' => array('id' => 'lon') + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'place', + 'display' => 'Place' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'address', + 'display' => 'Address' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'city', + 'display' => 'City' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'state', + 'display' => 'State' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'zip', + 'display' => 'ZIP' + ); + $e[] = array( + 'type' => 'header', + 'name' => 'eventContactHeader_rmv', + 'display' => 'Event Contact Information' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'contact_name', + 'display' => 'Event Contact Person
(published on Web site)' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'contact_email', + 'display' => 'Contact Email
(published on Web site)' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'contact_phone', + 'display' => 'Contact Phone
(published on Web site)' + ); + + $e[] = array( + 'type' => 'header', + 'name' => 'adminInfoHdr', + 'display' => 'Event Admin Information' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'admin_contact', + 'display' => 'Contact Name Submitting Event' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'admin_org', + 'display' => 'Organization Name Submitting Event' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'admin_phone', + 'display' => 'Phone' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'admin_email', + 'display' => 'Email Address' + ); + + if ($this->useCaptcha) { + $e[] = array( + 'type' => 'CAPTCHA_Image', + 'req' => false, + 'name' => 'captcha_question', + 'display' => 'Verification code', + 'opts' => $this->captchaOptions + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'captcha_rmv', + 'display' => 'Enter verification code', + ); + } + $e[] = array( + 'type' => 'submit', + 'req' => false, + 'name' => 'submit_rmv', + 'display' => 'Submit' + ); + + $this->setupElements($e); + } + + // }}} + // {{{ configureFilters() + + /** + * Form filter definitions + * + * Applies a data filter for the given fields when the form is submitted + * + * @return void + * @access public + */ + public function configureFilters() + { + $f = array(); + + $f[] = array( + 'element' => '__ALL__', + 'filter' => 'trim' + ); + $f[] = array( + 'element' => 'website', + 'filter' => array('Toolkit_Common', 'filterURI') + ); + + $this->setupFilters($f); + } + + // }}} + // {{{ configureForm() + + /** + * Helper function to handle setting up the form + * + * @return void + * @access public + */ + public function configureForm() + { + $this->configureElements(); + $this->configureFilters(); + $this->configureRules(); + } + + // }}} + // {{{ configureRules() + + /** + * Form rule definitions + * + * Adds validation rules for the given fields + * + * @return void + * @access public + */ + public function configureRules() + { + // Form Rules + $r[] = array( + 'element' => 'topicid', + 'message' => 'ERROR: Invalid Category!', + 'type' => 'numeric', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => 'email', + 'message' => 'ERROR: Invalid Email Format!', + 'type' => 'checkEmail', + 'format' => array('use_rfc822' => true), + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => array('starting', 'ending'), + 'message' => 'ERROR: Starting Date must be before Ending Date', + 'type' => 'callback', + 'format' => array(&$this, 'checkDateRange'), + 'validation' => $this->validationType, + 'reset' => false, + 'force' => false + ); + $r[] = array( + 'element' => 'starting', + 'message' => 'ERROR: Invalid date!', + 'type' => 'callback', + 'format' => array(&$this, 'checkDate'), + 'validation' => $this->validationType, + 'reset' => false, + 'force' => false + ); + $r[] = array( + 'element' => 'ending', + 'message' => 'ERROR: Invalid date!', + 'type' => 'callback', + 'format' => array(&$this, 'checkDate'), + 'validation' => $this->validationType, + 'reset' => false, + 'force' => false + ); + $r[] = array( + 'element' => 'website', + 'message' => 'ERROR: Invalid URL format', + 'type' => 'checkURI', + 'format' => array( + 'allowed_schemes' => array('http', 'https'), + 'strict' => false + ), + 'validation' => $this->validationType, + 'reset' => false, + 'force' => false + ); + $r[] = array( + 'element' => 'contact_phone', + 'message' => 'ERROR: Invalid Phone Format (xxx) xxx - xxxx!', + 'type' => 'phone', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + if ($this->useCaptcha) { + $r[] = array( + 'element' => 'captcha_rmv', + 'message' => 'ERROR: What you entered didn\'t match!', + 'type' => 'CAPTCHA', + 'format' => $this->captchaQuestion, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + } + + $this->setupRules($r); + } + + // }}} + // {{{ getTopicFields() + + /** + * get event topics + * + * @return array topics + * @access protected + */ + protected function getTopicFields() + { + $categories = array('' => '- select -'); + $catData = $this->eventMapper->fetchAllCategories(); + foreach ($catData as $category) { + $categories[$category->getId()] = $category->getName(); + } + return $categories; + } + + // }}} + // {{{ hasEndDate() + + /** + * verifies if we have a valid end date to work with + * + * @param array $d end date + * + * @return boolean if the end date is + */ + protected function hasEndDate($d) + { + $pattern = '/([0-9]{2})\/([0-9]{2})\/([0-9]{4})/'; + if (preg_match($pattern, $d, $m)) { + return checkdate((int) $m[1], (int) $m[2], (int) $m[3]); + } else { + return false; + } + } + + // }}} + // {{{ emailOwner() + + /** + * Emails the owner the submitted data from the submitted form + * + * Uses a flexy template to render a nice looking html email. + * Fills in the supplied data from the form and doesn't add the + * empty fields the user didn't fill in. + * + * @return boolean result of the mailing + * @access protected + */ + protected function emailOwner() + { + if (!$this->email) { + return; + } + + $template = new HTML_Template_Flexy($this->flexyOptions); + $page = new stdClass(); + // for comments textarea need to replace newlines with br + $this->formData['comments']['element'] = nl2br($this->getSubmitValue('comments')); + unset($this->formData['lat'], $this->formData['lon']); + + // these values are required, therefor will always be part of + // the formData array + $bdate = explode('/', $this->formData['bdate']['element']); + $foo = array_map('trim', $bdate); + $this->formatValue($foo, '%02d/%02d/%d'); + $this->formData['bdate']['element'] = $foo; + + $btime = explode('/', $this->formData['btime']['element']); + $foo = array_map('trim', $btime); + $this->formatValue($foo, '%02d:%02d %s'); + $this->formData['btime']['element'] = $foo; + + // not required, so check to make sure it exists before trying + // to format the value + if (isset($this->formData['edate'])) { + $edate = explode('/', $this->formData['edate']['element']); + $foo = array_map('trim', $edate); + $this->formatValue($foo, '%02d/%02d/%d'); + $this->formData['edate']['element'] = $foo; + } + if (isset($this->formData['etime'])) { + $etime = explode('/', $this->formData['etime']['element']); + $foo = array_map('trim', $etime); + $this->formatValue($foo, '%02d:%02d %s'); + $this->formData['etime']['element'] = $foo; + } + + $category = $this->eventMapper->fetchCategory( + $this->formData['category']['element'] + ); + if ($category) { + $this->formData['category']['element'] = $category->getName(); + } + + $page->email_from = FROM_NEWS_EMAIL; + $page->subject = $this->subject; + $page->formData = $this->formData; + $page->eventAdminURL = MEDIA_BASE_URL . 'admin/CommonEvents/index.php?pending=1'; + + $template->compile('emailOwner.tpl'); + $htmlMsg = $template->bufferedOutputObject($page); + + // Text version can't have HTML in it + $msg = "{$page->subject}\n\n"; + $msg .= "From {$page->fname} {$page->lname}\n\n"; + $msg .= "Information\n\n"; + foreach ($page->formData as $i) { + $msg .= "{$i['label']}: {$i['element']}\n"; + } + + $crlf = "\n"; + $mimeMail = new Mail_mime($crlf); + $mimeMail->setFrom("{$this->siteName} <{$page->email_from}>"); + $mimeMail->setSubject($this->subject); + $mimeMail->setHTMLBody($htmlMsg); + $mimeMail->setTXTBody($msg); + + $mail = Mail::factory('mail'); + $body = $mimeMail->get(); + $headers = $mimeMail->headers(); + + $res = $mail->send($this->email, $headers, $body); + if (PEAR::isError($res)) { + return Toolkit_Common::handleError($res); + } else { + return $res; + } + } + + // }}} + // {{{ formatValue() + + /** + * Format an array into an acceptable string + * + * @param mixed &$i array values to format or null value for + * element that was not filled in + * @param string $format string to format values into + * + * @return string formatted string + * @access public + */ + public function formatValue(&$i, $format) + { + // Allow for 0 to be not empty. This allows for minutes in the + // time arrays to be valid if they are on the hour ie. (1:00 pm) + $notEmpty = create_function('$v', 'return strlen($v) > 0;'); + if (is_array($i) && count(array_filter($i, $notEmpty)) == 3) { + list($x, $y, $z) = array_values($i); + eval("\$i = sprintf('$format', $x, $y, $z);"); + } else { + $i = null; + } + } + + // }}} + // {{{ insertData() + + /** + * Inserts contact data into the contact db + * + * @param array $values submitted values + * + * @return object result of db insert query + * @access protected + */ + protected function insertData($values) + { + $values = $this->_geocode($values); + + try { + // need to set the dates up first + $this->formatValue($values['btime'], '%d:%02d %s'); + $this->formatValue($values['etime'], '%d:%02d %s'); + $values['description'] = nl2br($values['description']); + $values['website'] = preg_replace("/^(http:\/\/)/", "", $values['website']); + if ($values['btime']) { + $values['starthour'] = $values['btime']; + unset($values['btime']); + } + if ($values['etime']) { + $values['endhour'] = $values['etime']; + unset($values['etime']); + } + if ($values['category']) { + $values['category'] = $this->eventMapper->fetchCategory( + $values['category'] + ); + } + if (defined('MEMBERS_DB') && MEMBERS_DB) { + $event = MemberEvent::createByValues($values); + } else { + $event = Event::createByValues($values); + } + return $this->eventMapper->saveEvent($event); + + return false; + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + private function _geocode(array $values) + { + $geocoder = new GeocodeYahoo(); + if (!$values['address'] && !$values['city'] && !$values['state']) { + return $values; + } + $address = array( + 'city' => $values['city'], + 'state' => $values['state'], + 'zip' => $values['zip'], + ); + if (!empty($values['address'])) { + $address['street'] = $values['address']; + } + try { + $response = $geocoder->geocodeAddress($address); + $responseArray = unserialize($response); + if ($responseArray['ResultSet']['Result'][0]['Latitude']) { + $values['lat'] = $responseArray['ResultSet']['Result'][0]['Latitude']; + $values['lon'] = $responseArray['ResultSet']['Result'][0]['Longitude']; + } else { + $values['lat'] = $responseArray['ResultSet']['Result']['Latitude']; + $values['lon'] = $responseArray['ResultSet']['Result']['Longitude']; + } + + return $values; + } catch (BadMethodCallException $e) { + Toolkit_Logger::logException('Invalid Arg', $e); + } catch (Exception $e) { + Toolkit_Logger::logException('Yahoo GeoCode', $e); + } + + } + // {{{ processData() + + /** + * Handles how to process the form when submitted + * + * @param array $values Form submitted values + * + * @return array Result of Insert / Update function + * @access protected + */ + public function processData($values) + { + // Form data used for the insert/update sql queries and + // the form email. + $e = array(); + $this->setFormData($e); + + // Get rid of any defined un-needed elements. + // un-needed elements after the form is submitted are defined + // by the ending _rmv name. + foreach ($values as $k => &$v) { + if (!is_array($v)) { + $values[$k] = preg_replace("/\r/", "\n", $v); + } + if (preg_match('/^.+_rmv$/', $k)) { + unset($values[$k]); + } + } + $values['create_date'] = date('m/d/Y'); + + return $this->insertData($values); + } + + // }}} + // {{{ setupRenderers() + + /** + * Custom rendering templates for special fields on the form + * + * @return void + * @access protected + */ + protected function setupRenderers() + { + parent::setupRenderers(); + $renderer = $this->defaultRenderer(); + $required = '*'; + $error = '
{error}
'; + + $renderer->setElementTemplate('

' . $required . '{label}' . $error . '{element}
' . $required . '{label}' . $error . '{element}
{element}
' . $required . '' . $error . '{element}What is this?